diff --git a/internal/intent/flags.go b/internal/intent/flags.go index 0fc5a677..ed5a3854 100644 --- a/internal/intent/flags.go +++ b/internal/intent/flags.go @@ -59,7 +59,10 @@ func parseV2DecisionTier(raw string) V2DecisionTier { case "all": return V2TierAll default: - return V2TierQuery + // E-7: fail closed to none, aligned with intentflow.parsePlanTier's + // conservative fallback. An unrecognized value must never silently + // enable V2 query routing. + return V2TierNone } } diff --git a/internal/intent/flags_test.go b/internal/intent/flags_test.go index d5935640..90d4781d 100644 --- a/internal/intent/flags_test.go +++ b/internal/intent/flags_test.go @@ -23,6 +23,12 @@ func TestTierAllowsRisk(t *testing.T) { } } +func TestUnknownV2DecisionTierFailsClosedToNone(t *testing.T) { + if parseV2DecisionTier("definitely-not-a-tier") != V2TierNone { + t.Fatal("unknown INTENT_V2_DECISION_TIER must fail closed to none, not query") + } +} + func TestBuildV2ShadowReport_MismatchDetection(t *testing.T) { SetFeatureFlagsForTest(FeatureFlags{IntentV2Shadow: true}) defer ResetFeatureFlagsForTest()