Commit 7a0069c5c5be9cbcad82d33b0258f8a958deab70

Authored by yanghl
1 parent 42b6ed8e

docs: 前端 jsdom-only 重叠编排实施计划(设计真值)

前后端并行唯一安全形态:前端不依赖后端的部分(骨架+spec/plan+tdd 的 jsdom
任务+vitest verify)与后端波次并发跑、打 fe-code-done,所有真后端测试(e2e
任务+行为门+测试闸)延到后端全 done 后的 phase2。含三前提对比、流程、改动
清单、不变量保住性(补 8/9/10)、风险与验证。开关 parallel.frontendOverlap
缺省关。后续 coding.mjs 实现注释引用本稿为设计真值。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs/superpowers/plans/2026-06-15-frontend-overlap-jsdom.md 0 → 100644
  1 +# 前端 jsdom-only 重叠编排 — 实施计划(待评审)
  2 +
  3 +> 目标:让前端**不依赖后端**的工作(骨架 + spec + plan + jsdom 驱动的组件代码)与后端波次循环**并发**,
  4 +> 把所有**依赖后端**的工作(e2e tdd 任务、e2e verify、静态 review→req-done、行为门、测试闸、里程碑)
  5 +> **延后**到后端全部完成之后。这是前后端重叠唯一安全的形态——重叠期前端只跑代码 + jsdom(无栈、无固定
  6 +> 端口、无 DB),不碰后端 lane 的端口/库,补 8/9/10 不变量全部保住。
  7 +>
  8 +> 总开关 `parallel.frontendOverlap`(缺省 **false**,完全回退现行串行终波)。一切失败 fail-open 降级现行路径,
  9 +> 绝不因重叠机制新增 halt 点。
  10 +
  11 +## 一、现状与目标流程
  12 +
  13 +**现状**(`runModule(frontend-phase)`,终波宽 1 主根,依赖全部后端):
  14 +```
  15 +branchSetup → skeleton → featureLoop(frontend: 逐FE spec→plan→tdd(jsdom+e2e)→verify(unit+e2e)→review→req-done)
  16 + → behaviorGate → testGate(frontend) → report → milestone
  17 +```
  18 +
  19 +**目标**(frontendOverlap 开启时):
  20 +```
  21 +Phase 1(重叠,与后端波次并发,跑在前端 worktree):
  22 + branchSetup(fe) → skeleton → 逐FE [ spec → plan → tdd(仅 jsdom 任务) → verify(仅 vitest) → tag fe-code-done/<FE> ]
  23 + ↑ 不打 req-done(e2e+review 未做)
  24 +
  25 + ─── 屏障:等后端全部 done(后端波次循环结束) ───
  26 +
  27 +Phase 2(后端 done 后,前端分支并入已完成的 default,主根跑全栈):
  28 + 逐FE [ tdd(仅延后的 e2e 任务) → verify(unit+e2e) → review → tag req-done/<FE> ]
  29 + → behaviorGate → testGate(frontend) → report → milestone
  30 +```
  31 +
  32 +## 二、改动清单(函数级)
  33 +
  34 +### 1. 新增执行序拆分(核心)
  35 +- **`runFrontendPhase1(feModule, feCtx)`**:branchSetup + skeleton + `featureLoopFE(items, 'jsdom', feCtx)`。
  36 +- **`runFrontendPhase2(feModule, c)`**:`featureLoopFE(items, 'e2e', c)` + behaviorGate + testGate + report + milestone。
  37 +- 现行 `runModule` 的前端段(3078–3096)在 frontendOverlap 关时**一字不动**;开时改走上面两段。
  38 +
  39 +### 2. `featureLoop` 拆 mode(最小侵入:加形参,不动串行语义)
  40 +- 现 `featureLoop(items, phase, c)` 内部按 FE 链已抽出共用闭包(isDone/ensureSpec/runPlanStage/runImplChain/tagDone)。
  41 +- 新增 `feStage` 参数(`'jsdom'` | `'e2e'` | `'all'`,缺省 `'all'`=现行):
  42 + - `jsdom`:spec→plan→`runImplChain(jsdom)`→`tag fe-code-done`(**不** review、**不** req-done)。
  43 + - `e2e`:入口 dedup 读 `fe-code-done`(必须已存在,否则回退 all)→ `runImplChain(e2e)`→review→`tag req-done`。
  44 + - `all`:现行完整链。
  45 +
  46 +### 3. `tddPrompt(id, phase, planPath, c, feStage='all')`
  47 +- 新增 `feStage`:
  48 + - `jsdom`:只处理 plan 中 `测试先行类型 = jsdom` 的任务;e2e 任务**显式跳过并记账**(输出 deferred 列表);
  49 + FeStub→真组件替换(554)**在此完成**(组件由 jsdom 任务建出)。测试命令只用 `frontend.test_command`(vitest),
  50 + **绝不**触发 `pnpm e2e:ci` / Playwright。
  51 + - `e2e`:只处理 `= e2e` 的任务(jsdom 已在 phase1 绿);e2e 基线约束(551)照旧。
  52 + - `all`:现行文案,一字不动。
  53 +- 「c 为末位参数」的第三个 opts 特例(先例 deriveSpecPrompt `{batch}` / reviewWithFixLoop `{flipDocs08}`)。
  54 +
  55 +### 4. `verifyPrompt(id, phase, implSummary, specPath, round, c, feStage='all')`
  56 +- `jsdom`:只跑 unit(vitest),不跑 e2e;红则 halt。
  57 +- `e2e` / `all`:现行 unit+e2e(595),一字不动。
  58 +
  59 +### 5. 新增中间 tag `fe-code-done/<FE>`
  60 +- 语义:phase1 完成(组件代码 + jsdom 绿)。`createFeCodeDoneTagPromptM` + check 复用 `checkReqDoneTagPromptM` 同构。
  61 +- resume 真值链:`fe-code-done/<FE>` 存在 → phase1 跳过该 FE;`req-done/<FE>` 存在 → phase2 跳过。
  62 + 二者皆缺 → phase1 重跑该 FE。
  63 +
  64 +### 6. 主循环并发点(`while (remaining.length)` 段)
  65 +- frontendOverlap 开 **且** 存在 frontend-phase 模块时:
  66 + - 从波次图**剔除** frontend-phase(`todo`/`remaining` 仅后端;frontend 不再经 annotateDeps 硬依赖)。
  67 + - `const [beResults, fe1] = await Promise.allSettled([ 后端波次循环(), runFrontendPhase1(feModule, feCtx) ])`
  68 + - 两者独立 try/catch,互不 break:前端 phase1 halt 不停后端,反之亦然(各自结构化 halted 入 results)。
  69 + - 屏障后:**仅当**后端全部 done **且** phase1 全部 fe-code-done → `runFrontendPhase2`。
  70 + - 后端有 halt/pending → phase2 不跑(e2e 需完整后端);phase1 产物(fe-code-done)已落 tag,resume 续跑。
  71 +- frontendOverlap 关 → 现行路径(frontend-phase 留在波次图当终波),**零改动**。
  72 +
  73 +### 7. worktree / 分支隔离(重叠期)
  74 +- phase1 跑在前端专属 worktree(分支 `frontend-phase`,路径 `<ROOT>-lanes/frontend-phase` 同 lane 命名族);
  75 + 与后端主根/lane 的 git index 互不干扰。phase1 **不** merge、**不** milestone → 不取 withMainRootLock。
  76 +- phase1→phase2 边界:后端已全部 milestone 到 default。phase2 起手 **merge default → frontend-phase**
  77 + (把完成的后端代码并进前端树,e2e 才打得到真后端)。路径互斥(`frontend/` vs `backend/`)→ 冲突概率极低;
  78 + 冲突按现行 milestone merge 同口径「留树 halt 给人工」。phase2 完成后照现行 runMilestone 合回 default。
  79 +
  80 +### 8. 开关透传 + 入口
  81 +- `coding-start/SKILL.md` 步骤 4 的 `parallel` **不传** `frontendOverlap`(与 features 闸同纪律:留作显式评估开关,
  82 + 收益验证通过后才一行加上)。文档补一句逃生口说明。
  83 +- README 阶段 B 同步一句。
  84 +
  85 +## 三、不变量与安全性
  86 +
  87 +| 不变量 | 是否保住 | 依据 |
  88 +|---|---|---|
  89 +| 补 8/10 行为门/骨架 lane DB 注入豁免 | ✅ | 重叠期前端只跑 jsdom(无 DB);行为门仍在 phase2 后端 done 后、主根、无后端 lane 时跑 |
  90 +| 补 9 起栈互斥(固定端口) | ✅ | 重叠期前端不起栈不占端口;phase2 全栈门在后端 lane 全清后跑 |
  91 +| fail-open 不新增 halt 点 | ✅ | frontendOverlap 失败/关 → 现行终波路径;phase1 halt 不停后端 |
  92 +| req-done 语义(静态过) | ✅ | 仍在 phase2 review 后打;phase1 用独立 `fe-code-done` |
  93 +| resume 经 tag 续跑 | ✅ | fe-code-done + req-done 双 tag 链 |
  94 +
  95 +## 四、风险
  96 +
  97 +1. **契约漂移返工**:前端对 docs/05 写代码,后端编码期若偏离契约 → 错误拖到 phase2 的 e2e/行为门才暴露、返工。
  98 + (任何重叠固有代价;用户已接受「先把能做的做了」。)
  99 +2. **任务分类错配**:plan 把 e2e 任务误标 jsdom → phase1 误跑 e2e 触后端。缓解:tddPrompt jsdom 模式**硬禁**
  100 + Playwright/e2e 命令,命中即 halt(不静默放行)。
  101 +3. **组件依赖后端类型**:前端应只依赖 docs/05 契约类型,不依赖后端代码。若个别 FE 的 jsdom 测试隐性需要真后端
  102 + → 该 FE 的该任务在 phase1 红 → 按 tdd 账本上限 halt(结构化),phase1 跳过它、其余 FE 照常,resume 续跑。
  103 +4. **phase1→phase2 merge 冲突**:路径互斥,概率极低;冲突走现行 milestone 同口径 halt。
  104 +
  105 +## 五、验证
  106 +
  107 +- coding.mjs 无法 `node --test`:纯函数/流程以 `.tmp/` 临时脚本 stub agent/parallel/phase/log 跑确定性断言
  108 + (①overlap 关=现行终波 ②overlap 开+后端全 done+phase1 全 fe-code-done→phase2 跑 ③后端 halt→phase2 不跑、
  109 + phase1 tag 保留 ④phase1 halt 不停后端 ⑤tddPrompt jsdom 模式不含 e2e 命令字样)。即跑即删不入库。
  110 +- `node lib/check-workflow-syntax.mjs workflows/coding.mjs` 必过。
  111 +
  112 +## 六、落地顺序(建议分提交)
  113 +
  114 +1. tddPrompt / verifyPrompt 加 feStage(纯 prompt,行为默认不变)+ fe-code-done tag builder。
  115 +2. featureLoop 加 feStage 分流 + runFrontendPhase1/2 拆分(overlap 关时等价现行)。
  116 +3. 主循环并发点 + worktree 隔离 + phase1→phase2 merge。
  117 +4. coding-start/README 开关透传(不默认开)。
  118 +5. 临时脚本验证 + 语法门。
  119 +
  120 +---
  121 +**待你确认**:范围是否就按以上五类改动?有无要砍/加的?确认后我从第 1 步开始实现,每步过语法门。
... ...