@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
|
@@ -69,7 +69,7 @@ const DOCS_ADAPTIVE_BUNDLE = [
|
|
|
69
69
|
'references/update-workflow.md',
|
|
70
70
|
'references/standard-docs-workflow.md'
|
|
71
71
|
];
|
|
72
|
-
const HOTFIX_SOURCE_ROOT = path.join(PACKAGE_ROOT, 'src/claude/skills/
|
|
72
|
+
const HOTFIX_SOURCE_ROOT = path.join(PACKAGE_ROOT, 'src/claude/skills/fix');
|
|
73
73
|
const HOTFIX_BUNDLE = [
|
|
74
74
|
'SKILL.md',
|
|
75
75
|
'references/diagnosis-protocol.md',
|
|
@@ -111,7 +111,7 @@ function boundaryTableHasRequiredRows(table) {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
const IMPLEMENTATION_READINESS_CLAUSES = {
|
|
114
|
-
noInvention: 'Before implementation handoff, apply the **no-invention gate**: if two implementations conform to the packet text yet can produce different externally observable output, state, error, security, or compatibility behavior, surface the missing choice as an explicit
|
|
114
|
+
noInvention: 'Before implementation handoff, apply the **no-invention gate**: if two implementations conform to the packet text yet can produce different externally observable output, state, error, security, or compatibility behavior, surface the missing choice as an explicit GATE-SCOPE or GATE-REVIEW question and block handoff.',
|
|
115
115
|
materialDefinition: 'A boundary is material when the task creates, changes, or depends on it and a different choice changes an external observation, security, durable data, compatibility, or proof reachability. Require only the matching material row; omit nonmaterial categories.',
|
|
116
116
|
exactBoundaryChoices: 'For every required row, name each listed choice exactly; labels such as “JSON”, “local path”, “locked”, or “timestamped” alone remain unresolved.',
|
|
117
117
|
proofPlanLines: [
|
|
@@ -130,11 +130,11 @@ const IMPLEMENTATION_READINESS_CLAUSES = {
|
|
|
130
130
|
disposableReviewControls: 'Run mutation or destructive negative controls only on disposable copies below a verified temporary root, never tracked worktree or canonical source bytes.',
|
|
131
131
|
failureSemantics: '`Crash` means abrupt unhandled termination before the claimed catch point; a catchable failure returns/raises an error or exits nonzero. Never use them interchangeably.',
|
|
132
132
|
privacyIdentifiers: 'Any privacy/security claim names the exact identifier surface at risk, such as an env var, header, path, token class, or field name; generic “sensitive data” is insufficient.',
|
|
133
|
-
freshReplay: 'After applying an accepted
|
|
133
|
+
freshReplay: 'After applying an accepted GATE-REVIEW finding, a fresh-context closure pass records and freshly replays its original counterexample after the repair under this exact review-log header:',
|
|
134
134
|
distinctRepairProof: '`Repaired at` cites the repair edit; `Proved at` must cite distinct evidence from the fresh replay, never the repair-edit citation.',
|
|
135
135
|
closureTransition: 'An accepted finding transitions `accepted → repaired → PASS|FAIL|UNKNOWN`.',
|
|
136
136
|
unknownBlocks: 'Only `PASS` closes it; `FAIL` remains open for the remaining paper-review round; `UNKNOWN` blocks implementation handoff.',
|
|
137
|
-
scopeReturnsToC1: 'A repair that adds user semantics or scope returns to
|
|
137
|
+
scopeReturnsToC1: 'A repair that adds user semantics or scope returns to GATE-SCOPE.'
|
|
138
138
|
};
|
|
139
139
|
const ADAPTIVE_COVERAGE_PROFILE_HEADER = [
|
|
140
140
|
'ID', 'Outcome', 'Change kinds', 'Material surfaces', 'Ambiguity/action',
|
|
@@ -148,7 +148,7 @@ const ADAPTIVE_COVERAGE_AMBIGUITY_ROWS = [
|
|
|
148
148
|
['State', 'Required action'],
|
|
149
149
|
['`none`', 'proceed'],
|
|
150
150
|
['`examples-needed`', 'add two or three examples only for an already decided rule; promote to `decision-needed` if an example changes observable behavior'],
|
|
151
|
-
['`decision-needed`', 'ask the user at
|
|
151
|
+
['`decision-needed`', 'ask the user at GATE-SCOPE/GATE-REVIEW and keep affected tasks blocked'],
|
|
152
152
|
['`design-needed`', 'after user-owned decisions settle, route material competing technical designs through Brainstorm']
|
|
153
153
|
];
|
|
154
154
|
const ADAPTIVE_REVIEWER_ROWS = [
|
|
@@ -169,12 +169,12 @@ const ADAPTIVE_COVERAGE_CLAUSES = {
|
|
|
169
169
|
openKinds: 'Change kinds are multi-valued (`add`, `modify`, `fix`, `refactor`, `remove`, `migrate`, `integrate`), and unfamiliar kinds or surfaces use `other:<verbatim>` rather than disappearing.',
|
|
170
170
|
scopedUnion: 'Each task references its CP IDs; authoring, review, edge, and proof obligations union only inside affected rows/tasks.',
|
|
171
171
|
profileRederivation: 'Rederive affected CP rows after any accepted scope, outcome, criteria, ownership, dependency, risk, or proof delta before task status.',
|
|
172
|
-
plannedProof: '`Required proof` is a planned level set, not execution\nevidence: known but unrun proof may be `pending`; `UNKNOWN` reachability blocks\n`pending`; missing, failed, or unavailable required evidence blocks `done`/
|
|
172
|
+
plannedProof: '`Required proof` is a planned level set, not execution\nevidence: known but unrun proof may be `pending`; `UNKNOWN` reachability blocks\n`pending`; missing, failed, or unavailable required evidence blocks `done`/GATE-DONE.',
|
|
173
173
|
proofSeparation: 'Levels stay separate and never promote one another.',
|
|
174
174
|
liveLimit: 'Source/static checks prove the written contract, not live-model adherence.',
|
|
175
175
|
specMakerAuthority: 'they are the canonical risk and coverage authority. Do not duplicate\ntheir taxonomy here.',
|
|
176
176
|
specMakerAmbiguity: 'Apply the canonical ambiguity action; examples never decide observable behavior.',
|
|
177
|
-
specMakerRoute: 'Apply their risk-first route before
|
|
177
|
+
specMakerRoute: 'Apply their risk-first route before GATE-SCOPE and stop when the\nrequest qualifies for direct work; hand off when it requires Brainstorm-only exploration.',
|
|
178
178
|
reviewRisk: 'Keep Fact Checker as the baseline. Assign every remaining material CP risk to a\nnamed reviewer lens; a critical row includes both relevant security-adversary and\nfailure-mode coverage, and nonmaterial lenses are not added.',
|
|
179
179
|
reviewCapacity: 'Reviewer count is fixed by the table, not lens count. Give each reviewer a distinct primary lens; when material lenses exceed reviewers, combine related named lenses on one reviewer and keep every material lens assigned.'
|
|
180
180
|
};
|
|
@@ -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}`);
|
|
@@ -558,7 +495,7 @@ function authoringProjectionIssues(files) {
|
|
|
558
495
|
|| !files.templates.includes('task-NN-<slug>.md')) {
|
|
559
496
|
issues.push('flat-layout-template');
|
|
560
497
|
}
|
|
561
|
-
for (const gate of ['
|
|
498
|
+
for (const gate of ['GATE-SCOPE', 'GATE-REVIEW', 'GATE-DONE']) {
|
|
562
499
|
if (!files.skill.includes(gate)) issues.push(`human-gate-${gate.slice(0, 2).toLowerCase()}`);
|
|
563
500
|
}
|
|
564
501
|
if (!files.review.includes('fresh-context red team')
|
|
@@ -596,7 +533,7 @@ function authoringProjectionIssues(files) {
|
|
|
596
533
|
}
|
|
597
534
|
if (!files.codex.includes('flat `task-NN-*.md` files')
|
|
598
535
|
|| !files.codex.includes('inline `## Receipt`')
|
|
599
|
-
|| !files.codex.includes('
|
|
536
|
+
|| !files.codex.includes('GATE-SCOPE') || !files.codex.includes('GATE-REVIEW') || !files.codex.includes('GATE-DONE')) {
|
|
600
537
|
issues.push('codex-process-v3');
|
|
601
538
|
}
|
|
602
539
|
return [...new Set(issues)].sort();
|
|
@@ -1203,8 +1140,8 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
|
|
|
1203
1140
|
name: 'fresh-original-counterexample-replay',
|
|
1204
1141
|
issue: 'repair-closure',
|
|
1205
1142
|
relative: 'references/review.md',
|
|
1206
|
-
from: 'After applying an accepted
|
|
1207
|
-
to: 'After applying an accepted
|
|
1143
|
+
from: 'After applying an accepted GATE-REVIEW finding, a fresh-context closure pass records and\nfreshly replays its original counterexample after the repair under this exact review-log header:',
|
|
1144
|
+
to: 'After applying an accepted GATE-REVIEW finding, record the repair under this review-log header:'
|
|
1208
1145
|
},
|
|
1209
1146
|
{
|
|
1210
1147
|
name: 'distinct-repair-and-proof-evidence',
|
|
@@ -1313,7 +1250,7 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
|
|
|
1313
1250
|
['stale-profile-after-c2', 'templates', ADAPTIVE_COVERAGE_CLAUSES.profileRederivation,
|
|
1314
1251
|
'Keep existing coverage rows after accepted plan changes.', ['profile-lifecycle']],
|
|
1315
1252
|
['planned-proof-blocks-start', 'templates', ADAPTIVE_COVERAGE_CLAUSES.plannedProof,
|
|
1316
|
-
'`Required proof` is execution evidence: known but unrun proof blocks `pending`; `UNKNOWN` may proceed; missing evidence may still reach `done`/
|
|
1253
|
+
'`Required proof` is execution evidence: known but unrun proof blocks `pending`; `UNKNOWN` may proceed; missing evidence may still reach `done`/GATE-DONE.', ['proof-lifecycle']],
|
|
1317
1254
|
['source-promotes-live', 'templates', ADAPTIVE_COVERAGE_CLAUSES.proofSeparation,
|
|
1318
1255
|
'Source proof may promote installed and live proof.', ['proof-lifecycle']],
|
|
1319
1256
|
['unmapped-proof-level', 'templates', IMPLEMENTATION_READINESS_CLAUSES.proofLevelMapping,
|
|
@@ -1327,7 +1264,7 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
|
|
|
1327
1264
|
['spec-maker-examples-decide', 'specMaker', ADAPTIVE_COVERAGE_CLAUSES.specMakerAmbiguity,
|
|
1328
1265
|
'Use examples to settle every ambiguous observable behavior.', ['spec-maker-authority']],
|
|
1329
1266
|
['spec-maker-skips-brainstorm', 'specMaker', ADAPTIVE_COVERAGE_CLAUSES.specMakerRoute,
|
|
1330
|
-
'Apply the risk-first route before
|
|
1267
|
+
'Apply the risk-first route before GATE-SCOPE and stop only for direct work.', ['spec-maker-authority']],
|
|
1331
1268
|
['static-proves-live', 'skill', ADAPTIVE_COVERAGE_CLAUSES.liveLimit,
|
|
1332
1269
|
'Source/static checks prove live-model adherence.', ['proof-lifecycle']]
|
|
1333
1270
|
];
|
|
@@ -1561,13 +1498,15 @@ test('Codex structured-input corpus oracle stays differential and production-awa
|
|
|
1561
1498
|
'src/claude/agents/spec-maker.md',
|
|
1562
1499
|
'src/claude/hooks/session.cjs',
|
|
1563
1500
|
'src/claude/skills/git/SKILL.md',
|
|
1564
|
-
'src/claude/skills/
|
|
1501
|
+
'src/claude/skills/scout/SKILL.md',
|
|
1502
|
+
'src/claude/skills/sync/references/rebind-and-audit.md'
|
|
1565
1503
|
];
|
|
1566
1504
|
assert.deepEqual(actualPaths, expectedPaths, 'every source occurrence needs an explicit projection oracle');
|
|
1567
1505
|
|
|
1568
1506
|
const instructionExpectedSnippets = new Map([
|
|
1569
1507
|
['src/claude/skills/git/SKILL.md', 'Present options via a structured user-input request — header'],
|
|
1570
|
-
['src/claude/skills/
|
|
1508
|
+
['src/claude/skills/scout/SKILL.md', '**Fallback to a structured user-input request:**'],
|
|
1509
|
+
['src/claude/skills/sync/references/rebind-and-audit.md', 'End by asking with a structured user-input request when the host has']
|
|
1571
1510
|
]);
|
|
1572
1511
|
for (const [relativePath, expectedSnippet] of instructionExpectedSnippets) {
|
|
1573
1512
|
const sourcePath = path.join(PACKAGE_ROOT, relativePath);
|
|
@@ -1983,8 +1922,7 @@ test('Codex Windows hook launchers stay project-bound without Git from nested cw
|
|
|
1983
1922
|
);
|
|
1984
1923
|
const launchers = allHookLaunchers(config);
|
|
1985
1924
|
assert.ok(launchers.length > 0, 'installed Codex config must register hook launchers');
|
|
1986
|
-
const
|
|
1987
|
-
for (const { event, handler } of launchers) {
|
|
1925
|
+
for (const { handler } of launchers) {
|
|
1988
1926
|
assert.doesNotMatch(handler.commandWindows, /\$\(/);
|
|
1989
1927
|
assert.doesNotMatch(handler.commandWindows, /\bgit\b/i);
|
|
1990
1928
|
assert.doesNotMatch(handler.commandWindows, /process\.cwd\(\)|existsSync/);
|
|
@@ -1997,11 +1935,7 @@ test('Codex Windows hook launchers stay project-bound without Git from nested cw
|
|
|
1997
1935
|
true,
|
|
1998
1936
|
`missing installed hook: ${path.basename(target)}`
|
|
1999
1937
|
);
|
|
2000
|
-
if (path.basename(target) === 'semantic-review-authority.cjs') {
|
|
2001
|
-
semanticReviewEvents.push(event);
|
|
2002
|
-
}
|
|
2003
1938
|
}
|
|
2004
|
-
assert.deepEqual(semanticReviewEvents, ['SubagentStop']);
|
|
2005
1939
|
|
|
2006
1940
|
const nested = path.join(projectRoot, 'nested', 'workspace');
|
|
2007
1941
|
fs.mkdirSync(nested, { recursive: true });
|
|
@@ -2163,22 +2097,12 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2163
2097
|
'.codex/rules/state-sync.md',
|
|
2164
2098
|
'.codex/rules/review-audit-self-decision.md',
|
|
2165
2099
|
'.codex/rules/process-management.md',
|
|
2166
|
-
'.codex/scripts/spec-ground.cjs',
|
|
2167
|
-
'.codex/scripts/validate-spec-output.cjs',
|
|
2168
2100
|
'.agents/.gitignore',
|
|
2169
2101
|
...V3_SPECS_BUNDLE.map((file) => `.agents/skills/specs/${file}`)
|
|
2170
2102
|
]) {
|
|
2171
2103
|
assert.equal(fs.existsSync(path.join(root, relative)), true, `missing ${relative}`);
|
|
2172
2104
|
}
|
|
2173
2105
|
|
|
2174
|
-
const installedDesign = fs.readFileSync(
|
|
2175
|
-
path.join(root, '.agents/skills/specs/templates/design.md'), 'utf8'
|
|
2176
|
-
);
|
|
2177
|
-
assert.equal((installedDesign.match(/^## Verification Definitions$/gm) || []).length, 1);
|
|
2178
|
-
assertInstalledVerificationModel(
|
|
2179
|
-
path.join(root, '.codex/scripts/spec-ground.cjs'),
|
|
2180
|
-
installedDesign
|
|
2181
|
-
);
|
|
2182
2106
|
const installedSpecsRoot = path.join(root, '.agents/skills/specs');
|
|
2183
2107
|
assert.throws(
|
|
2184
2108
|
() => installedAuthoringProjectionIssues(root, '.agents/skills/specs'),
|
|
@@ -2194,22 +2118,6 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2194
2118
|
);
|
|
2195
2119
|
assertInstalledAuthoringProjection(root, installedSpecsRoot);
|
|
2196
2120
|
|
|
2197
|
-
const installedTask = fs.readFileSync(
|
|
2198
|
-
path.join(root, '.agents/skills/specs/templates/task.md'), 'utf8'
|
|
2199
|
-
);
|
|
2200
|
-
assert.deepEqual(
|
|
2201
|
-
[...installedTask.matchAll(/^## (.+)$/gm)].map((match) => match[1]),
|
|
2202
|
-
['Outcome', 'Scope', 'Anchors and Ownership', 'Changes', 'Acceptance', 'Dependencies', 'Verification Plan']
|
|
2203
|
-
);
|
|
2204
|
-
assert.match(installedTask, /^- \*\*Task role:\*\*/m);
|
|
2205
|
-
|
|
2206
|
-
const installedState = JSON.parse(fs.readFileSync(
|
|
2207
|
-
path.join(root, '.agents/skills/specs/templates/spec-state.json'), 'utf8'
|
|
2208
|
-
));
|
|
2209
|
-
assert.deepEqual(Object.keys(installedState.workflow_policy).sort(), [
|
|
2210
|
-
'assurance_level', 'classified_minimum', 'planning_depth', 'risks', 'version'
|
|
2211
|
-
]);
|
|
2212
|
-
|
|
2213
2121
|
const agentsGitignore = fs.readFileSync(
|
|
2214
2122
|
path.join(root, '.agents', '.gitignore'),
|
|
2215
2123
|
'utf8'
|
|
@@ -2220,7 +2128,6 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2220
2128
|
|
|
2221
2129
|
if (process.platform !== 'win32') {
|
|
2222
2130
|
for (const [sourceRelative, installedRelative] of [
|
|
2223
|
-
['src/claude/scripts/validate-spec-output.cjs', '.codex/scripts/validate-spec-output.cjs'],
|
|
2224
2131
|
['src/claude/skills/chrome-devtools/scripts/install.sh', '.agents/skills/chrome-devtools/scripts/install.sh'],
|
|
2225
2132
|
['src/claude/skills/ai-multimodal/scripts/check_setup.py', '.agents/skills/ai-multimodal/scripts/check_setup.py']
|
|
2226
2133
|
]) {
|
|
@@ -2260,24 +2167,24 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2260
2167
|
assert.ok(skillNames.every((name) => /^[a-z0-9-]+$/.test(name)));
|
|
2261
2168
|
|
|
2262
2169
|
const scoutSkill = fs.readFileSync(
|
|
2263
|
-
path.join(root, '.agents', 'skills', '
|
|
2170
|
+
path.join(root, '.agents', 'skills', 'scout', 'SKILL.md'),
|
|
2264
2171
|
'utf8'
|
|
2265
2172
|
);
|
|
2266
2173
|
assert.match(scoutSkill, /^name:\s*cf-scout$/m);
|
|
2267
2174
|
assert.equal(
|
|
2268
|
-
fs.existsSync(path.join(root, '.agents', 'skills', '
|
|
2175
|
+
fs.existsSync(path.join(root, '.agents', 'skills', 'inspect')),
|
|
2269
2176
|
false,
|
|
2270
|
-
'
|
|
2177
|
+
'Scout lives in the scout directory; the retired inspect directory must not be installed'
|
|
2271
2178
|
);
|
|
2272
2179
|
const askSkill = fs.readFileSync(
|
|
2273
|
-
path.join(root, '.agents', 'skills', '
|
|
2180
|
+
path.join(root, '.agents', 'skills', 'ask', 'SKILL.md'),
|
|
2274
2181
|
'utf8'
|
|
2275
2182
|
);
|
|
2276
2183
|
assert.match(askSkill, /^name:\s*cf-ask$/m);
|
|
2277
2184
|
assert.equal(
|
|
2278
|
-
fs.existsSync(path.join(root, '.agents', 'skills', '
|
|
2185
|
+
fs.existsSync(path.join(root, '.agents', 'skills', 'question')),
|
|
2279
2186
|
false,
|
|
2280
|
-
'
|
|
2187
|
+
'Ask lives in the ask directory; the retired question directory must not be installed'
|
|
2281
2188
|
);
|
|
2282
2189
|
|
|
2283
2190
|
const catalog = spawnSync(
|
|
@@ -2338,10 +2245,10 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2338
2245
|
(key.startsWith('.codex/') || key.startsWith('.agents/')) && !key.includes('../')
|
|
2339
2246
|
)));
|
|
2340
2247
|
|
|
2341
|
-
const questionSkill = path.join(root, '.agents', 'skills', '
|
|
2248
|
+
const questionSkill = path.join(root, '.agents', 'skills', 'ask', 'SKILL.md');
|
|
2342
2249
|
fs.appendFileSync(questionSkill, '\nUSER-CODEX-SENTINEL\n');
|
|
2343
2250
|
// Fresh installs are exact. Refresh/upgrade intentionally documents the
|
|
2344
|
-
//
|
|
2251
|
+
// A skill file the manifest lists as obsolete is removed on refresh; edited skills stay.
|
|
2345
2252
|
const obsoleteSpecsRule = path.join(
|
|
2346
2253
|
root, '.agents', 'skills', 'specs', 'rules', 'design-principles.md'
|
|
2347
2254
|
);
|
|
@@ -2354,14 +2261,15 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2354
2261
|
assert.match(fs.readFileSync(questionSkill, 'utf8'), /USER-CODEX-SENTINEL/);
|
|
2355
2262
|
assert.equal(
|
|
2356
2263
|
fs.existsSync(obsoleteSpecsRule),
|
|
2357
|
-
|
|
2358
|
-
'
|
|
2264
|
+
false,
|
|
2265
|
+
'Codex refresh removes obsolete skill files'
|
|
2359
2266
|
);
|
|
2360
2267
|
|
|
2361
2268
|
const metadataPath = path.join(root, '.codex', 'cafekit.json');
|
|
2362
2269
|
const metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
2363
2270
|
metadata.version = '0.14.1';
|
|
2364
2271
|
fs.writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}\n`);
|
|
2272
|
+
fs.writeFileSync(obsoleteSpecsRule, 'LEGACY-CODEX-ORPHAN\n');
|
|
2365
2273
|
|
|
2366
2274
|
const upgrade = install(root);
|
|
2367
2275
|
assert.equal(upgrade.status, 0, `${upgrade.stdout}\n${upgrade.stderr}`);
|
|
@@ -2369,8 +2277,8 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2369
2277
|
assert.match(fs.readFileSync(questionSkill, 'utf8'), /USER-CODEX-SENTINEL/);
|
|
2370
2278
|
assert.equal(
|
|
2371
2279
|
fs.existsSync(obsoleteSpecsRule),
|
|
2372
|
-
|
|
2373
|
-
'
|
|
2280
|
+
false,
|
|
2281
|
+
'Codex upgrade removes obsolete skill files'
|
|
2374
2282
|
);
|
|
2375
2283
|
assert.ok(fs.readFileSync(path.join(root, 'AGENTS.md'), 'utf8').startsWith(userInstructions));
|
|
2376
2284
|
|
|
@@ -2426,7 +2334,7 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
|
|
|
2426
2334
|
const mutations = [
|
|
2427
2335
|
{
|
|
2428
2336
|
name: 'adaptive-direct-precedence-removed', source: 'skill',
|
|
2429
|
-
from: 'Route Direct first, then
|
|
2337
|
+
from: 'Route Direct first, then apply controls only to requests that remain in Brainstorm.',
|
|
2430
2338
|
to: 'Apply controls before Direct classification.', expected: ['adaptive-direct-precedence']
|
|
2431
2339
|
},
|
|
2432
2340
|
{
|
|
@@ -2441,37 +2349,37 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
|
|
|
2441
2349
|
},
|
|
2442
2350
|
{
|
|
2443
2351
|
name: 'adaptive-failure-isolation-removed', source: 'skill',
|
|
2444
|
-
from: 'failure isolation for partial or cascading failure
|
|
2352
|
+
from: 'failure isolation for partial or cascading failure across boundaries',
|
|
2445
2353
|
to: 'generic failure notes', expected: ['adaptive-lens-trigger-skip']
|
|
2446
2354
|
},
|
|
2447
2355
|
{
|
|
2448
2356
|
name: 'adaptive-evidence-fallback-removed', source: 'skill',
|
|
2449
|
-
from: 'Missing evidence
|
|
2357
|
+
from: 'Missing evidence forces feasibility `unknown` and confidence `low`.',
|
|
2450
2358
|
to: 'Missing evidence permits a confident guess.', expected: ['adaptive-evidence-semantics']
|
|
2451
2359
|
},
|
|
2452
2360
|
{
|
|
2453
2361
|
name: 'adaptive-numeric-evidence-removed', source: 'skill',
|
|
2454
|
-
from: 'A numeric estimate requires
|
|
2362
|
+
from: 'A numeric estimate requires range, unit, basis, evidence, and assumptions; otherwise report `unknown`.',
|
|
2455
2363
|
to: 'A numeric estimate may be a best-effort number.', expected: ['adaptive-numeric-estimates']
|
|
2456
2364
|
},
|
|
2457
2365
|
{
|
|
2458
2366
|
name: 'adaptive-pre-tool-redaction-removed', source: 'skill',
|
|
2459
|
-
from: 'Before an
|
|
2367
|
+
from: 'Before an external visual tool or adviser handoff, minimize context and redact secrets, credentials, private keys, access tokens, and unnecessary PII.',
|
|
2460
2368
|
to: 'Forward full context to every external tool and adviser.', expected: ['adaptive-pre-tool-redaction']
|
|
2461
2369
|
},
|
|
2462
2370
|
{
|
|
2463
2371
|
name: 'adaptive-adviser-gate-removed', source: 'skill',
|
|
2464
|
-
from: '`--advice` invokes
|
|
2372
|
+
from: '`--advice` invokes `brainstormer` only after the material-choice gate;',
|
|
2465
2373
|
to: '`--advice` invokes `brainstormer` before routing;', expected: ['adaptive-adviser-gate']
|
|
2466
2374
|
},
|
|
2467
2375
|
{
|
|
2468
2376
|
name: 'adaptive-decision-freshness-removed', source: 'skill',
|
|
2469
|
-
from: 'The first section records target
|
|
2377
|
+
from: 'The first section records target identity, current source revision and worktree state or `[UNVERIFIED]`, an evidence-as-of value, and what change invalidates the brief.',
|
|
2470
2378
|
to: 'The handoff has no revision or freshness binding.', expected: ['adaptive-decision-freshness']
|
|
2471
2379
|
},
|
|
2472
2380
|
{
|
|
2473
2381
|
name: 'adaptive-overlay-authority-removed', source: 'skill',
|
|
2474
|
-
from: 'Neither overlay
|
|
2382
|
+
from: 'Neither overlay writes, approves, persists, dispatches, or completes work.',
|
|
2475
2383
|
to: 'Overlays may persist, approve, dispatch, and complete work.', expected: ['adaptive-non-authority']
|
|
2476
2384
|
},
|
|
2477
2385
|
{
|
|
@@ -2491,7 +2399,7 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
|
|
|
2491
2399
|
{
|
|
2492
2400
|
name: 'exploration-stop-removed',
|
|
2493
2401
|
source: 'skill',
|
|
2494
|
-
from: 'Do not request design approval, persist a report, or
|
|
2402
|
+
from: 'Do not request design approval, persist a report, or invoke another workflow without a new explicit request.',
|
|
2495
2403
|
to: 'Request approval, persist a report, and invoke another workflow.',
|
|
2496
2404
|
expected: ['exploration-stop']
|
|
2497
2405
|
},
|
|
@@ -2841,7 +2749,7 @@ function hotfixProjectionIssues(files) {
|
|
|
2841
2749
|
}
|
|
2842
2750
|
if (!parallel.includes('Diagnosis still starts only')
|
|
2843
2751
|
|| !parallel.includes('after the required scout outputs are synthesized')
|
|
2844
|
-
|| !parallel.includes('Research begins only after
|
|
2752
|
+
|| !parallel.includes('Research begins only after diagnosis')
|
|
2845
2753
|
|| parallel.includes('scout + diagnose + research together')
|
|
2846
2754
|
|| parallel.includes("You don't need to wait for scouting")) {
|
|
2847
2755
|
issues.add('scout-before-diagnosis');
|
|
@@ -2858,9 +2766,9 @@ test('Codex installed Fix preserves the adaptive repair contract', () => {
|
|
|
2858
2766
|
const result = install(root);
|
|
2859
2767
|
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
|
|
2860
2768
|
|
|
2861
|
-
const installedRoot = path.join(root, '.agents/skills/
|
|
2862
|
-
assert.equal(fs.existsSync(path.join(root, '.agents/skills/
|
|
2863
|
-
'
|
|
2769
|
+
const installedRoot = path.join(root, '.agents/skills/fix');
|
|
2770
|
+
assert.equal(fs.existsSync(path.join(root, '.agents/skills/hotfix')), false,
|
|
2771
|
+
'Fix lives in the fix directory; the retired hotfix directory must not be installed');
|
|
2864
2772
|
for (const relative of HOTFIX_BUNDLE) {
|
|
2865
2773
|
const sourcePath = path.join(HOTFIX_SOURCE_ROOT, relative);
|
|
2866
2774
|
assert.equal(
|
|
@@ -2952,7 +2860,7 @@ test('Codex installed Fix preserves the adaptive repair contract', () => {
|
|
|
2952
2860
|
},
|
|
2953
2861
|
{
|
|
2954
2862
|
name: 'research-starts-before-diagnosis', file: 'references/parallel-patterns.md',
|
|
2955
|
-
from: 'Research begins only after
|
|
2863
|
+
from: 'Research begins only after diagnosis', to: 'Research may begin before diagnosis',
|
|
2956
2864
|
expected: ['scout-before-diagnosis']
|
|
2957
2865
|
}
|
|
2958
2866
|
];
|
|
@@ -3139,8 +3047,6 @@ test('Codex install on top of existing Claude installation preserves content and
|
|
|
3139
3047
|
assert.equal(fs.existsSync(path.join(root, '.codex', 'runtime.json')), true, '.codex/runtime.json should exist');
|
|
3140
3048
|
assert.equal(fs.existsSync(path.join(root, '.codex', 'hooks', 'privacy-block.cjs')), true, '.codex/hooks/privacy-block.cjs should exist');
|
|
3141
3049
|
assert.equal(fs.existsSync(path.join(root, '.codex', 'rules', 'workflow.md')), true, '.codex/rules/workflow.md should exist');
|
|
3142
|
-
assert.equal(fs.existsSync(path.join(root, '.codex', 'scripts', 'spec-ground.cjs')), true, '.codex/scripts/spec-ground.cjs should exist');
|
|
3143
|
-
assert.equal(fs.existsSync(path.join(root, '.codex', 'scripts', 'validate-spec-output.cjs')), true, '.codex/scripts/validate-spec-output.cjs should exist');
|
|
3144
3050
|
assert.equal(fs.existsSync(path.join(root, '.agents', '.gitignore')), true, '.agents/.gitignore should exist');
|
|
3145
3051
|
assert.equal(fs.existsSync(path.join(root, '.agents', 'skills', 'specs', 'SKILL.md')), true, '.agents/skills/specs/SKILL.md should exist');
|
|
3146
3052
|
|
|
@@ -3162,59 +3068,76 @@ test('Codex install on top of existing Claude installation preserves content and
|
|
|
3162
3068
|
});
|
|
3163
3069
|
});
|
|
3164
3070
|
|
|
3165
|
-
test('Codex installed code_auditor
|
|
3071
|
+
test('Codex installed code_auditor carries no Strict attestation marker', () => {
|
|
3166
3072
|
inTempProject((root) => {
|
|
3167
3073
|
const result = install(root);
|
|
3168
3074
|
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
|
|
3169
3075
|
const toml = fs.readFileSync(path.join(root, '.codex', 'agents', 'code_auditor.toml'), 'utf8');
|
|
3170
|
-
assert.
|
|
3171
|
-
assert.
|
|
3172
|
-
assert.
|
|
3173
|
-
assert.doesNotMatch(toml, /host-signed/);
|
|
3174
|
-
assert.match(toml, /specs\/<feature>\/spec\.json/);
|
|
3076
|
+
assert.doesNotMatch(toml, /CAFEKIT_SEMANTIC_REVIEW_ATTESTATION/);
|
|
3077
|
+
assert.doesNotMatch(toml, /Strict Semantic Review Attestation/);
|
|
3078
|
+
assert.doesNotMatch(toml, /MAC-protected host-hook observation/);
|
|
3175
3079
|
});
|
|
3176
3080
|
});
|
|
3177
3081
|
|
|
3178
|
-
test('
|
|
3082
|
+
test('reinstall removes obsolete scripts and skill files from Codex and omp installs', () => {
|
|
3179
3083
|
inTempProject((root) => {
|
|
3180
|
-
const
|
|
3181
|
-
assert.equal(
|
|
3182
|
-
const
|
|
3183
|
-
const
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
fs.
|
|
3188
|
-
const
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
fs.
|
|
3194
|
-
|
|
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
|
+
}
|
|
3195
3104
|
});
|
|
3196
3105
|
});
|
|
3197
3106
|
|
|
3198
|
-
test('Claude and Codex
|
|
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
|
+
}
|
|
3130
|
+
});
|
|
3131
|
+
});
|
|
3132
|
+
|
|
3133
|
+
test('Claude and Codex installed routing rules preserve the live-catalog semantics and install no Route', () => {
|
|
3199
3134
|
inTempProject((root) => {
|
|
3200
3135
|
const result = installPlatforms(root, ['claude', 'codex']);
|
|
3201
3136
|
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
|
|
3202
|
-
const sourceRoot = path.join(PACKAGE_ROOT, 'src/claude/skills/route');
|
|
3203
|
-
const expectedFiles = [
|
|
3204
|
-
'SKILL.md', 'references/task-taxonomy.md',
|
|
3205
|
-
'references/chaining-patterns.md', 'references/agent-timing.md'
|
|
3206
|
-
];
|
|
3207
3137
|
const expectedRules = ['skill-workflow-routing.md', 'skill-domain-routing.md'];
|
|
3208
3138
|
for (const runtime of ['claude', 'codex']) {
|
|
3209
3139
|
const installedRoot = path.join(root, runtime === 'codex' ? '.agents/skills/route' : '.claude/skills/route');
|
|
3210
|
-
|
|
3211
|
-
const source = fs.readFileSync(path.join(sourceRoot, relative), 'utf8');
|
|
3212
|
-
const installed = fs.readFileSync(path.join(installedRoot, relative), 'utf8');
|
|
3213
|
-
const expected = runtime === 'codex'
|
|
3214
|
-
? normalizeCodexBody(source, path.join(sourceRoot, relative))
|
|
3215
|
-
: source;
|
|
3216
|
-
assert.equal(installed, expected, `${runtime}:${relative}`);
|
|
3217
|
-
}
|
|
3140
|
+
assert.equal(fs.existsSync(installedRoot), false, `${runtime} still installs Route`);
|
|
3218
3141
|
for (const relative of expectedRules) {
|
|
3219
3142
|
const sourcePath = path.join(PACKAGE_ROOT, 'src/claude/rules', relative);
|
|
3220
3143
|
const source = fs.readFileSync(sourcePath, 'utf8');
|
|
@@ -3224,12 +3147,8 @@ test('Claude and Codex installed Route preserve proportional live-catalog semant
|
|
|
3224
3147
|
const expected = runtime === 'codex' ? normalizeCodexBody(source, sourcePath) : source;
|
|
3225
3148
|
assert.equal(installed, expected, `${runtime}:rules/${relative}`);
|
|
3226
3149
|
}
|
|
3227
|
-
const route = fs.readFileSync(path.join(installedRoot, 'SKILL.md'), 'utf8');
|
|
3228
|
-
assert.match(route, /names a valid installed skill[\s\S]*one installed skill clearly covers[\s\S]*Direct factual conversation/);
|
|
3229
|
-
assert.match(route, /highest-link[\s\S]*risk[\s\S]*number of material domains/);
|
|
3230
|
-
assert.match(route, /never expand it/);
|
|
3231
3150
|
const catalog = installedCatalog(root, runtime);
|
|
3232
|
-
assert.
|
|
3151
|
+
assert.equal(catalog.skills.some((skill) => skill.public_id === 'cf:route'), false);
|
|
3233
3152
|
assert.equal(catalog.skills.some((skill) => skill.public_id === 'cf:docs'), false);
|
|
3234
3153
|
}
|
|
3235
3154
|
});
|
|
@@ -3304,24 +3223,3 @@ test('Claude and Codex installed rules preserve the ported review and process gu
|
|
|
3304
3223
|
});
|
|
3305
3224
|
});
|
|
3306
3225
|
|
|
3307
|
-
test('installed Route degrades safely when an agent is absent', () => {
|
|
3308
|
-
inTempProject((root) => {
|
|
3309
|
-
const result = installPlatforms(root, ['claude', 'codex']);
|
|
3310
|
-
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
|
|
3311
|
-
const cases = [
|
|
3312
|
-
['claude', '.claude/agents/researcher.md', '.claude/skills/route'],
|
|
3313
|
-
['codex', '.codex/agents/researcher.toml', '.agents/skills/route'],
|
|
3314
|
-
];
|
|
3315
|
-
for (const [runtime, agentRelative, routeRelative] of cases) {
|
|
3316
|
-
fs.rmSync(path.join(root, agentRelative), { force: true });
|
|
3317
|
-
assert.equal(fs.existsSync(path.join(root, agentRelative)), false);
|
|
3318
|
-
const timing = fs.readFileSync(path.join(root, routeRelative, 'references/agent-timing.md'), 'utf8');
|
|
3319
|
-
const route = fs.readFileSync(path.join(root, routeRelative, 'SKILL.md'), 'utf8');
|
|
3320
|
-
const normalizedRoute = route.replace(/\s+/g, ' ');
|
|
3321
|
-
assert.match(timing, /If the preferred agent is absent[\s\S]*never synthesize a role/);
|
|
3322
|
-
assert.match(normalizedRoute, /continue inline when safe or return the named gap/);
|
|
3323
|
-
assert.match(normalizedRoute, /Never synthesize an unavailable agent/);
|
|
3324
|
-
assert.doesNotMatch(`${timing}\n${route}`, /researcher(?:\.md|\.toml)/i, runtime);
|
|
3325
|
-
}
|
|
3326
|
-
});
|
|
3327
|
-
});
|