# 模块 11:历史代码治理与可交付资产库
资产库不是提示词文件夹。 一份可交付资产要让使用者看得出:解决什么重复问题、需要什么输入、如何运行、输出什么、什么情况下不能继续,以及如何验证它仍然有效。
项目约束生成
项目知识构建
复杂业务设计
业务交付 Review
Review 修复闭环
--- # 历史代码识别:先定位职责交界
`OfficialVehicleDispatchServiceImpl.assign` 不是已被判定的缺陷;源码能确认的是,它是一个同时协调多个业务对象的入口。 | 源码事实 | 涉及对象 | 重构时必须保留的含义 | |---|---|---| | 申请已完成、且不能重复派车 | 申请 / 派车 | 拒绝条件仍在任何写入之前 | | 车辆可用且时间不冲突 | 车辆 / 派车 | 车辆选择不是只看当前状态 | | 需要司机时司机必填、且时间不冲突 | 司机 / 派车 | `needDriver` 决定额外前置条件 | | 创建派车任务后预占车辆 | 派车 / 车辆 | 两次写入处于同一个事务中 |
“职责交界较多”是重构候选,不等同于“现有实现有错误”。
--- # 重构方案先比选,再决定是否拆分
| 方案 | 对当前 `assign` 的处理 | 依据与判断 | |---|---|---| | 保留编排入口,提取校验段 | 分出申请、车辆、司机校验与派车创建的内部方法 | 保持事务、写入顺序和接口不变,便于定向测试 | | 合并车辆与司机冲突校验 | 抽成通用“资源冲突”组件 | 当前只有查询形状相似,数据模型和错误语义是否统一尚无证据 | | 将业务校验移动到前端 | 依赖页面下拉选项和表单必填 | 前端可被绕过,不能代替 Service 的业务保护 |
当前源码支持“先做内部拆分的可行性评估”,不支持直接引入跨领域的通用抽象。
--- # 重构风险审查要逐项回到现有行为
以 `cancel` 为例,以下行为来自当前 Service、Controller 和事务注解: | 风险点 | 当前行为 | 重构后的验证点 | |---|---|---| | 输入保护 | 空白取消原因在查询与写入之前被拒绝 | 无效输入不能读取或修改业务状态 | | 状态保护 | 只有 `DISPATCHED` 的派车任务可取消 | 非法状态被拒绝,不能释放车辆 | | 写入耦合 | 派车变为 `CANCELLED` 并记录原因;车辆恢复 `AVAILABLE` | 两类状态同时成功,异常时整体回滚 | | 接口边界 | Controller 保留取消权限、审计记录与成功语义 | 不因内部拆分丢失权限或审计入口 |
风险清单不是重构方案的附录,而是判断“能否改”的前提。
--- # TypeScript 类型治理:类型不能遮住契约冲突
当前公务用车模块已经提供了一个需要核验的跨端契约案例: | 位置 | 现有定义或行为 | 需要确认的事实 | |---|---|---| | 后端常量 | 审批结果仅定义 `pass` / `reject` | Service 只接受这两个小写值 | | 前端类型 | `ApproveResult` 同时允许大小写字符串和 `boolean` | 放宽联合类型掩盖了实际允许范围 | | 前端表单 | 审批选项提交 `PASS` / `REJECT` | 请求载荷与后端接收值是否一致 | | 申请状态模型 | 后端为字符串,前端同时接受字符串与 `number` | 需要明确接口中的唯一表示方式 |
源码已证明存在定义差异;是否发生运行时错误,仍需以实际请求和接口验证为准。
--- # 现有测试证明了什么,也暴露了什么
| 已有测试证据 | 能支持的结论 | 仍不能支持的结论 | |---|---|---| | `OfficialVehicleDispatchServiceImplTest` | 空白取消原因会在依赖访问前被拒绝 | 正常取消是否更新派车和车辆状态 | | `OfficialVehicleDispatchControllerTest` | 接口委派、成功提示和 Service 异常透传 | Service 内的状态校验、事务与持久化结果 | | 官方车辆模块的 Maven 测试配置 | 该后端模块可以执行 Surefire 测试 | 所有状态分支均已覆盖 | | 前端 `jest.config.mjs` | 当前前端已有 Jest 测试基座 | 派车页面或模型已经具备测试 |
“已有单测通过”只能说明已运行的场景通过,不能替代对未覆盖状态和副作用的判断。
--- # 单测补齐必须服从当前项目的测试基座
远程大纲中的“Vitest 单测补齐”,在当前项目应转换为“按既有测试框架补齐行为证据”。 | 测试目标 | 当前适用基座 | 应补的行为证据 | |---|---|---| | Service 规则 | JUnit 5 / Mockito | 非 `DISPATCHED` 取消被拒绝且不写入;正常取消同步更新派车与车辆 | | 派车前置条件 | JUnit 5 / Mockito | 未审批、重复派车、车辆不可用、需司机但缺司机等分支 | | 前端请求与模型 | Jest / Vue Test Utils | 审批值的真实载荷、派车表单的必填与可见条件 | | 跨端类型契约 | API 验证或集成测试 | 大小写审批值、状态值表示与服务端拒绝语义 |
不为引入新工具而另起 Vitest;先让现有 JUnit 和 Jest 覆盖真实业务行为。
--- # 拆开一个真实 Skill 包
```text track-review-fix-loop/ ├── SKILL.md # 输入、状态模型、流程、输出与质量门禁 ├── agents/openai.yaml # 展示名、简介和默认触发语 └── assets/ ├── 修复记录生成.prompt.md # 将原始材料整理为固定结构 ├── 修复记录.template.md # 下游可消费的结果格式 ├── Review修复闭环检查清单.md # 固定遗漏点 └── 多份反例.md # 权限、审计、状态等典型误用 ```
核心文档不求长,而是把“输入、判断、输出、停止、验证”写成能被人和 Agent 同时执行的契约。
--- # 资产库需要一个可检索的索引
| 索引字段 | 要回答的问题 | 示例 | |---|---|---| | 资产名称与类型 | 这是 Rule、Prompt、Skill 还是 Agent? | 状态变更审查 Agent | | 适用信号 | 什么任务应该选择它? | 涉及状态写入或资源释放 | | 必要输入 | 缺少什么就不能运行? | 目标、源码、状态规则、验证记录 | | 输出契约 | 结果能交给谁使用? | 事实表、方案比较、验证清单 | | 权威位置 | 应到哪个文件更新? | Skill 的 SKILL.md 或 assets/ | | 复核触发 | 什么变化会使它失效? | 框架、流程、接口或真实误用变化 |
索引不记录“有哪些好提示词”,而是帮助使用者快速判断“此刻该用哪一份资产”。
--- # 用测试夹具验证资产,而不是验证文案
| 夹具类型 | 提供的材料 | 应观察的行为 | |---|---|---| | 完整事实 | 入口、状态、diff 与测试记录齐全 | 结论可追溯,输出结构完整 | | 证据缺失 | 缺少关键 Service 或验证记录 | 明确列出缺口并停止结论 | | 范围冲突 | 同时要求改数据库、权限和页面 | 指出越界,不默认扩大改动 | | 反例输入 | 已知的权限、审计或状态误用 | 能识别风险并引用检查项 | | 跨项目输入 | 不同目录、字段、框架和测试基座 | 重新取证,不复制旧项目结论 |
资产测试关心的是边界是否正确,不要求模型每次生成完全相同的句子。
--- # 资产库还应包含 MCP 能力契约
案例提供事实;资产保存判断;自定义 Agent 在受控权限下调用这些资产。连接外部系统的 MCP 还需要独立的能力与权限契约。
选型
Rule
Prompt
Skill
Agent
验证