# AI 合同平台 V2 Phase 3 Slice 3.4 UI 展示字段派生设计评审 ## 背景 本次继续对齐《AI 合同平台 V2 下一阶段开发优化方案》和 Phase 3 schema 硬化设计评审。 Slice 3.1 已完成 `contract_versions`。 Slice 3.2 已完成正式审批模型。 Slice 3.3 已完成治理字段和软删除,并已在权威 V2 smoke PostgreSQL/Docker 环境验证到 Alembic head `20260630_0021`。 Slice 3.4 的目标不是新增业务页面,也不是立即删除数据库字段,而是把 `status_label`、`status_tone`、`next_action`、`next_actions` 这类 UI 展示字段逐步从事实表中迁出,转为 domain/serializer 派生。 ## 当前问题 `contracts` 表仍保存以下 UI 展示字段: - `status_label` - `status_tone` - `next_action` - `next_actions` 这些字段目前还被以下路径使用: - 合同列表和合同详情响应。 - 工作台待办卡片。 - dashboard 状态统计标签。 - 统一搜索文档的 `status_label`、`summary` 和 `search_text`。 - 审批、审查、文件上传、条款修复等状态流副作用。 - 前端 TypeScript service 和 OpenAPI schema 兼容字段。 直接删除字段风险较高,因为前端和搜索仍需要这些响应字段。 ## 设计原则 1. 不在 Slice 3.4 第一片删除数据库列。 2. 不改变现有 API 响应字段名。 3. 不改变前端读取字段方式。 4. 先把派生规则集中到 domain/serializer 层。 5. 旧字段暂时保留为兼容缓存,用于灰度和回滚。 6. 当数据库缓存值与派生值不一致时,响应层优先使用派生值,并记录 warning。 7. `status_label` 和 `status_tone` 可以直接从 `status` 强派生。 8. `next_action` 和 `next_actions` 需要分阶段迁出,因为当前它们既包含状态默认动作,也包含少量合同上下文提示。 ## 第一片实现边界 新增 `contract_display.py`,集中维护: - `ContractDisplayFields` - `CONTRACT_DISPLAY_BY_STATUS` - `derive_contract_display` - `status_label_for_status` - `status_tone_for_status` 第一片 read-switch: - 合同列表响应:`status_label`、`status_tone` 优先派生。 - 合同详情响应:`status_label`、`status_tone` 优先派生。 - 合同详情响应:`next_action`、`next_actions` 对已知旧状态默认文案做派生修正。 - 统一搜索文档:合同类文档的 `status_label`、`summary`、`search_text` 使用派生结果。 - in-memory dashboard:状态标签从 `status` 派生。 第一片暂不做: - 不删除 `contracts.status_label` 等旧列。 - 不移除写路径中的旧字段写入。 - 不修改 OpenAPI 字段。 - 不修改前端字段名。 - 不把所有合同特定 `next_action` 强制覆盖成状态默认值。 ## next_action 分阶段策略 `next_action` 当前有两类含义: 1. 状态默认动作,例如“审批人处理”“修改后重新提交”“准备签署与归档”。 2. 业务上下文提示,例如“法务确认付款和验收条款”“补充租赁期限后提交”“跟踪履约节点”。 第一片只覆盖明显属于旧状态默认文案、且与当前 `status` 不一致的缓存值。 后续要把 `next_action` 完全派生,需要先从结构化事实中提取上下文: - 审批实例和待办步骤。 - 最新审查任务状态。 - 未完成义务任务。 - 条款修复动作。 - 合同版本/草稿编辑状态。 ## 验收标准 第一片验收: - 当数据库中 `status_label/status_tone` 与 `status` 不一致时,合同列表和详情响应返回派生值。 - 当数据库中 `next_action/next_actions` 是已知旧状态默认文案且与当前 `status` 不一致时,合同详情响应返回派生默认动作。 - 合同搜索文档重建后使用派生的 `status_label`。 - 现有合同工作流测试继续通过。 后续完整验收: - 合同列表、详情、搜索、工作台展示不依赖手工维护 UI 文案。 - 数据库字段表达业务事实,UI 文案集中在代码映射层。 - PostgreSQL smoke 环境中搜索重建、合同列表、详情、workspace 抽样均通过。 ## 回滚策略 第一片只新增集中派生层并切换响应读取,不删除旧列。 如出现前端展示异常,可以回滚 mapper/search 对 `derive_contract_display` 的调用,数据库旧字段仍可继续支撑响应。 ## 后续拆分建议 1. 权威 V2 smoke PostgreSQL 环境复跑合同列表、详情、搜索、workspace、runtime schema-check 抽样。 2. 稳定后再评审是否进入 cleanup migration,删除或降级旧 UI 缓存列。 ## 第二片实施记录 本次已实现 `ContractActionContext`,将 `next_action` 和 `next_actions` 从“状态默认 + 旧缓存兼容”推进到“状态 + 结构化上下文”派生。 新增上下文来源: - 最新审查任务状态:`queued`、`running`、`succeeded`、`failed`。 - 审查风险项是否存在未处理风险。 - 审查风险项是否已有 `repair_status=applied` 的条款修复记录。 - 正式审批模型中的 pending approval instance/step。 - 未完成履约任务的首个待处理节点。 派生优先级: 1. 已应用条款修复:提示“复核已应用的条款修订”。 2. 审查任务排队或运行中:提示“等待法律审查结果”。 3. 审查失败:提示“重新发起法律审查”。 4. 审查完成且存在未处理风险:提示“处理审查风险并应用推荐条款”。 5. 审查完成且存在风险但无需条款修复:提示“根据审查结果修改或提交审批”。 6. 正式审批待办:提示“等待审批人审批”。 7. 已审批、已签署、已归档阶段存在未完成履约任务:提示具体履约节点。 8. 否则回落到 `status` 默认动作。 接入范围: - SQLAlchemy 合同列表响应。 - SQLAlchemy 合同详情响应。 - 工作台待办响应。 - 统一搜索文档同步/重建。 - transition 写路径的即时响应。 仍未做: - 未删除 `contracts.status_label/status_tone/next_action/next_actions` 旧列。 - 未移除旧写路径对 UI 缓存字段的写入。 - 未修改 OpenAPI 和前端字段名。 - 未把合同版本/草稿编辑状态纳入 `ContractActionContext`。 验证: ```powershell python -m compileall -q yuqei-contract-platform\services\contract-api\src\yuqei_contract_api python -m pytest yuqei-contract-platform\services\contract-api\tests -q ``` 结果:完整 Contract API 测试通过。 ## 远端 PostgreSQL / Docker 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-30T16-40-34` 执行命令: ```powershell powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\deploy-v2-smoke-docker.ps1 -UseSshpass -AllowDirtyWorktree -KeepRemoteBackup ``` 结果: - 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:通过。 `/api/v1/runtime/schema-check` 抽样结果: - 顶层状态:`warning`。 - `database_backend`:`ok`,PostgreSQL。 - `database_name`:`ok`,当前数据库为 `yuqei_contract`。 - `alembic_version`:`ok`,actual/head 均为 `20260630_0021`。 - `core_tables`:`ok`,检查 20 张核心表。 - `governance_columns`:`ok`,检查 11 张表、36 个治理字段。 - `postgres_extensions`:`ok`,已安装 `pg_trgm`。 - `display_cache_consistency`:`warning`,检查 12010 条未软删除合同记录,发现 8000 条旧 UI 缓存字段与派生值不一致。 样例: ```text 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 ``` 处理说明: - 本片只做只读检查,不自动修复旧缓存。 - 本片不删除 `contracts.status_label/status_tone/next_action/next_actions` 旧列。 - 为避免报告型 `warning` 误伤容器健康状态,Contract API Docker healthcheck 已调整为只在 schema-check 顶层状态为 `error` 时失败;`warning` 继续保留在 runtime schema-check 报告中供后续治理。 ## 第三片实施记录 本次已将 display cache consistency 纳入 Contract API runtime schema-check。 新增检查项: - `display_cache_consistency` 检查范围: - 只读扫描 `contracts` 表中未软删除记录。 - 对比旧缓存字段与 `derive_contract_display` 派生值: - `status_label` - `status_tone` - `next_action` - `next_actions` 返回策略: - 全部一致:`status=ok`。 - 存在不一致:`status=warning`,不自动修复。 - `contracts` 表缺失:`status=warning` 并标记 skipped,由 `core_tables` 继续负责报 `error`。 返回 details: - `checked_rows` - `mismatch_count` - `sample_limit` - `samples`:最多 5 条,格式为 `contract_id:field1,field2`。 本片仍不做: - 不写库。 - 不修复旧缓存。 - 不删除旧列。 - 不改变 OpenAPI 和前端字段。 验证: ```powershell python -m compileall -q yuqei-contract-platform\services\contract-api\src\yuqei_contract_api python -m pytest yuqei-contract-platform\services\contract-api\tests\test_health.py::test_runtime_schema_check_warns_for_local_sqlite_auto_created_schema yuqei-contract-platform\services\contract-api\tests\test_health.py::test_runtime_schema_check_errors_for_missing_core_tables yuqei-contract-platform\services\contract-api\tests\test_health.py::test_runtime_schema_check_warns_for_stale_contract_display_cache -q python -m pytest yuqei-contract-platform\services\contract-api\tests -q ``` 结果:完整 Contract API 测试通过。