@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
@@ -17,6 +17,7 @@ import './verify-approved.mjs';
17
17
  import './review-clean.mjs';
18
18
  import './followups-adjudicated.mjs';
19
19
  import './gitignore-in-sync.mjs';
20
+ import './features-reconciled.mjs';
20
21
  import './consistency-check.mjs';
21
22
  import './tdd-iron-law.mjs';
22
23
  import './r-persona-alignment.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/index.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,yBAAyB,CAAA;AAChC,OAAO,6BAA6B,CAAA;AACpC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,6BAA6B,CAAA;AACpC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,6BAA6B,CAAA;AACpC,OAAO,yBAAyB,CAAA;AAChC,OAAO,yBAAyB,CAAA;AAChC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,2BAA2B,CAAA"}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/cli/gate/gates/index.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,yBAAyB,CAAA;AAChC,OAAO,6BAA6B,CAAA;AACpC,OAAO,mBAAmB,CAAA;AAC1B,OAAO,6BAA6B,CAAA;AACpC,OAAO,uBAAuB,CAAA;AAC9B,OAAO,oBAAoB,CAAA;AAC3B,OAAO,6BAA6B,CAAA;AACpC,OAAO,yBAAyB,CAAA;AAChC,OAAO,2BAA2B,CAAA;AAClC,OAAO,yBAAyB,CAAA;AAChC,OAAO,oBAAoB,CAAA;AAC3B,OAAO,2BAA2B,CAAA"}
package/dist/cli/help.mjs CHANGED
@@ -36,7 +36,7 @@ Commands:
36
36
  task close-merged <dir> [--task <id>] [--narrate-only] [--dry-run] Sweep shipped-pending-merge tasks for confirmed merges (--narrate-only returns pending_narration[] entries read-only without closing).
37
37
  task narration-drain <dir> --task <task-id> Remove a row from state.pending_narration[] under withFileLock (called by /apt:close-task --narrate-only after a successful narrator spawn)
38
38
  task complete-subtask <dir> --task-id <id> --subtask-id <sid|a+b+c> [--commit <sha>] [--notes <text>] Atomic plan ↔ build-progress sync
