@aperant/framework 0.19.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 (108) hide show
  1. package/CHANGELOG.md +109 -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/features-reconcile.d.mts +2 -0
  13. package/dist/cli/commands/features-reconcile.d.mts.map +1 -0
  14. package/dist/cli/commands/features-reconcile.mjs +143 -0
  15. package/dist/cli/commands/features-reconcile.mjs.map +1 -0
  16. package/dist/cli/commands/health-check.d.mts +2 -2
  17. package/dist/cli/commands/health-check.mjs +2 -2
  18. package/dist/cli/dispatch.mjs +2 -2
  19. package/dist/cli/dispatch.mjs.map +1 -1
  20. package/dist/cli/features/area-shape.d.mts +11 -0
  21. package/dist/cli/features/area-shape.d.mts.map +1 -0
  22. package/dist/cli/features/area-shape.mjs +141 -0
  23. package/dist/cli/features/area-shape.mjs.map +1 -0
  24. package/dist/cli/features/delta.d.mts +78 -0
  25. package/dist/cli/features/delta.d.mts.map +1 -0
  26. package/dist/cli/features/delta.mjs +591 -0
  27. package/dist/cli/features/delta.mjs.map +1 -0
  28. package/dist/cli/features/reconcile.d.mts +236 -0
  29. package/dist/cli/features/reconcile.d.mts.map +1 -0
  30. package/dist/cli/features/reconcile.mjs +1126 -0
  31. package/dist/cli/features/reconcile.mjs.map +1 -0
  32. package/dist/cli/features/surface-map.d.mts +63 -0
  33. package/dist/cli/features/surface-map.d.mts.map +1 -0
  34. package/dist/cli/features/surface-map.mjs +191 -0
  35. package/dist/cli/features/surface-map.mjs.map +1 -0
  36. package/dist/cli/{commands/features-audit.d.mts → features/write-root.d.mts} +4 -3
  37. package/dist/cli/features/write-root.d.mts.map +1 -0
  38. package/dist/cli/features/write-root.mjs +137 -0
  39. package/dist/cli/features/write-root.mjs.map +1 -0
  40. package/dist/cli/gate/gates/features-reconciled.d.mts +36 -0
  41. package/dist/cli/gate/gates/features-reconciled.d.mts.map +1 -0
  42. package/dist/cli/gate/gates/features-reconciled.mjs +67 -0
  43. package/dist/cli/gate/gates/features-reconciled.mjs.map +1 -0
  44. package/dist/cli/gate/gates/index.mjs +1 -0
  45. package/dist/cli/gate/gates/index.mjs.map +1 -1
  46. package/dist/cli/help.mjs +1 -1
  47. package/dist/cli/release-notes/ship-autodraft.mjs +2 -2
  48. package/dist/cli/variant/gallery.d.mts.map +1 -1
  49. package/dist/cli/variant/gallery.mjs +7 -3
  50. package/dist/cli/variant/gallery.mjs.map +1 -1
  51. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  52. package/dist/plugin/agents/apt-executor.md +6 -0
  53. package/dist/plugin/agents/apt-planner.md +3 -2
  54. package/dist/plugin/skills/apt-close-task/SKILL.md +2 -2
  55. package/dist/plugin/skills/apt-debug/SKILL.md +8 -0
  56. package/dist/plugin/skills/apt-execute/SKILL.md +35 -26
  57. package/dist/plugin/skills/apt-mockup/SKILL.md +1 -1
  58. package/dist/plugin/skills/apt-quick/SKILL.md +13 -11
  59. package/dist/plugin/skills/apt-review/SKILL.md +14 -11
  60. package/dist/plugin/skills/apt-run/SKILL.md +9 -3
  61. package/dist/plugin/skills/apt-ship/SKILL.md +27 -5
  62. package/dist/plugin/skills/apt-watch-ci/SKILL.md +2 -0
  63. package/dist/schemas/feature-registry.d.ts.map +1 -1
  64. package/dist/schemas/feature-registry.js +34 -3
  65. package/dist/schemas/feature-registry.js.map +1 -1
  66. package/dist/types/config.d.ts +8 -5
  67. package/dist/types/config.d.ts.map +1 -1
  68. package/package.json +1 -1
  69. package/skills/apt-close-task/SKILL.md +2 -2
  70. package/skills/apt-debug/SKILL.md +8 -0
  71. package/skills/apt-execute/SKILL.md +35 -26
  72. package/skills/apt-mockup/SKILL.md +1 -1
  73. package/skills/apt-quick/SKILL.md +13 -11
  74. package/skills/apt-review/SKILL.md +14 -11
  75. package/skills/apt-run/SKILL.md +9 -3
  76. package/skills/apt-ship/SKILL.md +27 -5
  77. package/skills/apt-watch-ci/SKILL.md +2 -0
  78. package/src/cli/artifacts/self-stage.mjs +2 -1
  79. package/src/cli/cli-wrappers/features-reconcile.mjs +9 -0
  80. package/src/cli/commands/features-reconcile.mjs +157 -0
  81. package/src/cli/commands/health-check.mjs +2 -2
  82. package/src/cli/dispatch.mjs +2 -2
  83. package/src/cli/features/area-shape.mjs +140 -0
  84. package/src/cli/features/delta.mjs +625 -0
  85. package/src/cli/features/reconcile.mjs +1169 -0
  86. package/src/cli/features/surface-map.mjs +192 -0
  87. package/src/cli/features/write-root.mjs +140 -0
  88. package/src/cli/gate/gates/features-reconciled.mjs +70 -0
  89. package/src/cli/gate/gates/index.mjs +1 -0
  90. package/src/cli/help.mjs +1 -1
  91. package/src/cli/release-notes/ship-autodraft.mjs +2 -2
  92. package/src/cli/variant/gallery.mjs +7 -3
  93. package/templates/aperant-claude-md-appendix.md +2 -2
  94. package/workflows/scan-features.md +17 -11
  95. package/dist/cli/cli-wrappers/features-audit.d.mts +0 -2
  96. package/dist/cli/cli-wrappers/features-audit.d.mts.map +0 -1
  97. package/dist/cli/cli-wrappers/features-audit.mjs +0 -8
  98. package/dist/cli/cli-wrappers/features-audit.mjs.map +0 -1
  99. package/dist/cli/commands/features-audit.d.mts.map +0 -1
  100. package/dist/cli/commands/features-audit.mjs +0 -293
  101. package/dist/cli/commands/features-audit.mjs.map +0 -1
  102. package/dist/cli/features/registry-audit.d.mts +0 -56
  103. package/dist/cli/features/registry-audit.d.mts.map +0 -1
  104. package/dist/cli/features/registry-audit.mjs +0 -264
  105. package/dist/cli/features/registry-audit.mjs.map +0 -1
  106. package/src/cli/cli-wrappers/features-audit.mjs +0 -8
  107. package/src/cli/commands/features-audit.mjs +0 -302
  108. package/src/cli/features/registry-audit.mjs +0 -254
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/types/config.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aperant/framework",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "AI coding framework — composable skills for planning, executing, verifying, and reviewing code with any LLM provider. Works as Claude Code commands, Codex tasks, or programmatically.",
5
5
  "author": "Mikalsen AI <hello@mikalsen.ai>",
