@aperant/framework 0.17.0 → 0.20.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 (242) hide show
  1. package/CHANGELOG.md +261 -0
  2. package/agents/apt-executor.md +6 -0
  3. package/agents/apt-planner.md +3 -2
  4. package/bin/features-reconcile-check.mjs +77 -0
  5. package/dist/cli/artifacts/self-stage.d.mts.map +1 -1
  6. package/dist/cli/artifacts/self-stage.mjs +2 -1
  7. package/dist/cli/artifacts/self-stage.mjs.map +1 -1
  8. package/dist/cli/cli-wrappers/features-reconcile.d.mts +2 -0
  9. package/dist/cli/cli-wrappers/features-reconcile.d.mts.map +1 -0
  10. package/dist/cli/cli-wrappers/features-reconcile.mjs +9 -0
  11. package/dist/cli/cli-wrappers/features-reconcile.mjs.map +1 -0
  12. package/dist/cli/commands/ci-watch.mjs +49 -2
  13. package/dist/cli/commands/ci-watch.mjs.map +1 -1
  14. package/dist/cli/commands/commit.mjs +3 -3
  15. package/dist/cli/commands/commit.mjs.map +1 -1
  16. package/dist/cli/commands/event.mjs +16 -16
  17. package/dist/cli/commands/event.mjs.map +1 -1
  18. package/dist/cli/commands/features-reconcile.d.mts +2 -0
  19. package/dist/cli/commands/features-reconcile.d.mts.map +1 -0
  20. package/dist/cli/commands/features-reconcile.mjs +143 -0
  21. package/dist/cli/commands/features-reconcile.mjs.map +1 -0
  22. package/dist/cli/commands/health-check.d.mts +2 -2
  23. package/dist/cli/commands/health-check.mjs +2 -2
  24. package/dist/cli/commands/merge-integrate.mjs +3 -3
  25. package/dist/cli/commands/merge-integrate.mjs.map +1 -1
  26. package/dist/cli/commands/produce.d.mts +9 -0
  27. package/dist/cli/commands/produce.d.mts.map +1 -0
  28. package/dist/cli/commands/produce.mjs +1345 -0
  29. package/dist/cli/commands/produce.mjs.map +1 -0
  30. package/dist/cli/commands/task.d.mts +16 -1
  31. package/dist/cli/commands/task.d.mts.map +1 -1
  32. package/dist/cli/commands/task.mjs +434 -266
  33. package/dist/cli/commands/task.mjs.map +1 -1
  34. package/dist/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
  35. package/dist/cli/coordination/auto-emit-artifact-ready.mjs.map +1 -1
  36. package/dist/cli/coordination/event-schema.d.mts +5 -3
  37. package/dist/cli/coordination/event-schema.d.mts.map +1 -1
  38. package/dist/cli/coordination/event-schema.mjs +245 -21
  39. package/dist/cli/coordination/event-schema.mjs.map +1 -1
  40. package/dist/cli/coordination/store.d.mts +2 -2
  41. package/dist/cli/coordination/store.mjs +4 -4
  42. package/dist/cli/coordination/store.mjs.map +1 -1
  43. package/dist/cli/dispatch.d.mts.map +1 -1
  44. package/dist/cli/dispatch.mjs +4 -2
  45. package/dist/cli/dispatch.mjs.map +1 -1
  46. package/dist/cli/features/area-shape.d.mts +11 -0
  47. package/dist/cli/features/area-shape.d.mts.map +1 -0
  48. package/dist/cli/features/area-shape.mjs +141 -0
  49. package/dist/cli/features/area-shape.mjs.map +1 -0
  50. package/dist/cli/features/delta.d.mts +78 -0
  51. package/dist/cli/features/delta.d.mts.map +1 -0
  52. package/dist/cli/features/delta.mjs +591 -0
  53. package/dist/cli/features/delta.mjs.map +1 -0
  54. package/dist/cli/features/reconcile.d.mts +236 -0
  55. package/dist/cli/features/reconcile.d.mts.map +1 -0
  56. package/dist/cli/features/reconcile.mjs +1126 -0
  57. package/dist/cli/features/reconcile.mjs.map +1 -0
  58. package/dist/cli/features/surface-map.d.mts +63 -0
  59. package/dist/cli/features/surface-map.d.mts.map +1 -0
  60. package/dist/cli/features/surface-map.mjs +191 -0
  61. package/dist/cli/features/surface-map.mjs.map +1 -0
  62. package/dist/cli/{commands/features-audit.d.mts → features/write-root.d.mts} +4 -3
  63. package/dist/cli/features/write-root.d.mts.map +1 -0
  64. package/dist/cli/features/write-root.mjs +137 -0
  65. package/dist/cli/features/write-root.mjs.map +1 -0
  66. package/dist/cli/gate/gates/features-reconciled.d.mts +36 -0
  67. package/dist/cli/gate/gates/features-reconciled.d.mts.map +1 -0
  68. package/dist/cli/gate/gates/features-reconciled.mjs +67 -0
  69. package/dist/cli/gate/gates/features-reconciled.mjs.map +1 -0
  70. package/dist/cli/gate/gates/index.mjs +1 -0
  71. package/dist/cli/gate/gates/index.mjs.map +1 -1
  72. package/dist/cli/help.d.mts.map +1 -1
  73. package/dist/cli/help.mjs +31 -1
  74. package/dist/cli/help.mjs.map +1 -1
  75. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  76. package/dist/cli/install/legacy-paths.mjs +2 -0
  77. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  78. package/dist/cli/produce/blind-probe.d.mts +85 -0
  79. package/dist/cli/produce/blind-probe.d.mts.map +1 -0
  80. package/dist/cli/produce/blind-probe.mjs +217 -0
  81. package/dist/cli/produce/blind-probe.mjs.map +1 -0
  82. package/dist/cli/produce/claim.d.mts +188 -0
  83. package/dist/cli/produce/claim.d.mts.map +1 -0
  84. package/dist/cli/produce/claim.mjs +518 -0
  85. package/dist/cli/produce/claim.mjs.map +1 -0
  86. package/dist/cli/produce/done-gate.d.mts +87 -0
  87. package/dist/cli/produce/done-gate.d.mts.map +1 -0
  88. package/dist/cli/produce/done-gate.mjs +200 -0
  89. package/dist/cli/produce/done-gate.mjs.map +1 -0
  90. package/dist/cli/produce/events.d.mts +77 -0
  91. package/dist/cli/produce/events.d.mts.map +1 -0
  92. package/dist/cli/produce/events.mjs +126 -0
  93. package/dist/cli/produce/events.mjs.map +1 -0
  94. package/dist/cli/produce/evidence-oracle.d.mts +63 -0
  95. package/dist/cli/produce/evidence-oracle.d.mts.map +1 -0
  96. package/dist/cli/produce/evidence-oracle.mjs +122 -0
  97. package/dist/cli/produce/evidence-oracle.mjs.map +1 -0
  98. package/dist/cli/produce/ledger.d.mts +140 -0
  99. package/dist/cli/produce/ledger.d.mts.map +1 -0
  100. package/dist/cli/produce/ledger.mjs +272 -0
  101. package/dist/cli/produce/ledger.mjs.map +1 -0
  102. package/dist/cli/produce/probe-family.d.mts +53 -0
  103. package/dist/cli/produce/probe-family.d.mts.map +1 -0
  104. package/dist/cli/produce/probe-family.mjs +160 -0
  105. package/dist/cli/produce/probe-family.mjs.map +1 -0
  106. package/dist/cli/produce/projection.d.mts +55 -0
  107. package/dist/cli/produce/projection.d.mts.map +1 -0
  108. package/dist/cli/produce/projection.mjs +97 -0
  109. package/dist/cli/produce/projection.mjs.map +1 -0
  110. package/dist/cli/produce/run-id.d.mts +42 -0
  111. package/dist/cli/produce/run-id.d.mts.map +1 -0
  112. package/dist/cli/produce/run-id.mjs +79 -0
  113. package/dist/cli/produce/run-id.mjs.map +1 -0
  114. package/dist/cli/produce/saga.d.mts +180 -0
  115. package/dist/cli/produce/saga.d.mts.map +1 -0
  116. package/dist/cli/produce/saga.mjs +290 -0
  117. package/dist/cli/produce/saga.mjs.map +1 -0
  118. package/dist/cli/produce/scheduler.d.mts +165 -0
  119. package/dist/cli/produce/scheduler.d.mts.map +1 -0
  120. package/dist/cli/produce/scheduler.mjs +399 -0
  121. package/dist/cli/produce/scheduler.mjs.map +1 -0
  122. package/dist/cli/produce/setpoint.d.mts +52 -0
  123. package/dist/cli/produce/setpoint.d.mts.map +1 -0
  124. package/dist/cli/produce/setpoint.mjs +113 -0
  125. package/dist/cli/produce/setpoint.mjs.map +1 -0
  126. package/dist/cli/produce/verification-ttl.d.mts +75 -0
  127. package/dist/cli/produce/verification-ttl.d.mts.map +1 -0
  128. package/dist/cli/produce/verification-ttl.mjs +169 -0
  129. package/dist/cli/produce/verification-ttl.mjs.map +1 -0
  130. package/dist/cli/release-notes/ship-autodraft.mjs +2 -2
  131. package/dist/cli/roadmap/{conductor-view.d.mts → showrunner-view.d.mts} +3 -3
  132. package/dist/cli/roadmap/showrunner-view.d.mts.map +1 -0
  133. package/dist/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +7 -7
  134. package/dist/cli/roadmap/showrunner-view.mjs.map +1 -0
  135. package/dist/cli/variant/gallery.d.mts.map +1 -1
  136. package/dist/cli/variant/gallery.mjs +7 -3
  137. package/dist/cli/variant/gallery.mjs.map +1 -1
  138. package/dist/plugin/.claude-plugin/plugin.json +2 -1
  139. package/dist/plugin/agents/apt-executor.md +6 -0
  140. package/dist/plugin/agents/apt-planner.md +3 -2
  141. package/dist/plugin/skills/apt/SKILL.md +112 -38
  142. package/dist/plugin/skills/apt-close-task/SKILL.md +2 -2
  143. package/dist/plugin/skills/apt-debug/SKILL.md +22 -24
  144. package/dist/plugin/skills/apt-execute/SKILL.md +35 -26
  145. package/dist/plugin/skills/apt-fan-out/SKILL.md +4 -4
  146. package/dist/plugin/skills/apt-handoff/SKILL.md +1 -1
  147. package/dist/plugin/skills/apt-mockup/SKILL.md +1 -1
  148. package/dist/plugin/skills/apt-plan/SKILL.md +5 -5
  149. package/dist/plugin/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
  150. package/dist/plugin/skills/apt-produce/SKILL.md +606 -0
  151. package/dist/plugin/skills/apt-quick/SKILL.md +27 -33
  152. package/dist/plugin/skills/apt-review/SKILL.md +14 -11
  153. package/dist/plugin/skills/apt-run/SKILL.md +132 -3
  154. package/dist/plugin/skills/apt-ship/SKILL.md +29 -5
  155. package/dist/plugin/skills/apt-spar/SKILL.md +5 -3
  156. package/dist/plugin/skills/apt-watch-ci/SKILL.md +6 -4
  157. package/dist/schemas/feature-registry.d.ts.map +1 -1
  158. package/dist/schemas/feature-registry.js +34 -3
  159. package/dist/schemas/feature-registry.js.map +1 -1
  160. package/dist/types/config.d.ts +8 -5
  161. package/dist/types/config.d.ts.map +1 -1
  162. package/package.json +4 -4
  163. package/prompts/{conductor-framework-context.md → showrunner-framework-context.md} +1 -1
  164. package/prompts/{conductor-status-check.md → showrunner-status-check.md} +1 -1
  165. package/prompts/{conductor-sub-agent.md → showrunner-sub-agent.md} +6 -6
  166. package/prompts/{conductor-system.md → showrunner-system.md} +8 -8
  167. package/skills/apt/SKILL.md +112 -38
  168. package/skills/apt-close-task/SKILL.md +2 -2
  169. package/skills/apt-debug/SKILL.md +22 -24
  170. package/skills/apt-execute/SKILL.md +35 -26
  171. package/skills/apt-fan-out/SKILL.md +4 -4
  172. package/skills/apt-handoff/SKILL.md +1 -1
  173. package/skills/apt-mockup/SKILL.md +1 -1
  174. package/skills/apt-plan/SKILL.md +5 -5
  175. package/skills/apt-plan/adapters/{conductor.md → showrunner.md} +16 -16
  176. package/skills/apt-produce/SKILL.md +606 -0
  177. package/skills/apt-quick/SKILL.md +27 -33
  178. package/skills/apt-review/SKILL.md +14 -11
  179. package/skills/apt-run/SKILL.md +132 -3
  180. package/skills/apt-ship/SKILL.md +29 -5
  181. package/skills/apt-spar/SKILL.md +5 -3
  182. package/skills/apt-watch-ci/SKILL.md +6 -4
  183. package/src/cli/artifacts/self-stage.mjs +2 -1
  184. package/src/cli/cli-wrappers/features-reconcile.mjs +9 -0
  185. package/src/cli/commands/ci-watch.mjs +51 -2
  186. package/src/cli/commands/commit.mjs +3 -3
  187. package/src/cli/commands/event.mjs +16 -16
  188. package/src/cli/commands/features-reconcile.mjs +157 -0
  189. package/src/cli/commands/health-check.mjs +2 -2
  190. package/src/cli/commands/merge-integrate.mjs +3 -3
  191. package/src/cli/commands/produce.mjs +1466 -0
  192. package/src/cli/commands/task.mjs +482 -285
  193. package/src/cli/coordination/auto-emit-artifact-ready.mjs +5 -5
  194. package/src/cli/coordination/event-schema.d.ts +4 -2
  195. package/src/cli/coordination/event-schema.mjs +276 -21
  196. package/src/cli/coordination/store.mjs +4 -4
  197. package/src/cli/dispatch.mjs +4 -2
  198. package/src/cli/features/area-shape.mjs +140 -0
  199. package/src/cli/features/delta.mjs +625 -0
  200. package/src/cli/features/reconcile.mjs +1169 -0
  201. package/src/cli/features/surface-map.mjs +192 -0
  202. package/src/cli/features/write-root.mjs +140 -0
  203. package/src/cli/gate/gates/features-reconciled.mjs +70 -0
  204. package/src/cli/gate/gates/index.mjs +1 -0
  205. package/src/cli/help.mjs +31 -1
  206. package/src/cli/install/legacy-paths.mjs +2 -0
  207. package/src/cli/produce/blind-probe.mjs +245 -0
  208. package/src/cli/produce/claim.mjs +543 -0
  209. package/src/cli/produce/done-gate.mjs +238 -0
  210. package/src/cli/produce/events.mjs +131 -0
  211. package/src/cli/produce/evidence-oracle.mjs +133 -0
  212. package/src/cli/produce/ledger.mjs +284 -0
  213. package/src/cli/produce/probe-family.mjs +168 -0
  214. package/src/cli/produce/projection.mjs +105 -0
  215. package/src/cli/produce/run-id.mjs +84 -0
  216. package/src/cli/produce/saga.mjs +303 -0
  217. package/src/cli/produce/scheduler.mjs +423 -0
  218. package/src/cli/produce/setpoint.mjs +122 -0
  219. package/src/cli/produce/verification-ttl.mjs +191 -0
  220. package/src/cli/release-notes/ship-autodraft.mjs +2 -2
  221. package/src/cli/roadmap/showrunner-view.d.ts +10 -0
  222. package/src/cli/roadmap/{conductor-view.mjs → showrunner-view.mjs} +6 -6
  223. package/src/cli/variant/gallery.mjs +7 -3
  224. package/templates/aperant-claude-md-appendix.md +2 -2
  225. package/workflows/scan-features.md +17 -11
  226. package/dist/cli/cli-wrappers/features-audit.d.mts +0 -2
  227. package/dist/cli/cli-wrappers/features-audit.d.mts.map +0 -1
  228. package/dist/cli/cli-wrappers/features-audit.mjs +0 -8
  229. package/dist/cli/cli-wrappers/features-audit.mjs.map +0 -1
  230. package/dist/cli/commands/features-audit.d.mts.map +0 -1
  231. package/dist/cli/commands/features-audit.mjs +0 -293
  232. package/dist/cli/commands/features-audit.mjs.map +0 -1
  233. package/dist/cli/features/registry-audit.d.mts +0 -56
  234. package/dist/cli/features/registry-audit.d.mts.map +0 -1
  235. package/dist/cli/features/registry-audit.mjs +0 -264
  236. package/dist/cli/features/registry-audit.mjs.map +0 -1
  237. package/dist/cli/roadmap/conductor-view.d.mts.map +0 -1
  238. package/dist/cli/roadmap/conductor-view.mjs.map +0 -1
  239. package/src/cli/cli-wrappers/features-audit.mjs +0 -8
  240. package/src/cli/commands/features-audit.mjs +0 -302
  241. package/src/cli/features/registry-audit.mjs +0 -254
  242. package/src/cli/roadmap/conductor-view.d.ts +0 -10
