@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
|
@@ -182,12 +182,7 @@ const V3_SPECS_BUNDLE = [
|
|
|
182
182
|
'SKILL.md',
|
|
183
183
|
'references/review.md',
|
|
184
184
|
'references/templates.md',
|
|
185
|
-
'templates/
|
|
186
|
-
'templates/requirements-init.md',
|
|
187
|
-
'templates/requirements.md',
|
|
188
|
-
'templates/research.md',
|
|
189
|
-
'templates/spec-state.json',
|
|
190
|
-
'templates/task.md'
|
|
185
|
+
'templates/research.md'
|
|
191
186
|
];
|
|
192
187
|
const OBSOLETE_SPECS_FILES = [
|
|
193
188
|
'references/archive-workflow.md',
|
|
@@ -272,64 +267,6 @@ function replaceGeneratedTomlString(content, key, value) {
|
|
|
272
267
|
return content.replace(pattern, `${key} = ${JSON.stringify(value)}`);
|
|
273
268
|
}
|
|
274
269
|
|
|
275
|
-
function renderCanonicalVerificationExample(template) {
|
|
276
|
-
const values = new Map([
|
|
277
|
-
['SUBJECT_REQ', '1'],
|
|
278
|
-
['X', '1'],
|
|
279
|
-
['PROOF_REQ', '1'],
|
|
280
|
-
['Y', '2'],
|
|
281
|
-
['exact command', 'node --test test/installed.test.js'],
|
|
282
|
-
['exact anchored target', 'src/installed.js#entry'],
|
|
283
|
-
['exact/repository/entrypoint', 'src/installed.js'],
|
|
284
|
-
['observable result', 'the subject behavior and verifier proof both pass'],
|
|
285
|
-
['concrete observable result and proof', 'the subject behavior and verifier proof both pass'],
|
|
286
|
-
['concrete rejected or recovery case', 'invalid input remains rejected and observable'],
|
|
287
|
-
['real entrypoint/caller and grounded anchor expectation', 'the installed entrypoint reaches A-D-01'],
|
|
288
|
-
]);
|
|
289
|
-
return template.replace(/\{\{([^}]+)\}\}/g, (placeholder, name) => (
|
|
290
|
-
values.has(name) ? values.get(name) : placeholder
|
|
291
|
-
));
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function assertInstalledVerificationModel(grounderPath, designTemplate) {
|
|
295
|
-
const { parseVerificationDefinitions } = require(grounderPath);
|
|
296
|
-
assert.equal(typeof parseVerificationDefinitions, 'function');
|
|
297
|
-
const concreteDesign = renderCanonicalVerificationExample(designTemplate);
|
|
298
|
-
const errors = [];
|
|
299
|
-
const definitions = parseVerificationDefinitions(concreteDesign, errors);
|
|
300
|
-
assert.deepEqual(errors, []);
|
|
301
|
-
assert.equal(definitions.size, 1);
|
|
302
|
-
const definition = definitions.get('V1');
|
|
303
|
-
assert.ok(definition);
|
|
304
|
-
assert.deepEqual(definition.subject_criteria, ['R1.1']);
|
|
305
|
-
assert.deepEqual(definition.proof_criteria, []);
|
|
306
|
-
assert.equal(definition.proof_owner, null);
|
|
307
|
-
assert.equal(definition.evidence_anchor, null);
|
|
308
|
-
assert.deepEqual(definition.decision_refs, ['D1', 'I1', 'C1']);
|
|
309
|
-
for (const field of [
|
|
310
|
-
'subject_criteria', 'subject_owner', 'decision_refs', 'method', 'expected',
|
|
311
|
-
'negative', 'reachability'
|
|
312
|
-
]) {
|
|
313
|
-
const value = definition[field];
|
|
314
|
-
assert.ok(
|
|
315
|
-
Array.isArray(value)
|
|
316
|
-
? value.length > 0
|
|
317
|
-
: (typeof value === 'string' ? value.trim() !== '' : value && Object.keys(value).length > 0)
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
for (const mutation of [
|
|
321
|
-
concreteDesign.replace('- **V1**:', '### V1 —'),
|
|
322
|
-
concreteDesign.replace('- **V1**:', '| V1 |'),
|
|
323
|
-
concreteDesign.replace('; Expected ', '\nExpected '),
|
|
324
|
-
concreteDesign.replace('Decision refs ', 'Decisions '),
|
|
325
|
-
]) {
|
|
326
|
-
const mutationErrors = [];
|
|
327
|
-
const mutated = parseVerificationDefinitions(mutation, mutationErrors);
|
|
328
|
-
assert.ok(mutationErrors.length > 0);
|
|
329
|
-
assert.equal(mutated.has('V1'), false);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
270
|
function markdownSection(content, heading) {
|
|
334
271
|
const lines = String(content).split('\n');
|
|
335
272
|
const start = lines.findIndex((line) => line.trim() === `## ${heading}`);
|
|
@@ -2160,22 +2097,12 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2160
2097
|
'.codex/rules/state-sync.md',
|
|
2161
2098
|
'.codex/rules/review-audit-self-decision.md',
|
|
2162
2099
|
'.codex/rules/process-management.md',
|
|
2163
|
-
'.codex/scripts/spec-ground.cjs',
|
|
2164
|
-
'.codex/scripts/validate-spec-output.cjs',
|
|
2165
2100
|
'.agents/.gitignore',
|
|
2166
2101
|
...V3_SPECS_BUNDLE.map((file) => `.agents/skills/specs/${file}`)
|
|
2167
2102
|
]) {
|
|
2168
2103
|
assert.equal(fs.existsSync(path.join(root, relative)), true, `missing ${relative}`);
|
|
2169
2104
|
}
|
|
2170
2105
|
|
|
2171
|
-
const installedDesign = fs.readFileSync(
|
|
2172
|
-
path.join(root, '.agents/skills/specs/templates/design.md'), 'utf8'
|
|
2173
|
-
);
|
|
2174
|
-
assert.equal((installedDesign.match(/^## Verification Definitions$/gm) || []).length, 1);
|
|
2175
|
-
assertInstalledVerificationModel(
|
|
2176
|
-
path.join(root, '.codex/scripts/spec-ground.cjs'),
|
|
2177
|
-
installedDesign
|
|
2178
|
-
);
|
|
2179
2106
|
const installedSpecsRoot = path.join(root, '.agents/skills/specs');
|
|
2180
2107
|
assert.throws(
|
|
2181
2108
|
() => installedAuthoringProjectionIssues(root, '.agents/skills/specs'),
|
|
@@ -2191,22 +2118,6 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2191
2118
|
);
|
|
2192
2119
|
assertInstalledAuthoringProjection(root, installedSpecsRoot);
|
|
2193
2120
|
|
|
2194
|
-
const installedTask = fs.readFileSync(
|
|
2195
|
-
path.join(root, '.agents/skills/specs/templates/task.md'), 'utf8'
|
|
2196
|
-
);
|
|
2197
|
-
assert.deepEqual(
|
|
2198
|
-
[...installedTask.matchAll(/^## (.+)$/gm)].map((match) => match[1]),
|
|
2199
|
-
['Outcome', 'Scope', 'Anchors and Ownership', 'Changes', 'Acceptance', 'Dependencies', 'Verification Plan']
|
|
2200
|
-
);
|
|
2201
|
-
assert.match(installedTask, /^- \*\*Task role:\*\*/m);
|
|
2202
|
-
|
|
2203
|
-
const installedState = JSON.parse(fs.readFileSync(
|
|
2204
|
-
path.join(root, '.agents/skills/specs/templates/spec-state.json'), 'utf8'
|
|
2205
|
-
));
|
|
2206
|
-
assert.deepEqual(Object.keys(installedState.workflow_policy).sort(), [
|
|
2207
|
-
'assurance_level', 'classified_minimum', 'planning_depth', 'risks', 'version'
|
|
2208
|
-
]);
|
|
2209
|
-
|
|
2210
2121
|
const agentsGitignore = fs.readFileSync(
|
|
2211
2122
|
path.join(root, '.agents', '.gitignore'),
|
|
2212
2123
|
'utf8'
|
|
@@ -2217,7 +2128,6 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2217
2128
|
|
|
2218
2129
|
if (process.platform !== 'win32') {
|
|
2219
2130
|
for (const [sourceRelative, installedRelative] of [
|
|
2220
|
-
['src/claude/scripts/validate-spec-output.cjs', '.codex/scripts/validate-spec-output.cjs'],
|
|
2221
2131
|
['src/claude/skills/chrome-devtools/scripts/install.sh', '.agents/skills/chrome-devtools/scripts/install.sh'],
|
|
2222
2132
|
['src/claude/skills/ai-multimodal/scripts/check_setup.py', '.agents/skills/ai-multimodal/scripts/check_setup.py']
|
|
2223
2133
|
]) {
|
|
@@ -2338,7 +2248,7 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2338
2248
|
const questionSkill = path.join(root, '.agents', 'skills', 'ask', 'SKILL.md');
|
|
2339
2249
|
fs.appendFileSync(questionSkill, '\nUSER-CODEX-SENTINEL\n');
|
|
2340
2250
|
// Fresh installs are exact. Refresh/upgrade intentionally documents the
|
|
2341
|
-
//
|
|
2251
|
+
// A skill file the manifest lists as obsolete is removed on refresh; edited skills stay.
|
|
2342
2252
|
const obsoleteSpecsRule = path.join(
|
|
2343
2253
|
root, '.agents', 'skills', 'specs', 'rules', 'design-principles.md'
|
|
2344
2254
|
);
|
|
@@ -2351,14 +2261,15 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2351
2261
|
assert.match(fs.readFileSync(questionSkill, 'utf8'), /USER-CODEX-SENTINEL/);
|
|
2352
2262
|
assert.equal(
|
|
2353
2263
|
fs.existsSync(obsoleteSpecsRule),
|
|
2354
|
-
|
|
2355
|
-
'
|
|
2264
|
+
false,
|
|
2265
|
+
'Codex refresh removes obsolete skill files'
|
|
2356
2266
|
);
|
|
2357
2267
|
|
|
2358
2268
|
const metadataPath = path.join(root, '.codex', 'cafekit.json');
|
|
2359
2269
|
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
2360
2270
|
metadata.version = '0.14.1';
|
|
2361
2271
|
fs.writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`);
|
|
2272
|
+
fs.writeFileSync(obsoleteSpecsRule, 'LEGACY-CODEX-ORPHAN\n');
|
|
2362
2273
|
|
|
2363
2274
|
const upgrade = install(root);
|
|
2364
2275
|
assert.equal(upgrade.status, 0, `${upgrade.stdout}\n${upgrade.stderr}`);
|
|
@@ -2366,8 +2277,8 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2366
2277
|
assert.match(fs.readFileSync(questionSkill, 'utf8'), /USER-CODEX-SENTINEL/);
|
|
2367
2278
|
assert.equal(
|
|
2368
2279
|
fs.existsSync(obsoleteSpecsRule),
|
|
2369
|
-
|
|
2370
|
-
'
|
|
2280
|
+
false,
|
|
2281
|
+
'Codex upgrade removes obsolete skill files'
|
|
2371
2282
|
);
|
|
2372
2283
|
assert.ok(fs.readFileSync(path.join(root, 'AGENTS.md'), 'utf8').startsWith(userInstructions));
|
|
2373
2284
|
|
|
@@ -3136,8 +3047,6 @@ test('Codex install on top of existing Claude installation preserves content and
|
|
|
3136
3047
|
assert.equal(fs.existsSync(path.join(root, '.codex', 'runtime.json')), true, '.codex/runtime.json should exist');
|
|
3137
3048
|
assert.equal(fs.existsSync(path.join(root, '.codex', 'hooks', 'privacy-block.cjs')), true, '.codex/hooks/privacy-block.cjs should exist');
|
|
3138
3049
|
assert.equal(fs.existsSync(path.join(root, '.codex', 'rules', 'workflow.md')), true, '.codex/rules/workflow.md should exist');
|
|
3139
|
-
assert.equal(fs.existsSync(path.join(root, '.codex', 'scripts', 'spec-ground.cjs')), true, '.codex/scripts/spec-ground.cjs should exist');
|
|
3140
|
-
assert.equal(fs.existsSync(path.join(root, '.codex', 'scripts', 'validate-spec-output.cjs')), true, '.codex/scripts/validate-spec-output.cjs should exist');
|
|
3141
3050
|
assert.equal(fs.existsSync(path.join(root, '.agents', '.gitignore')), true, '.agents/.gitignore should exist');
|
|
3142
3051
|
assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', 'specs', 'SKILL.md')), true, '.agents/skills/specs/SKILL.md should exist');
|
|
3143
3052
|
|
|
@@ -3170,23 +3079,54 @@ test('Codex installed code_auditor carries no Strict attestation marker', () =>
|
|
|
3170
3079
|
});
|
|
3171
3080
|
});
|
|
3172
3081
|
|
|
3173
|
-
test('
|
|
3082
|
+
test('reinstall removes obsolete scripts and skill files from Codex and omp installs', () => {
|
|
3174
3083
|
inTempProject((root) => {
|
|
3175
|
-
const
|
|
3176
|
-
assert.equal(
|
|
3177
|
-
const
|
|
3178
|
-
const
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
fs.
|
|
3183
|
-
const
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
fs.
|
|
3189
|
-
|
|
3084
|
+
const first = installPlatforms(root, ['codex', 'omp']);
|
|
3085
|
+
assert.equal(first.status, 0, `${first.stdout}\n${first.stderr}`);
|
|
3086
|
+
const retired = ['change-firewall.cjs', 'spec-final-state.cjs'];
|
|
3087
|
+
for (const runtime of ['.codex', '.omp']) {
|
|
3088
|
+
for (const name of retired) fs.writeFileSync(path.join(root, runtime, 'scripts', name), 'legacy\n');
|
|
3089
|
+
}
|
|
3090
|
+
const retiredSkillFiles = ['code-review/references/verification-gate.md', 'specs/references/archive-workflow.md'];
|
|
3091
|
+
for (const rel of retiredSkillFiles) fs.writeFileSync(path.join(root, '.agents', 'skills', rel), 'legacy\n');
|
|
3092
|
+
const again = installPlatforms(root, ['codex', 'omp'], ['--force-overwrite']);
|
|
3093
|
+
assert.equal(again.status, 0, `${again.stdout}\n${again.stderr}`);
|
|
3094
|
+
for (const rel of retiredSkillFiles) {
|
|
3095
|
+
assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', rel)), false, `.agents/skills/${rel} must be removed`);
|
|
3096
|
+
}
|
|
3097
|
+
assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', 'code-review', 'SKILL.md')), true, 'the code-review skill stays');
|
|
3098
|
+
for (const runtime of ['.codex', '.omp']) {
|
|
3099
|
+
for (const name of retired) {
|
|
3100
|
+
assert.equal(fs.existsSync(path.join(root, runtime, 'scripts', name)), false, `${runtime}/scripts/${name} must be removed`);
|
|
3101
|
+
}
|
|
3102
|
+
assert.equal(fs.existsSync(path.join(root, runtime, 'scripts', 'spec-resolver.cjs')), true, `${runtime} keeps the resolver`);
|
|
3103
|
+
}
|
|
3104
|
+
});
|
|
3105
|
+
});
|
|
3106
|
+
|
|
3107
|
+
test('reinstall removes the retired spec.json templates from Claude and Codex but a dry run keeps them', () => {
|
|
3108
|
+
inTempProject((root) => {
|
|
3109
|
+
const first = installPlatforms(root, ['claude', 'codex']);
|
|
3110
|
+
assert.equal(first.status, 0, `${first.stdout}\n${first.stderr}`);
|
|
3111
|
+
const templateDirs = ['.claude/skills/specs/templates', '.agents/skills/specs/templates'];
|
|
3112
|
+
const retired = ['design.md', 'task.md', 'requirements.md', 'requirements-init.md', 'spec-state.json'];
|
|
3113
|
+
for (const dir of templateDirs) {
|
|
3114
|
+
for (const name of retired) fs.writeFileSync(path.join(root, dir, name), 'legacy\n');
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
const dry = installPlatforms(root, ['claude', 'codex'], ['--force-overwrite', '--dry-run']);
|
|
3118
|
+
assert.equal(dry.status, 0, `${dry.stdout}\n${dry.stderr}`);
|
|
3119
|
+
for (const dir of templateDirs) {
|
|
3120
|
+
for (const name of retired) {
|
|
3121
|
+
assert.equal(fs.existsSync(path.join(root, dir, name)), true, `dry run removed ${dir}/${name}`);
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
const again = installPlatforms(root, ['claude', 'codex'], ['--force-overwrite']);
|
|
3126
|
+
assert.equal(again.status, 0, `${again.stdout}\n${again.stderr}`);
|
|
3127
|
+
for (const dir of templateDirs) {
|
|
3128
|
+
assert.deepEqual(fs.readdirSync(path.join(root, dir)), ['research.md'], `${dir} keeps only research.md`);
|
|
3129
|
+
}
|
|
3190
3130
|
});
|
|
3191
3131
|
});
|
|
3192
3132
|
|