6
6
  "type": "module",
@@ -185,7 +185,7 @@ Flags:
185
185
  Per ledger entry `{ task_id, scope, phase_id, closed_at, pr_number }`:
186
186
 
187
187
  0. **Enumerate the ledger first.** Run `apt-tools task close-merged . --narrate-only [--task <id>]`. The envelope's `closed[]` is the read-only list of pending narration rows (each carries `narration_pending: true`); state.json is not mutated. When `closed[]` is empty, exit early with `{status: 'ok', narrated: [], skipped: [], remaining: 0}` — there is nothing to drain.
188
- 1. Run `apt-tools features-audit . --apply-stubs --task <task_id>` so the feature registry catches whatever the closed task introduced. If the subprocess exits non-zero, skip the entry with `reason: 'features-audit-failed'` — never block narration on registry update.
188
+ 1. Run `apt-tools features-reconcile . --gc` to prune feature-registry receipts that are merged to origin/main and older than 30 days. Receipt GC is close-task's ONLY registry role the registry WRITE happened at ship time (`/apt:ship` §0.0 materialize), so there is no post-merge registry write to drift main. If the subprocess exits non-zero, skip the entry with `reason: 'features-gc-failed'` — never block narration on registry GC.
189
189
  2. When `phase_id` is non-null, spawn `apt-team-docs-narrator` (background, fire-and-forget) using the same shape as §2.5: `subagent_type: apt-team-docs-narrator`, `run_in_background: true`, `description: Narrate shipped phase {phase_id}`, `prompt: Run in phase-ship mode with --phase {phase_id} --scope {scope}.`. When `phase_id` is null, skip the spawn with `reason: 'no-phase-id'` (quick tasks have no phase to narrate).