39
- features-audit <dir> [--task-id <id>] [--no-worktree-redirect] [--diff-files <csv>|--since <ref>] [--apply-stubs] [--format json|md] Audit features registry for unregistered feature-qualifying files (BUG-025b: --task-id redirects writes to active task's worktree)
39
+ features-reconcile <dir> (--draft|--write|--check|--gc) [--task-id <id>] [--subtask-id <id>] [--base <ref>] [--dry-run] [--warn-only] [--max-age-days <n>] [--no-worktree-redirect] Feature-registry delta ledger: --draft scaffolds a per-writer delta from the base..HEAD diff, --write materializes deltas into area JSONs + a receipt, --check verifies coverage/schema/integrity/orphans, --gc prunes merged receipts (BUG-025b: --task-id redirects writes to active task's worktree)
40
40
  docs-audit <dir> [--diff-files <csv>|--since <ref>|--dry-run] [--policy <path>] [--format json|md] Audit documented surfaces for docs-drift
41
41
 
42
42
  lock claim <dir> --subtask <id> Claim exclusive lock on a subtask
@@ -6,8 +6,8 @@
6
6
  * should grow a `Release note: …` line OR ship should block.
7
7
  *
8
8
  * This module is intentionally pure — the apt-ship SKILL.md body shells
9
- * `apt-tools features-audit . --diff-since <base> --json` and feeds the
10
- * envelope here. Keeping the decision pure makes TD-4 trivial: fixture in,
9
+ * `apt-tools features-reconcile . --draft --dry-run --base "$base"` and feeds
10
+ * the envelope here. Keeping the decision pure makes TD-4 trivial: fixture in,
11
11
  * decision out, no I/O.
12
12
  */
13
13
  import { buildPersonaTierMap, classifyFragment } from './persona-filter.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"gallery.d.mts","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"AA8CA;;;;;GAKG;AACH,qCAHW,YAAY,GACV,MAAM,CAkFlB;AAID;;;;;;;;;GASG;AACH,uDAJW,MAAM,EAAE,kBACR,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,GAClE;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAyB7D;6BArJY;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;2BAC1E;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE"}
1
+ {"version":3,"file":"gallery.d.mts","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"AAkDA;;;;;GAKG;AACH,qCAHW,YAAY,GACV,MAAM,CAkFlB;AAID;;;;;;;;;GASG;AACH,uDAJW,MAAM,EAAE,kBACR,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC,GAClE;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAyB7D;6BArJY;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE;2BAC1E;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE"}
@@ -12,6 +12,10 @@
12
12
  * no privilege for that). Picking happens by running a terminal
13
13
  * command — the gallery's job is to make the letter obvious and the
14
14
  * command copy-pasteable.
15
+ * - Each card links to its variant file via a plain relative anchor
16
+ * with target="_blank", so the user can open any variant full-size
17
+ * in a new tab straight from the gallery (relative hrefs resolve
18
+ * against the gallery's own file:// URL — no server needed).
15
19
  * - Responsive grid: 1 column on narrow, 2 on medium, N on wide.
16
20
  * - Each variant iframe is rendered at full device-width-feel, not a
17
21
  * thumbnail, so the user can actually read the content.
@@ -74,11 +78,11 @@ export function renderGallery(input) {
74
78
  ` <div class="truncate text-xs text-slate-400">${description}</div>`,
75
79
  ' </div>',
76
80
  ' </div>',
77
- ` <code class="shrink-0 rounded bg-slate-800 px-2 py-1 text-xs text-slate-300">${filename}</code>`,
81
+ ` <a href="${filename}" target="_blank" rel="noopener" title="Open variant ${letter} in a new tab" class="shrink-0 rounded bg-slate-800 px-2 py-1 text-xs text-slate-300 hover:bg-slate-700 hover:text-slate-100"><code>${filename}</code> ↗</a>`,
78
82
  ' </header>',
79
83
  ` <iframe src="${filename}" title="Variant ${letter}" loading="lazy" class="block h-[720px] w-full bg-white"></iframe>`,
80
84
  ' <footer class="flex items-center justify-between gap-3 border-t border-slate-800 px-4 py-3">',
81
- ` <div class="text-xs text-slate-500">Pick this one:</div>`,
85
+ ` <a href="${filename}" target="_blank" rel="noopener" class="text-xs font-medium ${ACCENT} hover:underline">Open full size ↗</a>`,
82
86
  ` <code class="rounded bg-slate-800 px-2 py-1 text-xs text-slate-100">/apt:mockup --pick ${letter.toLowerCase()}</code>`,
83
87
  ' </footer>',
84
88
  ' </article>',
@@ -104,7 +108,7 @@ export function renderGallery(input) {
104
108
  ' <div>',
105
109
  ` <div class="text-xs uppercase tracking-[0.2em] text-slate-500">Variant gallery · iteration ${iterationEsc}</div>`,
106
110
  ` <h1 class="mt-1 text-2xl font-semibold text-slate-100">${featureEsc}</h1>`,
107
- ` <p class="mt-1 text-sm text-slate-400">${variants.length} parallel generations. Open this page via <code>file://</code>, scan the iframes, pick the letter that lands.</p>`,
111
+ ` <p class="mt-1 text-sm text-slate-400">${variants.length} parallel generations. Open this page via <code>file://</code>, scan the iframes, click “Open full size” to view any variant in its own tab, then pick the letter that lands.</p>`,
108
112
  ' </div>',
109
113
  ' <div class="flex flex-col gap-2 text-xs text-slate-400 sm:items-end">',
110
114
  ` <div>Directory: <code class="text-slate-300">${taskDirEsc}/mockups/</code></div>`,
@@ -1 +1 @@
1
- {"version":3,"file":"gallery.mjs","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gallery.mjs","sourceRoot":"","sources":["../../../src/cli/variant/gallery.mjs"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aperant",
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": {
6
6
  "name": "Mikalsen AI",
@@ -103,6 +103,12 @@ node packages/framework/bin/apt-tools.mjs commit "feat: {subtask.title}" --files
103
103
  ```
104
104
  Update `implementation_plan.json` status to `"completed"`. Write `build-progress.json`.
105
105
 
106
+ **Delta-emit (feature registry).** After the commit, scaffold this subtask's registry delta and enrich it while the build context is still in your window:
107
+ ```bash
108
+ node packages/framework/bin/apt-tools.mjs features-reconcile . --draft --task-id {task-id} --subtask-id {subtask.id}
109
+ ```
110
+ Fill every `needs-disposition` entry (`upsert` / `remove` / `wiring-transition` / `no-semantic-change` — the last needs a one-line `reason`), assign any `area: null`, and replace draft upsert stubs with real `sub_features` carrying `wired`/`handler`/`test_hint`. Then stage the delta and amend it into the subtask commit: `git add .aperant/features/deltas/ && git commit --amend --no-edit`. Non-blocking: on a reconcile glitch, log and continue — the ship gate + CI check catch real gaps.
111
+
106
112
  ### 3f. Checkpoint State
107
113
  `build-progress.json` is written every subtask in 3e — that is the durable resume point. Do NOT self-estimate context. Do NOT voluntarily exit. Keep executing until the plan is complete or a risk gate stops you. If the harness auto-compacts mid-run, re-read `{task_dir}/implementation_plan.json` + `{task_dir}/build-progress.json` after compaction and continue from the next pending subtask — the checkpoint is authoritative, your in-memory state is not.
108
114
 
@@ -190,8 +190,9 @@ Two policy buckets, two behaviors:
190
190
  finding if you omit it.
191
191
  - **`auto-update`** (default for milestones.json, REGISTRY.md,
192
192
  project_index.json, .aperant/tasks/**): a doc subtask that invokes the
193
- appropriate apt-tools subcommand (`features-audit --apply-stubs`,
194
- `roadmap rollup`, etc.) so the internal state stays coherent.
193
+ appropriate apt-tools subcommand (`features-reconcile --draft` at the
194
+ executor's delta-emit step, `roadmap rollup`, etc.) so the internal
195
+ state stays coherent.
195
196
 
196
197
  Bias toward false positives — a no-op doc subtask costs nothing; a missed
197
198
  drift finding ships to the user. Full rules in
@@ -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).
@@ -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
  }