Files
ai-contract-platform/project-docs/V2-phase3-next-action-action-hint-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

28 KiB
Raw Blame History

AI 合同平台 V2 Phase 3 next_action / action_hint 语义设计

背景

本设计继续对齐《AI 合同平台 V2 下一阶段开发优化方案》的 Phase 3 schema 硬化方向。

截至本设计前:

  • contract_versions 已完成。
  • 正式审批模型 approval_instances / approval_steps / approval_actions 已完成。
  • 治理字段和软删除已完成。
  • status_label / status_tone 已进入停写第一片,生产 SQLAlchemy 写路径会按 status 派生兼容缓存。
  • 远端 smoke PostgreSQL / Docker 已验证 display_cache_cleanup_prestate.status=ok,旧展示缓存一致性为 0 mismatch。

当前不应删除 contracts.next_action / contracts.next_actions。这两个字段已经不是纯 UI 缓存,仍混合了承载系统动作、结构化上下文动作和人工跟进提示。

当前代码实况

API 和前端读取

  • ContractListItem.next_action 仍是合同列表、workspace 任务、统一搜索摘要的重要展示字段。
  • ContractDetail.next_actions 仍是合同详情动作列表。
  • 前端合同列表和详情页仍读取 next_action / next_actions。
  • OpenAPI / BFF / 前端类型仍依赖这两个字段,短期不能改名或移除。

人工编辑入口

前端合同编辑面板仍允许编辑 next_action:

  • apps/contract-web/src/app/contracts/[id]/contract-edit-panel.tsx
  • 表单字段名:next_action
  • 当前 UI 文案:下一步操作

后端仍允许 PATCH 更新:

  • ContractUpdateRequest.next_action
  • ContractUpdateRequest.next_actions
  • ContractCoreRepository.update_contract(...) 会把 next_action / next_actions 写入 contracts 表。

这说明人工编辑入口仍存在,并且当前语义容易和系统派生动作混淆。

系统派生动作来源

ContractActionContext 已经从以下结构化事实派生动作:

  • 最新审查任务状态:queued / running / succeeded / failed。
  • 审查风险和未应用条款修复。
  • 已应用条款修复。
  • 待审批实例和待审批步骤。
  • 未完成履约任务。

同时仍有部分写路径会直接写旧列 next_action / next_actions,例如文件上传、审查任务、条款修复、审批流和归档流程。这些后续应逐步改为写结构化事实,或只通过兼容 helper 写入派生缓存。

产品语义决策

结论:保留人工编辑入口,但不再把它称为“下一步操作”。

建议将人工可编辑内容定义为:

  • 字段语义:人工跟进提示。
  • 推荐字段名:action_hint。
  • 推荐前端标签:人工跟进提示。
  • 推荐说明:用于补充系统无法从流程事实推导出的提醒,例如“法务确认付款和验收条款”“补充租赁期限后提交”。

next_action / next_actions 继续作为 API 兼容展示字段保留,但其来源应逐步变为:

  1. 结构化流程上下文。
  2. 人工 action_hint。
  3. 状态默认动作。

这样既保留用户需要的人工备注能力,又避免人工字段覆盖审批、审查、条款修复这类系统关键动作。

方案评估

方案 A:新增 contracts.action_hint

做法:

  • 在 contracts 表新增 nullable 文本字段 action_hint。
  • 前端编辑面板把原来的 next_action 输入改为 action_hint。
  • API PATCH 暂时同时接受 action_hint 和旧 next_action,旧字段作为兼容入口。
  • 响应继续返回 next_action / next_actions。
  • derive_contract_display(...) 按优先级将 action_hint 纳入派生。

优点:

  • 迁移小,语义清楚。
  • 保留人工提示能力。
  • 与当前 ContractActionContext 最容易衔接。
  • 回滚简单,旧列仍保留。

缺点:

  • 只能表达一条人工提示,不能精细覆盖多个动作按钮。
  • 后续如果需要角色级、场景级动作覆盖,仍需要扩展。

结论:推荐作为第一片实现。

方案 B:新增 contract_action_overrides

做法:

  • 新建子表或 JSON 结构,保存 action overrides。
  • 字段可能包含 source_type、priority、label、target_url、role_scope、expires_at、created_by。