190
190
  3. On successful spawn (or successful no-phase skip), drain the row via `apt-tools task narration-drain . --task <task_id>` which acquires `withFileLock(state.json)` and removes the matching `pending_narration[]` entry. On spawn failure, leave the row in place with `reason: 'narrator-spawn-failed'` so the user can re-invoke.
191
191
 
@@ -198,7 +198,7 @@ Emit a summary envelope:
198
198
  "status": "ok",
199
199
  "command": "close-task-narrate-only",
200
200
  "narrated": [{ "task_id": "<id>", "phase_id": "<p|null>", "scope": "<s>" }],
201
- "skipped": [{ "task_id": "<id>", "reason": "no-phase-id|features-audit-failed|narrator-spawn-failed" }],
201
+ "skipped": [{ "task_id": "<id>", "reason": "no-phase-id|features-gc-failed|narrator-spawn-failed" }],
202
202
  "remaining": <ledger.length>
203
203
  }
204
204
  ```
@@ -291,6 +291,14 @@ Document the root cause clearly:
291
291
  cd {worktree_path} && node packages/framework/bin/apt-tools.mjs commit "fix: {concise description of fix}" --files {changed-files}
292
292
  ```
293
293
 
294
+ After the commit, emit the registry delta (one non-blocking command):
295
+
296
+ ```bash
297
+ node packages/framework/bin/apt-tools.mjs features-reconcile . --draft --task-id {task-id} || true
298
+ ```
299
+
300
+ Stage `.aperant/features/deltas/` with the commit; fill any `needs-disposition` field (usually `no-semantic-change` + a one-line reason).
301
+
294
302
  ### 6c. Update Status
295
303
 
296
304
  ```markdown
@@ -373,38 +373,47 @@ node packages/framework/bin/apt-tools.mjs audit pending-artifacts . --stage
373
373
  - **`unknown[]` non-empty** → HARD STOP. A path under `.aperant/` is not classified. Treat as a planner gap — the subtask touched state that the contract does not know about. Write the decision to `{task_dir}/execution-decisions.md` (decision class: `classification-gap`), then either extend `packages/framework/src/cli/artifacts/classification.mjs` inline (if the subtask already modifies framework code) or open a follow-up task (if the drift is orthogonal). Do NOT proceed to the next subtask until the envelope returns `clean`.
374
374
  - **Envelope status == `clean`** → proceed to 3e-features.
375
375
 
376
- ### 3e-features. Features Registry Post-Step (C33)
376
+ ### 3e-features. Feature-Registry Delta Emit
377
377
 
378
- After the subtask commits, run `features-audit --apply-stubs` so any
379
- newly-added UI/core/hook/IPC file in the diff lands in
380
- `.aperant/features/<area>.json` automatically. The reviewer Pass 6 covers
381
- whatever the post-step missed; running it here closes the gap where
382
- executor commits introduce a new feature surface without registering it.
378
+ After the subtask commits, emit this subtask's registry DELTA — semantic
379
+ capture happens HERE, while the build context is still in your window.
380
+ `/apt:ship` §0.0 materializes all pending deltas into the area JSONs +
381
+ a receipt later; you only record what changed and what it means.
383
382
 
384
383
  ```bash
