@haposoft/cafekit 0.16.6 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) 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 +0 -36
  4. package/bin/__tests__/codex-native.test.js +46 -88
  5. package/bin/__tests__/develop-contract.test.js +26 -57
  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 +159 -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 +100 -541
  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 +0 -27
  20. package/bin/__tests__/specs-v2-execution-closeout.test.js +4 -69
  21. package/bin/__tests__/ui-ux-skill.test.js +101 -0
  22. package/bin/__tests__/usage-hook-retired.test.js +114 -0
  23. package/bin/__tests__/validator-grounding.test.js +9 -28
  24. package/bin/phases/codex-runtime.js +24 -0
  25. package/bin/phases/omp-runtime.js +22 -0
  26. package/package.json +1 -1
  27. package/src/claude/CLAUDE.md +3 -10
  28. package/src/claude/agents/brainstormer.md +7 -3
  29. package/src/claude/agents/code-auditor.md +35 -50
  30. package/src/claude/agents/debugger.md +5 -79
  31. package/src/claude/agents/deployer.md +3 -5
  32. package/src/claude/agents/docs-keeper.md +2 -7
  33. package/src/claude/agents/implementer.md +6 -9
  34. package/src/claude/agents/inspector.md +2 -3
  35. package/src/claude/agents/project-manager.md +7 -15
  36. package/src/claude/agents/researcher.md +9 -3
  37. package/src/claude/agents/spec-maker.md +11 -11
  38. package/src/claude/hooks/__tests__/fixtures/statusline-default.golden +1 -1
  39. package/src/claude/hooks/__tests__/spec-gate.test.js +112 -3
  40. package/src/claude/hooks/__tests__/spec-state-touched.test.js +134 -0
  41. package/src/claude/hooks/__tests__/state.test.js +68 -0
  42. package/src/claude/hooks/__tests__/statusline.test.js +140 -11
  43. package/src/claude/hooks/agent.cjs +2 -1
  44. package/src/claude/hooks/lib/context.cjs +0 -89
  45. package/src/claude/hooks/lib/hook-payload.cjs +2 -2
  46. package/src/claude/hooks/rules.cjs +2 -1
  47. package/src/claude/hooks/session.cjs +0 -1
  48. package/src/claude/hooks/spec-gate.cjs +18 -28
  49. package/src/claude/hooks/spec-state.cjs +95 -1
  50. package/src/claude/hooks/state.cjs +21 -2
  51. package/src/claude/migration-manifest.json +30 -15
  52. package/src/claude/rules/ai-dev-rules.md +1 -1
  53. package/src/claude/rules/hook-protocols.md +8 -15
  54. package/src/claude/rules/manage-docs.md +9 -23
  55. package/src/claude/rules/orchestrator.md +3 -4
  56. package/src/claude/rules/review-audit-self-decision.md +3 -3
  57. package/src/claude/rules/skill-domain-routing.md +1 -3
  58. package/src/claude/rules/skill-workflow-routing.md +4 -5
  59. package/src/claude/rules/state-sync.md +3 -12
  60. package/src/claude/rules/workflow.md +10 -18
  61. package/src/claude/runtime.schema.json +5 -3
  62. package/src/claude/scripts/generate-skill-catalog.cjs +7 -6
  63. package/src/claude/scripts/provenance.cjs +23 -5
  64. package/src/claude/scripts/spec-receipt.cjs +52 -6
  65. package/src/claude/scripts/spec-resolver.cjs +1 -2
  66. package/src/claude/scripts/validate-spec-output.cjs +5 -32
  67. package/src/claude/scripts/workflow-policy.cjs +22 -10
  68. package/src/claude/settings/settings.json +1 -32
  69. package/src/claude/skills/{question → ask}/SKILL.md +9 -75
  70. package/src/claude/skills/brainstorm/SKILL.md +43 -131
  71. package/src/claude/skills/code-review/SKILL.md +48 -17
  72. package/src/claude/skills/code-review/references/spec-compliance-review.md +2 -3
  73. package/src/claude/skills/code-review/references/verification-gate.md +22 -27
  74. package/src/claude/skills/debug/SKILL.md +29 -149
  75. package/src/claude/skills/develop/SKILL.md +27 -36
  76. package/src/claude/skills/develop/references/parallel-waves.md +0 -8
  77. package/src/claude/skills/develop/references/quality-gate.md +15 -13
  78. package/src/claude/skills/docs/SKILL.md +2 -2
  79. package/src/claude/skills/docs/references/update-workflow.md +1 -1
  80. package/src/claude/skills/fix/SKILL.md +153 -0
  81. package/src/claude/skills/{hotfix → fix}/references/diagnosis-protocol.md +2 -2
  82. package/src/claude/skills/{hotfix → fix}/references/parallel-patterns.md +2 -2
  83. package/src/claude/skills/{hotfix → fix}/references/prevention-gate.md +3 -3
  84. package/src/claude/skills/{hotfix → fix}/references/review-cycle.md +1 -1
  85. package/src/claude/skills/git/SKILL.md +48 -9
  86. package/src/claude/skills/git/references/commit-protocols.md +35 -16
  87. package/src/claude/skills/git/references/worktree-blueprint.md +42 -6
  88. package/src/claude/skills/orca/SKILL.md +9 -8
  89. package/src/claude/skills/research/SKILL.md +2 -0
  90. package/src/claude/skills/scout/SKILL.md +61 -0
  91. package/src/claude/skills/{inspect → scout}/references/internal-inspection.md +26 -10
  92. package/src/claude/skills/specs/SKILL.md +22 -29
  93. package/src/claude/skills/specs/references/review.md +8 -6
  94. package/src/claude/skills/specs/references/templates.md +38 -44
  95. package/src/claude/skills/sync/SKILL.md +8 -15
  96. package/src/claude/skills/sync/references/rebind-and-audit.md +59 -0
  97. package/src/claude/skills/sync/references/sync-protocols.md +4 -13
  98. package/src/claude/skills/test/SKILL.md +22 -3
  99. package/src/claude/skills/test/references/execution-strategy.md +83 -0
  100. package/src/claude/skills/test/references/failure-triage.md +1 -1
  101. package/src/claude/skills/ui-ux/LICENSE +21 -0
  102. package/src/claude/skills/ui-ux/SKILL.md +497 -0
  103. package/src/claude/skills/ui-ux/references/brand-tokens.md +90 -0
  104. package/src/claude/skills/ui-ux/references/budgets.md +113 -0
  105. package/src/claude/skills/ui-ux/references/checklist.md +271 -0
  106. package/src/claude/skills/ui-ux/references/components/accordion.md +246 -0
  107. package/src/claude/skills/ui-ux/references/components/avatar.md +153 -0
  108. package/src/claude/skills/ui-ux/references/components/banner.md +43 -0
  109. package/src/claude/skills/ui-ux/references/components/breadcrumb.md +201 -0
  110. package/src/claude/skills/ui-ux/references/components/button.md +142 -0
  111. package/src/claude/skills/ui-ux/references/components/card.md +113 -0
  112. package/src/claude/skills/ui-ux/references/components/charts.md +376 -0
  113. package/src/claude/skills/ui-ux/references/components/chat.md +132 -0
  114. package/src/claude/skills/ui-ux/references/components/choice-controls.md +369 -0
  115. package/src/claude/skills/ui-ux/references/components/comment-thread.md +17 -0
  116. package/src/claude/skills/ui-ux/references/components/description-list.md +116 -0
  117. package/src/claude/skills/ui-ux/references/components/empty-state.md +98 -0
  118. package/src/claude/skills/ui-ux/references/components/file-upload.md +107 -0
  119. package/src/claude/skills/ui-ux/references/components/inline-edit.md +128 -0
  120. package/src/claude/skills/ui-ux/references/components/input.md +161 -0
  121. package/src/claude/skills/ui-ux/references/components/list-row.md +56 -0
  122. package/src/claude/skills/ui-ux/references/components/loading.md +198 -0
  123. package/src/claude/skills/ui-ux/references/components/logo.md +147 -0
  124. package/src/claude/skills/ui-ux/references/components/otp-input.md +43 -0
  125. package/src/claude/skills/ui-ux/references/components/quantity-input.md +100 -0
  126. package/src/claude/skills/ui-ux/references/components/range-slider.md +16 -0
  127. package/src/claude/skills/ui-ux/references/components/small-controls.md +340 -0
  128. package/src/claude/skills/ui-ux/references/components/sortable-header.md +86 -0
  129. package/src/claude/skills/ui-ux/references/components/tag-input.md +14 -0
  130. package/src/claude/skills/ui-ux/references/components/timeline.md +38 -0
  131. package/src/claude/skills/ui-ux/references/components/tree.md +30 -0
  132. package/src/claude/skills/ui-ux/references/design-process.md +650 -0
  133. package/src/claude/skills/ui-ux/references/layouts/app-kanban.html +303 -0
  134. package/src/claude/skills/ui-ux/references/layouts/app.md +1369 -0
  135. package/src/claude/skills/ui-ux/references/layouts/form.md +430 -0
  136. package/src/claude/skills/ui-ux/references/layouts/overlay.md +552 -0
  137. package/src/claude/skills/ui-ux/references/layouts/pricing.md +204 -0
  138. package/src/claude/skills/ui-ux/references/locked-rules.md +35 -0
  139. package/src/claude/skills/ui-ux/references/principles.md +408 -0
  140. package/src/claude/skills/ui-ux/references/refactor.md +245 -0
  141. package/src/claude/skills/ui-ux/references/responsive.md +195 -0
  142. package/src/claude/skills/ui-ux/references/review.md +528 -0
  143. package/src/claude/skills/ui-ux/references/rules-color.md +623 -0
  144. package/src/claude/skills/ui-ux/references/rules-form.md +235 -0
  145. package/src/claude/skills/ui-ux/references/rules-state.md +680 -0
  146. package/src/claude/skills/ui-ux/references/rules-type.md +369 -0
  147. package/src/claude/skills/ui-ux/references/styles.md +311 -0
  148. package/src/claude/skills/ui-ux/references/system.md +219 -0
  149. package/src/claude/skills/ui-ux/references/tailwind-v4-traps.md +237 -0
  150. package/src/claude/skills/ui-ux/references/tokens.css +362 -0
  151. package/src/claude/skills/ui-ux/scripts/lint-skill.mjs +216 -0
  152. package/src/claude/skills/ui-ux/scripts/package.json +9 -0
  153. package/src/claude/skills/ui-ux/scripts/probe.mjs +4447 -0
  154. package/src/claude/skills/ui-ux-pro-max/SKILL.md +1 -1
  155. package/src/claude/status.cjs +149 -144
  156. package/src/codex/AGENTS.md +8 -13
  157. package/src/codex/hooks/agent.cjs +2 -1
  158. package/src/codex/hooks/lib/spec-receipt.cjs +5 -0
  159. package/src/codex/hooks/lib/spec-utils.cjs +0 -7
  160. package/src/codex/hooks/rules.cjs +2 -1
  161. package/src/codex/hooks/session.cjs +0 -2
  162. package/src/codex/hooks/spec-gate.cjs +8 -18
  163. package/src/codex/hooks.json +0 -20
  164. package/src/codex/rules/state-sync.md +3 -12
  165. package/src/common/AGENTS.md +2 -2
  166. package/src/omp/extensions/cafekit-bridge.mjs +6 -6
  167. package/src/claude/hooks/__tests__/completion-authority.test.js +0 -990
  168. package/src/claude/hooks/__tests__/semantic-review-authority.test.js +0 -259
  169. package/src/claude/hooks/completion-authority-check.cjs +0 -56
  170. package/src/claude/hooks/completion-authority-state.cjs +0 -527
  171. package/src/claude/hooks/completion-authority.cjs +0 -163
  172. package/src/claude/hooks/semantic-review-authority.cjs +0 -154
  173. package/src/claude/hooks/task-scaffold-guard.cjs +0 -114
  174. package/src/claude/hooks/usage.cjs +0 -197
  175. package/src/claude/skills/delegate/SKILL.md +0 -124
  176. package/src/claude/skills/delegate/references/codex-delegation.md +0 -71
  177. package/src/claude/skills/delegate/references/grok-delegation.md +0 -84
  178. package/src/claude/skills/hotfix/SKILL.md +0 -289
  179. package/src/claude/skills/inspect/SKILL.md +0 -142
  180. package/src/claude/skills/loop/SKILL.md +0 -114
  181. package/src/claude/skills/loop/references/bounded-loop-protocol.md +0 -104
  182. package/src/claude/skills/loop/references/metric-and-guard-contract.md +0 -76
  183. package/src/claude/skills/route/SKILL.md +0 -94
  184. package/src/claude/skills/route/references/agent-timing.md +0 -46
  185. package/src/claude/skills/route/references/chaining-patterns.md +0 -53
  186. package/src/claude/skills/route/references/task-taxonomy.md +0 -48
  187. package/src/codex/hooks/completion-authority-check.cjs +0 -67
  188. package/src/codex/hooks/completion-authority-state.cjs +0 -527
  189. package/src/codex/hooks/completion-authority.cjs +0 -109
  190. package/src/codex/hooks/semantic-review-authority.cjs +0 -130
  191. package/src/codex/hooks/task-scaffold-guard.cjs +0 -63
  192. /package/src/claude/skills/{question → ask}/templates/question.md +0 -0
  193. /package/src/claude/skills/{hotfix → fix}/references/escalation-tactics.md +0 -0
  194. /package/src/claude/skills/{hotfix → fix}/references/workflow-specialized.md +0 -0
