# 迁移前后业务语义对照分析

## 1. 文档目的

本文档只做一件事：

- 把迁移前项目 `/home/wren-dev/Porject/govdoc-audit` 的**真实业务语义**与当前 `leaudit-platform` 中 `govdoc` 模块的**平台化实现语义**对齐清楚

本文档的目标不是要求“旧项目代码逐行照搬”，而是明确以下边界：

- **业务逻辑不改**
- **代码实现方式可以按当前项目规范重构**
- **平台化接入可以改承载层，但不能改业务语义**

换句话说：

- 可以从旧项目的 `audit_id` 单体模型迁移为当前平台的 `document + run` 模型
- 可以从本地文件持久化迁移为 `DB + OSS + worker`
- 可以从独立 FastAPI 项目迁移为 `leaudit-platform` 的模块化结构

但不能把“公文格式审查业务”改造成另一套语义。

---

## 2. 结论先行

本次迁移应遵守的总原则是：

> **保持业务语义一致，允许技术实现重构。**

具体解释如下：

- **不要求旧项目的目录结构、表结构、路由写法、同步/异步实现方式一字不改**
- **要求用户视角的业务流程、结果语义、报告语义、规则语义、页面交互语义保持一致**
- **要求新增实现遵守当前 `leaudit-platform` 的代码规范、分层方式、权限体系、存储方式、路由组织方式**

因此，后续所有补齐和修复都必须先回答一个问题：

> 这是“实现方式变化”，还是“业务语义变化”？

只有前者允许直接重构；后者必须先明确是否获得业务确认。

---

## 2.1 必须继承什么，不继承什么

为了避免把“参考旧项目”误解成“照搬旧代码”，这里把边界明确写死。

### 必须继承的是业务语义

必须继承的，是旧项目已经成立并已对外生效的业务语义，包括：

- 审查对象是什么
- 审查链路顺序是什么
- 规则怎么定义、怎么解释
- 结果对象由哪些部分构成
- `pass / fail / skipped` 三分态语义
- 报告产物有哪些
- 详情页交付什么能力
- 规则版本如何追溯

也就是说，必须继承的是：

- **业务口径**
- **结果口径**
- **规则口径**
- **交付口径**

### 不必须继承的是旧实现

不必须继承的，是旧项目为了落地这些业务语义所采用的具体技术实现，包括：

- 旧目录结构
- 旧项目模块拆分
- 旧接口路径
- 旧表结构
- 旧本地文件存储方式
- 旧同步执行方式
- 旧前端工程组织方式
- 旧缓存或本地路径约定

也就是说，不需要继承的是：

- **代码写法**
- **工程结构**
- **部署方式**
- **存储承载方式**

### 正确理解

因此，“以旧项目为基线”这句话，准确含义应是：

> **以旧项目作为业务语义基线，而不是作为代码实现模板。**

后续所有实施动作，都应按下面这个标准判断：

- 如果是在恢复旧业务语义，可以推进
- 如果是在复制旧实现细节，不应作为目标

这也是后续为什么应说：

- **按旧业务语义补齐**

而不应简单说：

- **补齐到旧项目**

---

## 3. 迁移前项目的业务基准

## 3.1 业务定位

迁移前项目 `govdoc-audit` 的本质不是普通文档管理，也不是审批流系统，而是：

- **内部公文格式审查系统**

其目标是：

- 上传一份公文文件
- 对公文格式、结构、文种、实体、规则进行审查
- 产出一份完整审查结果和对应报告产物

因此它的核心不是“保存文件”，而是：

- **完成一次完整审查并交付审查结果**

---

## 3.2 核心业务对象

旧项目的核心业务对象是：

- `AuditResult`

它聚合了以下业务结果：

- `document`
- `summary`
- `findings`
- `checked_rules`
- `entities`
- `structure`
- `outline`

这说明旧项目的业务中心是：

- **一次完整审查结果**

而不是：

- 单纯的文档主档
- 单纯的异步任务记录
- 单纯的某次规则执行流水

