@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
@@ -10,17 +10,19 @@
10
10
  - For skill selection, read `.codex/rules/skill-workflow-routing.md` and
11
11
  `.codex/rules/skill-domain-routing.md`. When capability presence is uncertain,
12
12
  run `node .codex/scripts/generate-skill-catalog.cjs --skills`; its Codex-bound
13
- root is `.agents/skills`. Use `$cf-route` only for ambiguous, multi-step,
14
- multi-domain, or risk-elevated work; explicit, obvious, and factual intents
15
- stay direct.
13
+ root is `.agents/skills`. Explicit, obvious, and factual intents stay
14
+ direct; compose a short chain only for ambiguous, multi-step, multi-domain, or
15
+ risk-elevated work.
16
16
  - Consult `.codex/rules/review-audit-self-decision.md` before applying audit
17
17
  feedback, reversing a verified or user decision, or cutting scope, and
18
18
  `.codex/rules/process-management.md` whenever a task starts, reuses, or ends
19
19
  long-running processes.
20
+ - Read `.codex/rules/state-sync.md` before changing a task `Status:` or Receipt,
21
+ and `.codex/rules/hook-protocols.md` when a hook blocks or asks.
20
22
  - Project hooks live in `.codex/hooks.json`; review trusted hooks with `/hooks`.
21
- - New Specs work uses the process-first flow. `$cf-specs` opens C1, writes
23
+ - New Specs work uses the process-first flow. `$cf-specs` opens GATE-SCOPE, writes
22
24
  `specs/<feature>/plan.md` with flat `task-NN-*.md` files beside it, then opens
23
- C2 after adversarial review. It never starts implementation.
25
+ GATE-REVIEW after adversarial review. It never starts implementation.
24
26
  - Start implementation only through a new explicit `$cf-develop` invocation.
25
27
  Execute one unblocked task at a time; each task has exactly one `Status:`
26
28
  field and the controller is its sole state-and-proof writer.
@@ -28,16 +30,9 @@
28
30
  requires a canonical final inline `## Receipt` with the exact command,
29
31
  `Exit: 0`, `Verification: PASS`, runtime-derived Base and Head values, and
30
32
  non-empty fenced current output.
31
- - At C3, show current receipts and unresolved limitations. The user decides
33
+ - At GATE-DONE, show current receipts and unresolved limitations. The user decides
32
34
  completion; no command, review, or host state may invent approval or proof.
33
35
 
34
- ### Legacy Specs compatibility
35
-
36
- Existing packets containing `spec.json`, nested tasks, or legacy kernel
37
- artifacts keep their installed adapter, `task_registry`, `semantic_model`,
38
- `planning_depth`, lane, `execution_tier`, machine authority, separate receipts,
39
- and closeout contract. Do not migrate them during unrelated process-first work.
40
-
41
36
  ## Codex caveats
42
37
 
43
38
  - Custom agents use snake_case names and `fork_turns: "none"` for explicit delegation.
