# System Prompt + Structured Bootstrap Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Fix bootstrap by adding `--system-prompt-file` to replace CC's default prompt, restoring structured output with server-side validation.

**Architecture:** Two-layer prompting: `--system-prompt-file` (base identity, generated by codegen) + `--agent` (behavior via @ file references) + `--json-schema` (structured output). Bootstrap completion: `bootstrap_complete` field in schema, gated by server-side file-presence check.

**Tech Stack:** Rust, Claude Code CLI, rmcp MCP framework

---

### Task 1: Add `generate_system_prompt()` and restore `BOOTSTRAP_SCHEMA_JSON`

**Files:**
- Modify: `crates/rightclaw/src/codegen/agent_def.rs`

- [ ] **Step 1: Write tests for generate_system_prompt**

Add to `crates/rightclaw/src/codegen/agent_def_tests.rs`:

```rust
#[test]
fn system_prompt_contains_agent_name() {
    let result = generate_system_prompt("mybot", &crate::agent::types::SandboxMode::Openshell);
    assert!(result.contains("mybot"));
}

#[test]
fn system_prompt_contains_rightclaw_description() {
    let result = generate_system_prompt("test", &crate::agent::types::SandboxMode::Openshell);
    assert!(result.contains("RightClaw"));
    assert!(result.contains("multi-agent runtime"));
}

#[test]
fn system_prompt_contains_sandbox_mode() {
    let openshell = generate_system_prompt("test", &crate::agent::types::SandboxMode::Openshell);
    assert!(openshell.contains("OpenShell"));

    let none = generate_system_prompt("test", &crate::agent::types::SandboxMode::None);
    assert!(none.contains("no sandbox"));
}

#[test]
fn system_prompt_mentions_right_mcp() {
    let result = generate_system_prompt("test", &crate::agent::types::SandboxMode::Openshell);
    assert!(result.contains("right"));
    assert!(result.contains("MCP"));
}
```

Update the import line at the top of `agent_def_tests.rs`:

```rust
use crate::codegen::{generate_agent_definition, generate_bootstrap_definition, generate_system_prompt, BOOTSTRAP_SCHEMA_JSON, REPLY_SCHEMA_JSON};
```

- [ ] **Step 2: Run tests to verify they fail**

Run: `cargo test -p rightclaw -- codegen::agent_def_tests`
Expected: FAIL — `generate_system_prompt` and `BOOTSTRAP_SCHEMA_JSON` not found

- [ ] **Step 3: Implement generate_system_prompt and restore BOOTSTRAP_SCHEMA_JSON**

In `crates/rightclaw/src/codegen/agent_def.rs`, replace the comment on line 22:

```rust
// BOOTSTRAP_SCHEMA_JSON removed — bootstrap completion detected via MCP tool + file presence.
```

With:

```rust
/// JSON schema for bootstrap mode — adds `bootstrap_complete` field.
///
/// `bootstrap_complete` is required but the bot does NOT trust it alone —
/// server-side file-presence check (`should_accept_bootstrap`) gates completion.
pub const BOOTSTRAP_SCHEMA_JSON: &str = r#"{"type":"object","properties":{"content":{"type":["string","null"]},"bootstrap_complete":{"type":"boolean"},"reply_to_message_id":{"type":["integer","null"]},"attachments":{"type":["array","null"],"items":{"type":"object","properties":{"type":{"enum":["photo","document","video","audio","voice","video_note","sticker","animation"]},"path":{"type":"string"},"filename":{"type":["string","null"]},"caption":{"type":["string","null"]}},"required":["type","path"]}}},"required":["content","bootstrap_complete"]}"#;
```

Add `generate_system_prompt` function after `generate_bootstrap_definition`:

```rust
/// Generate the base system prompt for all agent modes.
///
/// This replaces CC's default system prompt via `--system-prompt-file`.
/// Content: agent identity, RightClaw description, sandbox info, MCP reference.
/// Behavior-specific instructions come from the agent definition (`--agent`).
pub fn generate_system_prompt(agent_name: &str, sandbox_mode: &crate::agent::types::SandboxMode) -> String {
    let sandbox_desc = match sandbox_mode {
        crate::agent::types::SandboxMode::Openshell => "OpenShell sandbox (k3s container with network and filesystem policies)",
        crate::agent::types::SandboxMode::None => "no sandbox (direct host access)",
    };

    format!(
        "\
You are {agent_name}, a RightClaw agent.

RightClaw is a multi-agent runtime for Claude Code built on NVIDIA OpenShell. Each agent runs \
as an independent Claude Code session inside its own sandbox with declarative YAML policies. \
Agents have persistent memory, scheduled tasks (cron), and tool management via MCP.

Source: https://github.com/onsails/rightclaw

## Environment

- Agent name: {agent_name}
- Sandbox: {sandbox_desc}

## MCP

You are connected to the `right` MCP server for persistent memory, cron job management, \
and external MCP server management. Use `mcp_list` to see all configured servers.
"
    )
}
```

- [ ] **Step 4: Restore bootstrap schema tests**

In `crates/rightclaw/src/codegen/agent_def_tests.rs`, replace the comment:

```rust
// BOOTSTRAP_SCHEMA_JSON tests removed — bootstrap completion via MCP tool now.
```

With:

```rust
#[test]
fn bootstrap_schema_json_is_valid() {
    let parsed: serde_json::Value = serde_json::from_str(BOOTSTRAP_SCHEMA_JSON)
        .expect("BOOTSTRAP_SCHEMA_JSON must be valid JSON");
    let required = parsed.get("required").unwrap().as_array().unwrap();
    let required_strs: Vec<&str> = required.iter().map(|v| v.as_str().unwrap()).collect();
    assert!(required_strs.contains(&"content"), "must require content");
    assert!(required_strs.contains(&"bootstrap_complete"), "must require bootstrap_complete");
}

#[test]
fn bootstrap_schema_has_bootstrap_complete_field() {
    let parsed: serde_json::Value = serde_json::from_str(BOOTSTRAP_SCHEMA_JSON).unwrap();
    let props = parsed.get("properties").unwrap();
    assert!(props.get("bootstrap_complete").is_some(), "must have bootstrap_complete property");
}
```

- [ ] **Step 5: Run tests to verify they pass**

Run: `cargo test -p rightclaw -- codegen::agent_def_tests`
Expected: PASS — all tests including new system_prompt and restored bootstrap_schema tests

- [ ] **Step 6: Commit**

```bash
git add crates/rightclaw/src/codegen/agent_def.rs crates/rightclaw/src/codegen/agent_def_tests.rs
git commit -m "feat: add generate_system_prompt(), restore BOOTSTRAP_SCHEMA_JSON"
```

---

### Task 2: Update codegen pipeline and exports

**Files:**
- Modify: `crates/rightclaw/src/codegen/mod.rs`
- Modify: `crates/rightclaw/src/codegen/pipeline.rs`

- [ ] **Step 1: Update mod.rs exports**

In `crates/rightclaw/src/codegen/mod.rs`, replace the agent_def re-export block:

```rust
pub use agent_def::{
    generate_agent_definition, generate_bootstrap_definition, CONTENT_MD_FILES, REPLY_SCHEMA_JSON,
};
```

With:

```rust
pub use agent_def::{
    generate_agent_definition, generate_bootstrap_definition, generate_system_prompt,
    BOOTSTRAP_SCHEMA_JSON, CONTENT_MD_FILES, REPLY_SCHEMA_JSON,
};
```

- [ ] **Step 2: Update pipeline.rs — write system-prompt.md and restore bootstrap-schema.json**

In `crates/rightclaw/src/codegen/pipeline.rs`, find the line:

```rust
        tracing::debug!(agent = %agent.name, "wrote agent definitions + schemas");
```

Insert BEFORE it:

```rust
        // Write system-prompt.md (base identity for --system-prompt-file).
        std::fs::write(
            claude_dir.join("system-prompt.md"),
            crate::codegen::generate_system_prompt(&agent.name, &agent.config.sandbox.mode),
        )
        .map_err(|e| {
            miette::miette!(
                "failed to write system-prompt.md for '{}': {e:#}",
                agent.name
            )
        })?;

        // Write bootstrap-schema.json (bootstrap mode structured output).
        std::fs::write(
            claude_dir.join("bootstrap-schema.json"),
            crate::codegen::BOOTSTRAP_SCHEMA_JSON,
        )
        .map_err(|e| {
            miette::miette!(
                "failed to write bootstrap-schema.json for '{}': {e:#}",
                agent.name
            )
        })?;
```

- [ ] **Step 3: Update pipeline test — verify system-prompt.md and bootstrap-schema.json**

In `crates/rightclaw/src/codegen/pipeline.rs`, find the comment:

```rust
        // bootstrap-schema.json no longer generated — completion via MCP tool.
```

Replace with:

```rust
        // System prompt must exist
        let sys_prompt = agent_dir.join(".claude/system-prompt.md");
        assert!(sys_prompt.exists(), "system-prompt.md must be written");
        let sys_content = std::fs::read_to_string(&sys_prompt).unwrap();
        assert!(sys_content.contains("test-agent"));

        // Bootstrap schema must exist
        let bs_schema = agent_dir.join(".claude/bootstrap-schema.json");
        assert!(bs_schema.exists(), "bootstrap-schema.json must be written");
```

- [ ] **Step 4: Run tests**

Run: `cargo test -p rightclaw -- codegen`
Expected: PASS

- [ ] **Step 5: Commit**

```bash
git add crates/rightclaw/src/codegen/mod.rs crates/rightclaw/src/codegen/pipeline.rs
git commit -m "feat: codegen writes system-prompt.md and bootstrap-schema.json"
```

---

### Task 3: Add system-prompt.md to sync

**Files:**
- Modify: `crates/bot/src/sync.rs`

- [ ] **Step 1: Add system-prompt.md upload to sync_cycle**

In `crates/bot/src/sync.rs`, find the line:

```rust
    // 2b.
```

(This was left after removing bootstrap-schema upload.) Replace with:

```rust
    // 2b. Upload system-prompt.md (base identity for --system-prompt-file)
    let sys_prompt = agent_dir.join(".claude").join("system-prompt.md");
    if sys_prompt.exists() {
        rightclaw::openshell::upload_file(sandbox, &sys_prompt, "/sandbox/.claude/")
            .await
            .map_err(|e| miette::miette!("sync system-prompt.md: {e:#}"))?;
        tracing::debug!("sync: uploaded system-prompt.md");
    }

    // 2c. Upload bootstrap-schema.json
    let bs_schema = agent_dir.join(".claude").join("bootstrap-schema.json");
    if bs_schema.exists() {
        rightclaw::openshell::upload_file(sandbox, &bs_schema, "/sandbox/.claude/")
            .await
            .map_err(|e| miette::miette!("sync bootstrap-schema.json: {e:#}"))?;
        tracing::debug!("sync: uploaded bootstrap-schema.json");
    }

    // 2d.
```

Also update the comment on the next line from `// 2b.` (for .claude/agents/) to `// 2d.` if present, or just `// Upload .claude/agents/...`.

- [ ] **Step 2: Update sync test fixture**

In the test `initial_sync_uploads_content_md_files` in `sync.rs`, add to the test setup:

```rust
        std::fs::write(claude_dir.join("bootstrap-schema.json"), "{}").unwrap();
        std::fs::write(claude_dir.join("system-prompt.md"), "# test system prompt\n").unwrap();
```

- [ ] **Step 3: Run build**

Run: `cargo build -p rightclaw-bot`
Expected: PASS

- [ ] **Step 4: Commit**

```bash
git add crates/bot/src/sync.rs
git commit -m "feat: sync system-prompt.md and bootstrap-schema.json to sandbox"
```

---

### Task 4: Refactor worker.rs — system-prompt-file + restore bootstrap schema

**Files:**
- Modify: `crates/bot/src/telegram/worker.rs`

