Commit 2664a0f8ba8eebf212c792759e064b2054486452
1 parent
13000c55
fix(add-req): new 单元不复位里程碑导致新需求静默不跑;proto 变更收敛到受影响 FE
步骤 5 原本只处理 changed 单元("new 单元无 tag,跳过"),但新单元挂靠的 模块可能已 done: routerPrompt 判 done = 里程碑字段匹配 且 tag 存在 → 模块已 done 时 reqs 为 空数组 → coding.mjs 的 todo = routed.modules.filter(m => !m.done) 把该模块 整个剔出待跑列表 于是新 REQ 挂进已有模块时不报错、不 halt,就是永远不跑。新 FE 行挂进已打 milestone/frontend-phase 的前端阶段同理。 步骤 5 改为六个显式分支:changed 处理功能级 tag + 里程碑,new 只处理里程碑; kind=proto(new) 显式声明为基线建立、不作废任何 tag(原先只在步骤 3 旁注里)。 kind=proto(changed) 另收窄重跑范围:__prototype__ 是聚合单元,只能说明"原型变了", 原先据此删全部 req-done/FE-*,改一个原型文件就重跑整个前端阶段。改为先用 git log -1 -- .req-ledger.json 取上次台账 commit 作基线、git diff --name-only 还原到文件级,再经 AskUserQuestion 确认映射到受影响 FE,只删这些 tag;取不到 基线/diff 为空/用户选"说不准"一律回退整体重跑,语义同改动前。 coding.mjs 无需改动——runPrototypePreview / featureLoop / runBehaviorGate 本就按 feItems 伸缩,粗粒度完全来自 add-req 删 tag 的范围。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Showing
1 changed file
with
25 additions
and
8 deletions
skills/plan/add-req/SKILL.md
| 1 | --- | 1 | --- |
| 2 | name: add-req | 2 | name: add-req |
| 3 | -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 只重跑增量、不必整仓重跑。 | 3 | +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 只重跑增量、不必整仓重跑。 |
| 4 | user-invocable: true | 4 | user-invocable: true |
| 5 | allowed-tools: Read Write Edit Grep Glob AskUserQuestion Bash(node *) Bash(git *) Bash(ls *) Bash(mkdir *) | 5 | allowed-tools: Read Write Edit Grep Glob AskUserQuestion Bash(node *) Bash(git *) Bash(ls *) Bash(mkdir *) |
| 6 | --- | 6 | --- |
| @@ -102,19 +102,36 @@ node ${CLAUDE_PLUGIN_ROOT}/lib/req-ledger.mjs scan <root> | @@ -102,19 +102,36 @@ node ${CLAUDE_PLUGIN_ROOT}/lib/req-ledger.mjs scan <root> | ||
| 102 | 102 | ||
| 103 | ## 步骤 5:作废变更单元的完成标记(关键——否则 Router 会跳过) | 103 | ## 步骤 5:作废变更单元的完成标记(关键——否则 Router 会跳过) |
| 104 | 104 | ||
| 105 | -对每个 `changed` 单元(`new` 单元无 tag,跳过): | 105 | +对每个 `changed` 单元处理**功能级 tag + 所属模块里程碑**;对每个 `new` 单元只处理**所属模块里程碑**(新单元自身无 tag 可删,但它挂靠的模块可能已 done——不复位就会被 Router 整模块跳过): |
| 106 | 106 | ||
| 107 | -- **kind=req**: | 107 | +- **kind=req(`changed`)**: |
| 108 | - `git -C <root> tag -l "req-done/<id>"` 存在 → `git -C <root> tag -d req-done/<id>`。 | 108 | - `git -C <root> tag -l "req-done/<id>"` 存在 → `git -C <root> tag -d req-done/<id>`。 |
| 109 | - 该 REQ 所属后端模块若已打里程碑(`git -C <root> tag -l "milestone/<module_id>"` 存在)→ `git -C <root> tag -d milestone/<module_id>`,并 `Edit` `docs/08 §二` 该模块 `里程碑:` 字段从 `milestone/<module_id>` 复位为 `—`。(否则 Router 判定模块 done 而整模块跳过,改动不会重跑。) | 109 | - 该 REQ 所属后端模块若已打里程碑(`git -C <root> tag -l "milestone/<module_id>"` 存在)→ `git -C <root> tag -d milestone/<module_id>`,并 `Edit` `docs/08 §二` 该模块 `里程碑:` 字段从 `milestone/<module_id>` 复位为 `—`。(否则 Router 判定模块 done 而整模块跳过,改动不会重跑。) |
| 110 | -- **kind=fe**: | 110 | +- **kind=req(`new`)**:新 REQ 无 `req-done` tag 可删,但**若步骤 4 把它挂进了已有模块**,必须同样复位该模块里程碑: |
| 111 | + - 从步骤 4 的 docs/08 §二 落点确定所属 `<module_id>`(新建模块的里程碑字段本就是 `—`,跳过本条)。 | ||
| 112 | + - `git -C <root> tag -l "milestone/<module_id>"` 存在 → `git -C <root> tag -d milestone/<module_id>`,并 `Edit` `docs/08 §二` 该模块 `里程碑:` 字段复位为 `—`。 | ||
| 113 | + - **为何必须**:`routerPrompt` 判 `done = 里程碑字段匹配 且 tag 存在`,且「模块已 done → `reqs` 空数组」;`coding.mjs` 的 `todo = routed.modules.filter(m => !m.done)` 又把 done 模块整个剔出待跑列表。漏掉这步 → 新 REQ **不报错、不 halt,就是永远不跑**。 | ||
| 114 | +- **kind=fe(`changed`)**: | ||
| 111 | - `git -C <root> tag -l "req-done/<FE-NN>"` 存在 → 删。 | 115 | - `git -C <root> tag -l "req-done/<FE-NN>"` 存在 → 删。 |
| 112 | - 前端阶段若已 `milestone/frontend-phase` → 删该 tag,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。 | 116 | - 前端阶段若已 `milestone/frontend-phase` → 删该 tag,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。 |
| 117 | +- **kind=fe(`new`)**:新 FE 行无 `req-done` tag 可删,但前端阶段若已 `milestone/frontend-phase`,同样要删该 tag 并把 `docs/08 §三` `整体里程碑:` 复位 `—`(否则 Router 判前端阶段 done,新 FE 不跑)。**只删里程碑,不动任何既有 `req-done/FE-*`**——那些 FE 没变,让它们保持 done,Router 的 `feItems` 便只含新 FE。 | ||
| 113 | 118 | ||
| 114 | -- **kind=proto**(`__prototype__`,原型快照变更):原型是整个前端的权威,FE 行与具体原型文件无显式映射,且前端在 Coding 阶段本就是单一 `frontend-phase` 里程碑——故任一原型文件改动按「前端阶段需整体重跑」处理: | ||
| 115 | - - 删**全部**前端功能完成 tag:`git -C <root> tag -l "req-done/FE-*"` 列出后逐个 `git -C <root> tag -d <tag>`(Router 据 `req-done/<FE-NN>` 缺失把 FE 收回 `frontend-phase`,单删 milestone 不够)。 | ||
| 116 | - - `milestone/frontend-phase` 存在 → `git -C <root> tag -d milestone/frontend-phase`,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。 | ||
| 117 | - - (若曾开 `frontendOverlap`:同时 `git -C <root> tag -l "fe-code-done/FE-*"` 逐个删,复位 phase1 重叠状态。缺省关时无此 tag,跳过。) | 119 | +- **kind=proto(`changed`)**(`__prototype__`,原型快照变更):`__prototype__` 是把全部原型 html 聚成的**单一**单元,只能告诉你「原型变了」,不能告诉你变的是哪个文件、影响哪些 FE。故先把范围**还原到文件级再收敛到 FE 级**,收敛不了才整体重跑。 |
| 120 | + | ||
| 121 | + `milestone/frontend-phase` 无论走哪条路径都要删:`git -C <root> tag -l "milestone/frontend-phase"` 存在 → `git -C <root> tag -d milestone/frontend-phase`,并 `Edit` `docs/08 §三` `整体里程碑:` 复位 `—`。(否则 Router 判前端阶段 done,什么都不会跑。)差别只在**删哪些 `req-done/FE-*`**: | ||
| 122 | + | ||
| 123 | + 1. **取基线 commit**:`git -C <root> log -1 --format=%H -- .req-ledger.json`(台账由步骤 6 随增量产物一并提交,故它最后一次被改动的 commit 就是上次 add-req 的基线)。无输出(台账从未提交 / 首次建立基线)→ 跳到第 4 条整体重跑。 | ||
| 124 | + 2. **取变更原型文件**:`git -C <root> diff --name-only <基线commit> -- prototype/`。命令失败或结果为空 → 第 4 条整体重跑。 | ||
| 125 | + 3. **映射到 FE 行**:`Read` 这些原型文件 + `docs/08 §三` FE 清单,判定每个变更文件影响哪些 `FE-NN`,然后用 `AskUserQuestion` 把「变更文件 → 受影响 FE」的判定结果交用户确认,并始终提供「说不准,整体重跑」选项。 | ||
| 126 | + - 用户确认了受影响 FE 集合 → **只**删这些 `req-done/FE-<NN>`,其余 FE 保持 done。Router 的 `feItems` 于是只含受影响 FE,`coding.mjs` 的 `runPrototypePreview` / `featureLoop` / `runBehaviorGate` 全部按 `feItems` 伸缩,前端阶段成本随之收敛。 | ||
| 127 | + - 用户选「说不准」→ 第 4 条。 | ||
| 128 | + - **纯新增原型文件**(新界面,对应步骤 4 刚追加的新 FE 行)是最干净的情形:受影响集合 = 新 FE,既有 `req-done/FE-*` **一个都不用删**。 | ||
| 129 | + 4. **回退:整体重跑**(保守路径,语义同本次改动之前)——删**全部**前端功能完成 tag:`git -C <root> tag -l "req-done/FE-*"` 列出后逐个 `git -C <root> tag -d <tag>`(Router 据 `req-done/<FE-NN>` 缺失把 FE 收回 `frontend-phase`,单删 milestone 不够)。 | ||
| 130 | + - (若曾开 `frontendOverlap`:对**上面实际删掉的那些 FE**,同时删对应的 `fe-code-done/FE-<NN>`(整体重跑则 `git -C <root> tag -l "fe-code-done/FE-*"` 全删),复位 phase1 重叠状态。缺省关时无此 tag,跳过。) | ||
| 131 | + | ||
| 132 | + > 收窄的是**重跑范围**,不是验收强度:受影响 FE 仍走完整流水线(Preview → featureLoop → Behavior 行为门 → testGate 全量回归)。未受影响的 FE 保持既有 `req-done`,其行为验收证据来自上一轮,且步骤末尾的 `testGate` 本就是**全量**回归,会兜住任何跨 FE 的连带回归。 | ||
| 133 | + | ||
| 134 | +- **kind=proto(`new`)**:唯一例外,**不作废任何 tag**——`__prototype__` 作为 `new` 出现只发生在老项目首次升级到带原型跟踪的台账时(无历史哈希可比),此为基线建立而非真实变更,见步骤 3 的说明。 | ||
| 118 | 135 | ||
| 119 | 逐条记录已删的 tag,供步骤 6 横幅汇总。 | 136 | 逐条记录已删的 tag,供步骤 6 横幅汇总。 |
| 120 | 137 |