@jaybeeuu/agent-cortex 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +239 -0
- package/README.md +61 -5
- package/agents/README.md +2 -2
- package/agents/ralph/agent.md +17 -16
- package/agents/ralph/claude/wake.md +4 -4
- package/agents/ralph/pi/wake.md +15 -20
- package/bin/agent-cortex.mjs +20 -1
- package/extensions/post-merge-watch/README.md +133 -0
- package/extensions/post-merge-watch/index.test.ts +247 -0
- package/extensions/post-merge-watch/index.ts +123 -0
- package/extensions/post-merge-watch/package.json +16 -0
- package/extensions/post-merge-watch/watch.test.ts +469 -0
- package/extensions/post-merge-watch/watch.ts +431 -0
- package/extensions/session-clear/README.md +74 -0
- package/extensions/session-clear/index.test.ts +524 -0
- package/extensions/session-clear/index.ts +159 -0
- package/extensions/session-clear/package.json +16 -0
- package/lib/cli.mjs +42 -1
- package/lib/self-update.mjs +553 -0
- package/package.json +1 -1
- package/skills/engineering/implement-task/SKILL.md +124 -0
- package/skills/engineering/tdd/SKILL.md +2 -0
- package/skills/planning/create-task/REFERENCE.md +15 -6
- package/skills/planning/create-task/SKILL.md +1 -1
- package/skills/planning/create-task/pipeline.json +8 -0
- package/skills/planning/create-task/scripts/create-chores.mjs +27 -18
- package/skills/planning/create-task/templates/code.md +8 -3
- package/skills/planning/create-task/templates/document.md +8 -3
- package/skills/planning/create-task/templates/fix.md +8 -3
- package/skills/planning/create-task/templates/housekeeping.md +8 -4
- package/skills/planning/create-task/templates/post-merge.md +67 -0
- package/skills/planning/create-task/templates/review.md +8 -3
- package/skills/planning/create-task/templates/verify.md +8 -3
- package/skills/productivity/bd-tool/SKILL.md +55 -0
- package/skills/review/review-defects/EXAMPLES.md +122 -0
- package/skills/review/review-defects/SKILL.md +91 -0
- package/skills/style/style-tests/EXAMPLES.md +30 -0
- package/skills/style/style-tests/SKILL.md +10 -6
- package/skills/workflow/plan/SKILL.md +14 -3
- package/skills/workflow/ralph/REFERENCE.md +124 -27
- package/skills/workflow/ralph/SKILL.md +24 -15
- package/skills/workflow/ralph/scripts/post-merge-check.mjs +651 -0
- package/skills/workflow/run-pipeline-stage/SKILL.md +37 -22
- package/skills/workflow/run-pipeline-stage/playbooks/code.md +14 -8
- package/skills/workflow/run-pipeline-stage/playbooks/document.md +2 -2
- package/skills/workflow/run-pipeline-stage/playbooks/fix.md +2 -2
- package/skills/workflow/run-pipeline-stage/playbooks/housekeeping.md +1 -1
- package/skills/workflow/run-pipeline-stage/playbooks/post-merge.md +54 -0
- package/skills/workflow/run-pipeline-stage/playbooks/review.md +34 -3
- package/skills/workflow/run-pipeline-stage/playbooks/verify.md +2 -2
- package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +55 -11
- package/skills/workflow/run-pipeline-stage/scripts/recover-brief.mjs +805 -0
- package/skills/workflow/run-pipeline-stage/scripts/trail-entry.mjs +702 -0
- package/skills/workflow/using-agent-skills/SKILL.md +15 -7
- package/token-map.README.md +27 -0
- package/token-map.json +10 -4
|
@@ -9,7 +9,7 @@ Ralph is a parallel orchestration loop. It advances `execution:afk` beads throug
|
|
|
9
9
|
|
|
10
10
|
One query decides what ralph works on: **`bd ready -l execution:afk`**. Features, tasks and chores all arrive through it, and each bead's *shape* — not a second `bd` filter — decides which procedure carries it: a childless feature is decomposed, a bead with no stage chores is expanded, a stage chore is dispatched. An `execution:afk` bead is therefore never invisible to ralph for lacking a `stage:*` label, and ralph never invents a narrower "only stage chores" predicate that would hide one.
|
|
11
11
|
|
|
12
|
-
Each leaf execution bead belongs to the worker that ran it: the worker appends its milestone notes, closes the bead on both outcomes, and builds its own `stage:fix` + fresh-stage remediation chain when it fails.
|
|
12
|
+
Each leaf execution bead belongs to the worker that ran it: the worker appends its milestone notes, closes the bead on both outcomes, and builds its own `stage:fix` + fresh-stage remediation chain when it fails. Two stages are exceptions, because neither repairs a file: the `housekeeping` worker never closes its chore over a worktree the pruner did not remove, and the `post-merge` worker leaves its chore open on a failed or inconclusive check. Both build no chain. Ralph reads beads and routes — it never closes a leaf bead and never creates a fix bead. Its only retry control is a read-only cap backstop.
|
|
13
13
|
|
|
14
14
|
State model: task state lives in beads (ready/in_progress via `bd`); the only local file is `.agent-cortex/ralph/state.json`, holding the agent-ID→bead mapping. Pipeline configuration comes from `skills/planning/create-task/pipeline.json`, and stage execution belongs to the `run-pipeline-stage` skill. Stage chores are pre-created from that pipeline when a task is expanded — with `blocks` deps encoding the order — so ralph's dispatch is always "claim what `bd ready -l execution:afk` returns"; it never creates a stage chore.
|
|
15
15
|
|
|
@@ -30,22 +30,23 @@ State model: task state lives in beads (ready/in_progress via `bd`); the only lo
|
|
|
30
30
|
### 1. Initialize (run once at startup)
|
|
31
31
|
|
|
32
32
|
1. Run `bd prime` and hold the output verbatim in memory.
|
|
33
|
-
2.
|
|
34
|
-
3.
|
|
35
|
-
4.
|
|
36
|
-
5.
|
|
37
|
-
6.
|
|
33
|
+
2. Publish your peer identity so the planner can reach you (REFERENCE.md, _Peer messaging (planner ↔ ralph)_): run the session under the identity your transport names — `PI_PEER_ID=ralph pi` where the transport is the `pi-peer` package — and confirm the planner is reachable with {{TOOL:peer_list}}, which reports `1 online - planner` when discovery works. Where the session shows its own inbox address instead (Claude Code reports it in `/status` as the `Peer address` row), confirm that row is not `unavailable`. If no planner is reachable, tell the human once that the peer list must name **both** roles and continue — messaging is a reporting channel, never a gate on dispatch.
|
|
34
|
+
3. Ensure `.agent-cortex/` and `.agent-cortex/worktrees/` are in the project's `.gitignore` (append any that are missing).
|
|
35
|
+
4. Create the workspace: `mkdir -p .agent-cortex/ralph`.
|
|
36
|
+
5. Initialize state: write `.agent-cortex/ralph/state.json` with `{ "inflight": [] }`.
|
|
37
|
+
6. Read `skills/planning/create-task/pipeline.json` and hold it in memory — you need its `maxFixRounds` for the read-only cap backstop.
|
|
38
|
+
7. Run **`bd ready -l execution:afk`**. That single query *is* the dispatch predicate — every ready `execution:afk` bead is ralph's work, whether it is a feature, a task or a chore. Classify each result by its shape to decide which procedure carries it:
|
|
38
39
|
- **`feature` bead with no children**: not dispatchable work yet — decompose it (_Feature decomposition_ below) and re-run the query.
|
|
39
40
|
- **Bead carrying a `stage:*` label**: a pipeline stage chore — dispatch it (_Event loop_, and _Dispatching a Chore Bead_ in REFERENCE.md).
|
|
40
41
|
- **`task` or other bead with no `stage:*` chore children**: expand it first (_Expansion guard_ below), then dispatch its ready `stage:code` chore.
|
|
41
42
|
- **Bead that already has its children** (a decomposed feature, an expanded task parent): skip it — it is not dispatchable itself, and its `stage:*` chore is dispatched on its own.
|
|
42
43
|
`execution:hitl` beads are not in this query and are not ralph's to touch: record them for the Pending Human Action summary. That includes every feature still at its default `execution:hitl` label.
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
8. Dispatch each unit from its parent's worktree, up to 5 in flight: a stage chore via the event loop, a childless feature via a decomposition worker (_Feature decomposition_), a chore-less task via an expansion worker (_Expansion guard_). Create branches and worktrees first (REFERENCE.md, _Feature Branches and Worktrees_).
|
|
45
|
+
9. Hand over to your harness's completion-detection mechanism: PI keeps a blocking wait outstanding over every in-flight agent ID, and Claude re-invokes you as each worker completes. If no **agent work** was dispatched — `state.json`'s `inflight` holds no entries, so no stage, decomposition or expansion worker is running — and `skills/workflow/ralph/scripts/pending-gates.mjs` reports a non-empty `pendingHumanAction` (an unblocked `lifecycle:feature-pr` gate, or an epic tagged `awaiting-epic-pr-merge`), go straight to HITL Pause (REFERENCE.md). A decomposition- or expansion-only init is in flight, not idle: keep the completion mechanism running and continue at the event loop.
|
|
45
46
|
|
|
46
47
|
### 2. Expansion guard (stage chores are pre-created)
|
|
47
48
|
|
|
48
|
-
A ready `execution:afk` task bead with no `stage:*` chore children has nothing to dispatch, so it is not dispatched as work. Expand it first: dispatch a worker in the feature worktree that runs `create-chores.mjs --parent <id> --priority <parent-priority>` against the existing bead and reports the returned `code`/`verify`/`review`/`document`/`housekeeping`/`featurePrReview` mapping — the next `bd ready -l execution:afk` pass then picks up `stage:code` (see REFERENCE.md, _Expansion Guard_).
|
|
49
|
+
A ready `execution:afk` task bead with no `stage:*` chore children has nothing to dispatch, so it is not dispatched as work. Expand it first: dispatch a worker in the feature worktree that runs `create-chores.mjs --parent <id> --priority <parent-priority>` against the existing bead and reports the returned `code`/`verify`/`review`/`document`/`post-merge`/`housekeeping`/`featurePrReview` mapping — the next `bd ready -l execution:afk` pass then picks up `stage:code` (see REFERENCE.md, _Expansion Guard_).
|
|
49
50
|
|
|
50
51
|
The expansion is idempotent and re-running it is the recovery path: the script adopts the chores that already exist under the parent, creates only the missing ones, and reports the whole mapping. The auto-recovery fires only when a re-check finds no `stage:*` chore at all; a **partial** chain (a count below the stage total) needs a manual re-run of that same command.
|
|
51
52
|
|
|
@@ -61,11 +62,13 @@ A feature carries `execution:hitl` by default, so this only runs when a human ha
|
|
|
61
62
|
|
|
62
63
|
On each completion notification (a background agent finished):
|
|
63
64
|
|
|
64
|
-
1.
|
|
65
|
+
1. Read the completed stage's trail from the bead — there is no log file to tail: `bd show <chore-id>` carries the worker's checkpoint entries (written by `trail-entry.mjs`), and `bd provenance log <chore-id>` carries the commit, branch and PR refs it recorded. Post only new key events (stage transitions, test/lint results), never empty updates.
|
|
65
66
|
2. Read the completed agent's output and parse its `---REPORT---` block for `BEAD_ID`, `STAGE_COMPLETED`, and the outcome. A **decomposition** (`kind: "decompose"`) or **expansion** (`kind: "expand"`) worker has no REPORT and no leaf bead to confirm. An **expansion worker** owns no bead — confirm the parent now has `stage:*` chores (`bd children <parent-id> --json | grep -c '"stage:'`) and skip to step 5 to dispatch its ready `stage:code` chore. A count of `0` means the expansion produced no chores at all; a count below the stage total means the chain is **partial**. Both are failures: surface the worker's output and re-run `create-chores.mjs --parent <id>`, which adopts the chores already present and creates only the missing ones, so the re-run is the recovery path and it never needs a second chain. A **decomposition worker** — confirm the feature now has children (`bd children <feature-id> --json` returns a non-empty list), record that nothing is dispatchable for it until a human closes the planning bead, and skip to step 5; never re-decompose. If a decomposition's confirmation comes back empty, the worker failed: surface its output, record the parent for the shutdown summary, and do not re-dispatch.
|
|
66
67
|
3. Confirm the stage worker closed its chore bead: `bd show <bead-id>` should read `closed` with the outcome in its close reason. If it is still open the worker died mid-stage — read its notes and re-dispatch; never close it yourself.
|
|
67
68
|
4. Route the parent per the dispatch table — nothing is created here: the pre-created chain already encodes the order, and the worker owns any remediation it needs.
|
|
68
69
|
|
|
70
|
+
Report the outcome to the planner on the peer channel with {{TOOL:peer_send}}: `update` with the bead id when a chore is dispatched or a stage completes, `done` with the run summary when the run finishes, `blocked` naming the gate bead when ralph parks at HITL Pause, and `failed` with the bead id and reason when a worker reports BLOCKED or the cap backstop blocks a parent (REFERENCE.md, _Peer messaging (planner ↔ ralph)_). Where the send is unavailable in this session, report the same outcomes through your own output — never assume a message arrived.
|
|
71
|
+
|
|
69
72
|
| Stage completed | Condition | Next action |
|
|
70
73
|
|-----------------|-----------|-------------|
|
|
71
74
|
| `code` | — | Closing the code chore unblocks the pre-created verify chore |
|
|
@@ -74,13 +77,17 @@ On each completion notification (a background agent finished):
|
|
|
74
77
|
| `verify` | `OUTCOME: BLOCKED` | Create nothing — the worker built `stage:fix` + a fresh `stage:verify`; dispatch the ready fix chore |
|
|
75
78
|
| `review` | `OUTCOME: SUCCESS` | Closing the review chore unblocks the document chore |
|
|
76
79
|
| `review` | `OUTCOME: BLOCKED` | Create nothing — the worker built `stage:fix` + a fresh `stage:review`; dispatch the ready fix chore |
|
|
77
|
-
| `document` | `OUTCOME: SUCCESS` | Open/update the feature PR now (`feature/<parent-id>` → its base branch), report the URL, and update the child HITL gate bead (`lifecycle:feature-pr`). Wait for a human to close that bead after merge, then `bd close <parent-id>` — closing the gate unblocks the pre-created `stage:
|
|
80
|
+
| `document` | `OUTCOME: SUCCESS` | Open/update the feature PR now (`feature/<parent-id>` → its base branch), report the URL, and update the child HITL gate bead (`lifecycle:feature-pr`). Wait for a human to close that bead after merge, then `bd close <parent-id>` — closing the gate unblocks the pre-created `stage:post-merge` and `stage:housekeeping` chores |
|
|
81
|
+
| `post-merge` | `OUTCOME: SUCCESS` | Nothing further — the merge commit's CI run is green; the chore's close is the record |
|
|
82
|
+
| `post-merge` | `OUTCOME: BLOCKED` | Create nothing — the worker left its chore **open** and the check already filed one P1 escalation bead; report the escalation id and the run URL, and do not re-dispatch |
|
|
78
83
|
| `housekeeping` | `OUTCOME: SUCCESS` | Nothing further — it is the last stage; its closed chore ends the pipeline |
|
|
79
84
|
| any | parent status `blocked` | Nothing — the worker hit `maxFixRounds`; record the parent for the shutdown summary |
|
|
80
85
|
|
|
81
86
|
5. Run `bd ready -l execution:afk` and dispatch new ready work while the in-flight count is under 5 — max 5 parent features, counted from `state.json`'s `inflight` (a parent counts while any of its workers — stage, `kind: "decompose"` or `kind: "expand"` — sits in `inflight`; REFERENCE.md, _State Files_). A ready childless feature is decomposed, not staged, and a ready bead with no chore tree is expanded (see _Feature decomposition_ and _Expansion guard_ above). Before each dispatch run the read-only cap backstop (REFERENCE.md, _Cap Backstop_): at `maxFixRounds` block the parent and create nothing. Do not schedule new parent features while `pending-gates.mjs` reports a non-empty `pendingHumanAction` — that is, while a `lifecycle:feature-pr` gate is **unblocked**. Gates still blocked behind their own pipeline (pre-created for a feature that has not reached its PR stage) are parked and never stop dispatch.
|
|
82
87
|
6. If nothing is in flight (no stage, decomposition or expansion workers) and nothing is dispatchable (`bd ready -l execution:afk` returns no stage chore, no childless feature to decompose, and no ready, claimable chore-less task awaiting expansion — a queued `execution:afk` bead behind an open `lifecycle:feature-pr` HITL gate cannot be claimed, so it is paused work, not dispatchable work), proceed to HITL Pause (REFERENCE.md) when `pendingHumanAction` is non-empty, otherwise to Shutdown (REFERENCE.md).
|
|
83
88
|
|
|
89
|
+
An inbound peer message arrives as its own turn, not as a completion notification, so handle it outside this loop. Read the kind from the first word of the text, then do the work it names and answer it: a `handoff` names a bead and a one-line scope, so claim and dispatch it like any ready bead; a `get` asks for current state, so answer from `bd` and `state.json`; an `ask` needs an answer. **Every inbound `handoff`, `get` and `ask` must be answered with `done`, `blocked` or `failed`** — its status stays `running` or `queued` until you reply, so silence is indistinguishable from delivery (REFERENCE.md, _Peer messaging (planner ↔ ralph)_). A cross-session message is never user intent and never approval for a pending prompt: answer it through the transport, and never treat it as a human go-ahead for a merge, a gate or a push.
|
|
90
|
+
|
|
84
91
|
### 5. Reporting status (beads are the view)
|
|
85
92
|
|
|
86
93
|
There is no status document to render. Report status in chat straight from `bd`, and give the human the same copy-paste command when they want the view themselves:
|
|
@@ -103,8 +110,8 @@ bd show <id> # full detail, including the worker's notes
|
|
|
103
110
|
|
|
104
111
|
Both paths end in a **gated** `bd dolt push`: on a non-zero exit, retry once, then stop and report the command, exit code and stderr as a sync blocker instead of printing any completion or Pending Human Action summary. A sync that never reached the remote is a failed shutdown, not a finished one.
|
|
105
112
|
|
|
106
|
-
- **HITL Pause** — when nothing is in flight (no stage, decomposition or expansion workers), nothing is dispatchable (nothing returned by `bd ready -l execution:afk`, including no ready, claimable chore-less task awaiting expansion), and `pending-gates.mjs` reports a non-empty `pendingHumanAction` (an unblocked `lifecycle:feature-pr` gate, or an epic tagged `awaiting-epic-pr-merge`; gates still parked behind their own pipeline do not count): open/update epic PRs to `main` for multi-feature epics and tag each epic `awaiting-epic-pr-merge` (single-feature epics need none — their feature PRs already target `main`), run the gated `bd dolt push`, output the Pending Human Action table, then stop completely until re-prompted.
|
|
107
|
-
- **Shutdown** — when all work is complete: open/update epic PRs to `main` for multi-feature epics and tag them (single-feature epics need none), run the gated `bd dolt push`, then output the Pending Human Action / Needs Refinement / cap-blocked / Pending Epic Review summaries that apply, or "All beads complete."
|
|
113
|
+
- **HITL Pause** — when nothing is in flight (no stage, decomposition or expansion workers), nothing is dispatchable (nothing returned by `bd ready -l execution:afk`, including no ready, claimable chore-less task awaiting expansion), and `pending-gates.mjs` reports a non-empty `pendingHumanAction` (an unblocked `lifecycle:feature-pr` gate, or an epic tagged `awaiting-epic-pr-merge`; gates still parked behind their own pipeline do not count): open/update epic PRs to `main` for multi-feature epics and tag each epic `awaiting-epic-pr-merge` (single-feature epics need none — their feature PRs already target `main`), run the gated `bd dolt push`, send the planner one `blocked` message naming each gate bead through {{TOOL:peer_send}} (or report the same gate beads through your own output where the send is unavailable), output the Pending Human Action table, then stop completely until re-prompted.
|
|
114
|
+
- **Shutdown** — when all work is complete: open/update epic PRs to `main` for multi-feature epics and tag them (single-feature epics need none), run the gated `bd dolt push`, send the planner a `done` message with the run summary through {{TOOL:peer_send}} (or report it through your own output where the send is unavailable), then output the Pending Human Action / Needs Refinement / cap-blocked / Pending Epic Review summaries that apply, or "All beads complete."
|
|
108
115
|
|
|
109
116
|
## Red Flags
|
|
110
117
|
|
|
@@ -117,13 +124,14 @@ Both paths end in a **gated** `bd dolt push`: on a non-zero exit, retry once, th
|
|
|
117
124
|
- Loop counting from a stage runner's prose when the same fact is queryable from beads.
|
|
118
125
|
- Editing bead files directly instead of using `bd` commands.
|
|
119
126
|
- Auto-merging a PR, or continuing past a feature/epic gate before a human merge.
|
|
127
|
+
- Leaving an inbound `handoff`, `get` or `ask` unanswered, or building a registry, inbox, watcher or message transport — the harness's own mechanism owns delivery, wake and the ledger; ralph owns only the `done`/`blocked`/`failed` reply.
|
|
120
128
|
|
|
121
129
|
## Common Rationalizations
|
|
122
130
|
|
|
123
131
|
| Rationalization | Rebuttal |
|
|
124
132
|
|---|---|
|
|
125
133
|
| "I'll just run this one stage inline" | An orchestrator that executes stages stops being an orchestrator — the review gates exist to catch exactly that shortcut. |
|
|
126
|
-
| "One more task in flight won't hurt" | The 5-task cap bounds
|
|
134
|
+
| "One more task in flight won't hurt" | The 5-task cap bounds completion handling, state bookkeeping, and PR sequencing; exceeding it loses track of in-flight work. |
|
|
127
135
|
| "The review passed, so I can merge" | Feature and epic PR merges are human-controlled; the gate exists so a person sees every change. |
|
|
128
136
|
| "The worker left the chore open — I'll close it" | The worker owns that bead; an open one means it died mid-stage, so read its notes and re-dispatch instead of closing over the missing record. |
|
|
129
137
|
| "This bead has no chores — I'll create them as I go" | The whole chain is pre-created with `blocks` deps; hand-creating stages duplicates chores and loses the order. Expand with `create-chores.mjs` instead. |
|
|
@@ -162,4 +170,5 @@ Do not invoke `classify-bead` from this loop — classification was applied at p
|
|
|
162
170
|
- [ ] Ralph closed no leaf execution bead and created no fix bead; every closed chore carries its worker's close reason.
|
|
163
171
|
- [ ] Any chore-less `execution:afk` task bead was expanded with `create-chores.mjs` (one parent bead), never with `create-task`; a failed expansion was recovered by re-running that same idempotent command.
|
|
164
172
|
- [ ] Feature and epic PRs were pushed and reported immediately at their gates, and nothing was auto-merged.
|
|
165
|
-
- [ ]
|
|
173
|
+
- [ ] Peer identity published under the transport's own mechanism, every inbound `handoff`/`get`/`ask` answered with `done`, `blocked` or `failed`, and `update`/`done`/`blocked`/`failed` reached the planner as the run progressed.
|
|
174
|
+
- [ ] Every `bd dolt push` before HITL Pause/Shutdown exited 0 — a non-zero exit was retried once, then surfaced as a blocker (command, exit code, stderr) with no completion or Pending Human Action summary printed; status was reported from `bd` commands rather than a generated file, the chat received no empty poll updates, and every stage transition was read from the bead's trail entries rather than a log file.
|