feat(watchdog): [pipeline] — sequential standalone-agent phases via completion markers

Adds a [pipeline] block: an ordered sequence of DISTINCT agents (different prompt/model/dir) run one
at a time, advancing when each writes its completion marker — the standalone-agent analog of the
[loop] phase machine (which drives FIXED loop agents via ## DONE). The watchdog reconciles it every
tick, stateless (markers are the source of truth): exactly the first not-yet-complete stage runs,
earlier stages are retired, the active stage is stall/heal-watched. Pipeline agents are enabled=false
(the pipeline owns their lifecycle).

Also fixes a latent watchdog crash: wake_elapsed is built once at startup but config is re-read each
tick, so removing an agent's 'wake' mid-run (e.g. winding down a wake) hit agent['wake'] -> KeyError
and killed the whole watchdog silently (stalling phase advancement + stall recovery). Now skips agents
whose wake was removed.

IDEAS.md: note that [pipeline] and [loop].phases are the same shape and should be unified via an
optional per-phase agent/dir/done (fold pipeline into the phase machine, delete the parallel path).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UWTdUq2bsic7JZGqJp3nD6
This commit is contained in:
2026-07-04 13:45:47 +00:00
parent 08bbb60343
commit b739504e1f
2 changed files with 103 additions and 3 deletions

View File

@ -84,6 +84,36 @@ generations advance until fitness plateaus.
---
## Engine idea: unify the phase machine and per-agent pipelines (one apparatus)
The `[loop]` **phase machine** advances an ordered plan for a *fixed* set of loop agents (Builder +
Adversary) that run **every** phase in **one** worktree, detecting completion via a `## DONE`
commit-subject in a status file. A common variant, though, is a sequence of **distinct** agents —
different prompt/model, sometimes a different worktree — handed off one at a time (e.g. build → review →
e2e → integrate, each a separate agent). That's *the same shape* — an ordered sequence of stages, each
with a completion signal and the right agent(s) running — so it shouldn't need a **separate pipeline
apparatus**; it should be **the same phase machine**, generalized.
**The missing primitive is a per-stage `agent` + `dir`.** Agents already carry a `dir` (used for
per-agent token attribution). If a **phase entry** could optionally name the agent(s) that run it and
the directory they run in (plus a `done` marker as an alternative to `## DONE`), the one phase machine
covers both cases:
- **loop-style phase** (default/back-compat): no `agent` → the fixed loop agents run it; completion =
`## DONE` in the phase's status file, in the loop dir.
- **pipeline-style phase:** `agent = "fork-iroh"`, `dir = "work-fork"`, `done =
"work-fork/.ao-state/FORK-IROH-COMPLETE"` → advancing the phase stops the previous stage's agent and
starts this one in its dir; completion = the marker.
Advancing a phase then means "stop the outgoing stage's agent(s), start the incoming stage's agent(s) in
their dir" — a superset of today's "re-kickoff the same loop agents." The `p-lichen-orchestrator` project
prototyped this as a standalone `[pipeline]` block (stages = `{agent, done}`, reconciled by the watchdog
each tick, markers as source of truth); the lesson is that **that logic belongs in the phase machine**,
not beside it — fold `[pipeline]` into `[loop].phases` via optional `agent`/`dir`/`done` per phase and
delete the parallel mechanism. (Bonus: `on_complete`, per-phase model overrides, and the DONE-nudge all
already live on the phase machine, so pipeline-style phases inherit them for free.)
---
## Suggested next trio
If picking three that cover the most new ground: **The Line** (pipeline), **The Incident Room**