优点:

  • 能支持多动作、角色级动作、过期时间、来源追踪。
  • 适合未来做运营型动作配置。

缺点:

  • 当前需求过重。
  • 会把 Phase 3 cleanup 从 schema 硬化带到新业务模型设计。
  • 迁移和前端交互都更复杂。

结论:暂不作为第一片。可作为后续增强,不阻塞 action_hint。

方案 C:移除人工编辑入口

做法:

  • 前端删除 next_action 输入。
  • 后端拒绝或忽略 PATCH 中的 next_action / next_actions。
  • 所有动作完全由系统上下文派生。

优点:

  • 数据模型最干净。
  • 能最快停写旧 UI 缓存。

缺点:

  • 会损失当前业务人员补充跟进提示的能力。
  • V1/V2 早期样本里存在“法务确认付款和验收条款”“补充租赁期限后提交”这类人工上下文,它们不是纯状态默认动作。

结论:不建议当前采用。

推荐最终语义

字段分工

status

  • 合同状态事实。
  • 唯一来源:业务状态流。

status_label / status_tone

  • 旧兼容缓存。
  • 由 status 派生。
  • 后续可停写或删列,但 API 响应字段继续保留。

action_hint

  • 人工跟进提示事实。
  • 可为空。
  • 用户可编辑。
  • 不应覆盖高优先级系统动作。

next_action / next_actions

  • API 兼容展示字段。
  • 不再视为长期事实字段。
  • 由 ContractActionContext + action_hint + status 派生。
  • 旧数据库列保留为兼容缓存,后续停写或删列。

派生优先级

建议优先级如下:

  1. 已应用条款修复:复核已应用的条款修订。
  2. 审查任务 queued / running:等待法律审查结果。
  3. 审查任务 failed:重新发起法律审查。
  4. 审查任务 succeeded 且有未应用修复:处理审查风险并应用推荐条款。
  5. 审查任务 succeeded 且有风险:根据审查结果修改或提交审批。
  6. 待审批步骤:等待{role}审批。
  7. 已审批、已签署、已归档阶段的未完成履约任务:跟踪履约节点:{title}。
  8. 人工 action_hint:例如 法务确认付款和验收条款。
  9. 状态默认动作:例如 补充后提交审批、准备签署与归档。

原则:

  • 结构化流程动作高于人工提示。
  • 人工提示高于普通状态默认动作。
  • next_actions 的按钮列表优先来自结构化上下文;当只有 action_hint 时,按钮列表仍使用当前状态默认动作,避免把人工提示误当作可点击动作。

兼容策略

API 输入兼容

第一片建议:

  • ContractUpdateRequest 新增 action_hint: str | None = None。
  • 暂时保留 next_action / next_actions。
  • 如果请求包含 action_hint,写入 contracts.action_hint。
  • 如果请求只包含旧 next_action,按兼容策略写入 action_hint,但不再直接视为系统动作事实。
  • 如果请求包含旧 next_actions,短期仍接受但标记 deprecated;后续只允许系统派生。

API 输出兼容

短期不改:

  • 合同列表继续返回 next_action。
  • 合同详情继续返回 next_action / next_actions。

可选增强:

  • 合同详情新增只读字段 action_hint,用于前端编辑面板回填。
  • 合同列表是否返回 action_hint 可暂缓,避免扩大接口面。

前端兼容

第一片建议:

  • 编辑面板标签从 下一步操作 改为 人工跟进提示。
  • 表单提交字段改为 action_hint。
  • 当后端未返回 action_hint 时,前端可先用当前 contract.next_action 回填,但只作为过渡。
  • 详情页主展示仍显示 next_action,即系统派生后的下一步动作。

迁移切片

Slice 3.5.3-a:设计锁定

本设计即为该片产物。

验收:

  • 明确人工入口保留。
  • 明确 action_hint 是人工提示事实字段。
  • 明确 next_action / next_actions 是兼容展示字段。
  • 不写 migration。

Slice 3.5.3-b:新增字段和兼容写入

实现:

  • Alembic 新增 contracts.action_hint nullable text/string 字段。
  • SQLAlchemy ContractModel 新增 action_hint。
  • ContractUpdateRequest 新增 action_hint。
  • PATCH 兼容旧 next_action,写入 action_hint。
  • 创建合同和模板起草可选择写入 action_hint,默认空。

