review-provider classify(): missing/corrupt model-hints.json silently disables the non-text-model exclude filter #43

Closed
opened 2026-07-23 14:43:48 +00:00 by crenshawdev · 0 comments
crenshawdev commented 2026-07-23 14:43:48 +00:00 (Migrated from github.com)

Severity: medium · Area: review · surfaced in the post-v1.2.0 cross-model review sweep.

What happens

classify() tags each detected provider model with a tier and filters out non-text models (embeddings, audio, image) that cannot do text review, using the shipped references/model-hints.json. If that file is missing or malformed, the load is swallowed and defaults to rules=[], exclude=[] — byte-indistinguishable from a valid hints file that legitimately has no rules for the provider. Two silent degradations result:

  1. Every detected model comes back tier:null (all "unknown").
  2. The exclude filter that keeps non-text modalities out is off, so embedding/audio/image model IDs pass through as review candidates and can be assigned to a review tier in /cad-config — failing only later, at call time, with a confusing error.

Nothing in the {ok:true, models:[...]} output signals the hints file failed to load, so the operator cannot tell "hints broken" from "provider has no known models."

Mechanism (verified against source)

cadence-core/bin/review-provider.mjs:519-524:

try {
  const hints = JSON.parse(readFileSync(hintsFile || <shipped path>, 'utf8'));
  rules = (hints.rules && hints.rules[provider]) || [];
  exclude = hints.exclude || [];
} catch { /* no hints -> everything unknown, nothing excluded */ }

The catch turns a load failure into the same empty state as a present-but-ruleless file, and the empty exclude disables the non-text filter at :524.

Fix direction

Distinguish "hints file present and empty" from "hints file failed to load." On a genuine load/parse failure of the shipped file, surface it (a warning, or a flag on the result) rather than silently emptying both rules and exclude. Same benign-default-on-parse-error pattern as #39.

**Severity:** medium · **Area:** review · surfaced in the post-v1.2.0 cross-model review sweep. ## What happens `classify()` tags each detected provider model with a tier and filters out non-text models (embeddings, audio, image) that cannot do text review, using the shipped `references/model-hints.json`. If that file is missing or malformed, the load is swallowed and defaults to `rules=[]`, `exclude=[]` — byte-indistinguishable from a valid hints file that legitimately has no rules for the provider. Two silent degradations result: 1. Every detected model comes back `tier:null` (all "unknown"). 2. The `exclude` filter that keeps non-text modalities out is off, so embedding/audio/image model IDs pass through as review candidates and can be assigned to a review tier in `/cad-config` — failing only later, at call time, with a confusing error. Nothing in the `{ok:true, models:[...]}` output signals the hints file failed to load, so the operator cannot tell "hints broken" from "provider has no known models." ## Mechanism (verified against source) `cadence-core/bin/review-provider.mjs:519-524`: ```js try { const hints = JSON.parse(readFileSync(hintsFile || <shipped path>, 'utf8')); rules = (hints.rules && hints.rules[provider]) || []; exclude = hints.exclude || []; } catch { /* no hints -> everything unknown, nothing excluded */ } ``` The catch turns a load failure into the same empty state as a present-but-ruleless file, and the empty `exclude` disables the non-text filter at `:524`. ## Fix direction Distinguish "hints file present and empty" from "hints file failed to load." On a genuine load/parse failure of the shipped file, surface it (a warning, or a flag on the result) rather than silently emptying both `rules` and `exclude`. Same benign-default-on-parse-error pattern as #39.
Sign in to join this conversation.
No description provided.