@@ -22,10 +22,9 @@ Example prompt:
22
22
 
23
23
  ## Resource Constraints
24
24
 
25
- - Each subagent has a **200K token context window** — scope tasks to fit comfortably within it
26
- - Spawning many parallel agents degrades system performance — check available CPU/memory before scaling out. For parallel implementation waves the cap is 3 concurrent agents by default, never more than 5 (each agent carries the 200K budget above)
25
+ - Each subagent has its own context window — scope tasks to fit comfortably within it
26
+ - Spawning many parallel agents degrades system performance — check available CPU/memory before scaling out. For parallel implementation waves the cap is 3 concurrent agents by default, never more than 5 (each agent carries its own context window)
27
27
  - Prefer fewer, well-scoped agents over many overlapping ones
28
- - Include system resource info (from hook injection) when delegating tasks so subagents can self-regulate
29
28
 
30
29
  ---
31
30
 
@@ -132,7 +131,7 @@ Docs: [docs path]
132
131
 
133
132
  | ❌ Vague | ✅ Precise |
134
133
  |----------|-----------|
135
- | "Pick up where we left off" | "Add the `/users` POST endpoint per `phase-02.md`" |
134
+ | "Pick up where we left off" | "Add the `/users` POST endpoint per `task-02-api.md`" |
136
135
  | "Fix the issues we talked about" | "Add null-check in `auth.ts:45` — root cause: missing input validation" |