验收:

  • 旧 PATCH next_action 不报错。
  • 新 PATCH action_hint 可保存。
  • schema-check 确认 action_hint 字段存在。
  • Docker smoke 可创建、编辑、提交审批、退回、重提、发起审查。

Slice 3.5.3-c:派生层接入 action_hint

实现:

  • ContractActionContext 增加 action_hint。
  • SQLAlchemy action context loader 从 contracts.action_hint 读取。
  • derive_contract_display(...) 按优先级接入 action_hint。
  • 读路径返回派生后的 next_action / next_actions。
  • 搜索文档使用派生后的 next_action。

验收:

  • 没有审查、审批、履约、条款修复上下文时,action_hint 成为 next_action。
  • 有高优先级结构化动作时,next_action 使用结构化动作,action_hint 不覆盖。
  • next_actions 仍保持可执行动作列表,而不是人工提示列表。

Slice 3.5.3-d:前端改名

实现:

  • 编辑面板字段从 next_action 改为 action_hint。
  • 文案从 下一步操作 改为 人工跟进提示。
  • 详情页主动作展示继续用 next_action。

验收:

  • 用户仍能保存人工提示。
  • 保存后,在无更高优先级系统动作时,详情页下一步显示人工提示。
  • 一旦进入审批或审查,详情页下一步显示系统动作。

Slice 3.5.3-e:停写旧 next_action / next_actions

实现:

  • 文件上传、审查任务、条款修复、审批流、归档流程不再手写旧列。
  • 如仍需兼容缓存,由统一 helper 按派生结果刷新。
  • 旧列只作为兼容缓存,不再作为事实来源。

验收:

  • display_cache_cleanup_prestate 仍为 ok。
  • 合同列表、详情、workspace、统一搜索展示不退化。
  • 旧列与派生值一致性检查为 0 mismatch。

Slice 3.5.4:cleanup migration 设计评审

只有满足以下条件后才考虑:

  • status_label / status_tone / next_action / next_actions 已全部由派生层稳定输出。
  • 前端不再提交旧 next_action / next_actions 作为事实字段。
  • OpenAPI 兼容策略已明确。
  • smoke PostgreSQL 和 Docker smoke 已连续通过。

此时再决定是否删列。当前不建议进入删列 migration。

回滚策略

  • 新增 action_hint 为 nullable 字段,不影响旧读取。
  • 旧 next_action / next_actions 列保留。
  • 如果派生层有问题,可临时恢复使用旧列。
  • 如果前端改名有问题,可继续兼容旧 next_action PATCH。
  • 不做不可逆数据删除。

测试清单

后端单测:

  • action_hint 可通过 PATCH 保存。
  • 旧 next_action PATCH 可兼容写入 action_hint。
  • 无结构化上下文时,next_action 派生为 action_hint。
  • 有待审批步骤时,next_action 派生为审批动作,不被 action_hint 覆盖。
  • 有审查风险和未应用修复时,next_action 派生为条款修复动作,不被 action_hint 覆盖。
  • 有未完成履约任务时,已审批/已签署/已归档合同显示履约动作。
  • next_actions 不把人工提示当按钮列表。

前端抽样:

  • 合同详情编辑面板展示 人工跟进提示。
  • 保存人工提示后页面刷新正常。
  • 合同进入审批后,主下一步显示审批动作。
  • 合同退回后,主下一步显示退回后的系统动作或人工提示,按优先级生效。

远端 smoke:

  • 跑 /api/v1/runtime/schema-check。
  • 创建合同。
  • 编辑 action_hint。
  • 提交审批。
  • 退回。
  • 重提。
  • 发起审查。
  • 抽样合同列表、详情、workspace、统一搜索。

当前建议

下一步不要直接删除 next_action / next_actions,也不要马上设计复杂 contract_action_overrides 子表。

最稳的下一片是:

  1. 新增 nullable contracts.action_hint。
  2. 保留旧列和旧 API 字段。
  3. 让 PATCH 新旧字段都能进入 action_hint。
  4. 让派生层在无更高优先级结构化动作时使用 action_hint。
  5. 先在本地 PostgreSQL/测试中验证,再部署到 192.168.3.90 smoke。

Slice 3.5.3-b 实施记录

本片已完成 action_hint 的第一阶段落库能力,仍未进入删列或派生层重排。

