@jaybeeuu/agent-cortex 2.1.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 (178) hide show
  1. package/CHANGELOG.md +387 -0
  2. package/README.md +33 -13
  3. package/agents/README.md +22 -10
  4. package/agents/plan/agent.md +2 -2
  5. package/agents/ralph/agent.md +126 -88
  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 +182 -68
  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/hooks/claude/scripts/notify.mjs +8 -1
  18. package/lib/cli.mjs +91 -2
  19. package/package.json +27 -3
  20. package/scripts/check-changeset.mjs +4 -0
  21. package/scripts/check-no-sync.mjs +5 -1
  22. package/scripts/lib/compose-agent.mjs +69 -9
  23. package/scripts/lib/fs.mjs +10 -2
  24. package/scripts/lib/migrate.mjs +736 -0
  25. package/scripts/lib/release-gates.mjs +21 -1
  26. package/scripts/lib/skill-frontmatter.mjs +23 -6
  27. package/scripts/lib/skill-links.mjs +52 -0
  28. package/scripts/lib/verify-worker-tree.mjs +25 -0
  29. package/scripts/resolve-publish-command.mjs +4 -0
  30. package/skills/engineering/design-an-interface/SKILL.md +3 -3
  31. package/skills/engineering/grill-with-docs/SKILL.md +3 -5
  32. package/skills/engineering/improve-codebase-architecture/SKILL.md +5 -4
  33. package/skills/engineering/tdd/SKILL.md +5 -7
  34. package/skills/engineering/technical-direction/SKILL.md +5 -5
  35. package/skills/planning/classify-bead/REFERENCE.md +3 -3
  36. package/skills/planning/classify-bead/SKILL.md +14 -9
  37. package/skills/planning/classify-bead/scripts/classify-bead.mjs +5 -4
  38. package/skills/planning/create-task/REFERENCE.md +52 -3
  39. package/skills/planning/create-task/SKILL.md +70 -26
  40. package/skills/planning/create-task/scripts/{create-chores.ts → create-chores.mjs} +48 -23
  41. package/skills/planning/flesh-out-idea/REFERENCE.md +116 -0
  42. package/skills/planning/flesh-out-idea/SKILL.md +146 -0
  43. package/skills/planning/prd-to-tasks/REFERENCE.md +54 -5
  44. package/skills/planning/prd-to-tasks/SKILL.md +22 -16
  45. package/skills/planning/record-idea/FORMAT.md +66 -17
  46. package/skills/planning/record-idea/SKILL.md +48 -24
  47. package/skills/planning/request-refactor-plan/SKILL.md +4 -4
  48. package/skills/planning/spec-to-tickets/SKILL.md +5 -5
  49. package/skills/planning/write-a-prd/SKILL.md +8 -9
  50. package/skills/planning/write-a-ticket/SKILL.md +4 -6
  51. package/skills/productivity/bd-tool/SKILL.md +15 -10
  52. package/skills/productivity/grill-me/SKILL.md +5 -0
  53. package/skills/productivity/init-beads/SKILL.md +3 -3
  54. package/skills/productivity/migration/REFERENCE.md +227 -0
  55. package/skills/productivity/migration/SKILL.md +188 -0
  56. package/skills/productivity/validate-agent-dir/scripts/{validate-agent-dir.ts → validate-agent-dir.mjs} +49 -28
  57. package/skills/productivity/write-a-skill/SKILL.md +5 -5
  58. package/skills/review/maintain-agent-docs/SKILL.md +5 -7
  59. package/skills/review/refactor-skill/SKILL.md +4 -3
  60. package/skills/review/review-security/SKILL.md +3 -5
  61. package/skills/style/style-code/SKILL.md +5 -10
  62. package/skills/style/style-comms/SKILL.md +5 -7
  63. package/skills/style/style-documentation/SKILL.md +5 -6
  64. package/skills/style/style-tests/SKILL.md +5 -7
  65. package/skills/workflow/git-workflow/SKILL.md +28 -4
  66. package/skills/workflow/hitl-collab/SKILL.md +4 -6
  67. package/skills/workflow/plan/SKILL.md +41 -30
  68. package/skills/workflow/ralph/REFERENCE.md +182 -51
  69. package/skills/workflow/ralph/SKILL.md +89 -50
  70. package/skills/workflow/run-pipeline-stage/SKILL.md +72 -71
  71. package/skills/workflow/run-pipeline-stage/playbooks/code.md +11 -0
  72. package/skills/workflow/run-pipeline-stage/playbooks/document.md +12 -0
  73. package/skills/workflow/run-pipeline-stage/playbooks/fix.md +12 -0
  74. package/skills/workflow/run-pipeline-stage/playbooks/review.md +11 -0
  75. package/skills/workflow/run-pipeline-stage/playbooks/verify.md +13 -0
  76. package/skills/workflow/run-pipeline-stage/prompts/stage-runner.md +73 -1
  77. package/token-map.README.md +9 -4
  78. package/token-map.json +13 -6
  79. package/.agents/skills/style-versioning/SKILL.md +0 -172
  80. package/.changeset/README.md +0 -8
  81. package/.changeset/config.json +0 -11
  82. package/.github/workflows/ci.yml +0 -302
  83. package/.junie/guidelines.md +0 -87
  84. package/.junie/mcp/mcp.json +0 -10
  85. package/AGENTS.md +0 -153
  86. package/agents/ralph/claude/polling.md +0 -31
  87. package/agents-native/ralph.md +0 -203
  88. package/docs/claude-hooks.md +0 -144
  89. package/docs/commit-signing.md +0 -231
  90. package/docs/ideas/auto-model-selection.md +0 -75
  91. package/docs/ideas/ban-content-assertion-tests.md +0 -75
  92. package/docs/ideas/bead-progress-notes-for-session-resumption.md +0 -75
  93. package/docs/ideas/classify-beads-via-deterministic-script-with-agent-fallback.md +0 -70
  94. package/docs/ideas/ctx-alias-version-and-update-commands.md +0 -65
  95. package/docs/ideas/ctx-feedback-command-for-capturing-ideas-from-any-machine.md +0 -67
  96. package/docs/ideas/dedicated-review-tests-skill.md +0 -71
  97. package/docs/ideas/deployment-beads-for-post-merge-pipelines.md +0 -36
  98. package/docs/ideas/design-and-delivery-as-separate-bead-trees/design-and-delivery-as-separate-bead-trees.md +0 -99
  99. package/docs/ideas/enable-signed-commit-enforcement-changesets-bot-commits-must-be-signed.md +0 -42
  100. package/docs/ideas/extension-manifests.md +0 -121
  101. package/docs/ideas/improve-pi-system-prompt.md +0 -43
  102. package/docs/ideas/map-every-cortex-tool-to-a-real-pi-equivalent.md +0 -95
  103. package/docs/ideas/model-selector.md +0 -40
  104. package/docs/ideas/pi-task-memory.md +0 -34
  105. package/docs/ideas/qa-extension.md +0 -43
  106. package/docs/ideas/record-idea-implementation-questions.md +0 -68
  107. package/docs/ideas/record-ideas-as-beads.md +0 -115
  108. package/docs/ideas/self-flushing-session.md +0 -72
  109. package/docs/ideas/state-in-beads-not-md.md +0 -69
  110. package/docs/ideas/subagent-visibility.md +0 -72
  111. package/docs/ideas/task-session-context.local.md +0 -95
  112. package/docs/ideas/task-session-context.md +0 -89
  113. package/docs/ideas/test-data-creation-helpers.md +0 -92
  114. package/docs/ideas/test-planning-stage-bead-in-feature-planning.md +0 -68
  115. package/docs/ideas/unified-ci-pipeline.md +0 -28
  116. package/docs/ideas/unify-the-ticket-and-task-decomposition-workflows.md +0 -71
  117. package/docs/ideas/worktree-housekeeping-for-closed-beads.md +0 -39
  118. package/docs/inspirations.md +0 -33
  119. package/docs/research/disable-model-invocation.md +0 -82
  120. package/docs/research/gas-city-research.md +0 -256
  121. package/docs/research/skill-design-research.md +0 -286
  122. package/docs/research/skill-improvements-analysis.md +0 -117
  123. package/docs/research/skill-patterns-research.md +0 -24
  124. package/docs/skills/skill-anatomy.md +0 -200
  125. package/docs/technical-direction/harness-config.md +0 -177
  126. package/docs/technical-direction/migration-execution-labels.md +0 -177
  127. package/docs/user-preferences.md +0 -17
  128. package/extensions/agent-guardrails/tsconfig.json +0 -12
  129. package/extensions/agent-modes/tsconfig.json +0 -12
  130. package/extensions/output-style/tsconfig.json +0 -12
  131. package/extensions/session-start/tsconfig.json +0 -12
  132. package/extensions/skill-stats/pnpm-lock.yaml +0 -329
  133. package/extensions/skill-stats/tsconfig.json +0 -12
  134. package/extensions/subagent/agents/planner.md +0 -37
  135. package/extensions/subagent/agents/reviewer.md +0 -35
  136. package/extensions/subagent/agents/scout.md +0 -50
  137. package/extensions/subagent/agents/worker.md +0 -24
  138. package/extensions/subagent/prompts/implement-and-review.md +0 -10
  139. package/extensions/subagent/prompts/implement.md +0 -10
  140. package/extensions/subagent/prompts/scout-and-plan.md +0 -9
  141. package/extensions/subagent/tsconfig.json +0 -12
  142. package/pi/keybindings.json +0 -3
  143. package/pi/settings.json +0 -34
  144. package/pnpm-workspace.yaml +0 -14
  145. package/skills/planning/create-task/scripts/package.json +0 -14
  146. package/skills/planning/create-task/scripts/pnpm-lock.yaml +0 -342
  147. package/skills/planning/create-task/scripts/tsconfig.json +0 -12
  148. package/skills/planning/record-idea/scripts/new-idea.sh +0 -89
  149. package/skills/productivity/validate-agent-dir/scripts/package.json +0 -15
  150. package/skills/productivity/validate-agent-dir/scripts/pnpm-lock.yaml +0 -329
  151. package/skills/productivity/validate-agent-dir/scripts/pnpm-workspace.yaml +0 -2
  152. package/skills/productivity/validate-agent-dir/scripts/tsconfig.json +0 -19
  153. package/skills/productivity/validate-agent-dir/scripts/validate-agent-dir.test.ts +0 -317
  154. package/skills/workflow/run-pipeline-stage/REFERENCE.md +0 -22
  155. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.test.ts +0 -682
  156. package/skills/workflow/run-pipeline-stage/scripts/generate-progress.ts +0 -588
  157. package/skills/workflow/run-pipeline-stage/scripts/package.json +0 -15
  158. package/skills/workflow/run-pipeline-stage/scripts/pnpm-lock.yaml +0 -342
  159. package/skills/workflow/run-pipeline-stage/scripts/pnpm-workspace.yaml +0 -2
  160. package/skills/workflow/run-pipeline-stage/scripts/tsconfig.json +0 -12
  161. package/test/classify-bead.test.mjs +0 -277
  162. package/test/claude-installer.test.mjs +0 -308
  163. package/test/cli.test.mjs +0 -314
  164. package/test/create-chores.test.mjs +0 -85
  165. package/test/fake-bd.test.mjs +0 -72
  166. package/test/fs.test.mjs +0 -76
  167. package/test/helpers/fake-bd.mjs +0 -87
  168. package/test/helpers/fake-claude.mjs +0 -152
  169. package/test/helpers/fake-pi.mjs +0 -132
  170. package/test/installer.test.mjs +0 -806
  171. package/test/notify-hook.test.mjs +0 -63
  172. package/test/pending-gates.test.mjs +0 -147
  173. package/test/pi-installer.test.mjs +0 -785
  174. package/test/pi-register.test.mjs +0 -342
  175. package/test/pi-sweep.test.mjs +0 -619
  176. package/test/release-gates.test.mjs +0 -190
  177. package/test/skill-frontmatter.test.mjs +0 -137
  178. package/test/verify-worker-tree.test.mjs +0 -120
