# DM History Context Cleanup, Skill Rename & Startup Events Unification

## Problems

### 1. DM History as JSON in System Prompt
The `{{nostr_dm_history}}` template variable resolves to a raw JSON array string pasted into the system prompt. The LLM receives conversation history as JSON-within-text, wasting tokens and forcing it to parse structured data embedded in prose.

### 2. Misleading Skill Name
The skill `default_admin_dm` is really an identity and rules skill. Rename to `identity_and_rules`.

### 3. `default_skill` Config Section Is Redundant
The `default_skill` section in genesis.jsonc is a special-case config path that converts a skill into a startup event and auto-adopts it. This is unnecessary — skills should just be startup events like everything else. The program should treat all startup events equally and halt if any fail to publish.

## Solution

Three coordinated changes:

### Part A: DM History Text Format
Add a `format` parameter to the `nostr_dm_history` tool. Create a separate `dm_history` skill.

### Part B: Skill Rename
Rename `default_admin_dm` → `identity_and_rules` everywhere.

### Part C: Eliminate `default_skill` Config Section
Move skills into `startup_events`. Auto-adopt kind 31123/31124 startup events. Make startup event publishing mandatory (halt on failure).

---

## Implementation Steps

### Part A: DM History Text Format

#### A1. Add `format` parameter to `execute_nostr_dm_history()`

**File:** `src/tools/tool_agent.c` — line 265

Add a `format` parameter: `"json"` (default, current behavior) or `"text"`.

When `format` is `"text"`, after the filtering loop (lines 320-360), iterate the filtered array and build plain text:

```
User: Good morning
Assistant: Good morning! ☀️ How can I help you today?
User: What is the capital of England?
Assistant: London! 🇬🇧
```

Existing `include_current=false` default already deduplicates the current live message (line 339).

#### A2. Add `format` to the tool schema

**File:** `src/tools/tools_schema.c` — around line 1493

Add `format` property with description. Update tool description to mention the parameter.

---

### Part B: Skill Rename

#### B1. Update `src/default_events.h`

- `DIDACTYL_DEFAULT_SKILL_D_TAG`: `"default_admin_dm"` → `"identity_and_rules"`
- `DIDACTYL_DEFAULT_SKILL_TAGS_JSON`: update d-tag and description
- `DIDACTYL_DEFAULT_SKILL_TEMPLATE`: keep as-is (already clean, no `{{nostr_dm_history}}`)

#### B2. Update tool description examples in `src/tools/tools_schema.c`

- Line 854: `skill_get` example
- Line 883: `skill_view` example
- Line 911: `skill_set` example

#### B3. Update `docs/GENESIS.md`

- Line 33 and 124: `default_admin_dm` → `identity_and_rules`

---

### Part C: Eliminate `default_skill` Config Section

#### C1. Auto-adopt kind 31123/31124 startup events

**File:** `src/config.c`

Replace `config_ensure_default_skill_startup_events()` with a new function `config_ensure_startup_skill_adoption()` that:

1. Scans all startup events for kind 31123 and 31124
2. For each skill found, extracts its `d_tag` from tags
3. Builds the skill address (`kind:pubkey:d_tag`)
4. Ensures a kind 10123 adoption list startup event exists with all skill addresses
5. If no 10123 event exists, creates one

This replaces the single-skill logic with a generic "adopt all startup skills" approach.

#### C2. Remove `default_skill` config parsing

**File:** `src/config.c`

- Remove `parse_default_skill_config()` function (lines 733-816)
- Remove the call at line 1369
- Keep backward compatibility: if `default_skill` section exists in genesis.jsonc, convert it to a startup event during parsing (migration path) — OR just remove support and let users update their genesis.jsonc

#### C3. Remove `default_skill_config_t` from config struct

**File:** `src/config.h`

- Remove `default_skill_config_t` typedef (lines 67-72)
- Remove `default_skill` field from `didactyl_config_t` (line 134)

#### C4. Update `src/main.c`

- Line 1060: Replace `config_ensure_default_skill_startup_events()` call with `config_ensure_startup_skill_adoption()`

#### C5. Make startup event publishing mandatory

**File:** `src/nostr_handler.c`

In the startup publish flow (around line 3150), after all relays have been tried:
- Check that each startup event was published to at least one relay
- If any event failed on all relays, log an error and return failure
- The caller in `main.c` should halt on this failure

#### C6. Update setup wizard

**File:** `src/setup_wizard.c`

- `configure_default_skill_for_agent()` (line 498): Instead of populating `cfg->default_skill`, append the identity skill as a startup event directly
- Add the `dm_history` skill as a second startup event
- The auto-adoption logic (C1) handles the adoption list

