diff --git a/docs-ai/063-agent-workflows/release-plan.md b/docs-ai/063-agent-workflows/release-plan.md index 602e1aa4..32beeb06 100644 --- a/docs-ai/063-agent-workflows/release-plan.md +++ b/docs-ai/063-agent-workflows/release-plan.md @@ -34,7 +34,7 @@ user-facing surface may merge before "their" release and stay dormant. Three rel | A2 | Merged | #714 | | S1 | Merged | #715: bus, multicast observer, `agents signal` | | S2 | Draft PR #718 | Paired dispatch receipt, strict ID wait, generic evidence wait; [action record](../064-agent-completion-signals/005-s2-action.md) | -| S3 wave 1 | Planned | Follows A2 + S1: tier-A launch hooks | +| S3 wave 1 | Planned | Follows S2: tier-A launch hooks consume S2 wait/channel infrastructure | | 065-S0/K1 | Planned, parallel | Skill-target spike + bundled-skill registry | | 065-K2/K3 | Planned | Follow S0/K1 inside R1 | @@ -53,9 +53,9 @@ independently in parallel. | 2 | **A2** profile launch boundary + `create tab\|pane --profile

--prompt -` + `profiles list` | 063 | A1 | CLI launches a profile with a kickoff prompt and gets the pane back | | 2 | **S1** signal bus + `ObservedAgentState` multicast observer + `prowl agents signal` (`turn-ended`, needs-input/session/progress, bounded detail) | 064 | — | layer-0 signals for every runtime | | 2 | **065-K2** shared `SymlinkInstaller` + `prowl skills list\|install\|uninstall\|path` | 065 | 065-K1 | one command installs Prowl's skills into agent skill folders | -| 3 | **S2** prompted-profile dispatch pairing (`create` dispatch ID, required `dispatch-complete --outcome ... --summary`, 256-entry receipt retention, strict ID-only `agents wait --dispatch`) + generic evidence wait, `source`/`confidence`, `--include-screen`, live `agents.signals`, and skill rubric | 064 | S1 | no hand-written polling or stale completion; deterministic task receipts stay separate from labelled heuristics | +| 3 | **S2** prompted-profile dispatch pairing (`create` dispatch ID, required `dispatch-complete --outcome ... --summary`, 256-entry receipt retention, strict ID-only `agents wait --dispatch`) + generic evidence wait, `source`/`confidence`, `--include-screen`, live `agents.signals`, and skill rubric | 064 | A2, S1 | no hand-written polling or stale completion; deterministic task receipts stay separate from labelled heuristics | | 3 | **065-K3** Agent Skills section on Settings › Command Line Tool | 065 | 065-K2 | GUI users install skills without a terminal | -| 4 | **S3 wave 1** launch-scoped hooks for tier-A runtimes (Claude Code, Codex `notify`, Copilot, Droid, Qoder, Pi, OMP, OpenCode) + self-check | 064 | A2, S1 | `agents wait` is deterministic for Prowl-launched agents | +| 4 | **S3 wave 1** launch-scoped hooks for tier-A runtimes (Claude Code, Codex `notify`, Copilot, Droid, Qoder, Pi, OMP, OpenCode) + self-check | 064 | S2 | `agents wait` is deterministic for Prowl-launched agents | User-visible result: onevcat's daily CLI-driven orchestration is first-class (`create pane --profile --prompt -` → `agents wait` → `send`). Docs: `docs/components/cli.md`, @@ -97,9 +97,9 @@ cross-worktree roles, GUI editor) and the rest of 064-S5; scheduled by demand. ``` R1: C0 A1 ──► A1b - └──► A2 ─────────┐ - S1 ──┬──► S2 ├──► S3w1 - └──────────────┘ + └──► A2 ──┐ + ├──► S2 ──► S3w1 + S1 ──┘ 065-S0/K1 ──► 065-K2 ──► 065-K3 R2: B1 ──► B2 ──► B3 (◄ A2, S1) ──► C1 ──► C2 ──► D1 (◄ 065-K1) ──► D2 (◄ S3w1) R3: D3 (◄ D2) S3w2 (◄ S3w1) S4 (◄ S1) @@ -108,6 +108,9 @@ R3+: V2 / S5 rest; delete HANDOFF_RETIRED stubs ## Change log +- 2026-08-23 — S2 review corrected the explicit critical path to A2 + S1 → S2 → S3 wave 1; + S3 consumes the wait/channel/self-check infrastructure delivered by S2 rather than branching + directly from its two transitive prerequisites. - 2026-08-23 — S2 implemented on `feat/agent-dispatch-wait-s2`: prompted Profile dispatch pairing, immutable receipts, completion/abandonment, strict and generic waits, generation-aware evidence, stable screen evidence, peer-EOF cancellation, and live diff --git a/docs-ai/064-agent-completion-signals/000-plan.md b/docs-ai/064-agent-completion-signals/000-plan.md index 81bed825..53b5df36 100644 --- a/docs-ai/064-agent-completion-signals/000-plan.md +++ b/docs-ai/064-agent-completion-signals/000-plan.md @@ -176,8 +176,8 @@ interleaves with 063's slices, is owned by the shared living | Slice | Depends | Contents / expectation | | --- | --- | --- | | **S1** | — | Signal bus state + the `ObservedAgentState` multicast observer (snapshot / changed / removed / surfaceClosed / `.signal`; first specified in 063, delivered here so it ships first) + `prowl agents signal` for `turn-ended`, `needs-input`, session, and progress events (CLI four layers, bounded detail). Layer 0 works for every runtime immediately; 063-B3 later consumes the same observer. | -| **S2** | S1 | One atomic paired-dispatch path: every CLI `create tab|pane --profile --prompt` appends the completion protocol and returns `dispatch_id`; cooperative `dispatch-complete --outcome succeeded|failed --summary`; 256-entry non-destructive in-memory receipts; ID-only strict `prowl agents wait --dispatch`; generic `wait --until` with automatic overflow resnapshot and honest heuristic fallback; `agents` current evidence field; `--include-screen`; skill rubric. Route B becomes usable without polling or stale completion. | -| **S3 wave 1** | 063-A2, S1, research matrix | Launch-scoped hook injection (adapter `signalHooks`, self-check) for tier A of the research matrix (flag/env per launch, live-verified): Claude Code `--settings`, Codex `-c notify=[…]` (native `agent-turn-complete` maps to `turn-ended`; hook trust bypass is never passed), Copilot `--plugin-dir`, Droid `--settings`, Qoder `--settings`, Pi `-e`, OMP `--hook`, OpenCode `OPENCODE_CONFIG_CONTENT`. `agents wait` becomes deterministic for Prowl-launched agents on these runtimes. | +| **S2** | 063-A2, S1 | One atomic paired-dispatch path: every CLI `create tab|pane --profile --prompt` appends the completion protocol and returns `dispatch_id`; cooperative `dispatch-complete --outcome succeeded|failed --summary`; 256-entry non-destructive in-memory receipts; ID-only strict `prowl agents wait --dispatch`; generic `wait --until` with automatic overflow resnapshot and honest heuristic fallback; `agents` current evidence field; `--include-screen`; skill rubric. Route B becomes usable without polling or stale completion. | +| **S3 wave 1** | S2, research matrix | Launch-scoped hook injection (adapter `signalHooks`, self-check) for tier A of the research matrix (flag/env per launch, live-verified): Claude Code `--settings`, Codex `-c notify=[…]` (native `agent-turn-complete` maps to `turn-ended`; hook trust bypass is never passed), Copilot `--plugin-dir`, Droid `--settings`, Qoder `--settings`, Pi `-e`, OMP `--hook`, OpenCode `OPENCODE_CONFIG_CONTENT`. `agents wait` becomes deterministic for Prowl-launched agents on these runtimes. | | **S3 wave 2** | S3 wave 1, 053 dedicated homes | Tier B (`configDirOnly`: Gemini, Qwen, Grok, Cline, Kimi) for dedicated-home profiles only; tier C (Cursor, Amp: project files) is not attached. | | **S4** | S1 | Transcript file-watch and OSC producers — layer 2 without hooks. | | **S5** | 063 C1 (part), S3/S4 + 063 V2 (rest) | 063's watchdog consumes exact signals (nudge on `turn-ended` without `done`, immediate attention on `needs-input`) — ships with 063-D2; later: 063 V2 observe mode (`expect.status` + `agents read` / hook `last_assistant_message`) and `on_attention: ask `. Recorded in 063 amendments. | @@ -242,6 +242,9 @@ opencode; partial for qodercli/qwen/amp; docs/bundle for the rest). Key conclusi ## Amendments +- Updated 2026-08-23 during S2 review: corrected explicit slice dependencies to + 063-A2 + S1 → S2 → S3 wave 1. S3 consumes S2's wait/channel/self-check infrastructure; + A2 and S1 are transitive rather than parallel alternatives. - Updated 2026-08-23 during S2 implementation: delivered the frozen paired dispatch, completion/abandonment store, strict and generic waits, generation-aware evidence, peer-disconnect cancellation, signal visibility, schemas, and documentation. Execution diff --git a/scripts/test_agent_completion_release_plan.py b/scripts/test_agent_completion_release_plan.py new file mode 100644 index 00000000..71d6ec0d --- /dev/null +++ b/scripts/test_agent_completion_release_plan.py @@ -0,0 +1,44 @@ +import pathlib +import re +import unittest + + +class AgentCompletionReleasePlanTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + root = pathlib.Path(__file__).resolve().parents[1] + cls.release_plan = ( + root / "docs-ai" / "063-agent-workflows" / "release-plan.md" + ).read_text() + cls.signal_plan = ( + root / "docs-ai" / "064-agent-completion-signals" / "000-plan.md" + ).read_text() + + def test_release_table_records_s2_before_s3(self): + self.assertRegex( + self.release_plan, + re.compile(r"\| 3 \| \*\*S2\*\* .*?\| 064 \| A2, S1 \|"), + ) + self.assertRegex( + self.release_plan, + re.compile(r"\| 4 \| \*\*S3 wave 1\*\* .*?\| 064 \| S2 \|"), + ) + + def test_signal_plan_records_transitive_slice_dependencies(self): + self.assertRegex( + self.signal_plan, + re.compile(r"\| \*\*S2\*\* \| 063-A2, S1 \|"), + ) + self.assertRegex( + self.signal_plan, + re.compile(r"\| \*\*S3 wave 1\*\* \| S2, research matrix \|"), + ) + + def test_dependency_graph_is_linear_through_s2(self): + self.assertIn("A2 ──┐", self.release_plan) + self.assertIn("├──► S2 ──► S3w1", self.release_plan) + self.assertIn("S1 ──┘", self.release_plan) + + +if __name__ == "__main__": + unittest.main()