@@ -29,7 +29,7 @@ Execute a small task quickly without full pipeline overhead. For small fixes, do
29
29
  - **Working directory:** The project root (where you were invoked) UNLESS an active task has a task-level worktree (see below).
30
30
  - **Constitution:** Read `AGENTS.md` in the project root if it exists
31
31
  - **State directory:** `.aperant/quick/{task-id}/`
32
- - **Task-level worktree isolation:** Use the `worktree_path` the router passed in skill context (router path) OR that §1a parsed from `task create`'s envelope (direct path) — this is the worktree `task create` literally just provisioned for this task. When present, run all editing Bash commands with `cd {worktree_path} &&` prefix so the fix lands on the task branch. `apt-tools` calls still take the project root as `<project-dir>` so they coordinate through the main repo's shared `.aperant/`. The quick task's `.aperant/quick/{task-id}/` directory lives in the main repo, not the worktree. (Last-resort fallback only: if neither source supplied a `worktree_path` but `.aperant/state.json` has an active task with one, you may use that.)
32
+ - **Task-level worktree isolation:** Use the `worktree_path` the router passed in skill context (router path) OR that §1a parsed from `task ensure`'s envelope (direct path) — this is the worktree `task ensure` literally just provisioned for this task. When present, run all editing Bash commands with `cd {worktree_path} &&` prefix so the fix lands on the task branch. `apt-tools` calls still take the project root as `<project-dir>` so they coordinate through the main repo's shared `.aperant/`. The quick task's `.aperant/quick/{task-id}/` directory lives in the main repo, not the worktree. (Last-resort fallback only: if neither source supplied a `worktree_path` but `.aperant/state.json` has an active task with one, you may use that.)
33
33
  </your_environment>