package/CHANGELOG.md CHANGED
@@ -1,5 +1,392 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 3dd6ba1: Add `agent-cortex migrate`, a repo-agnostic, versioned migration command for beads
8
+ workspaces. It detects the workspace's current migration version from its own state, prints
9
+ a per-bead dry-run plan by default, and `--apply` renames `implementation-type:afk|hitl`
10
+ labels to `execution:afk|hitl` (step v1) across every bead including closed ones, verifying
11
+ each step and no-opping on a re-run.
12
+ - 3dd6ba1: Add the `migration` skill (`skills/productivity/migration/`). It documents how any workspace
13
+ runs the versioned `agent-cortex migrate` command to move from `implementation-type:afk|hitl` to
14
+ `execution:afk|hitl`: preflight and current-version detection, a pre-migration export snapshot, a
15
+ gated dry-run review, `--apply` with batched add-then-remove label writes, the four post-checks
16
+ (`bd label list-all` clean, the `bd list --label-pattern` group empty, the `bd ready -l
17
+ execution:afk` smoke, the stale-reference sweep), and an idempotence re-run. `REFERENCE.md`
18
+ records the command interface the skill depends on, the v1 label-rename and v2 idea-file steps,
19
+ rollback recipes, and the manual fallback for pinned versions. The two-axis model (bead type ×
20
+ execution) is stated as the rationale, including why a half-migrated workspace silently starves
21
+ ralph's queue.
22
+
23
+ The skill sets `disable-model-invocation: true`, so it is reachable only through its explicit
24
+ command and never auto-routed from a description match — `--apply` renames labels across a whole
25
+ workspace, which is not something a fuzzy match should be able to trigger. On Claude Code and pi
26
+ that hides the skill from automatic selection while `/skill-name` still works; on Copilot CLI the
27
+ field suppresses auto-routing _and_ model-mediated invocation, leaving only the interactive
28
+ `/migration` slash command (see `docs/research/disable-model-invocation.md`).
29
+
30
+ - 3dd6ba1: Ship the real ralph to Claude Code. `agents-native/ralph.md` is deleted along with the `DEFER` and
31
+ `buildNatives` path in `bin/installers/claude.mjs`, so every harness now composes the same ralph body
32
+ and differs only in its wake mechanism (`agents/ralph/<harness>/wake.md`). `SKILL_EXCLUDE` is gone too,
33
+ so the Claude plugin gains the `ralph` and `run-pipeline-stage` skills it previously stripped.
34
+
35
+ The native copy was authored before the chore model existed and had drifted: it ignored chore beads,
36
+ counted fix rounds in its own prose, and ran an implement → review loop with no verify or document
37
+ stage — while pi and Copilot ran the real orchestrator. Its description advertised that stale cycle.
38
+ `agents/ralph/claude/frontmatter.json` now matches the composed agent, and a test asserts the three
39
+ composed bodies are identical once frontmatter and the wake section are removed.
40
+
41
+ ### Patch Changes
42
+
43
+ - 3dd6ba1: Ban stacked branches, and make a stacked PR fail CI.
44
+
45
+ `git-workflow` gains rule 3: every branch is based on the integration branch (`main`, or
46
+ `epic/<id>` for multi-feature work), never on another `feature/*`. A dependency between two tasks
47
+ belongs in the bead graph — `bd dep add <waiting> <blocked-on>` keeps the dependent task out of
48
+ `bd ready` until its dependency merges — not in the branch base. `ralph`'s branching model and its
49
+ _Feature Branches and Worktrees_ procedure now say so explicitly, including not creating a worktree
50
+ early while a `blocks` dependency is unmerged and not reusing a sibling task's worktree.
51
+
52
+ A new `No stacked PRs` CI job fails any pull request whose base matches `feature/*`, because the
53
+ rule only holds if forgetting it is visible. The job must be added to the main branch ruleset's
54
+ required checks to actually block a merge.
55
+
56
+ The cost of the old behaviour: this repo squash-merges, so a lower branch's commits never become
57
+ ancestors of the integration branch. Once it merges, the upper PR carries that whole diff as new
58
+ work and reports conflicts on byte-identical files — three occurrences in two days, each repaired
59
+ with a manual `rebase --onto` plus a full re-verification.
60
+
61
+ - 3dd6ba1: Delete the generated `.agent-cortex/ralph/progress.md` view and its renderer. Beads are the
62
+ view: ralph now reports status straight from `bd list --parent <id>`, `bd ready`, and `bd show`,
63
+ and the ralph skill documents those commands for humans instead of a regeneration step. Removes
64
+ `generate-progress.ts`, its test, the `skills/workflow/run-pipeline-stage/scripts` workspace that
65
+ existed only to run them, and every regeneration instruction in the ralph agent, `ralph` skill,
66
+ `run-pipeline-stage` skill, and the Copilot poll tick.
67
+ - 74601a3: Add `agent-cortex --version` / `-V`, which prints the version of the package the CLI is running
68
+ from — a bare semver, nothing else — and exits 0. The version is resolved from the CLI's own
69
+ `package.json` relative to `bin/agent-cortex.mjs`, not from the cwd or `node_modules`, so a
70
+ published install reports the version it was installed at and two installs on one machine can be
71
+ told apart. Like `--help`, the flags are only recognised as the first argument, so they never
72
+ shadow a command's own options. A manifest that is missing, unreadable, malformed, or has no
73
+ `version` string is a broken install: it prints a one-line diagnostic on stderr and exits 1
74
+ rather than reporting a bogus version with a success exit. `--help` lists the new flags.
75
+ - 3dd6ba1: Move the skill guidance onto the two-axis model. `classify-bead` applies `execution:afk` /
76
+ `execution:hitl` instead of the retired `implementation-type:` namespace — in the skill, its
77
+ `REFERENCE.md`, the deterministic classifier's constants, and its tests — while its rubric,
78
+ tiers, legacy `## Type` read, and CLI stay unchanged. `record-idea` captures ideas as `kind:idea`
79
+ beads (`execution:hitl`, priority, `--acceptance` promotion criteria) instead of scaffold files
80
+ through `new-idea.sh`; its interview adds three bounded implementation questions and a
81
+ `## Design so far / provenance` section, and `FORMAT.md` becomes the bead field mapping that keeps
82
+ `##` section markers inside the description, design, and notes. `bd-tool` documents the
83
+ `execution:<class>` and `kind:idea` rows, the query-filter-only semantics, the measured fact that a
84
+ bare `bd ready` does list idea beads (so it needs `--exclude-label kind:idea`), and the new
85
+ `record-idea` / `flesh-out-idea` cross-references. New `flesh-out-idea` skill answers "which ideas
86
+ are ready?" with `bd ready -l kind:idea`, drives a deepening interview, writes section markers back
87
+ with `--design` / `--append-notes`, and documents the promotion path (idea bead becomes the
88
+ `kind:epic` epic node, `execution:afk` children joined by `--parent`, ordering by dependency).
89
+ - 3dd6ba1: create-task, prd-to-tasks and plan now express the feature → planning → implementation hierarchy: a feature or epic is `execution:hitl`, its planning bead blocks one `execution:afk` implementation child per deliverable, and the PR gate carries `execution:hitl`. Aggregate execution labels are no longer copied from children onto parents.
90
+ - 3dd6ba1: Correct the type annotations the widened tooling typecheck surfaced. Measuring what a repo-wide
91
+ `checkJs` pass would report (the widening itself is tracked separately) turned up a handful of
92
+ genuine JSDoc defects rather than merely missing annotations, all fixed here with no runtime
93
+ change: `bin/installers/pi.mjs` referenced a `ManagedFileResult` type that was never defined, now
94
+ declared as a proper `@typedef` matching what `writeManagedJson` returns; five `async` functions
95
+ declared `@returns` without wrapping them in `Promise<…>`, so `tsc` rejected the declared type
96
+ (`installClaude`, `registerClaude`, `installCopilot`, `installPi`, `composeAgent`);
97
+ `runClaudeCommand`'s `new Promise()` needed a `Promise<void>` hint before `resolve()` could be
98
+ called without an argument; and the two shared predicates in `scripts/lib/fs.mjs` plus
99
+ `collect` in `scripts/check-no-sync.mjs` had untyped parameters and an inferred recursive return
100
+ type. Widening the typecheck to `bin/ lib/ hooks/ scripts/` reports 12 fewer errors afterwards.
101
+ - 1e81c4b: Fix `See Also` links in the materialised Claude plugin. `install claude` copies skills flat
102
+ (`skills/<name>/`), so a handoff authored against the grouped tree (`../../style/style-code/SKILL.md`)
103
+ lost its group segment and 404'd. The flat copy now rewrites cross-skill links to the sibling path
104
+ (`../style-code/SKILL.md`) via `scripts/lib/skill-links.mjs`; the pi install, which keeps the
105
+ grouping, is unchanged.
106
+ - 3dd6ba1: Fold the skill scripts into the root workspace. The two remaining per-skill script packages
107
+ (`skills/planning/create-task/scripts`, `skills/productivity/validate-agent-dir/scripts`) lose
108
+ their `package.json`, `pnpm-lock.yaml`, `pnpm-workspace.yaml` and stray `tsconfig.json`, and the
109
+ dead `skills/**/scripts` glob is dropped from `pnpm-workspace.yaml`, so the root `pnpm-lock.yaml`
110
+ no longer lists script-dir importers. A new root `tsconfig.json` typechecks
111
+ `skills/**/scripts/**/*.mjs` with `checkJs` + `strict`, and the root `typecheck` script now runs
112
+ `tsc --noEmit -p tsconfig.json` before recursing into the extensions — so `pnpm lint` covers every
113
+ script, each of which still runs on bare `node`. `typescript` and `@types/node` join the root
114
+ devDependencies; `tsx` stays for the extensions' `node --test --import tsx/esm` runs. The
115
+ "3 script packages / NOT members of the root workspace" constraint in the migration memo is
116
+ corrected: the glob did make them members, and they are now deleted rather than listed.
117
+ - 3dd6ba1: Gate every `bd dolt push` in the `ralph` and `plan` skills on its exit status. Both skills ran
118
+ the push as a completion step and proceeded straight to the Pending Human Action / completion
119
+ summaries, so a failed sync — an unconfigured or corrupt Dolt remote exits non-zero — looked like
120
+ a clean shutdown while bead state never reached the remote.
121
+
122
+ Every push site now carries the same gate: on a non-zero exit, retry once, then stop and report
123
+ the command, exit code and stderr as a sync blocker instead of printing any completion summary.
124
+ The gate is stated once per path — the ralph skill's _HITL pause and shutdown_ section and its
125
+ verification checklist, the ralph REFERENCE _HITL Pause_ and _Shutdown_ steps, the ralph agent
126
+ body's equivalents, and the plan skill's push step and its Phase 4 and verification checklists —
127
+ and the checklists now require the push to have exited 0 rather than merely to have run.
128
+
129
+ - 3dd6ba1: Gate publishing on typecheck and tests.
130
+
131
+ Nothing ships unless both pass: a new `verify` script (`pnpm typecheck && pnpm test`) is the
132
+ single definition of the gate, and two paths enforce it. `prepublishOnly` runs it for a
133
+ directory publish, and `publish-package` runs it before `pnpm pack`, because
134
+ `npm publish <tarball>` — the path changesets/action execs, and therefore the one every release
135
+ takes — runs no npm publish lifecycle hook at all. `pnpm pack` is untouched, so packing locally
136
+ is still fast.
137
+
138
+ `test/release-gates.test.mjs` proves it by executing those script bodies in a real shell against
139
+ a stub `pnpm`/`npm` pair: a failing typecheck or test aborts before the tarball is packed, and a
140
+ green pair reaches `npm publish` with the packed tarball.
141
+
142
+ - 3dd6ba1: Make the ralph agent body harness-neutral and rename its `{{SECTION:polling}}` seam to
143
+ `{{SECTION:wake}}`. `agents/ralph/agent.md` no longer names a harness (Copilot, PI, Claude) or a
144
+ harness-specific tool (`wait_for_agents`, `read_agent`, `Task`): every such fact — the spawn call
145
+ and its argument shape, how a completion arrives, the ids tracked (`agentId`, `timerShellId`),
146
+ what stopping means, and whether a log must be flushed — now lives in that harness's
147
+ `agents/ralph/<harness>/wake.md`. The shared body refers to the wake section instead, so composing
148
+ it for one harness can never emit instructions about another harness's tools.
149
+
150
+ The section name now matches what it does: `wake` covers polling, blocking wait, and event-driven
151
+ wake-ups, whereas `polling` was simply wrong for the event-driven harness, where no polling exists.
152
+ The mechanism is recorded per harness rather than inferred from prose — `token-map.json` gains a
153
+ `wake.mechanism` table (`copilot`: `polling`, `pi`: `blocking-wait`, `claude`: `event-driven`) and
154
+ `agents/README.md` documents the same table alongside the ralph layout. `agents/ralph.agent.md` is
155
+ regenerated from the composable sources; no Copilot behaviour changes.
156
+
157
+ - 3dd6ba1: Harden `agent-cortex migrate` v1: allowlist its label values and drop the phantom `ctx` alias.
158
+
159
+ The v1 label rename now maps `implementation-type:afk|hitl` only. Any other value — a stray
160
+ `implementation-type:wip` — is a blocking error that names each offending bead id and label and
161
+ stops before any write, on the dry run and on `--apply` alike, instead of inventing an
162
+ `execution:wip` label nothing queries. The migration skill and its reference no longer document
163
+ `ctx migrate`: the package exposes one executable name, `agent-cortex`, with
164
+ `node bin/agent-cortex.mjs migrate` for a checkout that is not installed.
165
+
166
+ - 3dd6ba1: Fix `agent-cortex migrate` v1 reporting a half-migrated workspace as verified.
167
+
168
+ Detection and verification now read every bead from `bd export --all` and cross-check the
169
+ label index from `bd label list-all`, instead of querying `bd list --label-pattern`. On bd
170
+ 1.3.1 a label-filtered `bd list` can omit closed beads, so 28 closed beads kept
171
+ `implementation-type:afk` while `--apply` printed `✓ v1 label-rename verified` and advanced
172
+ the workspace to v1. A legacy label that survives the apply now names the residual bead ids
173
+ and exits non-zero, and an export that cannot attribute a legacy label the index still lists
174
+ fails loudly instead of shrinking the result set.
175
+
176
+ - 3dd6ba1: Add step v2 to `agent-cortex migrate` — loose idea files become `kind:idea` beads — and delete
177
+ the retired idea scaffold script.
178
+
179
+ `docs/ideas/*.md` (one level of nesting included, `--dir <path>` to point the step elsewhere)
180
+ previously had to be migrated by hand. Step v2 reads each file, maps its sections onto the bead
181
+ fields, and creates a `kind:idea` + `execution:hitl` bead: `--description` takes the problem and
182
+ outcome sections, `--design` the how sections, and everything else — including any `##` section
183
+ the template never named — lands in `--notes` with its marker intact, so the flesh-out pass can
184
+ still find sections by name. No line of a source file is dropped. Priority comes from the first
185
+ `P0`–`P4` token in the file and falls back to P4 (backlog), and every bead carries the promotion
186
+ criterion a `task` bead needs to lint clean. The step reads the files and never writes or deletes
187
+ one: retiring them is the repo's own cutover.
188
+
189
+ Each bead it creates cites its source file under a `## Provenance` heading. Before creating
190
+ anything the step lists the existing `kind:idea` beads and skips a file whose path a bead names
191
+ under that heading, or — for a bead that cites no source, i.e. one migrated by hand before the
192
+ step existed — whose title matches (prefix and punctuation ignored). Attribution by provenance
193
+ is what makes re-runs and resumed applies exact: two files can state the same title
194
+ (`task-session-context.md` and `task-session-context.local.md` do), and inferring identity from
195
+ the title alone let an `--apply` that died between the two creates resume silently short. A
196
+ passing cross-reference elsewhere in a bead's notes does not count as a record. The dry run
197
+ prints one `<file> → <title> (P<n>)` line per pending file with zero writes.
198
+
199
+ `skills/planning/record-idea/scripts/new-idea.sh` is gone: it wrote the markdown records the bead
200
+ flow replaced, and nothing has called it since `record-idea` started creating beads. The
201
+ `migration` skill's `SKILL.md` and `REFERENCE.md` document the shipped v2 mechanics — the section
202
+ alias inventory, the priority rule and its `P0-P4` caveat, the `--dir` flag, the collision skip,
203
+ and the deletion ordering.
204
+
205
+ - 3dd6ba1: Make stage chores pre-created only and add ralph's expansion guard. `create-chores.mjs` already
206
+ builds the whole `pipeline.json` chain with `blocks` deps, so the ralph agent body and the
207
+ `ralph` skill no longer create a chore on success paths or at first dispatch — they dispatch
208
+ whatever `bd ready` returns. A ready AFK task bead with no `stage:*` chore children is expanded
209
+ first by a worker running `create-chores.mjs --parent <id> --priority <parent-priority>`, whose
210
+ returned `code`/`verify`/`review`/`document`/`featurePrReview` mapping is reported before the
211
+ normal dispatch picks up `stage:code`; the guard names the duplicate-parent hazard of re-running
212
+ `create-task` for an existing bead. `create-task` documents expanding an existing bead as a
213
+ supported entry point.
214
+
215
+ An expansion worker has its own completion contract: it is recorded in `state.json`'s `inflight`
216
+ as `"kind": "expand"` with `choreId: null` (stage dispatches are `"kind": "stage"`), emits no
217
+ `---REPORT---`, and owns no bead to close — its completion means "the parent now has a `stage:*`
218
+ chain", so ralph confirms the chore tree exists and dispatches the ready `stage:code` chore. The
219
+ PI wait set and the Copilot timer start, HITL-pause check, and shutdown check all cover expansion
220
+ workers, so an in-flight expansion no longer looks like idle work and can no longer trigger HITL
221
+ Pause or Shutdown mid-expansion.
222
+
223
+ Every in-flight query now derives from `state.json`'s `inflight` instead of a
224
+ `--type=chore` beads listing: the dispatch cap counts parents with an `inflight` entry (stage or
225
+ `expand`), Log Polling tails the log of every `inflight` entry's `parentId`, and the Copilot
226
+ HITL-pause check, ralph's Shutdown condition, and the REFERENCE _What is in-flight?_ row all read
227
+ `inflight` — so a running expansion worker occupies a slot and is polled like any other worker.
228
+
229
+ That rule is now stated as an invariant and applied to every ralph control-flow predicate, not
230
+ just the ones an earlier round happened to touch: **every ralph predicate — is anything in flight,
231
+ is there work, is there room under the cap, may we pause, may we shut down — derives from
232
+ `state.json`'s `inflight` (`kind: stage|expand`) plus `bd ready`, never from a chore-type `bd`
233
+ query.** REFERENCE.md gains a _The in-flight invariant_ section with the derive-it-from /
234
+ never-from table, and the skill's init hand-over no longer gates on "no chore was dispatched"
235
+ (an expansion-only init is in flight, not idle, so it can no longer jump to HITL Pause
236
+ mid-expansion). The remaining chore-only predicates were widened at the same time: the init
237
+ hand-over, the HITL-pause conditions (agent body, skill, REFERENCE, Copilot poll tick), and the
238
+ Shutdown conditions now require that nothing is _dispatchable_ — no ready `stage:*` chore **and**
239
+ no **ready, claimable** chore-less AFK task bead awaiting expansion — instead of only "no stage
240
+ chores are ready".
241
+
242
+ "Claimable" is part of the predicate because the feature-PR gate already scopes it: while a
243
+ `lifecycle:feature-pr` HITL gate bead is open ralph schedules no new parent features, so a queued
244
+ unexpanded AFK bead in that state is paused work, not dispatchable work. Without that half of the
245
+ scope the pause predicate is unreachable in the canonical post-PR state — gate open, unexpanded
246
+ AFK beads queued, `inflight` empty, no ready `stage:*` chore — so Copilot would restart its 120 s
247
+ timer forever and PI would re-arm a wait set with no agent IDs. The invariant table now defines
248
+ "dispatchable" as ready _and_ claimable and explains that failure mode, and PI's wait loop defines
249
+ the empty-wait-set state explicitly: never call `wait_for_agents` with no IDs; run the event loop's
250
+ final check, which resolves to HITL Pause (gate beads pending) or Shutdown (none).
251
+
252
+ The chore-type carve-out is now stated as _the only legitimate chore-type control-flow predicate_
253
+ rather than "the one legitimate chore-type query": the `stage:fix` retry counter in _Cap Backstop_
254
+ counts remediation history, so it may gate a dispatch decision but may never answer "is anything in
255
+ flight?". The carve-out is scoped to _control-flow predicates_ so it no longer condemns the
256
+ expansion guard's own structural `grep -c '"stage:'` check, and that check states the count it
257
+ expects rather than demanding exit `0` — `grep -c` exits `1` on zero matches, so the guard now
258
+ says to add `|| true` under `set -e` or in an `&&` chain. The stale TDD loop-count line (`stage:test-writing` chore children) is dropped — that
259
+ label is absent from the pre-created chain in `skills/planning/create-task/pipeline.json`.
260
+
261
+ `agents/ralph/claude/wake.md` carries the same completion-handling text, aligned to the same
262
+ `kind` branch so the composed Claude agent branches identically without reintroducing the
263
+ chore-only predicate, and `agents/README.md` says so in the ralph layout.
264
+
265
+ - 3dd6ba1: Publish only runtime assets. `package.json` gains a `files` whitelist, so the tarball stops
266
+ shipping the whole repo: `.changeset/`, `test/`, `docs/`, `.github/`, `.junie/`, `.agents/`,
267
+ `AGENTS.md`, `tsconfig.json`, `pnpm-workspace.yaml` and the extensions' `node_modules/.bin`
268
+ symlinks are all excluded. `bin/`, `lib/`, `scripts/` (the `postinstall` installer lives there),
269
+ `skills/`, `agents/`, `extensions/`, `hooks/`, `claude/`, `claude-extras/`, `plugin.json` and
270
+ `token-map.json` remain, since the installers and the PI runtime read them. The `.beads/` task
271
+ database was previously excluded only by `.git/info/exclude`, which npm does not honour, so a
272
+ `pnpm pack` from a developer checkout could publish it — the whitelist closes that. Also adds the
273
+ `// @ts-check` pragma that `skills/planning/classify-bead/scripts/classify-bead.mjs` was missing,
274
+ matching the other skill scripts and the single-workspace decision.
275
+ - 3dd6ba1: Route ralph by `execution:afk` and give it feature decomposition (F4 of the two-axis model).
276
+
277
+ Ralph's dispatch predicate is now one query — `bd ready -l execution:afk` — and every ready
278
+ `execution:afk` bead is its work, whether that bead is a feature, a task or a chore. What happens
279
+ next is decided by the bead's _shape_: a childless `feature` bead is decomposed, a bead with no
280
+ `stage:*` chores is expanded, a `stage:*` chore is dispatched. This replaces the previous
281
+ `implementation-type:` vocabulary and, more importantly, removes a blind spot: a predicate that
282
+ looked only for "chores with `stage:*`" reported an `execution:afk` bead with no stage chores as
283
+ idle while it was work waiting for a worker.
284
+
285
+ Feature decomposition is the new behaviour (epic Q2). A ready `execution:afk` bead of type
286
+ `feature` with no children is not dispatchable work — ralph dispatches a decomposition worker that
287
+ builds the Q5 hierarchy (one `execution:hitl` planning bead plus `execution:afk` implementation
288
+ children wired to wait on it), confirms the children exist rather than trusting the report, records
289
+ the worker as `kind: "decompose"` in `state.json`, and then goes idle behind the planning bead.
290
+ Because a feature carries `execution:hitl` by default, this only ever runs for a feature a human has
291
+ deliberately relabelled `execution:afk`; the label, not the bead type, decides routing, so Q2 and Q5
292
+ hold together and Q5b's dependency gate does the pausing. The procedure lives in
293
+ `REFERENCE.md` (_Feature Decomposition_) with the trigger in `SKILL.md`, the whole flow mirrored
294
+ into `agents/ralph/agent.md`, and the planning-gate label in `agents/ralph-plan/agent.md` renamed to
295
+ match.
296
+
297
+ All HITL gate queries move to `execution:hitl` and live in one place —
298
+ `skills/workflow/ralph/scripts/pending-gates.mjs`, which counts gates on either HITL axis during the
299
+ cutover (_Gate predicate_) — and the parked-versus-pending invariant in _The in-flight invariant_ is
300
+ unchanged: dispatchable
301
+ still means ready _and_ claimable, so a bead behind an open feature-PR gate stays paused work rather
302
+ than re-arming a wait over an empty agent set.
303
+
304
+ - e7b03cc: `ralph-plan` now creates its planning gate in the Q5 shape the rest of the package implements: the
305
+ planning bead is owned by the feature (`--parent <feature-id>`, `execution:hitl`,
306
+ `--no-inherit-labels`) and every implementation child depends on it, instead of the owning feature
307
+ depending on a parentless gate. The step also records that a planning bead is not a PR gate —
308
+ `create-chores.mjs` keeps exclusive ownership of `lifecycle:feature-pr` — and that a standalone task
309
+ bead needs no planning bead, and it now scopes its hand-built gate block to a feature that has no
310
+ `Plan:` child yet, so it cannot be run beside the gate `create-task` already created. `agents/plan`
311
+ gates its `bd dolt push` on the exit status, and `agents/ralph` names the PR gate's owner precisely.
312
+ - 1e81c4b: Add `See Also` handoffs between related skills. Each skill that references another now names the
313
+ related skill with a relative `SKILL.md` link and the reason to load it — or, where the skill sits
314
+ at its 150-line budget, an inline reference — replacing the bare-name `## Cross-skill references`
315
+ lists and giving `classify-bead`, `refactor-skill`, and `grill-me` the pointer they were missing.
316
+ - 3dd6ba1: Sweep the last stale references to the retired bead model. The `plan` agent's Phase 3 summary no
317
+ longer tells the planner to tag parent epics with a classification aggregated from their children —
318
+ a container epic is `execution:hitl`, and each bead beneath it states its own execution class. The
319
+ `agent-guardrails` extension cites its originating idea by name instead of by its retired
320
+ `docs/ideas/` file path.
321
+ - 3dd6ba1: Typecheck the whole tooling surface — the test suite included — not just the skill scripts. The
322
+ root `tsconfig.json` covered `skills/**/scripts/**/*.mjs` only, so the repo's actual product code
323
+ (the CLI, both harness installers, the Claude hook, and the shared libs) and every test was never
324
+ type checked (only the `check-no-sync` lint reached them). `include` now covers `bin/`, `lib/`,
325
+ `hooks/`, `scripts/` and `test/` alongside the skill scripts, and every error that surfaced is fixed
326
+ with JSDoc annotations rather than by excluding files: no `@ts-nocheck`, no `exclude`, no file
327
+ converted to TypeScript.
328
+
329
+ The surface went from 13 unchecked modules to 0. Measured on the widened `include`, the tooling
330
+ sweep started at 273 errors in 10 files and is clean:
331
+
332
+ - `bin/installers/pi.mjs` 104 → 0, `bin/installers/claude.mjs` 76 → 0, `bin/agent-cortex.mjs` 24 → 0,
333
+ `scripts/lib/compose-agent.mjs` 28 → 0, `scripts/lib/verify-worker-tree.mjs` 13 → 0,
334
+ `scripts/lib/release-gates.mjs` 10 → 0, `hooks/claude/scripts/notify.mjs` 10 → 0, `lib/cli.mjs` 6 → 0,
335
+ and 1 each in `scripts/check-changeset.mjs` and `scripts/resolve-publish-command.mjs`. Most were
336
+ implicit-any parameters; the object shapes the installers pass around (install results, the token
337
+ map, the generated pi manifest, the sweep's options) now have `@typedef`s, exported from
338
+ `scripts/lib/compose-agent.mjs` where both installers share them.
339
+ - `parseArgs` declares its result as a `ParsedArgs` typedef, so `bin/agent-cortex.mjs` can read
340
+ `dryRun`/`output`/`pluginRoot`/`requireRegister` after narrowing on `command`.
341
+ - `validateHarness` treats an `undefined` harness as missing rather than unknown. `parseArgs` returns
342
+ `null` (never `undefined`), so no CLI path changes; `sweepLegacyPiUserDirs` loses its `= {}`
343
+ default, which its required `piUserDir` already made unusable (both its callers pass an object).
344
+ - Two guards replaced state that only looked like narrowing: the marketplace manifest path is built
345
+ from a non-null `marketplaceRoot`, and `hooks.json` is written when the read content is non-null
346
+ (`summary.hooks` was the same condition spelled indirectly).
347
+
348
+ The test suite swept the same way: 192 errors in 16 files → 0. The shape was different — untyped
349
+ fakes and partial fixtures rather than real code — so the fix is typedefs on the shared fakes and on
350
+ the per-file fixtures, not casts at the call sites:
351
+
352
+ - `test/helpers/` already modelled its fakes in JSDoc; the callers did not. `test/pi-register.test.mjs`
353
+ and `test/pi-sweep.test.mjs` grew `InstallTree`/`SweepTree` typedefs for their throwaway trees,
354
+ `test/pi-installer.test.mjs` a `PackageFixture`, and `test/create-chores.test.mjs` a `FakeBead`
355
+ mirroring what `test/helpers/fake-bd.mjs` records — partial option objects (`{ template }`,
356
+ `{ memory }`, `{ packages }`) now accept the fields the cases actually pass instead of inferring
357
+ `{}` from the default.
358
+ - `test/installer.test.mjs`'s generated `hooks.json` is read through a `HooksJson` typedef, so the
359
+ matcher and hook-command reads are checked rather than `any`; nullable results (`result.settings`,
360
+ `result.instructions`, `beads.find(...)`) are narrowed where they are asserted, never asserted
361
+ away with `!`.
362
+ - `execFile` callbacks narrow `error.code` to a number instead of passing a `string | number`
363
+ straight into `exitCode`.
364
+ - One real defect fell out of the sweep: `test/cli.test.mjs` had a `pathExists` helper calling an
365
+ unimported `stat`, dead code from a copy — deleted.
366
+
367
+ `test/typecheck-surface.test.mjs` is the regression guard: it fails if a tooling directory leaves
368
+ `include`, if any `.mjs` in those directories stops being matched by an include pattern, if the
369
+ `typecheck` script stops running the root project, or if `exclude` carves a tooling path out.
370
+ `test/` is in its `REQUIRED_SURFACE`, so dropping the suite back out of the surface is a build
371
+ failure rather than a silent gap.
372
+
373
+ - 3dd6ba1: Move leaf execution bead ownership to the stage worker. The stage runner now appends its
374
+ own milestone notes, closes its own bead on both outcomes, and builds its own remediation
375
+ chain (a `stage:fix` chore plus a fresh instance of the failed stage, blocked in order) with
376
+ a `maxFixRounds` check before it does. `run-pipeline-stage` documents that contract across its
377
+ prompt, playbooks, and skill, and ralph no longer closes leaf beads or creates feedback
378
+ beads — it keeps a read-only cap backstop only.
379
+ - 3dd6ba1: Convert the last two skill scripts to zero-dependency `.mjs` so they run under bare `node` —
380
+ no `tsx`, no per-skill install. `create-chores` (`skills/planning/create-task/scripts/`) and
381
+ `validate-agent-dir` (`skills/productivity/validate-agent-dir/scripts/`) now carry `// @ts-check`
382
+ and JSDoc types instead of TypeScript syntax, matching `classify-bead.mjs`; behaviour and output
383
+ are unchanged. `validate-agent-dir.test.ts` moves to `test/validate-agent-dir.test.mjs` and runs
384
+ in the repo's `node --test` glob, so its 21 tests no longer need a per-skill toolchain. Every
385
+ live invocation string (`create-task` SKILL/REFERENCE, the `ralph` agent body + skill docs,
386
+ `agents/README.md`) now calls `node <scripts>/create-chores.mjs`, and the regenerated Copilot
387
+ agent files follow. The two script packages keep their manifests for now, but with no scripts or
388
+ devDependencies — their deletion lands with the workspace consolidation.
389
+
3
390
  ## 2.1.0
4
391
 
5
392
  ### Minor Changes
package/README.md CHANGED
@@ -12,8 +12,6 @@ agent-cortex/
12
12
  │ ├── plan/ # "
13
13
  │ ├── ralph-plan/ # "
14
14
  │ └── strategy/ # "
15
- ├── agents-native/ # Claude-only agents
16
- │ └── ralph.md # the lean Claude Ralph
17
15
  ├── skills/ # Skills (grouped by domain) — shared by all harnesses
18
16
  │ ├── engineering/ # tdd, improve-codebase-architecture, …
19
17
  │ ├── planning/ # write-a-prd, prd-to-tasks, design-an-interface, …
@@ -71,11 +69,9 @@ temp-dir install plus structural checks:
71
69
  harness dirs
72
70
  (frontmatter.json + section files). Claude only loads agents from a plugin's default `agents/`
73
71
  dir, so the plugin ships them at its own root (default `~/.agent-cortex/claude/agents/`).
74
- - **Claude-native agents** that cannot be composed from a shared body live in
75
- `agents-native/*.md` and are copied verbatim into the materialised plugin's `agents/`. `ralph`
76
- is one: it is reimplemented for Claude around background workers + an independent review gate
77
- (Claude's event-driven completion delivery has no `task`/`read_agent` poll loop to reuse), so
78
- it can't be mechanically converted.
72
+ - **Every agent composes, `ralph` included.** There is no Claude-only agent source: the shared
73
+ body is harness-neutral and each harness supplies only its own wake mechanism
74
+ (`agents/ralph/<harness>/wake.md`), so one body serves both harnesses.
79
75
  - **Manifests** are generated too: the plugin's `.claude-plugin/plugin.json` (its `version`
80
76
  tracks `package.json`, so it never goes stale) and `hooks.json` (copied from the canonical
81
77
  `hooks/claude/hooks.json` source), plus any support files under `hooks/claude/` bundled into
@@ -84,7 +80,7 @@ temp-dir install plus structural checks:
84
80
  dir, which is their canonical store. See `docs/claude-hooks.md` for the
85
81
  extension→hook mapping and the rejections (auto-name, agent-guardrails, skill-stats, subagent, agent-modes).
86
82
 
87
- Edit the sources (`agents/<name>/` composable dirs, `agents-native/*.md`, `skills/**`,
83
+ Edit the sources (`agents/<name>/` composable dirs, `skills/**`,
88
84
  `hooks/claude/`, `claude-extras/`, `package.json`), never anything under the materialised
89
85
  `~/.agent-cortex/claude`.
90
86
 
@@ -434,15 +430,13 @@ extension→hook audit.
434
430
  rejection rationale live in `docs/claude-hooks.md`.
435
431
  - Ralph follow-ups: multi-feature epic branches, and a GitHub-trigger routine to auto-resume
436
432
  after a PR merge (instead of manual re-invocation).
437
- - The pi Ralph (the 4-stage `run-pipeline-stage` pipeline) is unchanged; those two
438
- ralph-coupled skills (`ralph`, `run-pipeline-stage`) are intentionally not shipped to Claude.
433
+ - Ralph's per-task pipeline is shared, not ported: `ralph` and `run-pipeline-stage` ship to
434
+ Claude and compose from the same harness-neutral body as pi, differing only in the wake section.
439
435
 
440
436
  #### Contributing to the Claude plugin
441
437
 
442
438
  Edit the **sources** — the composable `agents/<name>/` directories (shared `agent.md` +
443
- per-harness frontmatter/sections, composed by `bin/installers/claude.mjs`),
444
- `agents-native/*.md` (Claude-only
445
- agents like `ralph` — the canonical bodies the installer copies verbatim), `skills/**`,
439
+ per-harness frontmatter/sections, composed by `bin/installers/claude.mjs`), `skills/**`,
446
440
  `hooks/claude/hooks.json` (hook config), `claude/settings.json` (the user-settings template
447
441
  merged into `~/.claude/settings.json`), `claude-extras/` (hand-authored `.mcp.json` and
448
442
  `scripts/`), and `package.json` (plugin
@@ -453,3 +447,29 @@ re-registers it; `--output <dir>` generates a preview only). The only committed
453
447
  (`.claude-plugin/plugin.json`, `agents/`, `skills/`, `hooks.json`, `.mcp.json`, `scripts/`)
454
448
  so never edit anything under it. CI validates the Claude materialiser (structural checks on
455
449
  a temp-dir install) so sources and installer can never silently diverge.
450
+
451
+ ## Migrating a beads workspace
452
+
453
+ `agent-cortex migrate` brings the `.beads` workspace it runs in — any repo, not just this
454
+ one — up to the latest agent-cortex migration version. The current version is derived from
455
+ the workspace's own state (the first step with pending work), so there is no marker file to
456
+ drift and a re-run after an apply is a no-op. Step v1 renames `implementation-type:afk|hitl`
457
+ labels to `execution:afk|hitl` on every bead carrying them, closed ones included: the goal
458
+ is an empty legacy namespace, not just a clean live one (see
459
+ `docs/technical-direction/migration-execution-labels.md` for the two-axis model behind it).
460
+
461
+ A bare `agent-cortex migrate` is a **dry run** — it prints the per-bead plan and writes
462
+ nothing. `--apply` runs every pending step in order and verifies each before moving on. It
463
+ shells out to the `bd` CLI on `PATH` (`BD_PATH` overrides) and fails loudly, rather than
464
+ half-applying, when `bd` is missing or a `bd` subcommand errors.
465
+
466
+ Detection reads `bd export --all` and cross-checks `bd label list-all`, never a
467
+ label-filtered `bd list`: on bd 1.3.1 that query can omit closed beads, which once let a
468
+ partially migrated workspace report itself as verified. When the label index still reports a
469
+ legacy label that no exported bead carries — or a legacy label survives the apply — `migrate`
470
+ names the beads and exits non-zero.
471
+
472
+ ```sh
473
+ agent-cortex migrate # dry run — per-bead plan, zero writes
474
+ agent-cortex migrate --apply # apply pending steps, verifying each
475
+ ```
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