当前平台即使改为 `document + run` 模型，也必须保证对外仍能还原这一语义。

---

## 3.3 旧项目固定主链路

旧项目的审查链路顺序是明确且稳定的：

1. 上传文件
2. 统一转换为 `canonical.docx`
3. 解析文档结构 `parse_docx`
4. 角色标注 `role_tag`
5. 加载规则 `load_rules`
6. 先做结构化实体构建 `build_entities`
7. 对缺失实体做差量 LLM 抽取
8. 执行规则评估 `evaluate_rules`
9. 生成完整 `AuditResult`
10. 生成报告产物
11. 持久化结果

这条链路可以按当前项目规范拆层，但业务顺序不能被破坏。

---

## 3.4 旧项目的结果语义

旧项目对结果有几条明确语义：

- `summary` 是结果总览，不是从前端临时拼装出来的派生值
- `findings` 是问题清单，是详情页审查视图的主数据
- `checked_rules` 是规则级结果清单，且必须保留 `pass / fail / skipped`
- `entities` 不只是调试数据，而是前端“实体”标签页正式展示内容
- `structure` 与 `outline` 是正式交付数据，不是可有可无的附加信息

这意味着迁移后不能只保证“能查到一部分结果”，而必须保证：

- **前端详情页所依赖的一整组业务结果是完整成立的**

---

## 3.5 旧项目的规则语义

旧项目规则体系虽然技术上只是单个 YAML 文件，但业务语义是完整的：

- 有一个当前生效规则集
- 规则集有明确元数据：`type_id / version / source / description`
- 每次审查结果都知道自己使用的是哪一版规则
- 前端可以查看当前规则列表和单条规则详情

因此迁移到平台后：

- 可以不再沿用旧项目“本地单 YAML + 本地缓存”的实现方式
- 但必须保留“当前生效规则集 + 规则版本可追溯 + 规则详情可查看”的业务语义

---

## 3.6 旧项目的报告语义

旧项目一次审查完成后，正式产物包括：

- 原始文件 `original`
- 标准化文档 `canonical.docx`
- 审查结果 `result.json`
- 批注文档 `annotated.docx`
- 报告页面 `report.html`
- 段落视图 `paragraphs.html`

这里最关键的是：

- **报告产物不是附属功能，而是审查业务结果的一部分**

旧项目里，详情页默认就可以使用：

- 原始文件下载
- 批注 DOCX 下载
- 报告 HTML 打开
- 段落视图联动预览

因此迁移到平台后，不能接受以下状态长期存在：

- run 已完成，但报告产物为空
- 前端按钮可点，但实际上无真实产物
- 详情页只展示结构化 JSON 结果，不恢复正式报告闭环

---

## 3.7 旧项目的页面交互语义

旧项目前端已形成稳定交互语义：

- 列表页是主入口
- 上传成功后直接进入详情页
- 详情页是完整审查结果页
- `报告 HTML / 批注 DOCX / 原始文件 / 段落预览` 是四种不同能力
- 问题列表与段落视图双向联动
- `问题 / 已通过 / 已跳过` 是三分态展示，不可压扁为两态
- 详情页 `review / structure / outline / entities` 是正式功能页签

迁移时页面风格、代码写法、路由框架可以变化，但交互语义不能被弱化。

---

## 4. 当前平台允许变化的实现层

以下变化属于**承载层重构**，原则上允许：

## 4.1 对象模型变化

旧项目：

- `audit_id` 是单一业务主键

当前平台可改为：

- `document` 作为文档主档
- `run` 作为执行记录

但要求：

- 对外仍然要能还原“某份文档当前/某次完整审查结果”
- 前端详情页不能被迫暴露底层拆分复杂性

---

## 4.2 存储方式变化

旧项目：

- 本地目录存文件
- SQLite/本地 DB 存列表摘要

当前平台可改为：

- OSS 存原文和报告产物
- PostgreSQL 存文档、run、规则结果、产物索引

但要求：

- 存储迁移不能导致产物语义丢失
- 列表和详情所需的结果字段必须仍然可稳定读取