385
- node packages/framework/bin/apt-tools.mjs features-audit . \
386
- --task-id "$TASK_ID" \
387
- --diff-files "$(git diff --name-only HEAD^ HEAD | tr '\n' ',')" \
388
- --apply-stubs
384
+ node packages/framework/bin/apt-tools.mjs features-reconcile . \
385
+ --draft --task-id "$TASK_ID" --subtask-id "{subtask.id}"
389
386
  ```
390
387
 
388
+ Then ENRICH the scaffold at `.aperant/features/deltas/{task-id}-{subtask.id}.json`:
389
+
390
+ - Fill every `needs-disposition` files[] entry with a real disposition
391
+ (`upsert` | `remove` | `wiring-transition` | `no-semantic-change` — the
392
+ last REQUIRES a one-line `reason`). Added qualifying files MUST register
393
+ (added + no-semantic-change is a validation error).
394
+ - Assign any `area: null` (the hooks/ipc/services junk drawers no longer
395
+ exist — pick the owning product area).
396
+ - Replace draft upsert stubs with real feature groups: `sub_features[]`
397
+ entries carrying `wired` / `handler` / `test_hint` per
398
+ `FeatureRegistrySchema`.
399
+ - A wired-state change is `disposition: "wiring-transition"` plus a
400
+ `patch-sub-feature` operation carrying `expected_from` (the prior
401
+ `wired` value).
402
+
403
+ Stage the delta with the commit:
404
+ `git add .aperant/features/deltas/ && git commit --amend --no-edit`.
405
+
391
406
  Notes:
392
- - `--task-id $TASK_ID` (BUG-025b) is mandatory when the executor runs
393
- from the main-repo cwd instead of inside the worktree (the
394
- orchestrator's common path). features-audit resolves the worktree's
395
- `.aperant/features/` from the active task record and writes there,
396
- preventing generated `*.json` from leaking into main. When invoked
397
- from the worktree cwd directly, `--task-id` is a no-op (layer 1
398
- detection short-circuits). Pass `--no-worktree-redirect` only when
399
- you intentionally want to write to the invoking cwd.
400
- - `--apply-stubs` only runs when the matched surface's policy is
401
- `auto-update` (the default for `.aperant/features/*.json`). Users who
402
- opted out via `/apt:setup` Batch 7 get a no-op — the command still
403
- succeeds.
404
- - Pre-existing flag-drift findings are never emitted here — they're the
405
- reviewer's job. The post-step is append-only on internal state.
406
- - If the audit fails (exit code != 0), log the failure and continue; don't
407
- block subtask completion on a features-registry glitch.
407
+ - `--task-id "$TASK_ID"` (BUG-025b) redirects the delta write to the active
408
+ task's worktree `.aperant/features/deltas/` when you run from the
409
+ main-repo cwd; it is ALSO the per-writer delta filename, so it is always
410
+ required.
411
+ - The write is skipped (`policy-opt-out`) when the user opted
412
+ `.aperant/features/*.json` out of `auto-update` via `/apt:setup` Batch 7.
413
+ - Non-blocking: if the reconcile scaffold fails (exit code != 0), log the
414
+ failure and continue; don't block subtask completion on a registry
415
+ glitch. The ship-time `features-reconciled` gate + the always-on CI
416
+ check catch real gaps.
408
417
 
409
418
  ### 3e-gate. Per-Task Review Gate (R7)
410
419
 
@@ -58,7 +58,7 @@ Text-first design stays in `apt:design`. This skill never edits `DESIGN.md` or `
58
58
  **Writes:**
59
59
  - `{task_dir}/mockups/iteration-NNN.html` — One file per iteration, zero-padded 3-digit (`iteration-001.html`, `iteration-002.html`, ...). Promoted from a picked variant when the first render used `--variants`.
60
60
  - `{task_dir}/mockups/iteration-NNN-variant-<letter>.html` — One per variant in a `--variants` run (letters `a..e` for `N=2..5`)
61
- - `{task_dir}/mockups/iteration-NNN-gallery.html` — Generated by `apt-tools variant-gallery`; iframes the N variants side-by-side with the pick command spelled out.
61
+ - `{task_dir}/mockups/iteration-NNN-gallery.html` — Generated by `apt-tools variant-gallery`; iframes the N variants side-by-side with the pick command spelled out, and each variant card links to its full HTML file (opens in a new tab).
62
62
  - `{task_dir}/mockups/iteration-NNN-archive/` — After `--pick <letter>`, the losing variants and the gallery move here (preserved, not deleted, so the user can review what was rejected).
63
63
  - `{task_dir}/mockups/mockup_final.html` — On `--accept`, a byte-identical copy of the latest `iteration-NNN.html` so iteration history is preserved.
64
64
  - `{task_dir}/mockups/mockup_log.md` — Append-only log: one entry per turn with iteration number, mode, user prompt, and (when relevant) variant style seeds.
@@ -165,7 +165,7 @@ Show the affected files briefly before proceeding (5-second delay; user can inte
165
165
  Make the changes directly:
166
166
  - Follow existing code patterns and conventions
167
167
  - Keep changes minimal — solve the stated problem, nothing more
168
- - If touching code with tests, run the tests to make sure nothing breaks
168
+ - If touching tested code, run those tests
169
169
 
170
170
  ## 5. Verify (Lightweight)
171
171
 
@@ -175,7 +175,7 @@ Run a quick sanity check appropriate to the change:
175
175
  pnpm typecheck 2>&1 | tail -20
176
176
  ```
177
177
  - **Config change:** Validate the config is syntactically correct
178
- - **Doc change:** No verification needed unless `--verify` flag is set
178
+ - **Doc change:** none unless `--verify` is set
179
179
  - **Style change:** Run lint on changed files
180
180
 
181
181
  If visual verification is performed via MCP screenshots:
@@ -185,24 +185,26 @@ If visual verification is performed via MCP screenshots:
185
185
  If verification fails:
186
186
  - Fix the issue
187
187
  - Re-run verification
188
- - 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
189
189
 
190
190
  ## 6. Commit
191
191
 
192
- Create an atomic commit with a descriptive message:
192
+ Create an atomic commit:
193
193
 
194
194
  ```bash
195
195
  git add {changed-files}
196
196
  git commit -m "{type}: {description}"
197
197
  ```
198
198
 
199
- Use appropriate conventional commit type:
200
- - `fix:` for bug fixes
201
- - `docs:` for documentation
202
- - `style:` for formatting/style
203
- - `chore:` for config, dependencies, maintenance
204
- - `refactor:` for code restructuring
205
- - `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).
206
208
 
207
209
  ## 7. Record Task
208
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
@@ -30,7 +30,7 @@ Run the full Aperant pipeline: plan a task, execute all subtasks, verify the imp
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
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). `--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).
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).
34
34
  </objective>
35
35
 
36
36
  <your_environment>
@@ -399,7 +399,7 @@ Pipeline order note: the user's phrasing was *"review, verify"* but `/apt:run` r
399
399
 
400
400
  **Ship (Option A — PR that auto-merges to main on green; NEVER a direct push/merge):**
401
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.
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
403
 
404
404
  Capture the opened PR number `{N}` from the `/apt:ship` result for §6.2.
405
405
 
@@ -413,13 +413,19 @@ After the PR opens, force auto-merge for THIS run regardless of the config defau
413
413
  node packages/framework/bin/apt-tools.mjs ci-watch start . --pr {N} --task-id {task-id} --host {cli} --auto-merge-on-green
414
414
  ```
415
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
+
416
422
  **Branch on host cron capability.** Run host-detect and read `host_capabilities.cron`:
417
423
 
418
424
  ```bash
419
425
  node packages/framework/bin/apt-tools.mjs host-detect .
420
426
  ```
421
427
 
422
- - **cron-capable host** (e.g. Claude Code, `cron: true`): the watcher is armed with auto-merge ON; register the recurring tick via the host's `CronCreate` (per `/apt:watch-ci` §3). Then **EXIT — do NOT loop** (respect `/apt:watch-ci`'s single-execution-per-invocation contract). The cron beat drives the watcher to merged + green unattended. Report: watcher armed, auto-merge ON, and the deadline.
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.
423
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:
424
430
 
425
431
  ```
@@ -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
 
@@ -125,6 +125,8 @@ 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
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).
@@ -3,7 +3,8 @@
3
3
  * self-stage.mjs — self-staging wrapper for committable .aperant/ writes (C56 B4).
4
4
  *
5
5
  * Intended consumers: state-mutating CLI verbs in roadmap.mjs, task.mjs,
6
- * pr-review.mjs, features-audit.mjs. Call this helper just before returning
6
+ * pr-review.mjs, features-reconcile.mjs (--write self-stages its areas +
7
+ * receipt + REGISTRY.md). Call this helper just before returning
7
8
  * the success envelope so the caller's next commit picks up the writes.
8
9
  *
9
10
  * Contract:
@@ -0,0 +1,9 @@
1
+ /**
2
+ * cli-wrappers/features-reconcile.mjs — Layer 2 wrapper for the
3
+ * features-reconcile cmd.
4
+ *
5
+ * Today this is a passthrough — DISPATCH calls wrap() directly.
6
+ * Re-exporting keeps the file-per-cmd structural seam.
7
+ */
8
+
9
+ export { cmdFeaturesReconcile as cliFeaturesReconcile } from '../commands/features-reconcile.mjs'
@@ -0,0 +1,157 @@
1
+ /**
2
+ * commands/features-reconcile.mjs — CLI entry point for the feature-registry
3
+ * delta ledger (replaces the retired append-only registry-audit writer).
4
+ *
5
+ * Exactly ONE verb per invocation:
6
+ * --draft — scaffold/refresh a per-writer delta from `git diff
7
+ * --name-status <base>..HEAD` (renames preserved; deletions
8
+ * pre-filled `remove`; modifications marked needs-disposition).
9
+ * --write — the single ordered idempotent materializer (7 steps, ID-03):
10
+ * deltas → post-images → validate → atomic area replace →
11
+ * receipt → delete consumed deltas → regenerate REGISTRY.md.
12
+ * --check — read-only 4-clause verifier (ID-05): base..HEAD coverage with
13
+ * blob fingerprints, area schema validity, per-area latest-
14
+ * receipt integrity, no orphan consumed deltas.
15
+ * --gc — prune receipts present on origin/main AND older than
16
+ * --max-age-days (default 30). Fetch failure → warned no-op.
17
+ *
18
+ * Flags: --task-id, --subtask-id (draft), --base <ref> (draft/check; an
19
+ * explicit ref is normalized via `merge-base HEAD <ref>` — see resolveBase;
20
+ * default merge-base HEAD origin/main), --dry-run (draft), --warn-only
21
+ * (check), --max-age-days (gc), --no-worktree-redirect.
22
+ *
23
+ * BUG-025b: the mutating verbs (--draft/--write) resolve their write root via
24
+ * features/write-root.mjs so registry writes land in the active task's
25
+ * worktree, never leak onto main. --write self-stages its committable writes
26
+ * (self-stage.mjs contract) so the caller's next commit picks them up.
27
+ */
28
+
29
+ import { resolve } from 'node:path'
30
+ import { selfStageCommittableWrites } from '../artifacts/self-stage.mjs'
31
+ import { checkReconciled, draftDelta, gcReceipts, materialize } from '../features/reconcile.mjs'
32
+ import { resolveWriteRoot } from '../features/write-root.mjs'
33
+ import { parseFlags } from '../util/args.mjs'
34
+ import { err, exitWith, ok } from '../util/result.mjs'
35
+
36
+ const VERBS = ['draft', 'write', 'check', 'gc']
37
+
38
+ export function cmdFeaturesReconcile(projectDir, extraArgs) {
39
+ if (!projectDir) {
40
+ return err(
41
+ 'Usage: apt-tools features-reconcile <project-dir> (--draft|--write|--check|--gc) [flags]',
42
+ )
43
+ }
44
+ const root = resolve(projectDir)
45
+ const flags = parseFlags(extraArgs)
46
+ const verbs = VERBS.filter((v) => flags.has(v))
47
+ if (verbs.length !== 1) {
48
+ return err('features-reconcile requires exactly ONE of --draft | --write | --check | --gc', 1, {
49
+ command: 'features-reconcile',
50
+ })
51
+ }
52
+ const verb = verbs[0]
53
+
54
+ const taskIdFlag = flags.get('task-id')
55
+ const taskId = typeof taskIdFlag === 'string' && taskIdFlag.trim() ? taskIdFlag.trim() : null
56
+ const subtaskIdFlag = flags.get('subtask-id')
57
+ const subtaskId =
58
+ typeof subtaskIdFlag === 'string' && subtaskIdFlag.trim() ? subtaskIdFlag.trim() : null
59
+ const baseFlag = flags.get('base')
60
+ const base = typeof baseFlag === 'string' && baseFlag.trim() ? baseFlag.trim() : null
61
+ const noRedirect = flags.get('no-worktree-redirect') === true
62
+
63
+ // BUG-025b: only the MUTATING verbs redirect writes into the task worktree.
64
+ let writeRoot = root
65
+ let redirectNotice = null
66
+ if (verb === 'draft' || verb === 'write') {
67
+ const resolved = resolveWriteRoot({ projectDir: root, taskId, noRedirect })
68
+ if (resolved.error) {
69
+ return err(resolved.error.message, 1, {
70
+ command: 'features-reconcile',
71
+ kind: resolved.error.kind,
72
+ active_worktree_tasks: resolved.error.active_worktree_tasks,
73
+ })
74
+ }
75
+ writeRoot = resolved.writeRoot
76
+ redirectNotice = resolved.redirect_notice
77
+ if (redirectNotice) {
78
+ // Surface the redirect once on stderr so the executor's log carries
79
+ // the audit trail without polluting stdout JSON.
80
+ process.stderr.write(`[features-reconcile] ${redirectNotice}\n`)
81
+ }
82
+ }
83
+ const common = {
84
+ status: 'ok',
85
+ command: 'features-reconcile',
86
+ verb,
87
+ write_root: writeRoot,
88
+ ...(redirectNotice ? { redirect_notice: redirectNotice } : {}),
89
+ }
90
+
91
+ if (verb === 'draft') {
92
+ if (!taskId) {
93
+ return err(
94
+ 'features-reconcile --draft requires --task-id <id> (the delta path is per-writer)',
95
+ 1,
96
+ {
97
+ command: 'features-reconcile',
98
+ },
99
+ )
100
+ }
101
+ const res = draftDelta({
102
+ root: writeRoot,
103
+ base,
104
+ taskId,
105
+ subtaskId,
106
+ dryRun: flags.get('dry-run') === true,
107
+ })
108
+ if (!res.ok) return err(res.error, 1, { command: 'features-reconcile', verb })
109
+ return ok({
110
+ ...common,
111
+ delta_path: res.deltaPath,
112
+ wrote: res.wrote,
113
+ qualifying: res.qualifying,
114
+ base: res.base,
115
+ delta: res.delta,
116
+ })
117
+ }
118
+
119
+ if (verb === 'write') {
120
+ const res = materialize({ root: writeRoot, taskId })
121
+ if (res.status === 'error') {
122
+ return exitWith({ ...res, command: 'features-reconcile', verb, write_root: writeRoot }, 1)
123
+ }
124
+ let self_stage = null
125
+ if (res.status === 'ok' && Array.isArray(res.changed_paths) && res.changed_paths.length > 0) {
126
+ // Finally wiring the self-stage.mjs header contract: the write's
127
+ // committable outputs (areas + receipt + REGISTRY.md + deleted-delta
128
+ // paths) are staged so the ship-step commit picks them up.
129
+ self_stage = selfStageCommittableWrites(writeRoot, res.changed_paths)
130
+ }
131
+ return ok({
132
+ ...common,
133
+ ...res,
134
+ status: res.status,
135
+ ...(self_stage ? { self_stage } : {}),
136
+ })
137
+ }
138
+
139
+ if (verb === 'check') {
140
+ const res = checkReconciled({
141
+ root,
142
+ base,
143
+ warnOnly: flags.get('warn-only') === true,
144
+ taskId,
145
+ })
146
+ const envelope = { ...common, ...res, status: res.status }
147
+ if (res.status === 'fail') return exitWith(envelope, 1)
148
+ return ok(envelope)
149
+ }
150
+
151
+ // verb === 'gc'
152
+ const maxAgeFlag = flags.get('max-age-days')
153
+ const maxAgeDays =
154
+ typeof maxAgeFlag === 'string' && /^\d+$/.test(maxAgeFlag) ? Number(maxAgeFlag) : 30
155
+ const res = gcReceipts({ root, maxAgeDays })
156
+ return ok({ ...common, ...res, status: res.status, max_age_days: maxAgeDays })
157
+ }
@@ -16,8 +16,8 @@ const __dirname = dirname(__filename)
16
16
 
