From 6ed9f2dd0a5f2a573991c3d49a817f13a202b56c Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Wed, 29 Jul 2026 19:18:09 +0800 Subject: [PATCH] fix: enable semantic rectification rollout --- deploy/README.md | 11 +++++++---- deploy/configure-staging-rectification-rollout.sh | 6 +++++- docs/BUG_HISTORY.md | 14 ++++++++++++++ frontend/tests/staging-backend-workflows.test.ts | 11 ++++++++++- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/deploy/README.md b/deploy/README.md index fc9142b9..32e69025 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -406,11 +406,14 @@ previous-revision smoke SHA must remain pending. If the create flag, migration flag, deployment SHA, or strict UUID allowlist is invalid, creation audience must be `paused`, including for the smoke account. -After the smoke sequence below passes, set +After the smoke sequence below passes, use the guarded rollout workflow to set `RECTIFICATION_V3_SYNTHETIC_SMOKE_SHA` to the exact deployed 40-character -lowercase Git SHA, remove `RECTIFICATION_V3_SYNTHETIC_SMOKE_USER_IDS`, and -restart the web container. Then fetch health again and -verify all of the following against the revision that passed validation: +lowercase Git SHA, remove `RECTIFICATION_V3_SYNTHETIC_SMOKE_USER_IDS`, enable +`RECTIFICATION_AGENT_V5_ENABLED=true`, disable shadow mode, set the canary to +100 percent, and restart both the web and rectification worker containers. The +workflow writes these selectors together so public Case creation cannot silently +fall back to the fixed `v4_legacy` projector. Then fetch health again and verify +all of the following against the revision that passed validation: - `deployment.gitCommit` exactly equals the tested 40-character Git SHA; - `rollout.conversationalRectificationV3.protocol` is diff --git a/deploy/configure-staging-rectification-rollout.sh b/deploy/configure-staging-rectification-rollout.sh index 4edfbf9b..1725d6c6 100755 --- a/deploy/configure-staging-rectification-rollout.sh +++ b/deploy/configure-staging-rectification-rollout.sh @@ -102,12 +102,16 @@ awk \ -v create="$creation_enabled" \ -v migrations="true" \ -v smoke_sha="$smoke_sha" \ - -v smoke_users="$smoke_user_ids" ' + -v smoke_users="$smoke_user_ids" \ + -v agent_enabled="$creation_enabled" ' BEGIN { values["RECTIFICATION_V3_CREATE_ENABLED"] = create values["RECTIFICATION_V3_MIGRATIONS_READY"] = migrations values["RECTIFICATION_V3_SYNTHETIC_SMOKE_SHA"] = smoke_sha values["RECTIFICATION_V3_SYNTHETIC_SMOKE_USER_IDS"] = smoke_users + values["RECTIFICATION_AGENT_V5_ENABLED"] = agent_enabled + values["RECTIFICATION_AGENT_V5_SHADOW"] = "false" + values["RECTIFICATION_AGENT_V5_CANARY_PERCENT"] = "100" } { split($0, parts, "=") diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 53925c57..3daf8723 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -1634,3 +1634,17 @@ - 防复发:所有模型可写用户文案共享同一安全边界;模型提取不能决定评分主体;用于哈希的稳定顺序不得被复用为会话时序。 - 相关记录:BUG-075、BUG-086、BUG-087 - 修复版本:待本次 staging 修复提交与部署验收 + +## BUG-091 | Staging Case rollout 未启用 V5 Agent 导致 V6 继续输出固定模板 + +- 状态:resolved +- 首次发现:2026-07-29 +- 最近更新:2026-07-29 +- 影响面:staging 生时纠正新 Case 与 V6 未完成 Case 的用户可见回复 +- 用户现象:用户提交“2016 年 9 月离家去外地上大学”后,回复仍固定为“我记下了这段经历。接下来请继续讲另一件……”,没有进入 Semantic Question Renderer。 +- 根因:Case rollout 只写入 V3 创建门和 smoke 状态,没有写入 `RECTIFICATION_AGENT_V5_ENABLED`、`RECTIFICATION_AGENT_V5_SHADOW`、`RECTIFICATION_AGENT_V5_CANARY_PERCENT`;因此 `selectRectificationDeploymentMode()` 把新 Case 持久化为 `v4_legacy`,Orchestrator 必然调用 Legacy Projector。 +- 修复:受控 staging rollout 现在原子写入 V5 Agent 开关,public 与 smoke rollout 使用 `v5_agent`、100% canary,并重建 web/worker;staging 中唯一满足 V6 版本、未完成、无 open Job 条件的错误 Case 已原位升级为 `rectification-evidence-v5` / `v5_agent`,历史 Turn、Event、Job 与 Agent Run 保持不变。 +- 验证:rollout 脚本测试断言三项 V5 选择器只写一次;staging 运行容器已读取 `enabled=true`、`shadow=false`、`canary=100`;活跃 Case 聚合只剩 `v5_agent`;健康检查保持 exact SHA、public、ready。 +- 防复发:公开 Case rollout 必须同时控制创建门与 Agent deployment mode;仅有 `readyForNewCases=true` 不再视为新对话 Renderer 已启用的充分证据。 +- 相关记录:BUG-085、BUG-086、BUG-087 +- 修复版本:`birth-time-rectification-v6` / `rectification-agent-v6-1` diff --git a/frontend/tests/staging-backend-workflows.test.ts b/frontend/tests/staging-backend-workflows.test.ts index 9986d41c..2a94a8b7 100644 --- a/frontend/tests/staging-backend-workflows.test.ts +++ b/frontend/tests/staging-backend-workflows.test.ts @@ -405,7 +405,7 @@ test("production remains manual-only and separate from staging database automati }); -test("public rectification rollout rewrites only rollout gates and recreates web runtimes", () => { +test("public rectification rollout enables the semantic agent and recreates web runtimes", () => { const root = mkdtempSync(join(tmpdir(), "jyotisha-rollout-")); const deploymentPath = join(root, "app"); const statePath = join(deploymentPath, ".state"); @@ -441,6 +441,9 @@ test("public rectification rollout rewrites only rollout gates and recreates web "RECTIFICATION_V3_MIGRATIONS_READY=false", "RECTIFICATION_V3_SYNTHETIC_SMOKE_SHA=old", "RECTIFICATION_V3_SYNTHETIC_SMOKE_USER_IDS=00000000-0000-4000-8000-000000009001", + "RECTIFICATION_AGENT_V5_ENABLED=false", + "RECTIFICATION_AGENT_V5_SHADOW=true", + "RECTIFICATION_AGENT_V5_CANARY_PERCENT=0", "", ].join("\n"), { mode: 0o600 }, @@ -487,7 +490,13 @@ test("public rectification rollout rewrites only rollout gates and recreates web assert.match(env, /^RECTIFICATION_V3_MIGRATIONS_READY=true$/m); assert.match(env, new RegExp(`^RECTIFICATION_V3_SYNTHETIC_SMOKE_SHA=${sha}$`, "m")); assert.match(env, /^RECTIFICATION_V3_SYNTHETIC_SMOKE_USER_IDS=$/m); + assert.match(env, /^RECTIFICATION_AGENT_V5_ENABLED=true$/m); + assert.match(env, /^RECTIFICATION_AGENT_V5_SHADOW=false$/m); + assert.match(env, /^RECTIFICATION_AGENT_V5_CANARY_PERCENT=100$/m); assert.equal((env.match(/^RECTIFICATION_V3_CREATE_ENABLED=/gm) ?? []).length, 1); + assert.equal((env.match(/^RECTIFICATION_AGENT_V5_ENABLED=/gm) ?? []).length, 1); + assert.equal((env.match(/^RECTIFICATION_AGENT_V5_SHADOW=/gm) ?? []).length, 1); + assert.equal((env.match(/^RECTIFICATION_AGENT_V5_CANARY_PERCENT=/gm) ?? []).length, 1); assert.match(readFileSync(join(root, "docker.log"), "utf8"), /force-recreate --no-deps web rectification-v4-worker/); } finally { rmSync(root, { recursive: true, force: true });