---

## 4.3 执行方式变化

旧项目：

- 上传后同步或准同步返回完整结果

当前平台可改为：

- 上传后创建 `run`
- 通过 Celery/worker 异步执行

但要求：

- 最终完成后必须补齐旧项目那套完整审查结果语义
- 不能因为改成异步，就把“正式报告产物”降级成以后再说的可选项

---

## 4.4 代码组织变化

旧项目：

- 独立项目，接口、存储、规则、前端相对直连

当前平台可改为：

- `controller / service / bridge / engine / model / frontend api adapter`

但要求：

- 新实现必须遵守当前项目开发规范
- 不能为了“像旧项目”而破坏当前平台已有规范

换句话说：

- **保业务，不保旧代码写法**

---

## 4.5 路由变化

旧项目：

- `/audit`
- `/audits`
- `/rules`

当前平台可改为：

- `/govdoc/documents`
- `/govdoc/runs`
- `/govdoc/rules`

但要求：

- API 适配层必须把旧前端依赖的业务语义重新拼装出来
- 不能让前端为了适应后端重构而失去旧业务能力

---

## 5. 当前平台必须保持不变的业务语义

以下内容视为迁移边界，后续不得随意更改。

## 5.1 审查本质不变

`govdoc` 仍然是：

- **内部公文格式审查模块**

不是：

- 流程审批模块
- 纯文档归档模块
- 单纯的规则管理模块

---

## 5.2 结果对象语义不变

即便底层是 `document + run`，对外仍必须稳定提供：

- `summary`
- `findings`
- `checked_rules`
- `entities`
- `structure`
- `outline`

这些必须被视为同一份审查结果的正式组成部分。

---

## 5.3 内置实体语义不变

以下 8 个内置实体语义必须保留：

- `title`
- `doc_number`
- `recipient`
- `date`
- `signature`
- `attachments`
- `wenzhong`
- `issuer`

迁移后可以调整存储位置和实现方式，但不能弱化为“可有可无”。

---

## 5.4 评分语义不变

评分规则保持：

- `error` 每条扣 10
- `warning` 每条扣 3
- 最低 0

列表状态分段保持：

- `pass >= 90`
- `warning 70-89`
- `fail < 70`

这既影响后端汇总，也影响前端筛选和颜色语义。

---

## 5.5 规则状态语义不变

`checked_rules` 必须保留：

- `pass`
- `fail`
- `skipped`

不能做以下简化：

- 把 `skipped` 并入 `fail`
- 只保留问题规则，不保留通过/跳过规则

---

## 5.6 报告产物语义不变

迁移后必须恢复并保持以下正式能力：

- 原始文件下载
- 批注 DOCX 下载
- 报告 HTML 打开
- 段落视图联动预览

如果某项能力在页面上出现按钮或入口，就必须对应真实可用的后端产物。

---

## 5.7 规则版本追溯语义不变

每次审查必须知道：

- 使用了哪套规则
- 使用了哪一版规则

旧项目是 `ruleset_id / ruleset_version`，新平台可以改成平台自己的规则版本对象，但业务追溯语义不能丢。

---

## 5.8 页面交互语义不变

必须保留：

- 上传成功后直接进入详情
- 列表作为主入口
- 列表可查看、导出、删除
- 详情页具备完整结果展示
- 问题与段落视图双向联动
- 详情页保留 `review / structure / outline / entities`

页面样式可以按当前项目统一，但交互语义不能被削弱。

---

## 6. 当前平台与旧项目的主要差异判断

这里不讨论代码优劣，只判断“是否偏离业务语义”。

## 6.1 已经属于等价平台化改造的部分

以下变化本身没有问题：

- 以 `leaudit_documents` 复用文档主档
- 新增 `govdoc_runs` 记录执行历史
- 使用 worker 异步执行
- 使用 `govdoc_rule_results` 存储规则结果
- 前端通过适配层把 `document + run` 再组装成详情页结果

这些属于合理平台化改造。

---

