@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.
- package/README.md +12 -1
- package/bin/__tests__/claude-settings.test.js +123 -0
- package/bin/__tests__/codex-ask-guard.test.js +123 -0
- package/bin/__tests__/codex-ask-projection.test.js +51 -0
- package/bin/__tests__/codex-hooks-ownership.test.js +80 -1
- package/bin/__tests__/codex-hooks.test.js +938 -237
- package/bin/__tests__/codex-native-hook-boundaries.test.js +136 -0
- package/bin/__tests__/codex-native.test.js +222 -149
- package/bin/__tests__/codex-projection-parity.test.js +314 -0
- package/bin/__tests__/codex-quiet-hooks.test.js +170 -0
- package/bin/__tests__/codex-research-projection.test.js +70 -0
- package/bin/__tests__/codex-specs-projection.test.js +76 -0
- package/bin/__tests__/develop-contract.test.js +102 -1362
- package/bin/__tests__/docs-sync-on-demand.test.js +25 -20
- package/bin/__tests__/inspect-paths.test.js +183 -0
- package/bin/__tests__/installer-safety.test.js +335 -0
- package/bin/__tests__/legacy-authority-decoupled.test.js +14 -19
- package/bin/__tests__/legacy-hooks-retired.test.js +18 -8
- package/bin/__tests__/omp-bridge.test.js +66 -12
- package/bin/__tests__/omp-hooks.test.js +11 -5
- package/bin/__tests__/orca-session.test.js +7 -0
- package/bin/__tests__/package-inventory.test.js +1 -395
- package/bin/__tests__/privacy-paths.test.js +317 -0
- package/bin/__tests__/spec-narrowing.test.js +30 -134
- package/bin/__tests__/specs-v2-execution-closeout.test.js +0 -372
- package/bin/__tests__/test-runtime-dependency-closure.cjs +1 -2
- package/bin/__tests__/usage-hook-retired.test.js +5 -3
- package/bin/__tests__/validator-grounding.test.js +17 -2929
- package/bin/install.js +25 -0
- package/bin/lib/codex-install.js +134 -12
- package/bin/lib/context.js +1 -1
- package/bin/lib/managed-writer.js +2 -3
- package/bin/phases/claude-runtime.js +91 -25
- package/bin/phases/claude-settings.js +22 -1
- package/bin/phases/codex-hooks.js +96 -33
- package/bin/phases/codex-runtime.js +45 -49
- package/bin/phases/copy-payload.js +11 -28
- package/bin/phases/omp-runtime.js +6 -3
- package/package.json +2 -3
- package/src/claude/CLAUDE.md +4 -0
- package/src/claude/agents/code-auditor.md +9 -6
- package/src/claude/agents/debugger.md +3 -9
- package/src/claude/agents/docs-keeper.md +4 -7
- package/src/claude/agents/git-ops.md +2 -4
- package/src/claude/agents/implementer.md +6 -7
- package/src/claude/agents/inspector.md +2 -0
- package/src/claude/agents/project-manager.md +2 -2
- package/src/claude/agents/spec-maker.md +4 -4
- package/src/claude/agents/test-runner.md +8 -11
- package/src/claude/agents/ui-ux-designer.md +0 -1
- package/src/claude/gitignore +3 -0
- package/src/claude/hooks/__tests__/installed-root.test.js +111 -0
- package/src/claude/hooks/__tests__/precompact.test.js +206 -10
- package/src/claude/hooks/__tests__/privacy-block.test.js +27 -0
- package/src/claude/hooks/__tests__/session-writeenv.test.js +25 -0
- package/src/claude/hooks/__tests__/spec-gate.test.js +311 -340
- package/src/claude/hooks/__tests__/spec-state-touched.test.js +230 -8
- package/src/claude/hooks/__tests__/state.test.js +207 -7
- package/src/claude/hooks/__tests__/update-check.test.js +88 -0
- package/src/claude/hooks/agent.cjs +7 -6
- package/src/claude/hooks/inspect-block.cjs +15 -63
- package/src/claude/hooks/lib/inspect-paths.cjs +304 -0
- package/src/claude/hooks/lib/parser.cjs +1 -1
- package/src/claude/hooks/lib/privacy-command-analysis.cjs +191 -17
- package/src/claude/hooks/lib/privacy-paths.cjs +313 -0
- package/src/claude/hooks/lib/project-root.cjs +15 -0
- package/src/claude/hooks/lib/rules-reservation.cjs +36 -0
- package/src/claude/hooks/lib/spec-touch.cjs +67 -0
- package/src/claude/hooks/lib/update-check.cjs +77 -0
- package/src/claude/hooks/precompact.cjs +8 -15
- package/src/claude/hooks/privacy-block.cjs +23 -205
- package/src/claude/hooks/rules.cjs +6 -28
- package/src/claude/hooks/session.cjs +34 -117
- package/src/claude/hooks/spec-gate.cjs +17 -89
- package/src/claude/hooks/spec-state.cjs +89 -96
- package/src/claude/hooks/state.cjs +96 -51
- package/src/claude/migration-manifest.json +20 -8
- package/src/claude/output-styles/coding-level-0-eli5.md +9 -9
- package/src/claude/output-styles/coding-level-1-junior.md +3 -3
- package/src/claude/output-styles/coding-level-2-mid.md +3 -3
- package/src/claude/output-styles/coding-level-3-senior.md +2 -2
- package/src/claude/output-styles/coding-level-4-lead.md +5 -5
- package/src/claude/output-styles/coding-level-5-god.md +6 -6
- package/src/claude/rules/ai-dev-rules.md +1 -2
- package/src/claude/rules/hook-protocols.md +1 -1
- package/src/claude/rules/workflow.md +1 -1
- package/src/claude/runtime.json +0 -3
- package/src/claude/scripts/generate-skill-catalog.cjs +2 -2
- package/src/claude/scripts/provenance.cjs +14 -0
- package/src/claude/scripts/spec-receipt.cjs +0 -114
- package/src/claude/scripts/spec-resolver.cjs +41 -457
- package/src/claude/scripts/workflow-policy.cjs +3 -1801
- package/src/claude/settings/settings.json +1 -1
- package/src/claude/skills/agent-browser/SKILL.md +1 -1
- package/src/claude/skills/ai-multimodal/scripts/check_setup.py +8 -68
- package/src/claude/skills/ai-multimodal/scripts/gemini_batch_process.py +6 -28
- package/src/claude/skills/chrome-devtools/SKILL.md +14 -31
- package/src/claude/skills/code-review/SKILL.md +25 -108
- package/src/claude/skills/code-review/references/spec-compliance-review.md +4 -7
- package/src/claude/skills/develop/SKILL.md +22 -70
- package/src/claude/skills/develop/references/subagent-patterns.md +0 -6
- package/src/claude/skills/git/SKILL.md +1 -1
- package/src/claude/skills/git/references/worktree-blueprint.md +1 -1
- package/src/claude/skills/research/SKILL.md +24 -55
- package/src/claude/skills/sync/SKILL.md +12 -34
- package/src/claude/skills/sync/references/rebind-and-audit.md +2 -2
- package/src/claude/skills/test/SKILL.md +39 -123
- package/src/claude/skills/test/references/execution-strategy.md +11 -22
- package/src/claude/skills/ui-ux/SKILL.md +1 -1
- package/src/claude/skills/ui-ux-pro-max/SKILL.md +24 -79
- package/src/claude/skills/web-testing/SKILL.md +2 -20
- package/src/codex/AGENTS.md +8 -0
- package/src/codex/hooks/ask-guard.cjs +54 -0
- package/src/codex/hooks/inspect-block.cjs +11 -7
- package/src/codex/hooks/lib/inspect-paths.cjs +1 -199
- package/src/codex/hooks/lib/privacy-paths.cjs +1 -0
- package/src/codex/hooks/lib/privacy-state.cjs +98 -16
- package/src/codex/hooks/lib/rules-reservation.cjs +38 -0
- package/src/codex/hooks/lib/secret-keywords.cjs +1 -0
- package/src/codex/hooks/lib/spec-receipt.cjs +2 -30
- package/src/codex/hooks/lib/spec-session-touch.cjs +100 -0
- package/src/codex/hooks/lib/spec-touch.cjs +3 -0
- package/src/codex/hooks/lib/spec-utils.cjs +6 -45
- package/src/codex/hooks/lib/update-check.cjs +1 -0
- package/src/codex/hooks/precompact.cjs +39 -0
- package/src/codex/hooks/privacy-approval.cjs +28 -17
- package/src/codex/hooks/privacy-block.cjs +9 -215
- package/src/codex/hooks/rules.cjs +4 -30
- package/src/codex/hooks/secret-output-guardrail.cjs +1 -1
- package/src/codex/hooks/session.cjs +47 -11
- package/src/codex/hooks/spec-gate.cjs +32 -74
- package/src/codex/hooks/spec-state.cjs +68 -46
- package/src/codex/hooks/state.cjs +25 -4
- package/src/codex/hooks.json +39 -7
- package/src/codex/rules/hook-protocols.md +13 -6
- package/src/common/AGENTS.md +4 -10
- package/src/omp/extensions/cafekit-bridge.mjs +12 -4
- package/src/omp/hooks/privacy-block.cjs +24 -206
- package/bin/__tests__/change-firewall.semantic-firewall.test.js +0 -2133
- package/bin/__tests__/finalizer-pass-gate.semantic-firewall.test.js +0 -342
- package/bin/__tests__/release-preflight.semantic-firewall.test.js +0 -586
- package/bin/__tests__/review-receipt-c2.semantic-firewall.test.js +0 -378
- package/bin/__tests__/specs-v2-policy-and-scaffold.test.js +0 -665
- package/bin/__tests__/specs-v2-validator-grounder-contract.test.js +0 -1132
- package/src/claude/hooks/lib/context.cjs +0 -527
- package/src/claude/hooks/lib/detect.cjs +0 -474
- package/src/claude/scripts/change-firewall.cjs +0 -1748
- package/src/claude/scripts/spec-authoring-digest.cjs +0 -151
- package/src/claude/scripts/spec-authoring-validation.cjs +0 -126
- package/src/claude/scripts/spec-final-state.cjs +0 -290
- package/src/claude/scripts/spec-ground.cjs +0 -650
- package/src/claude/scripts/spec-readiness.cjs +0 -425
- package/src/claude/scripts/spec-scaffold.cjs +0 -2317
- package/src/claude/scripts/spec-semantic-model.cjs +0 -396
- package/src/claude/scripts/validate-spec-output.cjs +0 -3914
- package/src/claude/skills/code-review/references/verification-gate.md +0 -41
- package/src/claude/skills/specs/templates/design.md +0 -82
- package/src/claude/skills/specs/templates/requirements-init.md +0 -8
- package/src/claude/skills/specs/templates/requirements.md +0 -42
- package/src/claude/skills/specs/templates/spec-state.json +0 -56
- package/src/claude/skills/specs/templates/task.md +0 -47
- 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
|
-
##
|
|
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
|
|
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
|
|
24
|
-
2. **MUST** keep code
|
|
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**
|
|
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
|
-
##
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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**
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
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
|
-
##
|
|
13
|
+
## Rules
|
|
14
14
|
|
|
15
15
|
### Communication Rules
|
|
16
|
-
1. **MUST** lead with executive summary
|
|
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
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
##
|
|
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**
|
|
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
|
-
##
|
|
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"
|
|
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
|
|
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
|
-
-
|
|
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
|
|
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
|
-
-
|
|
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
|
|
package/src/claude/runtime.json
CHANGED
|
@@ -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:
|
|
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,
|