34
34
 
35
35
  <state_files>
@@ -54,35 +54,27 @@ Extract the task description from `$ARGUMENTS`.
54
54
 
55
55
  ### 1a. Resolve canonical task id (idempotent)
56
56
 
57
- QUICK now produces a canonical state.active_tasks record so `/apt:ship` can find the task via the lite ship profile. The body owns idempotency because `apt-tools task create` does NOT guard against existing ids (see spec §3 R8).
57
+ QUICK now produces a canonical state.active_tasks record so `/apt:ship` can find the task via the lite ship profile. Idempotency is owned by the deterministic allocator `apt-tools task ensure --intent create-new` (NOT raw `task create`) re-running returns the SAME task + worktree (`reused: true`), so the old `task get` guard dance is gone.
58
58
 
59
59
  Two invocation paths converge here:
60
60
 
61
- - **Router path** (`/apt` → `/apt:quick`): the router has already called `task create` and injected `task_id` into your skill context.
62
- - **Direct path** (`/apt:quick foo`): no `task_id` in context — you create one now.
63
-
64
- Sequence:
61
+ - **Router path** (`/apt` → `/apt:quick`): the router has already run `task ensure --intent create-new` and injected `task_id` (+ `worktree_path`) into your skill context. Re-affirm idempotently with the same id:
62
+ ```bash
63
+ apt-tools task ensure . --description "$ARGUMENTS" --intent create-new --track QUICK --id {task_id}
64
+ ```
65
+ The `--id {task_id}` makes ensure resolve to the EXACT record the router just provisioned (`reused: true`) — no second task, no second worktree.
65
66
 
66
- 1. **If `task_id` is present in skill context** (router path):
67
- ```bash
68
- apt-tools task get . --id {task_id}
69
- ```
70
- - If exit 0 AND the returned record has `track === "QUICK"` reuse, skip the create call.
71
- - Else (record missing OR wrong track) → call:
72
- ```bash
73
- apt-tools task create . --description "$ARGUMENTS" --track QUICK --id {task_id}
74
- ```
75
- Parse `task_id` from the returned envelope (it will match the id you passed).
67
+ - **Direct path** (`/apt:quick foo`): no `task_id` in context allocate now:
68
+ ```bash
69
+ apt-tools task ensure . --description "$ARGUMENTS" --intent create-new --track QUICK
70
+ ```
71
+ ensure is keyed on the normalized description + scope, so a retry returns the SAME canonical `{slug}_YY-MM-DD` `task_id`.
76
72
 
77
- 2. **If no `task_id` in skill context** (direct path):
78
- ```bash
79
- apt-tools task create . --description "$ARGUMENTS" --track QUICK
80
- ```
81
- Parse the generated `task_id` from the envelope — it will be the canonical `{slug}_YY-MM-DD` shape.
73
+ Parse `task_id` from the returned envelope.
82
74
 
83
75
  The task id is now canonical (no more `quick-YYYYMMDD-*` invention). `QuickTaskSchema` accepts both the canonical `{slug}_YY-MM-DD` form and the legacy `quick-YYYYMMDD-{slug}` form for back-compat with already-shipped task records on disk.
84
76
 
85
- **Worktree isolation (both paths).** `task create` provisions a worktree when `task_isolation.worktree_per_task` is enabled (track-agnostic — QUICK gets one too). Parse `worktree.worktree_path`, `worktree.branch`, and `worktree.base_branch` from the `task create` envelope (direct path); on the router path the orchestrator already passed `worktree_path` into your skill context — use that. When a `worktree` block is present, print the banner and run all subsequent editing Bash commands with `cd {worktree_path} &&`:
77
+ **Worktree isolation (both paths).** `task ensure --intent create-new` provisions a worktree when `task_isolation.worktree_per_task` is enabled (track-agnostic — QUICK gets one too). Parse `worktree.worktree_path`, `worktree.branch`, and `worktree.base_branch` from the `task ensure` envelope (direct path); on the router path the orchestrator already passed `worktree_path` into your skill context — use that. When a `worktree` block is present, print the banner and run all subsequent editing Bash commands with `cd {worktree_path} &&`:
86
78
 
87
79
  ```
88
80
  [APT] Working in isolated worktree: {worktree_path}
@@ -173,7 +165,7 @@ Show the affected files briefly before proceeding (5-second delay; user can inte
173
165
  Make the changes directly:
174
166
  - Follow existing code patterns and conventions
175
167
  - Keep changes minimal — solve the stated problem, nothing more
176
- - If touching code with tests, run the tests to make sure nothing breaks
168
+ - If touching tested code, run those tests
177
169
 
178
170
  ## 5. Verify (Lightweight)
179
171
 
@@ -183,7 +175,7 @@ Run a quick sanity check appropriate to the change:
183
175
  pnpm typecheck 2>&1 | tail -20
184
176
  ```
185
177
  - **Config change:** Validate the config is syntactically correct
186
- - **Doc change:** No verification needed unless `--verify` flag is set
178
+ - **Doc change:** none unless `--verify` is set
187
179
  - **Style change:** Run lint on changed files
188
180
 
189
181
  If visual verification is performed via MCP screenshots:
@@ -193,24 +185,26 @@ If visual verification is performed via MCP screenshots:
193
185
  If verification fails:
194
186
  - Fix the issue
195
187
  - Re-run verification
196
- - If stuck after 2 attempts, report the failure and let the user decide
188
+ - If stuck after 2 attempts, report and let the user decide
197
189
 
198
190
  ## 6. Commit
199
191
 
200
- Create an atomic commit with a descriptive message:
192
+ Create an atomic commit:
201
193
 
202
194
  ```bash
203
195
  git add {changed-files}
204
196
  git commit -m "{type}: {description}"
205
197
  ```
206
198
 
207
- Use appropriate conventional commit type:
208
- - `fix:` for bug fixes
209
- - `docs:` for documentation
210
- - `style:` for formatting/style
211
- - `chore:` for config, dependencies, maintenance
212
- - `refactor:` for code restructuring
213
- - `feat:` for small features (rare for quick tasks)
199
+ Use a conventional commit type: `fix:` / `docs:` / `style:` / `chore:` / `refactor:` / `feat:` (rare for quick tasks).
200
+
201
+ After the commit, emit the registry delta (one non-blocking command):
202
+
203
+ ```bash
204
+ node packages/framework/bin/apt-tools.mjs features-reconcile . --draft --task-id {task-id} || true
205
+ ```
206
+
207
+ Stage `.aperant/features/deltas/` with the commit; fill any `needs-disposition` field (usually `no-semantic-change` + a one-line reason).
214
208
 
215
209
  ## 7. Record Task
216
210
 