- [ ] **Step 1: Restore `bootstrap_complete` in ReplyOutput**

In `crates/bot/src/telegram/worker.rs`, replace the ReplyOutput comment (around line 68):

```rust
    // bootstrap_complete removed — completion detected by file presence after reverse_sync
```

With:

```rust
    /// Bootstrap mode: `true` signals agent claims onboarding is complete.
    /// Server-side file check (`should_accept_bootstrap`) gates actual completion.
    pub bootstrap_complete: Option<bool>,
```

Also restore in the plain-string fallback ReplyOutput construction (around line 214), add after `attachments: None,`:

```rust
            bootstrap_complete: None,
```

- [ ] **Step 2: Add --system-prompt-file to claude args**

In worker.rs, find the block that builds claude_args (after `--output-format json`, around line 702). Find the `--agent` block:

```rust
    // --agent only on first call (AGDEF-02); resume inherits from session (AGDEF-03)
    if is_first_call {
```

Insert BEFORE it:

```rust
    // --system-prompt-file replaces CC's default system prompt with our base identity.
    // Without this, CC's 8K+ token default prompt drowns the agent's instructions.
    let system_prompt_path = if ctx.ssh_config_path.is_some() {
        "/sandbox/.claude/system-prompt.md".to_string()
    } else {
        ctx.agent_dir.join(".claude").join("system-prompt.md").to_string_lossy().into_owned()
    };
    claude_args.push("--system-prompt-file".into());
    claude_args.push(system_prompt_path);
```

- [ ] **Step 3: Restore bootstrap schema selection and always pass --json-schema**

Replace the current json-schema block:

```rust
    // --json-schema on BOTH first and resume calls (D-01, Pitfall 4).
    // Bootstrap mode: NO schema — let the model converse freely without
    // StructuredOutput tool interference. Result is plain text in `result` field.
    if !bootstrap_mode {
        let reply_schema_path = ctx.agent_dir.join(".claude").join("reply-schema.json");
        let reply_schema = std::fs::read_to_string(&reply_schema_path)
            .map_err(|e| format_error_reply(-1, &format!("reply-schema.json read failed: {:#}", e)))?;
        claude_args.push("--json-schema".into());
        claude_args.push(reply_schema);
    }
```

With:

```rust
    // --json-schema on BOTH first and resume calls (D-01, Pitfall 4).
    // Bootstrap mode uses bootstrap-schema (adds bootstrap_complete field).
    let schema_filename = if bootstrap_mode {
        "bootstrap-schema.json"
    } else {
        "reply-schema.json"
    };
    let reply_schema_path = ctx.agent_dir.join(".claude").join(schema_filename);
    let reply_schema = std::fs::read_to_string(&reply_schema_path)
        .map_err(|e| format_error_reply(-1, &format!("{schema_filename} read failed: {:#}", e)))?;
    claude_args.push("--json-schema".into());
    claude_args.push(reply_schema);
```

- [ ] **Step 4: Restore bootstrap_complete check in invoke_cc (server-side gated)**

In invoke_cc, find the comment:

```rust
            // Bootstrap completion is now detected by file presence after
            // reverse_sync in spawn_worker — no bootstrap_complete field needed.

            Ok(Some(reply_output))
```

Replace with:

```rust
            Ok(Some(reply_output))
```

(Just remove the comment — bootstrap completion is checked in spawn_worker after reverse_sync.)

- [ ] **Step 5: Update bootstrap completion check in spawn_worker**

The existing check in spawn_worker (around line 394) already does file-presence gating. Update it to ALSO check `bootstrap_complete` from the reply:

Find:

```rust
            // Bootstrap completion: check if identity files are now on host after sync.
            // MCP tool bootstrap_done may have already deleted BOOTSTRAP.md, but
            // we also check here as a safety net (handles no-sandbox mode too).
            if bootstrap_mode && should_accept_bootstrap(&ctx.agent_dir) {
```

Replace with:

```rust
            // Bootstrap completion: structured output signal + file-presence gate.
            // Agent must set bootstrap_complete: true AND files must exist after sync.
            let bootstrap_complete = matches!(
                &reply_result,
                Ok(Some(ref output)) if output.bootstrap_complete == Some(true)
            );
            if bootstrap_mode && bootstrap_complete && should_accept_bootstrap(&ctx.agent_dir) {
```

- [ ] **Step 6: Restore bootstrap_complete tests**

In the tests section of worker.rs, find:

```rust
    // bootstrap_complete field removed — completion detected by file presence.
    // Tests for should_accept_bootstrap below cover the new logic.
```

Replace with:

```rust
    // bootstrap mode tests
    #[test]
    fn parse_reply_output_bootstrap_complete_true() {
        let json = r#"{"type":"result","result":{"content":"Done!","bootstrap_complete":true},"session_id":"abc-123"}"#;
        let (output, _sid) = parse_reply_output(json).unwrap();
        assert_eq!(output.content.as_deref(), Some("Done!"));
        assert_eq!(output.bootstrap_complete, Some(true));
    }

    #[test]
    fn parse_reply_output_bootstrap_complete_false() {
        let json = r#"{"type":"result","result":{"content":"What's your name?","bootstrap_complete":false},"session_id":"abc-123"}"#;
        let (output, _sid) = parse_reply_output(json).unwrap();
        assert_eq!(output.bootstrap_complete, Some(false));
    }

    #[test]
    fn parse_reply_output_no_bootstrap_field() {
        let json = r#"{"type":"result","result":{"content":"Hello!"},"session_id":"abc-123"}"#;
        let (output, _sid) = parse_reply_output(json).unwrap();
        assert_eq!(output.bootstrap_complete, None);
    }
```

- [ ] **Step 7: Run tests**

Run: `cargo test -p rightclaw-bot --lib`
Expected: PASS — all tests including restored bootstrap_complete tests

- [ ] **Step 8: Commit**

```bash
git add crates/bot/src/telegram/worker.rs
git commit -m "feat: add --system-prompt-file, restore bootstrap schema + structured output"
```

---

### Task 5: Expand MCP with_instructions()

**Files:**
- Modify: `crates/rightclaw-cli/src/memory_server.rs`
- Modify: `crates/rightclaw-cli/src/memory_server_http.rs`

- [ ] **Step 1: Update memory_server.rs with_instructions**

In `crates/rightclaw-cli/src/memory_server.rs`, replace the `.with_instructions(...)` string:

```rust
            .with_instructions(
                "RightClaw tools: store_record, query_records, search_records, delete_record, cron_list_runs, cron_show_run, mcp_add, mcp_remove, mcp_list, mcp_auth, bootstrap_done",
            )
```

With:

```rust
            .with_instructions(
                "RightClaw agent MCP server.\n\n\
                 ## Memory\n\
                 - store_record: Store tagged records for persistent memory\n\
                 - query_records: Query records by tag or keyword\n\
                 - search_records: Full-text search with BM25 ranking\n\
                 - delete_record: Soft-delete a record (preserves audit trail)\n\n\
                 ## Cron\n\
                 - cron_list_runs: List recent cron job executions\n\
                 - cron_show_run: Get details of a specific cron run\n\n\
                 ## MCP Management\n\
                 - mcp_add: Add an external HTTP MCP server\n\
                 - mcp_remove: Remove an MCP server (cannot remove 'right')\n\
                 - mcp_list: List all configured MCP servers\n\
                 - mcp_auth: Initiate OAuth for an HTTP MCP server\n\n\
                 ## Bootstrap\n\
                 - bootstrap_done: Signal onboarding completion. Verifies IDENTITY.md, SOUL.md, USER.md exist. Call AFTER creating all three files.",
            )
```

- [ ] **Step 2: Update memory_server_http.rs with_instructions**

Same replacement in `crates/rightclaw-cli/src/memory_server_http.rs`.

- [ ] **Step 3: Build**

Run: `cargo build -p rightclaw-cli`
Expected: PASS

- [ ] **Step 4: Commit**

