@haposoft/cafekit 0.18.0 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/__tests__/codex-hooks.test.js +169 -236
- package/bin/__tests__/codex-native.test.js +54 -114
- package/bin/__tests__/develop-contract.test.js +101 -1361
- package/bin/__tests__/legacy-authority-decoupled.test.js +14 -19
- package/bin/__tests__/package-inventory.test.js +1 -395
- 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__/validator-grounding.test.js +17 -2929
- package/bin/lib/managed-writer.js +2 -3
- package/bin/phases/codex-runtime.js +6 -3
- package/bin/phases/copy-payload.js +13 -28
- package/bin/phases/omp-runtime.js +6 -3
- package/package.json +2 -3
- 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/hooks/__tests__/spec-gate.test.js +170 -330
- package/src/claude/hooks/__tests__/spec-state-touched.test.js +26 -0
- package/src/claude/hooks/spec-gate.cjs +8 -63
- package/src/claude/hooks/spec-state.cjs +47 -38
- package/src/claude/migration-manifest.json +12 -7
- 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/workflow.md +1 -1
- 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/skills/agent-browser/SKILL.md +1 -1
- 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/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/hooks/lib/spec-receipt.cjs +2 -30
- package/src/codex/hooks/lib/spec-utils.cjs +6 -45
- package/src/codex/hooks/spec-gate.cjs +11 -68
- package/src/codex/hooks/spec-state.cjs +37 -41
- package/src/common/AGENTS.md +4 -10
- 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
|
@@ -40,7 +40,28 @@ try {
|
|
|
40
40
|
const RECEIPT = receiptLoaded.receipt;
|
|
41
41
|
const { projectRoot, runtime } = getHookContext(payload);
|
|
42
42
|
if (runtime.spec?.tollgate === false) process.exit(0);
|
|
43
|
-
const { resolveWorkflowCandidate } = require('./lib/spec-utils.cjs');
|
|
43
|
+
const { findLegacyPackets, resolveWorkflowCandidate } = require('./lib/spec-utils.cjs');
|
|
44
|
+
const sessionId = payload.session_id || payload.sessionId || payload.sessionID || payload.session?.id;
|
|
45
|
+
// A legacy packet (a specs/<x>/ directory without plan.md that the old flow left
|
|
46
|
+
// behind) is no longer read. Say so once per session instead of on every prompt.
|
|
47
|
+
const legacyPackets = findLegacyPackets(projectRoot, runtime);
|
|
48
|
+
if (legacyPackets.length > 0) {
|
|
49
|
+
const noticeFile = sessionId
|
|
50
|
+
? path.join(hookStateDir(projectRoot), `legacy-notice-${crypto.createHash('sha256').update(String(sessionId)).digest('hex').slice(0, 16)}.json`)
|
|
51
|
+
: null;
|
|
52
|
+
let noticed = [];
|
|
53
|
+
if (noticeFile) {
|
|
54
|
+
try { noticed = JSON.parse(fs.readFileSync(noticeFile, 'utf8')); } catch { noticed = []; }
|
|
55
|
+
if (!Array.isArray(noticed)) noticed = [];
|
|
56
|
+
}
|
|
57
|
+
const fresh = legacyPackets.filter((name) => !noticed.includes(name));
|
|
58
|
+
for (const name of fresh) {
|
|
59
|
+
process.stdout.write(`> ⚠️ \`specs/${name}\` is a legacy Specs packet without plan.md; CafeKit no longer reads it. Move ongoing work to a process-first plan.md packet.\n`);
|
|
60
|
+
}
|
|
61
|
+
if (noticeFile && fresh.length > 0) {
|
|
62
|
+
try { atomicWrite(noticeFile, `${JSON.stringify([...noticed, ...fresh].sort())}\n`); } catch { /* repeats the notice */ }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
44
65
|
const explicitFeature = payload.featureName || payload.feature || payload.explicitFeature || null;
|
|
45
66
|
const explicitPath = payload.specPath || payload.spec_path || payload.featurePath || null;
|
|
46
67
|
const resolved = resolveWorkflowCandidate(projectRoot, runtime, explicitFeature, explicitPath);
|
|
@@ -50,7 +71,7 @@ try {
|
|
|
50
71
|
process.exit(0);
|
|
51
72
|
}
|
|
52
73
|
if (resolved.error === 'invalid_specs') {
|
|
53
|
-
process.stdout.write(`> ⚠️ Invalid
|
|
74
|
+
process.stdout.write(`> ⚠️ Invalid workflow packet detected: ${resolved.candidates.join(', ')}. ${resolved.reason}. Fix the packet's plan.md or task files. Tollgate paused.\n`);
|
|
54
75
|
process.exit(0);
|
|
55
76
|
}
|
|
56
77
|
if (resolved.error === 'explicit_not_found' || resolved.error === 'explicit_malformed') {
|
|
@@ -60,18 +81,16 @@ try {
|
|
|
60
81
|
}
|
|
61
82
|
if (resolved.error) process.exit(0);
|
|
62
83
|
const active = resolved;
|
|
63
|
-
const processWorkflow = active.layoutKind === 'process-v3';
|
|
64
84
|
const runtimeContext = POLICY.deriveRuntimeContext({
|
|
65
85
|
projectRoot,
|
|
66
86
|
specsRoot: active.specsDir,
|
|
67
|
-
specFile: active.stateFile
|
|
87
|
+
specFile: active.stateFile,
|
|
68
88
|
featureName: active.featureName,
|
|
69
|
-
runtimeSession:
|
|
89
|
+
runtimeSession: sessionId,
|
|
70
90
|
});
|
|
71
91
|
|
|
72
|
-
const phase = active.phase ||
|
|
73
|
-
const taskRegistry = active.taskRegistry ||
|
|
74
|
-
const flashTasks = POLICY.flashState(taskRegistry);
|
|
92
|
+
const phase = active.phase || 'unknown';
|
|
93
|
+
const taskRegistry = active.taskRegistry || {};
|
|
75
94
|
const tasks = Object.entries(taskRegistry);
|
|
76
95
|
const counts = tasks.reduce((result, [, task]) => {
|
|
77
96
|
const status = task?.status || 'pending';
|
|
@@ -79,13 +98,7 @@ try {
|
|
|
79
98
|
return result;
|
|
80
99
|
}, {});
|
|
81
100
|
const featureDir = path.join(active.specsDir, active.featureName);
|
|
82
|
-
const
|
|
83
|
-
taskPath,
|
|
84
|
-
task?.status || 'pending'
|
|
85
|
-
]));
|
|
86
|
-
const dependencyProof = processWorkflow
|
|
87
|
-
? RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY)
|
|
88
|
-
: {};
|
|
101
|
+
const dependencyProof = RECEIPT.workflowDependencyProofState(featureDir, taskRegistry, runtimeContext, POLICY);
|
|
89
102
|
const taskState = tasks.map(([taskPath, task]) => [
|
|
90
103
|
taskPath,
|
|
91
104
|
task?.status || 'pending',
|
|
@@ -101,12 +114,8 @@ try {
|
|
|
101
114
|
const next = tasks.find(([, task]) => (
|
|
102
115
|
active.queueReady !== false
|
|
103
116
|
&& (task?.status || 'pending') === 'pending'
|
|
104
|
-
&& (task?.dependencies || []).every((dependency) =>
|
|
105
|
-
processWorkflow ? dependencyProof[dependency]?.eligible === true : statuses.get(dependency) === 'done'
|
|
106
|
-
))
|
|
117
|
+
&& (task?.dependencies || []).every((dependency) => dependencyProof[dependency]?.eligible === true)
|
|
107
118
|
));
|
|
108
|
-
const featureReceiptPresent = !processWorkflow
|
|
109
|
-
&& RECEIPT.safeRead(featureDir, 'feature-receipt.md').status === 'ok';
|
|
110
119
|
const stateKey = JSON.stringify({
|
|
111
120
|
project_root: runtimeContext.project_root,
|
|
112
121
|
specs_root: runtimeContext.specs_root,
|
|
@@ -124,14 +133,13 @@ try {
|
|
|
124
133
|
proof_state: proofState,
|
|
125
134
|
done: counts.done || 0,
|
|
126
135
|
total: tasks.length,
|
|
127
|
-
feature_receipt_present: featureReceiptPresent,
|
|
128
136
|
});
|
|
129
137
|
const cache = cacheFile(projectRoot, runtimeContext.runtime_session);
|
|
130
138
|
let previous = '';
|
|
131
139
|
try { previous = fs.readFileSync(cache, 'utf8').trim(); } catch { /* first run */ }
|
|
132
140
|
|
|
133
141
|
if (previous === stateKey) {
|
|
134
|
-
const migration =
|
|
142
|
+
const migration = active.queueReady === false
|
|
135
143
|
? ' Add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.'
|
|
136
144
|
: '';
|
|
137
145
|
process.stdout.write(
|
|
@@ -147,26 +155,14 @@ try {
|
|
|
147
155
|
`- Phase: \`${phase}\` | Tasks: ${counts.done || 0} done / ${tasks.length} total`
|
|
148
156
|
];
|
|
149
157
|
if (next) lines.push(`- Next unblocked: \`${next[0]}\``);
|
|
150
|
-
if (
|
|
151
|
-
lines.push(
|
|
152
|
-
}
|
|
153
|
-
if (processWorkflow) {
|
|
154
|
-
if (active.queueReady === false) {
|
|
155
|
-
lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
|
|
156
|
-
}
|
|
157
|
-
lines.push(
|
|
158
|
-
'- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.',
|
|
159
|
-
`- Workflow source: \`specs/${active.featureName}/plan.md\`; Stop re-checks every done receipt, binding Base/Head to the runtime only while a committed task file no longer matches its committed bytes.`,
|
|
160
|
-
'- Hooks revalidate receipt bytes but never grant approval.'
|
|
161
|
-
);
|
|
162
|
-
} else {
|
|
163
|
-
lines.push(
|
|
164
|
-
'- Sync `spec.json` and task Markdown status only after verified work; task proof belongs in `receipts/<task-basename>.md`.',
|
|
165
|
-
`- Create \`feature-receipt.md\` once after final integration proof${featureReceiptPresent ? ' (present)' : ' (not required before closeout)'}.`,
|
|
166
|
-
`- Validate with \`node .codex/scripts/validate-spec-output.cjs specs/${active.featureName}\`.`,
|
|
167
|
-
'- Hooks revalidate receipt bytes but never grant approval.'
|
|
168
|
-
);
|
|
158
|
+
if (active.queueReady === false) {
|
|
159
|
+
lines.push('- Migration required: add `Specs-Contract: process-first-ready-v1` after the plan title before tasks can enter Next.');
|
|
169
160
|
}
|
|
161
|
+
lines.push(
|
|
162
|
+
'- Sync each flat task `Status:` only after verified work; task proof belongs in that task\'s inline `## Receipt`.',
|
|
163
|
+
`- Workflow source: \`specs/${active.featureName}/plan.md\`; Stop re-checks every done receipt, binding Base/Head to the runtime only while a committed task file no longer matches its committed bytes.`,
|
|
164
|
+
'- Hooks revalidate receipt bytes but never grant approval.'
|
|
165
|
+
);
|
|
170
166
|
process.stdout.write(`${lines.join('\n')}\n`);
|
|
171
167
|
} catch (error) {
|
|
172
168
|
logCrash('spec-state', error);
|
package/src/common/AGENTS.md
CHANGED
|
@@ -33,17 +33,11 @@ Do the work yourself when it takes a handful of tool calls. Delegate genuinely i
|
|
|
33
33
|
- Runtime-specific instructions live in that runtime's own managed block, not in `CORE`.
|
|
34
34
|
- In a combined install, consume `CORE` plus your native block only. Ignore managed blocks not owned by your runtime. If ownership is unclear, treat the file as `CORE`-only (fail-safe).
|
|
35
35
|
|
|
36
|
-
##
|
|
36
|
+
## Project notes
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<!-- List files, directories, generated artifacts, or secrets that tasks must leave unchanged. -->
|
|
43
|
-
|
|
44
|
-
## Slow or expensive
|
|
45
|
-
|
|
46
|
-
<!-- Note commands, environments, or operations that need explicit planning before running. -->
|
|
38
|
+
Write project-specific commands, files tasks must leave unchanged, and slow or
|
|
39
|
+
expensive operations after the `CAFEKIT CORE END` marker. Everything between the
|
|
40
|
+
CafeKit markers is replaced on every install.
|
|
47
41
|
|
|
48
42
|
## Language Consistency <!-- cafekit:lang -->
|
|
49
43
|
|