@haposoft/cafekit 0.18.0 → 0.18.2

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 (162) hide show
  1. package/README.md +12 -1
  2. package/bin/__tests__/claude-settings.test.js +123 -0
  3. package/bin/__tests__/codex-ask-guard.test.js +123 -0
  4. package/bin/__tests__/codex-ask-projection.test.js +51 -0
  5. package/bin/__tests__/codex-hooks-ownership.test.js +80 -1
  6. package/bin/__tests__/codex-hooks.test.js +938 -237
  7. package/bin/__tests__/codex-native-hook-boundaries.test.js +136 -0
  8. package/bin/__tests__/codex-native.test.js +222 -149
  9. package/bin/__tests__/codex-projection-parity.test.js +314 -0
  10. package/bin/__tests__/codex-quiet-hooks.test.js +170 -0
  11. package/bin/__tests__/codex-research-projection.test.js +70 -0
  12. package/bin/__tests__/codex-specs-projection.test.js +76 -0
  13. package/bin/__tests__/develop-contract.test.js +102 -1362
  14. package/bin/__tests__/docs-sync-on-demand.test.js +25 -20
  15. package/bin/__tests__/inspect-paths.test.js +183 -0
  16. package/bin/__tests__/installer-safety.test.js +335 -0
  17. package/bin/__tests__/legacy-authority-decoupled.test.js +14 -19
  18. package/bin/__tests__/legacy-hooks-retired.test.js +18 -8
  19. package/bin/__tests__/omp-bridge.test.js +66 -12
  20. package/bin/__tests__/omp-hooks.test.js +11 -5
  21. package/bin/__tests__/orca-session.test.js +7 -0
  22. package/bin/__tests__/package-inventory.test.js +1 -395
  23. package/bin/__tests__/privacy-paths.test.js +317 -0
  24. package/bin/__tests__/spec-narrowing.test.js +30 -134
  25. package/bin/__tests__/specs-v2-execution-closeout.test.js +0 -372
  26. package/bin/__tests__/test-runtime-dependency-closure.cjs +1 -2
  27. package/bin/__tests__/usage-hook-retired.test.js +5 -3
  28. package/bin/__tests__/validator-grounding.test.js +17 -2929
  29. package/bin/install.js +25 -0
  30. package/bin/lib/codex-install.js +134 -12
  31. package/bin/lib/context.js +1 -1
  32. package/bin/lib/managed-writer.js +2 -3
  33. package/bin/phases/claude-runtime.js +91 -25
  34. package/bin/phases/claude-settings.js +22 -1
  35. package/bin/phases/codex-hooks.js +96 -33
  36. package/bin/phases/codex-runtime.js +45 -49
  37. package/bin/phases/copy-payload.js +11 -28
  38. package/bin/phases/omp-runtime.js +6 -3
  39. package/package.json +2 -3
  40. package/src/claude/CLAUDE.md +4 -0
  41. package/src/claude/agents/code-auditor.md +9 -6
  42. package/src/claude/agents/debugger.md +3 -9
  43. package/src/claude/agents/docs-keeper.md +4 -7
  44. package/src/claude/agents/git-ops.md +2 -4
  45. package/src/claude/agents/implementer.md +6 -7
  46. package/src/claude/agents/inspector.md +2 -0
  47. package/src/claude/agents/project-manager.md +2 -2
  48. package/src/claude/agents/spec-maker.md +4 -4
  49. package/src/claude/agents/test-runner.md +8 -11
  50. package/src/claude/agents/ui-ux-designer.md +0 -1
  51. package/src/claude/gitignore +3 -0
  52. package/src/claude/hooks/__tests__/installed-root.test.js +111 -0
  53. package/src/claude/hooks/__tests__/precompact.test.js +206 -10
  54. package/src/claude/hooks/__tests__/privacy-block.test.js +27 -0
  55. package/src/claude/hooks/__tests__/session-writeenv.test.js +25 -0
  56. package/src/claude/hooks/__tests__/spec-gate.test.js +311 -340
  57. package/src/claude/hooks/__tests__/spec-state-touched.test.js +230 -8
  58. package/src/claude/hooks/__tests__/state.test.js +207 -7
  59. package/src/claude/hooks/__tests__/update-check.test.js +88 -0
  60. package/src/claude/hooks/agent.cjs +7 -6
  61. package/src/claude/hooks/inspect-block.cjs +15 -63
  62. package/src/claude/hooks/lib/inspect-paths.cjs +304 -0
  63. package/src/claude/hooks/lib/parser.cjs +1 -1
  64. package/src/claude/hooks/lib/privacy-command-analysis.cjs +191 -17
  65. package/src/claude/hooks/lib/privacy-paths.cjs +313 -0
  66. package/src/claude/hooks/lib/project-root.cjs +15 -0
  67. package/src/claude/hooks/lib/rules-reservation.cjs +36 -0
  68. package/src/claude/hooks/lib/spec-touch.cjs +67 -0
  69. package/src/claude/hooks/lib/update-check.cjs +77 -0
  70. package/src/claude/hooks/precompact.cjs +8 -15
  71. package/src/claude/hooks/privacy-block.cjs +23 -205
  72. package/src/claude/hooks/rules.cjs +6 -28
  73. package/src/claude/hooks/session.cjs +34 -117
  74. package/src/claude/hooks/spec-gate.cjs +17 -89
  75. package/src/claude/hooks/spec-state.cjs +89 -96
  76. package/src/claude/hooks/state.cjs +96 -51
  77. package/src/claude/migration-manifest.json +20 -8
  78. package/src/claude/output-styles/coding-level-0-eli5.md +9 -9
  79. package/src/claude/output-styles/coding-level-1-junior.md +3 -3
  80. package/src/claude/output-styles/coding-level-2-mid.md +3 -3
  81. package/src/claude/output-styles/coding-level-3-senior.md +2 -2
  82. package/src/claude/output-styles/coding-level-4-lead.md +5 -5
  83. package/src/claude/output-styles/coding-level-5-god.md +6 -6
  84. package/src/claude/rules/ai-dev-rules.md +1 -2
  85. package/src/claude/rules/hook-protocols.md +1 -1
  86. package/src/claude/rules/workflow.md +1 -1
  87. package/src/claude/runtime.json +0 -3
  88. package/src/claude/scripts/generate-skill-catalog.cjs +2 -2
  89. package/src/claude/scripts/provenance.cjs +14 -0
  90. package/src/claude/scripts/spec-receipt.cjs +0 -114
  91. package/src/claude/scripts/spec-resolver.cjs +41 -457
  92. package/src/claude/scripts/workflow-policy.cjs +3 -1801
  93. package/src/claude/settings/settings.json +1 -1
  94. package/src/claude/skills/agent-browser/SKILL.md +1 -1
  95. package/src/claude/skills/ai-multimodal/scripts/check_setup.py +8 -68
  96. package/src/claude/skills/ai-multimodal/scripts/gemini_batch_process.py +6 -28
  97. package/src/claude/skills/chrome-devtools/SKILL.md +14 -31
  98. package/src/claude/skills/code-review/SKILL.md +25 -108
  99. package/src/claude/skills/code-review/references/spec-compliance-review.md +4 -7
  100. package/src/claude/skills/develop/SKILL.md +22 -70
  101. package/src/claude/skills/develop/references/subagent-patterns.md +0 -6
  102. package/src/claude/skills/git/SKILL.md +1 -1
  103. package/src/claude/skills/git/references/worktree-blueprint.md +1 -1
  104. package/src/claude/skills/research/SKILL.md +24 -55
  105. package/src/claude/skills/sync/SKILL.md +12 -34
  106. package/src/claude/skills/sync/references/rebind-and-audit.md +2 -2
  107. package/src/claude/skills/test/SKILL.md +39 -123
  108. package/src/claude/skills/test/references/execution-strategy.md +11 -22
  109. package/src/claude/skills/ui-ux/SKILL.md +1 -1
  110. package/src/claude/skills/ui-ux-pro-max/SKILL.md +24 -79
  111. package/src/claude/skills/web-testing/SKILL.md +2 -20
  112. package/src/codex/AGENTS.md +8 -0
  113. package/src/codex/hooks/ask-guard.cjs +54 -0
  114. package/src/codex/hooks/inspect-block.cjs +11 -7
  115. package/src/codex/hooks/lib/inspect-paths.cjs +1 -199
  116. package/src/codex/hooks/lib/privacy-paths.cjs +1 -0
  117. package/src/codex/hooks/lib/privacy-state.cjs +98 -16
  118. package/src/codex/hooks/lib/rules-reservation.cjs +38 -0
  119. package/src/codex/hooks/lib/secret-keywords.cjs +1 -0
  120. package/src/codex/hooks/lib/spec-receipt.cjs +2 -30
  121. package/src/codex/hooks/lib/spec-session-touch.cjs +100 -0
  122. package/src/codex/hooks/lib/spec-touch.cjs +3 -0
  123. package/src/codex/hooks/lib/spec-utils.cjs +6 -45
  124. package/src/codex/hooks/lib/update-check.cjs +1 -0
  125. package/src/codex/hooks/precompact.cjs +39 -0
  126. package/src/codex/hooks/privacy-approval.cjs +28 -17
  127. package/src/codex/hooks/privacy-block.cjs +9 -215
  128. package/src/codex/hooks/rules.cjs +4 -30
  129. package/src/codex/hooks/secret-output-guardrail.cjs +1 -1
  130. package/src/codex/hooks/session.cjs +47 -11
  131. package/src/codex/hooks/spec-gate.cjs +32 -74
  132. package/src/codex/hooks/spec-state.cjs +68 -46
  133. package/src/codex/hooks/state.cjs +25 -4
  134. package/src/codex/hooks.json +39 -7
  135. package/src/codex/rules/hook-protocols.md +13 -6
  136. package/src/common/AGENTS.md +4 -10
  137. package/src/omp/extensions/cafekit-bridge.mjs +12 -4
  138. package/src/omp/hooks/privacy-block.cjs +24 -206
  139. package/bin/__tests__/change-firewall.semantic-firewall.test.js +0 -2133
  140. package/bin/__tests__/finalizer-pass-gate.semantic-firewall.test.js +0 -342
  141. package/bin/__tests__/release-preflight.semantic-firewall.test.js +0 -586
  142. package/bin/__tests__/review-receipt-c2.semantic-firewall.test.js +0 -378
  143. package/bin/__tests__/specs-v2-policy-and-scaffold.test.js +0 -665
  144. package/bin/__tests__/specs-v2-validator-grounder-contract.test.js +0 -1132
  145. package/src/claude/hooks/lib/context.cjs +0 -527
  146. package/src/claude/hooks/lib/detect.cjs +0 -474
  147. package/src/claude/scripts/change-firewall.cjs +0 -1748
  148. package/src/claude/scripts/spec-authoring-digest.cjs +0 -151
  149. package/src/claude/scripts/spec-authoring-validation.cjs +0 -126
  150. package/src/claude/scripts/spec-final-state.cjs +0 -290
  151. package/src/claude/scripts/spec-ground.cjs +0 -650
  152. package/src/claude/scripts/spec-readiness.cjs +0 -425
  153. package/src/claude/scripts/spec-scaffold.cjs +0 -2317
  154. package/src/claude/scripts/spec-semantic-model.cjs +0 -396
  155. package/src/claude/scripts/validate-spec-output.cjs +0 -3914
  156. package/src/claude/skills/code-review/references/verification-gate.md +0 -41
  157. package/src/claude/skills/specs/templates/design.md +0 -82
  158. package/src/claude/skills/specs/templates/requirements-init.md +0 -8
  159. package/src/claude/skills/specs/templates/requirements.md +0 -42
  160. package/src/claude/skills/specs/templates/spec-state.json +0 -56
  161. package/src/claude/skills/specs/templates/task.md +0 -47
  162. package/src/codex/rules/state-sync.md +0 -60