```bash
git add crates/rightclaw-cli/src/memory_server.rs crates/rightclaw-cli/src/memory_server_http.rs
git commit -m "feat: expand MCP with_instructions() with full capability descriptions"
```

---

### Task 6: Update BOOTSTRAP.md template

**Files:**
- Modify: `templates/right/BOOTSTRAP.md`

- [ ] **Step 1: Add bootstrap_complete instructions back**

In `templates/right/BOOTSTRAP.md`, find:

```markdown
## When You're Done
```

Insert BEFORE it:

```markdown
## CRITICAL: bootstrap_complete

Your response JSON includes a `bootstrap_complete` field.

- Set `bootstrap_complete` to **`false`** in EVERY response until you have created ALL THREE files: IDENTITY.md, SOUL.md, and USER.md.
- Set `bootstrap_complete` to **`true`** ONLY after writing all three files.
- The system verifies files exist — premature `true` will be ignored and bootstrap continues.
- Do NOT set `bootstrap_complete: true` on your first response. Have a real conversation first.

```

- [ ] **Step 2: Commit**

```bash
git add templates/right/BOOTSTRAP.md
git commit -m "feat: add bootstrap_complete instructions back to BOOTSTRAP.md"
```

---

### Task 7: Documentation — PROMPT_SYSTEM.md, ARCHITECTURE.md, CLAUDE.md

**Files:**
- Create: `PROMPT_SYSTEM.md`
- Modify: `ARCHITECTURE.md`
- Modify: `CLAUDE.md`

- [ ] **Step 1: Create PROMPT_SYSTEM.md**

Create `PROMPT_SYSTEM.md` in the project root:

```markdown
# RightClaw Prompting System

How RightClaw constructs the prompt for each `claude -p` invocation.

## Two-Layer Architecture

Every CC invocation uses two prompt layers:

| Layer | Flag | Purpose | Same for all modes? |
|-------|------|---------|-------------------|
| **System prompt** | `--system-prompt-file` | Base identity: "who you are" | Yes |
| **Agent definition** | `--agent` | Behavior: "what to do" | No (bootstrap vs normal) |

Plus `--json-schema` for structured output (reply-schema or bootstrap-schema).

### Why --system-prompt-file?

`--agent` alone does NOT fully replace CC's default system prompt — CC adds ~8K tokens of
infrastructure (tool definitions, coding instructions, etc.) that drown the agent's instructions.
`--system-prompt-file` replaces CC's default prompt entirely, giving our instructions priority.

## System Prompt (system-prompt.md)

Generated by `generate_system_prompt()` in `codegen/agent_def.rs`.
Written to `agent_dir/.claude/system-prompt.md`, synced to `/sandbox/.claude/system-prompt.md`.

Content (~200 words):
- Agent identity: "You are {name}, a RightClaw agent"
- RightClaw description: multi-agent runtime, OpenShell sandboxes
- Environment: sandbox mode, agent name
- MCP reference: connected to `right` MCP server
- Repo link: github.com/onsails/rightclaw

Does NOT include: agent behavior, identity files, bootstrap instructions.

## Agent Definitions

Generated by `generate_agent_definition()` and `generate_bootstrap_definition()`.

### Normal mode (`{name}.md`)
```
@./AGENTS.md → @./SOUL.md → @./IDENTITY.md → @./USER.md → @./TOOLS.md
```
Cache-optimized order: static files first, dynamic last.

### Bootstrap mode (`{name}-bootstrap.md`)
```
@./BOOTSTRAP.md
```
Minimal — only onboarding instructions. No identity files (they don't exist yet).

## JSON Schemas

### reply-schema.json (normal mode)
Required: `content` (string|null).
Optional: `reply_to_message_id`, `attachments`.

### bootstrap-schema.json (bootstrap mode)
Same as reply-schema plus required `bootstrap_complete` (boolean).
Server-side validation: `bootstrap_complete: true` is ignored unless IDENTITY.md,
SOUL.md, USER.md all exist on the host after reverse_sync.

## MCP Server Instructions

The `right` MCP server provides `with_instructions()` describing all tools:
memory (store/query/search/delete), cron (list/show runs), MCP management
(add/remove/list/auth), and bootstrap (bootstrap_done).

Update `with_instructions()` in both `memory_server.rs` and `memory_server_http.rs`
whenever tools change.

## Bootstrap Completion Flow

1. Agent sends response with `bootstrap_complete: true` in structured output
2. Worker runs blocking `reverse_sync_md` (pulls files from sandbox to host)
3. `should_accept_bootstrap()` checks IDENTITY.md + SOUL.md + USER.md on host
4. If all present → delete session, delete BOOTSTRAP.md → normal mode
5. If missing → ignore bootstrap_complete, continue bootstrap mode

Additionally, `bootstrap_done` MCP tool provides in-session feedback: agent calls it
after creating files, gets immediate success/error response with missing file list.
```