## 6.2 已偏离旧项目业务语义的部分

以下问题不是单纯代码 bug，而是业务语义没有完全迁回来：

### 6.2.1 报告产物闭环未恢复

当前若 `run completed` 但 `annotated.docx / report.html` 没有真实产物，则已偏离旧项目“完成一次审查即交付正式报告”的业务语义。

### 6.2.2 规则版本参数未真正生效

如果接口出现了 `ruleVersionId`，但执行时仍然只走固定 YAML 路径，则不满足旧项目“当前规则集明确、结果可追溯”的业务语义，也不满足平台化后的规则治理预期。

### 6.2.3 文件能力被收缩但未做业务确认

旧项目支持 `.docx / .doc / .wps`，当前平台若只支持 `.docx`，这不一定绝对错误，但它已经是业务能力收缩，必须明确确认，不能默认当作正常迁移。

### 6.2.4 详情页结果仍依赖多接口拼接且存在缺口

旧项目详情页本质上拿到的是一份完整审查结果。当前平台如果只是“部分接口可用、部分产物缺失、部分状态不一致”，则尚未恢复旧项目业务完整性。

---

## 6.3 属于当前平台规范问题但不构成业务变更的部分

以下属于实现层改良点，不构成业务逻辑变化：

- 按当前项目规范补 service 分层
- 按当前项目规范补 schema / model / DDL
- 按当前项目规范补权限、菜单、entryModule
- 使用 OSS 而不是本地目录
- 使用 worker 而不是同步执行
- 把旧项目前端接口改成新平台 API adapter

这些都应当做，而且应该做得更规范。

---

## 7. 后续实施的硬边界

后续所有开发和修复，必须同时满足两条：

1. **业务语义对齐旧项目**
2. **代码实现遵守当前平台规范**

任何方案如果只满足其中一条，都不能视为合格迁移。

### 7.1 不能接受的方案

- 只求接口返回 200，不管结果是否构成完整审查语义
- 只把页面先点亮，不补正式报告产物
- 只保留 JSON 结果，不恢复批注 DOCX 和 HTML 报告
- 为了适配平台，擅自删除 `skipped`、实体页、结构页、大纲页等旧业务能力
- 用硬编码规则路径长期替代规则版本治理

### 7.2 可以接受的方案

- 底层对象从 `audit` 拆成 `document + run`
- 用异步 `run` 承载旧项目同步审查流程
- 用平台规则版本体系承载旧项目 `ruleset_id / ruleset_version`
- 用 OSS 索引表承载旧项目本地报告文件
- 用平台前端适配层恢复旧项目页面语义

---

## 8. 面向后续实施的判定标准

后续补齐时，建议每一项改动都按下面三个问题判断：

### 8.1 这项改动是在补实现，还是在改业务？

如果是补实现，可以继续推进。

如果是改业务，必须先业务确认。

### 8.2 这项改动是否恢复了旧项目正式能力？

例如：

- 是否恢复正式报告产物
- 是否恢复规则版本追溯
- 是否恢复详情页完整结果

### 8.3 这项改动是否符合当前项目规范？

例如：

- 是否走当前项目的 service / controller / bridge 分层
- 是否复用平台已有文档主档、权限、存储、规则治理能力
- 是否避免写出一套脱离平台的新“旧系统兼容层”

---

## 9. 结论

本次内部公文模块迁移，不应理解为：

- 旧项目代码照搬

也不应理解为：

- 只要能在当前平台里跑起来就算完成

正确理解应是：

> **旧项目负责定义业务语义，当前平台负责承载实现。**

因此后续实施必须坚持：

- **业务逻辑保持一致**
- **代码实现按当前项目规范重构**
- **平台化不等于业务降级**

在这个前提下，后续才有资格进入正式的补齐修复计划和实施排期。

---

## 10. YAML 迁移现状补充结论

这一节专门回答一个更具体的问题：

- 旧项目内部公文的 `rules.yaml` 有没有迁到当前平台
- 迁过来之后，是否符合当前平台的格式

