Files

79 lines
2.3 KiB
Go

package ctxmgr
import (
"os"
"strings"
"sync"
)
const (
EnvSemanticSummaryShadow = "SEMANTIC_SUMMARY_SHADOW"
// SEALED (Wave 5 X-2, 2026-09-18): REPLACE must stay unwired indefinitely per
// system-health-remediation-plan.md Wave5 + red-line "SEMANTIC_SUMMARY_REPLACE
// 不接线". Enabling REPLACE to swap served narrative requires a separate
// explicit user authorization + fail-closed rollout design; do not wire it as
// a side effect of an unrelated change. See .doc/ops/short-term/2026-09-18-
// wave5-deadcode-decisions.md#x-2.
EnvSemanticSummaryReplace = "SEMANTIC_SUMMARY_REPLACE"
)
// SummaryFeatureFlags controls semantic summary rollout.
// REPLACE is reserved and must remain unwired in PU6 shadow delivery (Wave 5 X-2 sealed).
type SummaryFeatureFlags struct {
Shadow bool
Replace bool
}
var (
summaryFlagsMu sync.RWMutex
activeSummaryFlags = loadSummaryFlagsFromEnv()
)
func loadSummaryFlagsFromEnv() SummaryFeatureFlags {
return SummaryFeatureFlags{
Shadow: envBoolDefault(EnvSemanticSummaryShadow, false),
Replace: envBoolDefault(EnvSemanticSummaryReplace, false),
}
}
func envBoolDefault(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")
}
// CurrentSummaryFlags returns the active summary feature flags.
func CurrentSummaryFlags() SummaryFeatureFlags {
summaryFlagsMu.RLock()
defer summaryFlagsMu.RUnlock()
return activeSummaryFlags
}
// SemanticSummaryShadowEnabled reports whether shadow semantic summary is on.
func SemanticSummaryShadowEnabled() bool {
return CurrentSummaryFlags().Shadow
}
// SemanticSummaryReplaceEnabled reports the REPLACE env bit.
// SEALED (Wave 5 X-2): PU6 must not use this to swap the served deterministic narrative.
// See .doc/ops/short-term/2026-09-18-wave5-deadcode-decisions.md#x-2.
func SemanticSummaryReplaceEnabled() bool {
return CurrentSummaryFlags().Replace
}
// SetSummaryFlagsForTest overrides flags in tests.
func SetSummaryFlagsForTest(f SummaryFeatureFlags) {
summaryFlagsMu.Lock()
activeSummaryFlags = f
summaryFlagsMu.Unlock()
}
// ResetSummaryFlagsForTest restores flags from the process environment.
func ResetSummaryFlagsForTest() {
summaryFlagsMu.Lock()
activeSummaryFlags = loadSummaryFlagsFromEnv()
summaryFlagsMu.Unlock()
}