新增内容:

  • Alembic migration:20260630_0022_add_contract_action_hint.py
  • contracts.action_hint nullable 字段。
  • SQLAlchemy ContractModel.action_hint。
  • ContractUpdateRequest.action_hint。
  • Contract API runtime schema-check:新增 action_hint_columns 检查。

兼容写入策略:

  • 新客户端提交 action_hint 时,写入 contracts.action_hint,并同步刷新旧 contracts.next_action 兼容缓存。
  • 旧客户端只提交 next_action 时,同步写入 contracts.action_hint。
  • next_actions 仍保持旧行为,本片不把人工提示转成按钮列表。

本片刻意没有做:

  • 没有删除 next_action / next_actions 旧列。
  • 没有改变合同列表、详情、workspace、搜索的响应字段名。
  • 没有把 action_hint 加入 API 输出模型。
  • 没有改前端编辑面板文案和字段名。
  • 没有改变 ContractActionContext 派生优先级。

验证:

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_contract_workflow.py::test_contract_update_accepts_action_hint_and_legacy_next_action 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_errors_when_action_hint_column_is_missing -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py yuqei-contract-platform\services\contract-api\tests\test_health.py -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_display_cache_governance.py -q
python -m alembic -c alembic.ini heads
$env:CONTRACT_API_DATABASE_URL='sqlite+pysqlite:///D:/yuqei-project/ai-contract-platform/.tmp-contract-action-hint-alembic.sqlite3'; python -m alembic -c alembic.ini upgrade head

结果:

  • Python compile 通过。
  • Contract API 工作流、health/schema-check、display cache governance 测试通过。
  • Alembic head 为 20260630_0022。
  • Alembic base -> head 临时 SQLite 迁移通过。

下一片建议:

  • Slice 3.5.3-c:将 action_hint 接入 ContractActionContext 和 derive_contract_display(...)。
  • 派生优先级仍按设计保持:结构化流程上下文 > action_hint > 状态默认动作。

Slice 3.5.3-c 实施记录

本片已将 action_hint 接入只读派生链路,继续保持旧 API 响应字段兼容。

新增内容:

  • ContractActionContext.action_hint。
  • SQLAlchemy action context loader 从 ContractModel.action_hint 读取人工跟进提示。
  • derive_contract_display(...) 在没有高优先级结构化动作时使用 action_hint 作为 next_action。

派生优先级:

  1. 条款修复、审查任务、待审批步骤、履约任务等结构化上下文。
  2. action_hint 人工跟进提示。
  3. 状态默认动作。

关键语义:

  • action_hint 只影响 next_action 的展示文案。
  • next_actions 仍保持当前状态默认按钮列表,不把人工提示当成动作按钮。
  • 审批、审查、条款修复、履约等系统动作会覆盖 action_hint。

本片刻意没有做:

  • 没有把 action_hint 加入 API 输出模型。
  • 没有改前端编辑面板字段名或文案。
  • 没有删除或停写旧 next_action / next_actions 兼容列。
  • 没有执行远端 smoke 部署。

验证:

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_contract_workflow.py::test_contract_update_accepts_action_hint_and_legacy_next_action yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_action_hint_derives_next_action_without_overriding_buttons yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_structured_action_context_overrides_action_hint -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py yuqei-contract-platform\services\contract-api\tests\test_health.py -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_display_cache_governance.py -q
python -m alembic -c alembic.ini heads

结果:

  • Python compile 通过。
  • 新增 action_hint 派生优先级回归通过。
  • Contract API 工作流、health/schema-check、display cache governance 测试通过。
  • Alembic head 仍为 20260630_0022。

下一片建议:

  • Slice 3.5.3-d:前端编辑面板改名,将 下一步操作 输入改为 人工跟进提示,提交字段从 next_action 改为 action_hint。
  • 后端仍继续兼容旧 next_action PATCH,方便灰度和回滚。

Slice 3.5.3-d 实施记录

本片已完成前端人工编辑入口的语义切换。

新增内容:

  • ContractDetail.action_hint 可选响应字段。
  • 合同详情 mapper 返回 row.action_hint。
  • 前端 ContractDetail TypeScript 类型新增 action_hint?: string | null。
  • 合同编辑面板标签从 下一步操作 改为 人工跟进提示。
  • 合同编辑面板提交字段从 next_action 改为 action_hint。
  • 表单默认值优先使用 contract.action_hint,旧后端或旧数据场景下兜底使用 contract.next_action。

