Files
Agent-System/internal/sysadmin/features.go
T
weichen d537778b60 fix(sysadmin): refresh feature maturity catalog to post-rollout wiring facts
The static adapter catalog still read I2-era states (degraded/shadow) after
the 2026-09-26 dev rollout, so the admin features page showed 降级 for flags
already enabled. Update six entries to live+ready with evidence-dated
reasons (I2/I3/P8 acceptance, P8 per-key gates kept visible, shadow
visibility digest now persisted, REPLACE wildcard wiring, PI narrative dev
rollout); keep FAV red lines untouched. Tests updated; FAV now carries the
configured-value-must-not-imply-readiness assertion.
2026-09-26 02:45:05 +00:00

167 lines
9.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sysadmin
import "os"
// Feature 功能开关视图。value / effectiveValue 是进程实际读到的配置,
// 不等于能力已经接入;是否可用看 implementationState 与 adapterReadiness。
type Feature struct {
Key string `json:"key"`
Label string `json:"label"`
Group string `json:"group"`
Value string `json:"value"`
ConfiguredValue string `json:"configuredValue"`
EffectiveValue string `json:"effectiveValue"`
ImplementationState string `json:"implementationState"`
AdapterReadiness string `json:"adapterReadiness"`
AdapterReason string `json:"adapterReason,omitempty"`
RolloutScope string `json:"rolloutScope"`
Source string `json:"source"`
RequiresRestart bool `json:"requiresRestart"`
Description string `json:"description"`
}
const (
implPlaceholder = "placeholder"
implDryRun = "dry_run"
implShadow = "shadow"
implLive = "live"
adapterReady = "ready"
adapterUnavailable = "unavailable"
adapterDegraded = "degraded"
rolloutEnvironment = "environment"
)
type featureMaturity struct {
state string
adapter string
reason string
}
// featureMaturityCatalog 是源码接线事实,不随环境变量翻转。
// 未列出的开关视为已接入的环境级能力;列出的项即使配置为 true 也保持此处状态。
var featureMaturityCatalog = map[string]featureMaturity{
"FAV_PUBLISHER_ENABLED": {
state: implDryRun, adapter: adapterUnavailable,
reason: "观察窗未授权,禁止 live",
},
"FAV_DEGRADED_READ": {
state: implDryRun, adapter: adapterUnavailable,
reason: "降级读保持关闭",
},
"MULTI_INTENT_PLAN_TIER": {
state: implLive, adapter: adapterReady,
reason: "I2/I3/P8 已合入并按 allowlist 验收(shadow→auto_read→confirm,项目 6579);dev 现行 confirm+*(2026-09-26 授权放量);U11/U12 逐键 live flag 默认关,禁止 full 一次放量",
},
"INTENT_PLAN_PROJECT_ALLOWLIST": {
state: implLive, adapter: adapterReady,
reason: "空值拒绝所有 elevated tier;* 放开全部;逗号分隔项目 ID",
},
"MULTI_INTENT_U9_SEGMENT": {
state: implLive, adapter: adapterReady,
reason: "HandleTurn 在规则无法分段且 elevated tier 时调用 PI proposer;失败 fail-closed;RulesCanDecide 跳过 LLM",
},
"MULTI_INTENT_U10_MUTATE": {
state: implLive, adapter: adapterReady,
reason: "project.fact.supplement 经 MutateOwner 写项目黑板(ctxmgr 端口);需 ExpectedResourceVersion",
},
"MULTI_INTENT_U11_DOCGOV": {
state: implLive, adapter: adapterReady,
reason: "P8 后全部 docgov 键已接真实引擎:claim/review.submit 随域名 flag,review/final/proposal 三组逐键 flag(默认关)另控;项目 143 只读",
},
"MULTI_INTENT_U12_RUN_CONTROL": {
state: implLive, adapter: adapterReady,
reason: "P8 后全部 run-control 键已接真实引擎:workflow.run/run.resume 随域名 flag,switch/restart 逐键 flag(默认关)另控",
},
"SEMANTIC_SUMMARY_SHADOW": {
state: implLive, adapter: adapterReady,
reason: "影子链路生产化(durable jobs/租约/watermark/provenance,dev schema 75 含 chat_summaries);可见集 digest 已随 provenance 落盘;dev 已开启(2026-09-26)",
},
"SEMANTIC_SUMMARY_REPLACE": {
state: implLive, adapter: adapterReady,
reason: "fail-closed 双开关已全量接线(master+SESSIONS,支持 * 全部会话含后续新建;四重校验;Facts/digest 保持 deterministic);dev 已开 *(2026-09-26)",
},
"PI_CHANGE_REPORT_NARRATIVE": {
state: implLive, adapter: adapterReady,
reason: "2026-09-23 收口真实 MiniMax 复测 PASS(截断差异+reasoning 落盘);dev 已按授权常驻开启(2026-09-26);test/main 保持默认关",
},
}
type featureSpec struct {
key string // 环境变量名
label string
group string
fallback string // 组合根未提供生效值时的兜底
description string
}
// featureCatalog 覆盖 config.Config 主要开关与各业务包灰度 flag(宁全勿缺)。
// 生效值由组合根(app)解析后注入,避免本包反向依赖业务模块。
var featureCatalog = []featureSpec{
{key: "AGENT_BACKEND", label: "Agent 执行后端", group: "agent", fallback: "pi-agent", description: "对话与任务执行的 Agent 后端(stub / cursor / pi-agent)"},
{key: "MAX_CONCURRENT_AGENTS", label: "Agent 全局并发上限", group: "agent", fallback: "8", description: "保护 pi-agent / GPU / API 的并发闸"},
{key: "PI_AGENT_RUNNER_URL", label: "PI Runner 地址", group: "agent", fallback: "", description: "产品内 PI Agent Runner 服务地址;空表示未接入"},
{key: "ALLOW_IN_MEMORY", label: "允许内存降级模式", group: "system", fallback: "false", description: "数据库不可用时降级内存模式(仅限本地 Demo)"},
{key: "AUTH_REGISTRATION_ENABLED", label: "开放注册", group: "auth", fallback: "true", description: "是否允许用户自主注册"},
{key: "AUTH_REQUIRE_APPROVAL", label: "注册需审核", group: "auth", fallback: "false", description: "新注册用户是否需要管理员审核后激活"},
{key: "FAV_PUBLISHER_ENABLED", label: "FAV 发布器", group: "artifact-vault", fallback: "false", description: "Final Artifact Vault 后台发布器;默认关闭"},
{key: "FAV_DEGRADED_READ", label: "FAV 降级读", group: "artifact-vault", fallback: "false", description: "FAV 缺失时允许降级读取;默认关闭"},
{key: "INTENT_V2_SHADOW", label: "意图 V2 影子模式", group: "intent", fallback: "false", description: "V2 意图识别影子运行,仅观测不接管"},
{key: "JEV_DECIDE_MODE", label: "jev 决策模式", group: "jevdecide", fallback: "off", description: "产品侧 jev-service:off / shadow / assist;默认 off,失败回退规则"},
{key: "INTENT_V2_DECISION", label: "意图 V2 决策", group: "intent", fallback: "false", description: "V2 意图识别接管路由决策"},
{key: "INTENT_V2_DECISION_TIER", label: "意图 V2 决策档位", group: "intent", fallback: "none", description: "V2 灰度风险档位:none/query/generate/write_low/write_high/all"},
{key: "WORKFLOW_INTENTS_ENABLED", label: "工作流意图", group: "intent", fallback: "true", description: "识别工作流类意图"},
{key: "MULTI_INTENT_ENABLED", label: "多意图识别", group: "intent", fallback: "true", description: "单条消息多意图拆解"},
{key: "MULTI_INTENT_PLAN_TIER", label: "多意图计划档位", group: "intentflow", fallback: "legacy", description: "意图计划灰度:legacy/shadow/auto_read/confirm/full"},
{key: "INTENT_PLAN_PROJECT_ALLOWLIST", label: "多意图计划项目白名单", group: "intentflow", fallback: "", description: "elevated tier 项目 allowlist:空拒绝;* 全部;逗号分隔项目 ID"},
{key: "MULTI_INTENT_U9_SEGMENT", label: "U9 LLM 分段", group: "intentflow", fallback: "false", description: "LLM 意图分段提议"},
{key: "MULTI_INTENT_U10_MUTATE", label: "U10 变更适配器", group: "intentflow", fallback: "false", description: "低/中风险 mutate 动作适配器"},
{key: "MULTI_INTENT_U11_DOCGOV", label: "U11 文档治理适配器", group: "intentflow", fallback: "false", description: "docgov 动作适配器"},
{key: "MULTI_INTENT_U12_RUN_CONTROL", label: "U12 运行控制适配器", group: "intentflow", fallback: "false", description: "workflow/run-control 动作适配器"},
{key: "WORKFLOW_SCOPE_MODE", label: "工作流作用域裁决", group: "intent", fallback: "strict", description: "文档命中裁决:strict 命中他流即拦截;weighted 按工作流关系权重打分"},
{key: "SEMANTIC_SUMMARY_SHADOW", label: "语义摘要影子", group: "ctxmgr", fallback: "false", description: "上下文语义摘要影子生成"},
{key: "SEMANTIC_SUMMARY_REPLACE", label: "语义摘要替换", group: "ctxmgr", fallback: "false", description: "验证 OK 后以语义叙事替换会话 served Narrative;fail-closed 灰度,需同时配置会话白名单"},
{key: "SEMANTIC_SUMMARY_REPLACE_SESSIONS", label: "语义摘要替换白名单", group: "ctxmgr", fallback: "", description: "逗号分隔会话 ID;* 全部会话(含后续新建);空则不替换任何会话(纵深防御)"},
{key: "PI_CHANGE_REPORT_NARRATIVE", label: "PI 变更报告叙事", group: "docrevision", fallback: "false", description: "变更报告 PI 叙事增强;默认仅确定性回退"},
}
// Features 返回功能开关快照;source 恒为 env,均需重启生效。
func (s *Service) Features() []Feature {
values := map[string]string{}
if s.featureValues != nil {
values = s.featureValues()
}
out := make([]Feature, 0, len(featureCatalog))
for _, spec := range featureCatalog {
value, ok := values[spec.key]
if !ok {
if env, set := os.LookupEnv(spec.key); set {
value = env
} else {
value = spec.fallback
}
}
maturity := featureMaturity{state: implLive, adapter: adapterReady}
if known, ok := featureMaturityCatalog[spec.key]; ok {
maturity = known
}
out = append(out, Feature{
Key: spec.key,
Label: spec.label,
Group: spec.group,
Value: value,
ConfiguredValue: value,
EffectiveValue: value,
ImplementationState: maturity.state,
AdapterReadiness: maturity.adapter,
AdapterReason: maturity.reason,
RolloutScope: rolloutEnvironment,
Source: "env",
RequiresRestart: true,
Description: spec.description,
})
}
return out
}