# AI 合同平台 V2 旧 UI 缓存治理策略 ## 背景 Phase 3 Slice 3.4 已将 `status_label`、`status_tone`、`next_action`、`next_actions` 逐步从数据库缓存字段转为 domain/serializer 派生。 远端 V2 smoke PostgreSQL 环境的 `runtime/schema-check` 已确认: - 检查未软删除合同记录:12010 条。 - 旧 UI 缓存与派生值不一致:8000 条。 - 当前仅报告 `warning`,不自动修复,不删除旧列。 ## 治理原则 1. 先评估,再 dry-run,再生成快照,最后才允许 apply。 2. `backfill --apply` 必须提供 snapshot 文件,确保可以回滚。 3. `rollback --apply` 必须读取 snapshot 文件恢复旧值。 4. 不在本阶段删除 `contracts.status_label/status_tone/next_action/next_actions`。 5. 不改变 OpenAPI 和前端字段名。 6. 不重置远端 PostgreSQL 数据卷。 ## 工具 新增治理工具: ```powershell python -m yuqei_contract_api.display_cache_governance_cli assess python -m yuqei_contract_api.display_cache_governance_cli backfill python -m yuqei_contract_api.display_cache_governance_cli backfill --apply --snapshot .runtime/display-cache-backfill-snapshot.json python -m yuqei_contract_api.display_cache_governance_cli rollback --snapshot .runtime/display-cache-backfill-snapshot.json python -m yuqei_contract_api.display_cache_governance_cli rollback --apply --snapshot .runtime/display-cache-backfill-snapshot.json ``` 默认行为: - `assess`:只读评估。 - `backfill`:默认 dry-run,只返回 would_update_rows。 - `backfill --apply`:写入派生值,并保存旧值/新值快照。 - `rollback`:默认 dry-run,只返回 would_restore_rows。 - `rollback --apply`:按 snapshot 恢复旧值。 ## 建议远端执行顺序 1. 在 192.168.3.90 的 smoke 容器内执行只读评估。 2. 执行 `backfill` dry-run,确认 would_update_rows 与 schema-check mismatch_count 一致。 3. 导出 snapshot 到远端可备份目录。 4. 备份 snapshot 到本地 artifact。 5. 仅在确认后执行 `backfill --apply --snapshot `。 6. 复跑 `/api/v1/runtime/schema-check`。 7. 若出现前端展示异常或抽样不通过,执行 `rollback --apply --snapshot `。 ## 验收标准 - dry-run 不修改数据库。 - apply 后 `display_cache_consistency.mismatch_count` 明显下降或归零。 - rollback 后可恢复 apply 前旧缓存值。 - 合同列表、合同详情、workspace、统一搜索抽样仍返回兼容字段。 - Docker healthcheck 不因 warning 误判 unhealthy;真正的 schema `error` 仍会失败。 ## 当前状态 本阶段只完成治理工具和策略,不对远端 8000 条旧缓存执行批量修复。 ## 远端 smoke 只读验证记录 验证环境: - 服务器:`192.168.3.90` - Compose project:`yuqei-contract-v2-smoke` - Contract API:`http://192.168.3.90:18100` - PostgreSQL 数据库:`yuqei_contract` - 部署 artifact:`project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-30T17-13-39` - CLI assess artifact:`project-docs/qa-artifacts/display-cache-governance/2026-06-30T17-19-32` - CLI backfill dry-run artifact:`project-docs/qa-artifacts/display-cache-governance/2026-06-30T17-20-11` 部署命令: ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\deploy-v2-smoke-docker.ps1 -UseSshpass -AllowDirtyWorktree -KeepRemoteBackup -SkipSmoke ``` 部署结果: - Docker smoke 部署:通过。 - Web、Contract API、AI Platform API health endpoints:通过。 - AI golden sample asset gate:通过,90 samples、6 suites、16 checks。 - Remote database baseline:`yuqei_contract`、`yuqei_ai`、`yuqei_ops` 均存在。 - Contract review worker smoke:跳过,避免本次只读治理验证额外创建 smoke 合同。 远端容器内 `assess` 结果: ```json { "command": "assess", "checked_rows": 12010, "mismatch_count": 8000, "field_counts": { "status_label": 4000, "status_tone": 6000 }, "samples": [ "perf-contract-000001:status_tone", "perf-contract-000004:status_label", "perf-contract-000005:status_tone", "perf-contract-000006:status_label,status_tone", "perf-contract-000007:status_tone" ] } ``` 远端容器内 `backfill` dry-run 结果: ```json { "command": "backfill", "mode": "dry-run", "would_update_rows": 8000, "snapshot_required_for_apply": true } ``` 复跑 `/api/v1/runtime/schema-check` 后确认: - `display_cache_consistency.checked_rows`:12010。 - `display_cache_consistency.mismatch_count`:8000。 - `field_counts`:`status_label=4000`、`status_tone=6000`。 结论: - 治理工具已部署进远端 smoke `contract-api` 容器。 - `assess` 与 `schema-check` 统计完全对齐。 - `backfill` dry-run 的 `would_update_rows` 与 `mismatch_count` 完全对齐。 - 本轮未执行 `backfill --apply`,未写库,未生成修复 snapshot,未重置 PostgreSQL 数据卷。 ## 远端候选 snapshot 预生成记录 本次只生成候选 snapshot,不执行 `backfill --apply`。 部署 artifact: - `project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-30T17-33-50` 本地备份 artifact: - `project-docs/qa-artifacts/display-cache-governance/2026-06-30T17-37-24` 远端容器内候选 snapshot: - `/opt/apps/ai-contract-platform-v2-smoke/backups/display-cache/display-cache-backfill-candidate-2026-06-30T17-37-24.json` 远端宿主机备份: - `/opt/apps/ai-contract-platform-v2-smoke/backups/display-cache/host-display-cache-backfill-candidate-2026-06-30T17-37-24.json` 本地备份: - `project-docs/qa-artifacts/display-cache-governance/2026-06-30T17-37-24/display-cache-backfill-candidate-2026-06-30T17-37-24.json` 候选 snapshot 校验: - 文件大小:1674118 bytes。 - SHA256:`853eaaf1024e43ebeb8530ac1ed47ed91bad4a09d0b79716f0aedbe791313f76`。 - `mode`:`dry-run`。 - `total_updates`:8000。 - values 数量:8000。 - 最后一条 contract_id:`perf-contract-012000`。 候选样例: ```json [ { "contract_id": "perf-contract-000001", "old_values": { "status_tone": "tag-primary" }, "new_values": { "status_tone": "tag-warning" } }, { "contract_id": "perf-contract-000004", "old_values": { "status_label": "��ͨ��" }, "new_values": { "status_label": "������" } }, { "contract_id": "perf-contract-000005", "old_values": { "status_tone": "tag-muted" }, "new_values": { "status_tone": "tag-success" } } ] ``` 说明:样例中的乱码来自历史性能数据中的旧缓存文本/终端编码表现;结构字段、contract_id、status_tone 和候选数量均已校验。 生成后复跑 `/api/v1/runtime/schema-check`: - `checked_rows`:12010。 - `mismatch_count`:8000。 - `field_counts`:`status_label=4000`、`status_tone=6000`。 结论: - 候选 snapshot 已生成并备份到本地 artifact。 - 本轮仍未执行 `backfill --apply`。 - PostgreSQL 数据未发生批量修复,schema-check 结果保持 8000 条 mismatch。 下一步如确认执行 apply,建议命令为: ```bash cd /opt/apps/ai-contract-platform-v2-smoke COMPOSE_PROJECT_NAME='yuqei-contract-v2-smoke' ENV_FILE='/opt/apps/ai-contract-platform-v2-smoke/yuqei-infra/compose/.env.smoke' COMPOSE_FILE='/opt/apps/ai-contract-platform-v2-smoke/yuqei-infra/compose/docker-compose.yml' SNAPSHOT='/opt/apps/ai-contract-platform-v2-smoke/backups/display-cache/display-cache-backfill-candidate-2026-06-30T17-37-24.json' docker compose -p "$COMPOSE_PROJECT_NAME" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" exec -T contract-api python -m yuqei_contract_api.display_cache_governance_cli backfill --apply --snapshot "$SNAPSHOT" ``` 如 apply 后需要回滚,建议命令为: ```bash cd /opt/apps/ai-contract-platform-v2-smoke COMPOSE_PROJECT_NAME='yuqei-contract-v2-smoke' ENV_FILE='/opt/apps/ai-contract-platform-v2-smoke/yuqei-infra/compose/.env.smoke' COMPOSE_FILE='/opt/apps/ai-contract-platform-v2-smoke/yuqei-infra/compose/docker-compose.yml' SNAPSHOT='/opt/apps/ai-contract-platform-v2-smoke/backups/display-cache/display-cache-backfill-candidate-2026-06-30T17-37-24.json' docker compose -p "$COMPOSE_PROJECT_NAME" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" exec -T contract-api python -m yuqei_contract_api.display_cache_governance_cli rollback --apply --snapshot "$SNAPSHOT" ``` ## 远端 smoke backfill apply 记录 本次已在 smoke 环境执行 `backfill --apply`,使用上一节确认过的 snapshot: - Snapshot:`/opt/apps/ai-contract-platform-v2-smoke/backups/display-cache/display-cache-backfill-candidate-2026-06-30T17-37-24.json` - Snapshot SHA256:`853eaaf1024e43ebeb8530ac1ed47ed91bad4a09d0b79716f0aedbe791313f76` - Apply artifact:`project-docs/qa-artifacts/display-cache-governance/2026-06-30T17-58-24` - Post-apply sample artifact:`project-docs/qa-artifacts/display-cache-governance/2026-06-30T18-01-02` Apply 输出: ```json { "command": "backfill", "mode": "apply", "updated_rows": 8000, "snapshot": "/opt/apps/ai-contract-platform-v2-smoke/backups/display-cache/display-cache-backfill-candidate-2026-06-30T17-37-24.json" } ``` Apply 后 `/api/v1/runtime/schema-check`: - 顶层状态:`ok`。 - `display_cache_consistency.status`:`ok`。 - `checked_rows`:12010。 - `mismatch_count`:0。 - Alembic actual/head:`20260630_0021`。 - PostgreSQL extension:`pg_trgm` 正常。 Apply 后接口抽样: - `/health`:`ok`。 - `/api/v1/contracts?limit=5`:可返回合同列表,样例包含 `perf-contract-000001`。 - `/api/v1/contracts/perf-contract-000001`:可返回合同详情。 - `/api/v1/search?keyword=PERF-000001&limit=5`:可返回统一搜索结果,包含 contract/file/review 三类分组。 说明: - 控制台输出中的中文乱码是 PowerShell/终端编码显示问题,接口 JSON 已保存为 UTF-8 artifact。 - 本次没有执行 rollback,因为 schema-check 已归零且列表、详情、搜索抽样可用。 - 如后续发现 smoke 展示异常,仍可使用上一节 `rollback --apply --snapshot` 命令恢复旧缓存。 ## 2026-07-01 完整上下文口径更新 后续排查发现,上一轮 `mismatch_count=0` 只代表旧缓存列与“状态默认派生值”一致,并不代表与真实用户读路径一致。 合同详情页会使用完整 `ContractActionContext`,纳入最新审查风险、条款修复、审批实例、履约任务和 `action_hint`。因此治理工具和 schema-check 已升级为同一完整上下文口径。 本次远端 smoke 复核: - 完整上下文口径首次发现 `12006` 条 `next_action/next_actions` 不一致。 - 已执行可回滚 `backfill --apply`,更新 `12006` 行。 - 回滚 snapshot:`/data/contract-files/display-cache-context-snapshot-20260701.json`。 - 复跑 `/api/v1/runtime/schema-check`:`status=ok`,`display_cache_consistency.mismatch_count=0`,`display_cache_cleanup_prestate.status=ok`。 - 合同详情页 `/contracts/contract-0ba3bd5b04b6` 抽样返回 200,推荐卡片仍展示,且本次请求后无 `Contract display cache mismatch` 日志。 详细记录见: - `project-docs/V2-phase3-display-cache-context-prestate-2026-07-01.md`