docs: 更新TRA编程培训课程材料、课件与AI技能交付包

- 新增全套考试卷、评估卷、参考答案与考试培训包模板
- 修正slidev培训课件:调整模块标题、链路图缩放,替换工单示例为通用业务对象
- 修正课堂红线表述为证据红线,将小组作业调整为个人作业要求
- 新增权限、状态流转、审计日志、看板指标四类可复用业务规则块
- 整理AI工程技能交付包,迁移旧资产至客户专属交付包并统一术语
- 新增考试输出模板与TRAE使用记录文档
This commit is contained in:
smart
2026-08-08 11:00:36 +08:00
parent e7d6db93c3
commit 67837df8d0
169 changed files with 6618 additions and 2887 deletions
@@ -0,0 +1,285 @@
# 模块 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 能力可以做什么、由谁调用、失败后怎样停止与怎样验证。下一模块补上这一层。
-->