diff --git a/skills/plan/add-req/SKILL.md b/skills/plan/add-req/SKILL.md index 7b7fa8d..de53291 100644 --- a/skills/plan/add-req/SKILL.md +++ b/skills/plan/add-req/SKILL.md @@ -1,6 +1,6 @@ --- name: add-req -description: 增量需求入口——初始 Plan 完结后追加 / 修改需求时运行。基于 lib/req-ledger.mjs 内容哈希台账识别新增 / 变更的 REQ 卡片、FE 行与原型快照(prototype/**/*.html),只对增量做 A3-delta(写 V_n migration + 同步 docs/03,绝不改 V1)+ A5-delta(补 docs/05 端点 / docs/02 顺序 / docs/08 模块行),并作废变更单元已有的 req-done/milestone tag(原型变更则整体重跑前端阶段),使 coding.mjs Router 只重跑增量、不必整仓重跑。 +description: 增量需求入口——初始 Plan 完结后追加 / 修改需求时运行。基于 lib/req-ledger.mjs 内容哈希台账识别新增 / 变更的 REQ 卡片、FE 行与原型快照(prototype/**/*.html),只对增量做 A3-delta(写 V_n migration + 同步 docs/03,绝不改 V1)+ A5-delta(补 docs/05 端点 / docs/02 顺序 / docs/08 模块行),并作废变更单元已有的 req-done/milestone tag——新增单元同样复位其所属模块/前端阶段的里程碑(否则 Router 判 done 整个跳过),原型变更先按 git diff 收敛到受影响 FE、收敛不了才整体重跑前端阶段,使 coding.mjs Router 只重跑增量、不必整仓重跑。 user-invocable: true allowed-tools: Read Write Edit Grep Glob AskUserQuestion Bash(node *) Bash(git *) Bash(ls *) Bash(mkdir *) --- @@ -102,19 +102,36 @@ node ${CLAUDE_PLUGIN_ROOT}/lib/req-ledger.mjs scan ## 步骤 5:作废变更单元的完成标记(关键——否则 Router 会跳过) -对每个 `changed` 单元(`new` 单元无 tag,跳过): +对每个 `changed` 单元处理**功能级 tag + 所属模块里程碑**;对每个 `new` 单元只处理**所属模块里程碑**(新单元自身无 tag 可删,但它挂靠的模块可能已 done——不复位就会被 Router 整模块跳过): -- **kind=req**: +- **kind=req(`changed`)**: - `git -C tag -l "req-done/"` 存在 → `git -C tag -d req-done/`。 - 该 REQ 所属后端模块若已打里程碑(`git -C tag -l "milestone/"` 存在)→ `git -C tag -d milestone/`,并 `Edit` `docs/08 §二` 该模块 `里程碑:` 字段从 `milestone/` 复位为 `—`。(否则 Router 判定模块 done 而整模块跳过,改动不会重跑。) -- **kind=fe**: +- **kind=req(`new`)**:新 REQ 无 `req-done` tag 可删,但**若步骤 4 把它挂进了已有模块**,必须同样复位该模块里程碑: + - 从步骤 4 的 docs/08 §二 落点确定所属 ``(新建模块的里程碑字段本就是 `—`,跳过本条)。 + - `git -C tag -l "milestone/"` 存在 → `git -C tag -d milestone/`,并 `Edit` `docs/08 §二` 该模块 `里程碑:` 字段复位为 `—`。 + - **为何必须**:`routerPrompt` 判 `done = 里程碑字段匹配 且 tag 存在`,且「模块已 done → `reqs` 空数组」;`coding.mjs` 的 `todo = routed.modules.filter(m => !m.done)` 又把 done 模块整个剔出待跑列表。漏掉这步 → 新 REQ **不报错、不 halt,就是永远不跑**。 +- **kind=fe(`changed`)**: - `git -C tag -l "req-done/"` 存在 → 删。 - 前端阶段若已 `milestone/frontend-phase` → 删该 tag,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。 +- **kind=fe(`new`)**:新 FE 行无 `req-done` tag 可删,但前端阶段若已 `milestone/frontend-phase`,同样要删该 tag 并把 `docs/08 §三` `整体里程碑:` 复位 `—`(否则 Router 判前端阶段 done,新 FE 不跑)。**只删里程碑,不动任何既有 `req-done/FE-*`**——那些 FE 没变,让它们保持 done,Router 的 `feItems` 便只含新 FE。 -- **kind=proto**(`__prototype__`,原型快照变更):原型是整个前端的权威,FE 行与具体原型文件无显式映射,且前端在 Coding 阶段本就是单一 `frontend-phase` 里程碑——故任一原型文件改动按「前端阶段需整体重跑」处理: - - 删**全部**前端功能完成 tag:`git -C tag -l "req-done/FE-*"` 列出后逐个 `git -C tag -d `(Router 据 `req-done/` 缺失把 FE 收回 `frontend-phase`,单删 milestone 不够)。 - - `milestone/frontend-phase` 存在 → `git -C tag -d milestone/frontend-phase`,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。 - - (若曾开 `frontendOverlap`:同时 `git -C tag -l "fe-code-done/FE-*"` 逐个删,复位 phase1 重叠状态。缺省关时无此 tag,跳过。) +- **kind=proto(`changed`)**(`__prototype__`,原型快照变更):`__prototype__` 是把全部原型 html 聚成的**单一**单元,只能告诉你「原型变了」,不能告诉你变的是哪个文件、影响哪些 FE。故先把范围**还原到文件级再收敛到 FE 级**,收敛不了才整体重跑。 + + `milestone/frontend-phase` 无论走哪条路径都要删:`git -C tag -l "milestone/frontend-phase"` 存在 → `git -C tag -d milestone/frontend-phase`,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。(否则 Router 判前端阶段 done,什么都不会跑。)差别只在**删哪些 `req-done/FE-*`**: + + 1. **取基线 commit**:`git -C log -1 --format=%H -- .req-ledger.json`(台账由步骤 6 随增量产物一并提交,故它最后一次被改动的 commit 就是上次 add-req 的基线)。无输出(台账从未提交 / 首次建立基线)→ 跳到第 4 条整体重跑。 + 2. **取变更原型文件**:`git -C diff --name-only <基线commit> -- prototype/`。命令失败或结果为空 → 第 4 条整体重跑。 + 3. **映射到 FE 行**:`Read` 这些原型文件 + `docs/08 §三` FE 清单,判定每个变更文件影响哪些 `FE-NN`,然后用 `AskUserQuestion` 把「变更文件 → 受影响 FE」的判定结果交用户确认,并始终提供「说不准,整体重跑」选项。 + - 用户确认了受影响 FE 集合 → **只**删这些 `req-done/FE-`,其余 FE 保持 done。Router 的 `feItems` 于是只含受影响 FE,`coding.mjs` 的 `runPrototypePreview` / `featureLoop` / `runBehaviorGate` 全部按 `feItems` 伸缩,前端阶段成本随之收敛。 + - 用户选「说不准」→ 第 4 条。 + - **纯新增原型文件**(新界面,对应步骤 4 刚追加的新 FE 行)是最干净的情形:受影响集合 = 新 FE,既有 `req-done/FE-*` **一个都不用删**。 + 4. **回退:整体重跑**(保守路径,语义同本次改动之前)——删**全部**前端功能完成 tag:`git -C tag -l "req-done/FE-*"` 列出后逐个 `git -C tag -d `(Router 据 `req-done/` 缺失把 FE 收回 `frontend-phase`,单删 milestone 不够)。 + - (若曾开 `frontendOverlap`:对**上面实际删掉的那些 FE**,同时删对应的 `fe-code-done/FE-`(整体重跑则 `git -C tag -l "fe-code-done/FE-*"` 全删),复位 phase1 重叠状态。缺省关时无此 tag,跳过。) + + > 收窄的是**重跑范围**,不是验收强度:受影响 FE 仍走完整流水线(Preview → featureLoop → Behavior 行为门 → testGate 全量回归)。未受影响的 FE 保持既有 `req-done`,其行为验收证据来自上一轮,且步骤末尾的 `testGate` 本就是**全量**回归,会兜住任何跨 FE 的连带回归。 + +- **kind=proto(`new`)**:唯一例外,**不作废任何 tag**——`__prototype__` 作为 `new` 出现只发生在老项目首次升级到带原型跟踪的台账时(无历史哈希可比),此为基线建立而非真实变更,见步骤 3 的说明。 逐条记录已删的 tag,供步骤 6 横幅汇总。