@xulthekl/team-flow 0.29.2 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/always/phase-guard.md +1 -1
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/marketplace.json +1 -1
- package/.cursor-plugin/plugin.json +2 -2
- package/.github/plugin/marketplace.json +2 -2
- package/AGENTS.md +8 -3
- package/CHANGELOG.md +50 -0
- package/GEMINI.md +1 -1
- package/HANDOFF.md +4 -4
- package/INSTALL.md +1 -1
- package/README.md +4 -4
- package/agents/architecture-design.md +1 -0
- package/agents/build-executor.md +80 -0
- package/agents/contract-builder.md +78 -0
- package/agents/cross-change-consistency-checker.md +1 -1
- package/agents/need-explorer.md +67 -0
- package/agents/release-archivist.md +82 -0
- package/agents/spec-writer.md +83 -0
- package/docs/README_en.md +1 -1
- package/gemini-extension.json +1 -1
- package/hooks/session-start +1 -1
- package/llms.txt +1 -1
- package/package.json +2 -2
- package/plugin.json +2 -2
- package/scripts/ensure-branch.mjs +200 -42
- package/scripts/lib/cmd-doctor.mjs +40 -1
- package/scripts/lib/cmd-state.mjs +24 -9
- package/scripts/lib/state-loader.mjs +22 -0
- package/skills/build-executor/SKILL.md +14 -4
- package/skills/contract-builder/SKILL.md +2 -0
- package/skills/need-explorer/SKILL.md +2 -0
- package/skills/release-archivist/SKILL.md +2 -0
- package/skills/spec-writer/SKILL.md +2 -0
- package/skills/workflow-start/SKILL.md +29 -15
- package/skills/workflow-start/references/routing-rules.md +12 -6
- package/tests/lib/ensure-branch.test.mjs +52 -1
|
@@ -67,6 +67,8 @@ If an `e2e/` suite exists for the change, fold its report into verification (see
|
|
|
67
67
|
|
|
68
68
|
## Final Checks
|
|
69
69
|
|
|
70
|
+
**⛔ 状态字段禁写(v0.30.0)**:仅写本 skill 的 `dp_6_*`/`dp_7_*` 决策字段与 `test_result`;**MUST NOT** 修改 `.team-flow.yaml` 的 `state`/`workflow` 核心字段——closing 转换由主代理经 `tf state transition` 执行(来源:workflow-feedback 2026-08-01)。
|
|
71
|
+
|
|
70
72
|
- Tests passing? (cite command and output)
|
|
71
73
|
- All batches complete? (cite batch status)
|
|
72
74
|
- Scope added without artifact updates?
|
|
@@ -72,6 +72,8 @@ Run: `tf runtime config --get artifacts.order` — generate in configured order
|
|
|
72
72
|
|
|
73
73
|
## Working Rules
|
|
74
74
|
|
|
75
|
+
**⛔ 状态字段禁写(v0.30.0)**:仅通过 `tf state set` 写本 skill 的 `dp_2_*` 决策字段;**MUST NOT** 修改 `.team-flow.yaml` 的 `state`/`workflow` 核心字段——状态转换是主代理(workflow-start)经 `tf state transition` 的专有职责(来源:workflow-feedback 2026-08-01)。
|
|
76
|
+
|
|
75
77
|
**Honor DP-0**: Read `dp_0_decisions`, respect confirmed constraints, don't silently expand scope. Pause on unconfirmed decisions.
|
|
76
78
|
|
|
77
79
|
**Honor Brief (v0.9)**: 若 `change-brief.md` 存在,尊重其 scope 边界与 AC 列表(见 Required Inputs「Change Brief」)——不静默丢弃 brief AC、不静默超出 brief scope;与 plan.md 冲突时以 plan.md 为准并注明。
|
|
@@ -17,6 +17,8 @@ Do NOT invoke for: general coding tasks outside team-flow changes, casual questi
|
|
|
17
17
|
|
|
18
18
|
`exploring` → `specifying` → `bridging` → `approved-for-build` → `executing` → `closing`, with `debugging` side-path from `executing`, and `abandoned` as terminal. If a transition is ambiguous, run `tf runtime asset read docs/state-machine.md`.
|
|
19
19
|
|
|
20
|
+
**状态转换命令(v0.30.0)**:实际转换用 `tf state transition <change-dir 绝对路径> <目标状态>`(内部自动执行 guard 校验并写入 `.team-flow.yaml`)。`tf runtime guard check <dir> <from> <to> --json` 是转换前的独立预检(fail = BLOCK)。**恒用绝对路径**——相对路径下 guard 子进程与状态文件解析基准不一致会找不到产物(v0.30.0 修复)。
|
|
21
|
+
|
|
20
22
|
## Initialization
|
|
21
23
|
|
|
22
24
|
1. **Update check**: Run `tf runtime check-update`. Exit 0 → continue. Exit 1 → non-blocking upgrade reminder. Exit 2 → skip.
|
|
@@ -52,14 +54,25 @@ Validate mode against artifact content. If hotfix/tweak criteria not met → upg
|
|
|
52
54
|
|
|
53
55
|
## Routing Rules
|
|
54
56
|
|
|
57
|
+
### Sub-agent Dispatch Protocol (v0.30.0)
|
|
58
|
+
|
|
59
|
+
产出型路由(spec-writer / contract-builder / build-executor / release-archivist)通过 `Agent(subagent_type: "team-flow:<name>")` **dispatch 子代理**执行——agent 定义经 `skills:` 预加载对应 SKILL.md,主代理**不得**凭记忆手写产物格式 prompt。need-explorer 为交互式澄清,**主进程执行**(需与用户对话;其 agent 定义 `team-flow:need-explorer` 仅作可 dispatch 后备)。
|
|
60
|
+
|
|
61
|
+
- **记录 agentId**:dispatch 后立即记录子代理 ID;修复一律 SendMessage 恢复原子代理(禁启动新子代理,见 v0.29.0 §37)
|
|
62
|
+
- **返回即验证(validation gate)**:子代理返回产物后**立即** `tf validate <change-dir>`;FAIL → SendMessage 回**原**子代理修复,通过后才能继续/转换。把格式失败拦截在返回时,而非状态转换时(避免浪费整次执行后再失败)
|
|
63
|
+
- **结果协议**:子代理终态须标注 `FINAL VERDICT: <DONE|BLOCKED|FAIL>`(审查类用 PASS/PASS_WITH_WARNINGS/FAIL);**SendMessage 报告为权威结果**,task-notification.result 仅内部元数据
|
|
64
|
+
- **子代理状态边界**:子代理 MUST NOT 修改 `.team-flow.yaml` 的 `state`/`workflow` 核心字段(状态转换是主代理专有职责,经 `tf state transition` 执行),只写自己的 `dp_N_*` 决策字段
|
|
65
|
+
|
|
55
66
|
### Route to need-explorer
|
|
56
|
-
Change is fuzzy, scope unclear, comparing options, no stable change name
|
|
67
|
+
Change is fuzzy, scope unclear, comparing options, no stable change name.(交互式澄清,主进程执行,见 Sub-agent Dispatch Protocol)
|
|
57
68
|
|
|
58
69
|
### Route to architecture-design (v0.9 §26, v0.28.1 §36 审查增强, v0.29.0 §37 DP-A 确认门)
|
|
59
70
|
Guard: `arch_design_decision` in `.team-flow.yaml` is `null` → must run before spec-writer.
|
|
60
71
|
|
|
61
72
|
**Four-step protocol (MUST execute in order)**:
|
|
62
73
|
|
|
74
|
+
> **⛔ 串行约束(v0.30.0)**:四步严格串行。**修复子代理(architecture-design)完成前 MUST NOT dispatch 审查子代理(architecture-reviewer)**——并行会使审查跑在修复之前、误报"全部未修复"FAIL(来源:workflow-feedback 2026-08-01)。并行白名单:仅多个独立 change 的工作可并行;修复→审查、设计→审查必须串行。
|
|
75
|
+
|
|
63
76
|
1. **Dispatch**: `architecture-design` as sub-agent → returns `decision` + `reason` + `artifacts`。**⛔ 记录子代理 ID**(后续循环修正和 DP-A 调整必须通过此 ID 恢复,禁止启动新子代理)
|
|
64
77
|
2. **Auto-review** (decision=required 时触发): 校验产物文件存在且非空 → dispatch `architecture-reviewer` sub-agent(**记录子代理 ID**)→ FAIL 则通过 **SendMessage 恢复原 architecture-design 子代理**修正(≤3 轮 + 收敛检测,不收敛转人工)→ 报告落盘 `changes/<name>/architecture/auto-review.md`
|
|
65
78
|
3. **Reasonableness check + state write**: PASS/PASS_WITH_WARNINGS → write `arch_design_decision` + `arch_review_*` to yaml; skipped + brief 含架构关键词 → BLOCK; required + artifacts 缺失 → BLOCK; required + auto-review FAIL → BLOCK
|
|
@@ -67,13 +80,13 @@ Guard: `arch_design_decision` in `.team-flow.yaml` is `null` → must run before
|
|
|
67
80
|
|
|
68
81
|
Full protocol in `references/routing-rules.md`「Route to architecture-design」.
|
|
69
82
|
|
|
70
|
-
### Route to spec-writer
|
|
83
|
+
### Route to spec-writer (dispatch sub-agent)
|
|
71
84
|
Guard: `tf runtime guard check <dir> exploring specifying --json` → fail = BLOCK. **arch_design_decision must not be null** → fail = BLOCK (v0.9 §26). User knows what they want, artifacts missing/incomplete.
|
|
72
85
|
|
|
73
|
-
### Route to contract-builder
|
|
86
|
+
### Route to contract-builder (dispatch sub-agent)
|
|
74
87
|
Guard: `... check <dir> specifying bridging --json` → fail = BLOCK. Artifacts exist, implementation requested, contract missing/stale. Include `DP-3: 契约批准`.
|
|
75
88
|
|
|
76
|
-
### Route to build-executor
|
|
89
|
+
### Route to build-executor (dispatch sub-agent)
|
|
77
90
|
Contract exists and approved, contract matches artifacts. Include `DP-4: 执行模式选择`: propose waves, run `tf execution recommend <change-dir> [--wave ...]`, show the user every available mode plus evidence and the recommendation, then obtain a clear selection. The command saves a current receipt; before the first implementation edit, `build-executor` must run `tf execution plan <change-dir> --mode <selected> --confirm ...` (and `--acknowledge-recommendation` when the selected mode differs from the recommendation) using matching artifacts, contract, and waves, then `tf execution show <change-dir> --json`; report the saved revision, selected mode, recommendation alignment, ordered waves, and actual concurrent-dispatch capability. A revision must repeat recommend and confirmation. Do not transition to `executing` until `show` reports `current: true`; then run `... check <dir> approved-for-build executing --json` → fail = BLOCK.
|
|
78
91
|
|
|
79
92
|
### Route to bug-investigator
|
|
@@ -82,7 +95,7 @@ Execution hit blockage: test failure, unexpected behavior, build error, task can
|
|
|
82
95
|
### Route to code-reviewer
|
|
83
96
|
The current planned wave is implemented and ready for spec-compliance + code-quality verification. A reviewer must write an `tf execution review <change-dir> --wave <id> --base <sha> --head <sha> --report <path> --verdict <pass|fail>` receipt before any dependent wave or closing transition.
|
|
84
97
|
|
|
85
|
-
### Route to release-archivist
|
|
98
|
+
### Route to release-archivist (dispatch sub-agent)
|
|
86
99
|
Guard: `... check <dir> executing closing --json` → fail = BLOCK. Implementation complete, verification complete/nearly complete. Include `DP-7: 归档确认`.
|
|
87
100
|
|
|
88
101
|
### Route to spec-merger
|
|
@@ -145,8 +158,9 @@ Use content inspection, not timestamps.
|
|
|
145
158
|
- No merging delta specs from abandoned change
|
|
146
159
|
- **No routing to spec-writer without architecture-design gate pass** (v0.9 §26): `arch_design_decision` must be `required` or `skipped` (not `null`). hotfix/tweak 不豁免
|
|
147
160
|
- **No arch state write without auto-review PASS** (v0.28.1 §36): when `decision: required`, auto-review MUST complete with PASS or PASS_WITH_WARNINGS before writing `arch_design_decision` to yaml. FAIL → loop fix (≤3 rounds) or escalate to human
|
|
148
|
-
- **No routing past DP-A without user confirmation** (v0.29.0 §37): architecture-design
|
|
161
|
+
- **No routing past DP-A without user confirmation** (v0.29.0 §37): architecture-design 四步协议完成后,必须经 DP-A 用户确认门(AskUserQuestion)才能路由到 spec-writer。用户选择"需要调整"时,修改必须通过子代理执行,修改后重新 auto-review + 重新 DP-A 确认
|
|
149
162
|
- **Artifact Ownership — 主代理不得直接修改子代理产物** (v0.29.0 §37): 子代理是其产物的唯一负责人(architecture-design → `architecture/` 目录,spec-writer → `proposal.md`/`specs/`/`design.md`/`tasks.md`,contract-builder → `execution-contract.md`)。主代理(workflow-start)不得通过 Read + Edit/Write 直接修改子代理的产物文件。修改必须通过 `SendMessage` 恢复原子代理(优先)或启动新子代理执行。例外:仅当子代理无法启动且用户明确授权时,主代理可直接修改,但必须在修改后重新触发对应的 review 验证
|
|
163
|
+
- **No cross-change artifact modification (v0.30.0)**: 处理 change X 时 **MUST NOT** 编辑 `changes/Y/`(Y≠X)下任何产物。发现跨 change 依赖/问题时:① 在 change X 的 ADR/proposal 中显式声明依赖;② change Y 进入 workflow-start 时,扫描是否有其他 change 声明了对 Y 的依赖并提醒用户;③ change Y 的产物修改必须走 Y 自己的完整流程(architecture-design → auto-review → DP-A),不得绕过。跨 change 一致性核查可调度 `cross-change-consistency-checker` agent(来源:workflow-feedback 2026-08-01)
|
|
150
164
|
|
|
151
165
|
## State Writes (v0.22.5 F06 修复)
|
|
152
166
|
|
|
@@ -156,14 +170,14 @@ workflow-start 负责写入以下字段到 `.team-flow.yaml`:
|
|
|
156
170
|
- `state`:当前状态(exploring/specifying/bridging/approved-for-build/executing/debugging/closing/abandoned)
|
|
157
171
|
- `workflow`:工作流类型(auto/full/hotfix/tweak)
|
|
158
172
|
|
|
159
|
-
|
|
160
|
-
- `dp_0_*`:
|
|
161
|
-
- `dp_1_*`:
|
|
162
|
-
- `dp_2_*`:
|
|
163
|
-
- `dp_3_*`:
|
|
164
|
-
- `dp_5_*`:
|
|
165
|
-
- `dp_6_*`:release-archivist
|
|
166
|
-
- `dp_7_
|
|
173
|
+
**决策点字段**(各阶段确认后写入;v0.30.0 修正错位,以各 skill 实际 `tf state set` 为准):
|
|
174
|
+
- `dp_0_*`:DP-0 用户确认门(workflow-start 本 skill 写入)
|
|
175
|
+
- `dp_1_*`:need-explorer 完成后的需求澄清决策
|
|
176
|
+
- `dp_2_*`:spec-writer 完成后的规格决策
|
|
177
|
+
- `dp_3_*`:contract-builder 完成后的契约决策
|
|
178
|
+
- `dp_5_*`:build-executor 执行决策 / bug-investigator 调试决策(共享 dp_5;dp_4 预留未用)
|
|
179
|
+
- `dp_6_*`:release-archivist 完成后的验证决策
|
|
180
|
+
- `dp_7_*`:release-archivist 归档确认决策
|
|
167
181
|
|
|
168
182
|
**架构设计门控字段**(v0.9 §26,v0.22.5 F02 修复):
|
|
169
183
|
- `arch_design_decision`:`required` | `skipped`(architecture-design 子代理返回,workflow-start 经 auto-review + reasonableness check 后写入)
|
|
@@ -181,7 +195,7 @@ workflow-start 负责写入以下字段到 `.team-flow.yaml`:
|
|
|
181
195
|
- `dp_a_timestamp`:ISO 8601 时间戳(UTC)
|
|
182
196
|
- `dp_a_adjustments`:用户调整意见摘要(adjustment_requested 时必填,confirmed 时为空)
|
|
183
197
|
|
|
184
|
-
**职责边界**:architecture-design 负责判断+产出,architecture-reviewer 负责 6 维度审查,workflow-start
|
|
198
|
+
**职责边界**:architecture-design 负责判断+产出,architecture-reviewer 负责 6 维度审查,workflow-start 负责编排四步协议(dispatch → auto-review → reasonableness check → DP-A 确认)+ 状态写入。**子代理 MUST NOT 修改 `state`/`workflow` 核心字段**(v0.30.0)——状态转换是 workflow-start 专有职责,经 `tf state transition` 执行;子代理只写自己的 `dp_N_*` 决策字段。详细写入命令见 `references/routing-rules.md`「Route to architecture-design」。
|
|
185
199
|
|
|
186
200
|
## Output Standard
|
|
187
201
|
|
|
@@ -34,6 +34,8 @@ artifacts: # required 时必填
|
|
|
34
34
|
- architecture/api.md
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
**📡 结果协议(v0.30.0)**:子代理终态须标注 `FINAL VERDICT: <DONE|BLOCKED|FAIL>`(审查类用 PASS/PASS_WITH_WARNINGS/FAIL)。**SendMessage 报告为权威结果**;task-notification.result 仅内部元数据,二者冲突时以 SendMessage + 落盘产物为准。
|
|
38
|
+
|
|
37
39
|
### Step 2: Auto-review (v0.11 §34, decision=required 时触发)
|
|
38
40
|
|
|
39
41
|
When `decision: required`, dispatch `architecture-reviewer` as sub-agent with inputs:
|
|
@@ -58,8 +60,12 @@ reviewer 报告 → FAIL → 不一致项交给 architecture-design 修正 →
|
|
|
58
60
|
reviewer 报告 → PASS / PASS_WITH_WARNINGS → 进入 Step 3
|
|
59
61
|
```
|
|
60
62
|
|
|
63
|
+
**🎯 实事求是原则(v0.30.0,修复子代理行为准则)**:reviewer 建议是**输入不是指令**。修复子代理收到 findings 后,**必须先对照代码库与项目既有模式逐条验证属实性**(搜索既有实现、读取参照模块):属实则修正;认为不属实或与既有模式冲突,则据实 SendMessage 反馈主代理(finding + 证据 + 替代建议),**不得盲目遵从**(移植自 ce-brainstorm「may contradict only on evidence / report it — do not suppress it」)。
|
|
64
|
+
|
|
65
|
+
> **⛔ 修复→审查必须串行(v0.30.0)**:修复子代理(architecture-design)**完成前 MUST NOT dispatch/恢复审查子代理**——并行会使审查跑在修复之前、误报"全部未修复"FAIL。
|
|
66
|
+
|
|
61
67
|
**⛔ 循环修正必须通过 SendMessage 恢复原子代理(v0.29.0 §37,禁止启动新子代理)**:
|
|
62
|
-
- FAIL 后修正:`SendMessage(to: arch_design_agent_id, message: "审查 FAIL,不一致项如下:{findings}
|
|
68
|
+
- FAIL 后修正:`SendMessage(to: arch_design_agent_id, message: "审查 FAIL,不一致项如下:{findings}。请先对照代码库与项目既有模式逐条验证 finding 属实性——属实则修正;认为不属实或冲突则据实反馈主代理(finding+证据+替代建议),勿盲目遵从。修正后返回更新的结构化输出。")`
|
|
63
69
|
- 重新审查:`SendMessage(to: arch_reviewer_agent_id, message: "第 {N} 轮审查,架构产物已修正。请重新执行 6 维度审查。")`
|
|
64
70
|
- **禁止**在循环中启动新的 architecture-design 或 architecture-reviewer 子代理——原子代理拥有完整的设计上下文和审查历史,新子代理需要重新加载全部上下文(浪费 10-20K tokens 且可能丢失修正连贯性)
|
|
65
71
|
- **唯一例外**:SendMessage 恢复失败(子代理 transcript 不可用)时,启动新子代理作为 fallback,但必须在 dispatch prompt 中传入:原产物路径 + auto-review 报告 + 历次修正记录
|
|
@@ -164,7 +170,7 @@ AskUserQuestion:
|
|
|
164
170
|
```
|
|
165
171
|
SendMessage(to: arch_design_agent_id, message: "用户评审反馈(DP-A 调整):
|
|
166
172
|
{用户调整意见}
|
|
167
|
-
|
|
173
|
+
请先对照代码库与项目既有模式验证调整点的合理性,再修改架构产物,保持内部一致性;若调整点与既有模式冲突请据实反馈。返回更新后的结构化输出。")
|
|
168
174
|
```
|
|
169
175
|
原子代理拥有完整的设计上下文(PRD、brief、基线、conventions),能保持修改的一致性。启动新子代理会丢失上下文(重新加载 10-20K tokens)且可能引入不一致。
|
|
170
176
|
3. 子代理修改完成后,**通过 SendMessage 恢复原 architecture-reviewer 子代理重新审查**(即使之前已 PASS):
|
|
@@ -189,16 +195,16 @@ AskUserQuestion:
|
|
|
189
195
|
- 用户选择 B 后不重新 auto-review 就直接重新确认
|
|
190
196
|
- **循环修正或 DP-A 调整时启动新的 architecture-design / architecture-reviewer 子代理**(必须通过 SendMessage 恢复原子代理,原子代理拥有完整上下文;新子代理 = 上下文断裂 + token 浪费。唯一例外:SendMessage 恢复失败时的 fallback)
|
|
191
197
|
|
|
192
|
-
## Route to spec-writer
|
|
198
|
+
## Route to spec-writer (dispatch sub-agent)
|
|
193
199
|
Guard: `tf runtime guard check <dir> exploring specifying --json` → fail = BLOCK.
|
|
194
200
|
**arch_design_decision must not be null** → fail = BLOCK(architecture-design gate not passed,v0.9 §26)。
|
|
195
201
|
User knows what they want, artifacts missing/incomplete.
|
|
196
202
|
|
|
197
|
-
## Route to contract-builder
|
|
203
|
+
## Route to contract-builder (dispatch sub-agent)
|
|
198
204
|
Guard: `... check <dir> specifying bridging --json` → fail = BLOCK.
|
|
199
205
|
Artifacts exist, implementation requested, contract missing/stale. Include DP-3: 契约批准.
|
|
200
206
|
|
|
201
|
-
## Route to build-executor
|
|
207
|
+
## Route to build-executor (dispatch sub-agent)
|
|
202
208
|
Contract exists and approved, contract matches artifacts. Include DP-4: 执行模式选择.
|
|
203
209
|
|
|
204
210
|
Propose waves, run:
|
|
@@ -222,7 +228,7 @@ Current planned wave implemented and ready for review. Reviewer must write:
|
|
|
222
228
|
tf execution review <change-dir> --wave <id> --base <sha> --head <sha> --report <path> --verdict <pass|fail>
|
|
223
229
|
```
|
|
224
230
|
|
|
225
|
-
## Route to release-archivist
|
|
231
|
+
## Route to release-archivist (dispatch sub-agent)
|
|
226
232
|
Guard: `... check <dir> executing closing --json` → fail = BLOCK. Include DP-7: 归档确认.
|
|
227
233
|
|
|
228
234
|
## Route to spec-merger
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { describe, it, before, after } from 'node:test';
|
|
7
7
|
import assert from 'node:assert/strict';
|
|
8
8
|
import { execSync } from 'node:child_process';
|
|
9
|
-
import { mkdtempSync, rmSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
9
|
+
import { mkdtempSync, rmSync, existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
import { tmpdir } from 'node:os';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
@@ -57,3 +57,54 @@ describe('BUG/#15: ensure-branch enforces isolation', () => {
|
|
|
57
57
|
assert.match(r.out, /already isolated/i);
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
|
+
|
|
61
|
+
// 来源:workflow-feedback 2026-08-01 #100009
|
|
62
|
+
// Case A 多仓库工作区:工作区根是近空壳 git 仓库(仅 .gitignore),真正业务代码在
|
|
63
|
+
// 平级独立仓库(各含 .git)。change-dir 位于 <root>/changes/<name>。tf isolate 必须
|
|
64
|
+
// 为每个代码仓库在 <root>/.worktrees/<change>/<repo> 建 worktree,实现子代理才能
|
|
65
|
+
// 看到与主工作区一致的参考代码(而非空工作区副本)。
|
|
66
|
+
describe('FEEDBACK/#100009: multi-repo workspace isolation (Case A)', () => {
|
|
67
|
+
let root;
|
|
68
|
+
const changeName = 'C2-multi';
|
|
69
|
+
before(() => {
|
|
70
|
+
root = mkdtempSync(join(tmpdir(), 'tf-ensure-ws-'));
|
|
71
|
+
// 工作区根:近空壳 git 仓库(仅跟踪 .gitignore)
|
|
72
|
+
writeFileSync(join(root, '.gitignore'), 'node_modules/\n');
|
|
73
|
+
git(root, 'init', '-q');
|
|
74
|
+
git(root, 'add', '-A');
|
|
75
|
+
git(root, 'commit', '-q', '-m', 'init-workspace');
|
|
76
|
+
// change 目录位于工作区根下(<root>/changes/<name>)
|
|
77
|
+
mkdirSync(join(root, 'changes', changeName), { recursive: true });
|
|
78
|
+
// 两个独立代码仓库,各自 git init+commit,处于默认分支(master/main,均属 PROTECTED)
|
|
79
|
+
for (const repo of ['repo-a', 'repo-b']) {
|
|
80
|
+
const repoDir = join(root, repo);
|
|
81
|
+
mkdirSync(repoDir, { recursive: true });
|
|
82
|
+
writeFileSync(join(repoDir, 'app.txt'), `${repo} reference code\n`);
|
|
83
|
+
git(repoDir, 'init', '-q');
|
|
84
|
+
git(repoDir, 'add', '-A');
|
|
85
|
+
git(repoDir, 'commit', '-q', '-m', `init-${repo}`);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
after(() => {
|
|
89
|
+
if (existsSync(root)) rmSync(root, { recursive: true, force: true });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('SHALL create a worktree per code repo under <root>/.worktrees/<change>/', () => {
|
|
93
|
+
const changeDir = join(root, 'changes', changeName);
|
|
94
|
+
const r = run(`"${changeDir}"`);
|
|
95
|
+
assert.equal(r.ok, true, `ensure-branch should isolate a multi-repo workspace, got: ${r.out}`);
|
|
96
|
+
|
|
97
|
+
const wtA = join(root, '.worktrees', changeName, 'repo-a');
|
|
98
|
+
const wtB = join(root, '.worktrees', changeName, 'repo-b');
|
|
99
|
+
assert.ok(existsSync(wtA), 'worktree for repo-a must be created');
|
|
100
|
+
assert.ok(existsSync(wtB), 'worktree for repo-b must be created');
|
|
101
|
+
// 各 worktree 含对应仓库文件(实现子代理可参考既有代码,而非空副本)
|
|
102
|
+
assert.ok(existsSync(join(wtA, 'app.txt')), 'repo-a worktree must contain its files');
|
|
103
|
+
assert.ok(existsSync(join(wtB, 'app.txt')), 'repo-b worktree must contain its files');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('SHALL add .worktrees/ to <root>/.gitignore', () => {
|
|
107
|
+
const gi = readFileSync(join(root, '.gitignore'), 'utf-8');
|
|
108
|
+
assert.match(gi, /\.worktrees\//, '.gitignore must ignore .worktrees/');
|
|
109
|
+
});
|
|
110
|
+
});
|