@jaybeeuu/agent-cortex 2.0.0 → 2.2.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.
Files changed (183) hide show
  1. package/CHANGELOG.md +437 -0
  2. package/README.md +46 -15
  3. package/agents/README.md +22 -10
  4. package/agents/plan/agent.md +2 -2
  5. package/agents/ralph/agent.md +128 -91
  6. package/agents/ralph/claude/frontmatter.json +3 -3
  7. package/agents/ralph/claude/wake.md +46 -0
  8. package/agents/ralph/pi/{polling.md → wake.md} +35 -20
  9. package/agents/ralph-plan/agent.md +23 -11
  10. package/bin/agent-cortex.mjs +66 -4
  11. package/bin/installers/claude.mjs +262 -77
  12. package/bin/installers/pi.mjs +200 -24
  13. package/extensions/agent-guardrails/README.md +1 -1
  14. package/extensions/agent-guardrails/guardrails.ts +1 -1
  15. package/extensions/agent-guardrails/index.ts +1 -1
  16. package/extensions/agent-modes/discover.test.ts +2 -2
  17. package/extensions/output-style/README.md +58 -0
  18. package/extensions/output-style/index.ts +23 -0
  19. package/extensions/output-style/output-style.md +43 -0
  20. package/extensions/output-style/output-style.test.ts +50 -0
  21. package/extensions/output-style/output-style.ts +32 -0
  22. package/extensions/output-style/package.json +19 -0
  23. package/hooks/claude/scripts/notify.mjs +8 -1
  24. package/lib/cli.mjs +91 -2
  25. package/package.json +29 -4
  26. package/scripts/check-changeset.mjs +4 -0
  27. package/scripts/check-no-sync.mjs +5 -1
  28. package/scripts/check-skill-frontmatter.mjs +21 -0
  29. package/scripts/lib/compose-agent.mjs +69 -9
  30. package/scripts/lib/fs.mjs +10 -2
  31. package/scripts/lib/migrate.mjs +736 -0
  32. package/scripts/lib/release-gates.mjs +21 -1
  33. package/scripts/lib/skill-frontmatter.mjs +152 -0
  34. package/scripts/lib/skill-links.mjs +52 -0
  35. package/scripts/lib/verify-worker-tree.mjs +25 -0
  36. package/scripts/resolve-publish-command.mjs +4 -0
  37. package/skills/engineering/design-an-interface/SKILL.md +3 -3
  38. package/skills/engineering/grill-with-docs/SKILL.md +3 -5
  39. package/skills/engineering/improve-codebase-architecture/SKILL.md +5 -4
  40. package/skills/engineering/tdd/SKILL.md +5 -7
  41. package/skills/engineering/technical-direction/SKILL.md +5 -5
  42. package/skills/planning/classify-bead/REFERENCE.md +3 -3
  43. package/skills/planning/classify-bead/SKILL.md +14 -9
  44. package/skills/planning/classify-bead/scripts/classify-bead.mjs +5 -4
  45. package/skills/planning/create-task/REFERENCE.md +52 -3
  46. package/skills/planning/create-task/SKILL.md +70 -26
  47. package/skills/planning/create-task/scripts/{create-chores.ts → create-chores.mjs} +48 -23
  48. package/skills/planning/flesh-out-idea/REFERENCE.md +116 -0
  49. package/skills/planning/flesh-out-idea/SKILL.md +146 -0
  50. package/skills/planning/prd-to-tasks/REFERENCE.md +54 -5
  51. package/skills/planning/prd-to-tasks/SKILL.md +22 -16
  52. package/skills/planning/record-idea/FORMAT.md +66 -17
  53. package/skills/planning/record-idea/SKILL.md +48 -24
  54. package/skills/planning/request-refactor-plan/SKILL.md +4 -4
  55. package/skills/planning/spec-to-tickets/SKILL.md +5 -5
  56. package/skills/planning/write-a-prd/SKILL.md +8 -9
  57. package/skills/planning/write-a-ticket/SKILL.md +4 -6
  58. package/skills/productivity/bd-tool/SKILL.md +15 -10
  59. package/skills/productivity/grill-me/SKILL.md +5 -0
  60. package/skills/productivity/init-beads/SKILL.md +3 -3
  61. package/skills/productivity/migration/REFERENCE.md +227 -0
  62. package/skills/productivity/migration/SKILL.md +188 -0
  63. package/skills/productivity/validate-agent-dir/scripts/{validate-agent-dir.ts → validate-agent-dir.mjs} +49 -28
  64. package/skills/productivity/write-a-skill/SKILL.md +5 -5
  65. package/skills/review/maintain-agent-docs/SKILL.md +5 -7
  66. package/skills/review/refactor-skill/SKILL.md +4 -3
  67. package/skills/review/review-security/SKILL.md +3 -5
  68. package/skills/style/style-code/SKILL.md +5 -10
  69. package/skills/style/style-comms/SKILL.md +5 -7
  70. package/skills/style/style-documentation/SKILL.md +5 -6
  71. package/skills/style/style-tests/SKILL.md +5 -7
  72. package/skills/workflow/git-workflow/SKILL.md +28 -4
  73. package/skills/workflow/hitl-collab/SKILL.md +4 -6
  74. package/skills/workflow/plan/SKILL.md +41 -30
  75. package/skills/workflow/ralph/REFERENCE.md +209 -55
  76. package/skills/workflow/ralph/SKILL.md +89 -50
  77. package/skills/workflow/ralph/scripts/pending-gates.mjs +134 -0
  78. package/skills/workflow/run-pipeline-stage/SKILL.md +72 -71
  79. package/skills/workflow/run-pipeline-stage/playbooks/code.md +11 -0
  80. package/skills/workflow/run-pipeline-stage/playbooks/document.md +12 -0
  81. package/skills/workflow/run-pipeline-stage/playbooks/fix.md +12 -0
  82. package/skills/workflow/run-pipeline-stage/playbooks/review.md +11 -0
  83. package/skills/workflow/run-pipeline-stage/playbooks/verify.md +13 -0
  84. package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +73 -1
  85. package/token-map.README.md +9 -4
  86. package/token-map.json +13 -6
  87. package/.agents/skills/style-versioning/SKILL.md +0 -172
  88. package/.changeset/README.md +0 -8
  89. package/.changeset/config.json +0 -11
  90. package/.github/workflows/ci.yml +0 -302
  91. package/.junie/guidelines.md +0 -87
  92. package/.junie/mcp/mcp.json +0 -10
  93. package/AGENTS.md +0 -151
  94. package/agents/ralph/claude/polling.md +0 -31
  95. package/agents-native/ralph.md +0 -193
  96. package/docs/claude-hooks.md +0 -128
  97. package/docs/commit-signing.md +0 -231
  98. package/docs/ideas/auto-model-selection.md +0 -75
  99. package/docs/ideas/ban-content-assertion-tests.md +0 -75
  100. package/docs/ideas/bead-progress-notes-for-session-resumption.md +0 -75
  101. package/docs/ideas/classify-beads-via-deterministic-script-with-agent-fallback.md +0 -70
  102. package/docs/ideas/ctx-alias-version-and-update-commands.md +0 -65
  103. package/docs/ideas/ctx-feedback-command-for-capturing-ideas-from-any-machine.md +0 -67
  104. package/docs/ideas/dedicated-review-tests-skill.md +0 -71
  105. package/docs/ideas/deployment-beads-for-post-merge-pipelines.md +0 -36
  106. package/docs/ideas/design-and-delivery-as-separate-bead-trees/design-and-delivery-as-separate-bead-trees.md +0 -99
  107. package/docs/ideas/enable-signed-commit-enforcement-changesets-bot-commits-must-be-signed.md +0 -42
  108. package/docs/ideas/extension-manifests.md +0 -121
  109. package/docs/ideas/improve-pi-system-prompt.md +0 -37
  110. package/docs/ideas/map-every-cortex-tool-to-a-real-pi-equivalent.md +0 -95
  111. package/docs/ideas/model-selector.md +0 -40
  112. package/docs/ideas/pi-task-memory.md +0 -34
  113. package/docs/ideas/qa-extension.md +0 -43
  114. package/docs/ideas/record-idea-implementation-questions.md +0 -68
  115. package/docs/ideas/record-ideas-as-beads.md +0 -115
  116. package/docs/ideas/self-flushing-session.md +0 -72
  117. package/docs/ideas/state-in-beads-not-md.md +0 -69
  118. package/docs/ideas/subagent-visibility.md +0 -72
  119. package/docs/ideas/task-session-context.local.md +0 -95
  120. package/docs/ideas/task-session-context.md +0 -89
  121. package/docs/ideas/test-data-creation-helpers.md +0 -92
  122. package/docs/ideas/test-planning-stage-bead-in-feature-planning.md +0 -68
  123. package/docs/ideas/unified-ci-pipeline.md +0 -28
  124. package/docs/ideas/unify-the-ticket-and-task-decomposition-workflows.md +0 -71
  125. package/docs/ideas/worktree-housekeeping-for-closed-beads.md +0 -39
  126. package/docs/inspirations.md +0 -33
  127. package/docs/research/disable-model-invocation.md +0 -82
  128. package/docs/research/gas-city-research.md +0 -256
  129. package/docs/research/skill-design-research.md +0 -286
  130. package/docs/research/skill-improvements-analysis.md +0 -117
  131. package/docs/research/skill-patterns-research.md +0 -24
  132. package/docs/skills/skill-anatomy.md +0 -197
  133. package/docs/technical-direction/harness-config.md +0 -177
  134. package/docs/technical-direction/migration-execution-labels.md +0 -177
  135. package/docs/user-preferences.md +0 -17
  136. package/extensions/agent-guardrails/tsconfig.json +0 -12
  137. package/extensions/agent-modes/tsconfig.json +0 -12
  138. package/extensions/session-start/tsconfig.json +0 -12
  139. package/extensions/skill-stats/pnpm-lock.yaml +0 -329
  140. package/extensions/skill-stats/tsconfig.json +0 -12
  141. package/extensions/subagent/agents/planner.md +0 -37
  142. package/extensions/subagent/agents/reviewer.md +0 -35
  143. package/extensions/subagent/agents/scout.md +0 -50
  144. package/extensions/subagent/agents/worker.md +0 -24
  145. package/extensions/subagent/prompts/implement-and-review.md +0 -10
  146. package/extensions/subagent/prompts/implement.md +0 -10
  147. package/extensions/subagent/prompts/scout-and-plan.md +0 -9
  148. package/extensions/subagent/tsconfig.json +0 -12
  149. package/pi/keybindings.json +0 -3
  150. package/pi/settings.json +0 -34
  151. package/pnpm-workspace.yaml +0 -14
  152. package/skills/planning/create-task/scripts/package.json +0 -14
  153. package/skills/planning/create-task/scripts/pnpm-lock.yaml +0 -342
  154. package/skills/planning/create-task/scripts/tsconfig.json +0 -12
  155. package/skills/planning/record-idea/scripts/new-idea.sh +0 -89
  156. package/skills/productivity/validate-agent-dir/scripts/package.json +0 -15
  157. package/skills/productivity/validate-agent-dir/scripts/pnpm-lock.yaml +0 -329
  158. package/skills/productivity/validate-agent-dir/scripts/pnpm-workspace.yaml +0 -2
  159. package/skills/productivity/validate-agent-dir/scripts/tsconfig.json +0 -19
  160. package/skills/productivity/validate-agent-dir/scripts/validate-agent-dir.test.ts +0 -317
  161. package/skills/workflow/run-pipeline-stage/REFERENCE.md +0 -22
  162. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +0 -682
  163. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.ts +0 -588
  164. package/skills/workflow/run-pipeline-stage/scripts/package.json +0 -15
  165. package/skills/workflow/run-pipeline-stage/scripts/pnpm-lock.yaml +0 -342
  166. package/skills/workflow/run-pipeline-stage/scripts/pnpm-workspace.yaml +0 -2
  167. package/skills/workflow/run-pipeline-stage/scripts/tsconfig.json +0 -12
  168. package/test/classify-bead.test.mjs +0 -277
  169. package/test/claude-installer.test.mjs +0 -308
  170. package/test/cli.test.mjs +0 -314
  171. package/test/create-chores.test.mjs +0 -85
  172. package/test/fake-bd.test.mjs +0 -72
  173. package/test/fs.test.mjs +0 -76
  174. package/test/helpers/fake-bd.mjs +0 -87
  175. package/test/helpers/fake-claude.mjs +0 -152
  176. package/test/helpers/fake-pi.mjs +0 -132
  177. package/test/installer.test.mjs +0 -664
  178. package/test/notify-hook.test.mjs +0 -63
  179. package/test/pi-installer.test.mjs +0 -785
  180. package/test/pi-register.test.mjs +0 -342
  181. package/test/pi-sweep.test.mjs +0 -619
  182. package/test/release-gates.test.mjs +0 -190
  183. package/test/verify-worker-tree.test.mjs +0 -120