兼容策略:

  • 合同详情主展示仍继续使用 next_action。
  • 合同列表、workspace、搜索等响应字段不变。
  • 后端仍继续兼容旧客户端提交 next_action。

本片刻意没有做:

  • 没有删除 next_action / next_actions。
  • 没有停止后端旧写路径的兼容缓存。
  • 没有改合同详情主动作卡片文案。
  • 没有执行远端 smoke 部署。

验证:

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_contract_workflow.py::test_contract_update_accepts_action_hint_and_legacy_next_action yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_action_hint_derives_next_action_without_overriding_buttons yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_structured_action_context_overrides_action_hint -q
npm run typecheck
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py yuqei-contract-platform\services\contract-api\tests\test_health.py -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_display_cache_governance.py -q
python -m alembic -c alembic.ini heads

结果:

  • Python compile 通过。
  • action_hint 兼容写入和派生优先级回归通过。
  • Contract Web typecheck 通过。
  • Contract API 工作流、health/schema-check、display cache governance 测试通过。
  • Alembic head 仍为 20260630_0022。

下一片建议:

  • Slice 3.5.3-e:逐步停写旧 contracts.next_action / next_actions 兼容列,优先处理文件上传、审查任务、条款修复、审批流、归档流程这些仍手写旧列的路径。
  • 停写时继续保留 API 响应字段,由派生层输出。

Slice 3.5.3-e 实施记录

本片已将生产 SQLAlchemy 写路径中的旧 contracts.next_action / next_actions 手写逻辑收敛到统一派生兼容缓存 helper。

新增内容:

  • sync_contract_action_display_cache(session, row)。
  • helper 基于 derive_contract_display(...) 和 ContractActionContext 派生:
    • status_label
    • status_tone
    • next_action
    • next_actions

已替换的生产 SQLAlchemy 写路径:

  • 审批状态流:提交审批、退回、重提、审批通过、归档等统一状态流。
  • 发起审查。
  • 审查任务重新排队。
  • 审查任务完成。
  • 审查任务失败。
  • 上传合同文件。
  • 应用审查推荐条款。

关键语义:

  • 旧兼容列仍保留,但不再由这些 orchestration 分散手写文案。
  • 文件上传产生的“可发起法律审查”被迁入 action_hint,再由派生层同步到旧兼容列。
  • 条款修复先更新 review task 的风险项状态,再同步旧兼容列,确保能派生出“复核已应用的条款修订”。
  • 状态流先写审批实例/步骤/动作,再同步旧兼容列,确保能派生出“等待审批人审批”。

本片刻意没有做:

  • 没有删除 contracts.next_action / next_actions。
  • 没有移除方法签名中仍用于旧兼容调用面的 next_action / next_actions 参数。
  • 没有改 in-memory demo 仓储。
  • 没有升级 display_cache_governance 为完整结构化上下文检查。
  • 没有执行远端 smoke 部署。

验证:

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_contract_workflow.py::test_contract_status_display_cache_is_derived_on_write_paths yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_action_display_cache_is_derived_for_review_write_paths yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_upload_file_and_start_review_closes_review_entry_flow yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_structured_action_context_overrides_action_hint -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py yuqei-contract-platform\services\contract-api\tests\test_health.py -q
python -m pytest yuqei-contract-platform\services\contract-api\tests\test_display_cache_governance.py -q
npm run typecheck
python -m alembic -c alembic.ini heads

结果:

  • Python compile 通过。
  • 新增/扩展 action display cache 回归通过。
  • Contract API 工作流、health/schema-check、display cache governance 测试通过。
  • Contract Web typecheck 通过。
  • Alembic head 仍为 20260630_0022。

下一片建议:

  • 继续做 Slice 3.5.3-f:清理旧方法签名和兼容参数,将 _transition_contract(...)、ContractAuditRepository.transition_contract(...) 中的 next_action / next_actions 参数下沉移除或标记 deprecated。
  • 或者先做远端 192.168.3.90 smoke 部署验证:跑 migration 到 20260630_0022,复跑 /api/v1/runtime/schema-check,抽样合同创建、编辑人工跟进提示、提交审批、退回、重提、发起审查、文件上传、条款修复。

