Files
TARE-Learn/slidev/pages/day5/m11-asset-library-delivery.md
smart 67837df8d0 docs: 更新TRA编程培训课程材料、课件与AI技能交付包
- 新增全套考试卷、评估卷、参考答案与考试培训包模板
- 修正slidev培训课件:调整模块标题、链路图缩放,替换工单示例为通用业务对象
- 修正课堂红线表述为证据红线,将小组作业调整为个人作业要求
- 新增权限、状态流转、审计日志、看板指标四类可复用业务规则块
- 整理AI工程技能交付包,迁移旧资产至客户专属交付包并统一术语
- 新增考试输出模板与TRAE使用记录文档
2026-08-08 11:00:36 +08:00

286 lines
16 KiB
Markdown
Raw Permalink 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.
# 模块 11:历史代码治理与可交付资产库
<div class="mt-6 text-sm">
资产库不是提示词文件夹。
一份可交付资产要让使用者看得出:解决什么重复问题、需要什么输入、如何运行、输出什么、什么情况下不能继续,以及如何验证它仍然有效。
</div>
<div class="grid grid-cols-5 gap-3 mt-8 text-xs">
<div class="p-3 rounded-xl bg-blue-500/10 border border-blue-500/30">项目约束生成</div>
<div class="p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30">项目知识构建</div>
<div class="p-3 rounded-xl bg-amber-500/10 border border-amber-500/30">复杂业务设计</div>
<div class="p-3 rounded-xl bg-purple-500/10 border border-purple-500/30">业务交付 Review</div>
<div class="p-3 rounded-xl bg-red-500/10 border border-red-500/30">Review 修复闭环</div>
</div>
<!--
逐字稿:资产库不是把好用的提示词集中存放,而是让使用者可以判断何时该用、需要什么输入、会得到什么结果、在哪些情况下不能继续。当前交付包中的五个 Skill 都是已有真实材料,它们的共同点是能被发现、运行、验证和维护,而不是目录看起来整齐。
课程交付包中已存在以上五个真实 Skill 包,均有 SKILL.md,部分还包含 agents/openai.yaml、Prompt、模板、检查单、反例、参考资料或脚本。本模块直接以这些现有资产为原料,不捏造新的目录规范。
-->
---
# 历史代码识别:先定位职责交界
<div class="mt-5 text-xs">
`OfficialVehicleDispatchServiceImpl.assign` 不是已被判定的缺陷;源码能确认的是,它是一个同时协调多个业务对象的入口。
| 源码事实 | 涉及对象 | 重构时必须保留的含义 |
|---|---|---|
| 申请已完成、且不能重复派车 | 申请 / 派车 | 拒绝条件仍在任何写入之前 |
| 车辆可用且时间不冲突 | 车辆 / 派车 | 车辆选择不是只看当前状态 |
| 需要司机时司机必填、且时间不冲突 | 司机 / 派车 | `needDriver` 决定额外前置条件 |
| 创建派车任务后预占车辆 | 派车 / 车辆 | 两次写入处于同一个事务中 |
</div>
<div class="mt-6 p-3 rounded-xl bg-blue-500/10 border border-blue-500/30 text-sm">
“职责交界较多”是重构候选,不等同于“现有实现有错误”。
</div>
<!--
逐字稿:远程大纲里的历史代码问题识别,不能靠看函数长短就下结论。这个真实的 assign 方法大约四十行,但已经协调申请、车辆、司机和派车任务四类对象。它既校验状态和时间冲突,又写入派车任务和车辆状态。
这里能得出的专业结论是:它是值得评估的重构候选,因为职责交界多;不能直接说它是坏代码或有生产缺陷。TRAE 的第一步应该把每一条源码事实、涉及对象和不可改变的含义列清楚,而不是立刻要求它输出一份重构 Diff。
-->
---
# 重构方案先比选,再决定是否拆分
<div class="mt-5 text-xs">
| 方案 | 对当前 `assign` 的处理 | 依据与判断 |
|---|---|---|
| 保留编排入口,提取校验段 | 分出申请、车辆、司机校验与派车创建的内部方法 | 保持事务、写入顺序和接口不变,便于定向测试 |
| 合并车辆与司机冲突校验 | 抽成通用“资源冲突”组件 | 当前只有查询形状相似,数据模型和错误语义是否统一尚无证据 |
| 将业务校验移动到前端 | 依赖页面下拉选项和表单必填 | 前端可被绕过,不能代替 Service 的业务保护 |
</div>
<div class="mt-6 p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30 text-sm">
当前源码支持“先做内部拆分的可行性评估”,不支持直接引入跨领域的通用抽象。
</div>
<!--
逐字稿:有了职责事实,第二步才是方案比选。对当前代码,最小且可证实的候选方案是保留 assign 作为事务编排入口,把申请、车辆、司机校验以及派车创建拆成内部职责段。这样不改变 Controller、接口和写入顺序,同时让关键判断可以被单独阅读和测试。
车辆和司机的时间冲突查询看起来相似,但它们的对象、字段和错误语义是否适合统一,目前没有足够事实。因此不能因为“看到重复”就强行抽象。把校验搬到前端同样不成立,因为接口仍可被绕过。TRAE 输出的应是方案比选与依据,而不是未经审查的改写代码。
-->
---
# 重构风险审查要逐项回到现有行为
<div class="mt-5 text-xs">
以 `cancel` 为例,以下行为来自当前 Service、Controller 和事务注解:
| 风险点 | 当前行为 | 重构后的验证点 |
|---|---|---|
| 输入保护 | 空白取消原因在查询与写入之前被拒绝 | 无效输入不能读取或修改业务状态 |
| 状态保护 | 只有 `DISPATCHED` 的派车任务可取消 | 非法状态被拒绝,不能释放车辆 |
| 写入耦合 | 派车变为 `CANCELLED` 并记录原因;车辆恢复 `AVAILABLE` | 两类状态同时成功,异常时整体回滚 |
| 接口边界 | Controller 保留取消权限、审计记录与成功语义 | 不因内部拆分丢失权限或审计入口 |
</div>
<div class="mt-6 p-3 rounded-xl bg-amber-500/10 border border-amber-500/30 text-sm">
风险清单不是重构方案的附录,而是判断“能否改”的前提。
</div>
<!--
逐字稿:重构风险审查要回到可以观察的现有行为。这里以 cancel 为例:空白原因必须先被拒绝;只有已派车状态才能取消;取消会同时更新派车和车辆;Controller 还承载权限和审计入口。这些都不是一般性原则,而是当前项目源码已经具备的行为。
任何拆分或整理代码的方案,都必须逐项说明如何保护这些行为。否则即使方法更短,也可能让非法取消释放车辆,或者在异常时留下半完成状态。第五天在这里讲的是重构前的风险清单;第六天才会处理改动完成后的 PR、CI 和回退证据。
-->
---
# TypeScript 类型治理:类型不能遮住契约冲突
<div class="mt-5 text-xs">
当前公务用车模块已经提供了一个需要核验的跨端契约案例:
| 位置 | 现有定义或行为 | 需要确认的事实 |
|---|---|---|
| 后端常量 | 审批结果仅定义 `pass` / `reject` | Service 只接受这两个小写值 |
| 前端类型 | `ApproveResult` 同时允许大小写字符串和 `boolean` | 放宽联合类型掩盖了实际允许范围 |
| 前端表单 | 审批选项提交 `PASS` / `REJECT` | 请求载荷与后端接收值是否一致 |
| 申请状态模型 | 后端为字符串,前端同时接受字符串与 `number` | 需要明确接口中的唯一表示方式 |
</div>
<div class="mt-6 p-3 rounded-xl bg-red-500/10 border border-red-500/30 text-sm">
源码已证明存在定义差异;是否发生运行时错误,仍需以实际请求和接口验证为准。
</div>
<!--
逐字稿:远程大纲里的 TypeScript 类型治理,在当前项目中不是补一份 interface,而是发现跨端契约被宽泛类型掩盖的情况。后端审批常量只定义小写 pass 和 reject;前端类型却允许大小写字符串和布尔值,表单实际配置的是大写值。申请状态也同时接受字符串和数字,而后端实体是字符串。
这里要严格区分事实和推断:源码已经能证明定义存在差异,但没有实际请求或接口执行记录,不能直接声称线上一定报错。正确的资产产出是类型契约和核验项:每个字段的唯一表示、允许值、请求样例、服务端拒绝语义以及对应测试,而不是继续用更宽的联合类型把问题藏起来。
-->
---
# 现有测试证明了什么,也暴露了什么
<div class="mt-5 text-xs">
| 已有测试证据 | 能支持的结论 | 仍不能支持的结论 |
|---|---|---|
| `OfficialVehicleDispatchServiceImplTest` | 空白取消原因会在依赖访问前被拒绝 | 正常取消是否更新派车和车辆状态 |
| `OfficialVehicleDispatchControllerTest` | 接口委派、成功提示和 Service 异常透传 | Service 内的状态校验、事务与持久化结果 |
| 官方车辆模块的 Maven 测试配置 | 该后端模块可以执行 Surefire 测试 | 所有状态分支均已覆盖 |
| 前端 `jest.config.mjs` | 当前前端已有 Jest 测试基座 | 派车页面或模型已经具备测试 |
</div>
<div class="mt-6 p-3 rounded-xl bg-purple-500/10 border border-purple-500/30 text-sm">
“已有单测通过”只能说明已运行的场景通过,不能替代对未覆盖状态和副作用的判断。
</div>
<!--
逐字稿:这张表只陈述已经找到的测试证据。Service 测试验证空白原因会立即抛出异常;Controller 测试验证请求是否正确委派、成功消息和异常透传。它们都很有价值,但还不能证明正常取消后派车状态和车辆状态是否按预期同时更新,也不能证明 assign 的多种拒绝条件。
前端项目使用 Jest 配置,后端官方车辆模块使用 JUnit 和 Maven Surefire。测试通过的正确表述应该是“已覆盖某个场景”,而不是“取消功能已经全面验证”。这也是让 TRAE 生成测试前必须提供的基线信息。
-->
---
# 单测补齐必须服从当前项目的测试基座
<div class="mt-5 text-xs">
远程大纲中的“Vitest 单测补齐”,在当前项目应转换为“按既有测试框架补齐行为证据”。
| 测试目标 | 当前适用基座 | 应补的行为证据 |
|---|---|---|
| Service 规则 | JUnit 5 / Mockito | 非 `DISPATCHED` 取消被拒绝且不写入;正常取消同步更新派车与车辆 |
| 派车前置条件 | JUnit 5 / Mockito | 未审批、重复派车、车辆不可用、需司机但缺司机等分支 |
| 前端请求与模型 | Jest / Vue Test Utils | 审批值的真实载荷、派车表单的必填与可见条件 |
| 跨端类型契约 | API 验证或集成测试 | 大小写审批值、状态值表示与服务端拒绝语义 |
</div>
<div class="mt-6 p-3 rounded-xl bg-cyan-500/10 border border-cyan-500/30 text-sm">
不为引入新工具而另起 Vitest;先让现有 JUnit 和 Jest 覆盖真实业务行为。
</div>
<!--
逐字稿:原远程大纲写的是 Vitest 单测补齐,但当前前端仓库实际配置的是 Jest,后端官方车辆模块已有 JUnit 和 Surefire。因此课程不应该为了贴合一个框架名而新增第二套前端测试体系。正确做法是沿用当前项目基座,把测试补到真实业务风险上。
后端优先补状态拒绝、正常取消的两类写入,以及 assign 的关键前置条件;前端优先验证请求载荷和动态表单条件;跨端类型差异需要 API 或集成验证。这样“测试用例生成”和“单测补齐”才是对现有工程负责的工作,而不是制造新的工具负担。
-->
---
# 拆开一个真实 Skill 包
<div class="mt-5 text-xs">
```text
track-review-fix-loop/
├── SKILL.md # 输入、状态模型、流程、输出与质量门禁
├── agents/openai.yaml # 展示名、简介和默认触发语
└── assets/
├── 修复记录生成.prompt.md # 将原始材料整理为固定结构
├── 修复记录.template.md # 下游可消费的结果格式
├── Review修复闭环检查清单.md # 固定遗漏点
└── 多份反例.md # 权限、审计、状态等典型误用
```
</div>
<div class="mt-6 p-3 rounded-xl bg-blue-500/10 border border-blue-500/30 text-sm">
核心文档不求长,而是把“输入、判断、输出、停止、验证”写成能被人和 Agent 同时执行的契约。
</div>
<!--
逐字稿:以这个真实 Skill 包为例,核心不在某个文件名,而在于每份文件都有明确职责。`SKILL.md` 定义输入、状态模型和质量门禁,模板定义下游结果,检查单保护固定遗漏点,反例帮助识别典型误用。完整交付的是一套能执行的判断结构,不是一段单独的文本。
目录和文件名均来自当前交付包中的真实 track-review-fix-loop Skill。讲解时可打开对应文件,展示为何一个成熟 Skill 不会只有一段大 Prompt:它还要有固定输出、检查清单和反例。
-->
---
# 资产库需要一个可检索的索引
<div class="mt-5 text-xs">
| 索引字段 | 要回答的问题 | 示例 |
|---|---|---|
| 资产名称与类型 | 这是 Rule、Prompt、Skill 还是 Agent? | 状态变更审查 Agent |
| 适用信号 | 什么任务应该选择它? | 涉及状态写入或资源释放 |
| 必要输入 | 缺少什么就不能运行? | 目标、源码、状态规则、验证记录 |
| 输出契约 | 结果能交给谁使用? | 事实表、方案比较、验证清单 |
| 权威位置 | 应到哪个文件更新? | Skill 的 SKILL.md 或 assets/ |
| 复核触发 | 什么变化会使它失效? | 框架、流程、接口或真实误用变化 |
</div>
<div class="mt-6 p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30 text-sm">
索引不记录“有哪些好提示词”,而是帮助使用者快速判断“此刻该用哪一份资产”。
</div>
<!--
逐字稿:资产库必须有索引,否则使用者只能凭文件名猜。索引要说明资产是什么、何时使用、缺什么不能运行、输出给谁、权威位置在哪里,以及什么变化会触发复核。它服务的是正确选择和正确使用,不是管理动作的清单。
资产目录不是客户组织管理方案,而是技术资产的使用入口。索引字段的目的在于定位和正确使用,尤其避免一个新任务随意挑选错误的 Skill 或 Agent。
-->
---
# 用测试夹具验证资产,而不是验证文案
<div class="mt-5 text-xs">
| 夹具类型 | 提供的材料 | 应观察的行为 |
|---|---|---|
| 完整事实 | 入口、状态、diff 与测试记录齐全 | 结论可追溯,输出结构完整 |
| 证据缺失 | 缺少关键 Service 或验证记录 | 明确列出缺口并停止结论 |
| 范围冲突 | 同时要求改数据库、权限和页面 | 指出越界,不默认扩大改动 |
| 反例输入 | 已知的权限、审计或状态误用 | 能识别风险并引用检查项 |
| 跨项目输入 | 不同目录、字段、框架和测试基座 | 重新取证,不复制旧项目结论 |
</div>
<div class="mt-6 p-3 rounded-xl bg-amber-500/10 border border-amber-500/30 text-sm">
资产测试关心的是边界是否正确,不要求模型每次生成完全相同的句子。
</div>
<!--
逐字稿:验证资产时要使用夹具,而不是只读文案。完整材料用于确认结果能回指证据,缺失材料用于确认会停止,范围冲突用于确认不会扩大改动,反例用于确认能识别风险,跨项目材料用于确认不会复制旧结论。生成式资产的正确性看边界和结构,不看每个字是否一样。
测试夹具是资产长期可靠的关键。它可以只是几个整理好的输入目录和预期行为,也可以逐步发展为自动化评测。无论形式如何,都要覆盖完整、缺失、冲突、反例和跨项目五类场景。
-->
---
# 资产库还应包含 MCP 能力契约
<div class="mt-8 text-lg">
案例提供事实;资产保存判断;自定义 Agent 在受控权限下调用这些资产。连接外部系统的 MCP 还需要独立的能力与权限契约。
</div>
<div class="grid grid-cols-6 gap-3 mt-8 text-sm">
<div class="p-3 rounded-xl bg-blue-500/10 border border-blue-500/30">选型</div>
<div class="p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/30">Rule</div>
<div class="p-3 rounded-xl bg-amber-500/10 border border-amber-500/30">Prompt</div>
<div class="p-3 rounded-xl bg-purple-500/10 border border-purple-500/30">Skill</div>
<div class="p-3 rounded-xl bg-red-500/10 border border-red-500/30">Agent</div>
<div class="p-3 rounded-xl bg-cyan-500/10 border border-cyan-500/30">验证</div>
</div>
<!--
逐字稿:资产库不仅管理给 Agent 的知识,也要管理 Agent 能调用的外部能力。一旦连接外部系统,就必须另外说明 MCP 能做什么、谁能调用、失败时怎样降级、调用后怎样验证。下一模块专门把这层能力、权限和验收契约补齐。
资产库还不能止步于“给 Agent 什么知识”。当 Agent 需要调用外部系统时,还必须定义 MCP 能力可以做什么、由谁调用、失败后怎样停止与怎样验证。下一模块补上这一层。
-->