package/agents/README.md CHANGED
@@ -4,13 +4,13 @@ This document defines the canonical format for composable agent directories in a
4
4
 
5
5
  ## Motivation
6
6
 
7
- The original format used a single `*.agent.md` file per agent, combining harness-agnostic logic with harness-specific configuration. This created duplication when the same agent needed to run on multiple harnesses (PI, Claude) with different tool names and polling mechanisms.
7
+ The original format used a single `*.agent.md` file per agent, combining harness-agnostic logic with harness-specific configuration. This created duplication when the same agent needed to run on multiple harnesses (PI, Claude) with different tool names and wake mechanisms.
8
8
 
9
9
  The composable directory format separates concerns:
10
10
 
11
11
  - **Shared body**: Harness-agnostic instructions (workflow, branching model, constraints)
12
12
  - **Harness-specific frontmatter**: Tool names, model preferences, metadata per harness
13
- - **Section files**: Harness-specific instructions (e.g., polling loops) included via tokens
13
+ - **Section files**: Harness-specific instructions (e.g., the harness wake mechanism) included via tokens
14
14
 
15
15
  ## Directory Structure
16
16
 
@@ -33,12 +33,25 @@ agents/ralph/
33
33
  ├── agent.md # Shared body (branching model, dispatch logic, constraints)
34
34
  ├── pi/
35
35
  │ ├── frontmatter.json # PI tools: ["bash", "task", "read_agent", "wait_for_agents"]
36
- │ └── polling.md # PI completion: blocking wait_for_agents (no poll timer)
36
+ │ └── wake.md # PI wake: blocking wait_for_agents (no poll timer)
37
37
  └── claude/
38
38
  ├── frontmatter.json # Claude tools: ["bash", "task"]
39
- └── polling.md # Claude event-driven (no polling)
39
+ └── wake.md # Claude wake: event-driven re-invocation on worker completion
40
40
  ```
41
41
 
42
+ ### Wake mechanisms by harness
43
+
44
+ `{{SECTION:wake}}` is the one seam where harness differences belong: the shared `agent.md`
45
+ names no harness and no harness-specific tool, and every one of those facts lives in a
46
+ `wake.md` that states its mechanism in one sentence, then covers **spawn** (tool and argument
47
+ shape), **completion arrival**, **id tracking**, **log flush**, and **stop** behaviour.
48
+ `token-map.json`'s `wake.mechanism` table records the same fact machine-readably.
49
+
50
+ | Harness | `wake.mechanism` | Completion arrives via | Id tracking | Stop means |
51
+ |---------|------------------|------------------------|-------------|------------|
52
+ | `pi` | `blocking-wait` | `wait_for_agents` returns as soon as a worker finishes, result inline | `agentId` only | stop calling `wait_for_agents` — nothing to kill |
53
+ | `claude` | `event-driven` | harness re-invokes ralph with the result inline | task ID only, no `logLine` | simply stop — nothing to kill |
54
+
42
55
  ### Example: plan agent (no per-harness sections)
43
56
 
44
57
  ```
