Files
WeiCHENandCursor 24478ec383 feat(intent): Phase 5 V2 shadow gray flags and IntentPlan execution
Add env-based feature flags (intent_v2_shadow/decision, multi_intent,
workflow_intents), V1/V2 shadow diff reporting, expectation_plus_new plan
building, ranked-frame L2 conflict gate, and coordinator sequential query
plan execution with confirm-step deferral.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 02:50:21 +00:00

112 lines
2.8 KiB
Go

package intent
import (
"os"
"strings"
"sync"
)
// V2DecisionTier 灰度切换的风险档位(由低到高逐步启用 V2 路由)
type V2DecisionTier string
const (
V2TierNone V2DecisionTier = "none"
V2TierQuery V2DecisionTier = "query"
V2TierGenerate V2DecisionTier = "generate"
V2TierWriteLow V2DecisionTier = "write_low"
V2TierWriteHigh V2DecisionTier = "write_high"
V2TierAll V2DecisionTier = "all"
)
// FeatureFlags Phase 5 意图识别灰度开关(环境变量覆盖,默认保守)
type FeatureFlags struct {
IntentV2Shadow bool
IntentV2Decision bool
V2DecisionTier V2DecisionTier
WorkflowIntentsEnabled bool
MultiIntentEnabled bool
SemanticFallbackEnabled bool
}
var (
flagsMu sync.RWMutex
activeFlags = defaultFeatureFlags()
)
func defaultFeatureFlags() FeatureFlags {
return FeatureFlags{
IntentV2Shadow: envBool("INTENT_V2_SHADOW", false),
IntentV2Decision: envBool("INTENT_V2_DECISION", false),
V2DecisionTier: parseV2DecisionTier(os.Getenv("INTENT_V2_DECISION_TIER")),
WorkflowIntentsEnabled: envBool("WORKFLOW_INTENTS_ENABLED", true),
MultiIntentEnabled: envBool("MULTI_INTENT_ENABLED", true),
SemanticFallbackEnabled: envBool("SEMANTIC_FALLBACK_ENABLED", false),
}
}
func parseV2DecisionTier(raw string) V2DecisionTier {
switch strings.ToLower(strings.TrimSpace(raw)) {
case "", "none":
return V2TierNone
case "query":
return V2TierQuery
case "generate":
return V2TierGenerate
case "write_low", "write-low", "low_write":
return V2TierWriteLow
case "write_high", "write-high", "high_write":
return V2TierWriteHigh
case "all":
return V2TierAll
default:
return V2TierQuery
}
}
func envBool(key string, def bool) bool {
v := strings.TrimSpace(os.Getenv(key))
if v == "" {
return def
}
return v == "1" || strings.EqualFold(v, "true") || strings.EqualFold(v, "yes")
}
// CurrentFeatureFlags 返回当前生效的功能开关
func CurrentFeatureFlags() FeatureFlags {
flagsMu.RLock()
defer flagsMu.RUnlock()
return activeFlags
}
// SetFeatureFlagsForTest 测试专用:临时覆盖开关
func SetFeatureFlagsForTest(f FeatureFlags) {
flagsMu.Lock()
activeFlags = f
flagsMu.Unlock()
}
// ResetFeatureFlagsForTest 测试专用:恢复默认
func ResetFeatureFlagsForTest() {
flagsMu.Lock()
activeFlags = defaultFeatureFlags()
flagsMu.Unlock()
}
// tierAllowsRisk 判断当前灰度档位是否允许该风险等级的 V2 路由
func tierAllowsRisk(tier V2DecisionTier, risk RiskLevel) bool {
switch tier {
case V2TierNone:
return false
case V2TierQuery:
return risk == RiskLow
case V2TierGenerate:
return risk == RiskLow || risk == RiskMedium
case V2TierWriteLow:
return risk != RiskHigh
case V2TierWriteHigh, V2TierAll:
return true
default:
return false
}
}