17
17
  /**
18
18
  * SECURITY: validate a component path string from `.aperant/features/*.json`
19
- * before passing it to git. The registry is on-disk JSON authored by
20
- * features-audit; pre-fix the orphan walker spliced this string into a
19
+ * before passing it to git. The registry is on-disk JSON written by the
20
+ * features-reconcile materializer; pre-fix the orphan walker spliced this string into a
21
21
  * shell command (`execSync(\`git rev-parse HEAD:${comp} 2>/dev/null\`)`),
22
22
  * making a malicious entry like `foo.ts; rm -rf $HOME` a command-injection
23
23
  * vector against any user who ran `apt-tools health-check`. The fix
@@ -62,7 +62,7 @@ import { cmdEditCheck } from './commands/edit-check.mjs'
62
62
  import { cmdEffects } from './commands/effects.mjs'
63
63
  import { cmdEvent } from './commands/event.mjs'
64
64
  import { cmdFanOut } from './commands/fan-out.mjs'
65
- import { cmdFeaturesAudit } from './commands/features-audit.mjs'
65
+ import { cmdFeaturesReconcile } from './commands/features-reconcile.mjs'
66
66
  import { cmdFollowups } from './commands/followups.mjs'
67
67
  import { cmdGate } from './commands/gate.mjs'
68
68
  import { cmdHealthCheck } from './commands/health-check.mjs'
@@ -261,7 +261,7 @@ export const DISPATCH = {
261
261
  exitCode: 1,
262
262
  }))()
263
263
  },
264
- 'features-audit': (args) => wrap(cmdFeaturesAudit)(args[1], args.slice(2)),
264
+ 'features-reconcile': (args) => wrap(cmdFeaturesReconcile)(args[1], args.slice(2)),
265
265
  'init-state': (args) => wrap(cmdInitState)(args[1], args.slice(2)),
266
266
  'risk-check': (args) => wrap(cmdRiskCheck)(args[1], args.slice(2)),
267
267
  'edit-check': (args) => wrap(cmdEditCheck)(args.slice(1)),