fix(pricing): resolve fable/mythos canary variants via fuzzy match - #188
Merged
Conversation
claude-auto-pilot-fable-v1-canary and claude-mythos-*-canary model ids wrap the pinned claude-fable-5/claude-mythos-5 names with extra prefix/suffix segments (auto-pilot-, -v1-canary), so "fable"/"mythos" is not a contiguous substring of the curated exact key. Every non-fuzzy resolution tier in matcher.js requires a contiguous substring match, so these ids fell through to miss and billed $0 — the dashboard hid the cost column entirely (formatCost() returns null for cost <= 0). Add curated fuzzy rules for "fable" and "mythos", matching the existing kiro/hy3/composer fuzzy pattern. Fixes#187
To use Codex here, create a Codex account and connect to github. |
Uh oh!
There was an error while loading. Please reload this page.
pitimon added a commit
that referenced
this pull request
Aug 22, 2026
This was referenced Aug 22, 2026
Open
pitimon added a commit
that referenced
this pull request
Aug 22, 2026
…closure (#194) Two follow-ups from the #187/#188 cross-verification review. 1. matcher.js: add a scoped denoise retry (issue #193). #188 fixed the fable/mythos canary regression with a per-name curated fuzzy rule, but left the structural gap open — any future auto-pilot/canary rename of an already-priced model would reproduce the same bug and require another one-line patch. The denoise retry strips the '-auto-pilot-' infix and trailing '-vN-canary'/'-canary' suffix and retries the full lookup ladder exactly once, only after every other tier has missed on the raw id, so a genuine exact match on the raw id (however unlikely) is never shadowed. Also narrows the #188 fuzzy rules from bare 'fable'/'mythos' substrings to 'claude-fable'/'claude-mythos'. Verified against the published pricing seed that a real collision risk existed: claude-mythos-preview is a genuine LiteLLM-priced model that happens to contain the substring 'mythos' — the bare rule would have silently mispriced any future model in the same shape that lacks its own exact LiteLLM/curated entry. 2. dashboard: wire the already-computed fuzzyPricingModels (from model-breakdown.ts) into ProviderBreakdownCard (issue #192). The provider card already discloses '{{count}} pricing missing' for unpriced models; it now also discloses '{{count}} pricing estimated' when any model resolved via substring/fuzzy match rather than an exact price, so a user sees when a total like $3,164.69 is a curated estimate, not a reconciled invoice figure. Verified: node --test test/pricing.test.js (39/39), dashboard ProviderBreakdownCard suite (10/10, incl. 2 new), npm run ci:local full gate (dashboard 320/320, product suite 1059/1059, all validators) — all green. Addresses #193, #192. Co-authored-by: itarun.p <itarun.p@somapait.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR Goal (one sentence)
Add curated fuzzy pricing rules so Claude Fable/Mythos canary model ids (e.g.
claude-auto-pilot-fable-v1-canary) resolve to their pinned price instead of silently billing $0.Scope
src/)dashboard/)Checklist
npm run ci:localpasses, or focused test commands are listed below with rationaledashboard/src/content/copy.csv(N/A — no new strings)feat:/fix:/refactor:/docs:/chore:/test:/ci:)package.json,package-lock.json) — deferred to a follow-up publish PR per CLAUDE.md release workflowWhy
src/lib/pricing/matcher.jsresolves pricing through 7 tiers, and every tier (including the reverse-substring fuzzy fallback) requires the queue model id to contain the known price key as a contiguous substring.claude-auto-pilot-fable-v1-canarydoes not containclaude-fable-5contiguously (-auto-pilot-interrupts it, and it ends in-v1-canaryinstead of-5), so it fell through every tier tomiss→computeRowCost()returned 0 → the dashboardsformatCost()returnsnullfor cost <= 0, hiding theThis is the same class of gap that #7 fixed for the literal
claude-fable-5/claude-mythos-5ids, but that fix does not cover vendor-renamed canary variants that wrap the name with extra segments.Fixes#187.
Fix
Two curated fuzzy rules added to
src/lib/pricing/curated-overrides.json, matching the existingkiro/hy3/composerfuzzy pattern:{ "match": "fable", "ref": "claude-fable-5" }, { "match": "mythos", "ref": "claude-mythos-5" },Codex Context (required when requesting @codex review)
fableormythos(case-insensitive) resolves viacurated:fuzzyto the pinned Fable 5 / Mythos 5 price. Curated exact match and LiteLLM exact/dot match still take priority over this fuzzy rule per the existing resolve order.claude-auto-pilot-fable-v1-canary,claude-mythos-v1-canary(regression test added); existingclaude-fable-5/claude-mythos-5exact ids continue to resolve viacurated:exact(higher-priority tier, unaffected).node --test test/pricing.test.js→ 34/34 pass (includes new regression case)NODE_ENV=test npm run ci:local→ full gate pass (dashboard build, dashboard tests 318/318, product suite 1054+38, copy/UI-hardcode/architecture-guardrail/curated-expiry/outbound/openwiki validators)Risk Layer Trigger (if any)
(No risk-layer trigger — pure pricing-lookup data change, no I/O/auth/exposure surface touched.)
Regression Test Gate
Most likely regression surface
fable/mythosfuzzy rules if their ids happen to contain those substrings.Verification method (choose at least one)
test/pricing.test.jssuite re-run (34/34 pass, no existing case regressed) plus new regression assertions for the two canary ids from issue Claude auto-pilot/canary model ids (fable/mythos) bill $0 — fuzzy pricing match misses non-contiguous substrings #187.Uncovered scope