阶段 当前状态 说明 Phase 0~3 基本完成 Document IR、证据链、人工确认、不可变 PlanData Snapshot、海报/PPT 投影已实现 Phase 4 代码完成 场景、策略、模板版本,校验/发布门禁,确定性 resolver 和严格槽位合并已实现 Phase 5 代码完成 输入冻结、PPTX/海报对账、失败关闭、幂等、心跳、重试和冻结输入重放已实现 Phase 6 基础完成 质量看板、结构化告警、Golden 审批、留存清理、孤儿检查和灰度开关已实现 正式上线 未完成 缺真实样本、生产模板、业务规则签字和灰度观察 目前验证基线: PPT/海报专项测试:107 passed, 1 skipped Vue TypeScript 检查:通过 前端生产构建:通过 代码变更仍在工作区,尚未提交 仓库全量测试仍有既有失败/挂起项,暂时不能宣称全仓测试完全绿色 仍未完成的代码任务主要有: 影子解析差异流水线 目前有灰度开关,但还没有完整的“新旧解析同时运行、字段差异入库、按保司/profile 聚合”的影子比较任务。 自动视觉回归 目前实现的是 DOM 模块、溢出、尺寸、文本和数值检查;还缺基于真实模板和标准图片的像素差异、字体缺失、遮挡和裁切回归。 告警通道接入 后台已经能产生结构化质量告警,但尚未自动推送到邮件、企微或其他通知通道。 留存任务生产化 dry-run、实删服务和失败审计已经具备,但尚未接入周期性 Celery/定时任务,也没有自动重试失败清理批次。 旧链路最终下线 旧 PPT 解析器和海报紧凑解析仍保留为回滚路径。需要全量灰度稳定后才能删除或彻底关闭写入口。 全仓测试收口 需要处理现有无关失败和挂起测试,建立真正全绿的 CI 基线。 仍需外部输入和生产环境完成的事项: 至少 30 份脱敏 Golden PDF,并完成双人标注和精确率验收。 业务专家确认派生公式、缺失值、可比较性和结论策略。 上传并标注真实生产 PPTX 的语义 shape、页面类型和容量。 安装生产字体并建立视觉基准图片。 实际执行数据库迁移 038~040。 完成留存 dry-run、实删演练以及 10% → 30% → 100% 灰度。 观察期通过后开启 SCENARIO_ENGINE_V2,目前它仍默认关闭;真实清理开关也默认关闭。 完整状态记录在 [PPT与海报Phase4至6补充实施记录](D:/work/code/python/coding/baodanagent/docs/PPT与海报Phase4至6补充实施记录_20260802.md)。
45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
"""迁移 037:PlanData、证据与不可变确认快照。"""
|
||
import logging
|
||
|
||
from sqlalchemy import inspect, text
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _add_columns_if_missing(table_name: str, columns: dict[str, str]) -> None:
|
||
"""一次读取现有列后完成本表变更,避免未提交 DDL 与二次反射互锁。"""
|
||
from insurance.db.compat import db
|
||
|
||
existing = {item["name"] for item in inspect(db.engine).get_columns(table_name)}
|
||
for column_name, ddl in columns.items():
|
||
if column_name not in existing:
|
||
db.session.execute(text(
|
||
f"ALTER TABLE {table_name} ADD COLUMN {column_name} {ddl}"
|
||
))
|
||
|
||
|
||
def migrate():
|
||
from insurance.db.compat import db
|
||
from insurance.models.plan_snapshot import (
|
||
InsuranceFieldEvidence,
|
||
InsurancePlanOverride,
|
||
InsurancePlanSnapshot,
|
||
)
|
||
|
||
for model in (InsurancePlanSnapshot, InsuranceFieldEvidence, InsurancePlanOverride):
|
||
model.__table__.create(bind=db.engine, checkfirst=True)
|
||
|
||
inspector = inspect(db.engine)
|
||
tables = set(inspector.get_table_names())
|
||
if "poster_case_uploads" in tables:
|
||
_add_columns_if_missing("poster_case_uploads", {
|
||
"document_id": "BIGINT",
|
||
"snapshot_id": "BIGINT",
|
||
})
|
||
if "insurance_ppt_sessions" in tables:
|
||
_add_columns_if_missing("insurance_ppt_sessions", {
|
||
"snapshot_ids_json": "TEXT",
|
||
})
|
||
db.session.commit()
|
||
logger.info("[migrate_037] PlanData 快照、证据与人工覆盖迁移完成")
|