### 10.1 先说结论

结论分三层：

1. **DSL 格式层面：已经迁过来，而且当前平台可以直接解析执行**
2. **规则内容层面：不是完整迁移，只迁了一个最小可运行规则集**
3. **规则标识层面：`type_id` 命名发生了变化，这属于语义边界，需要后续明确是否回归旧命名**

也就是说：

- 不能说“内部公文 YAML 没迁”
- 但也不能说“旧项目规则已经完整迁完”

更准确的表述是：

> **当前平台已经有一份按 `govdoc` DSL 编写、可被当前引擎真实加载执行的内部公文规则 YAML，但它只是旧项目完整规则语义的缩减版。**

---

### 10.2 当前平台与旧项目用的是同一套 govdoc DSL

旧项目规则文件：

- `/home/wren-dev/Porject/govdoc-audit/rules/govdoc_general/rules.yaml`

当前平台规则文件：

- `/home/wren-dev/Porject/leaudit-platform/rules/govdoc/govdoc_general/rules.yaml`

两边都采用同样的三段结构：

- `metadata`
- `extract`
- `rules`

并且两边 DSL schema 是同源的：

- 旧项目：`/home/wren-dev/Porject/govdoc-audit/src/govdoc_audit/dsl/schema.py`
- 当前平台：`/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/govdoc_engine/dsl/schema.py`

我已直接核对：

- `CheckType` 集合一致
- `Rule / RuleGroup / RuleSet` 结构一致
- `load_rules()` 加载方式一致

因此这里的事实不是：

- 旧项目一套 YAML
- 当前平台另一套 YAML

而是：

- **旧项目和当前平台本来就在使用同一套 `govdoc DSL`**

所以“按照我们的平台格式”这句话，正确理解应该是：

- **是否符合当前平台 `govdoc_engine` 的 DSL 格式**

而不是：

- 是否长得像合同规则那套 `leaudit DSL`

---

### 10.3 当前平台这份 YAML 已经被真实接入，不是摆设

当前平台 `govdoc` 服务里，规则文件解析路径已经明确指向：

- `rules/govdoc/govdoc_general/rules.yaml`

代码位置：

- [govdocServiceImpl.py](/home/wren-dev/Porject/leaudit-platform/fastapi_modules/fastapi_leaudit/services/impl/govdocServiceImpl.py:963)

并且我已用当前平台 loader 直接解析成功：

- `metadata.type_id = govdoc_general`
- `metadata.name = 内部公文通用规则`
- `2` 个规则组
- `6` 条规则

这说明：

- **当前平台里的内部公文 YAML 不是未接入状态**
- **它已经是当前 `govdoc` 引擎实际使用的规则源**

---

### 10.4 但规则内容不是旧项目全量迁移

旧项目规则文件统计结果：

- `8` 个规则组
- `31` 条规则

当前平台规则文件统计结果：

- `2` 个规则组
- `6` 条规则

而且两边 `rule_id` 没有重叠，说明当前平台这份 YAML 不是“把旧规则原样搬过来后删了几条”，而是：

- **重新写了一个最小规则集**

当前平台保留的 6 条规则是：

- `govdoc_title_required`
- `govdoc_doc_number_required`
- `govdoc_signature_required`
- `govdoc_date_required`
- `govdoc_wenzhong_whitelist`
- `govdoc_attachment_marker_style`

这 6 条规则只覆盖了：

- 标题是否识别
- 发文字号是否识别
- 署名是否识别
- 日期是否识别
- 文种是否合法
- 附件标记样式

它更像：

- **内部公文链路先跑通时的最小可运行审查集**

而不是：

- **旧项目完整业务规则集**

---

### 10.5 旧项目已存在、但当前平台尚未完整迁入的规则语义

旧项目那份规则 YAML 中，明确存在以下业务语义，而当前平台现有 YAML 尚未完整覆盖：

#### 10.5.1 标题类规则

