Skip to content

Intelligence Rollout — Flags, Defaults & Reversibility

How NanaSelect ships its three AI-model swaps under a feature-flagged, reversible rollout where the deterministic path is the standing fallback — not dead code (issue #1193, part of capability #1185). Each swap is independently flag-toggled; on a flag being off, a model error, a timeout, or budget exhaustion, the pipeline degrades to the deterministic path with no buyer-facing hang and no blocked enrichment. It enforces the quality thresholds (#1192), spends under budget governance (#1191), and respects the egress posture (#1190).

The one-line version: every swap ships OFF; it flips on only after it clears its #1192 go/no-go bar with Paul's approval; and flipping it off — or any request-time model failure — instantly and completely restores the deterministic behavior.

Flag inventory (AC-01)

The single source of truth is INTELLIGENCE_FLAGS in src/lib/server/intelligence-flags.ts; resolveIntelligenceFlagStates(env, egressEnabled) reports each flag's live state from the same resolvers the swaps use, so the inventory can never drift from what actually gates the code.

Where to look it up today: this inventory is code + this doc — no /admin screen renders it yet (#1581 tracks surfacing it in /admin/ai). To check live state, read the flag sources: wrangler.jsonc vars for the env-backed flags, and /admin/privacy for the media.egress_enabled toggle.

SwapFlagBackingFlipDefaultDegrade path
corpus-retrieval (#1187)CORPUS_HYBRID_RETRIEVALenv varredeployOFFlexical scoring (pre-#1187 retrieval)
visual-tags (#1188)media.egress_enabledapp_settingsinstant (admin toggle)OFFdeterministic stub analyzer (#1123), no egress
media-similarity (#1189)MEDIA_SIM_VECTORIZEenv varredeployOFFbrute-force D1 cosine (pre-#1189)
  • Independent — each swap has its own flag; turning one on/off never touches another.
  • Declared config — env flags live in wrangler.jsoncvars (also MEDIA_SIM_TOPK, CORPUS_HYBRID_W_*); the visual-tags flag is an app_settings row flipped from /admin/privacy (instant, no deploy — "flippable without a deploy where feasible", AC-01).

Defaults & the go/no-go gate (AC-02)

Every flag defaults OFF (defaultOn: false) — the conservative rollout of decision #1195. A flag is flipped on only after its swap clears its documented #1192 bar (DEFAULT_EVAL_BARS, linked from each inventory entry) and Paul authorizes it. Below the bar, or with the flag off, the deterministic path serves prod. The harness reports GO/NO-GO; a human holds the flip.

The degrade guarantee (AC-03)

The deterministic path is the standing fallback at request time, not just when a flag is off. Each swap degrades on any model failure and never hangs:

SwapDegrade triggerFalls back toSeam
corpus-retrievalflag off · no request context · empty/failed vector armlexical scoringresolveVectorBlend (try/catch → undefined)
media-similarityflag off · absent binding · index error · empty resultbrute-force cosinesimilarAssets (try/catch → rankBySimilarity)
visual-tagsflag off · no real analyzer wiredstub analyzerselectMediaAnalyzer (fail-closed)
all model callsrate-limit / transient error / budget exhaustionbounded retry → abort to partialwithModelRetry (rethrow-on-exhaustion, never loops)

Because the fallback is the original deterministic behavior, a model outage is invisible to the buyer — grounding still returns lexical matches, "assets like this" still returns brute-force neighbours, and the visual-tag pass still proposes stub tags. This is asserted holistically in src/lib/server/intelligence-rollout.spec.ts.

Reversibility (AC-04)

A flip-off is immediate and complete. The flags gate which path runs, not stored data, so turning a swap off restores its deterministic behavior with no residual state:

  • No corruption — the deterministic paths read the same D1/lexical inputs they always did; the model paths only add (Vectorize vectors, tag proposals for review), they never mutate or remove the deterministic inputs. The corpus/media D1 vectors are retained as the degrade seed (not deleted), and visual-tag proposals stay in the review queue, never live, until a human accepts them.
  • Instant where it matters — the visual-tags flag (app_settings) flips from the admin with no deploy; the env flags flip on the next deploy. Either way the next request after the flip uses the deterministic path — there is no warm-up or drain.
  • ProvenresolveIntelligenceFlagStates with everything off reports every swap deterministic; the rollout spec asserts a flip-off returns the fully-deterministic posture.

Operating the rollout

  1. Land the swap behind its flag (all three are already flag-gated, default OFF).
  2. Run its #1192 harness (corpus:eval / tag:eval / sim:eval) → GO/NO-GO.
  3. On GO and Paul's approval, flip the flag: the admin toggle for visual-tags, or set the env var + deploy for corpus-retrieval / media-similarity.
  4. To reverse at any time, flip it back off — the next request serves deterministic.

See the flag inventory for the authoritative list, and the deploy & activate runbook for the full ordered ops sequence (#1226).