diff --git a/.agents/skills/l-01-agent-lifecycles/SKILL.md b/.agents/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.agents/skills/l-01-agent-lifecycles/SKILL.md +++ b/.agents/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.agents/skills/l-01-agent-lifecycles/roles/architect.md b/.agents/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/curator.md b/.agents/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/designer.md b/.agents/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/manager.md b/.agents/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.agents/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/reviewer.md b/.agents/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/strategist.md b/.agents/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.agents/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.agents/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.agents/skills/l-01-agent-lifecycles/roles/worker.md b/.agents/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.agents/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.agents/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/SKILL.md b/.claude/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.claude/skills/l-01-agent-lifecycles/SKILL.md +++ b/.claude/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.claude/skills/l-01-agent-lifecycles/roles/architect.md b/.claude/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/curator.md b/.claude/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/designer.md b/.claude/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/manager.md b/.claude/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.claude/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/reviewer.md b/.claude/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/strategist.md b/.claude/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.claude/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.claude/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.claude/skills/l-01-agent-lifecycles/roles/worker.md b/.claude/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.claude/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.claude/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/SKILL.md b/.codex/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.codex/skills/l-01-agent-lifecycles/SKILL.md +++ b/.codex/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.codex/skills/l-01-agent-lifecycles/roles/architect.md b/.codex/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/curator.md b/.codex/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/designer.md b/.codex/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/manager.md b/.codex/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.codex/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/reviewer.md b/.codex/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/strategist.md b/.codex/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.codex/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.codex/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.codex/skills/l-01-agent-lifecycles/roles/worker.md b/.codex/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.codex/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.codex/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/SKILL.md b/.cursor/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.cursor/skills/l-01-agent-lifecycles/SKILL.md +++ b/.cursor/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/architect.md b/.cursor/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/curator.md b/.cursor/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/designer.md b/.cursor/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/manager.md b/.cursor/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.cursor/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/reviewer.md b/.cursor/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/strategist.md b/.cursor/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.cursor/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.cursor/skills/l-01-agent-lifecycles/roles/worker.md b/.cursor/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.cursor/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.cursor/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/SKILL.md b/.github-vscode/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/SKILL.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/architect.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/curator.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/designer.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/manager.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/reviewer.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/strategist.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.github-vscode/skills/l-01-agent-lifecycles/roles/worker.md b/.github-vscode/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.github-vscode/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.github-vscode/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/SKILL.md b/.hermes/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.hermes/skills/l-01-agent-lifecycles/SKILL.md +++ b/.hermes/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/architect.md b/.hermes/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/curator.md b/.hermes/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/designer.md b/.hermes/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/manager.md b/.hermes/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.hermes/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/reviewer.md b/.hermes/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/strategist.md b/.hermes/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.hermes/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.hermes/skills/l-01-agent-lifecycles/roles/worker.md b/.hermes/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.hermes/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.hermes/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/SKILL.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/SKILL.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/architect.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/curator.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/designer.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/manager.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/reviewer.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/strategist.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/worker.md b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.openclaw/workspace/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/SKILL.md b/.pi/skills/l-01-agent-lifecycles/SKILL.md index 4094072d..63b496df 100644 --- a/.pi/skills/l-01-agent-lifecycles/SKILL.md +++ b/.pi/skills/l-01-agent-lifecycles/SKILL.md @@ -281,6 +281,25 @@ For ordinary spawned seats, settings are the sole developer-controlled spend sur `spawn_agent_session` callers declare role and level, never harness/model/effort or direct launch/session spend controls. +### Hosted role dispatch is three explicit states + +Every role that dispatches another hosted role uses one exact session id through all three states: + +1. Call `spawn_agent_session` with `context` omitted and `submit=false`. Success is + `spawned-unbriefed`; it creates and binds the seat but assigns no work. +2. Call `hosted_session_readiness(session_id=, wait_seconds=)`. + Only `status=ready` advances that exact seat to harness-ready. Spawned-only and not-ready seats + are **not active work** and receive no task instructions. +3. Post exactly one durable `operator_inbox_post` row addressed by that same `agent_id`, with + `message_kind="dispatch-brief"` and `deliver_to_hosted=true`. Treat the seat as briefed only when + that row reports both `deliveryState=delivered` and + `deliveryDetail=harness-log-confirmed`. + +If step 3 fails, the original durable row stays pending on the original spawned session for the +standard injector/supervisor retry path. Never duplicate the row, append another visible draft, +or respawn merely because delivery is pending. Settings-owned `sessionCommands` remain launch +configuration; settings-owned `promptKeywords` ride the post-readiness dispatch brief exactly once. + ## settings.json Orchestration Block Machine/user overrides layer over the role-file defaults, in the **global agentic settings file** @@ -337,7 +356,8 @@ per-harness via the effective registry (claude `--model`/`--effort`; a mapping-l env-only; a session-vocabulary effort like claude's `ultracode` is delivered as a post-launch `/effort` paste). Unknown effort values REFUSE at dispatch naming the harness's vocabulary — the CLI would warn-and-silently-degrade. The free-form escape hatch (`launchArgs` verbatim argv, -`promptKeywords` riding the brief paste, `sessionCommands` pasted before the brief) is never +`promptKeywords` riding the post-readiness brief exactly once, `sessionCommands` applied during +fresh-session launch) is never validated, only recorded in spawn provenance; `orchestration.harnesses` teaches the framework new TUIs or pre-customizes builtin launches (manual: `docs/reference/harnesses.md`). `orchestration.loops` (the three-party-loop knobs: per-level loop sets, round cap, reviewer diff --git a/.pi/skills/l-01-agent-lifecycles/roles/architect.md b/.pi/skills/l-01-agent-lifecycles/roles/architect.md index 12dc4ebb..8a93631f 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/architect.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/architect.md @@ -110,6 +110,16 @@ host harness rules. Hat-collapse is allowed here because this is the owner/developer-facing seat. The same collapse is not allowed in spawned role seats. +## Hosted Role Dispatch + +Every horizontal expansion from this seat follows the shared three-state protocol in `../SKILL.md`: +`spawn_agent_session(context omitted, submit=false)` must return `spawned-unbriefed`; then +`hosted_session_readiness` must return `status=ready` for the exact returned session id; only then +post one exact-agent durable `dispatch-brief`. A spawned-only or not-ready orchestrator is not +active work. Count it briefed only from `deliveryState=delivered` plus +`deliveryDetail=harness-log-confirmed`; a failed delivery stays pending on the same row and session, +never a duplicate brief or automatic respawn. + ## Design And Drawing Board When the developer is still shaping the work, the architect wears `roles/designer.md` inline: @@ -247,8 +257,8 @@ developer or the configured distinct decider; the architect does not approve its | model | highest-reasoning | developer-facing architecture and ruling quality need the strongest model | | effort | high | decision framing is not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | developer-facing owner surface | `read_ar_files` · onboarding · route indexes · `task_doc` · inbox · gates for developer hand-offs · `spawn_agent_session` | Settings.json `orchestration.roles.architect` overrides these, and `orchestration.rolesPerLevel..architect` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/curator.md b/.pi/skills/l-01-agent-lifecycles/roles/curator.md index 7818ab59..f91534d8 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/curator.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/curator.md @@ -100,8 +100,8 @@ verdict. | model | mid-reasoning | precise onboarding edits and reference checking | | effort | medium | scales with onboarding blast radius via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | onboarding surface | native reads/edits in memory worktree · native reads in code worktree · c-05 workflow · local route indexes · shell checks · inbox | Settings.json `orchestration.roles.curator` overrides these, and `orchestration.rolesPerLevel..curator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/designer.md b/.pi/skills/l-01-agent-lifecycles/roles/designer.md index ddde9df8..b7102910 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/designer.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/designer.md @@ -91,8 +91,8 @@ absorbs architect, orchestrator, manager, worker, strategist, or reviewer work. | model | high-reasoning | reframe + blast-radius reasoning wants a strong model | | effort | high | design leverage justifies the thinking budget | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | bird's-eye toolkit | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · inbox | Settings.json `orchestration.roles.designer` overrides these, and `orchestration.rolesPerLevel..designer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/manager.md b/.pi/skills/l-01-agent-lifecycles/roles/manager.md index 3a73ea85..f4264515 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/manager.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/manager.md @@ -37,6 +37,16 @@ Roles expand horizontally into new chats; sub-agents drill vertically inside thi bounded analysis or report checks. A spawned manager never absorbs architect, orchestrator, strategist, reviewer, curator, or worker briefs. +## Hosted Role Dispatch + +Every worker, reviewer, or curator dispatch below uses the shared three-state protocol in +`../SKILL.md`: call `spawn_agent_session` with `context` omitted and `submit=false`, retain the exact +`spawned-unbriefed` session id, and require `hosted_session_readiness(...)=status=ready` for that +same id before posting one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats +are not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. If delivery fails, keep the original row and session pending +for standard retry; never duplicate the brief or respawn merely because delivery is pending. + ## Lens - **Opening move:** on a developer-declared takeover, first run `../SKILL.md`'s @@ -99,8 +109,9 @@ stops belong to the orchestrator via the system-specialist protocol. fix rounds resume the SAME builder); **every round must shrink the finding set** — a non-shrinking round escalates to the orchestrator immediately, with the full round history attached, regardless of the count. -- `spawn_agent_session(worker)` — a **fresh session** on the leaf: the brief (compiled from - `../templates/worker-brief.md`) is pasted + submitted, with `env={"AR_SPAWN_ROLE": "worker"}` and +- `spawn_agent_session(worker)` — a **fresh session** on the leaf: after exact-session readiness, + one durable `dispatch-brief` compiled from `../templates/worker-brief.md` is delivered and proven, + with `env={"AR_SPAWN_ROLE": "worker"}` and the **qualified** leaf key `//`; together they claim the worker's `(leaf, role)` seat, and the worker edits inside the leaf worktrees the brief names. - **Process and ack the worker's signals — passive contract.** A turn-report artifact is expected at @@ -224,8 +235,8 @@ own lifecycle if you need its state). | model | mid-reasoning | leaf review + coordination; strong but below the orchestrator | | effort | medium | one master's scope, not the portfolio | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | coordination + review + leaf lifecycle | `task_doc` · `read_ar_files` · gates · `spawn_agent_session` · `session_retire` (your own master's worker/reviewer/curator seats only) · worktree lifecycle (start · closeout · integrate · finalize) · C-11/`c-09` · inbox | Settings.json `orchestration.roles.manager` overrides these, and `orchestration.rolesPerLevel..manager` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/orchestrator.md b/.pi/skills/l-01-agent-lifecycles/roles/orchestrator.md index 4d7d3522..0c57eadd 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/orchestrator.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/orchestrator.md @@ -27,6 +27,16 @@ architect or owning seat via the inbox. Roles expand horizontally into new chats vertically inside this seat for bounded analysis. A spawned orchestrator never absorbs another role brief and never performs architect/developer-facing hat-collapse. +## Hosted Role Dispatch + +Every manager, strategist, reviewer, or system-specialist dispatch below means the complete shared +three-state protocol in `../SKILL.md`: spawn with `context` omitted and `submit=false` and retain the +exact `spawned-unbriefed` session id; require `hosted_session_readiness(...)=status=ready` for that +same id; then create one exact-agent durable `dispatch-brief`. Spawned-only and not-ready seats are +not active work. Briefed means both `deliveryState=delivered` and +`deliveryDetail=harness-log-confirmed`. A delivery failure remains pending on its original row and +session for standard retry; never duplicate its brief or respawn it merely for pending delivery. + ## The Event Loop **Opening move, every session — new or resumed** (resumption is the common case, not the @@ -56,8 +66,9 @@ exception): **Profile check (takeover).** Before heavy work in any job: if this session's harness/model/ effort is wrong for the run (resolved: role file < settings), spawn the right chair — -`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator` + a conversation-handover packet -(`../templates/conversation-handover-packet.md`) — and hand over; the architect still talks to the +`spawn_agent_session` with `AR_SPAWN_ROLE=orchestrator`, then deliver a conversation-handover packet +(`../templates/conversation-handover-packet.md`) as the post-readiness `dispatch-brief` — and hand +over; the architect still talks to the developer, and backend orchestrator seats stay behind the relay. Several jobs can be active across a day; the loop routes per event. The frame's phase axis stays @@ -234,7 +245,8 @@ acceptable and recorded in durable notes.) Dispatch independent ready masters in parallel by default up to `orchestration.concurrency.maxParallelMasters`. Sequential execution is the exception and must name a gate, a shared-file one-writer dependency, or an explicit ruling. For each ready master -(dependencies integrated into super), call `spawn_agent_session(manager)` with a brief compiled from +(dependencies integrated into super), run the three-state hosted-role dispatch for +`spawn_agent_session(manager)`, compiling its post-readiness `dispatch-brief` from `../templates/manager-brief.md` (`env={"AR_SPAWN_ROLE": "manager"}`, the **qualified** leaf key `//`; together the environment role and qualified leaf claim the manager's `(leaf, role)` seat; the brief carries the load-bearing base fact: master branches off @@ -444,8 +456,8 @@ task, fill small blanks, escalate real deltas). | model | highest-reasoning | portfolio blast-radius judgment wants the strongest model | | effort | high | the bird's-eye seat; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | full bird's-eye + orchestration | route indexes · onboarding · `grepai_search` · `cgc_*` · `read_ar_files` · `task_doc` · gates · `spawn_agent_session` · `session_retire` (any seat, portfolio-wide) · worktree/C-11 | Settings.json `orchestration.roles.orchestrator` overrides these, and `orchestration.rolesPerLevel..orchestrator` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/reviewer.md b/.pi/skills/l-01-agent-lifecycles/roles/reviewer.md index fbeab40d..7bc007fe 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/reviewer.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/reviewer.md @@ -180,8 +180,8 @@ integrated on super. | model | high-reasoning | adversarial review wants a strong, skeptical model | | effort | high | the last line of defense before a handover; do not economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | review surface | `read_ar_files` · `memory_quality_check` · `drift_check` · `grepai_search` · `cgc_*` · `system/tools.md` checks · report templates · inbox | Settings.json `orchestration.roles.reviewer` overrides these, and `orchestration.rolesPerLevel..reviewer` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/strategist.md b/.pi/skills/l-01-agent-lifecycles/roles/strategist.md index e4ae81d6..604e3ba3 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/strategist.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/strategist.md @@ -197,8 +197,8 @@ Everything else — `task_doc`, `worktree_*`, `lifecycle_*`, `gate_*`, `spawn_ag | model | highest-reasoning | whole-portfolio dependency + blast-radius reasoning wants the strongest model | | effort | high | the sprint plan parameterizes every downstream loop; not the place to economize | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | read-only analysis surface | `read_ar_files` · `grepai_*` · `cgc_*` · `context_packet` · `drift_check` · notes-draft write · inbox | Settings.json `orchestration.roles.strategist` overrides these, and `orchestration.rolesPerLevel..strategist` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/.pi/skills/l-01-agent-lifecycles/roles/system-specialist.md b/.pi/skills/l-01-agent-lifecycles/roles/system-specialist.md index 54422560..c38ec06c 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/system-specialist.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/system-specialist.md @@ -93,8 +93,8 @@ The orchestrator owns the final decision: fixable-in-session -> order a targeted | model | fable | system diagnosis and report synthesis | | effort | high | degradation triage is high-impact | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | provider diagnostics + native reads + inbox | provider_status · provider_diagnostics · provider_watchers when explicitly ordered · logs/metrics reads · inbox | Settings.json `orchestration.roles.system-specialist` overrides these, and diff --git a/.pi/skills/l-01-agent-lifecycles/roles/worker.md b/.pi/skills/l-01-agent-lifecycles/roles/worker.md index aa29e836..e2c59564 100644 --- a/.pi/skills/l-01-agent-lifecycles/roles/worker.md +++ b/.pi/skills/l-01-agent-lifecycles/roles/worker.md @@ -147,8 +147,8 @@ leaf well, ask when the leaf itself is in question" default. | model | mid-reasoning | competent implementer on a scoped leaf | | effort | medium | scales with leaf difficulty via settings | | launchArgs | — | free-form escape: verbatim harness argv (settings-only; never validated, recorded in spawn provenance) | -| sessionCommands | — | free-form escape: lines pasted + submitted into the fresh session before the brief (settings-only; never validated) | -| promptKeywords | — | free-form escape: prepended as the first line of the dispatch brief paste (settings-only; never validated) | +| sessionCommands | — | settings-owned launch configuration: lines pasted + submitted during fresh-session launch (never validated; not brief delivery) | +| promptKeywords | — | settings-owned keywords prepended exactly once to the post-readiness dispatch brief (never validated) | | tools | build surface | native edit · read-only AR retrieval · prescribed checks · inbox | Settings.json `orchestration.roles.worker` overrides these, and `orchestration.rolesPerLevel..worker` overrides per dispatch level (role-file defaults < settings < level override; spawn knobs manual: `docs/reference/harnesses.md`). diff --git a/README.md b/README.md index ce5531ed..34cb7bd6 100644 --- a/README.md +++ b/README.md @@ -162,8 +162,8 @@ upgrade is picked up by the next session ([Settings Reference](docs/reference/settings-json.md)). Pinning a version is the debugging/repro path, not the default: `uv tool -install 'agents-remember-mcp==3.0.0rc4'`, or one-shot without installing, -`uvx --from 'agents-remember-mcp==3.0.0rc4' agents-remember dashboard`. +install 'agents-remember-mcp==3.0.0rc5'`, or one-shot without installing, +`uvx --from 'agents-remember-mcp==3.0.0rc5' agents-remember dashboard`. > **Pre-release note (until 3.0.0 final):** the dashboard currently ships in > `3.0.0rcN` pre-releases, which default version resolution skips. Install with @@ -239,7 +239,7 @@ ar-coordination/ ## Status -Agents Remember is at `3.0.0rc4` and actively developed. The core path — by-path onboarding, drift checks, and approval-gated updates — is in real use and stable enough to rely on. The public contracts listed under [Stability](#stability) are held stable across minor releases and change only on a major bump; the internals beneath them and the optional semantic/relationship providers may still evolve, so pin a version and read the notes for your target version in [GitHub Releases](https://github.com/Foxfire1st/agents-remember/releases) — the repository's canonical changelog — before upgrading. The Claude Code path is the most exercised; other harnesses are supported but less battle-tested. +Agents Remember is at `3.0.0rc5` and actively developed. The core path — by-path onboarding, drift checks, and approval-gated updates — is in real use and stable enough to rely on. The public contracts listed under [Stability](#stability) are held stable across minor releases and change only on a major bump; the internals beneath them and the optional semantic/relationship providers may still evolve, so pin a version and read the notes for your target version in [GitHub Releases](https://github.com/Foxfire1st/agents-remember/releases) — the repository's canonical changelog — before upgrading. The Claude Code path is the most exercised; other harnesses are supported but less battle-tested. The 3.0 arc: the working session itself is now observable and steerable — a system-managed agent lifecycle with durable approval gates and an event/projection layer, served as the mission-control browser cockpit directly from the MCP package (`agents-remember dashboard`; [#2](https://github.com/Foxfire1st/agents-remember/issues/2), [#43](https://github.com/Foxfire1st/agents-remember/issues/43)). The `rc` tag means the cockpit surface is still settling toward the final 3.0.0 contract; the architecture beneath it is the one described above. diff --git a/dashboard/src/cockpit/Cockpit.test.tsx b/dashboard/src/cockpit/Cockpit.test.tsx index 846ebe78..7c980264 100644 --- a/dashboard/src/cockpit/Cockpit.test.tsx +++ b/dashboard/src/cockpit/Cockpit.test.tsx @@ -1,10 +1,15 @@ -import { cleanup, fireEvent, render } from "@testing-library/react"; +import { act, cleanup, fireEvent, render, waitFor } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; import { sessionStore } from "../data/sessions"; import { dashboardStore } from "../data/store"; import { GALLERY } from "../dev/fixtures"; -import type { LifecycleProjection, TaskDocNode, WorkspaceProjection } from "../types/projection"; +import type { + EnclosureNode, + LifecycleProjection, + TaskDocNode, + WorkspaceProjection, +} from "../types/projection"; import { CockpitShell } from "./Cockpit"; function seed(stateName: string) { @@ -113,11 +118,322 @@ function seedDrillableMaster() { afterEach(() => { cleanup(); + vi.unstubAllGlobals(); sessionStore.setState({ sessions: [], activeId: null, count: 0 }); dashboardStore.getState().reset(); window.localStorage.clear(); // the rail toggle now persists its choice; isolate it between tests }); +function deferred() { + let resolve!: () => void; + const promise = new Promise((done) => { + resolve = done; + }); + return { promise, resolve }; +} + +function liveEnclosure( + leafId: string, + lifecycleId: string, + enclosureId = leafId, +): EnclosureNode { + return { + enclosure: `/contracts/${enclosureId}`, + enclosureId, + leafId, + taskRoot: "/tasks/repo-a/ops", + taskId: "ops-master", + taskName: "ops", + repoName: "repo-a", + lifecycleId, + worktreeGroup: `/worktrees/${enclosureId}`, + humanReviewStatus: "pending-review", + closeoutStatus: "not-started", + integrationStatus: "not-started", + cleanup: "pending", + codeWorktreeExists: true, + memoryWorktreeExists: true, + actions: [], + }; +} + +function taskReaderProjection(): WorkspaceProjection { + const lifecycle = (id: string, enclosure: string): LifecycleProjection => ({ + id, + state: "running", + phase: "build", + fleeting: false, + repoId: "repo-a", + enclosure: `/contracts/${enclosure}`, + tokens: 0, + startedAt: "2026-07-12T10:00:00+00:00", + lastEventTs: "2026-07-12T10:00:30+00:00", + inferred: false, + actions: [], + tokenSeries: [], + }); + const master = taskDoc({ + id: "ops-master", + kind: "master", + title: "Body Priority Master", + docPath: "/tasks/repo-a/ops/task.json", + bodyRevision: "master-r1", + objective: "Master summary.", + subTasks: [ + { + number: "2", + name: "Drilled Reader", + file: "02_drilled.json", + status: "inProgress", + scope: "", + }, + ], + }); + const directLeaf = taskDoc({ + id: "direct-leaf", + kind: "subTask", + lifecycleId: "LC-DIRECT", + title: "Direct Leaf Reader", + docPath: "/tasks/repo-a/ops/01_direct-leaf.json", + bodyRevision: "direct-r1", + objective: "Direct leaf summary.", + }); + const drilledLeaf = taskDoc({ + id: "drilled-leaf", + kind: "subTask", + title: "Drilled Reader", + docPath: "/tasks/repo-a/ops/02_drilled.json", + bodyRevision: "drilled-r1", + objective: "Drilled summary.", + }); + const lifecycleBound = taskDoc({ + id: "bound-doc", + kind: "subTask", + lifecycleId: "LC-BOUND", + title: "Lifecycle Bound Reader", + docPath: "/tasks/repo-a/ops/03_lifecycle-bound.json", + bodyRevision: "bound-r1", + objective: "Lifecycle-bound summary.", + }); + return { + version: 2, + generatedAt: "2026-07-12T10:01:00+00:00", + lifecycles: [lifecycle("LC-DIRECT", "direct-leaf"), lifecycle("LC-BOUND", "runtime-only")], + enclosures: [ + liveEnclosure("direct-leaf", "LC-DIRECT"), + liveEnclosure("runtime-only", "LC-BOUND"), + ], + providers: [], + activeWorktreeGroups: ["direct-leaf", "runtime-only"], + metrics: { + lifecycleCount: 2, + runningCount: 2, + blockedCount: 0, + pausedCount: 0, + totalTokens: 0, + stalenessHistogram: {}, + }, + analytics: { + driftSnapshots: [], + stalestSidecars: [], + setupSummaries: [], + setupProgress: [], + routeCoverage: [], + toolReports: [], + ledgers: [], + taskDocuments: [master, directLeaf, drilledLeaf, lifecycleBound], + series: [ + { + seriesId: "ops", + repository: "repo-a", + title: "Body Priority Master", + status: "inProgress", + objective: "Master summary.", + subTasks: master.subTasks, + doneCount: 0, + totalCount: 1, + seriesTokenTotal: 0, + sections: [], + decisions: [], + docPath: master.docPath, + }, + ], + attentionQueue: [], + engineProcesses: [], + }, + }; +} + +function refreshTaskSummaries(): void { + const analytics = dashboardStore.getState().analytics; + if (!analytics) throw new Error("analytics missing"); + dashboardStore.getState().applyDelta("analytics", { + ...analytics, + taskDocuments: analytics.taskDocuments.map((doc) => ({ + ...doc, + stepsDone: doc.stepsDone + 1, + })), + }); +} + +function stubTaskReaderFetch( + projection: WorkspaceProjection, + gates: Map>, + completeObjective: Map, +) { + const fetchMock = vi.fn(async (url: string) => { + if (url.startsWith("/api/task-document")) { + const path = new URL(url, "http://dashboard.test").searchParams.get("path") ?? ""; + await gates.get(path)?.promise; + const summary = projection.analytics.taskDocuments.find((doc) => doc.docPath === path); + return { + ok: true, + status: 200, + json: async () => ({ ...summary, objective: completeObjective.get(path) }), + } as Response; + } + if (url === "/api/files/repos") { + return { ok: true, status: 200, json: async () => ({ repos: [] }) } as Response; + } + if (url === "/api/harnesses") { + return { ok: true, status: 200, json: async () => ({ harnesses: [] }) } as Response; + } + if (url === "/api/terminal/sessions") { + return { ok: true, status: 200, json: async () => ({ sessions: [] }) } as Response; + } + if (url.startsWith("/api/changeset/")) { + return { + ok: true, + status: 200, + json: async () => ({ + counters: { + code: { files: 0, insertions: 0, deletions: 0 }, + memory: { files: 0, insertions: 0, deletions: 0 }, + }, + }), + } as Response; + } + if (url.startsWith("/api/notes/list")) { + return { + ok: true, + status: 200, + json: async () => ({ repo: "repo-a", master: "ops", notes: [], truncated: false }), + } as Response; + } + return { ok: true, status: 200, json: async () => ({}) } as Response; + }); + vi.stubGlobal("fetch", fetchMock); + return fetchMock; +} + +describe("Operations click-to-detail body hydration", () => { + it("renders complete bodies for direct, master, drilled, and lifecycle-bound paths during analytics refreshes", async () => { + const projection = taskReaderProjection(); + dashboardStore.getState().applySnapshot(projection); + const gates = new Map( + projection.analytics.taskDocuments.map((doc) => [doc.docPath, deferred()]), + ); + const completeObjective = new Map( + projection.analytics.taskDocuments.map((doc) => [ + doc.docPath, + `Complete ${doc.title} objective.`, + ]), + ); + const fetchMock = stubTaskReaderFetch(projection, gates, completeObjective); + + const view = render(); + const assertClickHydratesOnce = async (label: string, path: string) => { + fireEvent.click(view.getByText(label)); + await waitFor(() => + expect( + fetchMock.mock.calls.filter(([url]) => + String(url).includes(encodeURIComponent(path)), + ), + ).toHaveLength(1), + ); + act(refreshTaskSummaries); + await Promise.resolve(); + expect( + fetchMock.mock.calls.filter(([url]) => String(url).includes(encodeURIComponent(path))), + ).toHaveLength(1); + gates.get(path)?.resolve(); + await waitFor(() => expect(view.getByText(completeObjective.get(path) ?? "")).toBeTruthy()); + }; + + await assertClickHydratesOnce( + "Direct Leaf Reader", + "/tasks/repo-a/ops/01_direct-leaf.json", + ); + await assertClickHydratesOnce("Body Priority Master", "/tasks/repo-a/ops/task.json"); + + fireEvent.click(view.getByTestId("subtask-open-1")); + const drilledPath = "/tasks/repo-a/ops/02_drilled.json"; + await waitFor(() => + expect( + fetchMock.mock.calls.filter(([url]) => String(url).includes(encodeURIComponent(drilledPath))), + ).toHaveLength(1), + ); + act(refreshTaskSummaries); + await Promise.resolve(); + expect( + fetchMock.mock.calls.filter(([url]) => String(url).includes(encodeURIComponent(drilledPath))), + ).toHaveLength(1); + gates.get(drilledPath)?.resolve(); + await waitFor(() => + expect(view.getByText(completeObjective.get(drilledPath) ?? "")).toBeTruthy(), + ); + + await assertClickHydratesOnce( + "runtime-only", + "/tasks/repo-a/ops/03_lifecycle-bound.json", + ); + }); + + it("discards task A's late body after selecting task B and hydrates B exactly once", async () => { + const projection = taskReaderProjection(); + dashboardStore.getState().applySnapshot(projection); + const gates = new Map( + projection.analytics.taskDocuments.map((doc) => [doc.docPath, deferred()]), + ); + const completeObjective = new Map( + projection.analytics.taskDocuments.map((doc) => [ + doc.docPath, + `Complete ${doc.title} objective.`, + ]), + ); + const fetchMock = stubTaskReaderFetch(projection, gates, completeObjective); + const view = render(); + const taskAPath = "/tasks/repo-a/ops/01_direct-leaf.json"; + const taskBPath = "/tasks/repo-a/ops/03_lifecycle-bound.json"; + const requestsFor = (path: string) => + fetchMock.mock.calls.filter(([url]) => String(url).includes(encodeURIComponent(path))); + + fireEvent.click(view.getByText("Direct Leaf Reader")); + await waitFor(() => expect(requestsFor(taskAPath)).toHaveLength(1)); + + fireEvent.click(view.getByText("runtime-only")); + await waitFor(() => expect(requestsFor(taskBPath)).toHaveLength(1)); + expect(view.getByText("Lifecycle-bound summary.")).toBeTruthy(); + + await act(async () => { + gates.get(taskAPath)?.resolve(); + await Promise.resolve(); + }); + + expect(view.queryByText(completeObjective.get(taskAPath) ?? "")).toBeNull(); + expect(view.queryByText(completeObjective.get(taskBPath) ?? "")).toBeNull(); + expect(view.getByText("Lifecycle-bound summary.")).toBeTruthy(); + expect(requestsFor(taskBPath)).toHaveLength(1); + + gates.get(taskBPath)?.resolve(); + await waitFor(() => + expect(view.getByText(completeObjective.get(taskBPath) ?? "")).toBeTruthy(), + ); + expect(view.queryByText(completeObjective.get(taskAPath) ?? "")).toBeNull(); + expect(requestsFor(taskBPath)).toHaveLength(1); + }); +}); + describe("serving-build stamp (260703-L15 — the July-4 ghost-process lesson)", () => { it("renders the muted stamp from the snapshot's servingBuild (commit-first)", () => { const fixture = GALLERY.find((entry) => entry.name === "engine-fleet"); diff --git a/dashboard/src/data/changeset.test.ts b/dashboard/src/data/changeset.test.ts index b7059ffc..6b11f9b7 100644 --- a/dashboard/src/data/changeset.test.ts +++ b/dashboard/src/data/changeset.test.ts @@ -18,14 +18,16 @@ describe("data/changeset client", () => { const fn = stubFetch({}); await taskChangeset("agents-remember", "files-api-ar"); await fileDiff("agents-remember", "files-api-ar", "memory", "onboarding/x.ts.md"); - await masterChangeset("agents-remember", "260628_operations-integration"); + await masterChangeset("agents-remember", "260628_operations-integration", { + includeLeaves: false, + }); const urls = (fn.mock.calls as unknown as string[][]).map((c) => c[0]); expect(urls[0]).toBe("/api/changeset/task?repo=agents-remember&scope=files-api-ar"); expect(urls[1]).toBe( "/api/changeset/file-diff?repo=agents-remember&scope=files-api-ar&kind=memory&path=onboarding%2Fx.ts.md", ); expect(urls[2]).toBe( - "/api/changeset/master?repo=agents-remember&master=260628_operations-integration", + "/api/changeset/master?repo=agents-remember&master=260628_operations-integration&includeLeaves=false", ); }); diff --git a/dashboard/src/data/changeset.ts b/dashboard/src/data/changeset.ts index 864402b5..77781552 100644 --- a/dashboard/src/data/changeset.ts +++ b/dashboard/src/data/changeset.ts @@ -49,6 +49,9 @@ export interface MasterChangeset { memory: ChangedFile[]; counters: { code: ChangeCounters; memory: ChangeCounters }; } +export interface MasterChangesetOptions { + includeLeaves?: boolean; +} export const taskChangeset = (repo: string, scope: string, base = ""): Promise => getJson(`${base}/api/changeset/task?${qs({ repo, scope })}`); @@ -65,9 +68,15 @@ export const fileDiff = ( export const masterChangeset = ( repo: string, master: string, + options: MasterChangesetOptions = {}, base = "", -): Promise => - getJson(`${base}/api/changeset/master?${qs({ repo, master })}`); +): Promise => { + const params: Record = { repo, master }; + if (options.includeLeaves !== undefined) { + params.includeLeaves = String(options.includeLeaves); + } + return getJson(`${base}/api/changeset/master?${qs(params)}`); +}; // `masterFileDiff` — BEFORE (master base) + AFTER (series tip) content for one file in the net // series diff. Same /api/changeset/file-diff route, with `master` instead of an enclosure `scope`. diff --git a/dashboard/src/data/useTaskDocumentBody.ts b/dashboard/src/data/useTaskDocumentBody.ts new file mode 100644 index 00000000..c5de79d3 --- /dev/null +++ b/dashboard/src/data/useTaskDocumentBody.ts @@ -0,0 +1,74 @@ +import { useEffect, useState } from "react"; + +import type { TaskDocNode } from "../types/projection"; + +import { fetchTaskDocument } from "./taskDocuments"; + +export type TaskDocumentBodyState = "loading" | "available" | "unavailable"; + +const taskDocumentBodyKey = ( + doc: Pick | undefined, +): string => (doc ? `${doc.docPath}\n${doc.bodyRevision ?? ""}` : ""); + +const mergeTaskDocumentBody = ( + summary: TaskDocNode, + body: Partial, +): TaskDocNode => ({ + ...summary, + ...body, + steps: body.steps ?? summary.steps, + requirements: body.requirements ?? summary.requirements, + codeExamples: body.codeExamples ?? summary.codeExamples, + decisions: body.decisions ?? summary.decisions, + openQuestions: body.openQuestions ?? summary.openQuestions, + references: body.references ?? summary.references, + subTasks: body.subTasks ?? summary.subTasks, + sections: body.sections ?? summary.sections, +}); + +export function useTaskDocumentBody(targetDoc: TaskDocNode | undefined): { + documentFor: (doc: TaskDocNode) => TaskDocNode; + state: TaskDocumentBodyState | undefined; +} { + const [bodies, setBodies] = useState>>({}); + const [states, setStates] = useState>>( + {}, + ); + const targetKey = taskDocumentBodyKey(targetDoc); + const targetPath = targetDoc?.docPath; + const cachedBody = targetKey ? bodies[targetKey] : undefined; + + useEffect(() => { + if (!targetPath || !targetKey || cachedBody) return; + let live = true; + void fetchTaskDocument(targetPath).then( + (body) => { + if (!live) return; + setBodies((current) => + current[targetKey] ? current : { ...current, [targetKey]: body }, + ); + setStates((current) => ({ ...current, [targetKey]: "available" })); + }, + () => { + if (live) setStates((current) => ({ ...current, [targetKey]: "unavailable" })); + }, + ); + return () => { + live = false; + }; + }, [targetPath, targetKey, cachedBody]); + + const state = !targetDoc + ? undefined + : cachedBody + ? "available" + : (states[targetKey] ?? "loading"); + + return { + documentFor: (doc) => { + const body = bodies[taskDocumentBodyKey(doc)]; + return body ? mergeTaskDocumentBody(doc, body) : doc; + }, + state, + }; +} diff --git a/dashboard/src/panels/AgentPickupIndicator.test.tsx b/dashboard/src/panels/AgentPickupIndicator.test.tsx index c2e9dd55..0108e81f 100644 --- a/dashboard/src/panels/AgentPickupIndicator.test.tsx +++ b/dashboard/src/panels/AgentPickupIndicator.test.tsx @@ -12,22 +12,26 @@ afterEach(() => { }); describe("AgentPickupIndicator", () => { - it("renders waiting-for-agent while the response is fresh", () => { - const { getByText, queryByTestId } = render( + it("renders inbox acknowledgment state without a model-busy spinner", () => { + const { container, getByText, queryByTestId } = render( , ); - expect(getByText("waiting for agent")).toBeTruthy(); + expect(getByText("brief unacknowledged")).toBeTruthy(); + expect(queryByTestId("agent-pickup")?.getAttribute("title")).toBe( + "Inbox delivery: delivered; brief awaiting acknowledgment", + ); + expect(container.querySelector("[style]")).toBeNull(); expect(queryByTestId("agent-pickup-dismiss")).toBeNull(); }); diff --git a/dashboard/src/panels/AgentPickupIndicator.tsx b/dashboard/src/panels/AgentPickupIndicator.tsx index 7bd30ddb..38f4348f 100644 --- a/dashboard/src/panels/AgentPickupIndicator.tsx +++ b/dashboard/src/panels/AgentPickupIndicator.tsx @@ -1,4 +1,3 @@ -import { motion } from "motion/react"; import { useState, type MouseEvent } from "react"; import { css } from "../../styled-system/css"; @@ -15,14 +14,14 @@ const shell = css({ color: "amber", fontSize: "0.66rem", }); -const spinner = css({ +const deliveryMarker = css({ width: "0.65rem", height: "0.65rem", + flex: "0 0 auto", borderWidth: "1px", borderStyle: "solid", - borderColor: "grid", - borderTopColor: "amber", - borderRadius: "999px", + borderColor: "amber", + borderRadius: "2px", }); const notice = css({ minWidth: "0", @@ -44,6 +43,8 @@ export function AgentPickupIndicator({ pickup }: { pickup: AgentPickupNode | und const [dismissing, setDismissing] = useState(false); if (!pickup) return null; const expired = pickup.state === "check-chat"; + const subject = pickup.messageKind === "dispatch-brief" ? "brief" : "message"; + const pendingLabel = `${subject} unacknowledged`; const dismissPickup = (event: MouseEvent) => { event.stopPropagation(); if (dismissing) return; @@ -55,21 +56,15 @@ export function AgentPickupIndicator({ pickup }: { pickup: AgentPickupNode | und className={shell} title={ expired - ? "The agent did not receive your approval, check your chat" - : "Waiting for agent" + ? "Inbox acknowledgment overdue; check chat" + : `Inbox delivery: ${pickup.deliveryState}; ${subject} awaiting acknowledgment` } + aria-label={expired ? "Inbox acknowledgment overdue; check chat" : pendingLabel} data-testid="agent-pickup" > - {expired ? null : ( -