Files
ai-contract-platform/project-docs/V2-phase3-ui-display-derivation-design-2026-06-30.md
T
yuqei a3bb78e06b
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 16m35s
release: freeze V2 release candidate
2026-07-12 15:32:24 +08:00

257 lines
9.8 KiB
Markdown
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.
# 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 测试通过。