Files
ccs/tests
Kenneth Wong 2b780ceae3 fix(extended-context): never write [1m] into the Fable tier key
Claude Code resolves ANTHROPIC_DEFAULT_FABLE_MODEL through a resolver that
strips the [1m] suffix before use, unlike the opus/sonnet resolvers which
pass their env value through untouched. The stripped value is then treated
as an env-supplied default and held to the standard 200k window instead of
the model's native 1M, so writing [1m] into that key costs the long context
window rather than granting it.

Measured against a Claude Code 2.1.259 session (`/context` on a live proxy
endpoint):

  ANTHROPIC_MODEL=claude-fable-5-1[1m]               -> 1m window
  ANTHROPIC_MODEL=claude-fable-5-1                   -> 200k window
  ANTHROPIC_DEFAULT_FABLE_MODEL=claude-fable-5-1[1m] -> 200k window

The fix is key-scoped rather than model-scoped, since the suffix is what
grants 1M on every other key. Adds envKeyAcceptsExtendedContextSuffix() as
the single place recording which keys reject the suffix, enforces it as a
floor inside applyExtendedContextPreferenceToAnthropicModels() so no caller
can bypass it, and strips a previously saved suffix from that key on the
next launch through the auto path.

Also extends the preference to CLAUDE_CODE_SUBAGENT_MODEL. Subagent windows
come from the same resolver as the main loop (the Explore inheritCap bounds
the model tier, not the context window), so a bare subagent model id sits at
200k while the suffixed form gets 1M. The new key list is kept separate from
ANTHROPIC_MODEL_ENV_KEYS, which also drives routing, model-id normalization
and profile validation.

Claude-Session: https://claude.ai/code/session_01NPkafQjVf4pSwPBwBistGk
2026-09-03 17:08:23 +08:00
..

CCS Test Suite

Root TypeScript and JavaScript tests run with Bun's test runner. Native shell, PowerShell, Docker, and standalone probes cover contracts that need a real platform or process boundary.

Ownership

Area Path Use for
Unit unit/ Focused module and command behavior
Integration integration/ Cross-module, process, proxy, auth, and web-server behavior
End to end e2e/ Packaged CLI workflows
npm package npm/ Installation, exports, and package behavior
Native native/ Unix and Windows shell behavior
Docker docker/ Compose and stable network/service contracts
Documentation docs/ Repository documentation invariants
Shared support shared/ Fixtures and helpers reused by suites
Mocks mocks/ Bounded test doubles and fixtures

Some source domains also keep focused tests in src/**/__tests__/. Follow the nearest established pattern and avoid moving tests solely for taxonomy.

Commands

Commands are defined in ../package.json. Bucket membership and execution live in ../scripts/run-test-bucket.js.

bun run test:fast      # Fast Bun test bucket
bun run test:slow      # Slow Bun test bucket
bun run test:all       # All root non-e2e Bun test buckets
bun run test:unit      # tests/unit
bun run test:npm       # tests/npm
bun run test:native    # Native Unix edge-case script
bun run test:e2e       # tests/e2e with fail-fast and extended timeout
bun run test           # Build, then test:all

For the normal contributor gate:

bun run format
bun run lint:fix
bun run validate

For the closest local equivalent to PR CI:

bun run validate:ci-parity

Dashboard tests use Vitest and are documented in ../ui/README.md.

Test Isolation

  • Set CCS_HOME to a temporary directory.
  • Never read or modify a contributor's real ~/.ccs/ or ~/.claude/.
  • Use getCcsDir() from ../src/utils/config-manager.ts for CCS paths.
  • Keep fixtures deterministic and free of credentials or private account data.
  • Use real behavior at the boundary under test; do not weaken assertions to hide regressions.

Adding Coverage

  • Add a focused unit test for isolated logic.
  • Add integration coverage when behavior crosses modules, processes, HTTP, or persistence boundaries.
  • Add e2e coverage when command routing or packaged CLI behavior is the contract.
  • Add native or Docker coverage only when platform/runtime behavior cannot be represented faithfully in Bun tests.
  • Run the smallest relevant command first, then broaden to the contributor or CI-parity gate when shared contracts changed.