@haposoft/cafekit 0.16.6 → 0.18.0
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 +0 -36
- package/bin/__tests__/codex-native.test.js +46 -88
- package/bin/__tests__/develop-contract.test.js +26 -57
- 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 +159 -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 +100 -541
- 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 +0 -27
- package/bin/__tests__/specs-v2-execution-closeout.test.js +4 -69
- 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 +9 -28
- package/bin/phases/codex-runtime.js +24 -0
- package/bin/phases/omp-runtime.js +22 -0
- package/package.json +1 -1
- package/src/claude/CLAUDE.md +3 -10
- package/src/claude/agents/brainstormer.md +7 -3
- package/src/claude/agents/code-auditor.md +35 -50
- package/src/claude/agents/debugger.md +5 -79
- package/src/claude/agents/deployer.md +3 -5
- package/src/claude/agents/docs-keeper.md +2 -7
- package/src/claude/agents/implementer.md +6 -9
- package/src/claude/agents/inspector.md +2 -3
- package/src/claude/agents/project-manager.md +7 -15
- package/src/claude/agents/researcher.md +9 -3
- package/src/claude/agents/spec-maker.md +11 -11
- package/src/claude/hooks/__tests__/fixtures/statusline-default.golden +1 -1
- package/src/claude/hooks/__tests__/spec-gate.test.js +112 -3
- package/src/claude/hooks/__tests__/spec-state-touched.test.js +134 -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/context.cjs +0 -89
- 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 +18 -28
- package/src/claude/hooks/spec-state.cjs +95 -1
- package/src/claude/hooks/state.cjs +21 -2
- package/src/claude/migration-manifest.json +30 -15
- package/src/claude/rules/ai-dev-rules.md +1 -1
- 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 +10 -18
- 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 +52 -6
- package/src/claude/scripts/spec-resolver.cjs +1 -2
- package/src/claude/scripts/validate-spec-output.cjs +5 -32
- package/src/claude/scripts/workflow-policy.cjs +22 -10
- package/src/claude/settings/settings.json +1 -32
- package/src/claude/skills/{question → ask}/SKILL.md +9 -75
- package/src/claude/skills/brainstorm/SKILL.md +43 -131
- package/src/claude/skills/code-review/SKILL.md +48 -17
- package/src/claude/skills/code-review/references/spec-compliance-review.md +2 -3
- package/src/claude/skills/code-review/references/verification-gate.md +22 -27
- package/src/claude/skills/debug/SKILL.md +29 -149
- package/src/claude/skills/develop/SKILL.md +27 -36
- 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/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 +2 -0
- 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 +38 -44
- package/src/claude/skills/sync/SKILL.md +8 -15
- 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 +22 -3
- package/src/claude/skills/test/references/execution-strategy.md +83 -0
- 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 +1 -1
- 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 +5 -0
- package/src/codex/hooks/lib/spec-utils.cjs +0 -7
- package/src/codex/hooks/rules.cjs +2 -1
- package/src/codex/hooks/session.cjs +0 -2
- package/src/codex/hooks/spec-gate.cjs +8 -18
- package/src/codex/hooks.json +0 -20
- package/src/codex/rules/state-sync.md +3 -12
- package/src/common/AGENTS.md +2 -2
- package/src/omp/extensions/cafekit-bridge.mjs +6 -6
- 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/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/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/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
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Native spec-driven workflow and runtime bundle for Claude Code and Codex CLI.
|
|
4
4
|
|
|
5
|
-
[](https://github.com/haposoft/cafekit)
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
[](https://claude.ai/code)
|
|
8
8
|
[](https://developers.openai.com/codex)
|
|
@@ -147,6 +147,13 @@ cat .codex/cafekit.json
|
|
|
147
147
|
The Claude statusline reads three keys from `.claude/runtime.json`:
|
|
148
148
|
|
|
149
149
|
- `"statusline"`: render mode — `full` (default), `compact`, `minimal`, or `none`.
|
|
150
|
+
The default is one line, `◆ model (effort) ϟ✱ ◔ context% ⧗ 5h quota% reset ◷ weekly% ⎇ branch ●changed ↑↓ #PR✓ ⊟ ± +added/-removed ⏱ session ↻ cache hit%`
|
|
151
|
+
(`ϟ` fast mode, `✱` thinking, `#PR` with ✓ approved / ✗ changes requested, `⊟` inside a git worktree;
|
|
152
|
+
each appears only when present), which drops cache, session time, changes, weekly, quota, then the
|
|
153
|
+
branch as the terminal narrows. Quota comes only from the `rate_limits` Claude Code sends (Pro/Max,
|
|
154
|
+
after a session's first API response); without it the quota segments are hidden. `full` adds
|
|
155
|
+
agent and todo lines only while they exist, `compact` is the line alone, and `minimal`
|
|
156
|
+
keeps model, context and branch.
|
|
150
157
|
- `statuslineColors`: set `false` to disable ANSI colors (`NO_COLOR` also wins).
|
|
151
158
|
- `statuslineLayout`: optional custom layout. Global shape
|
|
152
159
|
`{ "lines": [["model", "context"], ["directory", "git"]] }` — each inner
|
|
@@ -156,8 +163,8 @@ The Claude statusline reads three keys from `.claude/runtime.json`:
|
|
|
156
163
|
ids are ignored; an empty or invalid layout falls back to the default
|
|
157
164
|
renderers, and leaving the key out keeps the default output unchanged. The
|
|
158
165
|
`cost` section renders only when enabled here, billing mode is API, and cost
|
|
159
|
-
data exists. Quota shows five-hour and weekly windows only while
|
|
160
|
-
|
|
166
|
+
data exists. Quota shows five-hour and weekly windows only while Claude Code
|
|
167
|
+
sends `rate_limits`. The `usage` key is deprecated and has no effect.
|
|
161
168
|
|
|
162
169
|
## Core Skills
|
|
163
170
|
|
|
@@ -167,8 +174,6 @@ CafeKit ships many skills, but the main release surface is:
|
|
|
167
174
|
- `/cf:scout <search-target>`: discover relevant files locally first, delegating only for permitted broad independent scopes
|
|
168
175
|
- `/cf:brainstorm <idea-or-problem>`: scout the repo, clarify exact requirements, compare approaches, and hand off to specs
|
|
169
176
|
- `/cf:research <decision>`: choose proportional depth and return traceable evidence for an uncertain technical decision
|
|
170
|
-
- `/cf:route <material-request>`: classify ambiguous, multi-step, multi-domain, or elevated-risk work and compose the shortest valid installed chain
|
|
171
|
-
- `/cf:loop <bounded-experiment>`: run explicit-only numeric optimization in an isolated worktree and return a base-bound patch handoff
|
|
172
177
|
- `/cf:orca <orca-request>`: inside an Orca (onorca.dev) pane, route a request to read, wait on, or send to another agent pane, or spawn one into a worktree
|
|
173
178
|
- `/cf:specs <feature-description>`: create or resume a structured spec workflow
|
|
174
179
|
- `/cf:develop <feature-name>`: implement from approved spec artifacts
|
|
@@ -194,7 +199,7 @@ completes work. Chat is the default output. A durable file needs explicit user
|
|
|
194
199
|
authority, and no Brainstorm output is live proof or Specs/Develop approval or
|
|
195
200
|
execution authority.
|
|
196
201
|
|
|
197
|
-
### Adaptive Research
|
|
202
|
+
### Adaptive Research
|
|
198
203
|
|
|
199
204
|
Use `/cf:research` when the result is a decision: Quick, Standard, or Deep
|
|
200
205
|
research binds material claims to a URL or repository anchor, authority,
|
|
@@ -202,18 +207,9 @@ date/version, applicability, and `confirmed`, `inferred`, or `unresolved`
|
|
|
202
207
|
state. Research returns evidence and tradeoffs; it does not implement the
|
|
203
208
|
recommendation or guarantee correctness.
|
|
204
209
|
|
|
205
|
-
Use `/cf:loop` only by explicit request and only after its preflight freezes
|
|
206
|
-
Goal, isolated Scope, finite numeric Metric and Direction, reproducible
|
|
207
|
-
Baseline, distinct Guard, noise policy and minimum delta, budget, and stop
|
|
208
|
-
conditions. Each iteration stays in a detached worktree. The result is a
|
|
209
|
-
base-bound isolated patch handoff, never an automatic apply, commit, push, or
|
|
210
|
-
guarantee of improvement.
|
|
211
|
-
|
|
212
210
|
```text
|
|
213
211
|
/cf:research Compare current local-first search libraries for this repository
|
|
214
|
-
/cf:loop Goal="reduce parser latency" Scope="packages/parser" Metric="median ms, lower" Baseline="pinned base" Guard="npm test" Noise="MAD; minimum delta 2%" Budget="10 iterations" Stop="budget, drift, or failed guard"
|
|
215
212
|
$cf-research Compare current local-first search libraries for this repository
|
|
216
|
-
$cf-loop Goal="reduce parser latency" Scope="packages/parser" Metric="median ms, lower" Baseline="pinned base" Guard="npm test" Noise="MAD; minimum delta 2%" Budget="10 iterations" Stop="budget, drift, or failed guard"
|
|
217
213
|
```
|
|
218
214
|
|
|
219
215
|
Optional document skills are `docs`, `docx`, `pdf`, `pptx`, `xlsx`, and
|
|
@@ -244,7 +240,7 @@ node .claude/scripts/generate-skill-catalog.cjs --skills
|
|
|
244
240
|
Routing uses progressive disclosure: live catalog metadata selects a candidate,
|
|
245
241
|
the selected `SKILL.md` supplies its contract, and only relevant references are
|
|
246
242
|
loaded. Invoke an installed skill directly for explicit or obvious low-risk
|
|
247
|
-
work;
|
|
243
|
+
work; compose a short chain only when classification or chaining is material. When a
|
|
248
244
|
capability or agent is absent, continue inline when safe or name the gap.
|
|
249
245
|
Hooks are not a skill router and never grant capability presence or authority. Source
|
|
250
246
|
and installed projections are verified; live-model adherence remains
|
|
@@ -310,17 +306,13 @@ specs/<feature-name>/
|
|
|
310
306
|
```
|
|
311
307
|
|
|
312
308
|
The process-first workflow has three human decision gates. `cf:specs` opens
|
|
313
|
-
|
|
309
|
+
GATE-SCOPE to fix scope before authoring and GATE-REVIEW to resolve adversarial findings, then
|
|
314
310
|
stops. A later explicit `cf:develop` invocation executes the tasks and
|
|
315
|
-
presents
|
|
311
|
+
presents GATE-DONE for closeout only after real execution proof. Each task has one
|
|
316
312
|
`Status:` field and keeps its canonical `## Receipt` inline, including the
|
|
317
313
|
exact Verification Plan command, `Exit: 0`, `Verification: PASS`,
|
|
318
314
|
runtime-derived Base and Head, and current command output.
|
|
319
315
|
|
|
320
|
-
Existing packets with `spec.json`, nested `tasks/task-R*.md`, or separate
|
|
321
|
-
receipts remain supported through the legacy compatibility adapter. New Specs
|
|
322
|
-
work does not author those legacy artifacts.
|
|
323
|
-
|
|
324
316
|
## Development
|
|
325
317
|
|
|
326
318
|
Run package self-tests:
|
|
@@ -136,8 +136,8 @@ test('repeated installs never duplicate a CafeKit hook', () => {
|
|
|
136
136
|
const config = readHooks(root);
|
|
137
137
|
assert.equal(allHandlers(config).length, afterFirst, 'a reinstall added handlers that were already registered');
|
|
138
138
|
|
|
139
|
-
// Uniqueness is per event, not global: state.cjs
|
|
140
|
-
//
|
|
139
|
+
// Uniqueness is per event, not global: state.cjs registers under several events by
|
|
140
|
+
// design.
|
|
141
141
|
for (const [eventName, groups] of Object.entries(config.hooks)) {
|
|
142
142
|
const scripts = groups
|
|
143
143
|
.flatMap((group) => group.hooks || [])
|
|
@@ -611,24 +611,6 @@ test('Codex inspect hook scans native shell commands and structured paths', () =
|
|
|
611
611
|
});
|
|
612
612
|
});
|
|
613
613
|
|
|
614
|
-
test('Codex task scaffold hook blocks apply_patch Add File with stderr guidance', () => {
|
|
615
|
-
inHookFixture((root, hooks) => {
|
|
616
|
-
const result = runHook(path.join(hooks, 'task-scaffold-guard.cjs'), root, {
|
|
617
|
-
cwd: root,
|
|
618
|
-
session_id: 'session-a',
|
|
619
|
-
hook_event_name: 'PreToolUse',
|
|
620
|
-
tool_name: 'apply_patch',
|
|
621
|
-
tool_input: {
|
|
622
|
-
command: '*** Begin Patch\n*** Add File: specs/auth/tasks/task-R0-01-auth.md\n+x\n*** End Patch\n'
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
|
|
626
|
-
assert.equal(result.status, 2);
|
|
627
|
-
assert.match(result.stderr, /TASK SCAFFOLD REQUIRED/);
|
|
628
|
-
assert.match(result.stderr, /node \.codex\/scripts\/spec-scaffold\.cjs auth/);
|
|
629
|
-
});
|
|
630
|
-
});
|
|
631
|
-
|
|
632
614
|
test('Codex completion gate cannot be bypassed from a nested cwd', () => {
|
|
633
615
|
inHookFixture((root, hooks) => {
|
|
634
616
|
const nested = path.join(root, 'packages', 'app');
|
|
@@ -1036,24 +1018,6 @@ test('Codex state hook persists direct native event fields at project root', ()
|
|
|
1036
1018
|
});
|
|
1037
1019
|
});
|
|
1038
1020
|
|
|
1039
|
-
test('semantic review authority hook is registered only for SubagentStop on Claude and Codex', () => {
|
|
1040
|
-
const configurations = [
|
|
1041
|
-
JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'src/claude/settings/settings.json'), 'utf8')).hooks,
|
|
1042
|
-
JSON.parse(fs.readFileSync(path.join(PACKAGE_ROOT, 'src/codex/hooks.json'), 'utf8')).hooks,
|
|
1043
|
-
];
|
|
1044
|
-
for (const hooks of configurations) {
|
|
1045
|
-
const registrations = [];
|
|
1046
|
-
for (const [event, groups] of Object.entries(hooks)) {
|
|
1047
|
-
for (const group of groups) {
|
|
1048
|
-
for (const hook of group.hooks || []) {
|
|
1049
|
-
if (String(hook.command || '').includes('semantic-review-authority.cjs')) registrations.push(event);
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
}
|
|
1053
|
-
assert.deepEqual(registrations, ['SubagentStop']);
|
|
1054
|
-
}
|
|
1055
|
-
});
|
|
1056
|
-
|
|
1057
1021
|
test('Codex canonical receipt provenance requires both Base and Head', () => {
|
|
1058
1022
|
const receipt = require(path.join(CODEX_HOOKS, 'lib', 'spec-receipt.cjs'));
|
|
1059
1023
|
const onlyBase = receipt.validateCanonicalReceipt('Verification: PASS\nCommand: pnpm test\nExit: 0\nBase: abc\n');
|
|
@@ -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
|
};
|
|
@@ -558,7 +558,7 @@ function authoringProjectionIssues(files) {
|
|
|
558
558
|
|| !files.templates.includes('task-NN-<slug>.md')) {
|
|
559
559
|
issues.push('flat-layout-template');
|
|
560
560
|
}
|
|
561
|
-
for (const gate of ['
|
|
561
|
+
for (const gate of ['GATE-SCOPE', 'GATE-REVIEW', 'GATE-DONE']) {
|
|
562
562
|
if (!files.skill.includes(gate)) issues.push(`human-gate-${gate.slice(0, 2).toLowerCase()}`);
|
|
563
563
|
}
|
|
564
564
|
if (!files.review.includes('fresh-context red team')
|
|
@@ -596,7 +596,7 @@ function authoringProjectionIssues(files) {
|
|
|
596
596
|
}
|
|
597
597
|
if (!files.codex.includes('flat `task-NN-*.md` files')
|
|
598
598
|
|| !files.codex.includes('inline `## Receipt`')
|
|
599
|
-
|| !files.codex.includes('
|
|
599
|
+
|| !files.codex.includes('GATE-SCOPE') || !files.codex.includes('GATE-REVIEW') || !files.codex.includes('GATE-DONE')) {
|
|
600
600
|
issues.push('codex-process-v3');
|
|
601
601
|
}
|
|
602
602
|
return [...new Set(issues)].sort();
|
|
@@ -1203,8 +1203,8 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
|
|
|
1203
1203
|
name: 'fresh-original-counterexample-replay',
|
|
1204
1204
|
issue: 'repair-closure',
|
|
1205
1205
|
relative: 'references/review.md',
|
|
1206
|
-
from: 'After applying an accepted
|
|
1207
|
-
to: 'After applying an accepted
|
|
1206
|
+
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:',
|
|
1207
|
+
to: 'After applying an accepted GATE-REVIEW finding, record the repair under this review-log header:'
|
|
1208
1208
|
},
|
|
1209
1209
|
{
|
|
1210
1210
|
name: 'distinct-repair-and-proof-evidence',
|
|
@@ -1313,7 +1313,7 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
|
|
|
1313
1313
|
['stale-profile-after-c2', 'templates', ADAPTIVE_COVERAGE_CLAUSES.profileRederivation,
|
|
1314
1314
|
'Keep existing coverage rows after accepted plan changes.', ['profile-lifecycle']],
|
|
1315
1315
|
['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`/
|
|
1316
|
+
'`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
1317
|
['source-promotes-live', 'templates', ADAPTIVE_COVERAGE_CLAUSES.proofSeparation,
|
|
1318
1318
|
'Source proof may promote installed and live proof.', ['proof-lifecycle']],
|
|
1319
1319
|
['unmapped-proof-level', 'templates', IMPLEMENTATION_READINESS_CLAUSES.proofLevelMapping,
|
|
@@ -1327,7 +1327,7 @@ function assertInstalledAuthoringProjection(root, installedRoot) {
|
|
|
1327
1327
|
['spec-maker-examples-decide', 'specMaker', ADAPTIVE_COVERAGE_CLAUSES.specMakerAmbiguity,
|
|
1328
1328
|
'Use examples to settle every ambiguous observable behavior.', ['spec-maker-authority']],
|
|
1329
1329
|
['spec-maker-skips-brainstorm', 'specMaker', ADAPTIVE_COVERAGE_CLAUSES.specMakerRoute,
|
|
1330
|
-
'Apply the risk-first route before
|
|
1330
|
+
'Apply the risk-first route before GATE-SCOPE and stop only for direct work.', ['spec-maker-authority']],
|
|
1331
1331
|
['static-proves-live', 'skill', ADAPTIVE_COVERAGE_CLAUSES.liveLimit,
|
|
1332
1332
|
'Source/static checks prove live-model adherence.', ['proof-lifecycle']]
|
|
1333
1333
|
];
|
|
@@ -1561,13 +1561,15 @@ test('Codex structured-input corpus oracle stays differential and production-awa
|
|
|
1561
1561
|
'src/claude/agents/spec-maker.md',
|
|
1562
1562
|
'src/claude/hooks/session.cjs',
|
|
1563
1563
|
'src/claude/skills/git/SKILL.md',
|
|
1564
|
-
'src/claude/skills/
|
|
1564
|
+
'src/claude/skills/scout/SKILL.md',
|
|
1565
|
+
'src/claude/skills/sync/references/rebind-and-audit.md'
|
|
1565
1566
|
];
|
|
1566
1567
|
assert.deepEqual(actualPaths, expectedPaths, 'every source occurrence needs an explicit projection oracle');
|
|
1567
1568
|
|
|
1568
1569
|
const instructionExpectedSnippets = new Map([
|
|
1569
1570
|
['src/claude/skills/git/SKILL.md', 'Present options via a structured user-input request — header'],
|
|
1570
|
-
['src/claude/skills/
|
|
1571
|
+
['src/claude/skills/scout/SKILL.md', '**Fallback to a structured user-input request:**'],
|
|
1572
|
+
['src/claude/skills/sync/references/rebind-and-audit.md', 'End by asking with a structured user-input request when the host has']
|
|
1571
1573
|
]);
|
|
1572
1574
|
for (const [relativePath, expectedSnippet] of instructionExpectedSnippets) {
|
|
1573
1575
|
const sourcePath = path.join(PACKAGE_ROOT, relativePath);
|
|
@@ -1983,8 +1985,7 @@ test('Codex Windows hook launchers stay project-bound without Git from nested cw
|
|
|
1983
1985
|
);
|
|
1984
1986
|
const launchers = allHookLaunchers(config);
|
|
1985
1987
|
assert.ok(launchers.length > 0, 'installed Codex config must register hook launchers');
|
|
1986
|
-
const
|
|
1987
|
-
for (const { event, handler } of launchers) {
|
|
1988
|
+
for (const { handler } of launchers) {
|
|
1988
1989
|
assert.doesNotMatch(handler.commandWindows, /\$\(/);
|
|
1989
1990
|
assert.doesNotMatch(handler.commandWindows, /\bgit\b/i);
|
|
1990
1991
|
assert.doesNotMatch(handler.commandWindows, /process\.cwd\(\)|existsSync/);
|
|
@@ -1997,11 +1998,7 @@ test('Codex Windows hook launchers stay project-bound without Git from nested cw
|
|
|
1997
1998
|
true,
|
|
1998
1999
|
`missing installed hook: ${path.basename(target)}`
|
|
1999
2000
|
);
|
|
2000
|
-
if (path.basename(target) === 'semantic-review-authority.cjs') {
|
|
2001
|
-
semanticReviewEvents.push(event);
|
|
2002
|
-
}
|
|
2003
2001
|
}
|
|
2004
|
-
assert.deepEqual(semanticReviewEvents, ['SubagentStop']);
|
|
2005
2002
|
|
|
2006
2003
|
const nested = path.join(projectRoot, 'nested', 'workspace');
|
|
2007
2004
|
fs.mkdirSync(nested, { recursive: true });
|
|
@@ -2260,24 +2257,24 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2260
2257
|
assert.ok(skillNames.every((name) => /^[a-z0-9-]+$/.test(name)));
|
|
2261
2258
|
|
|
2262
2259
|
const scoutSkill = fs.readFileSync(
|
|
2263
|
-
path.join(root, '.agents', 'skills', '
|
|
2260
|
+
path.join(root, '.agents', 'skills', 'scout', 'SKILL.md'),
|
|
2264
2261
|
'utf8'
|
|
2265
2262
|
);
|
|
2266
2263
|
assert.match(scoutSkill, /^name:\s*cf-scout$/m);
|
|
2267
2264
|
assert.equal(
|
|
2268
|
-
fs.existsSync(path.join(root, '.agents', 'skills', '
|
|
2265
|
+
fs.existsSync(path.join(root, '.agents', 'skills', 'inspect')),
|
|
2269
2266
|
false,
|
|
2270
|
-
'
|
|
2267
|
+
'Scout lives in the scout directory; the retired inspect directory must not be installed'
|
|
2271
2268
|
);
|
|
2272
2269
|
const askSkill = fs.readFileSync(
|
|
2273
|
-
path.join(root, '.agents', 'skills', '
|
|
2270
|
+
path.join(root, '.agents', 'skills', 'ask', 'SKILL.md'),
|
|
2274
2271
|
'utf8'
|
|
2275
2272
|
);
|
|
2276
2273
|
assert.match(askSkill, /^name:\s*cf-ask$/m);
|
|
2277
2274
|
assert.equal(
|
|
2278
|
-
fs.existsSync(path.join(root, '.agents', 'skills', '
|
|
2275
|
+
fs.existsSync(path.join(root, '.agents', 'skills', 'question')),
|
|
2279
2276
|
false,
|
|
2280
|
-
'
|
|
2277
|
+
'Ask lives in the ask directory; the retired question directory must not be installed'
|
|
2281
2278
|
);
|
|
2282
2279
|
|
|
2283
2280
|
const catalog = spawnSync(
|
|
@@ -2338,7 +2335,7 @@ test('Codex installed Specs and spec-maker reject adaptive coverage mutations',
|
|
|
2338
2335
|
(key.startsWith('.codex/') || key.startsWith('.agents/')) && !key.includes('../')
|
|
2339
2336
|
)));
|
|
2340
2337
|
|
|
2341
|
-
const questionSkill = path.join(root, '.agents', 'skills', '
|
|
2338
|
+
const questionSkill = path.join(root, '.agents', 'skills', 'ask', 'SKILL.md');
|
|
2342
2339
|
fs.appendFileSync(questionSkill, '\nUSER-CODEX-SENTINEL\n');
|
|
2343
2340
|
// Fresh installs are exact. Refresh/upgrade intentionally documents the
|
|
2344
2341
|
// current Codex limitation: removed skill paths are not pruned.
|
|
@@ -2426,7 +2423,7 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
|
|
|
2426
2423
|
const mutations = [
|
|
2427
2424
|
{
|
|
2428
2425
|
name: 'adaptive-direct-precedence-removed', source: 'skill',
|
|
2429
|
-
from: 'Route Direct first, then
|
|
2426
|
+
from: 'Route Direct first, then apply controls only to requests that remain in Brainstorm.',
|
|
2430
2427
|
to: 'Apply controls before Direct classification.', expected: ['adaptive-direct-precedence']
|
|
2431
2428
|
},
|
|
2432
2429
|
{
|
|
@@ -2441,37 +2438,37 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
|
|
|
2441
2438
|
},
|
|
2442
2439
|
{
|
|
2443
2440
|
name: 'adaptive-failure-isolation-removed', source: 'skill',
|
|
2444
|
-
from: 'failure isolation for partial or cascading failure
|
|
2441
|
+
from: 'failure isolation for partial or cascading failure across boundaries',
|
|
2445
2442
|
to: 'generic failure notes', expected: ['adaptive-lens-trigger-skip']
|
|
2446
2443
|
},
|
|
2447
2444
|
{
|
|
2448
2445
|
name: 'adaptive-evidence-fallback-removed', source: 'skill',
|
|
2449
|
-
from: 'Missing evidence
|
|
2446
|
+
from: 'Missing evidence forces feasibility `unknown` and confidence `low`.',
|
|
2450
2447
|
to: 'Missing evidence permits a confident guess.', expected: ['adaptive-evidence-semantics']
|
|
2451
2448
|
},
|
|
2452
2449
|
{
|
|
2453
2450
|
name: 'adaptive-numeric-evidence-removed', source: 'skill',
|
|
2454
|
-
from: 'A numeric estimate requires
|
|
2451
|
+
from: 'A numeric estimate requires range, unit, basis, evidence, and assumptions; otherwise report `unknown`.',
|
|
2455
2452
|
to: 'A numeric estimate may be a best-effort number.', expected: ['adaptive-numeric-estimates']
|
|
2456
2453
|
},
|
|
2457
2454
|
{
|
|
2458
2455
|
name: 'adaptive-pre-tool-redaction-removed', source: 'skill',
|
|
2459
|
-
from: 'Before an
|
|
2456
|
+
from: 'Before an external visual tool or adviser handoff, minimize context and redact secrets, credentials, private keys, access tokens, and unnecessary PII.',
|
|
2460
2457
|
to: 'Forward full context to every external tool and adviser.', expected: ['adaptive-pre-tool-redaction']
|
|
2461
2458
|
},
|
|
2462
2459
|
{
|
|
2463
2460
|
name: 'adaptive-adviser-gate-removed', source: 'skill',
|
|
2464
|
-
from: '`--advice` invokes
|
|
2461
|
+
from: '`--advice` invokes `brainstormer` only after the material-choice gate;',
|
|
2465
2462
|
to: '`--advice` invokes `brainstormer` before routing;', expected: ['adaptive-adviser-gate']
|
|
2466
2463
|
},
|
|
2467
2464
|
{
|
|
2468
2465
|
name: 'adaptive-decision-freshness-removed', source: 'skill',
|
|
2469
|
-
from: 'The first section records target
|
|
2466
|
+
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
2467
|
to: 'The handoff has no revision or freshness binding.', expected: ['adaptive-decision-freshness']
|
|
2471
2468
|
},
|
|
2472
2469
|
{
|
|
2473
2470
|
name: 'adaptive-overlay-authority-removed', source: 'skill',
|
|
2474
|
-
from: 'Neither overlay
|
|
2471
|
+
from: 'Neither overlay writes, approves, persists, dispatches, or completes work.',
|
|
2475
2472
|
to: 'Overlays may persist, approve, dispatch, and complete work.', expected: ['adaptive-non-authority']
|
|
2476
2473
|
},
|
|
2477
2474
|
{
|
|
@@ -2491,7 +2488,7 @@ test('Codex installed Brainstorm skill reference and agent preserve proportional
|
|
|
2491
2488
|
{
|
|
2492
2489
|
name: 'exploration-stop-removed',
|
|
2493
2490
|
source: 'skill',
|
|
2494
|
-
from: 'Do not request design approval, persist a report, or
|
|
2491
|
+
from: 'Do not request design approval, persist a report, or invoke another workflow without a new explicit request.',
|
|
2495
2492
|
to: 'Request approval, persist a report, and invoke another workflow.',
|
|
2496
2493
|
expected: ['exploration-stop']
|
|
2497
2494
|
},
|
|
@@ -2841,7 +2838,7 @@ function hotfixProjectionIssues(files) {
|
|
|
2841
2838
|
}
|
|
2842
2839
|
if (!parallel.includes('Diagnosis still starts only')
|
|
2843
2840
|
|| !parallel.includes('after the required scout outputs are synthesized')
|
|
2844
|
-
|| !parallel.includes('Research begins only after
|
|
2841
|
+
|| !parallel.includes('Research begins only after diagnosis')
|
|
2845
2842
|
|| parallel.includes('scout + diagnose + research together')
|
|
2846
2843
|
|| parallel.includes("You don't need to wait for scouting")) {
|
|
2847
2844
|
issues.add('scout-before-diagnosis');
|
|
@@ -2858,9 +2855,9 @@ test('Codex installed Fix preserves the adaptive repair contract', () => {
|
|
|
2858
2855
|
const result = install(root);
|
|
2859
2856
|
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
|
|
2860
2857
|
|
|
2861
|
-
const installedRoot = path.join(root, '.agents/skills/
|
|
2862
|
-
assert.equal(fs.existsSync(path.join(root, '.agents/skills/
|
|
2863
|
-
'
|
|
2858
|
+
const installedRoot = path.join(root, '.agents/skills/fix');
|
|
2859
|
+
assert.equal(fs.existsSync(path.join(root, '.agents/skills/hotfix')), false,
|
|
2860
|
+
'Fix lives in the fix directory; the retired hotfix directory must not be installed');
|
|
2864
2861
|
for (const relative of HOTFIX_BUNDLE) {
|
|
2865
2862
|
const sourcePath = path.join(HOTFIX_SOURCE_ROOT, relative);
|
|
2866
2863
|
assert.equal(
|
|
@@ -2952,7 +2949,7 @@ test('Codex installed Fix preserves the adaptive repair contract', () => {
|
|
|
2952
2949
|
},
|
|
2953
2950
|
{
|
|
2954
2951
|
name: 'research-starts-before-diagnosis', file: 'references/parallel-patterns.md',
|
|
2955
|
-
from: 'Research begins only after
|
|
2952
|
+
from: 'Research begins only after diagnosis', to: 'Research may begin before diagnosis',
|
|
2956
2953
|
expected: ['scout-before-diagnosis']
|
|
2957
2954
|
}
|
|
2958
2955
|
];
|
|
@@ -3162,16 +3159,14 @@ test('Codex install on top of existing Claude installation preserves content and
|
|
|
3162
3159
|
});
|
|
3163
3160
|
});
|
|
3164
3161
|
|
|
3165
|
-
test('Codex installed code_auditor
|
|
3162
|
+
test('Codex installed code_auditor carries no Strict attestation marker', () => {
|
|
3166
3163
|
inTempProject((root) => {
|
|
3167
3164
|
const result = install(root);
|
|
3168
3165
|
assert.equal(result.status, 0, `${result.stdout}\n${result.stderr}`);
|
|
3169
3166
|
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/);
|
|
3167
|
+
assert.doesNotMatch(toml, /CAFEKIT_SEMANTIC_REVIEW_ATTESTATION/);
|
|
3168
|
+
assert.doesNotMatch(toml, /Strict Semantic Review Attestation/);
|
|
3169
|
+
assert.doesNotMatch(toml, /MAC-protected host-hook observation/);
|
|
3175
3170
|
});
|
|
3176
3171
|
});
|
|
3177
3172
|
|
|
@@ -3195,26 +3190,14 @@ test('Codex scaffold resolver rejects symlink template', () => {
|
|
|
3195
3190
|
});
|
|
3196
3191
|
});
|
|
3197
3192
|
|
|
3198
|
-
test('Claude and Codex installed
|
|
3193
|
+
test('Claude and Codex installed routing rules preserve the live-catalog semantics and install no Route', () => {
|
|
3199
3194
|
inTempProject((root) => {
|
|
3200
3195
|
const result = installPlatforms(root, ['claude', 'codex']);
|
|
3201
3196
|
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
3197
|
const expectedRules = ['skill-workflow-routing.md', 'skill-domain-routing.md'];
|
|
3208
3198
|
for (const runtime of ['claude', 'codex']) {
|
|
3209
3199
|
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
|
-
}
|
|
3200
|
+
assert.equal(fs.existsSync(installedRoot), false, `${runtime} still installs Route`);
|
|
3218
3201
|
for (const relative of expectedRules) {
|
|
3219
3202
|
const sourcePath = path.join(PACKAGE_ROOT, 'src/claude/rules', relative);
|
|
3220
3203
|
const source = fs.readFileSync(sourcePath, 'utf8');
|
|
@@ -3224,12 +3207,8 @@ test('Claude and Codex installed Route preserve proportional live-catalog semant
|
|
|
3224
3207
|
const expected = runtime === 'codex' ? normalizeCodexBody(source, sourcePath) : source;
|
|
3225
3208
|
assert.equal(installed, expected, `${runtime}:rules/${relative}`);
|
|
3226
3209
|
}
|
|
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
3210
|
const catalog = installedCatalog(root, runtime);
|
|
3232
|
-
assert.
|
|
3211
|
+
assert.equal(catalog.skills.some((skill) => skill.public_id === 'cf:route'), false);
|
|
3233
3212
|
assert.equal(catalog.skills.some((skill) => skill.public_id === 'cf:docs'), false);
|
|
3234
3213
|
}
|
|
3235
3214
|
});
|
|
@@ -3304,24 +3283,3 @@ test('Claude and Codex installed rules preserve the ported review and process gu
|
|
|
3304
3283
|
});
|
|
3305
3284
|
});
|
|
3306
3285
|
|
|
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
|
-
});
|