- 标题文种合规性 AI 判断
- `"请求"+"请示"` 重复表述
- `"上报"+"报告"` 重复表述
- `"关于"+"对"` 介词连用
- 标题回行破词检查
- 标题字体字号检查

#### 10.5.2 发文字号规则

- 年份必须用六角括号 `〔〕`
- 顺序号前不加 `第`
- 顺序号不编虚位

#### 10.5.3 格式规则

- 主标题字体
- 一级标题字体
- 二级标题字体
- 正文字体
- 三级标题字体
- 四级标题字体
- 附件后不加冒号
- 不使用“此页无正文”
- 附件项末尾不加标点
- 附件标记字体样式

#### 10.5.4 层级序号规则

- 层级序号格式
- 二级标题换行不带句号

#### 10.5.5 标点规则

- 并列书名号/引号之间不加顿号
- 句内括号末尾不加标点
- 引号嵌套规范

#### 10.5.6 文字表述与提法规则

- 易混淆词
- 简称使用规范
- 成文日期必须用阿拉伯数字
- 成文日期不编虚位

#### 10.5.7 发文机关规则

- 发文机关署名不能用简称
- 发文机关与党务/行政文稿性质一致性检查

这些规则并不是“旧项目里某些未来能力”，而是旧项目已经写进当前正式规则集、并通过 DSL 表达出来的既有业务语义。

因此从迁移判断上讲，当前状态应定义为：

- **格式已迁**
- **规则内容仅部分迁移**

不能定义为：

- 完整迁移

---

### 10.6 当前平台 DSL 能力足够承接旧规则，不存在“格式不兼容”问题

我核对了旧项目规则里实际使用到的检查类型，包括：

- `ai`
- `attachment_marker_style`
- `confused_pair`
- `cross_role`
- `font`
- `forbid_chars`
- `forbid_phrase`
- `hierarchy`
- `punctuation`
- `regex_forbid`
- `wenzhong_whitelist`

这些检查类型都已经存在于当前平台 `govdoc_engine` 的 schema 与执行器中。

这意味着：

- 当前没完整迁入旧规则，**主要不是因为平台 DSL 不支持**
- 而是因为当前仓库只先落了一份缩减规则集

这点很重要，因为它直接限定了后续实施边界：

- 后续补齐旧规则时，原则上应优先补 YAML 内容
- 不应先假设必须重写一套新的业务逻辑

---

### 10.7 需要特别注意的边界：`type_id` 命名已变化

旧项目规则元数据：

- `metadata.type_id: govdoc.general`

当前平台规则元数据：

- `metadata.type_id: govdoc_general`

这不是格式错误，但它是一个需要明确的语义边界，因为旧项目里与规则集相关的设计、文档、测试、存储语义，大量使用的是：

- `govdoc.general`

当前平台现在改成了：

- `govdoc_general`

因此这里至少要明确一件事：

- 这是当前平台有意做的命名收敛
- 还是迁移过程中临时改写后的遗留差异

在没有进一步统一之前，当前更稳妥的结论是：

- **当前平台规则 YAML 在 DSL 格式上是合法的**
- **但其 `type_id` 与旧项目规则集标识并不完全一致**

这个差异不一定马上要改，但必须在后续实施时被明确记录，避免后面在规则版本治理、回溯、接口契约、前端展示上继续漂移。

---

### 10.8 最终判断

针对“内部公文 YAML 有没有迁移过来，是否按我们平台格式”这个问题，最终判断如下：

- **有迁过来**
- **格式上符合当前平台 `govdoc` 引擎 DSL**
- **并且已经被当前平台真实加载使用**
- **但只迁了最小可运行规则集，不等于旧项目完整规则语义已经迁完**
- **另外 `metadata.type_id` 从 `govdoc.general` 变成了 `govdoc_general`，这是一个应显式管理的命名差异**

所以后续如果要继续推进，不应再讨论“要不要重新发明一套内部公文规则格式”，而应直接进入更准确的问题：

> **在保持当前平台 `govdoc DSL` 不变的前提下，如何把旧项目内部公文 31 条规则语义按当前平台规范补齐回来。**
