@haposoft/cafekit 0.16.7 → 0.18.1

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 (231) hide show
  1. package/README.md +14 -22
  2. package/bin/__tests__/codex-hooks-ownership.test.js +2 -2
  3. package/bin/__tests__/codex-hooks.test.js +169 -272
  4. package/bin/__tests__/codex-native.test.js +100 -202
  5. package/bin/__tests__/develop-contract.test.js +122 -1413
  6. package/bin/__tests__/docs-sync-on-demand.test.js +93 -0
  7. package/bin/__tests__/grok-envelope.test.js +0 -56
  8. package/bin/__tests__/hook-payload.test.js +4 -6
  9. package/bin/__tests__/legacy-authority-decoupled.test.js +154 -0
  10. package/bin/__tests__/legacy-hooks-retired.test.js +221 -0
  11. package/bin/__tests__/omp-bridge.test.js +20 -17
  12. package/bin/__tests__/omp-hooks.test.js +0 -19
  13. package/bin/__tests__/optional-skill-inventory.test.js +112 -4
  14. package/bin/__tests__/orca-session.test.js +0 -2
  15. package/bin/__tests__/package-inventory.test.js +90 -925
  16. package/bin/__tests__/runtime-dir.test.js +0 -3
  17. package/bin/__tests__/runtime-schema.test.js +3 -2
  18. package/bin/__tests__/skill-routing-source.test.js +27 -15
  19. package/bin/__tests__/spec-narrowing.test.js +30 -161
  20. package/bin/__tests__/specs-v2-execution-closeout.test.js +0 -437
  21. package/bin/__tests__/test-runtime-dependency-closure.cjs +1 -2
  22. package/bin/__tests__/ui-ux-skill.test.js +101 -0
  23. package/bin/__tests__/usage-hook-retired.test.js +114 -0
  24. package/bin/__tests__/validator-grounding.test.js +18 -2949
  25. package/bin/lib/managed-writer.js +2 -3
  26. package/bin/phases/codex-runtime.js +27 -0
  27. package/bin/phases/copy-payload.js +13 -28
  28. package/bin/phases/omp-runtime.js +25 -0
  29. package/package.json +2 -3
  30. package/src/claude/CLAUDE.md +3 -10
  31. package/src/claude/agents/brainstormer.md +7 -3
  32. package/src/claude/agents/code-auditor.md +44 -56
  33. package/src/claude/agents/debugger.md +8 -88
  34. package/src/claude/agents/deployer.md +3 -5
  35. package/src/claude/agents/docs-keeper.md +6 -14
  36. package/src/claude/agents/git-ops.md +2 -4
  37. package/src/claude/agents/implementer.md +12 -16
  38. package/src/claude/agents/inspector.md +4 -3
  39. package/src/claude/agents/project-manager.md +9 -17
  40. package/src/claude/agents/researcher.md +9 -3
  41. package/src/claude/agents/spec-maker.md +15 -15
  42. package/src/claude/agents/test-runner.md +8 -11
  43. package/src/claude/agents/ui-ux-designer.md +0 -1
  44. package/src/claude/hooks/__tests__/fixtures/statusline-default.golden +1 -1
  45. package/src/claude/hooks/__tests__/spec-gate.test.js +244 -333
  46. package/src/claude/hooks/__tests__/spec-state-touched.test.js +160 -0
  47. package/src/claude/hooks/__tests__/state.test.js +68 -0
  48. package/src/claude/hooks/__tests__/statusline.test.js +140 -11
  49. package/src/claude/hooks/agent.cjs +2 -1
  50. package/src/claude/hooks/lib/hook-payload.cjs +2 -2
  51. package/src/claude/hooks/rules.cjs +2 -1
  52. package/src/claude/hooks/session.cjs +0 -1
  53. package/src/claude/hooks/spec-gate.cjs +17 -83
  54. package/src/claude/hooks/spec-state.cjs +142 -39
  55. package/src/claude/hooks/state.cjs +21 -2
  56. package/src/claude/migration-manifest.json +42 -22
  57. package/src/claude/output-styles/coding-level-0-eli5.md +9 -9
  58. package/src/claude/output-styles/coding-level-1-junior.md +3 -3
  59. package/src/claude/output-styles/coding-level-2-mid.md +3 -3
  60. package/src/claude/output-styles/coding-level-3-senior.md +2 -2
  61. package/src/claude/output-styles/coding-level-4-lead.md +5 -5
  62. package/src/claude/output-styles/coding-level-5-god.md +6 -6
  63. package/src/claude/rules/ai-dev-rules.md +2 -3
  64. package/src/claude/rules/hook-protocols.md +8 -15
  65. package/src/claude/rules/manage-docs.md +9 -23
  66. package/src/claude/rules/orchestrator.md +3 -4
  67. package/src/claude/rules/review-audit-self-decision.md +3 -3
  68. package/src/claude/rules/skill-domain-routing.md +1 -3
  69. package/src/claude/rules/skill-workflow-routing.md +4 -5
  70. package/src/claude/rules/state-sync.md +3 -12
  71. package/src/claude/rules/workflow.md +11 -19
  72. package/src/claude/runtime.schema.json +5 -3
  73. package/src/claude/scripts/generate-skill-catalog.cjs +7 -6
  74. package/src/claude/scripts/provenance.cjs +23 -5
  75. package/src/claude/scripts/spec-receipt.cjs +24 -121
  76. package/src/claude/scripts/spec-resolver.cjs +41 -458
  77. package/src/claude/scripts/workflow-policy.cjs +3 -1801
  78. package/src/claude/settings/settings.json +1 -32
  79. package/src/claude/skills/agent-browser/SKILL.md +1 -1
  80. package/src/claude/skills/{question → ask}/SKILL.md +9 -75
  81. package/src/claude/skills/brainstorm/SKILL.md +43 -131
  82. package/src/claude/skills/chrome-devtools/SKILL.md +14 -31
  83. package/src/claude/skills/code-review/SKILL.md +29 -81
  84. package/src/claude/skills/code-review/references/spec-compliance-review.md +4 -8
  85. package/src/claude/skills/debug/SKILL.md +29 -149
  86. package/src/claude/skills/develop/SKILL.md +26 -83
  87. package/src/claude/skills/develop/references/parallel-waves.md +0 -8
  88. package/src/claude/skills/develop/references/quality-gate.md +15 -13
  89. package/src/claude/skills/develop/references/subagent-patterns.md +0 -6
  90. package/src/claude/skills/docs/SKILL.md +2 -2
  91. package/src/claude/skills/docs/references/update-workflow.md +1 -1
  92. package/src/claude/skills/fix/SKILL.md +153 -0
  93. package/src/claude/skills/{hotfix → fix}/references/diagnosis-protocol.md +2 -2
  94. package/src/claude/skills/{hotfix → fix}/references/parallel-patterns.md +2 -2
  95. package/src/claude/skills/{hotfix → fix}/references/prevention-gate.md +3 -3
  96. package/src/claude/skills/{hotfix → fix}/references/review-cycle.md +1 -1
  97. package/src/claude/skills/git/SKILL.md +48 -9
  98. package/src/claude/skills/git/references/commit-protocols.md +35 -16
  99. package/src/claude/skills/git/references/worktree-blueprint.md +42 -6
  100. package/src/claude/skills/orca/SKILL.md +9 -8
  101. package/src/claude/skills/research/SKILL.md +17 -46
  102. package/src/claude/skills/scout/SKILL.md +61 -0
  103. package/src/claude/skills/{inspect → scout}/references/internal-inspection.md +26 -10
  104. package/src/claude/skills/specs/SKILL.md +22 -29
  105. package/src/claude/skills/specs/references/review.md +8 -6
  106. package/src/claude/skills/specs/references/templates.md +34 -41
  107. package/src/claude/skills/sync/SKILL.md +16 -45
  108. package/src/claude/skills/sync/references/rebind-and-audit.md +59 -0
  109. package/src/claude/skills/sync/references/sync-protocols.md +4 -13
  110. package/src/claude/skills/test/SKILL.md +39 -104
  111. package/src/claude/skills/test/references/execution-strategy.md +93 -21
  112. package/src/claude/skills/test/references/failure-triage.md +1 -1
  113. package/src/claude/skills/ui-ux/LICENSE +21 -0
  114. package/src/claude/skills/ui-ux/SKILL.md +497 -0
  115. package/src/claude/skills/ui-ux/references/brand-tokens.md +90 -0
  116. package/src/claude/skills/ui-ux/references/budgets.md +113 -0
  117. package/src/claude/skills/ui-ux/references/checklist.md +271 -0
  118. package/src/claude/skills/ui-ux/references/components/accordion.md +246 -0
  119. package/src/claude/skills/ui-ux/references/components/avatar.md +153 -0
  120. package/src/claude/skills/ui-ux/references/components/banner.md +43 -0
  121. package/src/claude/skills/ui-ux/references/components/breadcrumb.md +201 -0
  122. package/src/claude/skills/ui-ux/references/components/button.md +142 -0
  123. package/src/claude/skills/ui-ux/references/components/card.md +113 -0
  124. package/src/claude/skills/ui-ux/references/components/charts.md +376 -0
  125. package/src/claude/skills/ui-ux/references/components/chat.md +132 -0
  126. package/src/claude/skills/ui-ux/references/components/choice-controls.md +369 -0
  127. package/src/claude/skills/ui-ux/references/components/comment-thread.md +17 -0
  128. package/src/claude/skills/ui-ux/references/components/description-list.md +116 -0
  129. package/src/claude/skills/ui-ux/references/components/empty-state.md +98 -0
  130. package/src/claude/skills/ui-ux/references/components/file-upload.md +107 -0
  131. package/src/claude/skills/ui-ux/references/components/inline-edit.md +128 -0
  132. package/src/claude/skills/ui-ux/references/components/input.md +161 -0
  133. package/src/claude/skills/ui-ux/references/components/list-row.md +56 -0
  134. package/src/claude/skills/ui-ux/references/components/loading.md +198 -0
  135. package/src/claude/skills/ui-ux/references/components/logo.md +147 -0
  136. package/src/claude/skills/ui-ux/references/components/otp-input.md +43 -0
  137. package/src/claude/skills/ui-ux/references/components/quantity-input.md +100 -0
  138. package/src/claude/skills/ui-ux/references/components/range-slider.md +16 -0
  139. package/src/claude/skills/ui-ux/references/components/small-controls.md +340 -0
  140. package/src/claude/skills/ui-ux/references/components/sortable-header.md +86 -0
  141. package/src/claude/skills/ui-ux/references/components/tag-input.md +14 -0
  142. package/src/claude/skills/ui-ux/references/components/timeline.md +38 -0
  143. package/src/claude/skills/ui-ux/references/components/tree.md +30 -0
  144. package/src/claude/skills/ui-ux/references/design-process.md +650 -0
  145. package/src/claude/skills/ui-ux/references/layouts/app-kanban.html +303 -0
  146. package/src/claude/skills/ui-ux/references/layouts/app.md +1369 -0
  147. package/src/claude/skills/ui-ux/references/layouts/form.md +430 -0
  148. package/src/claude/skills/ui-ux/references/layouts/overlay.md +552 -0
  149. package/src/claude/skills/ui-ux/references/layouts/pricing.md +204 -0
  150. package/src/claude/skills/ui-ux/references/locked-rules.md +35 -0
  151. package/src/claude/skills/ui-ux/references/principles.md +408 -0
  152. package/src/claude/skills/ui-ux/references/refactor.md +245 -0
  153. package/src/claude/skills/ui-ux/references/responsive.md +195 -0
  154. package/src/claude/skills/ui-ux/references/review.md +528 -0
  155. package/src/claude/skills/ui-ux/references/rules-color.md +623 -0
  156. package/src/claude/skills/ui-ux/references/rules-form.md +235 -0
  157. package/src/claude/skills/ui-ux/references/rules-state.md +680 -0
  158. package/src/claude/skills/ui-ux/references/rules-type.md +369 -0
  159. package/src/claude/skills/ui-ux/references/styles.md +311 -0
  160. package/src/claude/skills/ui-ux/references/system.md +219 -0
  161. package/src/claude/skills/ui-ux/references/tailwind-v4-traps.md +237 -0
  162. package/src/claude/skills/ui-ux/references/tokens.css +362 -0
  163. package/src/claude/skills/ui-ux/scripts/lint-skill.mjs +216 -0
  164. package/src/claude/skills/ui-ux/scripts/package.json +9 -0
  165. package/src/claude/skills/ui-ux/scripts/probe.mjs +4447 -0
  166. package/src/claude/skills/ui-ux-pro-max/SKILL.md +25 -80
  167. package/src/claude/skills/web-testing/SKILL.md +2 -20
  168. package/src/claude/status.cjs +149 -144
  169. package/src/codex/AGENTS.md +8 -13
  170. package/src/codex/hooks/agent.cjs +2 -1
  171. package/src/codex/hooks/lib/spec-receipt.cjs +4 -32
  172. package/src/codex/hooks/lib/spec-utils.cjs +6 -52
  173. package/src/codex/hooks/rules.cjs +2 -1
  174. package/src/codex/hooks/session.cjs +0 -2
  175. package/src/codex/hooks/spec-gate.cjs +13 -81
  176. package/src/codex/hooks/spec-state.cjs +37 -41
  177. package/src/codex/hooks.json +0 -20
  178. package/src/codex/rules/state-sync.md +3 -12
  179. package/src/common/AGENTS.md +6 -12
  180. package/src/omp/extensions/cafekit-bridge.mjs +6 -6
  181. package/bin/__tests__/change-firewall.semantic-firewall.test.js +0 -2133
  182. package/bin/__tests__/finalizer-pass-gate.semantic-firewall.test.js +0 -342
  183. package/bin/__tests__/release-preflight.semantic-firewall.test.js +0 -586
  184. package/bin/__tests__/review-receipt-c2.semantic-firewall.test.js +0 -378
  185. package/bin/__tests__/specs-v2-policy-and-scaffold.test.js +0 -665
  186. package/bin/__tests__/specs-v2-validator-grounder-contract.test.js +0 -1132
  187. package/src/claude/hooks/__tests__/completion-authority.test.js +0 -990
  188. package/src/claude/hooks/__tests__/semantic-review-authority.test.js +0 -259
  189. package/src/claude/hooks/completion-authority-check.cjs +0 -56
  190. package/src/claude/hooks/completion-authority-state.cjs +0 -527
  191. package/src/claude/hooks/completion-authority.cjs +0 -163
  192. package/src/claude/hooks/lib/context.cjs +0 -616
  193. package/src/claude/hooks/lib/detect.cjs +0 -474
  194. package/src/claude/hooks/semantic-review-authority.cjs +0 -154
  195. package/src/claude/hooks/task-scaffold-guard.cjs +0 -114
  196. package/src/claude/hooks/usage.cjs +0 -197
  197. package/src/claude/scripts/change-firewall.cjs +0 -1748
  198. package/src/claude/scripts/spec-authoring-digest.cjs +0 -151
  199. package/src/claude/scripts/spec-authoring-validation.cjs +0 -126
  200. package/src/claude/scripts/spec-final-state.cjs +0 -290
  201. package/src/claude/scripts/spec-ground.cjs +0 -650
  202. package/src/claude/scripts/spec-readiness.cjs +0 -425
  203. package/src/claude/scripts/spec-scaffold.cjs +0 -2317
  204. package/src/claude/scripts/spec-semantic-model.cjs +0 -396
  205. package/src/claude/scripts/validate-spec-output.cjs +0 -3941
  206. package/src/claude/skills/code-review/references/verification-gate.md +0 -46
  207. package/src/claude/skills/delegate/SKILL.md +0 -124
  208. package/src/claude/skills/delegate/references/codex-delegation.md +0 -71
  209. package/src/claude/skills/delegate/references/grok-delegation.md +0 -84
  210. package/src/claude/skills/hotfix/SKILL.md +0 -289
  211. package/src/claude/skills/inspect/SKILL.md +0 -142
  212. package/src/claude/skills/loop/SKILL.md +0 -114
  213. package/src/claude/skills/loop/references/bounded-loop-protocol.md +0 -104
  214. package/src/claude/skills/loop/references/metric-and-guard-contract.md +0 -76
  215. package/src/claude/skills/route/SKILL.md +0 -94
  216. package/src/claude/skills/route/references/agent-timing.md +0 -46
  217. package/src/claude/skills/route/references/chaining-patterns.md +0 -53
  218. package/src/claude/skills/route/references/task-taxonomy.md +0 -48
  219. package/src/claude/skills/specs/templates/design.md +0 -82
  220. package/src/claude/skills/specs/templates/requirements-init.md +0 -8
  221. package/src/claude/skills/specs/templates/requirements.md +0 -42
  222. package/src/claude/skills/specs/templates/spec-state.json +0 -56
  223. package/src/claude/skills/specs/templates/task.md +0 -47
  224. package/src/codex/hooks/completion-authority-check.cjs +0 -67
  225. package/src/codex/hooks/completion-authority-state.cjs +0 -527
  226. package/src/codex/hooks/completion-authority.cjs +0 -109
  227. package/src/codex/hooks/semantic-review-authority.cjs +0 -130
  228. package/src/codex/hooks/task-scaffold-guard.cjs +0 -63
  229. /package/src/claude/skills/{question → ask}/templates/question.md +0 -0
  230. /package/src/claude/skills/{hotfix → fix}/references/escalation-tactics.md +0 -0
  231. /package/src/claude/skills/{hotfix → fix}/references/workflow-specialized.md +0 -0