@@ -105,7 +118,7 @@ JSON schema for harness-specific metadata:
105
118
  Optional markdown files in harness subdirectories that contain harness-specific instructions. Included via `{{SECTION:name}}` tokens in agent.md.
106
119
 
107
120
  Examples:
108
- - `polling.md` — Polling loop logic (differs between PI and Claude)
121
+ - `wake.md` — How a background worker's completion reaches the agent (polling, blocking wait, event-driven)
109
122
  - `authentication.md` — Harness-specific auth setup
110
123
  - `output-format.md` — Harness-specific output formatting
111
124
 
@@ -126,7 +139,7 @@ Use {{TOOL:task}} to spawn subagents.
126
139
 
127
140
  Read {{PATH:skills/workflow/plan/SKILL.md}} for the full workflow.
128
141
 
129
- {{SECTION:polling}}
142
+ {{SECTION:wake}}
130
143
  ```
131
144
 
132
145
  When composing the final agent file for a specific harness:
@@ -161,7 +174,7 @@ as well, so either form round-trips safely.
161
174
  When a harness directory contains section files:
162
175
 
163
176
  ```
164
- agent.md + pi/frontmatter.json + pi/polling.md → composed agent
177
+ agent.md + pi/frontmatter.json + pi/wake.md → composed agent
165
178
  ```
166
179
 
167
180
  The composer:
@@ -210,8 +223,7 @@ flat agent file is committed:
210
223
  - `bin/installers/claude.mjs` (plain `agent-cortex install claude` materialises the plugin
211
224
  into `~/.agent-cortex/claude` and registers it with Claude Code; `--output <dir>` is its
212
225
  generate-only form, used by tests/CI) composes the plugin's
213
- `agents/*.md` from each agent's `claude/` harness dir (except `ralph`, which ships natively
214
- from `agents-native/ralph.md`, copied verbatim).
226
+ `agents/*.md` from each agent's `claude/` harness dir — `ralph` included.
215
227
  - The pi harness delivers two ways: the `agent-modes` extension composes `agent.md` +
216
228
  `pi/frontmatter.json` at runtime against `token-map.json`, and `agent-cortex install pi`
217
229
  renders flat pi agents + token-substituted skills into a self-contained package at
@@ -236,7 +248,7 @@ agents, token-substituted skills, extensions) at `~/.agent-cortex/pi`.
236
248
  Use the `validate-agent-dir` script to validate agent directories:
237
249
 
238
250
  ```bash
239
- node --test --import tsx/esm skills/productivity/validate-agent-dir/scripts/validate-agent-dir.test.ts
251
+ node --test test/validate-agent-dir.test.mjs
240
252
  ```
241
253
 
242
254
  The validator checks:
@@ -23,13 +23,13 @@ You follow the **plan** skill workflow. The skill is defined in `{{PATH:skills/w
23
23
 
24
24
  ### Phase 3 — Create and classify beads
25
25
  13. Create task beads via `create-task` for each task.
26
- 14. Tag parent epics with aggregate classification.
26
+ 14. Never aggregate a child's classification onto its parent — a container epic is `execution:hitl`, and the work beads beneath it state their own execution class.
27
27
  15. Present the full bead tree.
28
28
 
29
29
  ### Phase 4 — Prepare handoff to ralph
30
30
  16. Determine the handoff bead (epic or meta-epic).
31
31
  17. Tag it `workflow:ralph`.
32
- 18. Push bead state with `bd dolt push`.
32
+ 18. Push bead state with `bd dolt push` and **gate on the exit status** — non-zero: retry once, then stop and report the command, exit code and stderr as a sync blocker; the handoff has not left this machine, so do not present the handoff summary.
33
33
  19. Present the handoff summary.
34
34
 
35
35
  ## Permitted writes
@@ -4,9 +4,9 @@ You are a parallel task orchestration agent. You run multiple beads concurrently
4
4
 
5
5
  ## Spawning subagents (critical — read this first)
6
6
 
7
- RALPH HAS ONLY ONE WAY TO SPAWN SUBAGENTS: the harness-specific spawning and completion-detection mechanism documented in this file's polling section. Read that section before doing anything else — it lists the exact tool calls for your harness and the id-handling rules that keep completion tracking working.
7
+ RALPH HAS ONLY ONE WAY TO SPAWN SUBAGENTS: the harness-specific spawning and completion-detection mechanism documented in this file's **Wake mechanism** section. Read that section before doing anything else — it is the only place harness-specific tool names belong, and it lists the exact spawn call, how a completion reaches you, the id-tracking rules that keep completion handling working, and what stopping means here.
8
8
 
9
- Harness-agnostic rules (tool names and completion detection differ per harness — see the polling section):
9
+ Harness-agnostic rules (tool names and completion detection differ per harness — see the wake section):
10
10
 
11
11
  - NEVER spawn subagents from `bash` (no `pi`, no `tsx`, no `node` scripts).
12
12
  - NEVER try to run subagent work inline yourself — you only orchestrate.
@@ -14,14 +14,14 @@ Harness-agnostic rules (tool names and completion detection differ per harness
14
14
  - ALWAYS set the subagent's working directory to the feature worktree path when running stage chores.
15
15
  - ALWAYS keep the returned agent/task id in memory so you can read the result later.
16
16
 
17
- Each pipeline stage is a separate **chore bead** created on-demand as the previous stage completes. Stage tags (`stage:*`) live on chore beads, not on the parent feature bead. Loop counts are derived by querying chore children of the parent, not stored in state. Orchestration state is derived entirely from beads — the only local state is `state.json` (timer shellId + agent-ID-to-bead mapping) and per-parent log files.
17
+ Each pipeline stage is a separate **chore bead**, pre-created by `create-chores.mjs` from the `create-task` skill's `pipeline.json` when the task is expanded, with `blocks` deps that encode the stage order. Ralph never creates a stage chore — dispatch is always "claim what `bd ready -l execution:afk` returns". Stage tags (`stage:*`) live on chore beads, not on the parent feature bead. Loop counts are derived by querying chore children of the parent, not stored in state. Orchestration state is derived entirely from beads — the only local state is `state.json` (worker-ID-to-bead mapping plus whatever wake-loop handle the wake section tracks) and per-parent log files.
18
18
 
19
19
  ## Branching model
20
20
 
21
21
  - **Single-feature epics** (epic has exactly one feature task child): skip the epic branch entirely. The feature branch (`feature/<parent-id>`) is based directly from `origin/main`. The HITL PR targets `main` directly. No epic PR is required.
22
22
  - **Multi-feature epics** (epic has two or more feature task children): each epic runs on `epic/<epic-id>` (base: `origin/main`, never local `main`). Each feature branch is based from its epic branch. Completed features PR into `epic/<epic-id>`; the completed epic PRs into `main`.
23
23
  - Each parent feature task runs on `feature/<parent-id>` in `.agent-cortex/worktrees/<parent-id>`.
24
- - Each feature includes a child HITL task bead (`lifecycle:feature-pr`) for PR review/merge.
24
+ - Each implemented bead owns a child HITL PR-gate task bead (`lifecycle:feature-pr`, blocked by its own `document` chore) for PR review/merge.
25
25
  - Completed features must be reviewed by PR merge from the agent branch (`feature/<parent-id>`) into its base (epic branch for multi-feature epics, `main` for single-feature epics), then the HITL PR task bead must be closed by a human before Ralph continues feature scheduling.
26
26
  - Completed multi-feature epics must be reviewed by PR merge into `main`.
27
27
 
@@ -33,23 +33,15 @@ Run once at startup:
33
33
 
34
34
  1. Run `bd prime`. Hold the full output in memory for your own context. Subagents can run `bd prime` themselves if they need project context.
35
35
  2. Ensure `.agent-cortex/` and `.agent-cortex/worktrees/` are in the project's `.gitignore` (append any that are missing).
36
- 3. Run `bd ready` to get the initial list of available beads.
37
- 4. For each available bead, **check its classification** (already applied at creation by
38
- `create-task` via the `classify-bead` skill — do not spawn `classify-bead` from this loop):
39
- - **AFK** — eligible for agent work.
40
- - **HITL** — skip entirely; record the bead ID for the **Pending Human Action** summary at shutdown.
41
- - **Missing label / NEEDS-REFINEMENT** — skip entirely; record the bead ID for the **Needs Refinement** summary at shutdown.
36
+ 3. Run **`bd ready -l execution:afk`**. That one query is the dispatch predicate: every ready `execution:afk` bead is Ralph's work — feature, task or chore alike — so a bead is never invisible to Ralph for lacking a `stage:*` label.
37
+ 4. Classification is already settled by the query — no `classify-bead` call belongs in this loop. Route each result by its shape:
38
+ - **`feature` bead with no children** — not dispatchable work; decompose it (see _Feature decomposition_ below), then re-run the query.
39
+ - **Bead carrying a `stage:*` label** — a pipeline stage chore; dispatch it (see _Dispatching a stage chore_ below).
40
+ - **`task` or other bead with no `stage:*` chore children** — expand it (see _Expanding a chore-less task bead_ below), then dispatch its `stage:code` chore.
41
+ - **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
+ `execution:hitl` beads never appear in this query and are not Ralph's to touch: record them for the **Pending Human Action** summary at shutdown. That includes every feature still at its default `execution:hitl` label.
42
43
  5. Create Ralph's workspace directory: `mkdir -p .agent-cortex/ralph`
43
- 6. Create `.agent-cortex/ralph/state.json` with initial content:
44
- ```json
45
- { "inflight": [] }
46
- ```
47
- Then generate the progress file:
48
- ```bash
49
- # workspace must be the absolute path you cd'd into — never . or $(pwd)
50
- workspace="/absolute/path/to/worktree"
51
- pnpm --prefix skills/workflow/run-pipeline-stage/scripts exec tsx generate-progress.ts --workspace "$workspace" > "$workspace/.agent-cortex/ralph/progress.md"
52
- ```
44
+ 6. Create `.agent-cortex/ralph/state.json` with the initial shape given in the wake section (`inflight` empty, plus whatever wake-loop handle that mechanism tracks).
53
45
  7. For each AFK bead (up to 5), kick off its pipeline:
54
46
  a. Determine the epic for each bead, count its feature task children, then create branches accordingly:
55
47
  - Count feature children: `bd children <epic-id> | grep -v 'chore'` (or use `bd show` to inspect the epic).
@@ -57,44 +49,83 @@ Run once at startup:
57
49
  - **Multi-feature epic (2+ children)**: create `epic/<epic-id>` based from `origin/main`, then `feature/<parent-id>` based from `epic/<epic-id>`.
58
50
  - Ensure `.agent-cortex/worktrees/<parent-id>` exists.
59
51
  b. Claim the parent bead: `bd update <parent-id> --claim`.
60
- c. Create the first stage chore bead and dispatch it (see _Creating and dispatching a stage chore_ below).
52
+ c. Expand the bead if it has no `stage:*` chore children, then dispatch its first ready chore (see _Expanding a chore-less task bead_ and _Dispatching a stage chore_ below).
61
53
  8. Record each launched agent in `.agent-cortex/ralph/state.json` (see format below).
62
- 9. Hand over to the completion-detection mechanism in the polling section: it blocks with `wait_for_agents` (PI) or waits for event-driven wake-ups (Claude), and proceeds to **HITL Pause** directly when no agent work was dispatched and HITL gate beads are pending.
54
+ 9. Hand over to the completion-detection mechanism in the wake section: start the wake loop it describes when agent work was dispatched, and proceed to **HITL Pause** directly when none was 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`. Gates still parked behind their own pipeline do not count (REFERENCE.md, _Gate predicate_).
63
55
 
64
56
  ---
65
57
 
66
- ## Creating and dispatching a stage chore
58
+ ## Feature decomposition
67
59
 
68
- Use this procedure whenever a new chore bead is needed (initial stage, success-path next stage, or picking up a feedback chore from `bd ready`):
60
+ A ready `execution:afk` bead of type `feature` with **no** children is not dispatchable work — there is nothing to stage and nothing to expand. Decompose it, once:
69
61
 
70
- ```bash
71
- chore_id=$(bd create "[<parent-id>] <Stage title>" \
72
- --type chore --priority <same as parent> -q)
73
- bd tag $chore_id stage:<stage>
74
- bd tag $chore_id workflow:ralph
75
- bd dep add $chore_id <parent-id> --type parent-child
76
- bd update $chore_id --claim
77
- ```
62
+ 1. Confirm it is childless: `bd children <feature-id> --json` returns an empty list `[]`. Any existing child means the feature is already decomposed and this does not apply.
63
+ 2. Dispatch a **decomposition worker** in the feature worktree (`.agent-cortex/worktrees/<feature-id>`) whose whole job is to run the `create-task` hierarchy flow (`prd-to-tasks` → `create-task`) for that one **existing** feature — its planning bead and impl children only, never a second feature bead — and report the IDs it created. The worker builds one `execution:hitl` planning bead (`--parent <feature-id>`) plus `execution:afk` implementation task children (`--parent <feature-id>`, `--no-inherit-labels`), each wired with `bd dep add <impl-child> <planning-bead>` so the dependency — not an extra label — is the readiness gate. `create-task`'s feature path (its `SKILL.md` steps 5–6) is the authority for this shape.
64
+ 3. Record the worker in `inflight` as a **decomposition** entry — it holds no chore, so `choreId` is `null`:
65
+ ```json
66
+ { "kind": "decompose", "choreId": null, "parentId": "<feature-id>", "title": "<feature title>", "agentId": "<agent-id>", "logLine": 1 }
67
+ ```
68
+ 4. On completion, confirm the children exist (`bd children <feature-id> --json`) rather than trusting the report, and surface the created IDs in chat. An empty list means the decomposition failed: record the feature for the shutdown summary and continue — do **not** re-dispatch.
69
+ 5. **Never re-dispatch a decomposition.** The bead creation it runs is not idempotent, so a second run duplicates the planning bead and every implementation child beside the first.
70
+ 6. **Go idle.** After decomposition nothing is dispatchable for that feature: `bd ready -l execution:afk` still lists the feature itself (it now has children, so it is skipped — never decomposed again) but none of its children until a human closes the planning bead. Returning to the event loop with nothing to dispatch is the correct outcome — not a failure to re-expand.
78
71
 
79
- Then load the universal stage runner prompt from `skills/workflow/run-pipeline-stage/prompts/stage-runner.md`, fill in all placeholders (including `<stage>` from the bead label, parent task description from `bd show <parent-id>`, prior SUMMARY/FILES_CHANGED from the last REPORT, chore bead ID, log path `.agent-cortex/ralph/ralph-<parent-id>.log`), and spawn a subagent in **background** mode using the spawning mechanism described in the polling section, running from the feature worktree. Stage-specific policy comes from `skills/workflow/run-pipeline-stage/playbooks/<stage>.md`.
72
+ A feature carries `execution:hitl` by default, so this whole procedure only runs when a human has deliberately relabelled a feature `execution:afk` to make its delivery agent-routable. Ralph decomposes it once and then pauses behind the human's planning bead.
73
+
74
+ ---
75
+
76
+ ## Expanding a chore-less task bead
77
+
78
+ 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, then let the normal dispatch pick up the resulting `stage:code` chore:
79
+
80
+ 1. Confirm the bead is chore-less: `bd children <parent-id> --json | grep -c '"stage:'` prints `0` — add `|| true` under `set -e` or inside an `&&` chain, since `grep -c` exits `1` on a zero count and the printed number is the answer. A bead that already has stage chores is never expanded again.
81
+ 2. Dispatch an **expansion worker** in the feature worktree (`.agent-cortex/worktrees/<parent-id>`, created per the branching model if it is missing) whose whole job is to run the pre-creator against the existing bead and report the JSON it printed:
82
+
83
+ ```bash
84
+ node <create-task-scripts>/create-chores.mjs \
85
+ --parent <parent-id> --priority <parent-priority>
86
+ ```
87
+
88
+ `<create-task-scripts>` is the absolute path to the `create-task` skill's `scripts/` directory, resolved from wherever the skill was loaded. `<parent-priority>` is the parent bead's own priority from `bd show <parent-id>`.
89
+ 3. Record the worker in `inflight` as an **expansion** entry — it has no chore to key on, so `choreId` is `null`:
90
+ ```json
91
+ { "kind": "expand", "choreId": null, "parentId": "<parent-id>", "title": "<parent title>", "agentId": "<agent-id>", "logLine": 1 }
92
+ ```
93
+ That entry is what keeps it in the wait set and makes its completion attributable to the parent.
94
+ 4. The worker reports the returned mapping — `code`, `verify`, `review`, `document`, `featurePrReview` — and closes nothing. It emits **no** `---REPORT---` block and owns no bead, so there is nothing to parse and no close to confirm.
95
+ 5. Its completion means the parent now has a `stage:*` chain: the event loop's next `bd ready -l execution:afk` pass picks up the `stage:code` chore (event loop step 7).
96
+
97
+ **Expansion completion contract.** An expansion worker is dispatched like a stage worker but is not one: no chore claim, no `---REPORT---`, no leaf-bead close. Handle its completion with the expansion branch in event-loop step 3, which confirms the chain exists (`bd children <parent-id> --json | grep -c '"stage:'` prints a non-zero count) and dispatches the ready `stage:code` chore. If the parent still has no `stage:*` children the expansion failed: surface the worker's output in chat, **never re-run `create-chores.mjs`** (it is not idempotent — a second run duplicates the chain), and record the parent for the shutdown summary. Either way, create nothing and close nothing.
98
+
99
+ **Never expand an existing bead by running `create-task`** (or any other command that creates a bead). `create-task` creates a bead first and expands second, so running it for an existing bead leaves a **second parent** beside the original, which stays chore-less and never gets dispatched. `create-chores.mjs` expands a bead that already exists; it never creates parents.
100
+
101
+ ---
102
+
103
+ ## Dispatching a stage chore
104
+
105
+ Chores already exist and their deps already encode the order, so dispatch is claim-and-spawn — claim the ready chore (`bd update <chore-id> --claim`) and skip to the prompt.
106
+
107
+ Load the universal stage runner prompt from the `run-pipeline-stage` skill's `prompts/stage-runner.md`, fill in all placeholders (including `<stage>` from the bead label, parent task description from `bd show <parent-id>`, prior SUMMARY/FILES_CHANGED from the last REPORT, chore bead ID, log path `.agent-cortex/ralph/ralph-<parent-id>.log`), and spawn a subagent in **background** mode using the spawning mechanism described in the wake section, running from the feature worktree. Stage-specific policy comes from that skill's `playbooks/<stage>.md`. The prompt's lifecycle, remediation, and REPORT sections are the worker's contract — pass them through verbatim, never restate or trim them.
80
108
 
81
109
  Add the entry to `inflight` in `state.json`:
82
110
  ```json
83
- { "choreId": "<chore-id>", "parentId": "<parent-id>", "title": "<parent title>", "agentId": "<agent-id>", "logLine": 1 }
111
+ { "kind": "stage", "choreId": "<chore-id>", "parentId": "<parent-id>", "title": "<parent title>", "agentId": "<agent-id>", "logLine": 1 }
84
112
  ```
85
113
 
86
114
  ---
87
115
 
88
116
  ## State Files
89
117
 
90
- Ralph uses two kinds of file:
118
+ All status is read from beads — Ralph renders nothing to disk:
91
119
 
92
- - **`.agent-cortex/ralph/progress.md`** — human-readable output generated by the script. **Never hand-edit this file.** Regenerate it by running:
93
- ```bash
94
- # workspace must be the absolute path you cd'd into — never . or $(pwd)
95
- workspace="/absolute/path/to/worktree"
96
- pnpm --prefix skills/workflow/run-pipeline-stage/scripts exec tsx generate-progress.ts --workspace "$workspace" > "$workspace/.agent-cortex/ralph/progress.md"
97
- ```
120
+ ```bash
121
+ bd list --parent <parent-id> # every chore for a feature, with its state
122
+ bd ready -l execution:afk # the next dispatchable work
123
+ bd show <id> # full detail, including the worker's notes
124
+ ```
125
+
126
+ Report status in chat from those commands. The only files Ralph owns are:
127
+
128
+ - **`.agent-cortex/ralph/state.json`** — runtime bookkeeping only (worker-ID→bead mapping plus the wake loop's own handle).
98
129
  - **`.agent-cortex/ralph/ralph-*.log`** — per-parent log files written by subagents (e.g. `.agent-cortex/ralph/ralph-abc-123.log`). Keyed by **parent** bead ID so all chore stages for a feature share one log.
99
130
 
100
131
  All orchestration state is derived from beads:
@@ -102,79 +133,80 @@ All orchestration state is derived from beads:
102
133
  ```json
103
134
  {
104
135
  "inflight": [
105
- { "choreId": "xyz-456", "parentId": "abc-123", "title": "Add auth", "agentId": "agent-xyz-456", "logLine": 4 },
106
- { "choreId": "def-789", "parentId": "ghi-101", "title": "Fix cache", "agentId": "agent-def-789", "logLine": 7 }
136
+ { "kind": "stage", "choreId": "xyz-456", "parentId": "abc-123", "title": "Add auth", "agentId": "agent-xyz-456", "logLine": 4 },
137
+ { "kind": "stage", "choreId": "def-789", "parentId": "ghi-101", "title": "Fix cache", "agentId": "agent-def-789", "logLine": 7 },
138
+ { "kind": "expand", "choreId": null, "parentId": "jkl-202", "title": "Expand billing", "agentId": "agent-jkl-202", "logLine": 1 }
107
139
  ]
108
140
  }
109
141
  ```
110
142
 
143
+ - **inflight[].kind**: `"stage"` for a dispatched stage chore (the only shape that carries a `choreId`), `"decompose"` for a feature-decomposition worker and `"expand"` for an expansion worker (both no chore — `choreId` is `null`). Every dispatched agent has an entry; anything missing from `inflight` is invisible to the wait set and to the HITL-pause check.
144
+ - **inflight[].agentId**: the worker id the spawn call returned — the key every completion is correlated to its bead against, and the identifier the wake section's read/wait path takes (see that section).
111
145
  - **inflight[].choreId**: the chore bead currently being worked by the subagent.
112
146
  - **inflight[].parentId**: the parent feature task bead. Log file is `.agent-cortex/ralph/ralph-<parentId>.log`.
113
147
  - **inflight[].logLine**: the next line number to read from the parent's log file (1-based; start at 1). Updated after every poll.
114
148
  - **Loop counts are not stored here** — derive them from beads:
115
- - TDD loop count = number of `stage:test-writing` chore children of `<parentId>` (including the current one)
116
- - Fix round count = number of `stage:fixing` chore children of `<parentId>`
149
+ - Fix round count = number of `stage:fix` chore children of `<parentId>` (closed ones count)
117
150
 
118
- Update `.agent-cortex/ralph/state.json` after **every** agent completion or dispatch, then regenerate `.agent-cortex/ralph/progress.md`.
151
+ Update `.agent-cortex/ralph/state.json` after **every** agent completion or dispatch.
119
152
 
120
153
  ---
121
154
 
122
- {{SECTION:polling}}
155
+ {{SECTION:wake}}
123
156
 
124
157
  ---
125
158
 
126
159
  ## Event loop
127
160
 
128
- After initialization, Ralph waits for background agents to complete. Completion notifications are delivered by the mechanism documented in the polling section — PI blocks with `wait_for_agents` until a worker completes and its result is returned inline; Claude is event-driven (you are re-invoked automatically when a worker completes, with its result delivered inline). On each completion notification:
161
+ After initialization, Ralph waits for background agents to complete. Completions arrive through the mechanism documented in the wake section — and only through that mechanism. On each completion notification:
129
162
 
130
163
  ### If a background agent completed
131
164
 
132
- 1. **Flush** that bead's log using the log-polling procedure in the polling section to pick up any final lines for the chat summary (PI: flush new log lines as part of handling the `wait_for_agents` result; Claude: nothing to flush — the result is delivered with the wake-up).
133
- 2. **Read** the completed agent's full output (PI: the result arrives in the `wait_for_agents` response, with `read_agent` as a fallback for a specific result; Claude: the result was delivered inline).
134
- 3. **Re-read** `.agent-cortex/ralph/state.json` to identify the chore bead and parent for that agent ID.
165
+ 1. **Flush** that bead's log using the procedure in the wake section to pick up any final lines for the chat summary (a mechanism that delivers the log with the completion needs no flush).
166
+ 2. **Read** the completed agent's full output the way the wake section describes.
167
+ 3. **Re-read** `.agent-cortex/ralph/state.json` to identify the entry for that agent ID, then branch on its `kind`:
168
+ - **`kind: "expand"` — expansion completion branch.** The worker claimed no chore, emits no `---REPORT---`, and owns no bead to confirm, so steps 4-6 **do not apply**: remove the entry from `inflight`, confirm the parent now has `stage:*` chore children (`bd children <parent-id> --json | grep -c '"stage:'`) and surface the reported mapping in chat, then go straight to step 7 — the new `stage:code` chore is ready to dispatch. If the parent still has no `stage:*` children the expansion failed: surface the worker's output, do **not** re-run `create-chores.mjs` (not idempotent), record the parent for the shutdown summary, remove the entry, and continue at step 7. Never create or close a bead for an expansion.
169
+ - **`kind: "decompose"` — decomposition completion branch.** Same shape as expansion: no chore, no `---REPORT---`, so steps 4-6 **do not apply**: remove the entry from `inflight`, confirm the feature now has children (`bd children <feature-id> --json` returns a non-empty list) and surface the created IDs in chat, then go straight to step 7. Nothing is dispatchable for that feature until a human closes the planning bead, so finding no ready work for it is the correct outcome — do **not** re-dispatch the decomposition (the bead creation it ran is not idempotent). If the feature still has no children, the worker failed: surface its output, record it for the shutdown summary, remove the entry, and continue at step 7. Never create or close a bead here.
170
+ - **`kind: "stage"`** — a stage worker: continue with steps 4-6.
135
171
  4. **Parse** the agent's `---REPORT---` block (see report format in the `run-pipeline-stage` skill).
136
- 5. **Close** the completed chore bead: `bd close <chore-id>`.
137
- 6. **Advance** the parent using the dispatch rules in the `run-pipeline-stage` skill:
138
- - **Success paths** (code → verify, verify SUCCESS → review, review SUCCESS → document): create the next chore bead and dispatch it immediately (see _Creating and dispatching a stage chore_ above). Update the inflight entry with the new choreId/agentId, reset logLine to 1.
172
+ 5. **Confirm** the worker closed its own leaf execution bead: `bd show <chore-id>` should read `closed`. If it is still open the worker died mid-stage — read its notes and re-dispatch. Never close it yourself.
173
+ 6. **Advance** the parent using the routing guidance in the `run-pipeline-stage` skill:
174
+ - **Success paths** (code → verify, verify SUCCESS → review, review SUCCESS → document): create nothing — closing the chore already unblocked the next stage of the pre-created chain. Point the parent's inflight entry at that newly ready `stage:*` chore and dispatch it (see _Dispatching a stage chore_ above), resetting logLine to 1.
139
175
  - **Documenting → done**: close the parent feature bead (`bd close <parent-id>`), remove it from inflight, open/update the feature PR immediately (agent-branch → feature branch), report the PR URL in chat, then update the HITL PR gate bead with the PR URL.
140
- - **Failure paths** (verify BLOCKED, review CHANGES_REQUESTED): check loop cap (see below), then create a feedback bead per the _Feedback Beads_ section in `run-pipeline-stage`. Do **not** dispatch immediately — the feedback bead appears in `bd ready` and is picked up in step 7. Remove the inflight entry for this chore; the feedback bead will create a new entry when dispatched.
141
- 7. **Check for newly ready beads**: run `bd ready`. For each bead not yet tracked:
142
- - **Chore bead with `stage:*` label** (a feedback bead): find its parent via `bd show <chore-id>` (follow the `parent-child` dep). Check loop cap (see below). If under cap: dispatch it via _Creating and dispatching a stage chore_. If at cap: block it (`bd update <chore-id> --status blocked --notes "<cap> cap reached"`) and record for shutdown.
143
- - **Task bead, AFK, in-flight count < 5, no open feature PR HITL gate**: claim the parent, create its first code chore, dispatch it.
144
- - **Task bead, AFK, in-flight count at 5**: hold in memory as Waiting.
145
- - **HITL task bead**: note for **Pending Human Action** shutdown summary.
146
- - **NEEDS-REFINEMENT bead**: note for **Needs Refinement** shutdown summary.
147
- When a parent is removed from `inflight` (completed or failed), immediately promote the first Waiting AFK parent.
148
- 8. **If no tasks remain in-flight** and `bd ready` returns no chore beads with `stage:*` labels and no AFK task beads:
149
- - If HITL gate beads are pending (`bd list -l lifecycle:feature-pr -l implementation-type:hitl` or `bd list -l awaiting-epic-pr-merge` returns results), proceed to **HITL Pause** (see below).
176
+ - **Failure paths** (`OUTCOME: BLOCKED` from any stage): create nothing. The worker already closed its failed chore and built its own remediation — a `stage:fix` chore plus a fresh instance of the failed stage blocked on it. Run the cap backstop (see below); if the parent is at `maxFixRounds`, block the parent instead and record it for shutdown. Remove the inflight entry for this chore; the worker's beads appear in `bd ready` and are picked up in step 7.
177
+ 7. **Check for newly ready beads**: run `bd ready -l execution:afk`. For each bead not yet tracked:
178
+ - **Chore bead with `stage:*` label** (a worker-built remediation chore or a pre-created stage): find its parent via `bd show <chore-id>` (follow the `parent-child` dep). Run the cap backstop (see below). If under cap: dispatch it via _Dispatching a stage chore_. If at cap: block the parent (`bd update <parent-id> --status blocked --append-notes "<cap> reached"`) and record it for shutdown — create nothing.
179
+ - **Childless `feature` bead, in-flight count < 5, no pending human action**: dispatch a decomposition worker (see _Feature decomposition_ above). Check `pendingHumanAction` with `node skills/workflow/ralph/scripts/pending-gates.mjs` — an unblocked `lifecycle:feature-pr` gate means a feature is awaiting a human merge, so hold new parent features. Gates still blocked behind their own pipeline are parked and do not count.
180
+ - **Task bead with no `stage:*` chore children, in-flight count < 5, no pending human action**: claim the parent and dispatch an expansion worker (see _Expanding a chore-less task bead_ above) instead of a stage; otherwise dispatch its first ready chore. Check `pendingHumanAction` the same way as the row above.
181
+ - **Any other `execution:afk` bead, in-flight count at 5**: hold in memory as Waiting.
182
+ When a parent is removed from `inflight` (completed or failed), immediately promote the first Waiting parent.
183
+ `execution:hitl` beads are absent from this query by construction, so nothing needs filtering out here.
184
+ 8. **If nothing remains in flight** — `inflight` holds no stage, decomposition or expansion workers, and `bd ready -l execution:afk` returns nothing (no stage chore, no childless feature to decompose, and no ready, claimable chore-less task bead awaiting expansion — a queued `execution:afk` bead behind an open `lifecycle:feature-pr` HITL gate is not claimable, so it keeps ralph paused rather than awake):
185
+ - If `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 — REFERENCE.md, _Gate predicate_), proceed to **HITL Pause** (see below).
150
186
  - Otherwise, proceed to **Shutdown** (see below).
151
187
 
152
- ### Loop cap check
188
+ ### Cap backstop (read-only)
153
189
 
154
- Before creating a fix feedback bead, read `maxFixRounds` from `skills/planning/create-task/pipeline.json` and count existing fix chore children:
190
+ Ralph never builds remediation and never closes a leaf bead — the worker that failed a stage did both (see _Remediation Children_ in the `run-pipeline-stage` skill). Ralph only guards retry blow-up, and only reads:
155
191
 
156
192
  ```bash
157
- fix_rounds=$(bd children <parent-id> | grep 'stage:fix' | wc -l)
193
+ fix_rounds=$(bd children <parent-id> --json | grep -c '"stage:fix"')
158
194
  ```
159
195
 
160
- - If `fix_rounds ≥ maxFixRounds` → do **not** create feedback bead; block the parent instead.
161
-
162
- Block command: `bd update <parent-id> --status blocked --notes "<cap> cap reached"`. Record for shutdown summary.
196
+ Read `maxFixRounds` from the `create-task` skill's `pipeline.json`. If `fix_rounds >= maxFixRounds`, create nothing and block the parent: `bd update <parent-id> --status blocked --append-notes "[<ISO-timestamp>] max fix rounds reached (<fix_rounds>/<maxFixRounds>)"`. Record it for the shutdown summary.
163
197
 
164
198
  ---
165
199
 
166
200
  ## HITL Pause
167
201
 
168
- Proceed here when no chore beads are in-flight, no `stage:*` chore beads are ready, and HITL gate beads are pending (open `lifecycle:feature-pr` beads or epics tagged `awaiting-epic-pr-merge`). Ralph stops rather than burning requests on idle polls.
202
+ Proceed here when no agent work is in flight (no stage, decomposition or expansion workers in `inflight`), no work is dispatchable (nothing returned by `bd ready -l execution:afk` — no `stage:*` chore, no childless feature to decompose, no ready, claimable chore-less `execution:afk` task bead awaiting expansion — claimability is part of dispatchability: an `execution:afk` bead behind an open `lifecycle:feature-pr` HITL gate cannot be claimed, so it does not keep ralph awake), and `pending-gates.mjs` reports a non-empty `pendingHumanAction` — an **unblocked** `lifecycle:feature-pr` gate (a feature genuinely awaiting human merge) or an epic tagged `awaiting-epic-pr-merge`. Gates still parked behind their own pipeline do not count (REFERENCE.md, _Gate predicate_). Ralph stops rather than burning requests on idle polls.
169
203
 
170
- 1. Regenerate `.agent-cortex/ralph/progress.md` one final time — do not delete it.
171
- 2. For each **multi-feature** epic whose feature beads are all closed but not yet tagged `awaiting-epic-pr-merge`, open/update an epic PR to main, then tag the epic `awaiting-epic-pr-merge`. Skip single-feature epics — their feature branch PRs already target `main` directly.
172
- 3. Run `bd dolt push`.
173
- 4. Collect pending HITL gate beads and their PR URLs:
174
- - Run `bd list -l lifecycle:feature-pr -l implementation-type:hitl`
175
- - Run `bd list -l awaiting-epic-pr-merge`
176
- - For each bead, run `bd show <id>` to retrieve the PR URL from bead notes.
177
- 5. Output the **Pending Human Action** summary:
204
+ 1. For each **multi-feature** epic whose feature beads are all closed but not yet tagged `awaiting-epic-pr-merge`, open/update an epic PR to main, then tag the epic `awaiting-epic-pr-merge`. Skip single-feature epics — their feature branch PRs already target `main` directly.
205
+ 2. Run `bd dolt push` and gate it on the exit status: non-zero, retry once, then stop and report the command, exit code and stderr as a sync blocker — no Pending Human Action table.
206
+ 3. Collect the table rows from the script's `pendingHumanAction` list:
207
+ - Run `node skills/workflow/ralph/scripts/pending-gates.mjs`
208
+ - For each entry, run `bd show <id>` to retrieve the PR URL from bead notes. `kind: "feature-pr"` rows read "review and merge the feature PR"; `kind: "epic-pr"` rows read "review and merge the epic PR into main".
209
+ 4. Output the **Pending Human Action** summary:
178
210
  ```
179
211
  ⏸️ Ralph is paused — human action required before work can continue.
180
212
 
@@ -186,21 +218,21 @@ Proceed here when no chore beads are in-flight, no `stage:*` chore beads are rea
186
218
 
187
219
  When you've completed the above actions, prompt me to continue.
188
220
  ```
189
- 6. **Stop completely.** Stop the polling mechanism documented in the polling section (PI and Claude: nothing to stop — there is no timer). Do **not** restart or schedule anything. Do **not** start any background processes. Do **not** check bead status again. Do **not** continue the event loop. Output **nothing further** after the summary above. Ralph is now fully idle — it must not act again until the user explicitly re-prompts.
221
+ 5. **Stop completely.** Stop the wake mechanism exactly as the wake section describes — whatever killing it takes, and nothing more. Do **not** restart or schedule anything. Do **not** start any background processes. Do **not** check bead status again. Do **not** continue the event loop. Output **nothing further** after the summary above. Ralph is now fully idle — it must not act again until the user explicitly re-prompts.
190
222
 
191
223
  ---
192
224
 
193
225
  ## Shutdown
194
226
 
195
- When `bd list --status=in_progress --type=chore` returns no results AND `bd ready` returns no chore beads with `stage:*` labels:
227
+ When nothing is in flight AND nothing is dispatchable — `inflight` holds no entries, and `bd ready -l execution:afk` returns nothing (no `stage:*` chore, no childless feature to decompose, no ready, claimable chore-less task bead awaiting expansion — see _The in-flight invariant_ in the `ralph` skill's REFERENCE.md):
196
228
 
197
- 1. Regenerate `.agent-cortex/ralph/progress.md` one final time — do not delete it.
198
- 2. For each **multi-feature** epic whose feature beads are complete, open/update a PR from `epic/<epic-id>` into `main`, then tag the epic `awaiting-epic-pr-merge`. Skip single-feature epics — no epic branch exists.
199
- 3. Run:
229
+ 1. For each **multi-feature** epic whose feature beads are complete, open/update a PR from `epic/<epic-id>` into `main`, then tag the epic `awaiting-epic-pr-merge`. Skip single-feature epics — no epic branch exists.
230
+ 2. Run:
200
231
  ```bash
201
232
  bd dolt push
202
233
  ```
203
- 4. If any HITL beads were noted during the session, output:
234
+ **Gate on the exit status.** Non-zero: retry once, then stop and report the command, exit code and stderr as a sync blocker — no completion summary, no "All beads complete.", and the remaining shutdown steps are not run.
235
+ 3. If any HITL beads were noted during the session, output:
204
236
  ```
205
237
  All agent work is complete. The following steps require human action before work can continue:
206
238
 
@@ -211,7 +243,7 @@ When `bd list --status=in_progress --type=chore` returns no results AND `bd read
211
243
 
212
244
  Run `bd show <id>` for full details on each step.
213
245
  ```
214
- 5. If any needs-refinement beads were noted during the session, output:
246
+ 4. If any needs-refinement beads were noted during the session, output:
215
247
  ```
216
248
  The following beads need refinement before they can be implemented:
217
249
 
@@ -222,7 +254,7 @@ The following beads need refinement before they can be implemented:
222
254
 
223
255
  Remove the `needs-refinement` label once a bead is ready to implement.
224
256
  ```
225
- 6. If any parents were blocked due to cap exhaustion, output:
257
+ 5. If any parents were blocked due to cap exhaustion, output:
226
258
  ```
227
259
  The following features were blocked after reaching their retry cap and need human intervention:
228
260
 
@@ -234,8 +266,8 @@ The following features were blocked after reaching their retry cap and need huma
234
266
 
235
267
  Run `bd show <id>` for full details on each.
236
268
  ```
237
- 7. If any epics are tagged `awaiting-epic-pr-merge`, output a **Pending Epic Review** table (epic bead ID, branch, PR URL) and stop.
238
- 8. If no HITL, needs-refinement, cap-blocked, or pending epic-review beads remain, output:
269
+ 6. If any epics are tagged `awaiting-epic-pr-merge`, output a **Pending Epic Review** table (epic bead ID, branch, PR URL) and stop.
270
+ 7. If no HITL, needs-refinement, cap-blocked, or pending epic-review beads remain, output:
239
271
  ```
240
272
  All beads complete.
241
273
  ```
@@ -250,8 +282,13 @@ All beads complete.
250
282
  - **ALWAYS use the documented spawning mechanism to spawn subagents** — never use bash, never run stages inline, never use any other tool. This is your only spawning mechanism.
251
283
  - **Always** derive orchestration state from beads — do not store loop counts in state.json.
252
284
  - **Subagents can fetch their own context** — they will run `bd prime` if they need project-level state. Do not inject `bd prime` output into subagent prompts.
253
- - **Max 5** tasks in-flight at once (counted by parent features, not individual chore beads).
254
- - **Max fix rounds** per parent (read `maxFixRounds` from `skills/planning/create-task/pipeline.json`; count of `stage:fix` chore children); block the parent if exceeded.
285
+ - **Max 5** tasks in-flight at once (counted by parent features, not individual chore beads) — a parent counts while any of its workers, stage, decomposition or expansion, sits in `inflight`.
286
+ - **Never** close a leaf execution bead and **never** create a `stage:fix`/feedback bead — the worker owns its bead's lifecycle and builds its own remediation chain.
287
+ - **Never** create a stage chore — `create-chores.mjs` pre-creates the chain; dispatch what `bd ready -l execution:afk` returns.
288
+ - **Never** re-dispatch a decomposition or an expansion, and never narrow the dispatch query to "chores with `stage:*`": an `execution:afk` bead with no stage chores is work waiting, not work that does not exist.
289
+ - **Always** record every dispatch in `inflight`, stage workers as `kind: "stage"`, decomposition workers as `kind: "decompose"` and expansion workers as `kind: "expand"` with `choreId: null` — an untracked worker is never waited on, and its absence can make HITL Pause or Shutdown fire mid-decomposition.
290
+ - **Never** run `create-task` for a bead that already exists to give it a pipeline — it creates a **second parent**. Expand with `create-chores.mjs --parent <id>`.
291
+ - **Max fix rounds** per parent is a read-only backstop (read `maxFixRounds` from the `create-task` skill's `pipeline.json`; count `stage:fix` chore children); block the parent at cap and create nothing.
255
292
  - **Always** run feature chores in the feature worktree (`.agent-cortex/worktrees/<parent-id>`), never from repo root.
256
293
  - **Never** auto-merge feature or epic PRs — merge decisions are human-controlled.
257
294
  - **Never** continue past feature completion until PR `feature/<parent-id> -> epic/<epic-id>` is merged and the child HITL PR gate bead is closed by a human.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-cortex:ralph",
3
- "description": "Use when running all pending beads end-to-end: finds the next available beads (dependencies met), runs the full implement → review → fix cycle for each feature in its own worktree, opens and reports PRs immediately, then waits for human merges before continuing.",
4
- "tools": ["Bash", "Read", "Grep", "Glob", "Skill", "Task", "TaskList", "TaskGet", "TaskStop", "SendMessage"],
3
+ "description": "Use when running all pending beads end-to-end: finds the next available beads (dependencies met), advances each one through its pre-created pipeline-stage chores (code → verify → review → document) in its own worktree, opens and reports PRs immediately, then waits for human merges before continuing.",
4
+ "tools": ["Bash", "Read", "Grep", "Glob", "Skill", "Task", "TaskList", "TaskGet", "TaskStop"],
5
5
  "argumentHint": "Run all pending beads"
6
- }
6
+ }
@@ -0,0 +1,46 @@
1
+ ## Wake mechanism (Claude Code — event-driven)
2
+
3
+ **Mechanism: event-driven — the harness re-invokes you automatically when a background worker completes and delivers that worker's result inline, so there is no poll timer, no sleep, and no log flush.**
4
+
5
+ ### Spawn
6
+
7
+ RALPH HAS ONLY ONE WAY TO SPAWN SUBAGENTS: call the **`Task`** tool (not bash, not any other tool).
8
+
9
+ **`Task`** — Spawn a background sub-agent and return a task ID immediately.
10
+ - `prompt` (string, required): Full task prompt for the sub-agent.
11
+ - `cwd` (string, optional): Working directory for the sub-agent (default: current project root). Always set this to the feature worktree path when running stage chores.
12
+ - `model`, `subagent_type` (optional): Overrides for the worker; the Implementer and Reviewer workers keep the default (full reasoning), the Fix worker uses `model: haiku`.
13
+
14
+ The response is a plain task ID string. Store it in memory — you need it to track the worker against its parent bead. Use `TaskList`/`TaskGet` to see which workers are still running and `TaskStop` to cancel one.
15
+
16
+ Rules:
17
+ - NEVER use `bash` to spawn subagents (no `claude`, no `tsx`, no `node` scripts).
18
+ - NEVER try to run subagent work inline yourself — you only orchestrate.
19
+ - ALWAYS use `Task` for every subagent interaction; track running workers with `TaskList`/`TaskGet`.
20
+ - ALWAYS set `cwd` to the feature worktree path when running stage chores.
21
+ - ALWAYS keep the task ID in memory to correlate a completion with its parent bead.
22
+
23
+ ### Completion arrival
24
+
25
+ A completion is **delivered, not observed**: Claude Code re-invokes you automatically when a background worker finishes, with the worker's result inline on the wake-up. **Do not poll and do not `sleep`.** React to completions as they arrive. On each completion, apply the shared handling in the **Event loop** section of agent.md (steps 3–8: correlate the task ID to its entry via `state.json`'s `inflight`, branch on the entry's `kind` — a `stage` entry parses the REPORT and confirms the worker closed its chore, an `expand` entry has no REPORT and no bead to confirm, so confirm the parent now has `stage:*` chores and dispatch its ready `stage:code` — advance the parent, check for newly ready beads, run the shutdown check).
26
+
27
+ ### Id tracking
28
+
29
+ Initialize `.agent-cortex/ralph/state.json` as `{ "inflight": [] }` — there is no timer handle to track.
30
+
31
+ - **inflight[].agentId** — the task ID `Task` returned for that worker; it is the key the delivered completion is correlated to its bead, and the equivalent of `TaskGet`'s identifier when you need to inspect one worker.
32
+ - **inflight[].logLine** — not used on Claude; leave it at `1`. Progress lines (`.agent-cortex/ralph/ralph-<parentId>.log`) are written by the workers themselves and surfaced by the harness with the completion.
33
+
34
+ ### Log flush
35
+
36
+ None. There is **no log tailing on Claude**: the completion is delivered with the result already in hand, so there is nothing to flush and nothing to poll. Produce the shared chat summaries from the delivered result instead.
37
+
38
+ ### Stop
39
+
40
+ Stopping means simply **stop**: there is no poll timer to kill and no wait to cancel, so you do nothing further and the harness wakes you again when the user re-invokes you. Never schedule a replacement wake-up or start a background process.
41
+
42
+ ### Completion constraints
43
+
44
+ - **Always** keep completion tracking active while worker results are outstanding — the harness delivers each completion precisely once; never re-request a result.
45
+ - **Never** poll, **never** `sleep`, **never** start a background timer.
46
+ - **Never** post empty status updates — only surface actual completions.