137
136
  | "Explore the codebase" | "Read `src/api/routes.ts`, then add the missing handler" |
138
137
  | Dumping 50+ lines of chat history | A 5-line summary with file paths |
@@ -12,10 +12,10 @@ When rejecting an audit concern, name the verification source briefly.
12
12
 
13
13
  ## User Decisions
14
14
 
15
- Do not silently undo an explicit user decision. This covers the C1 scope choice,
16
- C2 finding dispositions, and C3 completion judgement, along with thresholds,
15
+ Do not silently undo an explicit user decision. This covers the GATE-SCOPE scope choice,
16
+ GATE-REVIEW finding dispositions, and GATE-DONE completion judgement, along with thresholds,
17
17
  selected libraries, feature scope, schema shape, pricing, timelines, compliance
18
- choices, and UX trade-offs. Those gates are defined in `workflow.md`; this rule
18
+ choices, and UX trade-offs. Those gates are defined in `state-sync.md`; this rule
19
19
  governs only how a later review may treat them.
20
20
 
21
21
  If an audit suggests reversing a user decision, present:
@@ -27,6 +27,4 @@ an entry condition for the primary. If zero valid capabilities match, continue
27
27
  inline when safe or name the gap. If multiple catalog entries expose the same
28
28
  public identity, do not auto-route; require explicit user disambiguation.
29
29
 
30
- Never infer an optional document capability from this rule. Never select the
31
- explicit-only numeric optimization capability unless the user invokes it with
32
- its required bounded metric/guard contract.
30
+ Never infer an optional document capability from this rule.
@@ -9,9 +9,9 @@ workflow.
9
9
  1. If the user names a valid installed skill, use it directly.
10
10
  2. If one obvious low-risk installed skill covers the intent, use it directly.
11
11
  3. For direct factual conversation, answer directly or use the installed
