Packet — fix-claude-config-cache

Execution plan

The change is a small surgical refactor. Do it in three edits, then add three test cases.

Edit 1 — Swap the import (src/domains/integrations/claude.ts:33)

- import { loadConfig } from '../../config.js';
+ import { config } from '../../config.js';

Edit 2 — Replace the fallback in createCompletion (lines 344–353)

Replace:

  // Resolve model: options → env → config default
  let defaultModel = 'claude-sonnet-4-5';
  try {
    const cfg = loadConfig(process.env);
    defaultModel = cfg.COLIBRI_ANTHROPIC_MODEL;
  } catch {
    // config may fail in test environments with minimal env — use hardcoded default
  }

  const model = options.model ?? defaultModel;

With:

  const model = options.model ?? config.COLIBRI_ANTHROPIC_MODEL;

Edit 3 — Replace the fallback in createCompletionWithTools (lines 385–393)

Replace:

  let defaultModel = 'claude-sonnet-4-5';
  try {
    const cfg = loadConfig(process.env);
    defaultModel = cfg.COLIBRI_ANTHROPIC_MODEL;
  } catch {
    // test env fallback
  }

  const model = options.model ?? defaultModel;

With:

  const model = options.model ?? config.COLIBRI_ANTHROPIC_MODEL;

Edit 4 — Add new test block

Inside src/__tests__/domains/integrations/claude.test.ts, append a new describe('default-model resolution from config') block before the final describe('edge cases') block. The block contains three tests:

  1. createCompletion uses config.COLIBRI_ANTHROPIC_MODEL when options.model is omitted
  2. createCompletion: injected options.model overrides the config default
  3. createCompletionWithTools uses config.COLIBRI_ANTHROPIC_MODEL when options.model is omitted

Each test imports config from '../../../config.js' and asserts the request body’s model matches the expected value.

Verification plan

After implementation:

cd .worktrees/claude/fix-claude-config-cache
npm run build
npm run lint
npm test

Expected:

  • Build: clean compile.
  • Lint: clean.
  • Tests: existing 30+ claude.test.ts tests pass + 3 new tests pass. Full suite count goes up by exactly 3.

If any test fails, investigate the failure — do not patch around it. The config singleton is loaded at module-import time using the test environment (NODE_ENV=test is set by jest), and the schema default for COLIBRI_ANTHROPIC_MODEL will resolve to 'claude-sonnet-4-5' unless the test env overrides it.

Step ordering for commits

# Step Commit prefix
1 Audit (already committed) audit(fix-claude-config-cache): inventory surface
2 Contract (already committed) contract(fix-claude-config-cache): behavioral contract
3 Packet (this file) packet(fix-claude-config-cache): execution plan
4 Implementation (single commit covering both source + tests) feat(fix-claude-config-cache): swap loadConfig try/catch for config singleton
5 Verification doc verify(fix-claude-config-cache): test evidence

Each step lands as a separate commit. The 5-step gate rule applies.

Risks and mitigations during implementation

Risk Mitigation
Edit 2 + Edit 3 are textually different (different comment lines, different surrounding whitespace) — must use distinct Edit calls or careful replace_all=false Use two separate Edit invocations with enough surrounding context to make each old_string unique.
Stripping the unused loadConfig import would break TypeScript compile if any other line references it — but a replace of the import line removes both occurrences cleanly The imports are the only loadConfig references in claude.ts. Once the two try/catch blocks are gone, loadConfig is no longer referenced.
New tests need to import config — but the test file already imports loadConfig at line 738+ via dynamic await import('../../../config.js') inside test bodies Add a static import { config } from '../../../config.js'; near the top alongside the other claude.js imports.

Out-of-scope (per dispatch packet constraints)

  • Retry logic (lines 245–315) — untouched.
  • Token accounting (parseResult lines 194–229) — untouched.
  • Response parsing — untouched.
  • AnthropicConfigError, AnthropicApiError — untouched.
  • Tool-use handling logic — untouched.
  • Config type / src/config.ts schema — untouched.
  • Public function signatures — preserved exactly.

Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.