Slice 3.5.3-f 实施记录

本片已完成生产 SQLAlchemy 状态流内部签名收口:状态迁移不再接收旧 next_action / next_actions 展示参数。

调整范围:

  • ContractAuditRepository.transition_contract(...)
  • ContractAuditRepository.transition_contract_in_session(...)
  • SqlAlchemyTransitionOrchestration.transition_contract(...)
  • SqlAlchemyContractRepository._transition_contract(...)
  • 审批状态流调用:提交审批、退回、重提、审批通过。
  • 归档状态流调用。

关键语义:

  • 状态迁移只接收状态事实、允许状态集合、timeline action 和操作者请求。
  • 旧 contracts.next_action / contracts.next_actions 列仍保留。
  • 旧兼容列仍由 sync_contract_action_display_cache(session, row) 基于 derive_contract_display(...) 统一同步。
  • API 响应继续返回派生后的 next_action / next_actions。
  • 前端和旧客户端 PATCH 兼容策略不变。

本片刻意没有做:

  • 没有删除旧数据库列。
  • 没有移除 API DTO 中的 next_action / next_actions 兼容字段。
  • 没有改 InMemoryContractRepository 的 demo/test 内部 transition 参数,避免把生产 SQLAlchemy 收口扩大成 demo 仓储重写。
  • 没有进入后续 cleanup migration。

验证:

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_contract_workflow.py::test_submit_reject_resubmit_and_approve_workflow yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_support_operations_persist_with_sqlalchemy_repository yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_structured_action_context_overrides_action_hint -q

结果:

  • Python compile 通过。
  • 审批退回/重提/通过、归档支撑链路、结构化动作覆盖 action_hint 回归通过。

下一片建议:

  • 继续把生产写路径里剩余的旧展示字段入口收窄到 ContractUpdateRequest 兼容层和 seed/demo 初始化层,优先审计 persistence/contract_core.py 的更新路径与 seed_data.py 的历史默认值;仍不要删列。

Slice 3.5.3-g 实施记录

本片已完成 persistence/contract_core.py 更新兼容层和 seed_data.py 历史默认展示字段审计。

调整范围:

  • ContractCoreRepository.update_contract(...)
  • normalize_contract_update_fields(...)
  • ContractCoreRepository.add_contract_in_session(...)
  • contract_create_data_from_detail(...)
  • seed_data.py 三份 demo 合同的人工跟进提示字段

关键语义:

  • ContractUpdateRequest.action_hint 继续作为人工跟进提示事实字段。
  • 旧 ContractUpdateRequest.next_action 继续兼容接收,但会被规范化为 action_hint,不再直接写入 contracts.next_action。
  • 旧 ContractUpdateRequest.next_actions 继续兼容接收但不再写入 contracts.next_actions,按钮列表仍由派生层输出。
  • 合同创建和 seed 初始化后统一调用 sync_contract_action_display_cache(session, row),旧兼容列只保存派生结果。
  • V1/V2 demo 合同里的人工提示迁入 action_hint,next_action / next_actions 仅作为派生兼容缓存。

本片刻意没有做:

  • 没有删除旧数据库列。
  • 没有移除 API DTO 中的 next_action / next_actions 兼容字段。
  • 没有更改 InMemoryContractRepository 的 demo/test 内部写法。
  • 没有升级 display_cache_governance 为完整结构化上下文检查。

验证:

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_contract_workflow.py::test_create_and_update_contract_draft_persists_to_repository yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_update_accepts_action_hint_and_legacy_next_action yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_contract_action_hint_derives_next_action_without_overriding_buttons yuqei-contract-platform\services\contract-api\tests\test_contract_workflow.py::test_sqlalchemy_repository_persists_contracts_and_approval_timeline -q

结果:

  • Python compile 通过。
  • 旧 next_action PATCH 兼容到 action_hint 通过。
  • 旧 next_actions PATCH 不再覆盖派生按钮列表,回归通过。
  • seed demo 合同 action_hint 持久化与派生展示回归通过。

下一片建议:

  • 继续审计 display_cache_governance 与 search 文档生成是否要接入完整 ContractActionContext。当前仍先保持只读轻量检查,不急于删列。