@@ -26,6 +26,7 @@ try {
26
26
  const thinkLang = runtime.locale?.thinkingLanguage || (respondLang ? 'en' : '');
27
27
  const plansPath = resolveProjectPath(projectRoot, runtime.paths?.plans, 'plans');
28
28
  const docsPath = resolveProjectPath(projectRoot, runtime.paths?.docs, 'docs');
29
+ const specsPath = resolveProjectPath(projectRoot, runtime.paths?.specs, 'specs');
29
30
  const venv = resolveVenv(projectRoot);
30
31
  const lines = [
31
32
  `## Subagent: ${payload.agent_type || 'unknown'}`,
@@ -44,7 +45,7 @@ try {
44
45
 
45
46
  lines.push(
46
47
  '## Rules',
47
- `- Plans → ${plansPath}/ | Docs → ${docsPath}/`,
48
+ `- Specs → ${specsPath}/ | Plans → ${plansPath}/ | Docs → ${docsPath}/`,
48
49
  '- YAGNI · KISS · DRY',
49
50
  '- Be concise. List unresolved questions at end.'
50
51
  );
@@ -37,8 +37,8 @@ function loadSharedReceipt() {
37
37
  'spec-receipt.cjs',
38
38
  'spec-receipt.cjs',
39
39
  (receipt) => {
40
- if (typeof receipt?.checkTaskReceipt !== 'function') {
41
- throw new Error('shared spec receipt helper has no checkTaskReceipt function');
40
+ if (typeof receipt?.checkWorkflowTaskReceipt !== 'function') {
41
+ throw new Error('shared spec receipt helper has no checkWorkflowTaskReceipt function');
42
42
  }
43
43
  },
44
44
  'shared spec receipt helper is missing'
@@ -55,7 +55,6 @@ function receiptHelper() {
55
55
  return loaded.receipt;
56
56
  }
57
57
 
58
- function evidenceBody(text) { return receiptHelper().evidenceBody(text, getSharedPolicy() || {}); }
59
58
  function safeTaskFile(featureDir, taskPath) {
60
59
  const result = receiptHelper().safeRead(featureDir, taskPath);
61
60
  return result.status === 'ok' ? result.path : null;
@@ -64,11 +63,6 @@ function validateCanonicalReceipt(body, options = {}) {
64
63
  const validate = getSharedValidate();
65
64
  return validate ? validate(body, options) : ['shared_validator'];
66
65
  }
67
- function checkReceiptDetails(featureDir, taskPath, task, runtimeContext) {
68
- const policy = getSharedPolicy();
69
- if (!policy) return { failures: ['shared_validator'], status: 'missing' };
70
- return receiptHelper().checkTaskReceipt(featureDir, taskPath, task, runtimeContext, policy);
71
- }
72
66
  function checkWorkflowReceiptDetails(featureDir, taskPath, runtimeContext) {
73
67
  const policy = getSharedPolicy();
74
68
  const receipt = receiptHelper();
@@ -85,40 +79,18 @@ function checkWorkflowReceiptSet(candidates, projectRoot, runtimeSession) {
85
79
  }
86
80
  return receipt.checkWorkflowReceiptSet(candidates, projectRoot, runtimeSession, policy);
87
81
  }
88
- function checkReceipt(featureDir, taskPath, task, runtimeContext) {
89
- const map = {
90
- unsafe_path: 'a', missing_receipt: 'b', task_status: 'a', completed_at: 'd',
91
- verification_state: 'c', placeholder: 'c', validator_unavailable: 'c',
92
- command: 'e', command_identity: 'e', exit_result: 'f', provenance: 'g',
93
- artifact_hash: 'h', artifact_declaration: 'h',
94
- };
95
- return [...new Set(checkReceiptDetails(featureDir, taskPath, task, runtimeContext).failures.map((failure) => map[failure] || failure))];
96
- }
97
- function checkFeatureReceipt(featureDir, runtimeContext) {
98
- const policy = getSharedPolicy();
99
- if (!policy) return { failures: ['shared_validator'], status: 'missing' };
100
- return receiptHelper().checkFeatureReceipt(featureDir, runtimeContext, policy);
101
- }
102
- function receiptFixHint(failures) {
82
+ function receiptFixHint(failures, body) {
103
83
  const helper = receiptHelper();
104
- return typeof helper.receiptFixHint === 'function' ? helper.receiptFixHint(failures) : null;
105
- }
106
- function readTaskProof(featureDir, taskPath) {
107
- return receiptHelper().readTaskProof(featureDir, taskPath, getSharedPolicy() || {});
84
+ return typeof helper.receiptFixHint === 'function' ? helper.receiptFixHint(failures, body) : null;
108
85
  }
109
86
 
110
87
  module.exports = {
111
- checkFeatureReceipt,
112
- checkReceipt,
113
- checkReceiptDetails,
114
88
  checkWorkflowReceiptDetails,
115
89
  checkWorkflowReceiptSet,
116
- evidenceBody,
117
90
  getSharedPolicy,
118
91
  getSharedValidate,
119
92
  loadSharedPolicy,
120
93
  loadSharedReceipt,
121
- readTaskProof,
122
94
  receiptFixHint,
123
95
  safeTaskFile,
124
96
  validateCanonicalReceipt,
@@ -66,8 +66,8 @@ function sharedResolver() {
66
66
  // Use canonical realpath for require to avoid symlink hijack
67
67
  const realCandidate = canonicalRealpath(candidate);
68
68
  const resolver = require(realCandidate);
69
- if (typeof resolver?.resolveActiveSpec !== 'function') {
70
- throw new Error('shared spec resolver has no resolveActiveSpec function');
69
+ if (typeof resolver?.resolveWorkflowCandidate !== 'function') {
70
+ throw new Error('shared spec resolver has no resolveWorkflowCandidate function');
71
71
  }
72
72
  return resolver;
73
73
  } catch (error) {
@@ -80,31 +80,13 @@ function specsDirectory(projectRoot, runtime) {
80
80
  return sharedResolver().specsDirectory(projectRoot, runtime);
81
81
  }
82
82
 
83
- function findAllActiveSpecs(projectRoot, runtime) {
84
- return sharedResolver().findAllActiveSpecs(projectRoot, runtime);
85
- }
86
-
87
- function findAllSpecCandidates(projectRoot, runtime) {
88
- return sharedResolver().findAllSpecCandidates(projectRoot, runtime);
89
- }
90
-
91
- function resolveActiveSpec(projectRoot, runtime, explicitFeature, explicitPath) {
92
- if (projectRoot && typeof projectRoot === 'object') {
93
- return sharedResolver().resolveActiveSpec(projectRoot);
94
- }
95
- return sharedResolver().resolveActiveSpec({
96
- projectRoot,
97
- runtime,
98
- explicitFeature,
99
- explicitPath,
100
- });
83
+ function findLegacyPackets(projectRoot, runtime) {
84
+ const resolver = sharedResolver();
85
+ return typeof resolver.findLegacyPackets === 'function' ? resolver.findLegacyPackets(projectRoot, runtime) : [];
101
86
  }
102
87
 
103
88
  function resolveWorkflowCandidate(projectRoot, runtime, explicitFeature, explicitPath) {
104
89
  const resolver = sharedResolver();
105
- if (typeof resolver.resolveWorkflowCandidate !== 'function') {
106
- return resolveActiveSpec(projectRoot, runtime, explicitFeature, explicitPath);
107
- }
108
90
  if (projectRoot && typeof projectRoot === 'object') {
109
91
  return resolver.resolveWorkflowCandidate(projectRoot);
110
92
  }
@@ -123,23 +105,6 @@ function refineWorkflowGateResolution(resolved) {
123
105
  : resolved;
124
106
  }
125
107
 
126
- function findActiveSpec(projectRoot, runtime) {
127
- const resolved = resolveActiveSpec(projectRoot, runtime);
128
- if (!resolved) return null;
129
- if (resolved.error === 'multiple_active' || resolved.error === 'invalid_specs') return resolved;
130
- if (resolved.error) return null;
131
- return resolved;
132
- }
133
-
134
- function taskStatusMap(spec) {
135
- return Object.fromEntries(
136
- Object.entries(spec.task_registry || {}).map(([taskPath, task]) => [
137
- taskPath,
138
- task?.status || 'pending',
139
- ]),
140
- );
141
- }
142
-
143
108
  function extractExplicitTarget(...sources) {
144
109
  const resolver = sharedResolver();
145
110
  if (typeof resolver.extractExplicitTarget !== 'function') return null;
@@ -152,22 +117,11 @@ function readActiveFeatureTarget(options) {
152
117
  return resolver.readActiveFeatureTarget(options);
153
118
  }
154
119
 
155
- function resolvePersistedSpec(options) {
156
- const resolver = sharedResolver();
157
- if (typeof resolver.resolvePersistedSpec !== 'function') return null;
158
- return resolver.resolvePersistedSpec(options);
159
- }
160
-
161
120
  module.exports = {
162
- findActiveSpec,
163
121
  extractExplicitTarget,
122
+ findLegacyPackets,
164
123
  readActiveFeatureTarget,
165
- resolvePersistedSpec,
166
- findAllActiveSpecs,
167
- findAllSpecCandidates,
168
- resolveActiveSpec,
169
124
  resolveWorkflowCandidate,
170
125
  refineWorkflowGateResolution,
171
126
  specsDirectory,
172
- taskStatusMap,
173
127
  };
@@ -79,6 +79,7 @@ try {
79
79
  const thinkLang = runtime.locale?.thinkingLanguage || (respondLang ? 'en' : '');
80
80
  const plansPath = resolveProjectPath(projectRoot, runtime.paths?.plans, 'plans');
81
81
  const docsPath = resolveProjectPath(projectRoot, runtime.paths?.docs, 'docs');
82
+ const specsPath = resolveProjectPath(projectRoot, runtime.paths?.specs, 'specs');
82
83
  const lines = [];
83
84
 
84
85
  if ((thinkLang && thinkLang !== respondLang) || respondLang) {
@@ -92,7 +93,7 @@ try {
92
93
 
93
94
  lines.push(
94
95
  '## Rules',
95
- `- Markdown: Plans → "${plansPath}/" | Docs → "${docsPath}/"`,
96
+ `- Markdown: Specs → "${specsPath}/" | Plans → "${plansPath}/" | Docs → "${docsPath}/"`,
96
97
  '- Do not create markdown outside those directories unless explicitly asked.',
97
98
  `- docs.maxLoc: ${runtime.docs?.maxLoc || 800} lines per doc file`
98
99
  );
@@ -10,7 +10,6 @@ const {
10
10
  readPayload
11
11
  } = require('./lib/hook-context.cjs');
12
12
  const { clearState } = require('./lib/privacy-state.cjs');
13
- const { clearState: clearCompletionState } = require('./completion-authority-state.cjs');
14
13
 
15
14
  function readPackage(projectRoot) {
16
15
  try {
@@ -89,7 +88,6 @@ try {
89
88
 
90
89
  // Approval tokens never survive a session boundary or compaction.
91
90
  clearState(projectRoot);
92
- clearCompletionState(projectRoot, payload.session_id);
93
91
 
94
92
  // Orca (onorca.dev) sets ORCA_PANE_KEY in every pane; it is a presence marker, not a
95
93
  // secret. ORCA_AGENT_HOOK_TOKEN and ORCA_AGENT_LAUNCH_TOKEN live in the same
@@ -11,15 +11,11 @@ const {
11
11
  readPayload
12
12
  } = require('./lib/hook-context.cjs');
13
13
  const {
14
- checkFeatureReceipt,
15
- checkReceiptDetails,
16
14
  checkWorkflowReceiptDetails,
17
15
  checkWorkflowReceiptSet,
18
16
  loadSharedPolicy,
19
17
  receiptFixHint,
20
18
  } = require('./lib/spec-receipt.cjs');
21
- const { taskStatusMap } = require('./lib/spec-utils.cjs');
22
- const FINAL_STATE = require('./completion-authority-check.cjs');
23
19
 
24
20
  function emitBlock(reason) {
25
21
  process.stdout.write(`${JSON.stringify({ decision: 'block', reason })}\n`);
@@ -46,7 +42,7 @@ try {
46
42
  }
47
43
  const POLICY = loaded.policy;
48
44
  const { projectRoot, runtime } = getHookContext(payload);
49
- if (typeof POLICY.completionDecisionForSpec !== 'function') {
45
+ if (typeof POLICY.deriveRuntimeContext !== 'function') {
50
46
  throw new Error('shared workflow policy lacks completion authority functions');
51
47
  }
52
48
  const resolver = require('./lib/spec-utils.cjs');
@@ -54,9 +50,7 @@ try {
54
50
  // the payload leaves, which is what made the block unescapable on this runtime too.
55
51
  const target = resolver.extractExplicitTarget(payload)
56
52
  || resolver.readActiveFeatureTarget({ projectRoot, runtime });
57
- let resolved = typeof resolver.resolveWorkflowCandidate === 'function'
58
- ? resolver.resolveWorkflowCandidate({ projectRoot, runtime, target, includeCompleted: true })
59
- : FINAL_STATE.resolveCandidate({ resolver, projectRoot, runtime, payload });
53
+ let resolved = resolver.resolveWorkflowCandidate({ projectRoot, runtime, target, includeCompleted: true });
60
54
  if (typeof resolver.refineWorkflowGateResolution === 'function') {
61
55
  resolved = resolver.refineWorkflowGateResolution(resolved);
62
56
  }
@@ -76,7 +70,7 @@ try {
76
70
  const lines = [`Completion gate: ${checked.failures.length} done task(s) lack a verification receipt.`];
77
71
  for (const failure of checked.failures) {
78
72
  lines.push(`- \`${failure.featureName}/${failure.taskPath}\`: failed check(s) ${failure.failures.join(', ')}`);
79
- lines.push(` In \`specs/${failure.featureName}/${failure.taskPath}\`: ${receiptFixHint(failure.failures) || 'write a runtime-bound `## Receipt` with the planned command'}.`);
73
+ lines.push(` In \`specs/${failure.featureName}/${failure.taskPath}\`: ${receiptFixHint(failure.failures, failure.body) || 'write a runtime-bound `## Receipt` with the planned command'}.`);
80
74
  }
81
75
  emitBlock(lines.slice(0, 8).join('\n'));
82
76
  process.exit(0);
@@ -91,7 +85,7 @@ try {
91
85
  if (resolved.error === 'invalid_specs') {
92
86
  process.stdout.write(`${JSON.stringify({
93
87
  decision: 'block',
94
- reason: `Completion gate: invalid spec JSON detected (${resolved.candidates.join(', ')}): ${resolved.reason}. Fix or remove malformed spec.json before completing tasks.`
88
+ reason: `Completion gate: invalid workflow packet detected (${resolved.candidates.join(', ')}): ${resolved.reason}. Fix the packet's plan.md or task files before completing tasks.`
95
89
  })}\n`);
96
90
  process.exit(0);
97
91
  }
@@ -104,28 +98,10 @@ try {
104
98
  }
105
99
  if (resolved.error) process.exit(0);
106
100
  const active = resolved;
107
- const activeSpec = active.spec || {};
108
- const processWorkflow = active.layoutKind === 'process-v3';
109
- const lifecyclePhase = activeSpec.current_phase || activeSpec.phase;
110
- const explicitCloseout = ['done', 'completed', 'complete'].includes(activeSpec.status)
111
- || ['closeout', 'completion', 'completed', 'complete'].includes(lifecyclePhase);
112
- if (!processWorkflow && activeSpec.schema_version === '2.1') {
113
- const finalState = FINAL_STATE.evaluateCloseout({
114
- policy: POLICY,
115
- projectRoot,
116
- runtime,
117
- payload: { ...payload, session_id: sessionIdentity(payload) },
118
- });
119
- if (!finalState.ok) {
120
- emitBlock(`Completion gate: ${finalState.reason}`);
121
- process.exit(0);
122
- }
123
- if (finalState.active) process.exit(0);
124
- }
125
101
  const runtimeContext = POLICY.deriveRuntimeContext({
126
102
  projectRoot,
127
103
  specsRoot: active.specsDir,
128
- specFile: active.stateFile || active.specFile || path.join(active.specsDir, active.featureName, 'spec.json'),
104
+ specFile: active.stateFile,
129
105
  featureName: active.featureName,
130
106
  runtimeSession: sessionIdentity(payload),
131
107
  });
@@ -134,10 +110,10 @@ try {
134
110
  emitBlock('Completion gate: runtime.spec.completion_gate is a worker-writable flag, not an authorization; no completion-gate bypass is supported. Remove the flag and satisfy the gate.');
135
111
  process.exit(0);
136
112
  }
137
- const registry = active.taskRegistry || activeSpec.task_registry || {};
138
- const currentStatuses = processWorkflow
139
- ? Object.fromEntries(Object.entries(registry).map(([taskPath, task]) => [taskPath, task?.status || 'pending']))
140
- : taskStatusMap(activeSpec);
113
+ const registry = active.taskRegistry || {};
114
+ const currentStatuses = Object.fromEntries(
115
+ Object.entries(registry).map(([taskPath, task]) => [taskPath, task?.status || 'pending']),
116
+ );
141
117
  const cacheFile = path.join(hookStateDir(projectRoot), 'spec-gate-last.json');
142
118
  const cacheExists = fs.existsSync(cacheFile);
143
119
  let cache = {};
@@ -163,16 +139,6 @@ try {
163
139
  const previous = cacheExists && cacheEntries[runtimeContext.context_id]
164
140
  ? cacheEntries[runtimeContext.context_id].tasks || {}
165
141
  : {};
166
- const staleFlashTasks = processWorkflow ? [] : Object.entries(registry)
167
- .filter(([, task]) => POLICY.isStaleFlashDone(task))
168
- .map(([taskPath]) => taskPath);
169
- if (staleFlashTasks.length > 0) {
170
- process.stdout.write(`${JSON.stringify({
171
- decision: 'block',
172
- reason: `Completion gate: ${staleFlashTasks.length} task(s) marked done with FLASH_UNVERIFIED (${staleFlashTasks.join(', ')}). Run /cf:test, then use explicit sync-finalize.`
173
- })}\n`);
174
- process.exit(0);
175
- }
176
142
  const allDoneTasks = Object.keys(registry).filter((taskPath) => (
177
143
  currentStatuses[taskPath] === 'done'
178
144
  ));
@@ -180,9 +146,7 @@ try {
180
146
  const receiptBodies = new Map();
181
147
  const failures = allDoneTasks
182
148
  .map((taskPath) => {
183
- const proof = processWorkflow
184
- ? checkWorkflowReceiptDetails(featureDir, taskPath, runtimeContext)
185
- : checkReceiptDetails(featureDir, taskPath, registry[taskPath], runtimeContext);
149
+ const proof = checkWorkflowReceiptDetails(featureDir, taskPath, runtimeContext);
186
150
  if (proof.body) receiptBodies.set(taskPath, proof.body);
187
151
  return {
188
152
  taskPath,
@@ -191,52 +155,20 @@ try {
191
155
  })
192
156
  .filter((result) => result.failures.length);
193
157
 
194
- const featureCloseoutRequired = !processWorkflow && explicitCloseout && allDoneTasks.length > 0;
195
- const featureReceipt = featureCloseoutRequired
196
- ? checkFeatureReceipt(featureDir, runtimeContext)
197
- : null;
198
- if (featureReceipt && featureReceipt.failures.length) {
199
- failures.push({ taskPath: 'feature-receipt.md', failures: featureReceipt.failures });
200
- }
201
- const completion = featureCloseoutRequired && featureReceipt?.failures.length === 0
202
- && Object.prototype.hasOwnProperty.call(active.spec, 'workflow_policy')
203
- ? POLICY.completionDecisionForSpec(active.spec, {
204
- runtimeContext,
205
- executionReceipt: featureReceipt.body,
206
- taskContext: {},
207
- })
208
- : null;
209
-
210
158
  const next = { ...previous, ...currentStatuses };
211
159
  for (const result of failures) {
212
160
  if (previous[result.taskPath] === undefined) delete next[result.taskPath];
213
161
  else next[result.taskPath] = previous[result.taskPath];
214
162
  }
215
163
  atomicWrite(cacheFile, `${JSON.stringify({
216
- schema_version: '2',
217
164
  entries: { ...cacheEntries, [runtimeContext.context_id]: { identity: cacheIdentity, tasks: next } },
218
165
  })}\n`);
219
166
 
220
- const completionBlocked = completion && completion.completion !== 'complete' && completion.completion !== 'not_applicable';
221
- if (!failures.length && !completionBlocked) process.exit(0);
222
- const lines = [
223
- failures.length > 0
224
- ? `Completion gate: ${failures.length} done task(s) lack a verification receipt.`
225
- : 'Completion gate: workflow completion proof is incomplete.'
226
- ];
167
+ if (!failures.length) process.exit(0);
168
+ const lines = [`Completion gate: ${failures.length} done task(s) lack a verification receipt.`];
227
169
  for (const result of failures) {
228
170
  lines.push(`- \`${result.taskPath}\`: failed check(s) ${result.failures.join(', ')}`);
229
- lines.push(result.taskPath === 'feature-receipt.md'
230
- ? ` Run final integration proof, then write \`specs/${active.featureName}/feature-receipt.md\`.`
231
- : processWorkflow
232
- ? ` In \`specs/${active.featureName}/${path.posix.basename(result.taskPath)}\`: ${receiptFixHint(result.failures) || 'write a runtime-bound `## Receipt` with command output'}.`
233
- : ` Write canonical proof to \`specs/${active.featureName}/receipts/${path.posix.basename(result.taskPath)}\`; legacy \`## Evidence\` remains read-compatible.`);
234
- }
235
- if (completionBlocked) {
236
- lines.push(`- Completion decision unfinished: ${completion.blocker || 'required workflow proof is missing.'}`);
237
- if (Array.isArray(completion.missingProof) && completion.missingProof.length > 0) {
238
- lines.push(` Missing proof: ${completion.missingProof.join(', ')}`);
239
- }
171
+ lines.push(` In \`specs/${active.featureName}/${path.posix.basename(result.taskPath)}\`: ${receiptFixHint(result.failures, result.body) || 'write a runtime-bound `## Receipt` with command output'}.`);
240
172
  }
241
173
  process.stdout.write(`${JSON.stringify({
242
174
  decision: 'block',
@@ -40,7 +40,28 @@ try {
40
40
  const RECEIPT = receiptLoaded.receipt;
41
41
  const { projectRoot, runtime } = getHookContext(payload);
42
42
  if (runtime.spec?.tollgate === false) process.exit(0);
43
- const { resolveWorkflowCandidate } = require('./lib/spec-utils.cjs');
43
+ const { findLegacyPackets, resolveWorkflowCandidate } = require('./lib/spec-utils.cjs');
44
+ const sessionId = payload.session_id || payload.sessionId || payload.sessionID || payload.session?.id;
45
+ // A legacy packet (a specs/<x>/ directory without plan.md that the old flow left
46
+ // behind) is no longer read. Say so once per session instead of on every prompt.
47
+ const legacyPackets = findLegacyPackets(projectRoot, runtime);
48
+ if (legacyPackets.length > 0) {
49
+ const noticeFile = sessionId
50
+ ? path.join(hookStateDir(projectRoot), `legacy-notice-${crypto.createHash('sha256').update(String(sessionId)).digest('hex').slice(0, 16)}.json`)
51
+ : null;
52
+ let noticed = [];
53
+ if (noticeFile) {
54
+ try { noticed = JSON.parse(fs.readFileSync(noticeFile, 'utf8')); } catch { noticed = []; }
55
+ if (!Array.isArray(noticed)) noticed = [];
56
+ }
57
+ const fresh = legacyPackets.filter((name) => !noticed.includes(name));
58
+ for (const name of fresh) {
59
+ process.stdout.write(`> ⚠️ \`specs/${name}\` is a legacy Specs packet without plan.md; CafeKit no longer reads it. Move ongoing work to a process-first plan.md packet.\n`);
60
+ }
61
+ if (noticeFile && fresh.length > 0) {
62
+ try { atomicWrite(noticeFile, `${JSON.stringify([...noticed, ...fresh].sort())}\n`); } catch { /* repeats the notice */ }
63
+ }
64
+ }
44
65
  const explicitFeature = payload.featureName || payload.feature || payload.explicitFeature || null;
45
66
  const explicitPath = payload.specPath || payload.spec_path || payload.featurePath || null;
46
67
  const resolved = resolveWorkflowCandidate(projectRoot, runtime, explicitFeature, explicitPath);
@@ -50,7 +71,7 @@ try {
50
71
  process.exit(0);
51
72
  }
52
73
  if (resolved.error === 'invalid_specs') {
53
- process.stdout.write(`> ⚠️ Invalid spec JSON detected: ${resolved.candidates.join(', ')}. ${resolved.reason}. Fix or remove malformed spec.json. Tollgate paused.\n`);
74
+ process.stdout.write(`> ⚠️ Invalid workflow packet detected: ${resolved.candidates.join(', ')}. ${resolved.reason}. Fix the packet's plan.md or task files. Tollgate paused.\n`);
54
75
  process.exit(0);
55
76
  }
56
77
  if (resolved.error === 'explicit_not_found' || resolved.error === 'explicit_malformed') {
@@ -60,18 +81,16 @@ try {
60
81
  }
61
82
  if (resolved.error) process.exit(0);
62
83
  const active = resolved;
63
- const processWorkflow = active.layoutKind === 'process-v3';
64
84
  const runtimeContext = POLICY.deriveRuntimeContext({
65
85
  projectRoot,
66
86
  specsRoot: active.specsDir,
67
- specFile: active.stateFile || active.specFile || path.join(active.specsDir, active.featureName, 'spec.json'),
87
+ specFile: active.stateFile,
68
88
  featureName: active.featureName,
69
- runtimeSession: payload.session_id || payload.sessionId || payload.sessionID || payload.session?.id,
89
+ runtimeSession: sessionId,
70
90
  });
71
91
 
72
- const phase = active.phase || active.spec?.current_phase || active.spec?.phase || 'unknown';
73
- const taskRegistry = active.taskRegistry || active.spec?.task_registry || {};
74
- const flashTasks = POLICY.flashState(taskRegistry);
92
+ const phase = active.phase || 'unknown';
93
+ const taskRegistry = active.taskRegistry || {};
75
94
  const tasks = Object.entries(taskRegistry);
76
95
  const counts = tasks.reduce((result, [, task]) => {
77
96
  const status = task?.status || 'pending';
@@ -79,13 +98,7 @@ try {
79
98
  return result;
80
99
  }, {});
81
100
  const featureDir = path.join(active.specsDir, active.featureName);
82
- const statuses = new Map(tasks.map(([taskPath, task]) => [
83
- taskPath,
84
- task?.status || 'pending'
85
- ]));
86
- const dependencyProof = processWorkflow
87
- ? RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY)
88
- : {};
101
+ const dependencyProof = RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY);
89
102
  const taskState = tasks.map(([taskPath, task]) => [
90
103
  taskPath,
91
104
  task?.status || 'pending',
@@ -101,12 +114,8 @@ try {
101
114
  const next = tasks.find(([, task]) => (
102
115
  active.queueReady !== false
103
116
  && (task?.status || 'pending') === 'pending'
104
- && (task?.dependencies || []).every((dependency) => (
105
- processWorkflow ? dependencyProof[dependency]?.eligible === true : statuses.get(dependency) === 'done'
106
- ))
117
+ && (task?.dependencies || []).every((dependency) => dependencyProof[dependency]?.eligible === true)
107
118
  ));
108
- const featureReceiptPresent = !processWorkflow
109
- && RECEIPT.safeRead(featureDir, 'feature-receipt.md').status === 'ok';
110
119
  const stateKey = JSON.stringify({
111
120
  project_root: runtimeContext.project_root,
112
121
  specs_root: runtimeContext.specs_root,
@@ -124,14 +133,13 @@ try {
124
133
  proof_state: proofState,
125
134
  done: counts.done || 0,
126
135
  total: tasks.length,
127
- feature_receipt_present: featureReceiptPresent,
128
136
  });
129
137
  const cache = cacheFile(projectRoot, runtimeContext.runtime_session);
130
138
  let previous = '';
131
139
  try { previous = fs.readFileSync(cache, 'utf8').trim(); } catch { /* first run */ }
132
140
 
133
141
  if (previous === stateKey) {
134
- const migration = processWorkflow && active.queueReady === false
142
+ const migration = active.queueReady === false
135
143
  ? ' Add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.'
136
144
  : '';
137
145
  process.stdout.write(
@@ -147,26 +155,14 @@ try {
147
155
  `- Phase: \`${phase}\` | Tasks: ${counts.done || 0} done / ${tasks.length} total`
148
156
  ];
149
157
  if (next) lines.push(`- Next unblocked: \`${next[0]}\``);
150
- if (flashTasks.length > 0) {
151
- lines.push(`- Flash verification pending: ${flashTasks.map((taskPath) => `\`${taskPath}\``).join(', ')}. A PASS proof keeps the persisted task in_progress until explicit sync-finalize.`);
152
- }
153
- if (processWorkflow) {
154
- if (active.queueReady === false) {
155
- lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
156
- }
157
- lines.push(
158
- '- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.',
159
- `- Workflow source: \`specs/${active.featureName}/plan.md\`; Stop re-checks every done receipt, binding Base/Head to the runtime only while a committed task file no longer matches its committed bytes.`,
160
- '- Hooks revalidate receipt bytes but never grant approval.'
161
- );
162
- } else {
163
- lines.push(
164
- '- Sync `spec.json` and task Markdown status only after verified work; task proof belongs in `receipts/<task-basename>.md`.',
165
- `- Create \`feature-receipt.md\` once after final integration proof${featureReceiptPresent ? ' (present)' : ' (not required before closeout)'}.`,
166
- `- Validate with \`node .codex/scripts/validate-spec-output.cjs specs/${active.featureName}\`.`,
167
- '- Hooks revalidate receipt bytes but never grant approval.'
168
- );
158
+ if (active.queueReady === false) {
159
+ lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
169
160
  }
161
+ lines.push(
162
+ '- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.',
163
+ `- Workflow source: \`specs/${active.featureName}/plan.md\`; Stop re-checks every done receipt, binding Base/Head to the runtime only while a committed task file no longer matches its committed bytes.`,
164
+ '- Hooks revalidate receipt bytes but never grant approval.'
165
+ );
170
166
  process.stdout.write(`${lines.join('\n')}\n`);
171
167
  } catch (error) {
172
168
  logCrash('spec-state', error);
@@ -48,11 +48,6 @@
48
48
  "command": "node \".codex/hooks/privacy-approval.cjs\"",
49
49
  "commandWindows": "node \".codex/hooks/privacy-approval.cjs\""
50
50
  },
51
- {
52
- "type": "command",
53
- "command": "node \".codex/hooks/completion-authority.cjs\"",
54
- "commandWindows": "node \".codex/hooks/completion-authority.cjs\""
55
- },
56
51
  {
57
52
  "type": "command",
58
53
  "command": "node \".codex/hooks/rules.cjs\"",
@@ -79,11 +74,6 @@
79
74
  "type": "command",
80
75
  "command": "node \".codex/hooks/inspect-block.cjs\"",
81
76
  "commandWindows": "node \".codex/hooks/inspect-block.cjs\""
82
- },
83
- {
84
- "type": "command",
85
- "command": "node \".codex/hooks/task-scaffold-guard.cjs\"",
86
- "commandWindows": "node \".codex/hooks/task-scaffold-guard.cjs\""
87
77
  }
88
78
  ]
89
79
  }
@@ -108,11 +98,6 @@
108
98
  "command": "node \".codex/hooks/spec-gate.cjs\"",
109
99
  "commandWindows": "node \".codex/hooks/spec-gate.cjs\""
110
100
  },
111
- {
112
- "type": "command",
113
- "command": "node \".codex/hooks/completion-authority.cjs\"",
114
- "commandWindows": "node \".codex/hooks/completion-authority.cjs\""
115
- },
116
101
  {
117
102
  "type": "command",
118
103
  "command": "node \".codex/hooks/state.cjs\"",
@@ -125,11 +110,6 @@
125
110
  {
126
111
  "matcher": "*",
127
112
  "hooks": [
128
- {
129
- "type": "command",
130
- "command": "node \".codex/hooks/semantic-review-authority.cjs\"",
131
- "commandWindows": "node \".codex/hooks/semantic-review-authority.cjs\""
132
- },
133
113
  {
134
114
  "type": "command",
135
115
  "command": "node \".codex/hooks/state.cjs\"",
@@ -51,19 +51,10 @@ proves only the boundary it executed.
51
51
 
52
52
  ## Human gates and workflow ownership
53
53
 
54
- - C1 records the user's scope decision before the plan is written.
55
- - C2 records the user's disposition of deduplicated adversarial findings.
54
+ - GATE-SCOPE records the user's scope decision before the plan is written.
55
+ - GATE-REVIEW records the user's disposition of deduplicated adversarial findings.
56
56
  - Develop starts only after a new explicit user invocation and executes one
57
57
  unblocked task at a time.
58
58
  - Sync changes only observed file state and never starts implementation.
59
- - C3 occurs after current receipts and limitations are shown; the user decides
59
+ - GATE-DONE occurs after current receipts and limitations are shown; the user decides
60
60
  whether the requested feature is complete.
61
-
62
- ## Legacy compatibility
63
-
64
- Existing packets containing `spec.json`, nested `tasks/task-R*.md`, or other
65
- legacy kernel artifacts stay on their installed adapters. Preserve their
66
- `task_registry`, `semantic_model`, `planning_depth`, lane,
67
- `execution_tier`, typed topology, separate receipts, and feature closeout
68
- contract. Do not migrate that machine authority or storage shape while syncing
69
- an unrelated process-first packet.