Verification — fix-claude-config-cache
Test evidence
Gate 1 — npm run build
> colibri@0.0.1 build
> tsc
Exit code: 0. TypeScript compiled cleanly. No errors, no warnings.
Gate 2 — npm run lint
> colibri@0.0.1 lint
> eslint src
Exit code: 0. ESLint clean. No new warnings.
Gate 3 — npm test
Full Jest suite (matched against the documented baseline):
Test Suites: 30 passed, 30 total
Tests: 1360 passed, 1360 total
Snapshots: 0 total
Time: 21.232 s, estimated 31 s
Exit code: 0. All 1360 tests pass.
Pre-existing flake note
The first run of npm test hit the documented startup — subprocess
smoke › tsx src/server.ts boots and logs [Startup] Phase 1 flake (1 fail
under heavy parallel suite load). This is a pre-existing pre-Wave-H flake
documented in CLAUDE memory: “Pre-existing startup — subprocess smoke
flakiness under full-suite load — predates Wave H; all 4 R77 executors hit
it once, always green on rerun.”
Re-running the same suite immediately produced 30/30 suites + 1360/1360 tests green, confirming the flake is not introduced by this change.
Targeted test counts
claude.test.ts alone:
Test Suites: 1 passed, 1 total
Tests: 44 passed, 44 total
Pre-change baseline was 41 tests; +3 new tests = 44, confirming all three new test cases are wired and passing.
New test detail
PASS src/__tests__/domains/integrations/claude.test.ts
default-model resolution from config
✓ createCompletion uses config.COLIBRI_ANTHROPIC_MODEL when options.model is omitted
✓ createCompletion: injected options.model overrides the config default
✓ createCompletionWithTools uses config.COLIBRI_ANTHROPIC_MODEL when options.model is omitted
Each test asserts the request body’s model field against
config.COLIBRI_ANTHROPIC_MODEL (the frozen-singleton import) plus a
literal 'claude-sonnet-4-5' regression guard for the schema default.
The override test asserts:
body.model === overrideModel— the override wins.body.model !== config.COLIBRI_ANTHROPIC_MODEL— explicit regression guard against a future regression where overrides are silently swallowed.
Source diff summary
src/__tests__/domains/integrations/claude.test.ts | 67 +++++++++++++++++++++++
src/domains/integrations/claude.ts | 27 +++------
2 files changed, 74 insertions(+), 20 deletions(-)
src/domains/integrations/claude.ts:
- Net: −13 LOC (20 deletions, 7 additions). Two try/catch blocks (~10 LOC
each) are gone. Hardcoded fallback literals are gone. The import was
swapped (no LOC delta on imports). Replaced with a single
options.model ?? config.COLIBRI_ANTHROPIC_MODELline per entry point plus a clarifying comment block on the first occurrence.
src/__tests__/domains/integrations/claude.test.ts:
- +67 LOC (one new
describeblock with three tests + one new static import line). No existing tests modified.
Acceptance criteria — final check
| AC | Status | Evidence |
|---|---|---|
1. Replace try/catch+fallback with direct import from src/config.ts |
✅ | Diff shows import { config } from '../../config.js'; both try/catches deleted |
2. Preserve apiKey, model, timeoutMs injection seams |
✅ | CompletionOptions interface unchanged; all 41 prior tests still pass with explicit model: FAKE_MODEL injection |
3. Preserve AnthropicConfigError semantics for missing ANTHROPIC_API_KEY |
✅ | Lines 337–342 + 372–378 of claude.ts unchanged; test block “API key validation” (lines 309–365) still passes |
4. Singleton handles call-time validation; config.ANTHROPIC_API_KEY is string \| undefined |
✅ | apiKey resolution path on process.env['ANTHROPIC_API_KEY'] preserved exactly — same call-time semantics |
5. New tests verify model defaults match config.COLIBRI_ANTHROPIC_MODEL and override precedence |
✅ | 3 new tests in default-model resolution from config describe block, all green |
| 6. All gates pass: build + lint + test | ✅ | All three exit 0; 1360/1360 tests pass |
Risk re-check
| Risk from audit | Outcome |
|---|---|
| Singleton evaluated at module load | Confirmed working — config loads cleanly under jest’s NODE_ENV=test and all 1360 tests pass |
| Test injection seam regression | Zero existing tests modified; all 41 prior claude.test.ts tests still pass |
process.env mutation between calls no longer reflected |
Not load-bearing — verified in audit; no test broke |
| Silent-fallback path was load-bearing | Confirmed not load-bearing — full suite green |
Commit chain
| Step | SHA | Title |
|---|---|---|
| 1. Audit | 0fd22e83 |
audit(fix-claude-config-cache): inventory surface |
| 2. Contract | 0bc19a39 |
contract(fix-claude-config-cache): behavioral contract |
| 3. Packet | 84011471 |
packet(fix-claude-config-cache): execution plan |
| 4. Implement | f3a7830a |
feat(fix-claude-config-cache): swap loadConfig try/catch for config singleton |
| 5. Verify | (this commit) | verify(fix-claude-config-cache): test evidence |
Writeback summary
task_id: fix-claude-config-cache
branch: feature/fix-claude-config-cache
worktree: .worktrees/claude/fix-claude-config-cache
commits: 0fd22e83, 0bc19a39, 84011471, f3a7830a, (verify)
tests: npm run build && npm run lint && npm test
summary: Replaced per-call loadConfig() try/catch+hardcoded fallback in
src/domains/integrations/claude.ts with direct read from the frozen
config singleton. Added 3 tests for default-model resolution and
override precedence. Net -13 source LOC, +67 test LOC. All gates pass:
build clean, lint clean, 1360/1360 tests green.
blockers: none. Pre-existing 'startup — subprocess smoke' flake observed
on first run; documented in CLAUDE memory; clean on rerun.