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