12
- evidence-answer capability; do not invoke Route or agents for ceremony.
13
- 4. For ambiguous, multi-step, multi-domain, or elevated/high-risk work, use the
14
- installed Route capability to classify and compose the shortest valid chain.
12
+ evidence-answer capability; do not spawn agents for ceremony.
13
+ 4. For ambiguous, multi-step, multi-domain, or elevated/high-risk work, classify
14
+ it yourself and compose the shortest valid chain below.
15
15
 
16
16
  Resolve every abstract link against the current runtime catalog. An absent,
17
17
  invalid, folder-mismatched, duplicate, or retired entry is not routable. Continue
@@ -28,5 +28,4 @@ owner, entry condition, and observable exit per retained link. Diagnosis does
28
28
  not authorize repair; implementation does not authorize commit, push, deploy,
29
29
  publish, or release; no route expands the user's existing authority.
30
30
 
31
- Use `skill-domain-routing.md` to resolve domain capability slots. The numeric
32
- optimization capability remains explicit-only and must never be auto-routed.
31
+ Use `skill-domain-routing.md` to resolve domain capability slots.
@@ -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.
@@ -8,14 +8,14 @@ Use the CafeKit loop: **Understand -> Plan -> Execute -> Verify -> Sync**.
8
8
  - Read the active spec/task file when one exists.
9
9
  - Read and activate any CafeKit skill that likely applies before taking action.
10
10
  - Inspect only the code needed to understand the affected area.
11
- - Use `inspect` or focused search when structure is unclear.
11
+ - Use `cf:scout` or focused search when structure is unclear.
12
12
 
13
13
  ## 2. Plan
14
14
 
15
15
  - For non-trivial features, use `/cf:specs` to challenge the minimum scope,
16
- open C1, and create `specs/<feature>/plan.md` with flat
16
+ open GATE-SCOPE, and create `specs/<feature>/plan.md` with flat
17
17
  `task-NN-*.md` files beside it.
18
- - After adversarial review, open C2 and apply only the findings the user accepts
18
+ - After adversarial review, open GATE-REVIEW and apply only the findings the user accepts
19
19
  or revises. Specs never starts implementation.
20
20
  - Start implementation only after a new explicit `/cf:develop` invocation,
21
21
  then select one unblocked task at a time.
@@ -24,16 +24,18 @@ Use the CafeKit loop: **Understand -> Plan -> Execute -> Verify -> Sync**.
24
24
  - `Outcome`
25
25
  - `Scope`
26
26
  - `Ownership`
27
+ - `Steps`
27
28
  - `Acceptance`
28
29
  - `Dependencies`
29
30
  - `Verification Plan`
31
+ - `Failure Protocol`
30
32
  - If these are missing or too vague to verify, route back to spec correction.
31
33
 
32
34
  ## 3. Execute
33
35
 
34
36
  - Implement only the active scope.
35
37
  - Modify existing files directly; do not create duplicate "enhanced" variants.
36
- - Keep named contracts from `design.md` intact.
38
+ - Keep named contracts from the plan and task intact.
37
39
  - Do not use placeholder wiring, process-local stand-ins, or fake adapters as completion proof.
38
40
 
39
41
  ## 4. Verify
@@ -53,16 +55,15 @@ Use the CafeKit loop: **Understand -> Plan -> Execute -> Verify -> Sync**.
53
55
  sole writer of task Status and proof.
54
56
  - Keep exactly one `Status:` field. Write or replace the task's final inline
55
57
  `## Receipt` before setting `Status: done`.
56
- - A canonical Receipt contains the exact command, `Exit: 0`,
57
- `Verification: PASS`, runtime-derived Base and Head values, and non-empty
58
- fenced current output. Never invent, copy, or infer missing proof.
58
+ - The canonical Receipt is defined in `state-sync.md`. Never invent, copy, or
59
+ infer missing proof.
59
60
  - When the binding to Base and Head applies, and what the gate does and does not
60
61
  detect, are stated once in `state-sync.md`.
61
62
  - Re-read each edited task and reconcile its plan row, dependencies, acceptance
62
63
  mapping, status, and receipt without rewriting unrelated bytes.
63
- - Run docs checkpoint when a completed task affects public docs or architecture docs.
64
+ - Update affected existing docs when a completed task changes public or architecture docs.
64
65
  - After all requested work has current proof, show evidence and limitations at
65
- C3. The user decides whether the feature is complete.
66
+ GATE-DONE. The user decides whether the feature is complete.
66
67
 
67
68
  ## Production Or CI Issues
68
69
 
@@ -73,12 +74,3 @@ Use the CafeKit loop: **Understand -> Plan -> Execute -> Verify -> Sync**.
73
74
  5. Review before syncing or shipping.
74
75
 
75
76
  Do not patch symptoms before diagnosis unless the issue is a trivial syntax/type/lint failure with an obvious local cause.
76
-
77
- ## Legacy compatibility
78
-
79
- When an existing feature contains `spec.json`, nested `tasks/task-R*.md`, or
80
- other legacy kernel artifacts, keep using the installed adapter. Preserve its
81
- `task_registry`, `semantic_model`, `planning_depth`, lane,
82
- `execution_tier`, typed boundaries, separate receipts, and final feature
83
- receipt. Do not project that machine authority or storage shape into a new
84
- process-first packet.
@@ -58,7 +58,8 @@
58
58
  "scaffold_guard": {
59
59
  "type": "boolean",
60
60
  "default": true,
61
- "description": "Require task files to be generated by the scaffold script. Set false to write them by hand."
61
+ "deprecated": true,
62
+ "description": "Not honoured. The task-scaffold guard that read this key was removed; the key is kept so existing runtime.json files stay valid."
62
63
  },
