From a644bfde798ae30506751ed176dcaa557b012bc5 Mon Sep 17 00:00:00 2001 From: onevcat Date: Sat, 22 Aug 2026 09:38:04 +0900 Subject: [PATCH] docs(ai): plan Agent Completion Signals (064) and split agents wait out of 063 Add the layered signal-bus plan (cooperative / launch-scoped hooks / transcript+process+OSC / heuristic) with prowl agents signal and agents wait, index it, and make 063 reference 064 instead of owning agents wait. Claude-Session: https://claude.ai/code/session_019jRM3FXUGguPFCqWAWu1Yb --- docs-ai/063-agent-workflows/000-plan.md | 37 ++-- docs-ai/063-agent-workflows/dsl-spec.md | 12 +- .../064-agent-completion-signals/000-plan.md | 190 ++++++++++++++++++ docs-ai/README.md | 1 + 4 files changed, 221 insertions(+), 19 deletions(-) create mode 100644 docs-ai/064-agent-completion-signals/000-plan.md diff --git a/docs-ai/063-agent-workflows/000-plan.md b/docs-ai/063-agent-workflows/000-plan.md index b154f3b8..5af28ee1 100644 --- a/docs-ai/063-agent-workflows/000-plan.md +++ b/docs-ai/063-agent-workflows/000-plan.md @@ -5,7 +5,7 @@ | **Status** | Planned (design in discussion; see Open questions) | | **Anchor date** | 2026-08-21 | | **Primary PRs** | TBD (see Delivery slicing) | -| **Related** | [047 cross-agent-handoff](../047-cross-agent-handoff/000-plan.md), [049 agents-toolbar-entry](../049-agents-toolbar-entry/000-plan.md), [053 agent-profiles](../053-agent-profiles/000-plan.md), [055 agent-profile-runtimes](../055-agent-profile-runtimes/000-plan.md), [059 agent-transcript-snapshots](../059-agent-transcript-snapshots/000-plan.md), [060 cli-targeting-and-contract-governance](../060-prowl-cli-targeting-and-contract-governance/000-plan.md), [061 native-toolbar-controls](../061-native-toolbar-controls/toolbar-controls.md), [#699 `prowl create pane`](https://github.com/onevcat/Prowl/issues/699), [PR #651 (direction reference, not merged)](https://github.com/onevcat/Prowl/pull/651), [DSL spec (living)](dsl-spec.md), `docs/components/handoff.md`, `docs/components/agent-profiles.md`, `docs/components/cli.md` | +| **Related** | [047 cross-agent-handoff](../047-cross-agent-handoff/000-plan.md), [049 agents-toolbar-entry](../049-agents-toolbar-entry/000-plan.md), [053 agent-profiles](../053-agent-profiles/000-plan.md), [055 agent-profile-runtimes](../055-agent-profile-runtimes/000-plan.md), [059 agent-transcript-snapshots](../059-agent-transcript-snapshots/000-plan.md), [060 cli-targeting-and-contract-governance](../060-prowl-cli-targeting-and-contract-governance/000-plan.md), [061 native-toolbar-controls](../061-native-toolbar-controls/toolbar-controls.md), [064 agent-completion-signals](../064-agent-completion-signals/000-plan.md) (signal bus, `agents signal` / `agents wait`), [#699 `prowl create pane`](https://github.com/onevcat/Prowl/issues/699), [PR #651 (direction reference, not merged)](https://github.com/onevcat/Prowl/pull/651), [DSL spec (living)](dsl-spec.md), `docs/components/handoff.md`, `docs/components/agent-profiles.md`, `docs/components/cli.md` | ## Background @@ -292,10 +292,13 @@ reference is required otherwise; `--role` is source-specific (`launch` role → ``, `pick` role → `` in the source worktree, `current` → none); `prowl profiles list` (read-only, for CLI-driven orchestration); prerequisites -`prowl create pane --direction … [--profile --prompt -]` (#699 extended) -and `prowl agents wait --until idle|done|blocked [--timeout]`. `prowl handoff -to|save` are **retired**: one release of non-executing stubs that answer `HANDOFF_RETIRED` -with the exact `prowl workflow run …` replacement, then removal (see Built-ins). +`prowl create pane --direction … [--profile --prompt -]` (#699 extended); +`prowl agents signal` / `prowl agents wait` (deterministic completion signals for the +CLI-driven route) are specified and delivered by +[064 agent-completion-signals](../064-agent-completion-signals/000-plan.md), which consumes +this entry's observer and launch boundary. `prowl handoff to|save` are **retired**: one +release of non-executing stubs that answer `HANDOFF_RETIRED` with the exact `prowl workflow +run …` replacement, then removal (see Built-ins). ### Built-ins and distribution @@ -352,12 +355,11 @@ Shapes are intentionally close to what exists so the runner and the CLI share on (`PROFILE_NOT_FOUND` / `PROFILE_NOT_UNIQUE`); `prowl.cli.create.v1` is extended additively (`resource: pane`, `anchor`, `direction`, optional `launch {profile_id, profile_name, agent}`). `prowl profiles list` is a read-only snapshot of enabled/disabled - profiles with availability (`prowl.cli.profiles.v1`). `prowl agents wait --until - idle|done|blocked|changed --timeout 1…3600` consumes the typed `ObservedAgentState` - observer described above (snapshot first → immediate return when already satisfied; - `WAIT_TIMEOUT` on expiry; `removed` / `surfaceClosed` → error `AGENT_GONE` with the last - known status in the error payload) and returns `{status, raw_state, waited_ms}` - (`prowl.cli.agents.wait.v1`). + profiles with availability (`prowl.cli.profiles.v1`). `prowl agents wait` is owned by + [064](../064-agent-completion-signals/000-plan.md): it consumes the typed + `ObservedAgentState` observer described above (snapshot first; `removed` / + `surfaceClosed` → `AGENT_GONE`) and adds the signal bus, `source`/`confidence`, and + launch-scoped hooks on top of this entry's launch boundary. - **Tests**: terminal-layer coverage extends `supacodeTests/WorktreeTerminalStateAgentProfileTests.swift` (anchored split, placement override, background tab, returned identity, provisioning failure); planner intent rendering per adapter in `supacodeTests/AgentProfileTests.swift` @@ -383,7 +385,7 @@ built-ins land, handoff migrated). | 1 | **C0** Settings IA: Agents group (Profiles / Workflows placeholder / Command Line Tool moved from Advanced) | C | — | Independent, small, decides where everything lands | | 2 | **A1** `prowl create pane` (#699) + target-surface split primitive returning the surface id; CLI four layers | A | 060 | Foundation for every `launch` into a split | | 3 | **B1** Definitions: Yams, `AgentWorkflow` model + validator + JSON Schema, three-source discovery, `prowl workflow list/validate/schema`, read-only Settings list | B | — | Parallel with A1; makes the DSL concrete and authorable | -| 4 | **A2** Profile launch boundary (`.prompt`, placement override, anchor, background, synchronous `LaunchedSurface` result) + `prowl create tab/pane --profile --prompt -` + `prowl profiles list` + `prowl agents wait` | A | A1 | Unlocks the CLI-driven route and is the runner's `launch` boundary | +| 4 | **A2** Profile launch boundary (`.prompt`, placement override, anchor, background, synchronous `LaunchedSurface` result) + `prowl create tab/pane --profile --prompt -` + `prowl profiles list` (`prowl agents wait` moved to 064) | A | A1 | Unlocks the CLI-driven route and is the runner's `launch` boundary; 064-S3 attaches launch-scoped hooks here | | 5 | **B2** Runner core (pure): run state machine incl. `repeat`, run store, template renderer, `WorkflowRequestRegistry`, action registry, watchdog with injected clock — tested against fake boundaries | B | B1 | Parallel with A2 | | 6 | **B3** Runner wiring: `WorkflowRunsFeature` effects, detection-event subscription, CLI preflight, `prowl workflow run/status/done/cancel` + contracts | B | A2, B2 | Engine first powered on | | 7 | **C1** Status center fifth state + run panel + attention triggers + notifications (061 visual verification) | C | B3 | Runs become visible | @@ -456,8 +458,15 @@ built-ins land, handoff migrated). memory. Direction: V1 edits YAML in an external editor; a GUI editor with file ↔ UI two-way sync is the long-term goal (see Open questions for the round-trip constraint). - **CLI-driven orchestration primitives ship with #699**: `prowl create tab|pane - --profile [--prompt -]`, `prowl profiles list`, `prowl agents wait` are part - of the prerequisite PRs, not a later wave. + --profile [--prompt -]` and `prowl profiles list` are part of the + prerequisite PRs, not a later wave. (`prowl agents wait` was initially listed here and + moved to 064 on 2026-08-22 — see below.) +- **Completion signals split out as 064 (2026-08-22)**: the layered signal bus, + `prowl agents signal`, launch-scoped hooks, and `prowl agents wait` with + `source`/`confidence` are an independent entry. 063 V1 does not depend on it (steps + complete on `done`; the heuristic watchdog is harmless by design); 064 consumes 063's + observer (B3) and launch boundary (A2), and in return sharpens the watchdog and enables + 063's V2 observe mode / `on_attention: ask `. - **Settings IA**: Agents becomes a sidebar group with Profiles / Workflows / Command Line Tool pages (see Design / UI); the CLI install leaves Advanced. - **No default wall-clock timeout; state-driven watchdog with grace periods** (see Design diff --git a/docs-ai/063-agent-workflows/dsl-spec.md b/docs-ai/063-agent-workflows/dsl-spec.md index 1f628b3b..cf0dc3be 100644 --- a/docs-ai/063-agent-workflows/dsl-spec.md +++ b/docs-ai/063-agent-workflows/dsl-spec.md @@ -351,11 +351,13 @@ Companion primitives for CLI-driven orchestration (same boundaries as the runner `prowl create pane --direction [--profile --prompt -]`, `prowl create tab [--profile … --prompt -]`, `prowl profiles list`, `prowl agents wait --until idle|done|blocked|changed [--timeout]`, `prowl send`, -`prowl agents read`. `agents wait` consumes the typed per-surface observer -(`ObservedAgentState`: `snapshot` first, then `changed` / `removed` / `surfaceClosed`); -it returns immediately when the snapshot already satisfies `--until`, and maps `removed` -/ `surfaceClosed` to the terminal error `AGENT_GONE` (never to `done`) unless `--until -changed` was requested. +`prowl agents read`. `agents wait` (and `agents signal`) are specified in +[064 agent-completion-signals](../064-agent-completion-signals/000-plan.md); they consume +the typed per-surface observer (`ObservedAgentState`: `snapshot` first, then `changed` / +`removed` / `surfaceClosed`, plus 064's `.signal`), return immediately when the snapshot +already satisfies `--until`, report `source`/`confidence`, and map `removed` / +`surfaceClosed` to the terminal error `AGENT_GONE` (never to `done`) unless `--until +changed` / `exit` was requested. ## 10. Run semantics diff --git a/docs-ai/064-agent-completion-signals/000-plan.md b/docs-ai/064-agent-completion-signals/000-plan.md new file mode 100644 index 00000000..3dac1138 --- /dev/null +++ b/docs-ai/064-agent-completion-signals/000-plan.md @@ -0,0 +1,190 @@ +# 064 — Agent Completion Signals: Plan + +| | | +| --- | --- | +| **Status** | Planned (per-runtime matrix pending research) | +| **Anchor date** | 2026-08-22 | +| **Primary PRs** | TBD | +| **Related** | [063 agent-workflows](../063-agent-workflows/000-plan.md) (consumer; defines the `ObservedAgentState` observer this entry feeds), [030 agent-status-detection](../030-agent-status-detection/000-plan.md), [045 native-agent-session-detection](../045-native-agent-session-detection/000-plan.md), [055 agent-profile-runtimes](../055-agent-profile-runtimes/000-plan.md), [059 agent-transcript-snapshots](../059-agent-transcript-snapshots/000-plan.md), [060 cli-targeting-and-contract-governance](../060-prowl-cli-targeting-and-contract-governance/000-plan.md), [#473](https://github.com/onevcat/Prowl/issues/473), [#676](https://github.com/onevcat/Prowl/issues/676), `docs/components/agent-detection.md`, `docs/components/cli.md` | + +## Background + +Prowl's per-pane agent status (`working` / `blocked` / `idle` / `done`) comes from +heuristic screen and process detection (030/045, `supacode/Domain/AgentDetection/PaneAgentState.swift`) +plus the 3 s working hold. It is good enough for the sidebar and Active Agents, and #676 +documents the states it still misreports. Two consumers need something stronger: + +- An agent orchestrating other agents through the `prowl` CLI (the "route B" flow that + onevcat runs daily and that 063 formalizes) has to *wait* for a sibling agent to finish. + Today that means a hand-written polling loop over `prowl agents --json`, a completion + signal based on a conventional file name, and no way to tell a trustworthy "finished" + from a heuristic guess. Ten rounds of CLI-driven adversarial review during the 063 + design (2026-08-22) reproduced every one of these pains. +- The 063 runner's watchdog nudges and escalates on heuristic state; a deterministic + "turn complete" / "needs input" event would make those nudges exact instead of guessed. + +Several agent CLIs already expose deterministic, agent-reported events — hooks, notify +commands, plugin events — and most can be enabled per launch without touching the user's +global configuration. Prowl launches agents itself (053/055), so it can attach such hooks +at launch and have the agent report to Prowl through the bundled `prowl` binary. + +## Goals + +- Introduce one **agent signal bus** per pane that merges four layers of evidence, each + tagged with `source` and `confidence`: + 0. cooperative signals — `prowl agents signal` (and 063's `prowl workflow done`); + 1. native hooks installed by Prowl at launch (agent-reported, exact); + 2. deterministic observations — native transcript turn-end markers (059), agent process + exit, OSC progress/notification sequences the CLI emits itself; + 3. heuristic screen/process detection (existing). +- Add `prowl agents signal ` so any agent (or a hook it runs) can report + `turn-complete` / `needs-input` / `session-start` / `session-end`, attributed by the + caller pane (a hook is a child of the agent process, so process ancestry still resolves + the pane). +- Add `prowl agents wait --until … [--timeout] [--min-confidence] [--include-screen]` + that resolves on the bus and reports *what kind* of signal it got. +- Make `prowl agents` honest about what each pane can offer (`signals` field) and make + hook installation self-checking with visible degradation. +- Keep per-runtime knowledge in the runtime adapters (055 capability model) with a living + research matrix, so a changed hook API is a one-adapter change. + +### Non-goals + +- Making heuristic detection itself authoritative. Layer 3 remains a hint. +- Prowl calling an LLM to judge screens. Judgment belongs to the orchestrating agent (the + skill gives it the screen tail and a rubric); an on-device Foundation Model classifier is + at most a V2 experiment. +- Editing the user's global agent configuration (`~/.claude/settings.json`, `~/.codex/config.toml`, …). + Hooks are attached only through launch-scoped flags/config the adapter has verified; a + runtime without such a channel simply stays at layers 2–3. +- Waiting semantics inside 063 workflows: the runner still completes steps only on + `prowl workflow done`; this entry improves its watchdog and enables 063's V2 observe mode. + +## Design / Approach + +### The bus and its producers + +`WorktreeTerminalManager` gains per-surface signal state feeding the typed observer 063 +defines (`ObservedAgentState`: `snapshot` / `changed` / `removed` / `surfaceClosed`), +extended with `.signal(AgentSignal)` where + +```swift +struct AgentSignal: Sendable, Equatable { + enum Kind { case turnComplete, needsInput, sessionStart, sessionEnd, progress(Int?) } + enum Source { case cli, hook(runtime: AgentProfileRuntime, event: String), transcript, process, osc, screen } + enum Confidence { case exact, high, heuristic } + let kind: Kind; let source: Source; let confidence: Confidence; let at: Date + let sessionID: String?; let detail: String? // e.g. hook payload excerpt; never secrets +} +``` + +| Producer | Mechanism | Confidence | +| --- | --- | --- | +| `prowl agents signal` | CLI handler, caller-pane attribution, optional `--origin hook:.` and `--session ` | exact | +| Launch-scoped hooks | adapter capability `signalHooks` renders the launch flag/config that makes the CLI run ` agents signal --event … --origin hook:…` on its native events (per-runtime syntax: research matrix) | exact | +| Transcript turn-end | 059's reader on the exact/high-attributed transcript, file-watch instead of polling | high/exact | +| Process exit | existing `agentEntryRemoved` | exact | +| OSC | existing progress/notification OSC handling in the Ghostty bridge, surfaced as signals | high | +| Screen/process heuristics | existing detection | heuristic | + +Every producer writes to the same per-surface state; the reducer-side consumer (063 +runner via `AppFeature`) and the CLI-side consumer (`agents wait` via the multicast +observer) see identical events. Registration and snapshot capture stay one main-actor step. + +### `prowl agents wait` + +``` +prowl agents wait --until idle|blocked|changed|exit [--timeout 1…600] + [--min-confidence exact|high|heuristic] [--include-screen ] [--json] +``` + +- Snapshot first: return immediately when the current state already satisfies `--until` + at the required confidence. +- Default `--min-confidence auto`: if the pane has a deterministic channel (a live Prowl + hook, or an exact/high transcript attribution), only layer 0–2 events resolve the wait; + heuristic events merely update "last known". Without such a channel the wait resolves + heuristically once the state has been stable for `stable-for` (3 s hold + 2 s) and says + so. +- Response: `{status, raw_state, source, confidence, waited_ms, signals: […]}`; with + `--include-screen N`, a stable `detection`-source screen tail and, when available, the + 059 result state — everything an orchestrating agent needs to judge a heuristic result in + one call. +- `removed` / `surfaceClosed` → `AGENT_GONE` (unless `--until exit`); timeout → + `WAIT_TIMEOUT` with the last known status/source. The 600 s cap matches typical agent + tool timeouts; the skill documents "re-arm on timeout". + +### Self-check and visibility + +When a Prowl-launched runtime declares a `sessionStart` hook, the launch boundary expects +the corresponding signal within a grace window; if it never arrives the pane is marked +`signals: none` (hooks did not load) instead of silently pretending. `prowl agents` +JSON gains `signals: {channels: [hook, transcript, osc], last: {...}}` per pane, and the +Active Agents panel shows a small "exact" badge for panes with a live deterministic channel. + +### Judging heuristic results (skill, not code) + +When `source == screen`, the orchestrating agent — not Prowl — decides: the `prowl-cli` +skill ships a rubric (finished answer + empty prompt box vs. spinner/tool output vs. a +permission or question dialog), tells the agent to use `--include-screen` and +`agents read`, and forbids destructive actions on heuristic evidence alone. 063's V2 +`on_attention: ask ` is the declarative form of the same idea. + +### Maintenance rules + +- Each runtime's hook support, event → `AgentSignal.Kind` mapping, payload parsing, and + launch-time rendering live in its adapter (`supacode/Domain/AgentRuntime/AgentRuntimeAdapter.swift` + family) behind a `signalHooks` capability, with fixture tests for the rendered + flag/config and for payload decoding. A CLI that changes its hook API is a one-adapter + change plus a matrix row update. +- `research-agent-completion-signals.md` (living, this folder) records per runtime: + mechanism, events, per-launch enablement syntax, payload fields, OSC behavior, + transcript marker, verification method, version, date. +- CLI contracts follow 060's four layers: `prowl.cli.agents.signal.v1`, + `prowl.cli.agents.wait.v1`, the `agents` `signals` field; schema-validated in socket + tests; `docs/components/cli.md` and the `prowl-cli` skill updated in the same PRs. + +### Delivery slicing + +| Order | Slice | Depends | Notes | +| --- | --- | --- | --- | +| 1 | **S1** Signal bus state + `.signal` observer case + `prowl agents signal` (CLI four layers) | 063 B3's observer | Layer 0 works for every runtime immediately | +| 2 | **S2** `prowl agents wait` + `agents` `signals` field + `--include-screen` + skill rubric | S1 | Route B usable; heuristic fallback honest | +| 3 | **S3** Launch-scoped hook injection per runtime (adapter `signalHooks`, self-check) | 063 A2, research matrix | Start with Claude Code and Codex; add runtimes as verified | +| 4 | **S4** Transcript file-watch and OSC producers | S1 | Layer 2 without hooks | +| 5 | **S5** 063 consumption: watchdog uses exact signals; V2 observe mode / `on_attention: ask` | 063 C1+, S3 | Recorded in 063 amendments | + +### Verification + +Unit: bus merge/ordering, confidence gating, `wait` resolution matrix (already-satisfied, +transition, removal, pane close, timeout, two concurrent waiters), hook rendering per +adapter, payload decoding, self-check degradation. Socket: `signal`/`wait` round trips and +schema. Live: one Prowl-launched Claude Code and Codex pane each — verify hook signals +arrive, `wait` resolves with `source=hook`, and a manually launched agent resolves with +`source=screen` plus screen tail. + +## Alternatives & decisions + +- **Layered bus rather than a smarter heuristic.** #676 shows the heuristic can be + improved but never made authoritative for TUIs; deterministic channels exist and should + be used where present, with honest downgrade elsewhere. +- **Judgment by the orchestrating agent, not by Prowl.** Prowl has no model access worth + adding for this; the waiting agent already has the task context and can read the screen + tail that `wait` returns. On-device FM classification is deferred as an experiment. +- **Hooks only through launch-scoped channels.** Mirrors 053/006's launch-scoped + environment decision: Prowl-launched panes get Prowl hooks; user-launched agents are + never reconfigured. +- **Separate entry from 063.** The signals are valuable without workflows, touch + detection/adapters/CLI rather than the runner, and need their own per-runtime + maintenance; 063 consumes them through one observer type. + +## Open questions + +- Per-runtime hook/notify/event support, per-launch enablement syntax, and payload shapes + — being researched; results land in `research-agent-completion-signals.md`. +- Whether hook subprocesses can always reach Prowl's socket from sandboxed runtimes + (Codex sandbox); `PROWL_CLI_SOCKET` and the bundled binary path must be passed through. +- Exact `stable-for` and self-check grace defaults. + +## Amendments + +(append `- Updated 2026-MM-DD: ... — see [00N-topic.md](00N-topic.md)` lines here) diff --git a/docs-ai/README.md b/docs-ai/README.md index e7d73a33..ebeb5f30 100644 --- a/docs-ai/README.md +++ b/docs-ai/README.md @@ -115,3 +115,4 @@ agent-facing manual for that). | 061 | [native-toolbar-controls](061-native-toolbar-controls/000-plan.md) | 2026-08-17 | Native macOS toolbar grouping, Liquid Glass ownership, and review standards | | 062 | [workspace-child-diff](062-workspace-child-diff/000-plan.md) | 2026-08-19 | Per-repository diff for workspace children via unified DiffTarget routing | | 063 | [agent-workflows](063-agent-workflows/000-plan.md) | 2026-08-21 | Agent Workflows: YAML-declared, profile-bound multi-agent orchestration (runner, `prowl workflow` CLI, status center, built-in handoff/adversarial review); successor to 047's fixed handoff flow | +| 064 | [agent-completion-signals](064-agent-completion-signals/000-plan.md) | 2026-08-22 | Layered agent signal bus (cooperative / launch-scoped hooks / transcript+process+OSC / heuristic), `prowl agents signal` + `agents wait` with source/confidence, per-runtime hook research | -- 2.51.2