From eac6a7e58c83498b7709aaf8d4723212d137acf1 Mon Sep 17 00:00:00 2001 From: Parfii-bot Date: Thu, 23 Apr 2026 13:32:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(w9c):=20/spawn-agent=20Claude=20Code=20ski?= =?UTF-8?q?ll=20=E2=80=94=20click-only=20wizard=20for=20kei-spawn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 5-phase skill wrapping kei-spawn CLI: role pick → task desc → scope preset → confirm → emit composed Agent-tool invocation. Pattern matches existing skills/site-create + skills/new-agent. 4 AskUserQuestion minimum, sole free-text is task description. RULE 0.13 / 0.12 / 0.5 / ZERO enforced. Ready for /spawn-agent invocation once kei-spawn binary built via install.sh. Co-Authored-By: Claude Opus 4.7 (1M context) --- skills/spawn-agent/SKILL.md | 131 +++++++++++++++++ skills/spawn-agent/phase-1-role.md | 84 +++++++++++ skills/spawn-agent/phase-2-task.md | 91 ++++++++++++ skills/spawn-agent/phase-3-scope.md | 163 +++++++++++++++++++++ skills/spawn-agent/phase-4-emit.md | 218 ++++++++++++++++++++++++++++ 5 files changed, 687 insertions(+) create mode 100644 skills/spawn-agent/SKILL.md create mode 100644 skills/spawn-agent/phase-1-role.md create mode 100644 skills/spawn-agent/phase-2-task.md create mode 100644 skills/spawn-agent/phase-3-scope.md create mode 100644 skills/spawn-agent/phase-4-emit.md diff --git a/skills/spawn-agent/SKILL.md b/skills/spawn-agent/SKILL.md new file mode 100644 index 0000000..f443688 --- /dev/null +++ b/skills/spawn-agent/SKILL.md @@ -0,0 +1,131 @@ +--- +name: spawn-agent +description: Prepare a composed Agent-tool invocation via kei-spawn. Click-only wizard — pick role, describe task, set scope. Emits ready-to-paste prompt + subagent_type + isolation + DNA. +argument-hint: (no arguments) +--- + +# /spawn-agent — Click-only Agent-tool composer (index) + +You convert a user's intent into a ready-to-paste `Agent`-tool invocation +via the `kei-spawn` CLI. Every decision is a click; only the task description +(Phase 2) is typed. No git, no side-effects on disk beyond the task.toml the +CLI consumes. + +This `SKILL.md` is the INDEX. Each phase lives in its own file and is +executed in order. Never skip a phase. Never re-order phases. + +--- + +## Pipeline overview + +| Phase | File | Purpose | AskUserQuestion | +|---|---|---|---| +| 1 | [phase-1-role.md](phase-1-role.md) | Pick agent role (capability tier) | 1× AskUserQuestion | +| 2 | [phase-2-task.md](phase-2-task.md) | Free-text task description (ONE paragraph) | 0× (only free-text in the skill) | +| 3 | [phase-3-scope.md](phase-3-scope.md) | Files whitelist glob patterns | 2× AskUserQuestion | +| 4 | [phase-4-emit.md](phase-4-emit.md) | Write task.toml, run kei-spawn, emit Agent-tool invocation | 1× AskUserQuestion (confirm-emit) | + +**Minimum AskUserQuestion count: 4** — pure-click contract. + +--- + +## Variables the pipeline produces + +| Name | Set in | Meaning | +|---|---|---| +| `ROLE` | Phase 1 | One of `read-only` / `explorer` / `edit-local` / `edit-shared` | +| `TASK` | Phase 2 | Free-text task description (1-3 sentences) | +| `WHITELIST` | Phase 3 | List of glob patterns (relative to repo root) | +| `DENYLIST` | Phase 3 | Optional list of glob patterns (auto-derived from role if skipped) | +| `TASK_TOML` | Phase 4 | Path `tasks/.toml` relative to current repo | +| `AGENT_ID` | Phase 4 | UUID returned by `kei-spawn spawn` | +| `DNA` | Phase 4 | SHA-256 fingerprint returned by `kei-spawn spawn` | +| `SUBAGENT_TYPE` | Phase 4 | Resolved by kei-spawn from ROLE (e.g. `code-implementer` / `researcher`) | +| `ISOLATION` | Phase 4 | Resolved by kei-spawn from ROLE (`worktree` or `shared`) | +| `WORKTREE_PATH` | Phase 4 | Returned when isolation=worktree | + +--- + +## Role → defaults map (LOAD-BEARING) + +| ROLE | subagent_type | isolation | Bash? | Writes? | +|---|---|---|---|---| +| read-only | researcher | shared | no | no | +| explorer | researcher | shared | read-only bash | no | +| edit-local | code-implementer | worktree | cargo/test only | yes (whitelist) | +| edit-shared | code-implementer | worktree | cargo/test only | yes (whitelist) | + +`kei-spawn` owns the resolution — this table is reference only. The skill +passes the ROLE string verbatim; the CLI returns the resolved values. + +--- + +## Final report (emit after Phase 4) + +``` +=== /SPAWN-AGENT REPORT === +Role: +Task (first 80): ... +Whitelist: +Denylist: +Agent ID: +DNA: ... +subagent_type: +isolation: +Worktree: + +Ready-to-paste Agent-tool invocation: + + + +Next step on return: + kei-spawn verify +``` + +--- + +## Runtime binary resolution + +`kei-spawn` must be on `PATH` OR reachable via `$KEI_RUNTIME_BIN_DIR`. The +phases call `kei-spawn ` directly; if the shell returns `command not +found`, fall back to `"$KEI_RUNTIME_BIN_DIR/kei-spawn" `. If both fail, +STOP and surface the error to the user with three constructive paths: + +- (A) Build `kei-spawn` from the kit source (`cd _primitives/_rust/kei-spawn && cargo build --release`). +- (B) Export `KEI_RUNTIME_BIN_DIR` to point at an existing build. +- (C) Install via `install.sh` which wires both. + +Never silently substitute a mock. + +--- + +## Rules (enforced at every phase) + +- **Pure-click contract.** Only `TASK` (Phase 2) is typed. Every other + decision is an `AskUserQuestion`. Count them in the final report. +- **NO DOWNGRADE (RULE -1).** Any phase that fails returns 2-3 constructive + paths, never "can't be done". +- **NO HALLUCINATION (RULE 0.4).** Never fabricate a DNA or agent_id — they + come from `kei-spawn spawn --format=json` verbatim. Never emit an Agent + invocation without a successful spawn call first. +- **Plan Mode First (RULE 0.5).** This skill IS the plan; each phase file + has its own verify-criterion. No `kei-spawn spawn` call before Phase 4's + confirm click. +- **Orchestrator branch first (RULE 0.13).** The skill NEVER invokes git. + The emitted prompt MUST contain the phrase "MUST NOT invoke git" so the + spawned agent respects the rule. Phase 4 inserts this automatically. +- **Constructor Pattern (RULE ZERO).** One file per phase. This SKILL.md + stays <200 LOC; each phase file stays <200 LOC. +- **Surgical Changes.** The skill only writes `tasks/.toml`. It does + not modify project source, does not commit, does not push. + +--- + +## References + +- [phase-1-role.md](phase-1-role.md) · [phase-2-task.md](phase-2-task.md) · [phase-3-scope.md](phase-3-scope.md) · [phase-4-emit.md](phase-4-emit.md) +- `_primitives/_rust/kei-spawn/` — CLI source (task.toml schema + spawn/verify commands) +- `skills/new-agent/SKILL.md` — sister skill: generates agent *manifests*; this skill spawns *instances* of existing agents +- `skills/hooks-control/SKILL.md` — reference click-only pattern +- RULE 0.12 (agent-git-model) — ledger row auto-written by `kei-spawn spawn` +- RULE 0.13 (orchestrator-branch-first) — ban-phrase injected by Phase 4 diff --git a/skills/spawn-agent/phase-1-role.md b/skills/spawn-agent/phase-1-role.md new file mode 100644 index 0000000..92158ca --- /dev/null +++ b/skills/spawn-agent/phase-1-role.md @@ -0,0 +1,84 @@ +# Phase 1 — Role selection + +> Goal: pick the agent role (capability tier). This single choice resolves +> `subagent_type` + `isolation` + Bash/Write permissions via `kei-spawn`. +> **Verify criterion:** `ROLE` set to one of the four fixed labels. + +--- + +## 1.a — Single AskUserQuestion + +Send ONE `AskUserQuestion` call. `multiSelect: false`. Do NOT fall through +to a default — the user must click. + +```json +{ + "questions": [ + { + "question": "Agent role / capability tier?", + "header": "Role", + "multiSelect": false, + "options": [ + { + "label": "read-only", + "description": "Researcher. Read + Grep + Glob only. No Bash. No writes. Shared worktree. Use for: literature lookup, prior art, code exploration reports." + }, + { + "label": "explorer", + "description": "Researcher + read-only Bash (ls, cat, rg, git log — no state changes). Shared worktree. Use for: audits, diagnostics, benchmark snapshots." + }, + { + "label": "edit-local", + "description": "Code-implementer with worktree isolation. Can Write/Edit within a narrow whitelist (usually one module). Bash limited to cargo/test runners. Use for: single-crate changes, localized refactors." + }, + { + "label": "edit-shared", + "description": "Code-implementer with worktree isolation + broader whitelist (multiple modules / cross-cutting). Bash limited to cargo/test. Use for: workspace-wide refactors, feature-slice work touching ≥2 crates." + } + ] + } + ] +} +``` + +Store the clicked label verbatim as `ROLE`. + +--- + +## 1.b — Guidance (for the user, shown WITH the question) + +Before sending the question, print one short paragraph: + +> Pick the capability tier. Read-only and explorer never modify disk and +> are cheap to spawn. Edit-local and edit-shared get their own git worktree +> (per RULE 0.12) and inherit a Bash allowlist restricted to test runners. +> If unsure, pick `explorer` — it's the safest writeable-ish tier and +> covers most audit / diagnostic requests. + +--- + +## 1.c — Verify criterion + +`ROLE ∈ {read-only, explorer, edit-local, edit-shared}`. If the user +dismissed the question or picked something else, loop back. Do NOT proceed +to Phase 2 without ROLE set. + +Emit a single-line confirmation: `Role locked: `. Proceed to Phase 2. + +--- + +## 1.d — Failure paths (NO DOWNGRADE) + +If the user wants a role outside the four fixed tiers (e.g. "I want a +writer with full Bash"): + +- (A) Explain that the 4 tiers are the full capability grid in `kei-spawn` + — anything else would need a new role added to the CLI. Offer to open + a task for that. +- (B) Suggest the closest existing tier (usually `edit-shared` with a + broader whitelist covers 90% of "I need more power" requests). +- (C) Abort this skill invocation and escalate to `/new-agent` if the user + actually needs a new *agent manifest*, not a new *role tier*. + +Never invent a fifth tier. `kei-spawn` will reject any ROLE not in the +fixed set. diff --git a/skills/spawn-agent/phase-2-task.md b/skills/spawn-agent/phase-2-task.md new file mode 100644 index 0000000..6f6b95b --- /dev/null +++ b/skills/spawn-agent/phase-2-task.md @@ -0,0 +1,91 @@ +# Phase 2 — Task description (the only typed phase) + +> Goal: capture a 1-3 sentence task description. This is the SOLE free-text +> input in the skill. +> **Verify criterion:** `TASK` non-empty, ≤2000 chars, not a single word. + +--- + +## 2.a — Prompt + +Print this exact message to the user (NOT an AskUserQuestion — regular chat): + +> Describe the task in 1-3 sentences. Be concrete about the deliverable. +> +> Good: "Add a --verbose flag to kei-ledger list that prints the parent_branch and dna columns. Update the integration test accordingly." +> +> Weak: "Improve ledger output" (too vague, agent will ask clarifying questions and burn turns). +> +> Excellent tasks name: (1) the target file or module, (2) the verifiable +> deliverable, (3) any existing pattern to mirror. + +Wait for the user's reply. Capture the full message as `TASK`. + +--- + +## 2.b — Validation + +Apply these checks in order. On any failure, re-print the guidance and +ask again. Do NOT fall through to Phase 3 on failure. + +1. **Non-empty.** `len(TASK.trim()) > 0`. +2. **Minimum length.** `len(TASK.trim()) >= 20`. Shorter than 20 chars is + almost certainly a single-word request — ask for more detail. +3. **Maximum length.** `len(TASK) <= 2000`. If longer, ask the user to + trim: `kei-spawn` accepts up to 4000 chars but tasks >2000 typically + indicate the user is trying to write the agent's plan for it. Push back. +4. **No secrets.** Quick regex scan for `sk-`, `ghp_`, `Bearer `, `AKIA`, + `xoxb-`, `-----BEGIN`, `:AAG` (Telegram bot token infix). If any hits, + STOP and ask the user to remove — tokens belong in `~/.claude/secrets/.env` + per RULE 0.8, never in task descriptions. +5. **No git commands.** If `TASK` contains `git commit`, `git push`, + `git add`, `git merge`, warn the user that per RULE 0.13 the spawned + agent will be explicitly banned from git — if the task REQUIRES git + operations, this skill is the wrong tool (use `/new-project` or + orchestrator-meta flow instead). + +--- + +## 2.c — Auto-augmentation + +Before storing `TASK`, prepend a fixed preamble so the spawned agent sees +the orchestrator-branch-first rule verbatim. This is NOT optional — RULE +0.13 requires the ban-phrase in every non-trivial agent prompt: + +``` +You MUST NOT invoke git, bash state-changing commands, or shell commands +that mutate the repo. Tools allowed: Read, Write, Edit, Glob, Grep (plus +read-only Bash for explorer role; test-runners only for edit-* roles). +Write files to the paths inside the whitelist. Return a file-list block +in your final report. Orchestrator owns git. + +--- TASK --- + + +``` + +Store the composed prompt as `TASK_FULL`. Keep the raw user text as +`TASK` for the report. + +--- + +## 2.d — Verify criterion + +Both `TASK` and `TASK_FULL` populated. `TASK` passes all 5 validation +checks. Emit a single-line confirmation: + +`Task captured: ... ( chars)` + +Proceed to Phase 3. + +--- + +## 2.e — Failure paths (NO DOWNGRADE) + +If the user cannot articulate the task after two prompts: + +- (A) Suggest invoking `/research` or `/debug-deep` first to clarify the + problem, then return to `/spawn-agent` once the deliverable is concrete. +- (B) Offer to scaffold a skeleton task description from the user's rough + words — show the skeleton, ask for approval. +- (C) Abort this invocation — better no agent than a confused one. diff --git a/skills/spawn-agent/phase-3-scope.md b/skills/spawn-agent/phase-3-scope.md new file mode 100644 index 0000000..8dc5055 --- /dev/null +++ b/skills/spawn-agent/phase-3-scope.md @@ -0,0 +1,163 @@ +# Phase 3 — Scope (files whitelist + optional denylist) + +> Goal: produce a concrete `WHITELIST` (glob patterns the agent may touch) +> and optionally an explicit `DENYLIST`. For read-only / explorer roles +> the whitelist is advisory; for edit-* roles it is ENFORCED by kei-spawn. +> **Verify criterion:** `WHITELIST` non-empty list of glob strings. + +--- + +## 3.a — First AskUserQuestion: scope preset + +Send ONE `AskUserQuestion` call. Presets cover ≥80% of real invocations; +pick "Custom" only if none fit. + +```json +{ + "questions": [ + { + "question": "Scope preset?", + "header": "Scope", + "multiSelect": false, + "options": [ + { + "label": "Single crate (Rust)", + "description": "crates//** — typical edit-local scope. Also includes that crate's tests/ and Cargo.toml." + }, + { + "label": "Single skill (Markdown)", + "description": "skills//** — pure-markdown skill authoring. No code compilation." + }, + { + "label": "Single agent manifest", + "description": "agents/_manifests/.toml + agents/_blocks/*.md — agent fleet authoring." + }, + { + "label": "Docs / rules only", + "description": "**/*.md — read-only or explorer roles that only touch documentation." + }, + { + "label": "Whole project (read-only)", + "description": "** — read-only or explorer roles. Not valid for edit-* (too broad; use edit-shared with explicit globs)." + }, + { + "label": "Custom", + "description": "Enter glob patterns as one free-text line (comma- or newline-separated)." + } + ] + } + ] +} +``` + +Store the clicked label as `SCOPE_PRESET`. + +--- + +## 3.b — Resolve preset to `WHITELIST` + +- **Single crate (Rust)** → follow up with ONE free-text prompt: `Crate name?` + Validate `[a-z0-9-]+`. Build: `[ "crates//**", "Cargo.toml" ]`. +- **Single skill (Markdown)** → follow up: `Skill name?` Validate `[a-z0-9-]+`. + Build: `[ "skills//**" ]`. +- **Single agent manifest** → follow up: `Agent name?` Validate `[a-z0-9-]+`. + Build: `[ "agents/_manifests/.toml", "agents/_blocks/*.md" ]`. +- **Docs / rules only** → Build: `[ "**/*.md" ]`. Warn if ROLE is edit-* — + docs-only edits rarely need worktree isolation; suggest `explorer` or + `read-only` instead. +- **Whole project (read-only)** → BLOCK if ROLE is edit-local or edit-shared. + Print: "Whole-project scope is not allowed for edit roles. Use edit-shared + with explicit globs naming the ≥2 modules you will touch." Loop back to 3.a. + Otherwise build: `[ "**" ]`. +- **Custom** → follow up: `Enter glob patterns (comma- or newline-separated).` + Parse, trim, validate each glob against the rules in 3.c. Build the list. + +--- + +## 3.c — Glob validation rules + +Apply to every pattern in `WHITELIST`: + +1. **No absolute paths.** Must not start with `/` or `~/`. globs are + repo-relative. +2. **No parent traversal.** Reject any pattern containing `..`. +3. **No leading dot-dir unless explicit.** `.git/**`, `.claude/**` must + be typed in full; reject accidental `.**`. +4. **At least one literal char.** Reject `**` alone without a scoping prefix + unless ROLE is read-only or explorer AND SCOPE_PRESET was "Whole project". +5. **Max count.** ≤20 globs. If the user pastes more, ask them to consolidate. + +On any failure, print the offending pattern and the rule that tripped; +re-prompt for that one line; do NOT fall through. + +--- + +## 3.d — Second AskUserQuestion: explicit denylist? + +Send the second `AskUserQuestion` call: + +```json +{ + "questions": [ + { + "question": "Denylist?", + "header": "Deny", + "multiSelect": false, + "options": [ + { + "label": "Auto (recommended)", + "description": "kei-spawn applies the role-default denylist: secrets/**, **/*.env, target/**, node_modules/**, .git/**, dist/**, .keisei/** — covers 95% of cases." + }, + { + "label": "Explicit", + "description": "Enter additional deny globs on top of the auto default. Use when the task whitelist accidentally includes sensitive subpaths." + }, + { + "label": "None (override auto)", + "description": "Override the auto defaults and pass an empty denylist. BLOCKED for edit-* roles — read-only / explorer only." + } + ] + } + ] +} +``` + +Resolve: + +- **Auto** → `DENYLIST = []`, let `kei-spawn` apply its role defaults. Most + common path. +- **Explicit** → follow up: `Enter deny globs (comma- or newline-separated).` + Validate via 3.c rules. `DENYLIST = [ "" ]`. `kei-spawn` will + UNION these with the role defaults (not replace). +- **None (override auto)** → if ROLE ∈ {edit-local, edit-shared} BLOCK and + loop back. Otherwise set a marker `DENYLIST_OVERRIDE = true`; Phase 4 + will pass `--no-default-deny` to `kei-spawn`. Warn the user that this + disables the `secrets/**` and `.env` safety nets. + +--- + +## 3.e — Verify criterion + +- `WHITELIST` is a non-empty list (length ≥ 1). +- Every pattern passes 3.c validation. +- `DENYLIST` resolved (may be empty list — Auto path). +- If ROLE is edit-* and WHITELIST == `[ "**" ]`, REJECT and loop to 3.a. + +Emit confirmation: + +`Scope locked: whitelist globs, deny=` + +Proceed to Phase 4. + +--- + +## 3.f — Failure paths (NO DOWNGRADE) + +If the user cannot choose a preset and Custom produces invalid globs twice: + +- (A) Offer to inspect the current repo with `rg --files | head -50` and + propose 2-3 concrete whitelists based on what's actually there. +- (B) Suggest downgrading ROLE from `edit-shared` to `explorer` — explorer + accepts `[ "**" ]` and still reads everything, without write risk. +- (C) Abort this invocation and ask the user to run `/spawn-agent` again + once the target files are clearer. diff --git a/skills/spawn-agent/phase-4-emit.md b/skills/spawn-agent/phase-4-emit.md new file mode 100644 index 0000000..75f7d7d --- /dev/null +++ b/skills/spawn-agent/phase-4-emit.md @@ -0,0 +1,218 @@ +# Phase 4 — Write task.toml, spawn via kei-spawn, emit Agent-tool invocation + +> Goal: serialize `ROLE / TASK_FULL / WHITELIST / DENYLIST` into a +> `task.toml`, call `kei-spawn spawn --format=json`, parse the JSON, and +> emit a ready-to-paste Agent-tool invocation. One confirm click before +> the spawn call (it writes a ledger row). +> **Verify criterion:** `AGENT_ID`, `DNA`, `SUBAGENT_TYPE`, `ISOLATION` +> all set; Agent-tool invocation printed. + +--- + +## 4.a — Compute `TASK_TOML` path + +Generate a short UUID (v4, first 8 hex chars is sufficient — kei-spawn +validates uniqueness on write). Path: + +``` +tasks/.toml +``` + +Relative to the current repo root. If `tasks/` does not exist, do NOT +create it from this skill — `kei-spawn spawn` will fail loudly and the +constructive path is to run `mkdir tasks && git add tasks/.gitkeep` in +the orchestrator session. + +--- + +## 4.b — Render task.toml + +Use this exact schema (verify against `_primitives/_rust/kei-spawn/src/task.rs` +before any drift; if the CLI schema changes, this phase file updates too): + +```toml +# Generated by /spawn-agent skill — do not hand-edit. +# kei-spawn consumes this file; the spawn ceremony writes a ledger row +# (RULE 0.12) and returns agent_id + dna in JSON. + +role = "" + +task = """ + +""" + +[scope] +whitelist = [ + "", + "", + # ... +] +denylist = [ + # empty if Auto; populated if Explicit; absent if Override (see 4.c) +] +``` + +TOML rules: + +- Use triple-quoted `"""..."""` for `task` so newlines in TASK_FULL survive. +- Escape any triple-quote inside TASK_FULL as `\"\"\"` (unlikely but + validate before write). +- Every whitelist entry is a TOML string (double-quoted, 4-space indented, + trailing comma). +- If `DENYLIST_OVERRIDE = true` from Phase 3.d, OMIT the `denylist` key + entirely — `kei-spawn` distinguishes "empty list" (union with defaults) + from "absent" (no defaults applied) via the `--no-default-deny` flag + passed in 4.d. + +Write the file via the `Write` tool. + +--- + +## 4.c — Confirm-emit click + +Send ONE `AskUserQuestion` before calling `kei-spawn`: + +```json +{ + "questions": [ + { + "question": "Spawn agent with this configuration?", + "header": "Confirm", + "multiSelect": false, + "options": [ + { + "label": "Yes — spawn now", + "description": "Writes ledger row, returns agent_id + DNA + subagent_type + isolation. The Agent-tool invocation will be emitted for you to paste." + }, + { + "label": "No — show me the task.toml first", + "description": "Print the generated tasks/.toml contents verbatim, then re-ask." + }, + { + "label": "Abort", + "description": "Delete the task.toml and exit the skill." + } + ] + } + ] +} +``` + +Resolve: + +- **Yes** → proceed to 4.d. +- **No** → Read the file back and print it in a fenced code block; loop + the same AskUserQuestion. +- **Abort** → delete `tasks/.toml` and emit a short summary: no + spawn, no ledger row, no Agent invocation. + +--- + +## 4.d — Run kei-spawn + +Call exactly one command (no chaining, so errors surface cleanly): + +```bash +kei-spawn spawn tasks/.toml --format=json +``` + +If `DENYLIST_OVERRIDE = true`, append `--no-default-deny`. + +If `kei-spawn` is not on PATH, fall back to `"$KEI_RUNTIME_BIN_DIR/kei-spawn"`. +If both fail, surface the SKILL.md runtime-resolution paths (A/B/C) and +STOP — do NOT fabricate a response. + +Parse the stdout JSON. Expected shape (exact field names per +`_primitives/_rust/kei-spawn/src/spawn.rs`): + +```json +{ + "agent_id": "6a48ca7b-...", + "dna": "sha256:b37e2d1e9a...", + "subagent_type": "code-implementer", + "isolation": "worktree", + "worktree_path": ".claude/worktrees/agent-6a48ca7b", + "branch": "agent/-" +} +``` + +Store each field as named (`AGENT_ID`, `DNA`, `SUBAGENT_TYPE`, `ISOLATION`, +`WORKTREE_PATH`, `BRANCH`). If `isolation == "shared"`, `worktree_path` +and `branch` may be absent — handle that gracefully. + +On non-zero exit from `kei-spawn`: print stderr verbatim, surface the +error, offer three constructive paths: + +- (A) Fix the task.toml and re-spawn (show the diff first). +- (B) Fall back to a smaller scope (loop back to Phase 3). +- (C) Abort — delete task.toml, no ledger row written. + +--- + +## 4.e — Emit the Agent-tool invocation + +Print a single fenced code block with the ready-to-paste JSON. Use the +Agent tool's exact parameter names: + +```json +{ + "subagent_type": "", + "description": "", + "prompt": "", + "isolation": "" +} +``` + +Plus a short annotation under the block: + +``` +Agent ID: +DNA: +Branch: +Worktree: + +Paste the JSON above into an Agent tool call. On return, run: + + kei-spawn verify + +to check the 6-file artefact bundle (RULE 0.12) and merge-readiness. +``` + +--- + +## 4.f — Final report + +Emit the SKILL.md-defined `=== /SPAWN-AGENT REPORT ===` block. Populate +every field from the variables above. Do NOT invent any field value — if +something is absent (e.g. worktree for shared isolation), print `n/a`. + +--- + +## 4.g — Verify criterion + +- `AGENT_ID` non-empty UUID +- `DNA` non-empty sha256 prefix +- `SUBAGENT_TYPE ∈ {researcher, code-implementer, ...}` (whatever kei-spawn + returns — the skill does not enforce a specific set) +- `ISOLATION ∈ {shared, worktree}` +- The Agent-tool invocation JSON is printed in a fenced block +- `TASK_FULL` in the `prompt` field contains the literal phrase + `MUST NOT invoke git` (RULE 0.13 ban-phrase — added in Phase 2.c) + +If the ban-phrase check fails (should be impossible after Phase 2.c), STOP +and surface a bug report — do NOT emit the invocation. + +--- + +## 4.h — Failure paths (NO DOWNGRADE) + +Covered inline in 4.d. Additionally, if the user tries to paste the +emitted JSON but the Agent tool rejects it: + +- (A) Likely `subagent_type` mismatch — run `kei-spawn roles` to list + valid subagent_type values in the current runtime and reconcile. +- (B) Likely `isolation` unsupported in the caller's Claude Code version + — fall back to `shared` and loop back to Phase 1 to re-pick a + read-only / explorer role. +- (C) Escalate to `/new-agent` if the user actually needs a new agent + manifest rather than a new instance.