63
64
  "tollgate": {
64
65
  "type": "boolean",
@@ -75,12 +76,13 @@
75
76
  "usage": {
76
77
  "type": "object",
77
78
  "additionalProperties": false,
78
- "description": "Usage and quota reporting.",
79
+ "deprecated": true,
80
+ "description": "Not honoured. The usage hook that read this key was removed; the statusline takes quota from the rate_limits Claude Code sends. Kept so existing runtime.json files stay valid.",
79
81
  "properties": {
80
82
  "enabled": {
81
83
  "type": "boolean",
82
84
  "default": true,
83
- "description": "Set false to stop fetching quota data for the statusline."
85
+ "description": "Not honoured. Nothing fetches quota data any more."
84
86
  }
85
87
  }
86
88
  },
@@ -15,12 +15,13 @@ const RETIRED_DIRECTORIES = new Set([
15
15
  'mobile-development',
16
16
  'devops',
17
17
  'react-best-practices',
18
+ 'inspect',
19
+ 'hotfix',
20
+ 'question',
21
+ 'loop',
22
+ 'route',
23
+ 'delegate',
18
24
  ]);
19
- const PUBLIC_SUFFIX_BY_DIRECTORY = {
20
- hotfix: 'fix',
21
- inspect: 'scout',
22
- question: 'ask',
23
- };
24
25
 
25
26
  function usage() {
26
27
  console.log(`Usage:
@@ -124,7 +125,7 @@ function publicIdentity(name) {
124
125
  }
125
126
 
126
127
  function expectedIdentity(directory) {
127
- return `cf:${PUBLIC_SUFFIX_BY_DIRECTORY[directory] || directory}`;
128
+ return `cf:${directory}`;
128
129
  }
129
130
 
130
131
  function diagnostic(code, directory, message) {
@@ -228,13 +228,30 @@ function identity(input) {
228
228
  return { root, specsRoot, specFile, feature, session, mode };
229
229
  }
230
230
 
231
+ // A Stop hook checks every done receipt against one checkout. Without a memo each
232
+ // receipt re-read the whole repository twice, so the gate grew with the number of
233
+ // done tasks (minutes on a large specs root). The memo is opt-in and lives only in
234
+ // the enabling process; every other caller still captures a fresh snapshot.
235
+ const snapshotMemo = new Map();
236
+ let snapshotMemoEnabled = false;
237
+ function enableSnapshotMemo() { snapshotMemoEnabled = true; }
238
+
239
+ function captureSnapshot(root, specsRoot) {
240
+ const key = `${root}\0${specsRoot}`;
241
+ if (snapshotMemoEnabled && snapshotMemo.has(key)) return snapshotMemo.get(key);
242
+ const base = gitBase(root, specsRoot);
243
+ const first = manifest(root, specsRoot);
244
+ const head = manifestDigest(first);
245
+ const second = manifest(root, specsRoot);
246
+ if (JSON.stringify(first) !== JSON.stringify(second) || gitBase(root, specsRoot) !== base) fail('worktree_race', 'checkout changed during provenance capture');
247
+ const snapshot = { base, head };
248
+ if (snapshotMemoEnabled) snapshotMemo.set(key, snapshot);
249
+ return snapshot;
250
+ }
251
+
231
252
  function deriveRuntimeProvenance(input) {
232
253
  const current = identity(input);
233
- const base = gitBase(current.root, current.specsRoot);
234
- const first = manifest(current.root, current.specsRoot);
235
- const head = manifestDigest(first);
236
- const second = manifest(current.root, current.specsRoot);
237
- if (JSON.stringify(first) !== JSON.stringify(second) || gitBase(current.root, current.specsRoot) !== base) fail('worktree_race', 'checkout changed during provenance capture');
254
+ const { base, head } = captureSnapshot(current.root, current.specsRoot);
238
255
  const stable = {
239
256
  schema_version: CONTEXT_SCHEMA_VERSION,
240
257
  project_root: current.root,
@@ -328,6 +345,7 @@ module.exports = {
328
345
  createReceiptBinding,
329
346
  deriveRuntimeContext: deriveRuntimeProvenance,
330
347
  deriveRuntimeProvenance,
348
+ enableSnapshotMemo,
331
349
  isTrustedRuntimeContext,
332
350
  recomputeRuntimeContext: recomputeRuntimeProvenance,
333
351
  recomputeRuntimeProvenance,
@@ -113,7 +113,10 @@ function hasNonEmptyFencedBlock(body) {
113
113
 
114
114
  function fieldValues(body, name) {
115
115
  const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
116
- const matcher = new RegExp(`^\\s*${escaped}\\s*:\\s*(.*?)\\s*$`, 'i');
116
+ // A leading list marker is accepted: every neighbouring section of a task file writes
117
+ // its fields as list items, so continuing that style inside the Receipt is the
118
+ // natural mistake rather than a malformed receipt.
119
+ const matcher = new RegExp(`^\\s*(?:[-*+]\\s+)?${escaped}\\s*:\\s*(.*?)\\s*$`, 'i');
117
120
  return String(body || '').split('\n').map((line) => line.match(matcher)).filter(Boolean).map((match) => match[1]);
118
121
  }
119
122
 
@@ -146,11 +149,18 @@ function workflowVerificationCommand(taskText) {
146
149
  if (current) current.push(line);
147
150
  }
148
151
  if (sections.length !== 1) return null;
149
- const commands = sections[0]
150
- .map((line) => line.match(/^\s*-\s+(?:\*\*Command\*\*|Command)\s*:\s*(.*?)\s*$/i))
151
- .filter(Boolean)
152
+ // Only a top-level `- Command:` counts: an indented one belongs to another field such as a
153
+ // Counterexample, and one under a `###` sub-heading is a side step that must not outrank
154
+ // the main block. When commands exist only under sub-headings, they are used as before.
155
+ const commandOf = (line) => line.match(/^-\s+(?:\*\*Command\*\*|Command)\s*:\s*(.*?)\s*$/i);
156
+ const firstSub = sections[0].findIndex((line) => /^###\s+/.test(line));
157
+ const main = (firstSub === -1 ? sections[0] : sections[0].slice(0, firstSub)).map(commandOf).filter(Boolean);
158
+ const commands = (main.length ? main : sections[0].map(commandOf).filter(Boolean))
152
159
  .map((match) => normalizedCommand(match[1]));
153
- return commands.length === 1 ? commands[0] : null;
160
+ // A plan may declare several commands when its proof takes more than one step. The last
161
+ // is canonical: earlier ones are prerequisites, and binding the Receipt to any of them
162
+ // would let a task close on its cheapest step. None declared still fails closed.
163
+ return commands.length >= 1 ? commands[commands.length - 1] : null;
154
164
  }
155
165
 
156
166
  function workflowCommandFailures(taskText, body) {
@@ -335,6 +345,41 @@ function checkWorkflowTaskReceipt(featureDir, taskPath, runtimeContext, policy)
335
345
  };
336
346
  }
337
347
 
348
+ // The gate used to answer every receipt failure with the same sentence — write a
349
+ // runtime-bound Receipt — which is the wrong instruction whenever the Receipt is
350
+ // present and one field simply could not be read. Name what to change instead.
351
+ const RECEIPT_FIX_HINTS = Object.freeze([
352
+ ['missing_receipt', 'add exactly one `## Receipt` section at the end of the file'],
353
+ ['task_status', 'the file needs exactly one `Status: done` line outside any fence'],
354
+ ['verification_state', 'add a `Verification: PASS` line'],
355
+ ['command', 'add a `Command:` line holding the exact command that was run'],
356
+ ['command_identity', 'the `Command:` line must match the Verification Plan command exactly'],
357
+ ['exit_result', 'add `Exit: 0`; a non-zero exit or a failure marker does not close a task'],
358
+ ['command_output', 'add a non-empty fenced block holding the real command output'],
359
+ ['placeholder', 'replace the placeholder values with real ones'],
360
+ ['provenance', 'add runtime-derived `Base:` and `Head:` lines matching the current runtime'],
361
+ ]);
362
+
363
+ /**
364
+ * Turn receipt check codes into one instruction naming what to change. When the receipt
365
+ * body is available, a provenance failure is refined: telling someone to add lines they
366
+ * already wrote sends them looking in the wrong place, and the common cause is a pair
367
+ * typed by hand — git short SHAs — rather than the pair this runtime derives.
368
+ */
369
+ function receiptFixHint(failures, body) {
370
+ const codes = new Set(Array.isArray(failures) ? failures : []);
371
+ const hints = RECEIPT_FIX_HINTS.filter(([code]) => codes.has(code)).map(([, hint]) => hint);
372
+ if (hints.length === 0) return null;
373
+ if (codes.has('provenance') && typeof body === 'string'
374
+ && fieldValues(body, 'Base').length > 0 && fieldValues(body, 'Head').length > 0) {
375
+ const index = hints.length - 1;
376
+ hints[index] = 'the `Base:` and `Head:` lines are present but are not the pair this runtime derives'
377
+ + ' — re-derive them (`Base` is a 40-character commit id, `Head` a 64-character tree digest);'
378
+ + ' git short SHAs typed by hand never match';
379
+ }
380
+ return hints.length === 1 ? hints[0] : `${hints.slice(0, -1).join('; ')}; and ${hints[hints.length - 1]}`;
381
+ }
382
+
338
383
  function workflowProofSignature(taskPath, proof) {
339
384
  const hash = crypto.createHash('sha256');
340
385
  hash.update('cafekit-workflow-proof-v1\0');
@@ -381,7 +426,7 @@ function checkWorkflowReceiptSet(candidates, projectRoot, runtimeSession, policy
381
426
  for (const taskPath of doneTasks) {
382
427
  const proof = checkWorkflowTaskReceipt(candidate.featureDir, taskPath, runtimeContext, policy);
383
428
  if (proof.failures.length > 0) {
384
- failures.push({ featureName: candidate.featureName, taskPath, failures: proof.failures });
429
+ failures.push({ featureName: candidate.featureName, taskPath, failures: proof.failures, body: proof.body });
385
430
  }
386
431
  }
387
432
  }
@@ -404,6 +449,7 @@ module.exports = {
404
449
  checkTaskReceipt,
405
450
  checkWorkflowReceiptSet,
406
451
  checkWorkflowTaskReceipt,
452
+ receiptFixHint,
407
453
  evidenceBody,
408
454
  readTaskProof,
409
455
  safeRead,
@@ -860,8 +860,7 @@ function explicitWorkflowFeatureName({ projectRoot, specsDir, explicitFeature, e
860
860
 
861
861
  /**
862
862
  * Resolve the authoring/execution workflow visible to prompt and Stop hooks.
863
- * Persisted spec resolution remains unchanged; process-v3 is an additive adapter
864
- * and never becomes completion-authority input by way of findAllSpecCandidates.
863
+ * Persisted spec resolution remains unchanged; process-v3 is an additive adapter.
865
864
  */
866
865
  function resolveWorkflowCandidate({ projectRoot, runtime, explicitFeature, explicitPath, target, includeCompleted = false } = {}) {
867
866
  if (!projectRoot) throw new TypeError('projectRoot required');
@@ -724,11 +724,9 @@ function taskDeclaresParallel(content, taskPath, errors) {
724
724
  }
725
725
 
726
726
  /**
727
- * Task files are created from the scaffold template (the scaffold-guard hook
728
- * forces creation through it), so every task starts as a stub full of `{{...}}`
729
- * placeholders. The hook guarantees the stub is CREATED via scaffold, but
730
- * nothing guaranteed the model FILLED it. An unfilled `{{...}}` is an
731
- * incomplete task — SKILL.md: "Leave NO {{...}} placeholder ... fails DoCT" —
727
+ * Task files are usually created from the scaffold template, so a task can start as
728
+ * a stub full of `{{...}}` placeholders, and nothing guarantees the model FILLED it.
729
+ * An unfilled `{{...}}` is an incomplete task — SKILL.md: "Leave NO {{...}} placeholder ... fails DoCT" —
732
730
  * so it is a hard error here. A `.../` path fragment is a not-yet-resolved path
733
731
  * placeholder; it is only a warning, because it usually survives in prose Steps
734
732
  * while the Related Files table (which spec-ground.cjs does verify) is already
@@ -2471,23 +2469,7 @@ function validateSemanticReview(specDir, spec, context, subCriteriaIds, designTe
2471
2469
  errors.push('spec.json.validation.semantic_review.reviewed_artifact_digest: stale or does not match final artifacts and canonical state');
2472
2470
  }
2473
2471
  }
2474
- if (context.policy?.assurance_level === 'Strict' && SHA256_RE.test(review.reviewed_artifact_digest || '')) {
2475
- try {
2476
- const authority = require('../hooks/semantic-review-authority.cjs');
2477
- const canonicalSpecDir = fs.realpathSync(specDir);
2478
- let root = fs.realpathSync(process.cwd());
2479
- if (!isPathInside(root, canonicalSpecDir)) root = path.dirname(path.dirname(canonicalSpecDir));
2480
- const attestation = authority.verifyAttestation(
2481
- root,
2482
- path.join(canonicalSpecDir, 'spec.json'),
2483
- spec.feature_name,
2484
- review.reviewed_artifact_digest,
2485
- );
2486
- if (!attestation.ok) errors.push(`spec.json.validation.semantic_review: Strict assurance requires matching host-observed reviewer PASS attestation (${attestation.reason})`);
2487
- } catch (error) {
2488
- errors.push(`spec.json.validation.semantic_review: Strict assurance attestation is unavailable (${error.message})`);
2489
- }
2490
- }
2472
+ if (context.policy?.assurance_level === 'Strict') errors.push('spec.json.validation.semantic_review: Strict assurance is no longer supported (its reviewer attestation hook was removed); move the packet to plan.md with flat task files');
2491
2473
 
2492
2474
  const criteria = Array.isArray(review.reviewed_criteria) ? review.reviewed_criteria : [];
2493
2475
  const criterionSet = new Set(criteria);
@@ -2901,16 +2883,7 @@ function validateSemanticReview21(specDir, spec, criteria, designIds, verificati
2901
2883
  }
2902
2884
  }
2903
2885
  for (const criterion of criteria) if (!covered.has(criterion)) errors.push(`semantic review counterexamples missing criterion ${criterion}`);
2904
- if (spec.workflow_policy?.assurance_level === 'Strict' && SHA256_RE.test(review.semantic_digest || '')) {
2905
- try {
2906
- const authority = require('../hooks/semantic-review-authority.cjs');
2907
- const root = canonicalProjectRoot(specDir);
2908
- const attestation = authority.verifyAttestation(root, path.join(specDir, 'spec.json'), spec.feature_name, review.semantic_digest);
2909
- if (!attestation.ok) errors.push(`spec.json.validation.semantic_review: Strict readiness requires matching allowlisted host-observed reviewer PASS attestation (${attestation.reason})`);
2910
- } catch (error) {
2911
- errors.push(`spec.json.validation.semantic_review: Strict readiness attestation is unavailable (${error.message})`);
2912
- }
2913
- }
2886
+ if (spec.workflow_policy?.assurance_level === 'Strict') errors.push('spec.json.validation.semantic_review: Strict assurance is no longer supported (its reviewer attestation hook was removed); move the packet to plan.md with flat task files');
2914
2887
  }
2915
2888
 
2916
2889
  function computeLineageId(featureName, createdAt) {
@@ -1884,6 +1884,18 @@ function flashState(taskRegistry = {}) {
1884
1884
  .map(([taskPath]) => taskPath);
1885
1885
  }
1886
1886
 
1887
+ // Every other section of a task file writes its fields as list items — the Verification
1888
+ // Plan's own `- Command:` sits a few lines above the Receipt — so continuing that house
1889
+ // style inside the Receipt is the natural mistake, and it used to fail five checks at
1890
+ // once with a message that pointed at the content instead of the dash. Accept either
1891
+ // form. The receipt body is cut to its own `## Receipt` section, so this cannot pick up
1892
+ // the Verification Plan's fields.
1893
+ const RECEIPT_FIELD_PREFIX = '\\s*(?:[-*+]\\s+)?';
1894
+
1895
+ function receiptFieldPattern(name, tail = '\\s*:', flags = '') {
1896
+ return new RegExp(`^${RECEIPT_FIELD_PREFIX}${name}${tail}`, flags);
1897
+ }
1898
+
1887
1899
  function validateCanonicalReceipt(body, options = {}) {
1888
1900
  if (typeof body !== 'string') return ['verification_state'];
1889
1901
  const failures = [];
@@ -1900,15 +1912,15 @@ function validateCanonicalReceipt(body, options = {}) {
1900
1912
  addFailure('verification_state');
1901
1913
  }
1902
1914
  // Unambiguous verification state: must be Verification: PASS exactly
1903
- if (!/^\s*Verification:\s*PASS\s*$/m.test(body)) {
1915
+ if (!receiptFieldPattern('Verification', '\\s*:\\s*PASS\\s*$', 'm').test(body)) {
1904
1916
  addFailure('verification_state');
1905
1917
  }
1906
1918
  // Command must be present with non-empty concrete value on same line, not placeholder
1907
- const cmdLine = body.split('\n').find((l) => /^\s*Command(?:\(s\))?\s*:/m.test(l)) || null;
1908
- if (!cmdLine || !/^\s*Command(?:\(s\))?\s*:[ \t]*\S/m.test(cmdLine)) {
1919
+ const cmdLine = body.split('\n').find((l) => receiptFieldPattern('Command(?:\\(s\\))?', '\\s*:', 'm').test(l)) || null;
1920
+ if (!cmdLine || !receiptFieldPattern('Command(?:\\(s\\))?', '\\s*:[ \\t]*\\S', 'm').test(cmdLine)) {
1909
1921
  addFailure('command');
1910
1922
  } else {
1911
- const m = cmdLine.match(/^\s*Command(?:\(s\))?\s*:[ \t]*(.*)$/m);
1923
+ const m = cmdLine.match(receiptFieldPattern('Command(?:\\(s\\))?', '\\s*:[ \\t]*(.*)$', 'm'));
1912
1924
  const val = m ? m[1].trim() : '';
1913
1925
  if (isPlaceholderToken(val)) {
1914
1926
  addFailure('command');
@@ -1921,15 +1933,15 @@ function validateCanonicalReceipt(body, options = {}) {
1921
1933
  const exitValues = [];
1922
1934
  const resultValues = [];
1923
1935
  for (const line of lines) {
1924
- if (/^\s*Exit\s*:/i.test(line)) {
1925
- const m = line.match(/^\s*Exit\s*:\s*(.*)$/i);
1936
+ if (receiptFieldPattern('Exit', '\\s*:', 'i').test(line)) {
1937
+ const m = line.match(receiptFieldPattern('Exit', '\\s*:\\s*(.*)$', 'i'));
1926
1938
  exitValues.push(m ? m[1].trim() : '');
1927
1939
  } else if (/exit\s+code\s*[:=]/i.test(line)) {
1928
1940
  const m = line.match(/exit\s+code\s*[:=]\s*(.*)$/i);
1929
1941
  if (m) exitValues.push(m[1].trim());
1930
1942
  }
1931
- if (/^\s*Result\s*:/i.test(line)) {
1932
- const m = line.match(/^\s*Result\s*:\s*(.+?)\s*$/i);
1943
+ if (receiptFieldPattern('Result', '\\s*:', 'i').test(line)) {
1944
+ const m = line.match(receiptFieldPattern('Result', '\\s*:\\s*(.+?)\\s*$', 'i'));
1933
1945
  resultValues.push(m ? m[1].trim() : '');
1934
1946
  }
1935
1947
  }
@@ -1954,8 +1966,8 @@ function validateCanonicalReceipt(body, options = {}) {
1954
1966
  // Without expected values this validates schema only; it does not claim identity binding.
1955
1967
  const receiptLines = body.split('\n');
1956
1968
  const readField = (name) => receiptLines
1957
- .filter((line) => new RegExp(`^\\s*${name}\\s*:`, 'i').test(line))
1958
- .map((line) => line.replace(new RegExp(`^\\s*${name}\\s*:\\s*`, 'i'), '').trim());
1969
+ .filter((line) => receiptFieldPattern(name, '\\s*:', 'i').test(line))
1970
+ .map((line) => line.replace(receiptFieldPattern(name, '\\s*:\\s*', 'i'), '').trim());
1959
1971
  const baseValues = readField('Base');
1960
1972
  const headValues = readField('Head');
1961
1973
  const baseShaValues = readField('base_sha');
@@ -14,10 +14,6 @@
14
14
  "type": "command",
15
15
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/session.cjs\""
16
16
  },
17
- {
18
- "type": "command",
19
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/docs-sync.cjs\""
20
- },
21
17
  {
22
18
  "type": "command",
23
19
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/state.cjs\""
@@ -58,18 +54,9 @@
58
54
  "type": "command",
59
55
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/rules.cjs\""
60
56
  },
61
- {
62
- "type": "command",
63
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/completion-authority.cjs\""
64
- },
65
57
  {
66
58
  "type": "command",
67
59
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/spec-state.cjs\""
68
- },
69
- {
70
- "type": "command",
71
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/usage.cjs\"",
72
- "timeout": 30
73
60
  }
74
61
  ]
75
62
  }
@@ -87,15 +74,6 @@
87
74
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/inspect-block.cjs\""
88
75
  }
89
76
  ]
90
- },
91
- {
92
- "matcher": "Write",
93
- "hooks": [
94
- {
95
- "type": "command",
96
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/task-scaffold-guard.cjs\""
97
- }
98
- ]
99
77
  }
100
78
  ],
101
79
  "PostToolUse": [
@@ -113,8 +91,7 @@
113
91
  "hooks": [
114
92
  {
115
93
  "type": "command",
116
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/usage.cjs\"",
117
- "timeout": 30
94
+ "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/spec-state.cjs\""
118
95
  }
119
96
  ]
120
97
  }
@@ -126,10 +103,6 @@
126
103
  "type": "command",
127
104
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/spec-gate.cjs\""
128
105
  },
129
- {
130
- "type": "command",
131
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/completion-authority.cjs\""
132
- },
133
106
  {
134
107
  "type": "command",
135
108
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/state.cjs\""
@@ -140,10 +113,6 @@
140
113
  "SubagentStop": [
141
114
  {
142
115
  "hooks": [
143
- {
144
- "type": "command",
145
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/semantic-review-authority.cjs\""
146
- },
147
116
  {
148
117
  "type": "command",
149
118
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/state.cjs\""