@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.
- package/CHANGELOG.md +437 -0
- package/README.md +46 -15
- package/agents/README.md +22 -10
- package/agents/plan/agent.md +2 -2
- package/agents/ralph/agent.md +128 -91
- package/agents/ralph/claude/frontmatter.json +3 -3
- package/agents/ralph/claude/wake.md +46 -0
- package/agents/ralph/pi/{polling.md → wake.md} +35 -20
- package/agents/ralph-plan/agent.md +23 -11
- package/bin/agent-cortex.mjs +66 -4
- package/bin/installers/claude.mjs +262 -77
- package/bin/installers/pi.mjs +200 -24
- package/extensions/agent-guardrails/README.md +1 -1
- package/extensions/agent-guardrails/guardrails.ts +1 -1
- package/extensions/agent-guardrails/index.ts +1 -1
- package/extensions/agent-modes/discover.test.ts +2 -2
- package/extensions/output-style/README.md +58 -0
- package/extensions/output-style/index.ts +23 -0
- package/extensions/output-style/output-style.md +43 -0
- package/extensions/output-style/output-style.test.ts +50 -0
- package/extensions/output-style/output-style.ts +32 -0
- package/extensions/output-style/package.json +19 -0
- package/hooks/claude/scripts/notify.mjs +8 -1
- package/lib/cli.mjs +91 -2
- package/package.json +29 -4
- package/scripts/check-changeset.mjs +4 -0
- package/scripts/check-no-sync.mjs +5 -1
- package/scripts/check-skill-frontmatter.mjs +21 -0
- package/scripts/lib/compose-agent.mjs +69 -9
- package/scripts/lib/fs.mjs +10 -2
- package/scripts/lib/migrate.mjs +736 -0
- package/scripts/lib/release-gates.mjs +21 -1
- package/scripts/lib/skill-frontmatter.mjs +152 -0
- package/scripts/lib/skill-links.mjs +52 -0
- package/scripts/lib/verify-worker-tree.mjs +25 -0
- package/scripts/resolve-publish-command.mjs +4 -0
- package/skills/engineering/design-an-interface/SKILL.md +3 -3
- package/skills/engineering/grill-with-docs/SKILL.md +3 -5
- package/skills/engineering/improve-codebase-architecture/SKILL.md +5 -4
- package/skills/engineering/tdd/SKILL.md +5 -7
- package/skills/engineering/technical-direction/SKILL.md +5 -5
- package/skills/planning/classify-bead/REFERENCE.md +3 -3
- package/skills/planning/classify-bead/SKILL.md +14 -9
- package/skills/planning/classify-bead/scripts/classify-bead.mjs +5 -4
- package/skills/planning/create-task/REFERENCE.md +52 -3
- package/skills/planning/create-task/SKILL.md +70 -26
- package/skills/planning/create-task/scripts/{create-chores.ts → create-chores.mjs} +48 -23
- package/skills/planning/flesh-out-idea/REFERENCE.md +116 -0
- package/skills/planning/flesh-out-idea/SKILL.md +146 -0
- package/skills/planning/prd-to-tasks/REFERENCE.md +54 -5
- package/skills/planning/prd-to-tasks/SKILL.md +22 -16
- package/skills/planning/record-idea/FORMAT.md +66 -17
- package/skills/planning/record-idea/SKILL.md +48 -24
- package/skills/planning/request-refactor-plan/SKILL.md +4 -4
- package/skills/planning/spec-to-tickets/SKILL.md +5 -5
- package/skills/planning/write-a-prd/SKILL.md +8 -9
- package/skills/planning/write-a-ticket/SKILL.md +4 -6
- package/skills/productivity/bd-tool/SKILL.md +15 -10
- package/skills/productivity/grill-me/SKILL.md +5 -0
- package/skills/productivity/init-beads/SKILL.md +3 -3
- package/skills/productivity/migration/REFERENCE.md +227 -0
- package/skills/productivity/migration/SKILL.md +188 -0
- package/skills/productivity/validate-agent-dir/scripts/{validate-agent-dir.ts → validate-agent-dir.mjs} +49 -28
- package/skills/productivity/write-a-skill/SKILL.md +5 -5
- package/skills/review/maintain-agent-docs/SKILL.md +5 -7
- package/skills/review/refactor-skill/SKILL.md +4 -3
- package/skills/review/review-security/SKILL.md +3 -5
- package/skills/style/style-code/SKILL.md +5 -10
- package/skills/style/style-comms/SKILL.md +5 -7
- package/skills/style/style-documentation/SKILL.md +5 -6
- package/skills/style/style-tests/SKILL.md +5 -7
- package/skills/workflow/git-workflow/SKILL.md +28 -4
- package/skills/workflow/hitl-collab/SKILL.md +4 -6
- package/skills/workflow/plan/SKILL.md +41 -30
- package/skills/workflow/ralph/REFERENCE.md +209 -55
- package/skills/workflow/ralph/SKILL.md +89 -50
- package/skills/workflow/ralph/scripts/pending-gates.mjs +134 -0
- package/skills/workflow/run-pipeline-stage/SKILL.md +72 -71
- package/skills/workflow/run-pipeline-stage/playbooks/code.md +11 -0
- package/skills/workflow/run-pipeline-stage/playbooks/document.md +12 -0
- package/skills/workflow/run-pipeline-stage/playbooks/fix.md +12 -0
- package/skills/workflow/run-pipeline-stage/playbooks/review.md +11 -0
- package/skills/workflow/run-pipeline-stage/playbooks/verify.md +13 -0
- package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +73 -1
- package/token-map.README.md +9 -4
- package/token-map.json +13 -6
- package/.agents/skills/style-versioning/SKILL.md +0 -172
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.github/workflows/ci.yml +0 -302
- package/.junie/guidelines.md +0 -87
- package/.junie/mcp/mcp.json +0 -10
- package/AGENTS.md +0 -151
- package/agents/ralph/claude/polling.md +0 -31
- package/agents-native/ralph.md +0 -193
- package/docs/claude-hooks.md +0 -128
- package/docs/commit-signing.md +0 -231
- package/docs/ideas/auto-model-selection.md +0 -75
- package/docs/ideas/ban-content-assertion-tests.md +0 -75
- package/docs/ideas/bead-progress-notes-for-session-resumption.md +0 -75
- package/docs/ideas/classify-beads-via-deterministic-script-with-agent-fallback.md +0 -70
- package/docs/ideas/ctx-alias-version-and-update-commands.md +0 -65
- package/docs/ideas/ctx-feedback-command-for-capturing-ideas-from-any-machine.md +0 -67
- package/docs/ideas/dedicated-review-tests-skill.md +0 -71
- package/docs/ideas/deployment-beads-for-post-merge-pipelines.md +0 -36
- package/docs/ideas/design-and-delivery-as-separate-bead-trees/design-and-delivery-as-separate-bead-trees.md +0 -99
- package/docs/ideas/enable-signed-commit-enforcement-changesets-bot-commits-must-be-signed.md +0 -42
- package/docs/ideas/extension-manifests.md +0 -121
- package/docs/ideas/improve-pi-system-prompt.md +0 -37
- package/docs/ideas/map-every-cortex-tool-to-a-real-pi-equivalent.md +0 -95
- package/docs/ideas/model-selector.md +0 -40
- package/docs/ideas/pi-task-memory.md +0 -34
- package/docs/ideas/qa-extension.md +0 -43
- package/docs/ideas/record-idea-implementation-questions.md +0 -68
- package/docs/ideas/record-ideas-as-beads.md +0 -115
- package/docs/ideas/self-flushing-session.md +0 -72
- package/docs/ideas/state-in-beads-not-md.md +0 -69
- package/docs/ideas/subagent-visibility.md +0 -72
- package/docs/ideas/task-session-context.local.md +0 -95
- package/docs/ideas/task-session-context.md +0 -89
- package/docs/ideas/test-data-creation-helpers.md +0 -92
- package/docs/ideas/test-planning-stage-bead-in-feature-planning.md +0 -68
- package/docs/ideas/unified-ci-pipeline.md +0 -28
- package/docs/ideas/unify-the-ticket-and-task-decomposition-workflows.md +0 -71
- package/docs/ideas/worktree-housekeeping-for-closed-beads.md +0 -39
- package/docs/inspirations.md +0 -33
- package/docs/research/disable-model-invocation.md +0 -82
- package/docs/research/gas-city-research.md +0 -256
- package/docs/research/skill-design-research.md +0 -286
- package/docs/research/skill-improvements-analysis.md +0 -117
- package/docs/research/skill-patterns-research.md +0 -24
- package/docs/skills/skill-anatomy.md +0 -197
- package/docs/technical-direction/harness-config.md +0 -177
- package/docs/technical-direction/migration-execution-labels.md +0 -177
- package/docs/user-preferences.md +0 -17
- package/extensions/agent-guardrails/tsconfig.json +0 -12
- package/extensions/agent-modes/tsconfig.json +0 -12
- package/extensions/session-start/tsconfig.json +0 -12
- package/extensions/skill-stats/pnpm-lock.yaml +0 -329
- package/extensions/skill-stats/tsconfig.json +0 -12
- package/extensions/subagent/agents/planner.md +0 -37
- package/extensions/subagent/agents/reviewer.md +0 -35
- package/extensions/subagent/agents/scout.md +0 -50
- package/extensions/subagent/agents/worker.md +0 -24
- package/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/extensions/subagent/prompts/implement.md +0 -10
- package/extensions/subagent/prompts/scout-and-plan.md +0 -9
- package/extensions/subagent/tsconfig.json +0 -12
- package/pi/keybindings.json +0 -3
- package/pi/settings.json +0 -34
- package/pnpm-workspace.yaml +0 -14
- package/skills/planning/create-task/scripts/package.json +0 -14
- package/skills/planning/create-task/scripts/pnpm-lock.yaml +0 -342
- package/skills/planning/create-task/scripts/tsconfig.json +0 -12
- package/skills/planning/record-idea/scripts/new-idea.sh +0 -89
- package/skills/productivity/validate-agent-dir/scripts/package.json +0 -15
- package/skills/productivity/validate-agent-dir/scripts/pnpm-lock.yaml +0 -329
- package/skills/productivity/validate-agent-dir/scripts/pnpm-workspace.yaml +0 -2
- package/skills/productivity/validate-agent-dir/scripts/tsconfig.json +0 -19
- package/skills/productivity/validate-agent-dir/scripts/validate-agent-dir.test.ts +0 -317
- package/skills/workflow/run-pipeline-stage/REFERENCE.md +0 -22
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +0 -682
- package/skills/workflow/run-pipeline-stage/scripts/generate-progress.ts +0 -588
- package/skills/workflow/run-pipeline-stage/scripts/package.json +0 -15
- package/skills/workflow/run-pipeline-stage/scripts/pnpm-lock.yaml +0 -342
- package/skills/workflow/run-pipeline-stage/scripts/pnpm-workspace.yaml +0 -2
- package/skills/workflow/run-pipeline-stage/scripts/tsconfig.json +0 -12
- package/test/classify-bead.test.mjs +0 -277
- package/test/claude-installer.test.mjs +0 -308
- package/test/cli.test.mjs +0 -314
- package/test/create-chores.test.mjs +0 -85
- package/test/fake-bd.test.mjs +0 -72
- package/test/fs.test.mjs +0 -76
- package/test/helpers/fake-bd.mjs +0 -87
- package/test/helpers/fake-claude.mjs +0 -152
- package/test/helpers/fake-pi.mjs +0 -132
- package/test/installer.test.mjs +0 -664
- package/test/notify-hook.test.mjs +0 -63
- package/test/pi-installer.test.mjs +0 -785
- package/test/pi-register.test.mjs +0 -342
- package/test/pi-sweep.test.mjs +0 -619
- package/test/release-gates.test.mjs +0 -190
- package/test/verify-worker-tree.test.mjs +0 -120
|
@@ -4,8 +4,141 @@ Detailed procedures for the ralph orchestration workflow. See [SKILL.md](./SKILL
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## The in-flight invariant
|
|
8
|
+
|
|
9
|
+
Every ralph control-flow predicate — *is any agent work in flight?*, *is there work?*, *is there
|
|
10
|
+
room to dispatch?*, *may we pause?*, *may we shut down?* — is answered from `state.json`'s
|
|
11
|
+
`inflight` list (entries carry `kind: "stage"`, `kind: "decompose"` or `kind: "expand"`) plus
|
|
12
|
+
`bd ready -l execution:afk`. **Never** from a chore-type `bd` query, and never from "was a chore
|
|
13
|
+
dispatched?".
|
|
14
|
+
|
|
15
|
+
| Question | Derive it from | Never from |
|
|
16
|
+
|----------|----------------|------------|
|
|
17
|
+
| Is any agent work in flight? | `inflight` in `.agent-cortex/ralph/state.json` — stage, decomposition **and** expansion entries | `bd list -t chore`, `bd ready -t chore`, or any "were chores dispatched?" test |
|
|
18
|
+
| Is anything dispatchable? | `bd ready -l execution:afk`: a `stage:*` chore, a childless `execution:afk` `feature` bead to decompose, **or** a ready, claimable chore-less `execution:afk` task bead awaiting expansion | A chore listing alone — a ready, claimable childless feature or chore-less task is work waiting, not idle |
|
|
19
|
+
| Is there room under the 5-feature cap? | Parent count in `inflight` | A count of chore beads |
|
|
20
|
+
| May ralph pause or shut down? | `inflight` empty **and** nothing dispatchable (per the row above) | "No stage worker is running" |
|
|
21
|
+
|
|
22
|
+
**`execution:afk` is the one dispatch predicate.** It answers *whose work is this* for features,
|
|
23
|
+
tasks and chores alike, and the bead graph answers *when*. Ralph therefore never narrows the query
|
|
24
|
+
— "chores with `stage:*`" would report a ready childless feature or an unexpanded task as idle
|
|
25
|
+
while both are work waiting for a worker.
|
|
26
|
+
|
|
27
|
+
**Dispatchable means ready *and* claimable.** `bd ready -l execution:afk` decides ready; pending human action
|
|
28
|
+
decides claimable: while `pending-gates.mjs` reports an unblocked `lifecycle:feature-pr` gate, ralph
|
|
29
|
+
schedules no new parent features (_Feature PR gate_, step 6), so a queued unexpanded `execution:afk` bead in
|
|
30
|
+
that state is paused work, not dispatchable work. Scoping the predicate both ways is what makes HITL Pause
|
|
31
|
+
reachable in the canonical post-PR state — gate open, unexpanded `execution:afk` beads queued, `inflight`
|
|
32
|
+
empty, no ready `stage:*` chore — instead of re-arming a PI
|
|
33
|
+
wait over an empty agent set forever on an idle poll.
|
|
34
|
+
|
|
35
|
+
**Why:** an expansion or decomposition worker claims no chore. A chore-only predicate therefore
|
|
36
|
+
reports "nothing in flight" while an agent is running, which makes ralph pause or shut down
|
|
37
|
+
mid-expansion and leaves the parent's freshly created `stage:*` chain undispatched. The only
|
|
38
|
+
legitimate chore-type control-flow predicate in ralph is the retry counter in _Cap Backstop_
|
|
39
|
+
(`stage:fix` children): it counts remediation history rather than in-flight work, so it may gate a
|
|
40
|
+
dispatch decision but it must never answer *is anything in flight?*. Every other chore-type `bd`
|
|
41
|
+
query used as a control-flow predicate is a bug. Structural checks that ask nothing more than
|
|
42
|
+
*what does this bead already have?* — the _Expansion Guard_'s `grep -c '"stage:'`, the _Cap
|
|
43
|
+
Backstop_'s `stage:fix` count, the _Feature Decomposition_'s child count — are not predicates and
|
|
44
|
+
are fine.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Expansion Guard
|
|
49
|
+
|
|
50
|
+
Stage chores are pre-created, never created on demand. `create-chores.mjs` (in `skills/planning/create-task/`) reads `pipeline.json` and creates the whole chain in one shot — `code` → `verify` → `review` → `document`, plus the `featurePrReview` HITL gate — with `blocks` deps that encode the order, and with the parent's priority and inherited labels. Ralph's dispatch is therefore always "claim what `bd ready -l execution:afk` returns".
|
|
51
|
+
|
|
52
|
+
A ready `execution:afk` task bead with **no** `stage:*` chore children has nothing to dispatch. Expand it, then dispatch the resulting `stage:code` chore:
|
|
53
|
+
|
|
54
|
+
1. **Confirm it is chore-less** — a bead that already has stage chores is never expanded again:
|
|
55
|
+
```bash
|
|
56
|
+
bd children <parent-id> --json | grep -c '"stage:'
|
|
57
|
+
```
|
|
58
|
+
Expect `0` printed. `grep -c` exits `1` when it counts zero matches, so add `|| true` when the
|
|
59
|
+
check runs under `set -e` or inside an `&&` chain — the printed count is the answer, not the exit
|
|
60
|
+
status.
|
|
61
|
+
2. **Dispatch an expansion worker** in the feature worktree (`.agent-cortex/worktrees/<parent-id>`) whose whole job is to run the pre-creator against the existing bead and report the JSON it printed:
|
|
62
|
+
```bash
|
|
63
|
+
node <create-task-scripts>/create-chores.mjs \
|
|
64
|
+
--parent <parent-id> --priority <parent-priority>
|
|
65
|
+
```
|
|
66
|
+
`<create-task-scripts>` is the absolute path to `skills/planning/create-task/scripts/`, resolved from wherever the skill was loaded — never hardcode one harness's install path. `<parent-priority>` is the parent's own priority from `bd show <parent-id>`, so chores match the task they belong to.
|
|
67
|
+
3. **Record it in `inflight`** so its completion is attributable to the parent and it stays in the wait set — it has no chore, so `choreId` is `null`:
|
|
68
|
+
```json
|
|
69
|
+
{ "kind": "expand", "choreId": null, "parentId": "<parent-id>", "title": "<parent title>", "agentId": "<agent-id>", "logLine": 1 }
|
|
70
|
+
```
|
|
71
|
+
4. **Report the mapping** the worker returns — `code`, `verify`, `review`, `document`, `featurePrReview` — and close nothing. The worker owns no bead on this run; the expansion is bookkeeping, not a stage.
|
|
72
|
+
5. **Dispatch normally.** The next `bd ready -l execution:afk` pass picks up the `stage:code` chore, and the pre-created chain carries the rest.
|
|
73
|
+
6. **Handle the completion as an expansion completion**, not a stage completion — see below.
|
|
74
|
+
|
|
75
|
+
**Never expand an existing bead with `create-task`** — or with 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. The guard exists so an `execution:afk` task bead always ends with exactly one parent: `create-chores.mjs` expands a bead that already exists; only `create-task` creates parents.
|
|
76
|
+
|
|
77
|
+
**Labels on the chain.** Stage chores inherit `execution:afk` from their parent task bead, so they surface in ralph's `bd ready -l execution:afk` query without extra tagging — an expanded task never needs its chores relabelled. The `featurePrReview` HITL gate is the one exception: it declares its own `execution:hitl` + `lifecycle:feature-pr` labels and the script passes `--no-inherit-labels` for it, so it never picks up the parent's `execution:afk`.
|
|
78
|
+
|
|
79
|
+
### Expansion Completion Contract
|
|
80
|
+
|
|
81
|
+
An expansion worker is dispatched like a stage worker but is **not** one. Nothing downstream of a stage dispatch applies to it:
|
|
82
|
+
|
|
83
|
+
| Stage worker | Expansion worker |
|
|
84
|
+
|------|------|
|
|
85
|
+
| Correlates to a claimed chore: `kind: "stage"` with a `choreId` | Holds no chore: `kind: "expand"`, `choreId: null` |
|
|
86
|
+
| Emits a `---REPORT---` block | Emits none — it prints the `create-chores.mjs` JSON mapping |
|
|
87
|
+
| Owns its leaf bead, which must read `closed` | Owns nothing — no bead to close, nothing to confirm |
|
|
88
|
+
| Completion advances the parent along the chain | Completion means "chores now exist" — dispatch the ready `stage:code` chore |
|
|
89
|
+
|
|
90
|
+
On completion, remove the entry from `inflight` and confirm the chore tree exists rather than taking the worker's word for it:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
bd children <parent-id> --json | grep -c '"stage:'
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Expect a non-zero count — one match per `stage:*` label in the chain. A printed `0` means the
|
|
97
|
+
expansion failed. Surface the worker's output in chat and record the parent for the shutdown summary — **never re-dispatch the expansion**, because `create-chores.mjs` is not idempotent and a second run duplicates the chain beside the first. Then continue at the normal dispatch pass: either way nothing is created and nothing is closed by ralph.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Feature Decomposition
|
|
102
|
+
|
|
103
|
+
Epic Q2 makes ralph responsible for decomposing a feature bead into the hierarchy; Q5 makes a
|
|
104
|
+
feature `execution:hitl` by default. Both hold because the **label**, not the bead type, decides
|
|
105
|
+
routing: a feature is invisible to ralph while it carries `execution:hitl`, and a human exposes it
|
|
106
|
+
to ralph by relabelling it `execution:afk` when its delivery is genuinely agent-routable. Ralph
|
|
107
|
+
then decomposes it once and immediately goes idle behind the planning bead — Q5b's dependency gate
|
|
108
|
+
does the pausing, so no extra "ready to decompose" label is needed.
|
|
109
|
+
|
|
110
|
+
A ready `execution:afk` bead of type `feature` with **no** children is not dispatchable work.
|
|
111
|
+
Decompose it:
|
|
112
|
+
|
|
113
|
+
1. **Confirm it is childless** — any existing child means the feature is already decomposed and this
|
|
114
|
+
procedure does not apply:
|
|
115
|
+
```bash
|
|
116
|
+
bd children <feature-id> --json
|
|
117
|
+
```
|
|
118
|
+
Expect an empty list `[]`. A non-empty list, however few children, means stop here.
|
|
119
|
+
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 the Q5 shape:
|
|
120
|
+
- a **planning bead** — `--parent <feature-id>`, `execution:hitl` — held for a human to confirm planning is sufficient;
|
|
121
|
+
- **implementation task children** — `--parent <feature-id>`, `execution:afk`, `--no-inherit-labels` — each wired to wait on the planning bead with `bd dep add <impl-child> <planning-bead>`.
|
|
122
|
+
|
|
123
|
+
This is the shape `create-task` builds on its feature path (`SKILL.md` steps 5–6): an `execution:hitl` planning bead owned by the feature, whose impl children depend on it, so the dependency — not a label — is the readiness gate.
|
|
124
|
+
3. **Record it in `inflight`** so its completion is attributable to the feature and it stays in the wait set — it holds no chore, so `choreId` is `null`:
|
|
125
|
+
```json
|
|
126
|
+
{ "kind": "decompose", "choreId": null, "parentId": "<feature-id>", "title": "<feature title>", "agentId": "<agent-id>", "logLine": 1 }
|
|
127
|
+
```
|
|
128
|
+
4. **Confirm the children exist** rather than trusting the report — the worker's IDs are a claim, the bead graph is the evidence:
|
|
129
|
+
```bash
|
|
130
|
+
bd children <feature-id> --json
|
|
131
|
+
```
|
|
132
|
+
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.
|
|
133
|
+
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. This is the same hazard as re-running `create-chores.mjs`.
|
|
134
|
+
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 — that is Q5b working as designed.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
7
138
|
## Dispatching a Chore Bead
|
|
8
139
|
|
|
140
|
+
Chores already exist, so dispatch never creates one:
|
|
141
|
+
|
|
9
142
|
1. **Claim** the bead: `bd update <id> --claim`.
|
|
10
143
|
2. **Read its `stage:*` label** from `bd show <id>`.
|
|
11
144
|
3. **Load the universal stage runner prompt** from `skills/workflow/run-pipeline-stage/prompts/stage-runner.md`.
|
|
@@ -13,7 +146,7 @@ Detailed procedures for the ralph orchestration workflow. See [SKILL.md](./SKILL
|
|
|
13
146
|
5. **Ensure branch + worktree exist for this parent task** (see _Feature branches and worktrees_ below), then note the worktree path — you'll pass it as `cwd` to {{TOOL:task}}.
|
|
14
147
|
6. **Fill in the prompt** — replace placeholders with:
|
|
15
148
|
- Stage from bead label (`stage:<stage>`) for `<stage>`
|
|
16
|
-
-
|
|
149
|
+
- The leaf execution bead ID and its `bd show` output for the bead specification. Do **not** inject `bd prime` output — the stage runner runs `bd prime` itself if it needs project context
|
|
17
150
|
- Parent task description from `bd show <parent-id>`
|
|
18
151
|
- For `fix` stage: `FILES_CHANGED` from the preceding stage's report (the required changes come from the fix bead's own description — read via `bd show <fix-id>`)
|
|
19
152
|
- For `verify`, `review`, `document` stages: `SUMMARY` and `FILES_CHANGED` from the preceding stage's report
|
|
@@ -55,6 +188,10 @@ For each parent task bead (`<parent-id>`):
|
|
|
55
188
|
# <base> is epic/<epic-id> for multi-feature epics, origin/main for single-feature
|
|
56
189
|
git worktree add .agent-cortex/worktrees/<parent-id> -b feature/<parent-id> <base>
|
|
57
190
|
```
|
|
191
|
+
**`<base>` is `epic/<epic-id>` or `origin/main` — never another `feature/*` branch.** If this
|
|
192
|
+
task depends on another unmerged task, its `blocks` edge already keeps it out of `bd ready`;
|
|
193
|
+
do not create the worktree early to get ahead, and never reuse a sibling task's worktree — that
|
|
194
|
+
silently stacks the branches and turns the dependency into a squash-merge conflict later.
|
|
58
195
|
If `.agent-cortex/worktrees/<parent-id>` already exists, reuse it.
|
|
59
196
|
5. All chores for this parent run in `.agent-cortex/worktrees/<parent-id>`. The `feature/<parent-id>` branch is the agent branch for HITL PRs.
|
|
60
197
|
|
|
@@ -64,7 +201,7 @@ For each parent task bead (`<parent-id>`):
|
|
|
64
201
|
|
|
65
202
|
When the `document` chore for a parent task completes:
|
|
66
203
|
|
|
67
|
-
1.
|
|
204
|
+
1. Confirm the document worker closed its own chore (`bd show <id>` reads `closed`); do not close it yourself.
|
|
68
205
|
2. Create or update a feature PR immediately from the agent branch to the feature branch (`feature/<parent-id>` into `epic/<epic-id>`; into `main` for single-feature epics):
|
|
69
206
|
```bash
|
|
70
207
|
# <base> is epic/<epic-id> for multi-feature epics, main for single-feature
|
|
@@ -72,45 +209,56 @@ When the `document` chore for a parent task completes:
|
|
|
72
209
|
```
|
|
73
210
|
If an open PR already exists, update it instead of creating a duplicate.
|
|
74
211
|
3. Report the PR URL in chat as soon as it is created.
|
|
75
|
-
4. Find the child HITL task bead for this parent with label `lifecycle:feature-pr` (created by `create-task`).
|
|
212
|
+
4. Find the child HITL task bead for this parent with label `lifecycle:feature-pr` and `execution:hitl` (created by `create-task`).
|
|
76
213
|
5. Update that HITL bead with the PR URL/status (comment or note) so the reviewer has the link.
|
|
77
|
-
6. Do not schedule new parent features while this
|
|
78
|
-
7. Once the PR is merged, a human closes the HITL PR gate bead. After that, close the parent feature bead:
|
|
214
|
+
6. Do not schedule new parent features while this gate is **unblocked** — an unblocked gate is a feature genuinely awaiting a human merge (see _Gate predicate_ below).
|
|
215
|
+
7. Once the PR is merged, a human closes the HITL PR gate bead, which unblocks the scheduling brake. After that, close the parent feature bead:
|
|
79
216
|
```bash
|
|
80
217
|
bd close <parent-id>
|
|
81
218
|
```
|
|
82
219
|
Only then continue with next parent features.
|
|
83
220
|
|
|
84
|
-
|
|
221
|
+
### Gate predicate — parked vs pending
|
|
85
222
|
|
|
86
|
-
|
|
223
|
+
Ralph's only scheduling brake is a gate that is **unblocked**. `create-chores` pre-creates a `lifecycle:feature-pr` gate for *every* planned feature, blocked behind that feature's own `document` chore; such a gate is **parked** — the feature has not reached its PR stage — and must never stop dispatch. Only when the `document` chore closes does the gate unblock, and that is the state in which a human must merge.
|
|
87
224
|
|
|
88
|
-
|
|
225
|
+
Resolve the question with one command instead of ad-hoc `bd` queries:
|
|
89
226
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
4. **If fix rounds ≥ maxFixRounds**: close the parent task bead as failed (`bd close <parent-id> --reason "Max fix rounds reached"`). Do not create another fix chore.
|
|
94
|
-
5. **Otherwise, create a fix chore** with the feedback in its description so the fixer agent can read it directly from `bd show`:
|
|
95
|
-
```bash
|
|
96
|
-
fix_id=$(bd create "[<parent-id>] Fix (round <N>)" --type chore \
|
|
97
|
-
--priority <same as parent> \
|
|
98
|
-
--description "Requirements: see <parent-id> acceptance criteria (`bd show <parent-id>`).
|
|
227
|
+
```bash
|
|
228
|
+
node skills/workflow/ralph/scripts/pending-gates.mjs
|
|
229
|
+
```
|
|
99
230
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
231
|
+
| Field | Meaning | Effect on ralph |
|
|
232
|
+
| --- | --- | --- |
|
|
233
|
+
| `pendingHumanAction` | Unblocked `lifecycle:feature-pr` gates (all blockers closed) plus epics tagged `awaiting-epic-pr-merge`, each as `{ id, title, kind }` | Non-empty → do **not** schedule new parent features; the same list is the **Pending Human Action** table |
|
|
234
|
+
| `parked` | Open gates still blocked behind their own pipeline | Informational only — never stops dispatch, never appears in the table |
|
|
235
|
+
|
|
236
|
+
Gate queries match the HITL axis on either `execution:hitl` (current) or `implementation-type:hitl` (legacy), so gates created on either side of the two-axis migration are counted.
|
|
237
|
+
|
|
238
|
+
**Invariant — what may block a gate.** `parked` means "blocked by its own pipeline". A gate blocked by its parent **feature** bead is not parked in any harness: that bead stays open until after the merge, so the gate never reaches `bd ready`, never appears in `pendingHumanAction`, and a human merge is silently never requested. Keep the two shapes apart:
|
|
239
|
+
|
|
240
|
+
- A `create-chores` gate unblocks exactly once, when its `document` chore closes. Until then it is parked and must not stop dispatch.
|
|
241
|
+
- A gate must never carry a `blocks` dependency onto its own feature bead (e.g. `bd create ... --labels ...lifecycle:feature-pr` then dep it to `<id>`). Remove it with `bd dep rm <gate> <id>` if present, so the gate is unblocked while its PR awaits merge.
|
|
242
|
+
|
|
243
|
+
So the predicate is sensitive to *what* blocks a gate, not only whether something does. It is ralph's only gate predicate on every harness: the Claude-native agent file that kept an open-gate form is retired, so nothing else restates a second predicate.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Cap Backstop (read-only)
|
|
248
|
+
|
|
249
|
+
Ralph never builds remediation. The worker that fails a stage creates its own `stage:fix` chore, a fresh instance of the failed stage blocked on that fix, and re-blocks the later stages behind the fresh bead (see the `run-pipeline-stage` skill, _Remediation Children_). Ralph only guards the cap, and only reads:
|
|
250
|
+
|
|
251
|
+
1. **Read `maxFixRounds`** from `skills/planning/create-task/pipeline.json` (held in memory since initialization).
|
|
252
|
+
2. **Count existing fix rounds** for the parent — closed chores count:
|
|
106
253
|
```bash
|
|
107
|
-
bd
|
|
254
|
+
fix_rounds=$(bd children <parent-id> --json | grep -c '"stage:fix"')
|
|
108
255
|
```
|
|
109
|
-
|
|
256
|
+
3. **Before dispatching any `stage:*` chore of that parent**, if `fix_rounds >= maxFixRounds`: create nothing and block the parent, so a human sees it in the shutdown summary:
|
|
110
257
|
```bash
|
|
111
|
-
bd
|
|
258
|
+
bd update <parent-id> --status blocked \
|
|
259
|
+
--append-notes "[<ISO-timestamp>] max fix rounds reached (<fix_rounds>/<maxFixRounds>)"
|
|
112
260
|
```
|
|
113
|
-
|
|
261
|
+
4. Ralph does **not** close the parent as failed and does **not** reopen or re-wire any chore — the worker already closed the failed leaf bead and the fresh stage bead is already blocked on its fix.
|
|
114
262
|
|
|
115
263
|
---
|
|
116
264
|
|
|
@@ -118,44 +266,43 @@ When a verify or review stage fails:
|
|
|
118
266
|
|
|
119
267
|
Run whenever completion handling is triggered (an agent completion):
|
|
120
268
|
|
|
121
|
-
1. **
|
|
122
|
-
2. For each in-flight
|
|
269
|
+
1. **Read in-flight entries**: `inflight` in `.agent-cortex/ralph/state.json` — every dispatched worker: stage (`kind: "stage"`), decomposition (`kind: "decompose"`) or expansion (`kind: "expand"`). Each entry carries `parentId` and `logLine`.
|
|
270
|
+
2. For each in-flight entry, read new lines from its **parent's** log file — logs are keyed by **parent** bead ID, so all stages of a feature share one file:
|
|
123
271
|
```bash
|
|
124
|
-
tail -n +<
|
|
272
|
+
tail -n +<logLine> .agent-cortex/ralph/ralph-<parentId>.log 2>/dev/null
|
|
125
273
|
```
|
|
126
|
-
3. For each
|
|
274
|
+
3. For each entry that has new lines:
|
|
127
275
|
- **Post a chat summary** of new key events (stage transitions and notable events — not every line verbatim):
|
|
128
276
|
```
|
|
129
|
-
📋 [
|
|
277
|
+
📋 [parent-id] <title>
|
|
130
278
|
coding → verifying (or whatever transition)
|
|
131
279
|
Tests: 12 passed, 0 failed
|
|
132
280
|
```
|
|
133
|
-
- Update
|
|
134
|
-
4. If no
|
|
281
|
+
- Update `logLine` in `state.json` for that entry.
|
|
282
|
+
4. If no entry had new lines, post nothing — do not spam the chat with empty polls.
|
|
135
283
|
|
|
136
284
|
---
|
|
137
285
|
|
|
138
286
|
## HITL Pause
|
|
139
287
|
|
|
140
|
-
Proceed here when no
|
|
288
|
+
Proceed here when no agent work is in flight (no stage, decomposition or expansion workers in `inflight`), nothing is dispatchable (`bd ready -l execution:afk` returns no `stage:*` chore, no childless feature to decompose, and no ready, claimable chore-less `execution:afk` task bead 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` (see _Gate predicate_). Gates still parked behind their own pipeline do not count. Ralph stops rather than burning requests on idle polls.
|
|
141
289
|
|
|
142
|
-
1.
|
|
143
|
-
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 (skip single-feature epics — their feature branch PRs already target `main`):
|
|
290
|
+
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 (skip single-feature epics — their feature branch PRs already target `main`):
|
|
144
291
|
```bash
|
|
145
292
|
gh pr create --base main --head epic/<epic-id> --title "[<epic-id>] Merge epic into main" --body "<epic summary>"
|
|
146
293
|
```
|
|
147
294
|
Tag each epic bead with `awaiting-epic-pr-merge` until merged.
|
|
148
|
-
|
|
295
|
+
2. Run:
|
|
149
296
|
```bash
|
|
150
297
|
bd dolt push
|
|
151
298
|
```
|
|
152
|
-
|
|
299
|
+
**Gate 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, and ralph does not claim a clean pause.
|
|
300
|
+
3. Collect the table rows from the script's `pendingHumanAction` list:
|
|
153
301
|
```bash
|
|
154
|
-
|
|
155
|
-
bd list -l awaiting-epic-pr-merge
|
|
302
|
+
node skills/workflow/ralph/scripts/pending-gates.mjs
|
|
156
303
|
```
|
|
157
|
-
For each
|
|
158
|
-
|
|
304
|
+
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".
|
|
305
|
+
4. Output the **Pending Human Action** summary:
|
|
159
306
|
```
|
|
160
307
|
⏸️ Ralph is paused — human action required before work can continue.
|
|
161
308
|
|
|
@@ -167,25 +314,25 @@ Proceed here when no chore beads are in-flight, no `stage:*` chore beads are rea
|
|
|
167
314
|
|
|
168
315
|
When you've completed the above, prompt me to continue.
|
|
169
316
|
```
|
|
170
|
-
|
|
317
|
+
5. **Stop completely.** Stop the wake mechanism as the wake section describes. Do not continue the event loop. Wait for the user to re-prompt before doing any further work.
|
|
171
318
|
|
|
172
319
|
---
|
|
173
320
|
|
|
174
321
|
## Shutdown
|
|
175
322
|
|
|
176
|
-
When
|
|
323
|
+
When nothing is in flight AND nothing is dispatchable — `inflight` holds no entries, `bd ready -l execution:afk` returns nothing (no `stage:*` chore, no childless feature to decompose, no ready, claimable chore-less task bead awaiting expansion) (_The in-flight invariant_ above):
|
|
177
324
|
|
|
178
|
-
1.
|
|
179
|
-
2. For each **multi-feature** epic whose feature beads are all closed, open/update an epic PR to main (skip single-feature epics — no epic branch exists):
|
|
325
|
+
1. For each **multi-feature** epic whose feature beads are all closed, open/update an epic PR to main (skip single-feature epics — no epic branch exists):
|
|
180
326
|
```bash
|
|
181
327
|
gh pr create --base main --head epic/<epic-id> --title "[<epic-id>] Merge epic into main" --body "<epic summary>"
|
|
182
328
|
```
|
|
183
329
|
Tag each epic bead with `awaiting-epic-pr-merge` until merged.
|
|
184
|
-
|
|
330
|
+
2. Run:
|
|
185
331
|
```bash
|
|
186
332
|
bd dolt push
|
|
187
333
|
```
|
|
188
|
-
|
|
334
|
+
**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.
|
|
335
|
+
3. If any HITL beads were noted during the session, output:
|
|
189
336
|
```
|
|
190
337
|
All agent work is complete. The following steps require human action before work can continue:
|
|
191
338
|
|
|
@@ -206,20 +353,27 @@ When `bd list --status=in_progress --type=chore` returns no results AND `bd read
|
|
|
206
353
|
|
|
207
354
|
## State Files
|
|
208
355
|
|
|
356
|
+
Status is read from beads — there is no rendered status document to build or refresh:
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
bd list --parent <parent-id> # every chore for a feature, with its state
|
|
360
|
+
bd ready -l execution:afk # the next dispatchable work
|
|
361
|
+
bd show <id> # full detail, including the worker's notes
|
|
362
|
+
```
|
|
363
|
+
|
|
209
364
|
| File | Purpose |
|
|
210
365
|
|------|---------|
|
|
211
|
-
| `.agent-cortex/ralph/
|
|
212
|
-
| `.agent-cortex/ralph/state.json` | Runtime bookkeeping only: the in-flight agent-ID→bead mapping. Shape: `{ "inflight": [ { "choreId": "...", "parentId": "...", "title": "...", "agentId": "...", "logLine": 1 } ] }`. Initialise at startup with `{ "inflight": [] }`. Update after every dispatch and every agent completion. **Never hand-edit.** |
|
|
366
|
+
| `.agent-cortex/ralph/state.json` | Runtime bookkeeping only: the in-flight agent-ID→bead mapping. Shape: `{ "inflight": [ { "kind": "stage", "choreId": "...", "parentId": "...", "title": "...", "agentId": "...", "logLine": 1 } ] }`. A decomposition worker is recorded with `"kind": "decompose"` and an expansion worker with `"kind": "expand"`, both with `"choreId": null` — they hold no chore but still occupy the wait set and the in-flight check. Initialise at startup with `{ "inflight": [] }`. Update after every dispatch and every agent completion. **Never hand-edit.** |
|
|
213
367
|
| `.agent-cortex/ralph/ralph-*.log` | Per-parent log files written by subagents — every stage chore of a feature appends to `.agent-cortex/ralph/ralph-<parent-id>.log` (e.g. `ralph-abc-123.log`). |
|
|
214
368
|
|
|
215
369
|
All task state is derived from beads; `state.json` holds only runtime bookkeeping:
|
|
216
370
|
|
|
217
371
|
| Question | How to answer |
|
|
218
372
|
|----------|---------------|
|
|
219
|
-
| What is in-flight? | `
|
|
220
|
-
| What is ready? | `bd ready` —
|
|
373
|
+
| What is in-flight? | The `inflight` entries in `.agent-cortex/ralph/state.json` — `kind: "stage"` for a dispatched stage chore, `kind: "decompose"` for a feature-decomposition worker, `kind: "expand"` for an expansion worker. Decomposition and expansion workers hold no chore, so beads alone under-report in-flight work. |
|
|
374
|
+
| What is ready? | `bd ready -l execution:afk` — the single dispatch predicate. Each result is routed by its shape: a childless `feature` bead is decomposed (_Feature Decomposition_), a bead with no `stage:*` children is expanded (_Expansion Guard_), a `stage:*` chore is dispatched. |
|
|
221
375
|
| What stage is a bead in? | Read the `stage:*` label from `bd show <id>` |
|
|
222
376
|
| Which agent-ID maps to which bead? | `inflight` entries in `.agent-cortex/ralph/state.json` |
|
|
223
|
-
| How many fix rounds? | Count chore beads with label `stage:fix` that are children of the parent task. Read `maxFixRounds` from `skills/planning/create-task/pipeline.json`. |
|
|
224
|
-
| Which features are review-gated? |
|
|
377
|
+
| How many fix rounds? | Count chore beads with label `stage:fix` that are children of the parent task (`bd children <parent-id> --json | grep -c '"stage:fix"'`). Read `maxFixRounds` from `skills/planning/create-task/pipeline.json`. Read-only: used for the cap backstop, never to build remediation. |
|
|
378
|
+
| Which features are review-gated? | `pendingHumanAction` entries with `kind: "feature-pr"` from `pending-gates.mjs` — unblocked `lifecycle:feature-pr` gates on either HITL axis. A gate in `parked` is pre-created but not yet actionable |
|
|
225
379
|
| Which epics are review-gated? | `bd list -l awaiting-epic-pr-merge` |
|