@@ -146,8 +146,8 @@ AGENTS.md, READMEs, docs/**). It is **inline** in the reviewer brief — a
146
146
  grep workload that does not justify a separate agent spawn.
147
147
 
148
148
  This pass drives two CLI verbs: `apt-tools docs-audit` (external +
149
- internal drift detection) and `apt-tools features-audit` (registry
150
- coverage). Both emit JSON; the reviewer buckets by policy.
149
+ internal drift detection) and `apt-tools features-reconcile --check`
150
+ (registry coverage). Both emit JSON; the reviewer buckets by policy.
151
151
 
152
152
  1. Run the docs-drift audit against the task's diff:
153
153
 
@@ -159,23 +159,26 @@ coverage). Both emit JSON; the reviewer buckets by policy.
159
159
  Capture the `findings[]` (for `flag-drift` surfaces) and `patch_plan[]`
160
160
  (for `auto-update` surfaces).
161
161
 
162
- 2. Run the features-registry audit in report-only mode:
162
+ 2. Run the features-registry reconcile check in report-only mode:
163
163
 
164
164
  ```bash
165
- node packages/framework/bin/apt-tools.mjs features-audit . \
166
- --since <task-base-ref> --format json
165
+ node packages/framework/bin/apt-tools.mjs features-reconcile . \
166
+ --check --warn-only --base <task-base-ref>
167
167
  ```
168
168
 
169
- The executor post-step in `/apt:execute` already applies stubs for
170
- `auto-update` surfaces; this run catches anything the executor missed
171
- (e.g. stubs were generated but the user's policy opted out, or the
172
- executor skipped the post-step on a blocked subtask).
169
+ The executor's `/apt:execute` §3e-features delta-emit already recorded
170
+ this task's registry deltas; this run catches anything the executor
171
+ missed (an uncovered qualifying file, a stale fingerprint after a
172
+ re-edit, a delta still carrying `needs-disposition`). The repair the
173
+ reviewer surfaces is `features-reconcile . --draft --task-id <id>`
174
+ (then fill dispositions) — never a hand-authored area edit.
173
175
 
174
176
  3. **Policy split — critical:**
175
177
  - **auto-update findings** are FIXED inline via the fix-review loop. The
176
178
  reviewer applies the patch via the matching `apt-tools` subcommand
177
- (`features-audit --apply-stubs`, `roadmap rollup`, registry rewriter).
178
- These land in iterations 1–2 of the fix loop.
179
+ (`features-reconcile --draft` + fill dispositions + `--write`,
180
+ `roadmap rollup`, registry rewriter). These land in iterations 1–2 of
181
+ the fix loop.
179
182
  - **flag-drift findings** are SURFACED only. They appear in
180
183
  `review_findings.md` with category `docs-drift`, severity `warning`,
181
184
  and the full shape
@@ -17,7 +17,7 @@ execution_modes:
17
17
  - plan-mode
18
18
  - plan-only
19
19
  allowed-tools: "Bash, Read, Write, Edit, Grep, Glob, Task"
20
- argument-hint: "apt:run [task description] [--skip-review] [--phase-mode auto|agent-team|sub-agents|sequential] [--spar-gates plan[,execute]]"
20
+ argument-hint: "apt:run [task description] [--skip-review] [--phase-mode auto|agent-team|sub-agents|sequential] [--spar-gates plan[,execute]] [--full]"
21
21
  gates:
22
22
  - constitution-read
23
23
  - constitution-coverage
@@ -29,6 +29,8 @@ config_keys:
29
29
  Run the full Aperant pipeline: plan a task, execute all subtasks, verify the implementation, and optionally review the code. This is the one-command experience — from task description to verified, reviewed code.
30
30
 
31
31
  As of C32 the STANDARD and DEEP auto pipelines **terminate on review** (`plan → execute → verify → review`). Pass `--skip-review` to stop after verify; for trivial work the QUICK track still skips planning entirely.
32
+
33
+ Pass `--full` to carry a SINGLE task all the way to **merged + green**: it extends the pipeline past review through **ship** (a PR that auto-merges to main on green — never a direct push) and **watch-CI** (arm the watcher with auto-merge so the change lands once CI passes — the merge is performed by `/apt:watch-ci` alone, never a direct `gh pr merge`). `--full` is a thin chain over the existing `/apt:ship` + `/apt:watch-ci` skills — it forces review ON and is hard-guarded by `autonomy.allow_yolo` plus a one-time confirm (§1a). A `/apt:run` invocation WITHOUT `--full` behaves exactly as today (terminates on review).
32
34
  </objective>
33
35
 
34
36
  <your_environment>
@@ -58,7 +60,7 @@ As of C32 the STANDARD and DEEP auto pipelines **terminate on review** (`plan
58
60
 
59
61
  1. Read `AGENTS.md` if it exists
60
62
  2. Parse task description from `$ARGUMENTS` (everything before flags)
61
- 3. Parse flags: `--skip-review`, `--dry-run`, `--phase-mode <mode>`, `--spar-gates <comma-list>`.
63
+ 3. Parse flags: `--skip-review`, `--dry-run`, `--phase-mode <mode>`, `--spar-gates <comma-list>`, `--full`.
62
64
  - `--spar-gates <plan|execute|plan,execute>` (FRAMEWORK-RFC-001) — comma-separated stage list to auto-fire `/apt:spar` after. Per-invocation override of `.aperant/config.local.json` `spar.enabled`. On QUICK track, print the verbatim hard-reject line and discard the flag (Fast Path Guarantee — CLAUDE.md):
63
65
 
64
66
  ```
@@ -71,6 +73,52 @@ As of C32 the STANDARD and DEEP auto pipelines **terminate on review** (`plan
71
73
  node packages/framework/bin/apt-tools.mjs state .
72
74
  ```
73
75
 
76
+ ## 1a. `--full` flag — surface + gates
77
+
78
+ This section runs ONLY when `--full` was parsed in §1. When `--full` is absent, skip this entire section and run the pipeline exactly as today (manual mode is byte-behavior-unchanged).
79
+
80
+ **Contradiction handling (resolve in THIS precedence order — the "discard" cases win first, so a `--full` that is discarded never triggers the conflict or autonomy gates):**
81
+
82
+ 0. **QUICK track wins first (Fast Path Guarantee).** If the task is QUICK track, discard `--full` with the Fast-Path line (item 4 below) and run the QUICK one-shot path unchanged — do NOT evaluate the `--skip-review` conflict (item 1) or the autonomy gate. On QUICK, `--full` is treated as never passed.
83
+
84
+ 1. **`--full` + `--skip-review` → hard reject.** `--full` requires review before auto-ship, so the two flags are contradictory. Do NOT silently let one win — print the verbatim line and exit:
85
+
86
+ ```
87
+ [apt:run] --full and --skip-review conflict (--full requires review before auto-ship). Pick one.
88
+ ```
89
+
90
+ 2. **`--full` IMPLIES review ON.** Treat `--skip-review` as never set for the rest of the run; §6 Review always executes.
91
+
92
+ 3. **`--full` + `--dry-run` → dry-run wins.** Run the plan stage only and report (the existing §3 dry-run exit), then stop. No execute, no ship — `--full` is discarded for this run.
93
+
94
+ 4. **QUICK track → discard `--full` with the Fast-Path line.** On QUICK track `--full` is hard-exempt (CLAUDE.md Fast Path Guarantee). Print the verbatim line and run the QUICK one-shot path unchanged:
95
+
96
+ ```
97
+ [apt:run] --full ignored for QUICK track (Fast Path Guarantee)
98
+ ```
99
+
100
+ `--full` composes normally with `--phase-mode` and `--spar-gates`.
101
+
102
+ **Autonomy gate (load-bearing safety valve, ID-03):**
103
+
104
+ Auto-ship + auto-merge is YOLO-class. Read `.aperant/config.json` for `autonomy.allow_yolo` (boolean) and the autonomy `level` (0–3).
105
+
106
+ 1. **`allow_yolo` hard guard.** If `autonomy.allow_yolo !== true`, STOP before ship with the verbatim line and leave the task at `reviewing` (fully shippable by hand):
107
+
108
+ ```
109
+ [apt:run] --full needs autonomy.allow_yolo=true (auto-ship + auto-merge to main). Enable via /apt:setup or drop --full.
110
+ ```
111
+
112
+ 2. **One-time confirm at autonomy < 3.** Before opening the auto-merging PR (just before §6.1 Ship below), emit ONE confirmation when autonomy `level < 3` AND `--yolo` was not also passed:
113
+
114
+ ```
115
+ [apt:run --full] About to open a PR that auto-merges to main once CI is green. Proceed? [y/N]
116
+ ```
117
+
118
+ At autonomy 3 OR when `--yolo` is passed, degrade to silent (mirrors `/apt:ship`'s autonomy-3 degrade). On `N` / empty, STOP after review with the standard `/apt:ship` hand-off hint — the task is left at `reviewing`, fully shippable by hand.
119
+
120
+ Note: the `allow_yolo` guard + the one-time confirm are evaluated up front here (parse-time gating) and the confirm is RE-SURFACED at the ship boundary (§6.1) so the user confirms immediately before the irreversible auto-merge arm. Review always runs first, and auto-merge always waits for green.
121
+
74
122
  ## 1b. Resolve Orchestration Mode
75
123
 
76
124
  Run reconcile to determine the effective orchestration strategy for this pipeline run. Pass the task's track via `--track <quick|standard|deep>` so per-track defaults from `.aperant/config.json:orchestration.per_track` apply (roundtable 2026-05-14 R7):
@@ -338,6 +386,64 @@ Skip on `spar.enabled === true` (no pre-ship gate exists in v2 — see spec §8
338
386
 
339
387
  **This is the task review, not the PR review.** It runs inline without sub-agents. For heavy multi-agent PR review, use `/apt:pr-review` separately.
340
388
 
389
+ ## 6.1. Stage 5 — Ship (apt:ship) — `--full` only
390
+
391
+ **Run this section ONLY when `--full` was parsed (§1a) AND review passed** — "review passed" means the §6 review `assessment` is `approve`; a `request-changes` assessment STOPS here (task left at `reviewing`, no ship — see the stop-condition table in §6.2). When `--full` is absent, skip §6.1 + §6.2 entirely and go straight to §7 (manual mode — terminates on review).
392
+
393
+ Pipeline order note: the user's phrasing was *"review, verify"* but `/apt:run` runs **verify (§5) → review (§6) → ship (§6.1)**. KEEP this order — verify gates review, and review consumes `qa_signoff.json`. Do NOT silently reorder. `--full` runs `plan → execute → verify → review → ship → watch-ci`.
394
+
395
+ **Pre-ship gate (re-surface the §1a confirm at the boundary):**
396
+
397
+ 1. Re-check `autonomy.allow_yolo === true` (already validated in §1a; re-read here so a mid-run config edit cannot slip an auto-merge past the guard). If false, STOP with the §1a `allow_yolo` line; leave the task at `reviewing`.
398
+ 2. Emit the §1a one-time confirm (`[apt:run --full] About to open a PR that auto-merges to main once CI is green. Proceed? [y/N]`) when autonomy `level < 3` and `--yolo` was not passed. At autonomy 3 / `--yolo`, degrade to silent. On `N` / empty, STOP after review with the standard `/apt:ship` hand-off hint; the task stays at `reviewing`.
399
+
400
+ **Ship (Option A — PR that auto-merges to main on green; NEVER a direct push/merge):**
401
+
402
+ Invoke `/apt:ship` inline. It runs its own hard-gate (verify-approved / review-clean / consistency / gitignore), opens the PR against the task's recorded `base_branch` (main for a task forked from main), and atomically flips `reviewing → shipped-pending-merge` via `task update --pr-url` — which also arms the post-ship watcher per `ci_watch.after_ship`. `--full` MUST NEVER `git push`/`git merge` directly to main (ID-02 Option B is rejected unconditionally): "ship to main" means **a PR that auto-merges to main on green**, not a force-push. The merge itself is performed EXCLUSIVELY by `/apt:watch-ci` (§6.2, ID-10) — `--full` MUST NEVER run `gh pr merge` (with or without `--auto`) nor enable GitHub native auto-merge.
403
+
404
+ Capture the opened PR number `{N}` from the `/apt:ship` result for §6.2.
405
+
406
+ If `/apt:ship`'s hard-gate fails, or the branch is behind and the rebase conflicts with no `resolve_merge_conflicts`, STOP — no PR is opened and the task stays at `reviewing` (see the stop-condition table below).
407
+
408
+ ## 6.2. Stage 6 — Watch-CI arm (auto-merge-on-green) — `--full` only
409
+
410
+ After the PR opens, force auto-merge for THIS run regardless of the config default (`ci_watch.auto_merge_on_green` is `false` by default per the D-08 kill-criteria). `/apt:ship` already armed the watcher via `ci_watch.after_ship`; this call PATCHES that already-armed watch's auto-merge flag to `true` (it does NOT reimplement arming and is idempotent):
411
+
412
+ ```bash
413
+ node packages/framework/bin/apt-tools.mjs ci-watch start . --pr {N} --task-id {task-id} --host {cli} --auto-merge-on-green
414
+ ```
415
+
416
+ > **ID-10 — `/apt:watch-ci` is the SOLE merge authority (hard guardrail).**
417
+ > The auto-merge is performed EXCLUSIVELY by `/apt:watch-ci`: its §4 green branch runs a plain `gh pr merge {N} --squash` — NEVER `--auto` — only after its `allGreen` classifier confirms every check is terminal-green.
418
+ > `--full` (and `/apt:ship`) MUST NEVER itself run `gh pr merge` — with or without `--auto`/`--squash` — nor enable GitHub native auto-merge.
419
+ > Rationale: this repo has no required status checks, so `gh pr merge --auto` degrades to an immediate merge — it would land the PR before CI can turn it red (the exact bug this guardrail prevents).
420
+ > After ship, the ONLY merge-capable dispatch is invoking `/apt:watch-ci --tick --pr {N}` (below) and letting the watcher decide; you do NOT merge here.
421
+
422
+ **Branch on host cron capability.** Run host-detect and read `host_capabilities.cron`:
423
+
424
+ ```bash
425
+ node packages/framework/bin/apt-tools.mjs host-detect .
426
+ ```
427
+
428
+ - **cron-capable host** (e.g. Claude Code, `cron: true`): the watcher is armed with auto-merge ON; hand the merge to `/apt:watch-ci` — register a recurring `CronCreate` whose payload is `/apt:watch-ci --tick --pr {N}` (per `/apt:watch-ci` §3), then invoke `/apt:watch-ci --tick --pr {N}` once now to run the first (still-waiting) tick. Then **EXIT — do NOT loop** (respect `/apt:watch-ci`'s single-execution-per-invocation contract). The cron beat drives `/apt:watch-ci` to merged + green unattended, and its §4 green branch performs the green-gated squash-merge — you never merge from here. Report: watcher armed, auto-merge ON, and the deadline.
429
+ - **non-cron host** (Codex / Gemini / OpenCode): truly-unattended watching is impossible. Arm the watch state + auto-merge (the `ci-watch start --auto-merge-on-green` above) but do NOT impersonate a scheduler — NEVER fake a `while` / `sleep` loop. Print the honest manual-tick instruction:
430
+
431
+ ```
432
+ [apt:run --full] PR opened + CI watcher state created (host has no cron). Advance manually: /apt:watch-ci --tick --pr {N}. Auto-merge-on-green is set; the merge fires on the first green tick you run.
433
+ ```
434
+
435
+ **Stop conditions (every gate is reused; each STOP leaves the task in its current lifecycle state and NEVER merges). `--full` adds NO new gate — it only chains the existing ones and surfaces the stop reason in §7:**
436
+
437
+ | Stop point | Resulting state |
438
+ |---|---|
439
+ | QA `rejected` after max iters (§5) | `verifying`; no ship |
440
+ | Review `request-changes` (§6) | `reviewing`; no ship |
441
+ | Ship hard-gate fail (verify-approved / review-clean / consistency / gitignore) | `reviewing`; no PR |
442
+ | Branch behind + rebase conflict (no `resolve_merge_conflicts`) | `reviewing`; no PR |
443
+ | `allow_yolo=false` or confirm `N` (§1a / §6.1) | `reviewing`; no PR |
444
+ | CI red after 5-attempt / 4h-wall (watcher) | `shipped-pending-merge`; PR comment, NOT merged |
445
+ | Merge conflict mid-watch (`diverged-bailed`) | `shipped-pending-merge`; PR comment, NOT merged |
446
+
341
447
  ## 7. Pipeline Summary
342
448
 
343
449
  Render the phase rail panel verbatim — branch glyphs `┌─ │ └─`, status glyphs `✓` (done) / `●` (active) / `○` (pending/skipped), inline metrics per row drawn from the artifacts written across §3–§6:
@@ -359,7 +465,18 @@ Substitute live values from the on-disk artifacts: `build-progress.json.complete
359
465
  **Always end with a "What's Next" recommendation:**
360
466
 
361
467
  ```
362
- {If review assessment is "approve" and QA approved:}
468
+ {If --full ran and the PR opened (cron host):}
469
+ -> Shipped. PR #{N} opened; CI watcher armed with auto-merge-on-green (deadline {deadline}).
470
+ The cron beat drives it to merged + green. /apt:close-task runs post-merge.
471
+
472
+ {If --full ran and the PR opened (non-cron host):}
473
+ -> Shipped. PR #{N} opened; watcher state created with auto-merge-on-green.
474
+ Advance manually: /apt:watch-ci --tick --pr {N} (merge fires on the first green tick).
475
+
476
+ {If --full was requested but a gate STOPPED before ship:}
477
+ -> {stop reason}. Task left at {lifecycle state}, not merged. {remediation per the stop-condition table}
478
+
479
+ {If review assessment is "approve" and QA approved (no --full):}
363
480
  -> Recommended: /apt:ship — create PR for this task
364
481
  Also: /apt:pr-review (deep multi-agent review) | manual review
365
482
 
@@ -388,5 +505,17 @@ atomic `reviewing → shipped-pending-merge` flip. `/apt:ship` then flips
388
505
  does not need to record or drain anything beyond ensuring each child-skill
389
506
  stage runs to its success-end.
390
507
 
508
+ **`--full` full lifecycle map:** `planning → executing → verifying → reviewing
509
+ → shipped-pending-merge → (CI green + merged) → completed`. The `reviewing →
510
+ shipped-pending-merge` flip is done atomically by ship's `task update --pr-url`
511
+ (§6.1). `shipped-pending-merge → completed` is done by `/apt:close-task`
512
+ post-merge — **`--full` does NOT auto-invoke `/apt:close-task`.** On cron hosts
513
+ the merge happens asynchronously AFTER `--full` has exited, so `--full` cannot
514
+ observe it; closeout is left to the existing path (the watcher's green branch
515
+ suggests `/apt:close-task`, and the user / passive sweeper runs it). Folding
516
+ close-task into `--full` would require it to become a recurring watcher —
517
+ explicitly rejected (it would duplicate the watcher and violate the
518
+ single-execution contract).
519
+
391
520
  </process>
392
521
  </output>
@@ -24,6 +24,7 @@ gates:
24
24
  - consistency-check
25
25
  - r-persona-alignment
26
26
  - gitignore-in-sync
27
+ - features-reconciled
27
28
  config_keys:
28
29
  - pipeline.auto_branch
29
30
  - pipeline.branch_prefix
@@ -54,6 +55,27 @@ Create a pull request (or publish a package) with full traceability from decisio
54
55
 
55
56
  <process>
56
57
 
58
+ ## 0.0 Materialize feature-registry deltas
59
+
60
+ BEFORE the hard-gate check runs (write-then-verify: the `features-reconciled` gate in Section 0 verifies what this step wrote), materialize any pending feature-registry deltas into the area JSONs + a durable receipt:
61
+
62
+ ```bash
63
+ ship_cwd=$(node packages/framework/bin/apt-tools.mjs task get . --id {task-id} | jq -r '.task.worktree_path // empty')
64
+ ship_cwd=${ship_cwd:-.}
65
+ node packages/framework/bin/apt-tools.mjs features-reconcile "$ship_cwd" --write --task-id {task-id}
66
+ ```
67
+
68
+ Handle the envelope:
69
+
70
+ - **`status: "ok"` with writes** (`materialized > 0` or a non-empty `changed_paths`): the write already self-staged its committable outputs (areas + receipt + REGISTRY.md + deleted delta paths). Commit them in `ship_cwd`:
71
+ ```bash
72
+ git -C "$ship_cwd" commit -m "chore(aperant): materialize feature-registry deltas"
73
+ ```
74
+ (Skip the commit when nothing was staged — a zero-delta write only regenerates REGISTRY.md when it drifted.)
75
+ - **`status: "skip"` (`reason: "policy-opt-out"`)**: proceed — the `features-reconciled` gate reports `skip` for the same reason.
76
+ - **`status: "error"` with `kind: "hard-conflict"`**: STOP. Print the conflict report verbatim (it names BOTH writer delta files). The repair is `features-reconcile "$ship_cwd" --draft --task-id {task-id}` plus hand-fixing the conflicting operations — NEVER `--force` around this stop.
77
+ - **`status: "error"` with `kind: "invalid-deltas"`**: STOP and report — a pending delta still carries `needs-disposition` (or another validation failure); fill the dispositions and re-run.
78
+
57
79
  ## 0. Hard Gate Check
58
80
 
59
81
  Before gathering context or building any PR artifacts, run the hard-gate check for the `ship` skill:
@@ -72,7 +94,7 @@ Parse the JSON envelope:
72
94
  ```
73
95
  Exit the skill. Do NOT auto-apply `--force` — force is an explicit human decision.
74
96
 
75
- The ship gate covers constitution-read, verify-approved (qa_signoff.json verdict), review-clean (no unresolved critical/warning findings), gitignore-in-sync (.aperant/.gitignore conformance), and consistency-check (G8 — cross-artifact consistency between spec.md, implementation_plan.json, review.json, qa_signoff.json, and build-progress.json). Because these gates run here, Sections 1–3 below no longer need to re-check the verify verdict or block on review findings — the gate already did it.
97
+ The ship gate covers constitution-read, verify-approved (qa_signoff.json verdict), review-clean (no unresolved critical/warning findings), gitignore-in-sync (.aperant/.gitignore conformance), features-reconciled (feature-registry deltas materialized in Section 0.0 + coverage/schema/integrity verified — blocking on ALL profiles, QUICK/DEBUG included), and consistency-check (G8 — cross-artifact consistency between spec.md, implementation_plan.json, review.json, qa_signoff.json, and build-progress.json). Because these gates run here, Sections 1–3 below no longer need to re-check the verify verdict or block on review findings — the gate already did it.
76
98
 
77
99
  ### 0.1 Parse `profile` from the envelope
78
100
 
@@ -249,14 +271,14 @@ If `rn_enabled !== "true"`, jump to Section 3.
249
271
 
250
272
  ### 2.6.1 Compute the feature-registry diff
251
273
 
252
- The auto-draft needs to know which features the PR's commits touched. Use the same `features-audit` surface that `apt:execute` uses post-step:
274
+ The auto-draft needs to know which features the PR's commits touched. Source the diff from a read-only reconcile draft (no file is written):
253
275
 
254
276
  ```bash
255
- base=$(node packages/framework/bin/apt-tools.mjs task get . --id {task-id} | jq -r '.base_branch // "main"')
256
- feature_diff=$(node packages/framework/bin/apt-tools.mjs features-audit . --diff-since "$base" --json)
277
+ base=$(node packages/framework/bin/apt-tools.mjs task get . --id {task-id} | jq -r '.task.base_branch // "main"')
278
+ feature_diff=$(node packages/framework/bin/apt-tools.mjs features-reconcile . --draft --dry-run --base "$base" --task-id {task-id})
257
279
  ```
258
280
 
259
- The envelope shape (see `packages/framework/src/cli/commands/features-audit.mjs`) returns the list of touched features with their declared `personas: []` field (when the registry's feature row carries one).
281
+ The envelope's `delta.files[]` entries (see `packages/framework/src/cli/commands/features-reconcile.mjs`) carry each touched surface with its `area` — feed those areas to the helper below alongside the registry's declared `personas: []` fields (when the feature rows carry one).
260
282
 
261
283
  ### 2.6.2 Decide draft vs block via the helper
262
284
 
@@ -578,6 +600,8 @@ suggest_mode=$(jq -r '.pr_review.suggest_after_ship // "always"' .aperant/config
578
600
 
579
601
  ### 7.2 Post-ship /apt:watch-ci hook
580
602
 
603
+ > Cross-reference: `/apt:run --full` drives this skill's §6 PR creation + §7.2 watcher arming end-to-end (review → ship → auto-merge-on-green watch). When invoked from that chain, the watcher's auto-merge is force-enabled for the run via `apt-tools ci-watch start --auto-merge-on-green` (see `apt-run/SKILL.md` §6.1–§6.2); `/apt:ship` itself behaves identically whether invoked standalone or by `--full`.
604
+
581
605
  After Section 7.1's hint resolves (whether it ran the deep review or skipped), report or interactively arm the post-ship CI watcher. The hook is controlled by `ci_watch.after_ship` in `.aperant/config.json` (tri-state: `auto` | `ask` | `never`). The default depends on host capability — `auto` on cron-capable hosts (Claude Code, Pi), `never` elsewhere.
582
606
 
583
607
  **Skip entirely** when no PR URL was captured in Section 6 (library `npm publish`-only path — same skip rule as 7.1).
@@ -186,8 +186,8 @@ The table below shows the canonical command shape per (partner × rung); the act
186
186
  | Partner | Rung | Command | Notes |
187
187
  |---|---|---|---|
188
188
  | codex | mcp | tool call: `mcp__codex-mcp__codex({prompt, model})` where `model` is the `model` field returned by `apt-tools spar-resolve-partner --partner codex` (see §5a below). | **Demoted to LAST for codex** (see the codex walk-order note in §3) — attempt this rung only when the resolver returns `available: true`. 900000ms (15 min) timeout (configurable `apt-spar.mcp_timeout_ms`); on timeout fall through to plugin then CLI. When the resolver returns `available: false`, treat the MCP rung as UNAVAILABLE and fall through to plugin/CLI — never invent a default model (the MCP server silently substitutes a stale hardcoded default model id, which is exactly the bug we are fixing). |
189
- | codex | plugin | `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)"` | No `--model` flag — `codex-companion.mjs` invokes `codex exec` which inherits `~/.codex/config.toml` automatically. **NO `--write`. NO `--effort` override.** Per SPAR-04 — spar is conversation, not patching. |
190
- | codex | cli | `codex exec "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)"` | Precedent: `apt-pr-review/SKILL.md:1084`. No `--model` flag — `codex exec` inherits `~/.codex/config.toml` automatically. Verify with `codex --help`. |
189
+ | codex | plugin | `node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)" < /dev/null` | No `--model` flag — `codex-companion.mjs` invokes `codex exec` which inherits `~/.codex/config.toml` automatically. **NO `--write`. NO `--effort` override.** Per SPAR-04 — spar is conversation, not patching. The `< /dev/null` is load-bearing — the shim forwards to `codex exec`, which wedges on stdin EOF under a no-TTY subprocess (see the wedge note below). |
190
+ | codex | cli | `codex exec --sandbox read-only "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)" < /dev/null` | Precedent: `apt-pr-review/SKILL.md:1084`. No `--model` flag — `codex exec` inherits `~/.codex/config.toml` automatically. The `< /dev/null` un-wedges the no-TTY stdin block and `--sandbox read-only` keeps the spar read-only (see the wedge note below). Verify with `codex --help`. |
191
191
  | claude | mcp | tool call: `mcp__claude-code-mcp__claude_code({prompt})` | Preferred. Same 900000ms (15 min) timeout + fallthrough rule. |
192
192
  | claude | plugin | n/a | No plugin shim exists for Claude. Skip this rung. |
193
193
  | claude | cli | `claude -p "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)" --output-format text` | Symmetric. Claude has no `--write` equivalent — asymmetric flags are a smell. |
@@ -195,6 +195,8 @@ The table below shows the canonical command shape per (partner × rung); the act
195
195
  | gemini | plugin | n/a | No plugin shim exists for Gemini. Skip this rung. |
196
196
  | gemini | cli | `gemini "$(cat <<'APT_SPAR_PROMPT_EOF' ... APT_SPAR_PROMPT_EOF\n)"` | No `-m` flag — gemini-cli resolves model via `--model` > `GEMINI_MODEL` env > `~/.gemini/settings.json` > built-in default per `docs/cli/model-routing.md:47-58`. Drop the flag, let the cascade work; users override per-shell via `GEMINI_MODEL=...` or per-project via `settings.json`. |
197
197
 
198
+ **Codex stdin-wedge note (load-bearing).** `codex exec` reads the positional prompt and THEN blocks on stdin EOF under a no-TTY subprocess (the Bash tool), printing `Reading additional input from stdin…` and never returning. Redirecting `< /dev/null` un-wedges it (verified: returns in ~6s instead of hanging, exit 0, and prints the resolved `model:` it used). Both codex Bash rungs (plugin shim + raw CLI) carry `< /dev/null` because the shim forwards to `codex exec`. The `--sandbox read-only` flag on the raw-CLI rung keeps the spar read-only — aligning with the SPAR-04 "NO `--write`" rule; read-only still permits the partner's investigative Read/Grep.
199
+
198
200
  Set the Bash tool's `timeout` parameter to `--timeout-ms` (default 300000).
199
201
 
200
202
  **Timeout calibration.** The 5-min Bash-rung default and 15-min MCP-rung default are sized for heavy-research partner runs — modern partner CLIs commonly spend multiple minutes doing real Read/Grep/Bash investigation before producing a round response. The two defaults are intentionally asymmetric: the Bash rungs (plugin shim, raw CLI) are capped at the Claude Code Bash tool's 600000ms (10 min) host ceiling, while the MCP rung — a structured tool call rather than a Bash invocation — has no host ceiling and can carry the worst-case 15-min Claude Code partner. For tighter budgets (e.g. CI), pass `--timeout-ms` explicitly. The MCP-rung override is downward-only: if you observe consistent partner-CLI wedges (auth handshakes, hosted-API stalls, CI lanes wanting fast failure), set `apt-spar.mcp_timeout_ms` BELOW the 15-min default in `.aperant/config.json` (e.g. `120000` for a 2-min fast-fail budget) — raising it above 15 min is unnecessary because the default already covers the documented worst case. Future versions may introduce per-partner defaults.
@@ -224,7 +226,7 @@ Follow the envelope's `recommended_walk` / `prefer_self_resolving` for the rung
224
226
  node "${CLAUDE_PLUGIN_ROOT}/scripts/codex-companion.mjs" task "$(cat <<'APT_SPAR_PROMPT_EOF'
225
227
  <prompt body — opaque, no shell expansion>
226
228
  APT_SPAR_PROMPT_EOF
227
- )"
229
+ )" < /dev/null
228
230
 
229
231
  # Claude direction
230
232
  claude -p "$(cat <<'APT_SPAR_PROMPT_EOF'
@@ -37,7 +37,7 @@ The locked decisions backing every section are in `.aperant/context/notes/framew
37
37
  - **Working directory:** the task's worktree (or the project root if this is a non-worktree task).
38
38
  - **State files:** `.aperant/ci-watches/{pr}.json` (per-PR state, D-04); `.aperant/ci-watches/{pr}.lock` (per-PR atomic lock, D-05). Both ephemeral — they are NOT committed.
39
39
  - **Events:** every tick appends a `ci-watch.tick` event to `.aperant/events/{today}.jsonl`; `start` appends `ci-watch.armed`; the fix-and-push path appends `ci-watch.fix-pushed`; terminal actions append `ci-watch.stopped` with a `reason`.
40
- - **CLI surface:** `apt-tools ci-watch start|stop|status|tick --pr N`. The skill body shells out to those subcommands — DO NOT re-implement the classifier in your prompt; the cmd already does it.
40
+ - **CLI surface:** `apt-tools ci-watch start|stop|status|tick --pr N`. `start` also accepts `--auto-merge-on-green` (per-run override — forces `auto_merge_on_green: true` on the snapshot without persisting `ci_watch.auto_merge_on_green` into config; on an already-armed watch it PATCHES the snapshot rather than no-opping). `/apt:run --full` uses this flag to guarantee auto-merge for a single PR after ship's config-driven arm runs first. The skill body shells out to those subcommands — DO NOT re-implement the classifier in your prompt; the cmd already does it.
41
41
 
42
42
  ---
43
43
 
@@ -87,7 +87,7 @@ For the `--tick` mode, execute exactly the following sequence — once — insid
87
87
 
88
88
  When `action ∈ {green, merged, closed, attempts-cap, wall-cap, identical-log}`:
89
89
 
90
- - **green** — print "CI green for PR {N}." If `ci_watch.auto_merge_on_green` is `true` in `.aperant/config.json`, run `gh pr merge {N} --auto --squash` then suggest `/apt:close-task`.
90
+ - **green** — print "CI green for PR {N}." If `ci_watch.auto_merge_on_green` is `true` in `.aperant/config.json`, run `gh pr merge {N} --squash` then suggest `/apt:close-task`. Use a PLAIN merge here, NOT `--auto`: the classifier has already confirmed every check is `SUCCESS`/`SKIPPED` (`stop-matrix.mjs` `allGreen`) before this branch fires, so green is gated by the watcher, not by GitHub branch protection. `--auto` bought nothing on this path — in a repo WITHOUT required status checks `gh pr merge --auto` degrades to an immediate merge anyway — and dropping it removes the classify→merge ambiguity in unprotected repos.
91
91
  - **DO NOT pass `--delete-branch`** to `gh pr merge` from this auto-merge path — ever, unconditionally. The watcher's cwd is the task worktree, where `gh`'s `--delete-branch` post-merge cleanup tries to `git switch <base>` and fails because `<base>` is checked out in the primary worktree. The remote merge has already succeeded by then; local branch + worktree cleanup is `/apt:close-task`'s job via `apt-tools task close-merged` → `computeWorktreeCleanup` (see FRAMEWORK-BUG-019).
92
92
 
93
93
  Else print the exact D-08 text:
@@ -125,9 +125,11 @@ When `action === 'fix'` (or `diverged-rebased`/`diverged-bailed`):
125
125
  5. **Emit event.** `apt-tools event append . --type ci-watch.fix-pushed --data '{pr, attempts, commit_sha}'`.
126
126
  6. **Reschedule** per §3 step 4.
127
127
 
128
+ When the failed check is `features-reconcile`, the fixer MAY run the deterministic repair directly instead of a free-form fix: `apt-tools features-reconcile . --draft --task-id {task-id}` in the worktree, fill the scaffold's dispositions, `apt-tools features-reconcile . --write --task-id {task-id}`, commit + push. Correctness never depends on this path — raw PRs (no active task / pr_url) repair via the red check's printed `--draft` command.
129
+
128
130
  For `diverged-rebased`: the cmd already returned the verb; the orchestrator runs `git -C {worktree} fetch && git rebase origin/{base}` BEFORE the fix step. On conflict the action becomes `diverged-bailed`.
129
131
 
130
- For `diverged-bailed`: default behavior is to exit with a PR comment summarizing the conflict. Self-heal is **opt-in** via `ci_watch.resolve_merge_conflicts` (default false) in `.aperant/config.json`. When enabled, instead of bailing, hand off to **`/apt:merge-conflict-resolution`** (`--base origin/{base}`) for the worktree; it resolves the rebase conflict inline and re-probes mergeability. On success, continue to the §5 fix-and-push step (`git push origin {branch}`) and reschedule per §3 — the watcher keeps running. On its non-convergence STOP (it aborts the rebase to a clean tree first), fall back to the bail-with-PR-comment path. The resolved branch still goes through CI; the watcher never auto-merges except via the existing config-gated `gh pr merge --auto`.
132
+ For `diverged-bailed`: default behavior is to exit with a PR comment summarizing the conflict. Self-heal is **opt-in** via `ci_watch.resolve_merge_conflicts` (default false) in `.aperant/config.json`. When enabled, instead of bailing, hand off to **`/apt:merge-conflict-resolution`** (`--base origin/{base}`) for the worktree; it resolves the rebase conflict inline and re-probes mergeability. On success, continue to the §5 fix-and-push step (`git push origin {branch}`) and reschedule per §3 — the watcher keeps running. On its non-convergence STOP (it aborts the rebase to a clean tree first), fall back to the bail-with-PR-comment path. The resolved branch still goes through CI; the watcher never auto-merges except via the existing config-gated green-branch `gh pr merge --squash` (§4).
131
133
 
132
134
  ---
133
135
 
@@ -164,5 +166,5 @@ If you find yourself wanting to add "and then wait 5 minutes and run again," STO
164
166
  ## Notes for the orchestrator
165
167
 
166
168
  - All gh CLI calls run with the host's existing auth. The watcher introduces no new secret material (per task `dimensions_covered.token-encryption.crossed: false`).
167
- - `auto_merge_on_green` is snapshotted from `.aperant/config.json` at `start` time (state file's `auto_merge_on_green` field). Changing the config mid-watch does NOT retroactively affect armed watches — re-run `start` to pick up the new value.
169
+ - `auto_merge_on_green` is snapshotted from `.aperant/config.json` at `start` time (state file's `auto_merge_on_green` field). Changing the config mid-watch does NOT retroactively affect armed watches — re-run `start` to pick up the new value. The `--auto-merge-on-green` start flag forces it `true` for one run regardless of the config default (it patches an already-armed snapshot too); this is how `/apt:run --full` drives auto-merge without flipping the global config.
168
170
  - The fix-CLI shell-out is the cleanest abstraction we have for portability. It's NOT a sub-agent. On Claude Code that means another `claude` invocation; on Codex/Gemini/OpenCode/Pi, the equivalent binary. Detection lives in `apt-tools host-detect`'s `cli` field.
@@ -1 +1 @@
1
- {"version":3,"file":"feature-registry.d.ts","sourceRoot":"","sources":["../../src/schemas/feature-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA0BvB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;iBAa3B,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;iBAK7B,CAAA;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAQhC,CAAA;AAGF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AACzD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAC7D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAGnE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;GAEpD;AAGD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAwC,CAAA"}
1
+ {"version":3,"file":"feature-registry.d.ts","sourceRoot":"","sources":["../../src/schemas/feature-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AA0BvB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;iBAa3B,CAAA;AAEF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;iBAK7B,CAAA;AAiBF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuBhC,CAAA;AAGF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AACzD,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAC7D,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAGnE,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;GAEpD;AAKD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAA4C,CAAA"}
@@ -38,7 +38,7 @@ export const FeatureGroupSchema = z.object({
38
38
  component: ComponentRef.optional(),
39
39
  sub_features: z.array(SubFeatureSchema).default([]),
40
40
  });
41
- export const FeatureRegistrySchema = z.object({
41
+ const FeatureRegistryBaseSchema = z.object({
42
42
  area: z.string().min(1),
43
43
  route: z.string().min(1),
44
44
  components: z.array(ComponentRef).default([]),
@@ -47,10 +47,41 @@ export const FeatureRegistrySchema = z.object({
47
47
  }),
48
48
  features: z.array(FeatureGroupSchema),
49
49
  });
50
+ // Uniqueness refinement (features-reconcile AC17): feature ids must be unique
51
+ // per area, and sub_feature ids unique per feature group. Mirrored by the
52
+ // dependency-free twin validator `src/cli/features/area-shape.mjs` (the
53
+ // bare-node CI check cannot import zod) — parity is locked by
54
+ // `feature-registry-schema-parity.test.ts`.
55
+ export const FeatureRegistrySchema = FeatureRegistryBaseSchema.superRefine((data, ctx) => {
56
+ const featureIds = new Set();
57
+ for (const [i, group] of data.features.entries()) {
58
+ if (featureIds.has(group.id)) {
59
+ ctx.addIssue({
60
+ code: 'custom',
61
+ path: ['features', i, 'id'],
62
+ message: `duplicate feature id "${group.id}" in area`,
63
+ });
64
+ }
65
+ featureIds.add(group.id);
66
+ const subIds = new Set();
67
+ for (const [j, sub] of group.sub_features.entries()) {
68
+ if (subIds.has(sub.id)) {
69
+ ctx.addIssue({
70
+ code: 'custom',
71
+ path: ['features', i, 'sub_features', j, 'id'],
72
+ message: `duplicate sub_feature id "${sub.id}" in group`,
73
+ });
74
+ }
75
+ subIds.add(sub.id);
76
+ }
77
+ }
78
+ });
50
79
  // Validator — thin wrapper returning zod's discriminated union { success: true, data } | { success: false, error }
51
80
  export function validateFeatureRegistry(data) {
52
81
  return FeatureRegistrySchema.safeParse(data);
53
82
  }
54
- // Pre-computed JSON Schema for use in LLM prompt injection
55
- export const featureRegistryJsonSchema = z.toJSONSchema(FeatureRegistrySchema);
83
+ // Pre-computed JSON Schema for use in LLM prompt injection. Derived from the
84
+ // BASE object schema — the uniqueness superRefine is not JSON-Schema
85
+ // representable and would be dropped/rejected by z.toJSONSchema.
86
+ export const featureRegistryJsonSchema = z.toJSONSchema(FeatureRegistryBaseSchema);
56
87
  //# sourceMappingURL=feature-registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature-registry.js","sourceRoot":"","sources":["../../src/schemas/feature-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"feature-registry.js","sourceRoot":"","sources":["../../src/schemas/feature-registry.ts"],"names":[],"mappings":"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"}
@@ -403,11 +403,14 @@ export interface CiWatchConfig {
403
403
  */
404
404
  after_ship?: 'auto' | 'ask' | 'never';
405
405
  /**
406
- * On all-green CI, auto-merge the PR via `gh pr merge --auto --squash`.
407
- * Default `false`the watcher prints a merge hint and leaves the merge
408
- * decision to the user (matches the user's stated rhythm). Flip to `true`
409
- * once a calendar week of clean post-launch usage shows zero false-green
410
- * merges (D-08 kill criteria).
406
+ * On all-green CI, `/apt:watch-ci` merges the PR with a plain
407
+ * `gh pr merge --squash` — NEVER `gh pr merge --auto` (in a repo without
408
+ * required status checks `--auto` degrades to an immediate merge; the
409
+ * watcher's `allGreen` classifier is the gate, not GitHub branch
410
+ * protection). Default `false` — the watcher prints a merge hint and leaves
411
+ * the merge decision to the user (matches the user's stated rhythm). Flip to
412
+ * `true` once a calendar week of clean post-launch usage shows zero
413
+ * false-green merges (D-08 kill criteria).
411
414
  */
412
415
  auto_merge_on_green?: boolean;
413
416
  }