@@ -69,7 +69,7 @@ const DOCS_ADAPTIVE_BUNDLE = [
69
69
  'references/update-workflow.md',
70
70
  'references/standard-docs-workflow.md'
71
71
  ];
72
- const HOTFIX_SOURCE_ROOT = path.join(PACKAGE_ROOT, 'src/claude/skills/hotfix');
72
+ const HOTFIX_SOURCE_ROOT = path.join(PACKAGE_ROOT, 'src/claude/skills/fix');
73
73
  const HOTFIX_BUNDLE = [
74
74
  'SKILL.md',
75
75
  'references/diagnosis-protocol.md',
@@ -111,7 +111,7 @@ function boundaryTableHasRequiredRows(table) {
111
111
  }
112
112
 
113
113
  const IMPLEMENTATION_READINESS_CLAUSES = {
114
- noInvention: 'Before implementation handoff, apply the **no-invention gate**: if two implementations conform to the packet text yet can produce different externally observable output, state, error, security, or compatibility behavior, surface the missing choice as an explicit C1 or C2 question and block handoff.',
114
+ noInvention: 'Before implementation handoff, apply the **no-invention gate**: if two implementations conform to the packet text yet can produce different externally observable output, state, error, security, or compatibility behavior, surface the missing choice as an explicit GATE-SCOPE or GATE-REVIEW question and block handoff.',
115
115
  materialDefinition: 'A boundary is material when the task creates, changes, or depends on it and a different choice changes an external observation, security, durable data, compatibility, or proof reachability. Require only the matching material row; omit nonmaterial categories.',
116
116
  exactBoundaryChoices: 'For every required row, name each listed choice exactly; labels such as “JSON”, “local path”, “locked”, or “timestamped” alone remain unresolved.',
117
117
  proofPlanLines: [
@@ -130,11 +130,11 @@ const IMPLEMENTATION_READINESS_CLAUSES = {
130
130
  disposableReviewControls: 'Run mutation or destructive negative controls only on disposable copies below a verified temporary root, never tracked worktree or canonical source bytes.',
131
131
  failureSemantics: '`Crash` means abrupt unhandled termination before the claimed catch point; a catchable failure returns/raises an error or exits nonzero. Never use them interchangeably.',
132
132
  privacyIdentifiers: 'Any privacy/security claim names the exact identifier surface at risk, such as an env var, header, path, token class, or field name; generic “sensitive data” is insufficient.',
133
- freshReplay: 'After applying an accepted C2 finding, a fresh-context closure pass records and freshly replays its original counterexample after the repair under this exact review-log header:',
133
+ freshReplay: 'After applying an accepted GATE-REVIEW finding, a fresh-context closure pass records and freshly replays its original counterexample after the repair under this exact review-log header:',
134
134
  distinctRepairProof: '`Repaired at` cites the repair edit; `Proved at` must cite distinct evidence from the fresh replay, never the repair-edit citation.',
135
135
  closureTransition: 'An accepted finding transitions `accepted → repaired → PASS|FAIL|UNKNOWN`.',
136
136
  unknownBlocks: 'Only `PASS` closes it; `FAIL` remains open for the remaining paper-review round; `UNKNOWN` blocks implementation handoff.',
137
- scopeReturnsToC1: 'A repair that adds user semantics or scope returns to C1.'
137
+ scopeReturnsToC1: 'A repair that adds user semantics or scope returns to GATE-SCOPE.'
138
138
  };
139
139
  const ADAPTIVE_COVERAGE_PROFILE_HEADER = [
140
140
  'ID', 'Outcome', 'Change kinds', 'Material surfaces', 'Ambiguity/action',
@@ -148,7 +148,7 @@ const ADAPTIVE_COVERAGE_AMBIGUITY_ROWS = [
148
148
  ['State', 'Required action'],
149
149
  ['`none`', 'proceed'],
150
150
  ['`examples-needed`', 'add two or three examples only for an already decided rule; promote to `decision-needed` if an example changes observable behavior'],
151
- ['`decision-needed`', 'ask the user at C1/C2 and keep affected tasks blocked'],
151
+ ['`decision-needed`', 'ask the user at GATE-SCOPE/GATE-REVIEW and keep affected tasks blocked'],
152
152
  ['`design-needed`', 'after user-owned decisions settle, route material competing technical designs through Brainstorm']
153
153
  ];
154
154
  const ADAPTIVE_REVIEWER_ROWS = [
@@ -169,12 +169,12 @@ const ADAPTIVE_COVERAGE_CLAUSES = {
169
169
  openKinds: 'Change kinds are multi-valued (`add`, `modify`, `fix`, `refactor`, `remove`, `migrate`, `integrate`), and unfamiliar kinds or surfaces use `other:<verbatim>` rather than disappearing.',
170
170
  scopedUnion: 'Each task references its CP IDs; authoring, review, edge, and proof obligations union only inside affected rows/tasks.',
171
171
  profileRederivation: 'Rederive affected CP rows after any accepted scope, outcome, criteria, ownership, dependency, risk, or proof delta before task status.',
172
- plannedProof: '`Required proof` is a planned level set, not execution\nevidence: known but unrun proof may be `pending`; `UNKNOWN` reachability blocks\n`pending`; missing, failed, or unavailable required evidence blocks `done`/C3.',
172
+ plannedProof: '`Required proof` is a planned level set, not execution\nevidence: known but unrun proof may be `pending`; `UNKNOWN` reachability blocks\n`pending`; missing, failed, or unavailable required evidence blocks `done`/GATE-DONE.',
173
173
  proofSeparation: 'Levels stay separate and never promote one another.',
174
174
  liveLimit: 'Source/static checks prove the written contract, not live-model adherence.',
175
175
  specMakerAuthority: 'they are the canonical risk and coverage authority. Do not duplicate\ntheir taxonomy here.',
176
176
  specMakerAmbiguity: 'Apply the canonical ambiguity action; examples never decide observable behavior.',
177
- specMakerRoute: 'Apply their risk-first route before C1 and stop when the\nrequest qualifies for direct work; hand off when it requires Brainstorm-only exploration.',
177
+ specMakerRoute: 'Apply their risk-first route before GATE-SCOPE and stop when the\nrequest qualifies for direct work; hand off when it requires Brainstorm-only exploration.',
178
178
  reviewRisk: 'Keep Fact Checker as the baseline. Assign every remaining material CP risk to a\nnamed reviewer lens; a critical row includes both relevant security-adversary and\nfailure-mode coverage, and nonmaterial lenses are not added.',
179
179
  reviewCapacity: 'Reviewer count is fixed by the table, not lens count. Give each reviewer a distinct primary lens; when material lenses exceed reviewers, combine related named lenses on one reviewer and keep every material lens assigned.'
180
180
  };
@@ -182,12 +182,7 @@ const V3_SPECS_BUNDLE = [
182
182
  'SKILL.md',
183
183
  'references/review.md',
184
184
  'references/templates.md',
185
- 'templates/design.md',
186
- 'templates/requirements-init.md',
187
- 'templates/requirements.md',
188
- 'templates/research.md',
189
- 'templates/spec-state.json',
190
- 'templates/task.md'
185
+ 'templates/research.md'
191
186
  ];
192
187
  const OBSOLETE_SPECS_FILES = [
193
188
  'references/archive-workflow.md',
@@ -272,64 +267,6 @@ function replaceGeneratedTomlString(content, key, value) {
272
267
  return content.replace(pattern, `${key} = ${JSON.stringify(value)}`);
273
268
  }
274
269
 
275
- function renderCanonicalVerificationExample(template) {
276
- const values = new Map([
277
- ['SUBJECT_REQ', '1'],
278
- ['X', '1'],
279
- ['PROOF_REQ', '1'],
280
- ['Y', '2'],
281
- ['exact command', 'node --test test/installed.test.js'],
282
- ['exact anchored target', 'src/installed.js#entry'],
283
- ['exact/repository/entrypoint', 'src/installed.js'],
284
- ['observable result', 'the subject behavior and verifier proof both pass'],
285
- ['concrete observable result and proof', 'the subject behavior and verifier proof both pass'],
286
- ['concrete rejected or recovery case', 'invalid input remains rejected and observable'],
287
- ['real entrypoint/caller and grounded anchor expectation', 'the installed entrypoint reaches A-D-01'],
288
- ]);
289
- return template.replace(/\{\{([^}]+)\}\}/g, (placeholder, name) => (
290
- values.has(name) ? values.get(name) : placeholder
291
- ));
292
- }
293
-
294
- function assertInstalledVerificationModel(grounderPath, designTemplate) {
295
- const { parseVerificationDefinitions } = require(grounderPath);
296
- assert.equal(typeof parseVerificationDefinitions, 'function');
297
- const concreteDesign = renderCanonicalVerificationExample(designTemplate);
298
- const errors = [];
299
- const definitions = parseVerificationDefinitions(concreteDesign, errors);
300
- assert.deepEqual(errors, []);
301
- assert.equal(definitions.size, 1);
302
- const definition = definitions.get('V1');
303
- assert.ok(definition);
304
- assert.deepEqual(definition.subject_criteria, ['R1.1']);
305
- assert.deepEqual(definition.proof_criteria, []);
306
- assert.equal(definition.proof_owner, null);
307
- assert.equal(definition.evidence_anchor, null);
308
- assert.deepEqual(definition.decision_refs, ['D1', 'I1', 'C1']);
309
- for (const field of [
310
- 'subject_criteria', 'subject_owner', 'decision_refs', 'method', 'expected',
311
- 'negative', 'reachability'
312
- ]) {
313
- const value = definition[field];
314
- assert.ok(
315
- Array.isArray(value)
316
- ? value.length > 0
317
- : (typeof value === 'string' ? value.trim() !== '' : value && Object.keys(value).length > 0)
318
- );
319
- }
320
- for (const mutation of [
321
- concreteDesign.replace('- **V1**:', '### V1 —'),
322
- concreteDesign.replace('- **V1**:', '| V1 |'),
323
- concreteDesign.replace('; Expected ', '\nExpected '),
324
- concreteDesign.replace('Decision refs ', 'Decisions '),
325
- ]) {
326
- const mutationErrors = [];
327
- const mutated = parseVerificationDefinitions(mutation, mutationErrors);
328
- assert.ok(mutationErrors.length > 0);
329
- assert.equal(mutated.has('V1'), false);
330
- }
331
- }
332
-
333
270
  function markdownSection(content, heading) {
334
271
  const lines = String(content).split('\n');
335
272
  const start = lines.findIndex((line) => line.trim() === `## ${heading}`);
@@ -558,7 +495,7 @@ function authoringProjectionIssues(files) {
558
495
  || !files.templates.includes('task-NN-<slug>.md')) {
559
496
  issues.push('flat-layout-template');
560
497
  }
561
- for (const gate of ['C1 — Scope', 'C2 — Findings', 'C3 — Done']) {
498
+ for (const gate of ['GATE-SCOPE', 'GATE-REVIEW', 'GATE-DONE']) {
562
499
  if (!files.skill.includes(gate)) issues.push(`human-gate-${gate.slice(0, 2).toLowerCase()}`);
563
500
  }
564
501
  if (!files.review.includes('fresh-context red team')
@@ -596,7 +533,7 @@ function authoringProjectionIssues(files) {
596
533
  }
597
534
  if (!files.codex.includes('flat `task-NN-*.md` files')
598
535
  || !files.codex.includes('inline `## Receipt`')
599
- || !files.codex.includes('C1') || !files.codex.includes('C2') || !files.codex.includes('C3')) {
536
+ || !files.codex.includes('GATE-SCOPE') || !files.codex.includes('GATE-REVIEW') || !files.codex.includes('GATE-DONE')) {
600
537
  issues.push('codex-process-v3');
601
538
  }
602
539
  return [...new Set(issues)].sort();
@@ -1203,8 +1140,8 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
1203
1140
  name: 'fresh-original-counterexample-replay',
1204
1141
  issue: 'repair-closure',
1205
1142
  relative: 'references/review.md',
1206
- from: 'After applying an accepted C2 finding, a fresh-context closure pass records and\nfreshly replays its original counterexample after the repair under this exact review-log header:',
1207
- to: 'After applying an accepted C2 finding, record the repair under this review-log header:'
1143
+ from: 'After applying an accepted GATE-REVIEW finding, a fresh-context closure pass records and\nfreshly replays its original counterexample after the repair under this exact review-log header:',
1144
+ to: 'After applying an accepted GATE-REVIEW finding, record the repair under this review-log header:'
1208
1145
  },
1209
1146
  {
1210
1147
  name: 'distinct-repair-and-proof-evidence',
@@ -1313,7 +1250,7 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
1313
1250
  ['stale-profile-after-c2', 'templates', ADAPTIVE_COVERAGE_CLAUSES.profileRederivation,
1314
1251
  'Keep existing coverage rows after accepted plan changes.', ['profile-lifecycle']],
1315
1252
  ['planned-proof-blocks-start', 'templates', ADAPTIVE_COVERAGE_CLAUSES.plannedProof,
1316
- '`Required proof` is execution evidence: known but unrun proof blocks `pending`; `UNKNOWN` may proceed; missing evidence may still reach `done`/C3.', ['proof-lifecycle']],
1253
+ '`Required proof` is execution evidence: known but unrun proof blocks `pending`; `UNKNOWN` may proceed; missing evidence may still reach `done`/GATE-DONE.', ['proof-lifecycle']],
1317
1254
  ['source-promotes-live', 'templates', ADAPTIVE_COVERAGE_CLAUSES.proofSeparation,
1318
1255
  'Source proof may promote installed and live proof.', ['proof-lifecycle']],
1319
1256
  ['unmapped-proof-level', 'templates', IMPLEMENTATION_READINESS_CLAUSES.proofLevelMapping,
@@ -1327,7 +1264,7 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
1327
1264
  ['spec-maker-examples-decide', 'specMaker', ADAPTIVE_COVERAGE_CLAUSES.specMakerAmbiguity,
1328
1265
  'Use examples to settle every ambiguous observable behavior.', ['spec-maker-authority']],
1329
1266
  ['spec-maker-skips-brainstorm', 'specMaker', ADAPTIVE_COVERAGE_CLAUSES.specMakerRoute,
1330
- 'Apply the risk-first route before C1 and stop only for direct work.', ['spec-maker-authority']],
1267
+ 'Apply the risk-first route before GATE-SCOPE and stop only for direct work.', ['spec-maker-authority']],
1331
1268
  ['static-proves-live', 'skill', ADAPTIVE_COVERAGE_CLAUSES.liveLimit,
1332
1269
  'Source/static checks prove live-model adherence.', ['proof-lifecycle']]
1333
1270
  ];
@@ -1561,13 +1498,15 @@ test('Codex structured-input corpus oracle stays differential and production-awa
1561
1498
  'src/claude/agents/spec-maker.md',
1562
1499
  'src/claude/hooks/session.cjs',
1563
1500
  'src/claude/skills/git/SKILL.md',
1564
- 'src/claude/skills/inspect/SKILL.md'
1501
+ 'src/claude/skills/scout/SKILL.md',
1502
+ 'src/claude/skills/sync/references/rebind-and-audit.md'
1565
1503
  ];
1566
1504
  assert.deepEqual(actualPaths, expectedPaths, 'every source occurrence needs an explicit projection oracle');
1567
1505
 
1568
1506
  const instructionExpectedSnippets = new Map([
1569
1507
  ['src/claude/skills/git/SKILL.md', 'Present options via a structured user-input request — header'],
1570
- ['src/claude/skills/inspect/SKILL.md', '**Fallback to a structured user-input request:**']
1508
+ ['src/claude/skills/scout/SKILL.md', '**Fallback to a structured user-input request:**'],
1509
+ ['src/claude/skills/sync/references/rebind-and-audit.md', 'End by asking with a structured user-input request when the host has']
1571
1510
  ]);
1572
1511
  for (const [relativePath, expectedSnippet] of instructionExpectedSnippets) {
1573
1512
  const sourcePath = path.join(PACKAGE_ROOT, relativePath);
@@ -1983,8 +1922,7 @@ test('Codex Windows hook launchers stay project-bound without Git from nested cw
1983
1922
  );
1984
1923
  const launchers = allHookLaunchers(config);
1985
1924
  assert.ok(launchers.length > 0, 'installed Codex config must register hook launchers');
1986
- const semanticReviewEvents = [];
1987
- for (const { event, handler } of launchers) {
1925
+ for (const { handler } of launchers) {
1988
1926
  assert.doesNotMatch(handler.commandWindows, /\$\(/);
1989
1927
  assert.doesNotMatch(handler.commandWindows, /\bgit\b/i);
1990
1928
  assert.doesNotMatch(handler.commandWindows, /process\.cwd\(\)|existsSync/);
@@ -1997,11 +1935,7 @@ test('Codex Windows hook launchers stay project-bound without Git from nested cw
1997
1935
  true,
1998
1936
  `missing installed hook: ${path.basename(target)}`
1999
1937
  );
2000
- if (path.basename(target) === 'semantic-review-authority.cjs') {
2001
- semanticReviewEvents.push(event);
2002
- }
2003
1938
  }
2004
- assert.deepEqual(semanticReviewEvents, ['SubagentStop']);
2005
1939
 
2006
1940
  const nested = path.join(projectRoot, 'nested', 'workspace');
2007
1941
  fs.mkdirSync(nested, { recursive: true });
@@ -2163,22 +2097,12 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2163
2097
  '.codex/rules/state-sync.md',
2164
2098
  '.codex/rules/review-audit-self-decision.md',
2165
2099
  '.codex/rules/process-management.md',
2166
- '.codex/scripts/spec-ground.cjs',
2167
- '.codex/scripts/validate-spec-output.cjs',
2168
2100
  '.agents/.gitignore',
2169
2101
  ...V3_SPECS_BUNDLE.map((file) => `.agents/skills/specs/${file}`)
2170
2102
  ]) {
2171
2103
  assert.equal(fs.existsSync(path.join(root, relative)), true, `missing ${relative}`);
2172
2104
  }
2173
2105
 
2174
- const installedDesign = fs.readFileSync(
2175
- path.join(root, '.agents/skills/specs/templates/design.md'), 'utf8'
2176
- );
2177
- assert.equal((installedDesign.match(/^## Verification Definitions$/gm) || []).length, 1);
2178
- assertInstalledVerificationModel(
2179
- path.join(root, '.codex/scripts/spec-ground.cjs'),
2180
- installedDesign
2181
- );
2182
2106
  const installedSpecsRoot = path.join(root, '.agents/skills/specs');
2183
2107
  assert.throws(
2184
2108
  () => installedAuthoringProjectionIssues(root, '.agents/skills/specs'),
@@ -2194,22 +2118,6 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2194
2118
  );
2195
2119
  assertInstalledAuthoringProjection(root, installedSpecsRoot);
2196
2120
 
2197
- const installedTask = fs.readFileSync(
2198
- path.join(root, '.agents/skills/specs/templates/task.md'), 'utf8'
2199
- );
2200
- assert.deepEqual(
2201
- [...installedTask.matchAll(/^## (.+)$/gm)].map((match) => match[1]),
2202
- ['Outcome', 'Scope', 'Anchors and Ownership', 'Changes', 'Acceptance', 'Dependencies', 'Verification Plan']
2203
- );
2204
- assert.match(installedTask, /^- \*\*Task role:\*\*/m);
2205
-
2206
- const installedState = JSON.parse(fs.readFileSync(
2207
- path.join(root, '.agents/skills/specs/templates/spec-state.json'), 'utf8'
2208
- ));
2209
- assert.deepEqual(Object.keys(installedState.workflow_policy).sort(), [
2210
- 'assurance_level', 'classified_minimum', 'planning_depth', 'risks', 'version'
2211
- ]);
2212
-
2213
2121
  const agentsGitignore = fs.readFileSync(
2214
2122
  path.join(root, '.agents', '.gitignore'),
2215
2123
  'utf8'
@@ -2220,7 +2128,6 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2220
2128
 
2221
2129
  if (process.platform !== 'win32') {
2222
2130
  for (const [sourceRelative, installedRelative] of [
2223
- ['src/claude/scripts/validate-spec-output.cjs', '.codex/scripts/validate-spec-output.cjs'],
2224
2131
  ['src/claude/skills/chrome-devtools/scripts/install.sh', '.agents/skills/chrome-devtools/scripts/install.sh'],
2225
2132
  ['src/claude/skills/ai-multimodal/scripts/check_setup.py', '.agents/skills/ai-multimodal/scripts/check_setup.py']
2226
2133
  ]) {
@@ -2260,24 +2167,24 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2260
2167
  assert.ok(skillNames.every((name) => /^[a-z0-9-]+$/.test(name)));
2261
2168
 
2262
2169
  const scoutSkill = fs.readFileSync(
2263
- path.join(root, '.agents', 'skills', 'inspect', 'SKILL.md'),
2170
+ path.join(root, '.agents', 'skills', 'scout', 'SKILL.md'),
2264
2171
  'utf8'
2265
2172
  );
2266
2173
  assert.match(scoutSkill, /^name:\s*cf-scout$/m);
2267
2174
  assert.equal(
2268
- fs.existsSync(path.join(root, '.agents', 'skills', 'scout')),
2175
+ fs.existsSync(path.join(root, '.agents', 'skills', 'inspect')),
2269
2176
  false,
2270
- 'public Scout rename must keep the manifest-owned inspect directory'
2177
+ 'Scout lives in the scout directory; the retired inspect directory must not be installed'
2271
2178
  );
2272
2179
  const askSkill = fs.readFileSync(
2273
- path.join(root, '.agents', 'skills', 'question', 'SKILL.md'),
2180
+ path.join(root, '.agents', 'skills', 'ask', 'SKILL.md'),
2274
2181
  'utf8'
2275
2182
  );
2276
2183
  assert.match(askSkill, /^name:\s*cf-ask$/m);
2277
2184
  assert.equal(
2278
- fs.existsSync(path.join(root, '.agents', 'skills', 'ask')),
2185
+ fs.existsSync(path.join(root, '.agents', 'skills', 'question')),
2279
2186
  false,
2280
- 'public Ask rename must keep the manifest-owned question directory'
2187
+ 'Ask lives in the ask directory; the retired question directory must not be installed'
2281
2188
  );
2282
2189
 
2283
2190
  const catalog = spawnSync(
@@ -2338,10 +2245,10 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2338
2245
  (key.startsWith('.codex/') || key.startsWith('.agents/')) && !key.includes('../')
2339
2246
  )));
2340
2247
 
2341
- const questionSkill = path.join(root, '.agents', 'skills', 'question', 'SKILL.md');
2248
+ const questionSkill = path.join(root, '.agents', 'skills', 'ask', 'SKILL.md');
2342
2249
  fs.appendFileSync(questionSkill, '\nUSER-CODEX-SENTINEL\n');
2343
2250
  // Fresh installs are exact. Refresh/upgrade intentionally documents the
2344
- // current Codex limitation: removed skill paths are not pruned.
2251
+ // A skill file the manifest lists as obsolete is removed on refresh; edited skills stay.
2345
2252
  const obsoleteSpecsRule = path.join(
2346
2253
  root, '.agents', 'skills', 'specs', 'rules', 'design-principles.md'
2347
2254
  );
@@ -2354,14 +2261,15 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2354
2261
  assert.match(fs.readFileSync(questionSkill, 'utf8'), /USER-CODEX-SENTINEL/);
2355
2262
  assert.equal(
2356
2263
  fs.existsSync(obsoleteSpecsRule),
2357
- true,
2358
- 'known limitation: Codex refresh does not prune obsolete skill files'
2264
+ false,
2265
+ 'Codex refresh removes obsolete skill files'
2359
2266
  );
2360
2267
 
2361
2268
  const metadataPath = path.join(root, '.codex', 'cafekit.json');
2362
2269
  const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
2363
2270
  metadata.version = '0.14.1';
2364
2271
  fs.writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`);
2272
+ fs.writeFileSync(obsoleteSpecsRule, 'LEGACY-CODEX-ORPHAN\n');
2365
2273
 
2366
2274
  const upgrade = install(root);
2367
2275
  assert.equal(upgrade.status, 0, `${upgrade.stdout}\n${upgrade.stderr}`);
@@ -2369,8 +2277,8 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
2369
2277
  assert.match(fs.readFileSync(questionSkill, 'utf8'), /USER-CODEX-SENTINEL/);
2370
2278
  assert.equal(
2371
2279
  fs.existsSync(obsoleteSpecsRule),
2372
- true,
2373
- 'known limitation: Codex upgrade does not prune obsolete skill files'
2280
+ false,
2281
+ 'Codex upgrade removes obsolete skill files'
2374
2282
  );
2375
2283
  assert.ok(fs.readFileSync(path.join(root, 'AGENTS.md'), 'utf8').startsWith(userInstructions));
2376
2284
 
@@ -2426,7 +2334,7 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
2426
2334
  const mutations = [
2427
2335
  {
2428
2336
  name: 'adaptive-direct-precedence-removed', source: 'skill',
2429
- from: 'Route Direct first, then\napply controls only to requests that remain in Brainstorm.',
2337
+ from: 'Route Direct first, then apply controls only to requests that remain in Brainstorm.',
2430
2338
  to: 'Apply controls before Direct classification.', expected: ['adaptive-direct-precedence']
2431
2339
  },
2432
2340
  {
@@ -2441,37 +2349,37 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
2441
2349
  },
2442
2350
  {
2443
2351
  name: 'adaptive-failure-isolation-removed', source: 'skill',
2444
- from: 'failure isolation for partial or cascading failure\nacross boundaries',
2352
+ from: 'failure isolation for partial or cascading failure across boundaries',
2445
2353
  to: 'generic failure notes', expected: ['adaptive-lens-trigger-skip']
2446
2354
  },
2447
2355
  {
2448
2356
  name: 'adaptive-evidence-fallback-removed', source: 'skill',
2449
- from: 'Missing evidence\nforces feasibility `unknown` and confidence `low`.',
2357
+ from: 'Missing evidence forces feasibility `unknown` and confidence `low`.',
2450
2358
  to: 'Missing evidence permits a confident guess.', expected: ['adaptive-evidence-semantics']
2451
2359
  },
2452
2360
  {
2453
2361
  name: 'adaptive-numeric-evidence-removed', source: 'skill',
2454
- from: 'A numeric estimate requires\nrange, unit, basis, evidence, and assumptions; otherwise report `unknown`.',
2362
+ from: 'A numeric estimate requires range, unit, basis, evidence, and assumptions; otherwise report `unknown`.',
2455
2363
  to: 'A numeric estimate may be a best-effort number.', expected: ['adaptive-numeric-estimates']
2456
2364
  },
2457
2365
  {
2458
2366
  name: 'adaptive-pre-tool-redaction-removed', source: 'skill',
2459
- from: 'Before an\nexternal visual tool or adviser handoff, minimize context and redact secrets,\ncredentials, private keys, access tokens, and unnecessary PII.',
2367
+ from: 'Before an external visual tool or adviser handoff, minimize context and redact secrets, credentials, private keys, access tokens, and unnecessary PII.',
2460
2368
  to: 'Forward full context to every external tool and adviser.', expected: ['adaptive-pre-tool-redaction']
2461
2369
  },
2462
2370
  {
2463
2371
  name: 'adaptive-adviser-gate-removed', source: 'skill',
2464
- from: '`--advice` invokes\n`brainstormer` only after the material-choice gate;',
2372
+ from: '`--advice` invokes `brainstormer` only after the material-choice gate;',
2465
2373
  to: '`--advice` invokes `brainstormer` before routing;', expected: ['adaptive-adviser-gate']
2466
2374
  },
2467
2375
  {
2468
2376
  name: 'adaptive-decision-freshness-removed', source: 'skill',
2469
- from: 'The first section records target\nidentity, current source revision and worktree state or `[UNVERIFIED]`, an\nevidence-as-of value, and what change invalidates the brief.',
2377
+ from: 'The first section records target identity, current source revision and worktree state or `[UNVERIFIED]`, an evidence-as-of value, and what change invalidates the brief.',
2470
2378
  to: 'The handoff has no revision or freshness binding.', expected: ['adaptive-decision-freshness']
2471
2379
  },
2472
2380
  {
2473
2381
  name: 'adaptive-overlay-authority-removed', source: 'skill',
2474
- from: 'Neither overlay\nwrites, approves, persists, dispatches, or completes work.',
2382
+ from: 'Neither overlay writes, approves, persists, dispatches, or completes work.',
2475
2383
  to: 'Overlays may persist, approve, dispatch, and complete work.', expected: ['adaptive-non-authority']
2476
2384
  },
2477
2385
  {
@@ -2491,7 +2399,7 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
2491
2399
  {
2492
2400
  name: 'exploration-stop-removed',
2493
2401
  source: 'skill',
2494
- from: 'Do not request design approval, persist a report, or\n invoke another workflow without a new explicit request.',
2402
+ from: 'Do not request design approval, persist a report, or invoke another workflow without a new explicit request.',
2495
2403
  to: 'Request approval, persist a report, and invoke another workflow.',
2496
2404
  expected: ['exploration-stop']
2497
2405
  },
@@ -2841,7 +2749,7 @@ function hotfixProjectionIssues(files) {
2841
2749
  }
2842
2750
  if (!parallel.includes('Diagnosis still starts only')
2843
2751
  || !parallel.includes('after the required scout outputs are synthesized')
2844
- || !parallel.includes('Research begins only after Step 2 diagnosis')
2752
+ || !parallel.includes('Research begins only after diagnosis')
2845
2753
  || parallel.includes('scout + diagnose + research together')
2846
2754
  || parallel.includes("You don't need to wait for scouting")) {
2847
2755
  issues.add('scout-before-diagnosis');
@@ -2858,9 +2766,9 @@ test('Codex installed Fix preserves the adaptive repair contract', () => {
2858
2766
  const result = install(root);
2859
2767
  assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
2860
2768
 
2861
- const installedRoot = path.join(root, '.agents/skills/hotfix');
2862
- assert.equal(fs.existsSync(path.join(root, '.agents/skills/fix')), false,
2863
- 'public Fix rename must keep the manifest-owned hotfix directory');
2769
+ const installedRoot = path.join(root, '.agents/skills/fix');
2770
+ assert.equal(fs.existsSync(path.join(root, '.agents/skills/hotfix')), false,
2771
+ 'Fix lives in the fix directory; the retired hotfix directory must not be installed');
2864
2772
  for (const relative of HOTFIX_BUNDLE) {
2865
2773
  const sourcePath = path.join(HOTFIX_SOURCE_ROOT, relative);
2866
2774
  assert.equal(
@@ -2952,7 +2860,7 @@ test('Codex installed Fix preserves the adaptive repair contract', () => {
2952
2860
  },
2953
2861
  {
2954
2862
  name: 'research-starts-before-diagnosis', file: 'references/parallel-patterns.md',
2955
- from: 'Research begins only after Step 2 diagnosis', to: 'Research may begin before Step 2 diagnosis',
2863
+ from: 'Research begins only after diagnosis', to: 'Research may begin before diagnosis',
2956
2864
  expected: ['scout-before-diagnosis']
2957
2865
  }
2958
2866
  ];
@@ -3139,8 +3047,6 @@ test('Codex install on top of existing Claude installation preserves content and
3139
3047
  assert.equal(fs.existsSync(path.join(root, '.codex', 'runtime.json')), true, '.codex/runtime.json should exist');
3140
3048
  assert.equal(fs.existsSync(path.join(root, '.codex', 'hooks', 'privacy-block.cjs')), true, '.codex/hooks/privacy-block.cjs should exist');
3141
3049
  assert.equal(fs.existsSync(path.join(root, '.codex', 'rules', 'workflow.md')), true, '.codex/rules/workflow.md should exist');
3142
- assert.equal(fs.existsSync(path.join(root, '.codex', 'scripts', 'spec-ground.cjs')), true, '.codex/scripts/spec-ground.cjs should exist');
3143
- assert.equal(fs.existsSync(path.join(root, '.codex', 'scripts', 'validate-spec-output.cjs')), true, '.codex/scripts/validate-spec-output.cjs should exist');
3144
3050
  assert.equal(fs.existsSync(path.join(root, '.agents', '.gitignore')), true, '.agents/.gitignore should exist');
3145
3051
  assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', 'specs', 'SKILL.md')), true, '.agents/skills/specs/SKILL.md should exist');
3146
3052
 
@@ -3162,59 +3068,76 @@ test('Codex install on top of existing Claude installation preserves content and
3162
3068
  });
3163
3069
  });
3164
3070
 
3165
- test('Codex installed code_auditor contains Strict conditional marker', () => {
3071
+ test('Codex installed code_auditor carries no Strict attestation marker', () => {
3166
3072
  inTempProject((root) => {
3167
3073
  const result = install(root);
3168
3074
  assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
3169
3075
  const toml = fs.readFileSync(path.join(root, '.codex', 'agents', 'code_auditor.toml'), 'utf8');
3170
- assert.match(toml, /Strict Semantic Review Attestation/);
3171
- assert.match(toml, /CAFEKIT_SEMANTIC_REVIEW_ATTESTATION/);
3172
- assert.match(toml, /MAC-protected host-hook observation/);
3173
- assert.doesNotMatch(toml, /host-signed/);
3174
- assert.match(toml, /specs\/<feature>\/spec\.json/);
3076
+ assert.doesNotMatch(toml, /CAFEKIT_SEMANTIC_REVIEW_ATTESTATION/);
3077
+ assert.doesNotMatch(toml, /Strict Semantic Review Attestation/);
3078
+ assert.doesNotMatch(toml, /MAC-protected host-hook observation/);
3175
3079
  });
3176
3080
  });
3177
3081
 
3178
- test('Codex scaffold resolver rejects symlink template', () => {
3082
+ test('reinstall removes obsolete scripts and skill files from Codex and omp installs', () => {
3179
3083
  inTempProject((root) => {
3180
- const result = install(root);
3181
- assert.equal(result.status, 0);
3182
- const template = path.join(root, '.agents', 'skills', 'specs', 'templates', 'task.md');
3183
- const target = path.join(root, 'outside.md');
3184
- fs.writeFileSync(target, 'evil');
3185
- const original = fs.readFileSync(template);
3186
- fs.unlinkSync(template);
3187
- fs.symlinkSync(target, template);
3188
- const scaffold = path.join(root, '.codex', 'scripts', 'spec-scaffold.cjs');
3189
- const out = spawnSync(process.execPath, [scaffold, 'symlink-test', '--tasks', 'R1-01-foo,R1-02-bar', '--boundaries', '[{"id":"B-OWN","type":"ownership","tasks":["R1-01","R1-02"],"write_sets":{"R1-01":["src/a.js"],"R1-02":["src/b.js"]}}]'], { cwd: root, encoding: 'utf8' });
3190
- // Should fail because template is symlink and resolver rejects it
3191
- assert.notEqual(out.status, 0, 'scaffold should reject symlink template');
3192
- assert.match(`${out.stdout}\n${out.stderr}`, /template not found|symlink/i);
3193
- fs.unlinkSync(template);
3194
- fs.writeFileSync(template, original);
3084
+ const first = installPlatforms(root, ['codex', 'omp']);
3085
+ assert.equal(first.status, 0, `${first.stdout}\n${first.stderr}`);
3086
+ const retired = ['change-firewall.cjs', 'spec-final-state.cjs'];
3087
+ for (const runtime of ['.codex', '.omp']) {
3088
+ for (const name of retired) fs.writeFileSync(path.join(root, runtime, 'scripts', name), 'legacy\n');
3089
+ }
3090
+ const retiredSkillFiles = ['code-review/references/verification-gate.md', 'specs/references/archive-workflow.md'];
3091
+ for (const rel of retiredSkillFiles) fs.writeFileSync(path.join(root, '.agents', 'skills', rel), 'legacy\n');
3092
+ const again = installPlatforms(root, ['codex', 'omp'], ['--force-overwrite']);
3093
+ assert.equal(again.status, 0, `${again.stdout}\n${again.stderr}`);
3094
+ for (const rel of retiredSkillFiles) {
3095
+ assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', rel)), false, `.agents/skills/${rel} must be removed`);
3096
+ }
3097
+ assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', 'code-review', 'SKILL.md')), true, 'the code-review skill stays');
3098
+ for (const runtime of ['.codex', '.omp']) {
3099
+ for (const name of retired) {
3100
+ assert.equal(fs.existsSync(path.join(root, runtime, 'scripts', name)), false, `${runtime}/scripts/${name} must be removed`);
3101
+ }
3102
+ assert.equal(fs.existsSync(path.join(root, runtime, 'scripts', 'spec-resolver.cjs')), true, `${runtime} keeps the resolver`);
3103
+ }
3195
3104
  });
3196
3105
  });
3197
3106
 
3198
- test('Claude and Codex installed Route preserve proportional live-catalog semantics', () => {
3107
+ test('reinstall removes the retired spec.json templates from Claude and Codex but a dry run keeps them', () => {
3108
+ inTempProject((root) => {
3109
+ const first = installPlatforms(root, ['claude', 'codex']);
3110
+ assert.equal(first.status, 0, `${first.stdout}\n${first.stderr}`);
3111
+ const templateDirs = ['.claude/skills/specs/templates', '.agents/skills/specs/templates'];
3112
+ const retired = ['design.md', 'task.md', 'requirements.md', 'requirements-init.md', 'spec-state.json'];
3113
+ for (const dir of templateDirs) {
3114
+ for (const name of retired) fs.writeFileSync(path.join(root, dir, name), 'legacy\n');
3115
+ }
3116
+
3117
+ const dry = installPlatforms(root, ['claude', 'codex'], ['--force-overwrite', '--dry-run']);
3118
+ assert.equal(dry.status, 0, `${dry.stdout}\n${dry.stderr}`);
3119
+ for (const dir of templateDirs) {
3120
+ for (const name of retired) {
3121
+ assert.equal(fs.existsSync(path.join(root, dir, name)), true, `dry run removed ${dir}/${name}`);
3122
+ }
3123
+ }
3124
+
3125
+ const again = installPlatforms(root, ['claude', 'codex'], ['--force-overwrite']);
3126
+ assert.equal(again.status, 0, `${again.stdout}\n${again.stderr}`);
3127
+ for (const dir of templateDirs) {
3128
+ assert.deepEqual(fs.readdirSync(path.join(root, dir)), ['research.md'], `${dir} keeps only research.md`);
3129
+ }
3130
+ });
3131
+ });
3132
+
3133
+ test('Claude and Codex installed routing rules preserve the live-catalog semantics and install no Route', () => {
3199
3134
  inTempProject((root) => {
3200
3135
  const result = installPlatforms(root, ['claude', 'codex']);
3201
3136
  assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
3202
- const sourceRoot = path.join(PACKAGE_ROOT, 'src/claude/skills/route');
3203
- const expectedFiles = [
3204
- 'SKILL.md', 'references/task-taxonomy.md',
3205
- 'references/chaining-patterns.md', 'references/agent-timing.md'
3206
- ];
3207
3137
  const expectedRules = ['skill-workflow-routing.md', 'skill-domain-routing.md'];
3208
3138
  for (const runtime of ['claude', 'codex']) {
3209
3139
  const installedRoot = path.join(root, runtime === 'codex' ? '.agents/skills/route' : '.claude/skills/route');
3210
- for (const relative of expectedFiles) {
3211
- const source = fs.readFileSync(path.join(sourceRoot, relative), 'utf8');
3212
- const installed = fs.readFileSync(path.join(installedRoot, relative), 'utf8');
3213
- const expected = runtime === 'codex'
3214
- ? normalizeCodexBody(source, path.join(sourceRoot, relative))
3215
- : source;
3216
- assert.equal(installed, expected, `${runtime}:${relative}`);
3217
- }
3140
+ assert.equal(fs.existsSync(installedRoot), false, `${runtime} still installs Route`);
3218
3141
  for (const relative of expectedRules) {
3219
3142
  const sourcePath = path.join(PACKAGE_ROOT, 'src/claude/rules', relative);
3220
3143
  const source = fs.readFileSync(sourcePath, 'utf8');
@@ -3224,12 +3147,8 @@ test('Claude and Codex installed Route preserve proportional live-catalog semant
3224
3147
  const expected = runtime === 'codex' ? normalizeCodexBody(source, sourcePath) : source;
3225
3148
  assert.equal(installed, expected, `${runtime}:rules/${relative}`);
3226
3149
  }
3227
- const route = fs.readFileSync(path.join(installedRoot, 'SKILL.md'), 'utf8');
3228
- assert.match(route, /names a valid installed skill[\s\S]*one installed skill clearly covers[\s\S]*Direct factual conversation/);
3229
- assert.match(route, /highest-link[\s\S]*risk[\s\S]*number of material domains/);
3230
- assert.match(route, /never expand it/);
3231
3150
  const catalog = installedCatalog(root, runtime);
3232
- assert.ok(catalog.skills.some((skill) => skill.public_id === 'cf:route'));
3151
+ assert.equal(catalog.skills.some((skill) => skill.public_id === 'cf:route'), false);
3233
3152
  assert.equal(catalog.skills.some((skill) => skill.public_id === 'cf:docs'), false);
3234
3153
  }
3235
3154
  });
@@ -3304,24 +3223,3 @@ test('Claude and Codex installed rules preserve the ported review and process gu
3304
3223
  });
3305
3224
  });
3306
3225
 
3307
- test('installed Route degrades safely when an agent is absent', () => {
3308
- inTempProject((root) => {
3309
- const result = installPlatforms(root, ['claude', 'codex']);
3310
- assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
3311
- const cases = [
3312
- ['claude', '.claude/agents/researcher.md', '.claude/skills/route'],
3313
- ['codex', '.codex/agents/researcher.toml', '.agents/skills/route'],
3314
- ];
3315
- for (const [runtime, agentRelative, routeRelative] of cases) {
3316
- fs.rmSync(path.join(root, agentRelative), { force: true });
3317
- assert.equal(fs.existsSync(path.join(root, agentRelative)), false);
3318
- const timing = fs.readFileSync(path.join(root, routeRelative, 'references/agent-timing.md'), 'utf8');
3319
- const route = fs.readFileSync(path.join(root, routeRelative, 'SKILL.md'), 'utf8');
3320
- const normalizedRoute = route.replace(/\s+/g, ' ');
3321
- assert.match(timing, /If the preferred agent is absent[\s\S]*never synthesize a role/);
3322
- assert.match(normalizedRoute, /continue inline when safe or return the named gap/);
3323
- assert.match(normalizedRoute, /Never synthesize an unavailable agent/);
3324
- assert.doesNotMatch(`${timing}\n${route}`, /researcher(?:\.md|\.toml)/i, runtime);
3325
- }
3326
- });
3327
- });