Files
oh-my-pi/packages/catalog/test/issue-3067-repro.test.ts
T
roboomp 47cc464962 fix(catalog): retired stale Claude 4.6 wire ids and healed the bundled Sonnet route
Follow-up to #3071 review (codex + @PGupta-Git): the family rewrite alone
did not heal users running off the bundled catalog or stale SQLite cache
rows, which still routed Sonnet 4.6 thinking efforts to the 404
`claude-sonnet-4-6-thinking` wire id. `collapseEffortVariants` treats
those collapsed snapshots as authoritative and `refreshCollapsedThinking`
exits early for families without `effortBudgets` (Claude pairs), so the
new empty routing in the hand table never reached the snapshot.

- Declared the dead wire ids as `retiredMembers` on the Claude 4.6
  families (`claude-sonnet-4-6-thinking` on the Sonnet family,
  `claude-opus-4-6` on the Opus family). This triggers
  `reconcileRetiredRouting` to rewrite every `effortRouting` entry that
  targets a retired id to a live wire id (Sonnet falls back to the bare
  member; Opus falls back to `-thinking`).
- Refreshed the bundled `packages/catalog/src/models.json` Sonnet 4.6
  entry so fresh installs do not boot with the dangling routing — the
  surgical diff matches what the generator would emit; the rest of the
  catalog is left untouched to keep the bug-fix PR scoped.
- Added regression tests in `variant-collapse.test.ts` for both
  reconciliation paths and a bundled-catalog test
  (`issue-3067-repro.test.ts`) that pins the live-wire-id resolution end
  to end through `buildModel` for every effort tier.

Fixes #3067
2026-06-19 22:25:48 +02:00

36 lines
1.7 KiB
TypeScript

import { describe, expect, it } from "bun:test";
import { buildModel } from "@oh-my-pi/pi-catalog/build";
import { Effort } from "@oh-my-pi/pi-catalog/effort";
import { resolveWireModelId } from "@oh-my-pi/pi-catalog/model-thinking";
import type { ModelSpec } from "@oh-my-pi/pi-catalog/types";
import modelsJson from "../src/models.json";
describe("issue #3067 — bundled Antigravity Claude 4.6 wire-id routing", () => {
const antigravity = modelsJson["google-antigravity"] as Record<string, ModelSpec<"google-gemini-cli">>;
it("never bundles the dead `claude-sonnet-4-6-thinking` wire id as a Sonnet routing target", () => {
const sonnet = antigravity["claude-sonnet-4-6"];
expect(sonnet).toBeDefined();
const routing = sonnet?.thinking?.effortRouting;
if (routing !== undefined) {
for (const key in routing) {
expect(routing[key as keyof typeof routing]).not.toBe("claude-sonnet-4-6-thinking");
}
}
// Resolving through buildModel must land on a live wire id for every effort.
const model = buildModel(sonnet as ModelSpec<"google-gemini-cli">);
for (const effort of [undefined, Effort.Minimal, Effort.Low, Effort.Medium, Effort.High] as const) {
expect(resolveWireModelId(model, effort)).toBe("claude-sonnet-4-6");
}
});
it("routes the bundled Opus 4.6 to the live `claude-opus-4-6-thinking` wire id for every effort", () => {
const opus = antigravity["claude-opus-4-6"];
expect(opus).toBeDefined();
const model = buildModel(opus as ModelSpec<"google-gemini-cli">);
for (const effort of [undefined, Effort.Minimal, Effort.Low, Effort.Medium, Effort.High] as const) {
expect(resolveWireModelId(model, effort)).toBe("claude-opus-4-6-thinking");
}
});
});