- [ ] **Step 2: Update ARCHITECTURE.md**

In `ARCHITECTURE.md`, find the `rightclaw up` section in the Agent Lifecycle (the line that lists codegen outputs). Update it to include `system-prompt.md`:

Find the line containing:
```
  │   ├─ Codegen: <name>.md + <name>-bootstrap.md (both @ file references), TOOLS.md, settings.json, .claude.json, .mcp.json, bootstrap-schema.json
```

Replace with:
```
  │   ├─ Codegen: system-prompt.md, <name>.md + <name>-bootstrap.md (both @ file references), TOOLS.md, settings.json, .claude.json, .mcp.json, bootstrap-schema.json, reply-schema.json
```

Add a new section after "### Configuration Hierarchy" (before "### Memory Schema"):

```markdown
### Prompting Architecture

Every `claude -p` invocation uses two prompt layers:

| Layer | Flag | Content |
|-------|------|---------|
| System prompt | `--system-prompt-file .claude/system-prompt.md` | Base identity (who you are) |
| Agent definition | `--agent {name}[-bootstrap]` | Behavior (what to do, @ file references) |

`--system-prompt-file` replaces CC's default 8K+ token system prompt. Without it, agent instructions are ~10% of the prompt and get ignored.

See PROMPT_SYSTEM.md for full documentation.
```

- [ ] **Step 3: Update CLAUDE.md conventions**

In `CLAUDE.md`, in the `## Conventions` section, add:

```markdown
- **PROMPT_SYSTEM.md**: Always keep PROMPT_SYSTEM.md in sync with the actual prompting system. When changing system prompt generation, agent definitions, JSON schemas, or MCP instructions, update PROMPT_SYSTEM.md to match.
- **MCP with_instructions()**: When adding, removing, or renaming MCP tools, always update `with_instructions()` in both `memory_server.rs` and `memory_server_http.rs` to reflect the current tool set and descriptions.
```

- [ ] **Step 4: Commit**

```bash
git add PROMPT_SYSTEM.md ARCHITECTURE.md CLAUDE.md
git commit -m "docs: add PROMPT_SYSTEM.md, update ARCHITECTURE.md and CLAUDE.md conventions"
```

---

### Task 8: Build and full test

**Files:** None (verification only)

- [ ] **Step 1: Full workspace build**

Run: `cargo build --workspace`
Expected: PASS, 0 errors, 0 warnings

- [ ] **Step 2: Full test suite**

Run: `cargo test --workspace`
Expected: rightclaw and rightclaw-bot tests PASS. rightclaw-cli integration tests may fail (pre-existing sandbox conflict — not related to our changes).

- [ ] **Step 3: Manual sandbox test**

```bash
ssh -F ~/.rightclaw/run/ssh/rightclaw-right.ssh-config openshell-rightclaw-right -- \
  "cd /sandbox && claude -p --dangerously-skip-permissions --output-format json \
   --system-prompt-file /sandbox/.claude/system-prompt.md \
   --agent right-bootstrap \
   --json-schema '{...bootstrap-schema...}' \
   'hi'"
```

Expected: Response contains bootstrap conversation (NOT "Hi! How can I help?"), `bootstrap_complete: false`.
