@haposoft/cafekit 0.16.7 → 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 +14 -22
- package/bin/__tests__/codex-hooks-ownership.test.js +2 -2
- package/bin/__tests__/codex-hooks.test.js +169 -272
- package/bin/__tests__/codex-native.test.js +100 -202
- package/bin/__tests__/develop-contract.test.js +122 -1413
- package/bin/__tests__/docs-sync-on-demand.test.js +93 -0
- package/bin/__tests__/grok-envelope.test.js +0 -56
- package/bin/__tests__/hook-payload.test.js +4 -6
- package/bin/__tests__/legacy-authority-decoupled.test.js +154 -0
- package/bin/__tests__/legacy-hooks-retired.test.js +221 -0
- package/bin/__tests__/omp-bridge.test.js +20 -17
- package/bin/__tests__/omp-hooks.test.js +0 -19
- package/bin/__tests__/optional-skill-inventory.test.js +112 -4
- package/bin/__tests__/orca-session.test.js +0 -2
- package/bin/__tests__/package-inventory.test.js +90 -925
- package/bin/__tests__/runtime-dir.test.js +0 -3
- package/bin/__tests__/runtime-schema.test.js +3 -2
- package/bin/__tests__/skill-routing-source.test.js +27 -15
- package/bin/__tests__/spec-narrowing.test.js +30 -161
- package/bin/__tests__/specs-v2-execution-closeout.test.js +0 -437
- package/bin/__tests__/test-runtime-dependency-closure.cjs +1 -2
- package/bin/__tests__/ui-ux-skill.test.js +101 -0
- package/bin/__tests__/usage-hook-retired.test.js +114 -0
- package/bin/__tests__/validator-grounding.test.js +18 -2949
- package/bin/lib/managed-writer.js +2 -3
- package/bin/phases/codex-runtime.js +27 -0
- package/bin/phases/copy-payload.js +13 -28
- package/bin/phases/omp-runtime.js +25 -0
- package/package.json +2 -3
- package/src/claude/CLAUDE.md +3 -10
- package/src/claude/agents/brainstormer.md +7 -3
- package/src/claude/agents/code-auditor.md +44 -56
- package/src/claude/agents/debugger.md +8 -88
- package/src/claude/agents/deployer.md +3 -5
- package/src/claude/agents/docs-keeper.md +6 -14
- package/src/claude/agents/git-ops.md +2 -4
- package/src/claude/agents/implementer.md +12 -16
- package/src/claude/agents/inspector.md +4 -3
- package/src/claude/agents/project-manager.md +9 -17
- package/src/claude/agents/researcher.md +9 -3
- package/src/claude/agents/spec-maker.md +15 -15
- package/src/claude/agents/test-runner.md +8 -11
- package/src/claude/agents/ui-ux-designer.md +0 -1
- package/src/claude/hooks/__tests__/fixtures/statusline-default.golden +1 -1
- package/src/claude/hooks/__tests__/spec-gate.test.js +244 -333
- package/src/claude/hooks/__tests__/spec-state-touched.test.js +160 -0
- package/src/claude/hooks/__tests__/state.test.js +68 -0
- package/src/claude/hooks/__tests__/statusline.test.js +140 -11
- package/src/claude/hooks/agent.cjs +2 -1
- package/src/claude/hooks/lib/hook-payload.cjs +2 -2
- package/src/claude/hooks/rules.cjs +2 -1
- package/src/claude/hooks/session.cjs +0 -1
- package/src/claude/hooks/spec-gate.cjs +17 -83
- package/src/claude/hooks/spec-state.cjs +142 -39
- package/src/claude/hooks/state.cjs +21 -2
- package/src/claude/migration-manifest.json +42 -22
- 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 +2 -3
- package/src/claude/rules/hook-protocols.md +8 -15
- package/src/claude/rules/manage-docs.md +9 -23
- package/src/claude/rules/orchestrator.md +3 -4
- package/src/claude/rules/review-audit-self-decision.md +3 -3
- package/src/claude/rules/skill-domain-routing.md +1 -3
- package/src/claude/rules/skill-workflow-routing.md +4 -5
- package/src/claude/rules/state-sync.md +3 -12
- package/src/claude/rules/workflow.md +11 -19
- package/src/claude/runtime.schema.json +5 -3
- package/src/claude/scripts/generate-skill-catalog.cjs +7 -6
- package/src/claude/scripts/provenance.cjs +23 -5
- package/src/claude/scripts/spec-receipt.cjs +24 -121
- package/src/claude/scripts/spec-resolver.cjs +41 -458
- package/src/claude/scripts/workflow-policy.cjs +3 -1801
- package/src/claude/settings/settings.json +1 -32
- package/src/claude/skills/agent-browser/SKILL.md +1 -1
- package/src/claude/skills/{question → ask}/SKILL.md +9 -75
- package/src/claude/skills/brainstorm/SKILL.md +43 -131
- package/src/claude/skills/chrome-devtools/SKILL.md +14 -31
- package/src/claude/skills/code-review/SKILL.md +29 -81
- package/src/claude/skills/code-review/references/spec-compliance-review.md +4 -8
- package/src/claude/skills/debug/SKILL.md +29 -149
- package/src/claude/skills/develop/SKILL.md +26 -83
- package/src/claude/skills/develop/references/parallel-waves.md +0 -8
- package/src/claude/skills/develop/references/quality-gate.md +15 -13
- package/src/claude/skills/develop/references/subagent-patterns.md +0 -6
- package/src/claude/skills/docs/SKILL.md +2 -2
- package/src/claude/skills/docs/references/update-workflow.md +1 -1
- package/src/claude/skills/fix/SKILL.md +153 -0
- package/src/claude/skills/{hotfix → fix}/references/diagnosis-protocol.md +2 -2
- package/src/claude/skills/{hotfix → fix}/references/parallel-patterns.md +2 -2
- package/src/claude/skills/{hotfix → fix}/references/prevention-gate.md +3 -3
- package/src/claude/skills/{hotfix → fix}/references/review-cycle.md +1 -1
- package/src/claude/skills/git/SKILL.md +48 -9
- package/src/claude/skills/git/references/commit-protocols.md +35 -16
- package/src/claude/skills/git/references/worktree-blueprint.md +42 -6
- package/src/claude/skills/orca/SKILL.md +9 -8
- package/src/claude/skills/research/SKILL.md +17 -46
- package/src/claude/skills/scout/SKILL.md +61 -0
- package/src/claude/skills/{inspect → scout}/references/internal-inspection.md +26 -10
- package/src/claude/skills/specs/SKILL.md +22 -29
- package/src/claude/skills/specs/references/review.md +8 -6
- package/src/claude/skills/specs/references/templates.md +34 -41
- package/src/claude/skills/sync/SKILL.md +16 -45
- package/src/claude/skills/sync/references/rebind-and-audit.md +59 -0
- package/src/claude/skills/sync/references/sync-protocols.md +4 -13
- package/src/claude/skills/test/SKILL.md +39 -104
- package/src/claude/skills/test/references/execution-strategy.md +93 -21
- package/src/claude/skills/test/references/failure-triage.md +1 -1
- package/src/claude/skills/ui-ux/LICENSE +21 -0
- package/src/claude/skills/ui-ux/SKILL.md +497 -0
- package/src/claude/skills/ui-ux/references/brand-tokens.md +90 -0
- package/src/claude/skills/ui-ux/references/budgets.md +113 -0
- package/src/claude/skills/ui-ux/references/checklist.md +271 -0
- package/src/claude/skills/ui-ux/references/components/accordion.md +246 -0
- package/src/claude/skills/ui-ux/references/components/avatar.md +153 -0
- package/src/claude/skills/ui-ux/references/components/banner.md +43 -0
- package/src/claude/skills/ui-ux/references/components/breadcrumb.md +201 -0
- package/src/claude/skills/ui-ux/references/components/button.md +142 -0
- package/src/claude/skills/ui-ux/references/components/card.md +113 -0
- package/src/claude/skills/ui-ux/references/components/charts.md +376 -0
- package/src/claude/skills/ui-ux/references/components/chat.md +132 -0
- package/src/claude/skills/ui-ux/references/components/choice-controls.md +369 -0
- package/src/claude/skills/ui-ux/references/components/comment-thread.md +17 -0
- package/src/claude/skills/ui-ux/references/components/description-list.md +116 -0
- package/src/claude/skills/ui-ux/references/components/empty-state.md +98 -0
- package/src/claude/skills/ui-ux/references/components/file-upload.md +107 -0
- package/src/claude/skills/ui-ux/references/components/inline-edit.md +128 -0
- package/src/claude/skills/ui-ux/references/components/input.md +161 -0
- package/src/claude/skills/ui-ux/references/components/list-row.md +56 -0
- package/src/claude/skills/ui-ux/references/components/loading.md +198 -0
- package/src/claude/skills/ui-ux/references/components/logo.md +147 -0
- package/src/claude/skills/ui-ux/references/components/otp-input.md +43 -0
- package/src/claude/skills/ui-ux/references/components/quantity-input.md +100 -0
- package/src/claude/skills/ui-ux/references/components/range-slider.md +16 -0
- package/src/claude/skills/ui-ux/references/components/small-controls.md +340 -0
- package/src/claude/skills/ui-ux/references/components/sortable-header.md +86 -0
- package/src/claude/skills/ui-ux/references/components/tag-input.md +14 -0
- package/src/claude/skills/ui-ux/references/components/timeline.md +38 -0
- package/src/claude/skills/ui-ux/references/components/tree.md +30 -0
- package/src/claude/skills/ui-ux/references/design-process.md +650 -0
- package/src/claude/skills/ui-ux/references/layouts/app-kanban.html +303 -0
- package/src/claude/skills/ui-ux/references/layouts/app.md +1369 -0
- package/src/claude/skills/ui-ux/references/layouts/form.md +430 -0
- package/src/claude/skills/ui-ux/references/layouts/overlay.md +552 -0
- package/src/claude/skills/ui-ux/references/layouts/pricing.md +204 -0
- package/src/claude/skills/ui-ux/references/locked-rules.md +35 -0
- package/src/claude/skills/ui-ux/references/principles.md +408 -0
- package/src/claude/skills/ui-ux/references/refactor.md +245 -0
- package/src/claude/skills/ui-ux/references/responsive.md +195 -0
- package/src/claude/skills/ui-ux/references/review.md +528 -0
- package/src/claude/skills/ui-ux/references/rules-color.md +623 -0
- package/src/claude/skills/ui-ux/references/rules-form.md +235 -0
- package/src/claude/skills/ui-ux/references/rules-state.md +680 -0
- package/src/claude/skills/ui-ux/references/rules-type.md +369 -0
- package/src/claude/skills/ui-ux/references/styles.md +311 -0
- package/src/claude/skills/ui-ux/references/system.md +219 -0
- package/src/claude/skills/ui-ux/references/tailwind-v4-traps.md +237 -0
- package/src/claude/skills/ui-ux/references/tokens.css +362 -0
- package/src/claude/skills/ui-ux/scripts/lint-skill.mjs +216 -0
- package/src/claude/skills/ui-ux/scripts/package.json +9 -0
- package/src/claude/skills/ui-ux/scripts/probe.mjs +4447 -0
- package/src/claude/skills/ui-ux-pro-max/SKILL.md +25 -80
- package/src/claude/skills/web-testing/SKILL.md +2 -20
- package/src/claude/status.cjs +149 -144
- package/src/codex/AGENTS.md +8 -13
- package/src/codex/hooks/agent.cjs +2 -1
- package/src/codex/hooks/lib/spec-receipt.cjs +4 -32
- package/src/codex/hooks/lib/spec-utils.cjs +6 -52
- package/src/codex/hooks/rules.cjs +2 -1
- package/src/codex/hooks/session.cjs +0 -2
- package/src/codex/hooks/spec-gate.cjs +13 -81
- package/src/codex/hooks/spec-state.cjs +37 -41
- package/src/codex/hooks.json +0 -20
- package/src/codex/rules/state-sync.md +3 -12
- package/src/common/AGENTS.md +6 -12
- package/src/omp/extensions/cafekit-bridge.mjs +6 -6
- 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/__tests__/completion-authority.test.js +0 -990
- package/src/claude/hooks/__tests__/semantic-review-authority.test.js +0 -259
- package/src/claude/hooks/completion-authority-check.cjs +0 -56
- package/src/claude/hooks/completion-authority-state.cjs +0 -527
- package/src/claude/hooks/completion-authority.cjs +0 -163
- package/src/claude/hooks/lib/context.cjs +0 -616
- package/src/claude/hooks/lib/detect.cjs +0 -474
- package/src/claude/hooks/semantic-review-authority.cjs +0 -154
- package/src/claude/hooks/task-scaffold-guard.cjs +0 -114
- package/src/claude/hooks/usage.cjs +0 -197
- 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 -3941
- package/src/claude/skills/code-review/references/verification-gate.md +0 -46
- package/src/claude/skills/delegate/SKILL.md +0 -124
- package/src/claude/skills/delegate/references/codex-delegation.md +0 -71
- package/src/claude/skills/delegate/references/grok-delegation.md +0 -84
- package/src/claude/skills/hotfix/SKILL.md +0 -289
- package/src/claude/skills/inspect/SKILL.md +0 -142
- package/src/claude/skills/loop/SKILL.md +0 -114
- package/src/claude/skills/loop/references/bounded-loop-protocol.md +0 -104
- package/src/claude/skills/loop/references/metric-and-guard-contract.md +0 -76
- package/src/claude/skills/route/SKILL.md +0 -94
- package/src/claude/skills/route/references/agent-timing.md +0 -46
- package/src/claude/skills/route/references/chaining-patterns.md +0 -53
- package/src/claude/skills/route/references/task-taxonomy.md +0 -48
- 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/hooks/completion-authority-check.cjs +0 -67
- package/src/codex/hooks/completion-authority-state.cjs +0 -527
- package/src/codex/hooks/completion-authority.cjs +0 -109
- package/src/codex/hooks/semantic-review-authority.cjs +0 -130
- package/src/codex/hooks/task-scaffold-guard.cjs +0 -63
- /package/src/claude/skills/{question → ask}/templates/question.md +0 -0
- /package/src/claude/skills/{hotfix → fix}/references/escalation-tactics.md +0 -0
- /package/src/claude/skills/{hotfix → fix}/references/workflow-specialized.md +0 -0
|
@@ -117,25 +117,6 @@ test('an unevaluable access denies rather than allows', () => {
|
|
|
117
117
|
}
|
|
118
118
|
});
|
|
119
119
|
|
|
120
|
-
test('a write to a scaffolded task path is guarded under omp lowercase names too', () => {
|
|
121
|
-
// The guard is no longer an overlay file, so this is a behaviour case on the tree an
|
|
122
|
-
// install produces: omp sends `write`, and the shared reader has to make it reach the
|
|
123
|
-
// rule that was authored against Claude's `Write`.
|
|
124
|
-
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'cafekit-omp-guard-'));
|
|
125
|
-
try {
|
|
126
|
-
const target = path.join(root, 'specs', 'demo', 'tasks', 'task-R0-01-x.md');
|
|
127
|
-
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
128
|
-
fs.cpSync(path.join(PACKAGE_ROOT, 'src/claude/scripts'), path.join(INSTALLED_ROOT, '.omp', 'scripts'),
|
|
129
|
-
{ recursive: true, force: true });
|
|
130
|
-
const r = verdict(path.join(INSTALLED, 'task-scaffold-guard.cjs'),
|
|
131
|
-
{ tool_name: 'write', tool_input: { file_path: target }, cwd: root });
|
|
132
|
-
assert.equal(r.code, 2, "omp sends `write`; an exact 'Write' comparison would skip the guard entirely");
|
|
133
|
-
assert.equal(r.decision, 'deny');
|
|
134
|
-
} finally {
|
|
135
|
-
fs.rmSync(root, { recursive: true, force: true });
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
120
|
/** Every file under a directory, relative and sorted. */
|
|
140
121
|
function walk(dir, prefix = '') {
|
|
141
122
|
return fs.readdirSync(dir).flatMap((name) => {
|
|
@@ -50,7 +50,7 @@ function silentUi() {
|
|
|
50
50
|
|
|
51
51
|
test('manifest separates core, optional documents, and retired skills', () => {
|
|
52
52
|
const manifest = loadClaudeMigrationManifest();
|
|
53
|
-
assert.equal(manifest.skills.required.includes('route'),
|
|
53
|
+
assert.equal(manifest.skills.required.includes('route'), false);
|
|
54
54
|
assert.deepEqual(manifest.skills.bundles.documentSkills, [
|
|
55
55
|
'ai-multimodal', 'docs', 'docx', 'pdf', 'pptx', 'xlsx'
|
|
56
56
|
]);
|
|
@@ -59,7 +59,8 @@ test('manifest separates core, optional documents, and retired skills', () => {
|
|
|
59
59
|
}
|
|
60
60
|
assert.deepEqual(manifest.obsolete.skills, [
|
|
61
61
|
'backend-development', 'frontend-development', 'frontend-design',
|
|
62
|
-
'mobile-development', 'devops', 'react-best-practices'
|
|
62
|
+
'mobile-development', 'devops', 'react-best-practices',
|
|
63
|
+
'inspect', 'hotfix', 'question', 'loop', 'route', 'delegate'
|
|
63
64
|
]);
|
|
64
65
|
});
|
|
65
66
|
|
|
@@ -167,7 +168,7 @@ test('fresh combined install defaults optional bundle OFF', () => {
|
|
|
167
168
|
for (const platformKey of ['claude', 'codex']) {
|
|
168
169
|
const platform = PLATFORMS[platformKey];
|
|
169
170
|
assert.equal(fs.existsSync(path.join(platform.skillsDir, 'docs')), false);
|
|
170
|
-
assert.equal(fs.existsSync(path.join(platform.skillsDir, 'route', 'SKILL.md')),
|
|
171
|
+
assert.equal(fs.existsSync(path.join(platform.skillsDir, 'route', 'SKILL.md')), false);
|
|
171
172
|
const metadata = JSON.parse(fs.readFileSync(path.join(platform.folder, 'cafekit.json'), 'utf8'));
|
|
172
173
|
assert.equal(metadata.schemaVersion, 2);
|
|
173
174
|
assert.equal(metadata.documentSkills.enabled, false);
|
|
@@ -193,7 +194,7 @@ test('explicit opt-in installs all six optional skills on both runtimes', () =>
|
|
|
193
194
|
], { cwd: root, encoding: 'utf8' });
|
|
194
195
|
assert.equal(catalog.status, 0, catalog.stderr);
|
|
195
196
|
const catalogData = JSON.parse(catalog.stdout);
|
|
196
|
-
assert.equal(catalogData.skills.some((skill) => skill.public_id === 'cf:route'),
|
|
197
|
+
assert.equal(catalogData.skills.some((skill) => skill.public_id === 'cf:route'), false);
|
|
197
198
|
assert.equal(catalogData.skills.some((skill) => skill.public_id === 'cf:docs'), true);
|
|
198
199
|
const metadata = JSON.parse(fs.readFileSync(path.join(platform.folder, 'cafekit.json'), 'utf8'));
|
|
199
200
|
assert.deepEqual(metadata.documentSkills, {
|
|
@@ -247,3 +248,110 @@ test('modified retired skill is preserved but excluded from automatic routing',
|
|
|
247
248
|
item.directory === 'backend-development' && item.code === 'retired_skill'));
|
|
248
249
|
});
|
|
249
250
|
});
|
|
251
|
+
|
|
252
|
+
for (const platformKey of ['claude', 'codex']) {
|
|
253
|
+
test(`${platformKey} upgrade retires the inspect, hotfix and question directories`, () => {
|
|
254
|
+
withTempProject((root) => {
|
|
255
|
+
const platform = PLATFORMS[platformKey];
|
|
256
|
+
const recordRoot = platform.ownership?.recordRoot || platform.folder;
|
|
257
|
+
const key = (file) => path.relative(recordRoot, file).replace(/\\/g, '/');
|
|
258
|
+
const ownership = { schemaVersion: 1, version: 'old', files: {} };
|
|
259
|
+
for (const old of ['inspect', 'hotfix', 'question']) {
|
|
260
|
+
const file = path.join(platform.skillsDir, old, 'SKILL.md');
|
|
261
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
262
|
+
fs.writeFileSync(file, `pristine ${old}\n`);
|
|
263
|
+
ownership.files[key(file)] = { sha256: manifestLib.hashFile(file), version: 'old' };
|
|
264
|
+
}
|
|
265
|
+
const ctx = {
|
|
266
|
+
manifest: loadClaudeMigrationManifest(),
|
|
267
|
+
documentSkills: { [platformKey]: { enabled: true, selectionSource: 'cli-opt-in' } },
|
|
268
|
+
ownership: { [platform.folder]: ownership },
|
|
269
|
+
trackers: { [platformKey]: manifestLib.createTracker(platform.folder, 'next', platform.ownership) },
|
|
270
|
+
dryRun: false,
|
|
271
|
+
ui: silentUi(),
|
|
272
|
+
results: { updated: 0, preserved: 0, preservedFiles: [] }
|
|
273
|
+
};
|
|
274
|
+
reconcileSkillInventory(ctx, platformKey);
|
|
275
|
+
for (const old of ['inspect', 'hotfix', 'question']) {
|
|
276
|
+
assert.equal(fs.existsSync(path.join(root, platform.skillsDir, old)), false, old);
|
|
277
|
+
}
|
|
278
|
+
assert.equal(ctx.results.updated, 3);
|
|
279
|
+
|
|
280
|
+
// A user-modified retired copy survives with a warning, and the catalog serves cf:fix from fix/
|
|
281
|
+
// while marking the old directory retired rather than reporting a folder mismatch.
|
|
282
|
+
const edited = path.join(root, platform.skillsDir, 'hotfix', 'SKILL.md');
|
|
283
|
+
fs.mkdirSync(path.dirname(edited), { recursive: true });
|
|
284
|
+
fs.writeFileSync(edited, [
|
|
285
|
+
'---', `name: ${platformKey === 'codex' ? 'cf-fix' : 'cf:fix'}`,
|
|
286
|
+
'description: "User-modified retired copy."', '---', '# Preserved', '',
|
|
287
|
+
].join('\n'));
|
|
288
|
+
const result = spawnSync(process.execPath, [
|
|
289
|
+
installerPath, '--platform', platformKey, '--yes'
|
|
290
|
+
], { cwd: root, encoding: 'utf8' });
|
|
291
|
+
assert.equal(result.status, 0, result.stderr || result.stdout);
|
|
292
|
+
assert.equal(fs.existsSync(edited), true);
|
|
293
|
+
assert.match(`${result.stdout}\n${result.stderr}`, /Preserved user-owned skill: .*hotfix/);
|
|
294
|
+
for (const renamed of ['scout', 'fix', 'ask']) {
|
|
295
|
+
assert.equal(fs.existsSync(path.join(root, platform.skillsDir, renamed, 'SKILL.md')), true, renamed);
|
|
296
|
+
}
|
|
297
|
+
const scriptRoot = platformKey === 'codex' ? '.codex' : '.claude';
|
|
298
|
+
const catalog = spawnSync(process.execPath, [
|
|
299
|
+
path.join(root, scriptRoot, 'scripts', 'generate-skill-catalog.cjs'), '--json'
|
|
300
|
+
], { cwd: root, encoding: 'utf8' });
|
|
301
|
+
assert.equal(catalog.status, 0, catalog.stderr);
|
|
302
|
+
const parsed = JSON.parse(catalog.stdout);
|
|
303
|
+
for (const id of ['cf:scout', 'cf:fix', 'cf:ask']) {
|
|
304
|
+
assert.ok(parsed.skills.some((skill) => skill.public_id === id), id);
|
|
305
|
+
}
|
|
306
|
+
assert.equal(parsed.skills.find((skill) => skill.public_id === 'cf:fix').directory, 'fix');
|
|
307
|
+
assert.ok(parsed.diagnostics.some((item) => item.directory === 'hotfix' && item.code === 'retired_skill'));
|
|
308
|
+
assert.equal(parsed.diagnostics.some((item) => item.code === 'duplicate_public_name'), false);
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
for (const platformKey of ['claude', 'codex']) {
|
|
314
|
+
test(`${platformKey} upgrade retires the removed loop, route and delegate directories`, () => {
|
|
315
|
+
withTempProject((root) => {
|
|
316
|
+
const platform = PLATFORMS[platformKey];
|
|
317
|
+
const recordRoot = platform.ownership?.recordRoot || platform.folder;
|
|
318
|
+
const key = (file) => path.relative(recordRoot, file).replace(/\\/g, '/');
|
|
319
|
+
const ownership = { schemaVersion: 1, version: 'old', files: {} };
|
|
320
|
+
const removed = ['loop', 'route', 'delegate'];
|
|
321
|
+
for (const old of removed) {
|
|
322
|
+
const file = path.join(platform.skillsDir, old, 'SKILL.md');
|
|
323
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
324
|
+
fs.writeFileSync(file, `pristine ${old}\n`);
|
|
325
|
+
ownership.files[key(file)] = { sha256: manifestLib.hashFile(file), version: 'old' };
|
|
326
|
+
}
|
|
327
|
+
// A user-edited copy has no matching ownership hash, so it must survive the upgrade.
|
|
328
|
+
const edited = path.join(platform.skillsDir, 'route', 'references', 'my-notes.md');
|
|
329
|
+
fs.mkdirSync(path.dirname(edited), { recursive: true });
|
|
330
|
+
fs.writeFileSync(edited, 'user notes\n');
|
|
331
|
+
const ctx = {
|
|
332
|
+
manifest: loadClaudeMigrationManifest(),
|
|
333
|
+
documentSkills: { [platformKey]: { enabled: true, selectionSource: 'cli-opt-in' } },
|
|
334
|
+
ownership: { [platform.folder]: ownership },
|
|
335
|
+
trackers: { [platformKey]: manifestLib.createTracker(platform.folder, 'next', platform.ownership) },
|
|
336
|
+
dryRun: false,
|
|
337
|
+
ui: silentUi(),
|
|
338
|
+
results: { updated: 0, preserved: 0, preservedFiles: [] }
|
|
339
|
+
};
|
|
340
|
+
reconcileSkillInventory(ctx, platformKey);
|
|
341
|
+
assert.equal(fs.existsSync(path.join(root, platform.skillsDir, 'loop')), false, 'loop');
|
|
342
|
+
assert.equal(fs.existsSync(path.join(root, platform.skillsDir, 'delegate')), false, 'delegate');
|
|
343
|
+
assert.equal(fs.existsSync(path.join(root, edited)), true, 'user-edited route copy is preserved');
|
|
344
|
+
assert.equal(ctx.results.updated, 2);
|
|
345
|
+
assert.equal(ctx.results.preserved, 1);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
test('the catalog retires exactly the directories the manifest retires', () => {
|
|
351
|
+
const source = fs.readFileSync(
|
|
352
|
+
path.resolve(__dirname, '..', '..', 'src', 'claude', 'scripts', 'generate-skill-catalog.cjs'), 'utf8');
|
|
353
|
+
const block = source.match(/const RETIRED_DIRECTORIES = new Set\(\[([\s\S]*?)\]\);/);
|
|
354
|
+
assert.ok(block, 'RETIRED_DIRECTORIES not found');
|
|
355
|
+
const retired = [...block[1].matchAll(/'([^']+)'/g)].map((match) => match[1]);
|
|
356
|
+
assert.deepEqual([...retired].sort(), [...loadClaudeMigrationManifest().obsolete.skills].sort());
|
|
357
|
+
});
|
|
@@ -145,8 +145,6 @@ function composeCodexHookTree(root) {
|
|
|
145
145
|
const hooksDir = path.join(root, '.codex', 'hooks');
|
|
146
146
|
fs.mkdirSync(path.join(hooksDir, 'lib'), { recursive: true });
|
|
147
147
|
fs.copyFileSync(path.join(PACKAGE_ROOT, 'src/codex/hooks/session.cjs'), path.join(hooksDir, 'session.cjs'));
|
|
148
|
-
fs.copyFileSync(path.join(PACKAGE_ROOT, 'src/codex/hooks/completion-authority-state.cjs'),
|
|
149
|
-
path.join(hooksDir, 'completion-authority-state.cjs'));
|
|
150
148
|
fs.copyFileSync(path.join(PACKAGE_ROOT, 'src/codex/hooks/lib/hook-context.cjs'),
|
|
151
149
|
path.join(hooksDir, 'lib', 'hook-context.cjs'));
|
|
152
150
|
fs.copyFileSync(path.join(PACKAGE_ROOT, 'src/codex/hooks/lib/privacy-state.cjs'),
|