#### C7. Update `default_events.h`

Add the `dm_history` skill template:

```c
#define DIDACTYL_DEFAULT_DM_HISTORY_SKILL_D_TAG "dm_history"

static const char* DIDACTYL_DEFAULT_DM_HISTORY_SKILL_TEMPLATE =
    "## Recent Conversation\n\n"
    "{{nostr_dm_history({\"format\":\"text\",\"limit\":12})}}";
```

---

### Part D: Genesis Config Updates

#### D1. Update `genesis.jsonc.example`

Remove `default_skill` section. Add skills as startup events:

```jsonc
"startup_events": [
    {
      "kind": 0,
      "content_fields": {
        "name": "Didactyl",
        "about": "I am a Didactyl agent living on Nostr"
      },
      "tags": []
    },
    {
      "kind": 3,
      "content": "",
      "tags": [["p", "ADMIN_HEX_PUBKEY"]]
    },
    {
      "kind": 10002,
      "content": "",
      "tags": [
        ["r", "wss://relay.damus.io"],
        ["r", "wss://relay.primal.net"]
      ]
    },
    {
      "kind": 31124,
      "content": "# Didactyl Agent\n\nYou are {{my_kind0_profile}}\n\nYour npub: {{my_npub}}\n\n## Rules\n\n- Communicate through encrypted Nostr direct messages\n- Keep responses concise and clear\n- Be helpful and technically accurate\n- If unsure, state uncertainty directly\n- Use tools when a request requires taking action\n- After a tool call, base your answer on the actual tool result\n- Never claim a tool was run if no tool was executed\n- Maintain your task list as short-term working memory\n- Never reveal your private key (nsec)\n- You may share your public key (npub) with anyone",
      "tags": [
        ["d", "identity_and_rules"],
        ["app", "didactyl"],
        ["scope", "private"],
        ["description", "Agent identity and behavioral rules"],
        ["trigger", "dm"],
        ["filter", "{\"from\":\"admin\"}"]
      ]
    },
    {
      "kind": 31124,
      "content": "## Recent Conversation\n\n{{nostr_dm_history({\"format\":\"text\",\"limit\":12})}}",
      "tags": [
        ["d", "dm_history"],
        ["app", "didactyl"],
        ["scope", "private"],
        ["description", "DM conversation history for context continuity"],
        ["trigger", "dm"],
        ["filter", "{\"from\":\"admin\"}"]
      ]
    }
  ]
```

#### D2. Update live `genesis.jsonc`

Same changes as D1 but for the actual deployment config.

---

## Result

### Before

```json
[
  {"role": "system", "content": "You are {...}\n\nYour npub: npub1...\n\n## Rules\n...\n[{\"role\":\"user\",\"content\":\"Good morning\",...}]"},
  {"role": "user", "content": "And Fiji?"}
]
```

### After

```json
[
  {"role": "system", "content": "# Didactyl Agent\n\nYou are {...}\n\nYour npub: npub1...\n\n## Rules\n...\n\n---\n\n## Recent Conversation\n\nUser: Good morning\nAssistant: Good morning! ☀️ How can I help you today?\nUser: What is the capital of England?\nAssistant: London! 🇬🇧\nUser: How about France?\nAssistant: Paris! 🇫🇷"},
  {"role": "user", "content": "And Fiji?"}
]
```

---

## Files Changed

| File | Change |
|------|--------|
| `src/tools/tool_agent.c` | Add `format` parameter to `execute_nostr_dm_history()` |
| `src/tools/tools_schema.c` | Add `format` to schema; update example d-tags |
| `src/default_events.h` | Rename d-tag; add `dm_history` skill template |
| `src/config.h` | Remove `default_skill_config_t` and field |
| `src/config.c` | Remove `parse_default_skill_config()`; replace `config_ensure_default_skill_startup_events()` with `config_ensure_startup_skill_adoption()` |
| `src/main.c` | Update call to new adoption function |
| `src/nostr_handler.c` | Make startup event publishing mandatory (halt on total failure) |
| `src/setup_wizard.c` | Put skills in startup_events; add dm_history |
| `genesis.jsonc.example` | Remove `default_skill`; add skills as startup events |
| `genesis.jsonc` | Same as example |
| `docs/GENESIS.md` | Update references |

## Migration Note

For backward compatibility, consider keeping `parse_default_skill_config()` as a migration shim that converts `default_skill` into a startup event with a deprecation warning. This way existing genesis.jsonc files with `default_skill` still work but users are prompted to update.