@@ -10,18 +10,18 @@ You are teaching someone who has NEVER written a single line of code. They don't
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Language Rules
16
16
  1. **MUST** use at least ONE real-world analogy per concept (cooking recipes, LEGO blocks, labeled boxes, etc.)
17
17
  2. **MUST** define EVERY technical term on first use with a simple comparison
18
18
  3. **MUST** spell out ALL acronyms and explain them (e.g., "API - Application Programming Interface - think of it like a waiter taking your order to the kitchen")
19
19
  4. **MUST** use "we" language to create partnership ("Let's try...", "We can...")
20
- 5. **MUST** end EVERY response with a check-in: "Does this make sense so far? Any questions about [specific topic]?"
20
+ 5. **MUST** end explanations with a short check-in, in the user's language, naming the topic just covered
21
21
 
22
22
  ### Code Rules
23
- 1. **MUST** add a comment explaining what EVERY single line does
24
- 2. **MUST** keep code blocks to 5-10 lines maximum - break larger examples into steps
23
+ 1. **MUST** add a comment explaining what every line does in code shown in chat (code written to files follows the project's comment rules)
24
+ 2. **MUST** keep each code block to one small idea - break larger examples into steps
25
25
  3. **MUST** use descriptive variable names that read like plain English (e.g., `numberOfApples` not `n`)
26
26
  4. **MUST** show the expected output/result after EVERY code block
27
27
  5. **MUST** start with the SIMPLEST possible version, then add complexity gradually
@@ -29,17 +29,17 @@ You are teaching someone who has NEVER written a single line of code. They don't
29
29
  ### Teaching Rules
30
30
  1. **MUST** explain the "why" BEFORE the "how"
31
31
  2. **MUST** use visual metaphors and real-world comparisons
32
- 3. **MUST** celebrate progress: "Great question!", "You're getting it!"
32
+ 3. **MUST** acknowledge progress specifically when the user gets something right
33
33
  4. **MUST** encourage experimentation: "Try changing X to see what happens!"
34
34
  5. **MUST** preemptively explain anything that might be confusing
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** assume they know ANY programming concept
41
41
  2. **NEVER** use technical jargon without explaining it first
42
- 3. **NEVER** show code blocks longer than 10 lines
42
+ 3. **NEVER** show a code block that teaches more than one idea at once
43
43
  4. **NEVER** use acronyms without spelling them out AND explaining
44
44
  5. **NEVER** skip steps - break everything into the smallest pieces
45
45
  6. **NEVER** use phrases like "obviously", "simply", "just", "easy"
@@ -50,7 +50,7 @@ You are teaching someone who has NEVER written a single line of code. They don't
50
50
 
51
51
  ## Required Response Structure
52
52
 
53
- Every response MUST follow this structure:
53
+ Use this structure for explanations; answer quick questions and report tool work directly:
54
54
 
55
55
  ### 1. Big Picture (1-2 sentences)
56
56
  What are we trying to accomplish? Use everyday language.
@@ -70,7 +70,7 @@ Give them something simple to experiment with.
70
70
  "Try changing the number 5 to 10 and see what happens!"
71
71
 
72
72
  ### 5. Check-In
73
- "Does this make sense so far? Any questions about [specific topic we just covered]?"
73
+ A short question, in the user's language, about the topic just covered.
74
74
 
75
75
  ---
76
76
 
@@ -10,7 +10,7 @@ You are mentoring a junior developer who understands basic programming (variable
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Explanation Rules
16
16
  1. **MUST** always explain WHY before showing HOW
@@ -24,7 +24,7 @@ You are mentoring a junior developer who understands basic programming (variable
24
24
  2. **MUST** use meaningful variable/function names that express intent
25
25
  3. **MUST** show before/after comparisons when refactoring or improving code
26
26
  4. **MUST** explain what each import/dependency does on first use
27
- 5. **MUST** keep code blocks under 30 lines - split larger examples
27
+ 5. **MUST** keep code examples focused - split larger examples
28
28
 
29
29
  ### Teaching Rules
30
30
  1. **MUST** define technical terms on first use (briefly, not ELI5-level)
@@ -35,7 +35,7 @@ You are mentoring a junior developer who understands basic programming (variable
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** assume they know advanced patterns (design patterns, architecture)
41
41
  2. **NEVER** skip explaining WHY - always give reasoning
@@ -10,7 +10,7 @@ You are collaborating with a solid developer who has 3-5 years of experience. Th
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
16
  1. **MUST** discuss design patterns and when/why to apply them
@@ -29,13 +29,13 @@ You are collaborating with a solid developer who has 3-5 years of experience. Th
29
29
  ### Growth Rules
30
30
  1. **MUST** encourage independent problem-solving ("Consider how you might...")
31
31
  2. **MUST** mention relevant design patterns by name
32
- 3. **MUST** suggest improvements beyond what was asked when obvious
32
+ 3. **MUST** point out an obvious problem you notice, without expanding the work beyond what was asked
33
33
  4. **MUST** discuss how this fits into larger system architecture
34
34
  5. **MUST** balance theory with practical implementation
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** explain basic programming concepts (loops, functions, variables)
41
41
  2. **NEVER** over-explain simple syntax
@@ -10,7 +10,7 @@ You are collaborating with a senior engineer (5-8 years experience) who thinks i
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
16
  1. **MUST** lead with trade-offs and decision points
@@ -35,7 +35,7 @@ You are collaborating with a senior engineer (5-8 years experience) who thinks i
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** explain basic or intermediate concepts
41
41
  2. **NEVER** add "Key Takeaways" or summary sections
@@ -10,17 +10,17 @@ You are advising a technical leader (8-15 years experience) who owns systems end
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
- 1. **MUST** lead with executive summary (3-4 sentences max)
16
+ 1. **MUST** lead with a short executive summary
17
17
  2. **MUST** quantify everything possible (latency, throughput, cost, effort)
18
18
  3. **MUST** be explicit about assumptions, unknowns, and confidence levels
19
19
  4. **MUST** identify decisions that need stakeholder alignment
20
20
  5. **MUST** consider cross-team and cross-system dependencies
21
21
 
22
22
  ### Risk Rules
23
- 1. **MUST** include formal risk assessment (likelihood × impact matrix)
23
+ 1. **MUST** include a likelihood × impact risk assessment when recommending a change
24
24
  2. **MUST** identify single points of failure
25
25
  3. **MUST** propose mitigation strategies for high-risk items
26
26
  4. **MUST** flag security, compliance, and legal implications
@@ -42,7 +42,7 @@ You are advising a technical leader (8-15 years experience) who owns systems end
42
42
 
43
43
  ---
44
44
 
45
- ## FORBIDDEN at this level (You MUST NOT do these)
45
+ ## Avoid at this level
46
46
 
47
47
  1. **NEVER** explain implementation details unless asked
48
48
  2. **NEVER** show trivial code - assume they can write it
@@ -58,7 +58,7 @@ You are advising a technical leader (8-15 years experience) who owns systems end
58
58
  ## Required Response Structure
59
59
 
60
60
  ### 1. Executive Summary
61
- 3-4 sentences. Key recommendation, critical risk, estimated effort.
61
+ A few sentences: key recommendation, critical risk, estimated effort.
62
62
 
63
63
  ### 2. Risk Assessment
64
64
  | Risk | Likelihood | Impact | Mitigation |
@@ -10,7 +10,7 @@ You are pair programming with an expert (15+ years, or deep domain specialist).
10
10
 
11
11
  ---
12
12
 
13
- ## MANDATORY RULES (You MUST follow ALL of these)
13
+ ## Rules
14
14
 
15
15
  ### Communication Rules
16
16
  1. **MUST** answer exactly what was asked - nothing more
@@ -30,18 +30,18 @@ You are pair programming with an expert (15+ years, or deep domain specialist).
30
30
  1. **MUST** match their communication style and pace
31
31
  2. **MUST** offer alternatives only when genuinely superior
32
32
  3. **MUST** flag only critical issues (security holes, data loss, production outages)
33
- 4. **MUST** skip the "here's what I did" - just show it
33
+ 4. **MUST** report file changes in a line or two (what changed, anything unresolved) without restating the request
34
34
  5. **MUST** respect their time as the most valuable resource
35
35
 
36
36
  ---
37
37
 
38
- ## FORBIDDEN at this level (You MUST NOT do these)
38
+ ## Avoid at this level
39
39
 
40
40
  1. **NEVER** explain concepts, patterns, or syntax
41
41
  2. **NEVER** add context, background, or motivation
42
42
  3. **NEVER** use phrases like "Here's how...", "Let me explain...", "This works by..."
43
- 4. **NEVER** add comments unless they request it
44
- 5. **NEVER** include "Key Takeaways", summaries, or next steps
43
+ 4. **NEVER** add comments to code shown in chat unless they request it
44
+ 5. **NEVER** include "Key Takeaways" or recap sections
45
45
  6. **NEVER** ask clarifying questions for minor ambiguities - make reasonable assumptions
46
46
  7. **NEVER** pad responses with alternatives unless they're meaningfully better
47
47
  8. **NEVER** treat them like they need hand-holding
@@ -55,7 +55,7 @@ You are pair programming with an expert (15+ years, or deep domain specialist).
55
55
  No required structure. Match the request:
56
56
 
57
57
  - **"How do I X?"** → Code block. Done.
58
- - **"What's wrong with X?"** → Point to the bug. One sentence max.
58
+ - **"What's wrong with X?"** → Point to the bug, briefly.
59
59
  - **"Which approach?"** → One-liner recommendation + brief rationale if non-obvious.
60
60
  - **"Review this"** → Bullet points of issues. No praise.
61
61
  - **Complex question** → Minimal prose + code. No sections.
@@ -34,8 +34,7 @@ Keep implementation simple, scoped, and verifiable.
34
34
 
35
35
  ## Skill And Tooling Use
36
36
 
37
- - Activate relevant skills before specialized work.
38
- - If a skill plausibly matches the task, prefer its workflow and references over an ad hoc plan.
37
+ - When a skill covers the task, follow its workflow and references instead of an ad hoc plan.
39
38
  - Use documentation lookup when current external docs matter.
40
39
  - Use `gh` for GitHub workflows and `psql` for Postgres inspection when needed.
41
40
  - Use multimodal/image/document skills for visual or document-heavy tasks.
@@ -24,5 +24,5 @@ Never use another command, path, encoding, or side channel to access a privacy-b
24
24
 
25
25
  - Treat hook errors as blockers when they affect safety, privacy, or task state.
26
26
  - Record the blocker in the task/spec state when relevant.
27
- - If the hook output is malformed, stop and ask for clarification instead of guessing.
27
+ - If hook output is malformed, stop and report the exact failure instead of guessing.
28
28
 
@@ -6,7 +6,7 @@ Use the CafeKit loop: **Understand -> Plan -> Execute -> Verify -> Sync**.
6
6
 
7
7
  - Read `./README.md` before feature planning or coding.
8
8
  - Read the active spec/task file when one exists.
9
- - Read and activate any CafeKit skill that likely applies before taking action.
9
+ - Use a CafeKit skill when its description matches the request; how to choose is in `skill-workflow-routing.md`.
10
10
  - Inspect only the code needed to understand the affected area.
11
11
  - Use `cf:scout` or focused search when structure is unclear.
12
12
 
@@ -26,9 +26,6 @@
26
26
  "thinkingLanguage": null,
27
27
  "responseLanguage": null
28
28
  },
29
- "usage": {
30
- "enabled": true
31
- },
32
29
  "hooks": {},
33
30
  "assertions": []
34
31
  }
@@ -27,7 +27,7 @@ function usage() {
27
27
  console.log(`Usage:
28
28
  node <runtime>/scripts/generate-skill-catalog.cjs [--skills] [--json] [--root <skills-dir>]
29
29
 
30
- The default root is bound to the script runtime: .claude/skills for Claude,
30
+ The default root is bound to the script runtime: the Claude runtime skills directory for Claude,
31
31
  .agents/skills for Codex, and ../skills for the source tree.`);
32
32
  }
33
33
 
@@ -192,7 +192,7 @@ function renderMarkdown(catalog) {
192
192
  const lines = ['# CafeKit Skills Catalog', '', `Skills root: \`${catalog.root}\``,
193
193
  `Routable skills: ${catalog.skills.length}`, ''];
194
194
  for (const skill of catalog.skills) {
195
- const intent = skill.when_to_use ? ` Use: ${skill.when_to_use}` : '';
195
+ const intent = skill.when_to_use && !skill.description.includes(skill.when_to_use) ? ` Use: ${skill.when_to_use}` : '';
196
196
  lines.push(`- \`${skill.name}\` (${skill.directory}, ${skill.category}): ${skill.description}${intent}`);
197
197
  }
198
198
  if (catalog.diagnostics.length > 0) {
@@ -84,6 +84,19 @@ function oneLine(value, label) {
84
84
  }
85
85
 
86
86
  function gitBase(root, specsRoot) {
87
+ const symbolic = spawnSync('git', ['-C', root, 'symbolic-ref', '-q', 'HEAD'], { encoding: 'buffer' });
88
+ if (!symbolic.error && !symbolic.signal && symbolic.status === 0) {
89
+ const ref = oneLine(symbolic.stdout, 'git symbolic-ref HEAD');
90
+ const exists = spawnSync('git', ['-C', root, 'show-ref', '--verify', '-q', ref], { encoding: 'buffer' });
91
+ if (!exists.error && !exists.signal && exists.status === 1) {
92
+ fail('no_git_history', 'repo has no commits yet; create the first commit, then record Base/Head after it');
93
+ }
94
+ if (exists.error || exists.signal || exists.status !== 0) {
95
+ fail('git_command_failed', `git show-ref HEAD failed: ${exists.error?.message || String(exists.stderr || '').trim() || `exit ${exists.status}`}`);
96
+ }
97
+ } else if (symbolic.error || symbolic.signal || symbolic.status !== 1) {
98
+ fail('git_command_failed', `git symbolic-ref HEAD failed: ${symbolic.error?.message || String(symbolic.stderr || '').trim() || `exit ${symbolic.status}`}`);
99
+ }
87
100
  const specsRelative = path.relative(root, specsRoot).split(path.sep).join('/');
88
101
  const sourceHistory = decode(runGit(
89
102
  root,
@@ -156,6 +169,7 @@ const RUNTIME_STATE_ROOTS = Object.freeze([
156
169
  '.claude/hooks/.logs', '.codex/hooks/.logs', '.omp/hooks/.logs',
157
170
  '.claude/.logs', '.codex/.logs', '.omp/.logs',
158
171
  '.claude/runtime.json', '.codex/runtime.json', '.omp/runtime.json',
172
+ '.codex/session-state', '.codex/hooks/.privacy',
159
173
  ]);
160
174
 
161
175
  function excluded(root, absolute, specsRoot) {
@@ -6,12 +6,6 @@ const path = require('path');
6
6
  const { spawnSync } = require('child_process');
7
7
  const { annotatedMarkdownLines } = require('./spec-resolver.cjs');
8
8
 
9
- const EVIDENCE_HEADINGS = new Set([
10
- 'Evidence',
11
- 'Task Test Plan & Verification Evidence',
12
- 'Verification & Evidence',
13
- ]);
14
-
15
9
  function inside(root, target) {
16
10
  const relative = path.relative(path.resolve(root), path.resolve(target));
17
11
  return relative === '' || (relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
@@ -40,34 +34,6 @@ function safeRead(root, relativePath) {
40
34
  }
41
35
  }
42
36
 
43
- function canonicalTaskReceiptPath(taskPath) {
44
- if (typeof taskPath !== 'string') return null;
45
- const match = taskPath.match(/^tasks\/(task-[A-Za-z0-9][A-Za-z0-9._-]*\.md)$/);
46
- return match ? `receipts/${match[1]}` : null;
47
- }
48
-
49
- function evidenceBody(text, policy = {}) {
50
- const lines = String(text || '').split('\n');
51
- let start = -1;
52
- let level = 0;
53
- for (let index = 0; index < lines.length; index += 1) {
54
- const match = lines[index].match(/^(#{2,3})\s+(.+?)\s*$/);
55
- if (match && EVIDENCE_HEADINGS.has(match[2])) {
56
- start = index + 1;
57
- level = match[1].length;
58
- break;
59
- }
60
- }
61
- if (start < 0) return null;
62
- let end = lines.length;
63
- for (let index = start; index < lines.length; index += 1) {
64
- const heading = lines[index].match(/^(#{1,6})\s+/);
65
- const tap = typeof policy.isTapMetadataHeading === 'function' && policy.isTapMetadataHeading(lines[index]);
66
- if (heading && heading[1].length <= level && !tap) { end = index; break; }
67
- }
68
- return lines.slice(start, end).join('\n');
69
- }
70
-
71
37
  function workflowReceiptBody(text, policy = {}) {
72
38
  const lines = annotatedMarkdownLines(text);
73
39
  const starts = [];
@@ -174,20 +140,6 @@ function workflowCommandFailures(taskText, body) {
174
140
  : ['command_identity'];
175
141
  }
176
142
 
177
- function plannedField(taskText, name) {
178
- const plan = String(taskText || '').split(/^##\s+Verification Plan\s*$/m)[1];
179
- if (!plan) return null;
180
- const value = fieldValues(plan.split(/^##\s+/m)[0], `- **${name}**`)[0];
181
- return value ? value.replace(/^`|`$/g, '').trim() : null;
182
- }
183
-
184
- function identity(body) {
185
- const names = ['Verification', 'Command', 'Commands', 'Exit', 'Result', 'Base', 'Head', 'base_sha', 'head_sha'];
186
- const fields = names.flatMap((name) => fieldValues(body, name).map((value) => [name.toLowerCase(), value.trim()]));
187
- const artifacts = String(body || '').split('\n').filter((line) => /^\s*Artifacts?\s*:|^\s*Artifact\s+produced\b/i.test(line)).map((line) => line.trim());
188
- return crypto.createHash('sha256').update(JSON.stringify({ fields, artifacts })).digest('hex');
189
- }
190
-
191
143
  function tryGitBytes(root, args) {
192
144
  const result = spawnSync('git', ['-C', root, ...args], { encoding: 'buffer', maxBuffer: 64 * 1024 * 1024 });
193
145
  if (result.error || result.status !== 0) return null;
@@ -247,57 +199,6 @@ function canonicalFailures(body, task, runtimeContext, policy, { bindProvenance
247
199
  return policy.validateCanonicalReceipt(body, options);
248
200
  }
249
201
 
250
- function separateMetadataFailures(body, taskPath, taskText) {
251
- const failures = [];
252
- const basename = path.posix.basename(taskPath);
253
- if (fieldValues(body, 'Task').length !== 1 || fieldValues(body, 'Task')[0] !== basename) failures.push('task_identity');
254
- if (fieldValues(body, 'Task path').length !== 1 || fieldValues(body, 'Task path')[0] !== taskPath) failures.push('task_identity');
255
- if (!concrete(fieldValues(body, 'Expected')[0]) || !concrete(fieldValues(body, 'Observed')[0])) failures.push('expected_observed');
256
- const plannedCommand = plannedField(taskText, 'Command');
257
- const actualCommand = fieldValues(body, 'Command')[0] || fieldValues(body, 'Commands')[0];
258
- if (plannedCommand && !/^N\/A\b/i.test(plannedCommand) && actualCommand !== plannedCommand) failures.push('command_identity');
259
- for (const name of ['Negative path', 'Reachability']) {
260
- const planned = plannedField(taskText, name);
261
- if (planned && !/^(?:N\/A|none|not relevant)\b/i.test(planned) && !concrete(fieldValues(body, name)[0])) failures.push(name.toLowerCase().replace(' ', '_'));
262
- }
263
- return [...new Set(failures)];
264
- }
265
-
266
- function readTaskProof(featureDir, taskPath, policy = {}) {
267
- const receiptPath = canonicalTaskReceiptPath(taskPath);
268
- if (typeof taskPath !== 'string' || !/^tasks\/[^/]+\.md$/.test(taskPath)) return { status: 'unsafe', taskPath, receiptPath: null };
269
- const taskFile = safeRead(featureDir, taskPath);
270
- if (taskFile.status !== 'ok') return { status: taskFile.status, taskPath, receiptPath };
271
- const taskText = taskFile.bytes.toString('utf8');
272
- const separate = receiptPath ? safeRead(featureDir, receiptPath) : { status: 'missing' };
273
- const legacyBody = evidenceBody(taskText, policy);
274
- if (separate.status === 'unsafe') return { status: 'unsafe', taskPath, receiptPath, taskFile };
275
- if (separate.status === 'ok') {
276
- const body = separate.bytes.toString('utf8');
277
- return { status: 'ok', source: 'separate', body, receiptBytes: separate.bytes, receiptFile: separate, taskFile, taskText, taskPath, receiptPath, legacyBody };
278
- }
279
- if (legacyBody !== null) return { status: 'ok', source: 'legacy', body: legacyBody, receiptBytes: Buffer.from(legacyBody), taskFile, taskText, taskPath, receiptPath, legacyBody };
280
- return { status: 'missing', taskPath, receiptPath, taskFile, taskText };
281
- }
282
-
283
- function checkTaskReceipt(featureDir, taskPath, task, runtimeContext, policy) {
284
- const proof = readTaskProof(featureDir, taskPath, policy);
285
- const failures = [];
286
- if (proof.status !== 'ok') return { ...proof, failures: [proof.status === 'unsafe' ? 'unsafe_path' : 'missing_receipt'] };
287
- const status = proof.taskText.split('\n').find((line) => /^\s*(?:\*\*)?Status(?:\*\*)?\s*:/i.test(line));
288
- if (!status || !/\bdone\b/i.test(status)) failures.push('task_status');
289
- failures.push(...canonicalFailures(proof.body, task, runtimeContext, policy));
290
- if (proof.source === 'separate') {
291
- failures.push(...separateMetadataFailures(proof.body, taskPath, proof.taskText));
292
- if (proof.legacyBody !== null
293
- && /^\s*Verification:\s*PASS\s*$/m.test(proof.legacyBody)
294
- && identity(proof.legacyBody) !== identity(proof.body)) failures.push('receipt_conflict');
295
- }
296
- const completedAt = task && task.completed_at;
297
- if (typeof completedAt !== 'string' || !/^\d{4}-\d{2}-\d{2}T/.test(completedAt) || Number.isNaN(Date.parse(completedAt))) failures.push('completed_at');
298
- return { ...proof, failures: [...new Set(failures)] };
299
- }
300
-
301
202
  function checkWorkflowTaskReceipt(featureDir, taskPath, runtimeContext, policy) {
302
203
  const safeTaskPath = typeof taskPath === 'string' && /^task-[A-Za-z0-9][A-Za-z0-9._-]*\.md$/.test(taskPath);
303
204
  if (!safeTaskPath) return { status: 'unsafe', taskPath, failures: ['unsafe_path'] };
@@ -433,25 +334,10 @@ function checkWorkflowReceiptSet(candidates, projectRoot, runtimeSession, policy
433
334
  return { failures };
434
335
  }
435
336
 
436
- function checkFeatureReceipt(featureDir, runtimeContext, policy) {
437
- const receipt = safeRead(featureDir, 'feature-receipt.md');
438
- if (receipt.status !== 'ok') return { status: receipt.status, failures: [receipt.status === 'unsafe' ? 'unsafe_path' : 'missing_receipt'] };
439
- const body = receipt.bytes.toString('utf8');
440
- const failures = canonicalFailures(body, {}, runtimeContext, policy);
441
- if (fieldValues(body, 'Feature').length !== 1 || fieldValues(body, 'Feature')[0] !== path.basename(featureDir)) failures.push('feature_identity');
442
- if (!concrete(fieldValues(body, 'Expected')[0]) || !concrete(fieldValues(body, 'Observed')[0])) failures.push('expected_observed');
443
- return { status: 'ok', source: 'feature', body, receiptBytes: receipt.bytes, receiptFile: receipt, failures: [...new Set(failures)] };
444
- }
445
-
446
337
  module.exports = {
447
- canonicalTaskReceiptPath,
448
- checkFeatureReceipt,
449
- checkTaskReceipt,
450
338
  checkWorkflowReceiptSet,
451
339
  checkWorkflowTaskReceipt,
452
340
  receiptFixHint,
453
- evidenceBody,
454
- readTaskProof,
455
341
  safeRead,
456
342
  workflowDependencyProofState,
457
343
  workflowReceiptBody,