@xulthekl/team-flow 0.47.0 → 0.48.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.
@@ -1,3 +1,3 @@
1
- # team-flow v0.47.0 | 阶段: {{state}} | 工作流: {{workflow}}
1
+ # team-flow v0.48.0 | 阶段: {{state}} | 工作流: {{workflow}}
2
2
  当前阶段允许的操作由 workflow-start 路由规则定义。
3
3
  禁止跨越 DP gate 进入下一阶段。变更范围以 execution-contract.md 的 Intent Lock 为准。
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "team-flow",
11
11
  "description": "8-state spec workflow + compound global compounding + architecture-design (4A/DDD) + local HTML prototype + product-level orchestration + bootstrap + e2e + session handoff + workflow feedback + independent business analysis. 26 skills + 17 agents with embedded TDD, SDD, code review, debugging, delta spec sync, and design-system-driven prototyping.",
12
- "version": "0.47.0",
12
+ "version": "0.48.0",
13
13
  "source": "./",
14
14
  "author": {
15
15
  "name": "LT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-flow",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Unified workflow plugin: team-flow (spec-driven dev: TDD/SDD/code-review/debugging) + compound-engineering core subset (brainstorm/plan/compound/strategy/ideate/proof, global compounding) + architecture-design (4A+DDD incremental design & global compounding) + prototype (local HTML prototype, zero external deps) + e2e (Playwright E2E, AC-driven) + workflow-orchestrator (product-level workflow orchestration) + workflow-bootstrap (existing project onboarding) + session-handoff (context transfer) + workflow-feedback (issue tracking) + business-analysis (independent requirement/scenario artifact). 26 skills + 17 agents, one install.",
5
5
  "source": "./",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-flow",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Spec-first workflow that bridges OpenSpec-style planning and Superpowers-style execution discipline.",
5
5
  "author": {
6
6
  "name": "MageByte",
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "Unified workflow plugin marketplace for Cursor (team-flow: team-flow + compound + architecture-design + prototype).",
8
- "version": "0.47.0"
8
+ "version": "0.48.0"
9
9
  },
10
10
  "plugins": [
11
11
  {
@@ -2,7 +2,7 @@
2
2
  "name": "team-flow",
3
3
  "displayName": "team-flow",
4
4
  "description": "Unified workflow plugin: team-flow (spec-driven dev: TDD/SDD/code-review/debugging) + compound-engineering core subset (brainstorm/plan/compound/strategy/ideate/proof, global compounding) + architecture-design (4A+DDD incremental design & global compounding) + prototype (local HTML prototype, zero external deps) + e2e (Playwright E2E, AC-driven) + workflow-orchestrator (product-level workflow orchestration) + workflow-bootstrap (existing project onboarding) + session-handoff (context transfer) + workflow-feedback (issue tracking) + business-analysis (independent requirement/scenario artifact). 26 skills + 17 agents, one install.",
5
- "version": "0.47.0",
5
+ "version": "0.48.0",
6
6
  "author": {
7
7
  "name": "LT",
8
8
  "url": "https://github.com/LT"
@@ -6,13 +6,13 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Unified workflow plugins and skills for AI coding agents (team-flow: team-flow + compound + architecture-design + prototype).",
9
- "version": "0.47.0"
9
+ "version": "0.48.0"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "team-flow",
14
14
  "description": "Unified workflow with planning artifacts, execution contracts, TDD, review gates, systematic debugging, delta spec sync, architecture-design, independent business analysis, and local HTML prototyping.",
15
- "version": "0.47.0",
15
+ "version": "0.48.0",
16
16
  "source": ".",
17
17
  "author": {
18
18
  "name": "LT",
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to `team-flow` will be documented in this file.
4
4
 
5
5
  The format loosely follows Keep a Changelog.
6
6
 
7
+ ## [0.48.0] - 2026-08-21
8
+
9
+ ### Added(多仓库场景支持,v0.48.0)
10
+
11
+ 设计来源:`docs/plan/multi-repo-support-design.md` v1.0(2026-08-21,fytx-message 4 feedback:cli-command-1/2 + sop-flow-1/2)
12
+
13
+ - **repo_layout 机制**(P0):`detectRepoLayout` 判定 single/monorepo/multi-repo + 代码仓库清单;`tf repo-layout detect <root>` CLI 写 `repo_layout` 段到 `team-flow.config.json`;config-loader DEFAULTS 固化
14
+ - **detect 修复**(P1,cli-command-1):change 目录→项目根解析(detectWorkspaceRoot/getGitRoot);repos 清单聚合判定 `is_glaf4_java`(任一仓库 Java → 项目级 true);`--target-repo` 精确探测;config 主副本写项目根(不再写 change 目录)
15
+ - **review 修复**(P2,cli-command-2):overlay 目录自动创建(修 ENOENT);`--repo <代码仓库>` 提供 base/head git 校验上下文;multi-repo 下 change 目录无 git 不再报错(--repo 场景)
16
+ - **isolate 修复**(P2,sop-flow-2):`checkSharedBranch` 检测 origin tracking + ahead/behind(有 upstream 即共享);共享分支建 worktree 而非就地实施;`checkUncommitted` 报告未提交变更归属
17
+ - **流程接入**(P3):workflow-start DP-0 + orchestrator S1 项目模式确认(识别存量结构,写 repo_layout config)
18
+ - **三评审闭环**:P3 code-reviewer(2 Important + 8 Minor)+ P4 plugin-validator(7 minor)+ skill-reviewer(5 minor)全修
19
+ - 723/723 测试通过
20
+
7
21
  ## [0.47.0] - 2026-08-21
8
22
 
9
23
  ### Added(PRD §8.4 契约级详述规范,v0.47.0)
package/GEMINI.md CHANGED
@@ -8,7 +8,7 @@ The workflow is self-contained and does not require OpenSpec or Superpowers at r
8
8
 
9
9
 
10
10
  <!-- team-flow-phase-guard-start -->
11
- # team-flow v0.47.0 | 阶段: {{state}} | 工作流: {{workflow}}
11
+ # team-flow v0.48.0 | 阶段: {{state}} | 工作流: {{workflow}}
12
12
  当前阶段允许的操作由 workflow-start 路由规则定义。
13
13
  禁止跨越 DP gate 进入下一阶段。变更范围以 execution-contract.md 的 Intent Lock 为准。
14
14
  <!-- team-flow-phase-guard-end -->
package/INSTALL.md CHANGED
@@ -7,7 +7,7 @@
7
7
  - [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec) — 规划引擎(Schema 验证、Delta Spec、工件解析)
8
8
  - [obra/superpowers](https://github.com/obra/superpowers) — 执行纪律(TDD 铁律、SDD、系统化调试、代码审查)
9
9
 
10
- 当前发布版本:**v0.47.0**。
10
+ 当前发布版本:**v0.48.0**。
11
11
 
12
12
  ---
13
13
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # team-flow
2
2
 
3
- > 当前版本:`v0.47.0`
3
+ > 当前版本:`v0.48.0`
4
4
 
5
5
  > 统一插件:**team-flow**(spec 驱动开发)+ **compound-engineering 核心子集**(全局复利)+ **architecture-design**(4A+DDD 增量设计)+ **prototype**(本地 HTML 原型)+ **e2e**(AC 驱动 E2E)+ **workflow-orchestrator**(产品级编排)+ **workflow-bootstrap**(既有项目接入)。一次安装,七套能力协同。
6
6
 
package/docs/README_en.md CHANGED
@@ -126,7 +126,7 @@ npm install -g team-flow
126
126
 
127
127
  ### Version
128
128
 
129
- - Current: `v0.47.0`
129
+ - Current: `v0.48.0`
130
130
  - v0.9.1 highlights: DP-4 execution-mode recommendations, a portable runtime across 17 platforms, and a raw-package smoke with no plugin-root variable.
131
131
  - Self-contained — no OpenSpec or Superpowers runtime required
132
132
  - Upstream: [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec), [obra/superpowers](https://github.com/obra/superpowers)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-flow",
3
3
  "description": "Unified workflow plugin: team-flow (spec-driven dev) + compound-engineering core subset + architecture-design (4A/DDD) + prototype (local HTML) + business-analysis (independent requirement/scenario artifact). 26 skills, one install.",
4
- "version": "0.47.0",
4
+ "version": "0.48.0",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bash
2
- # v0.47.0: auto-sync CLI version with plugin version
2
+ # v0.48.0: auto-sync CLI version with plugin version
3
3
  set -e
4
4
 
5
5
  # ═══════════════════════════════════════════════════════════════
6
6
  # Plugin version (update this when releasing new versions)
7
7
  # ═══════════════════════════════════════════════════════════════
8
- PLUGIN_VERSION="0.47.0"
8
+ PLUGIN_VERSION="0.48.0"
9
9
 
10
10
  # ═══════════════════════════════════════════════════════════════
11
11
  # Step 1: Auto-sync CLI version with plugin version
package/llms.txt CHANGED
@@ -3,7 +3,7 @@
3
3
  ## Overview
4
4
  spec-superflow is a self-contained workflow integration plugin for Claude Code, Cursor, OpenAI Codex CLI/App, GitHub Copilot CLI, Gemini CLI, OpenCode, WorkBuddy, and Trae. It merges spec-driven planning artifacts (proposal, specs, design, tasks) with disciplined execution guardrails (TDD, review gates, controlled handoff) into one unified workflow.
5
5
 
6
- Current version: v0.47.0.
6
+ Current version: v0.48.0.
7
7
 
8
8
  ## Key Documents
9
9
  - README.md: Chinese homepage with full usage guide and FAQ
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xulthekl/team-flow",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Unified plugin (26 skills + 17 agents) integrating team-flow, compound-engineering, architecture-design, prototype, design-system, workflow-orchestrator, workflow-bootstrap, e2e, session-handoff, workflow-feedback, business-analysis for multi-agent coding tools.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-flow",
3
- "version": "0.47.0",
3
+ "version": "0.48.0",
4
4
  "description": "Unified workflow plugin: team-flow (spec-driven dev: TDD/SDD/code-review/debugging) + compound-engineering core subset (brainstorm/plan/compound/strategy/ideate/proof, global compounding) + architecture-design (4A+DDD incremental design & global compounding) + prototype (local HTML prototype, zero external deps) + e2e (Playwright E2E, AC-driven) + workflow-orchestrator (product-level workflow orchestration) + workflow-bootstrap (existing project onboarding) + session-handoff (context transfer) + workflow-feedback (issue tracking) + business-analysis (independent requirement/scenario artifact). 26 skills + 17 agents, one install.",
5
5
  "author": {
6
6
  "name": "LT"
@@ -60,6 +60,53 @@ function sanitizeBranchName(raw) {
60
60
  return cleaned || 'change';
61
61
  }
62
62
 
63
+ // 检查未提交变更(sop-flow-2,multi-repo-support-design v1.0 §4.3 未提交变更归属)。
64
+ // git status --porcelain 统计未提交文件;worktree 基于已提交 HEAD 创建,未提交变更不自动带入,
65
+ // 报告数与文件列表供人工/编排确认归属(是否属于当前 change)。
66
+ function checkUncommitted(repoDir) {
67
+ const opts = { encoding: 'utf-8', cwd: repoDir, stdio: ['ignore', 'pipe', 'pipe'] };
68
+ try {
69
+ const out = execFileSync('git', ['status', '--porcelain'], opts).toString();
70
+ const files = out.split('\n').filter(Boolean);
71
+ return { count: files.length, files };
72
+ } catch {
73
+ return { count: 0, files: [] };
74
+ }
75
+ }
76
+
77
+ // 检查分支是否远程共享(sop-flow-2,multi-repo-support-design v1.0 §4.3)。
78
+ // 通过 git branch -vv 检测 [origin/...] tracking + ahead/behind。
79
+ // P3 #3:有 upstream tracking 即视为共享分支(ahead/behind 非 0 是充分非必要条件——
80
+ // 已同步分支就地实施后也会变 ahead 污染共享分支),须建 worktree/新分支,而非就地实施。
81
+ function checkSharedBranch(repoDir) {
82
+ const opts = { encoding: 'utf-8', cwd: repoDir, stdio: ['ignore', 'pipe', 'pipe'] };
83
+ let branch;
84
+ try {
85
+ branch = (execFileSync('git', ['branch', '--show-current'], opts) || '').trim();
86
+ } catch {
87
+ return { shared: false };
88
+ }
89
+ if (!branch) return { shared: false };
90
+ try {
91
+ const vv = execFileSync('git', ['branch', '-vv'], opts).toString();
92
+ // P3 评审 #5:当前分支行以 '*' 开头,避免子串误命中名称含当前分支名的其他分支(如 feature/x vs feature/x2)
93
+ const line = vv.split('\n').find((l) => l.startsWith('*') && l.includes(branch));
94
+ if (!line) return { shared: false };
95
+ const tracking = line.match(/\[([^\]]+)\]/);
96
+ if (!tracking) return { shared: false };
97
+ const ahead = line.match(/ahead (\d+)/)?.[1];
98
+ const behind = line.match(/behind (\d+)/)?.[1];
99
+ return {
100
+ shared: true,
101
+ upstream: tracking[1],
102
+ ahead: parseInt(ahead || '0', 10),
103
+ behind: parseInt(behind || '0', 10),
104
+ };
105
+ } catch {
106
+ return { shared: false };
107
+ }
108
+ }
109
+
63
110
  // 枚举 root 下含 .git 的直接子目录(= 代码仓库),按目录名排序保证确定性。
64
111
  // .git 可能是目录(普通仓库)或文件(worktree/submodule 链接),existsSync 均覆盖。
65
112
  function listCodeRepos(root) {
@@ -128,8 +175,34 @@ function runMultiRepo(root, repos) {
128
175
  continue;
129
176
  }
130
177
 
131
- // 该仓库已不在受保护分支 → 已隔离,无需建 worktree(沿用单仓库 already-isolated 语义)。
178
+ // 该仓库已不在受保护分支 → 判断是否远程共享分支(sop-flow-2,v1.0 §4.3):
179
+ // 共享分支(upstream tracking + ahead/behind 非 0)应视为"非隔离"——就地实施会污染共享分支,
180
+ // 须建独立 worktree/新分支。纯本地分支或无 tracking → 已隔离。
132
181
  if (!PROTECTED.includes(branch)) {
182
+ const shareInfo = checkSharedBranch(repoDir);
183
+ // P3 评审 #3:有 upstream tracking 即视为共享分支(ahead/behind 非 0 是充分非必要条件——
184
+ // 已同步分支就地实施后也会变 ahead 污染共享分支)
185
+ const sharedRisk = shareInfo.shared;
186
+ if (sharedRisk) {
187
+ const uncommitted = checkUncommitted(repoDir);
188
+ console.error(
189
+ `ensure-branch: [${repo}] on SHARED branch '${branch}' (upstream ${shareInfo.upstream}, `
190
+ + `ahead ${shareInfo.ahead}/behind ${shareInfo.behind}) — NOT isolated; creating worktree to avoid polluting the shared branch...`
191
+ + (uncommitted.count > 0 ? ` (${uncommitted.count} uncommitted change(s) not carried into worktree — verify ownership before discarding)` : '')
192
+ );
193
+ try {
194
+ execFileSync('git', ['worktree', 'add', wtPath, '-b', branchBase], { ...repoOpts, stdio: 'inherit' });
195
+ console.log(`ensure-branch: [${repo}] created worktree at ${wtPath} on branch '${branchBase}'.`);
196
+ } catch (e) {
197
+ console.error(`ensure-branch: [${repo}] worktree creation failed: ${(e.stderr || e.stdout || e.message || 'unknown').toString().trim()}`);
198
+ failed.push(repo);
199
+ }
200
+ continue;
201
+ }
202
+ const uncommitted = checkUncommitted(repoDir);
203
+ if (uncommitted.count > 0) {
204
+ console.warn(`ensure-branch: [${repo}] has ${uncommitted.count} uncommitted change(s); verify they belong to the current change.`);
205
+ }
133
206
  console.log(`ensure-branch: [${repo}] already isolated on branch '${branch}'.`);
134
207
  continue;
135
208
  }
@@ -173,11 +246,28 @@ function runSingleRepo() {
173
246
  }
174
247
 
175
248
  if (!PROTECTED.includes(branch)) {
176
- console.log(`ensure-branch: already isolated on branch '${branch}'. Proceed with implementation edits.`);
177
- process.exit(0);
249
+ const shareInfo = checkSharedBranch(changeDir);
250
+ // P3 评审 #3:有 upstream tracking 即视为共享分支
251
+ const sharedRisk = shareInfo.shared;
252
+ if (sharedRisk) {
253
+ const uncommitted = checkUncommitted(changeDir);
254
+ console.error(
255
+ `ensure-branch: on SHARED branch '${branch}' (upstream ${shareInfo.upstream}, `
256
+ + `ahead ${shareInfo.ahead}/behind ${shareInfo.behind}) — NOT isolated; creating worktree to avoid polluting the shared branch...`
257
+ + (uncommitted.count > 0 ? ` (${uncommitted.count} uncommitted change(s) not carried into worktree — verify ownership before discarding)` : '')
258
+ );
259
+ // fall through 到下方 worktree 创建逻辑(不 exit(0))
260
+ } else {
261
+ const uncommitted = checkUncommitted(changeDir);
262
+ if (uncommitted.count > 0) {
263
+ console.warn(`ensure-branch: ${uncommitted.count} uncommitted change(s); verify they belong to the current change.`);
264
+ }
265
+ console.log(`ensure-branch: already isolated on branch '${branch}'. Proceed with implementation edits.`);
266
+ process.exit(0);
267
+ }
178
268
  }
179
269
 
180
- console.error(`ensure-branch: on protected branch '${branch}'. Creating an isolated implementation context...`);
270
+ console.error(`ensure-branch: on ${PROTECTED.includes(branch) ? 'protected' : 'shared non-protected'} branch '${branch}'. Creating an isolated implementation context...`);
181
271
 
182
272
  const repoName = basename(changeDir) || 'repo';
183
273
  const name = sanitizeBranchName(changeName || repoName);
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * repo-layout — 项目布局检测 CLI(multi-repo-support-design v1.0 §3)
4
+ *
5
+ * 用法:tf repo-layout detect <root> [--json]
6
+ * 判定项目布局(single / monorepo / multi-repo)+ 代码仓库清单,写 team-flow.config.json 的 repo_layout 段。
7
+ * 由 workflow-start DP-0 / orchestrator S1 项目模式确认调用;detect/review/isolate 按模式路由。
8
+ */
9
+
10
+ import { resolve } from 'node:path';
11
+ import { existsSync } from 'node:fs';
12
+ import { detectRepoLayout, writeRepoLayoutConfig } from './conventions-generator.mjs';
13
+
14
+ export async function run(args) {
15
+ const positionals = args.filter(a => !a.startsWith('--'));
16
+ const json = args.includes('--json');
17
+ const subcommand = positionals[0];
18
+ const root = positionals[1];
19
+
20
+ if (subcommand !== 'detect' || !root) {
21
+ console.error('Usage: tf repo-layout detect <root> [--json]');
22
+ process.exit(2);
23
+ }
24
+
25
+ const rootPath = resolve(root);
26
+ if (!existsSync(rootPath)) {
27
+ console.error(`❌ 项目根不存在: ${rootPath}`);
28
+ process.exit(1);
29
+ }
30
+ const repoLayout = detectRepoLayout(rootPath);
31
+ writeRepoLayoutConfig(rootPath, repoLayout);
32
+
33
+ if (json) {
34
+ console.log(JSON.stringify({ ok: true, ...repoLayout }));
35
+ } else {
36
+ const repoCount = Object.keys(repoLayout.repos).length;
37
+ console.log(`✅ repo_layout: ${repoLayout.mode}(${repoCount} 个代码仓库)`);
38
+ if (repoCount > 0) {
39
+ console.log(` 仓库清单: ${Object.keys(repoLayout.repos).join(', ')}`);
40
+ }
41
+ console.log(` config 已写 ${rootPath}/.team-flow/team-flow.config.json`);
42
+ }
43
+ }
44
+
45
+ // 直接运行
46
+ if (import.meta.url === `file://${process.argv[1]}`) {
47
+ run(process.argv.slice(2)).catch(err => {
48
+ console.error(err);
49
+ process.exit(1);
50
+ });
51
+ }
@@ -1,10 +1,11 @@
1
1
  // Config loader for team-flow
2
2
  // Loads team-flow.config.json and merges with built-in defaults.
3
- // Lookup order: (1) projectRoot, (2) git root, (3) home directory.
3
+ // Lookup order: (1) projectRoot, (2) git root, (3) workspace root, (4) home directory.
4
4
 
5
5
  import { readFileSync, existsSync } from 'node:fs';
6
6
  import { join } from 'node:path';
7
7
  import { execFileSync } from 'node:child_process';
8
+ import { detectWorkspaceRoot } from './git-utils.mjs';
8
9
 
9
10
  const DEFAULTS = {
10
11
  artifacts: {
@@ -35,6 +36,12 @@ const DEFAULTS = {
35
36
  version: null,
36
37
  delegation_mode: 'auto',
37
38
  },
39
+ repo_layout: {
40
+ // 项目布局(multi-repo-support-design v1.0 §3)
41
+ // 项目模式确认(DP-0 / orchestrator S1)时写入;detect/review/isolate 按模式路由
42
+ mode: null,
43
+ repos: {},
44
+ },
38
45
  };
39
46
 
40
47
  export const MODEL_PROFILES = Object.freeze([
@@ -106,6 +113,15 @@ function findConfigFile(startDir) {
106
113
  // Not a git repo — skip
107
114
  }
108
115
 
116
+ // 3.5 multi-repo-support-design v1.0(P3 评审 #2 修复):change 目录 → 工作区根(changes/ 父目录)的 .team-flow/。
117
+ // 根非 git 仓库的 multi-repo 下,detect 写项目根 config 后,change 目录 loadConfig 需经此读到(findConfigFile
118
+ // 三级查找(changeDir→git root→home)不覆盖非 git 根的项目根 .team-flow/)。
119
+ const workspaceRoot = detectWorkspaceRoot(startDir);
120
+ if (workspaceRoot && workspaceRoot !== startDir) {
121
+ const wsTeamFlowDir = join(workspaceRoot, '.team-flow', 'team-flow.config.json');
122
+ if (existsSync(wsTeamFlowDir)) return wsTeamFlowDir;
123
+ }
124
+
109
125
  // 4. Check home directory
110
126
  const homePath = join(process.env.HOME || '', 'team-flow.config.json');
111
127
  if (existsSync(homePath)) return homePath;
@@ -59,10 +59,13 @@ export function detectGlaf4DevPlugin(pluginsFilePath = PLUGINS_INSTALLED_PATH) {
59
59
  * @returns {{ is_glaf4_java: boolean, glaf4_dev_available: boolean, glaf4_dev_version: string|null, delegation_mode: 'auto'|'manual'|'off' }}
60
60
  */
61
61
  export function detectGlaf4Delegation(root, options = {}) {
62
- const techStack = detectTechStack(root);
63
62
  // is_glaf4_java = Java 技术栈命中(pom.xml/build.gradle 存在即可,v2.1 §4)
64
63
  // glaf4-dev 只处理 Java,Spring/JUnit 细分由 contract-builder 已有检测负责
65
- const isGlaf4Java = techStack.language === 'java';
64
+ // multi-repo-support-design v1.0 §4.1:多仓库下按 repos 清单聚合判定——任一仓库 Java → 项目级 true
65
+ const repos = Array.isArray(options.repos) ? options.repos : null;
66
+ const isGlaf4Java = repos && repos.length > 0
67
+ ? repos.some(r => detectTechStack(r).language === 'java')
68
+ : detectTechStack(root).language === 'java';
66
69
  const plugin = detectGlaf4DevPlugin(options.pluginsFilePath);
67
70
  const mode = options.delegationMode || 'auto';
68
71
  return {
@@ -104,6 +107,62 @@ export function writeGlaf4DevConfig(root, glaf4DevInfo) {
104
107
  writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
105
108
  }
106
109
 
110
+ // ── repo_layout 检测(multi-repo-support-design v1.0 §3,2026-08-21)─────────────
111
+
112
+ // 非代码仓库目录(team-flow 产物/基础设施),扫描时排除
113
+ const NON_REPO_DIRS = new Set([
114
+ 'changes', '.team-flow', 'docs', 'doc', 'node_modules', '.worktrees',
115
+ 'requirement', 'prototype', 'specs', 'data', 'path', 'template',
116
+ ]);
117
+
118
+ /**
119
+ * 识别项目布局(single / monorepo / multi-repo,v1.0 §3.1)
120
+ * @param {string} root 项目根目录
121
+ * @returns {{ mode: 'single'|'monorepo'|'multi-repo', repos: Record<string,string> }}
122
+ */
123
+ export function detectRepoLayout(root) {
124
+ // 1. 根直接含技术栈特征(pom.xml/package.json/build.gradle)→ single 或 monorepo(Maven 聚合/多子模块)
125
+ if (existsSync(join(root, 'pom.xml')) || existsSync(join(root, 'package.json')) || existsSync(join(root, 'build.gradle'))) {
126
+ // P3 评审 #6:子模块排除 NON_REPO_DIRS(changes/docs/data 等含 package.json 会被 scanSubProjects 误计为模块 → 误判 monorepo)
127
+ const subModules = scanSubProjects(root).filter(m => !NON_REPO_DIRS.has(m.name));
128
+ const repos = {};
129
+ for (const m of subModules) repos[m.name] = m.path;
130
+ return { mode: subModules.length > 0 ? 'monorepo' : 'single', repos };
131
+ }
132
+ // 2. 根无技术栈特征 → 扫描子目录识别独立代码仓库(含 .git 或有技术栈语言)
133
+ const repos = {};
134
+ const entries = readdirSync(root, { withFileTypes: true });
135
+ for (const entry of entries) {
136
+ if (!entry.isDirectory()) continue;
137
+ if (entry.name.startsWith('.') || NON_REPO_DIRS.has(entry.name)) continue;
138
+ const sub = join(root, entry.name);
139
+ const hasGit = existsSync(join(sub, '.git'));
140
+ const tech = detectTechStack(sub);
141
+ if (hasGit || tech.language) {
142
+ repos[entry.name] = sub;
143
+ }
144
+ }
145
+ const repoCount = Object.keys(repos).length;
146
+ return { mode: repoCount >= 2 ? 'multi-repo' : 'single', repos };
147
+ }
148
+
149
+ /**
150
+ * 写 repo_layout 段到 team-flow.config.json(v1.0 §3.2)
151
+ * @param {string} root 项目根
152
+ * @param {{ mode: 'single'|'monorepo'|'multi-repo', repos: Record<string,string> }} repoLayout
153
+ */
154
+ export function writeRepoLayoutConfig(root, repoLayout) {
155
+ const teamFlowDir = join(root, '.team-flow');
156
+ const configPath = join(teamFlowDir, 'team-flow.config.json');
157
+ mkdirSync(teamFlowDir, { recursive: true });
158
+ let config = {};
159
+ if (existsSync(configPath)) {
160
+ try { config = JSON.parse(readFileSync(configPath, 'utf-8')); } catch { config = {}; }
161
+ }
162
+ config.repo_layout = repoLayout;
163
+ writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
164
+ }
165
+
107
166
  // ── 常量 ─────────────────────────────────────────────────────────────────────
108
167
 
109
168
  const TEMPLATE_DIR = join(import.meta.dirname, '../../templates/conventions');
@@ -271,12 +271,12 @@ function getPhysicalReviewsDirectory(changeDir) {
271
271
  let directory = changeRoot;
272
272
  for (const component of ['.superpowers', 'sdd', 'reviews']) {
273
273
  directory = join(directory, component);
274
- let metadata;
275
- try {
276
- metadata = lstatSync(directory);
277
- } catch (error) {
278
- throw new Error(`Review report evidence cannot read the ${component} overlay directory: ${error.message}`);
274
+ // multi-repo-support v1.0 §4.2(cli-command-2 修复):overlay 目录自动创建,修 ENOENT
275
+ // (首次 review 时 .superpowers/sdd/reviews/ 尚不存在,recordReview 写入前先建)
276
+ if (!existsSync(directory)) {
277
+ mkdirSync(directory, { recursive: true });
279
278
  }
279
+ const metadata = lstatSync(directory);
280
280
  if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
281
281
  throw new Error('Review report evidence requires physical .superpowers/sdd/reviews overlay directories');
282
282
  }
@@ -312,8 +312,11 @@ function validateReviewRange(changeDir, base, head, repoPath) {
312
312
  // This happens either through automatic fallback (subRepoPath set above)
313
313
  // or through explicit --repo pointing to a different repository.
314
314
  if (!subRepoPath && repoPath) {
315
- const defaultRoot = resolveGitRoot(changeDir);
316
- if (gitRoot !== defaultRoot) subRepoPath = gitRoot;
315
+ // multi-repo-support v1.0 §4.2(cli-command-2 修复):--repo 场景下 change 目录可能无 git
316
+ //(多仓库 changes/ 未版本化),defaultRoot 比较容错返回 null,不因 change 目录无 git 报错
317
+ let defaultRoot = null;
318
+ try { defaultRoot = resolveGitRoot(changeDir); } catch {}
319
+ if (defaultRoot && gitRoot !== defaultRoot) subRepoPath = gitRoot;
317
320
  }
318
321
 
319
322
  const effectiveRoot = subRepoPath || gitRoot;
@@ -3,8 +3,10 @@
3
3
  * glaf4-delegation — GLAF4 委托协议 CLI(v2.1 §6.6/§6.3/§6.7,P2 实施委托全链路)
4
4
  *
5
5
  * 用法:
6
- * tf glaf4-delegation detect <root> [--delegation-mode <mode>] [--json]
7
- * 运行时探测(v2.1 §4 接口①,C1 修复接线):三态检测 + 写 .team-flow/team-flow.config.json 的 glaf4_dev 段。
6
+ * tf glaf4-delegation detect <root> [--delegation-mode <mode>] [--target-repo <模块路径>] [--json]
7
+ * 运行时探测(v2.1 §4 接口①,C1 修复接线 + multi-repo-support v1.0 §4.1):
8
+ * root 解析(change 目录→项目根)+ 写 .team-flow/team-flow.config.json 的 glaf4_dev 段(项目根)。
9
+ * multi-repo 下按 repo_layout 清单聚合判定 is_glaf4_java;--target-repo 精确探测指定模块。
8
10
  * contract-builder 产出 execution-contract 时(DP-4 前)显式调用此命令,recommend 才能读到 glaf4_dev。
9
11
  * tf glaf4-delegation confirm <change-dir> --mode <mode> --write-set <json> [--json]
10
12
  * DP-4 委托方案确认:mode 枚举标量入 state,write_set_boundary 落 .superpowers/glaf4/write-set.json,
@@ -28,7 +30,9 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync
28
30
  import { join, isAbsolute, relative, resolve, normalize, sep } from 'node:path';
29
31
  import { readState, writeState } from './state-loader.mjs';
30
32
  import { getOverlayPaths } from './sdd-overlay.mjs';
31
- import { detectGlaf4Delegation, writeGlaf4DevConfig } from './conventions-generator.mjs';
33
+ import { detectGlaf4Delegation, detectTechStack, writeGlaf4DevConfig } from './conventions-generator.mjs';
34
+ import { detectWorkspaceRoot, getGitRoot } from './git-utils.mjs';
35
+ import { loadConfig } from './config-loader.mjs';
32
36
 
33
37
  // DP-4 委托模式合法枚举(对应 glaf4-dev 七模式中可委托 change 的六种)
34
38
  export const GLAF4_DELEGATION_MODES = [
@@ -72,26 +76,42 @@ export function hashWriteSet(writeSet) {
72
76
  * @param {string} [delegationMode] 覆盖 delegation_mode(auto/manual/off)
73
77
  * @returns {object} { ok, is_glaf4_java, glaf4_dev_available, glaf4_dev_version, delegation_mode, configPath }
74
78
  */
75
- export function detectAndWriteConfig(root, delegationMode) {
76
- const detection = detectGlaf4Delegation(root, { delegationMode });
79
+ export function detectAndWriteConfig(root, delegationMode, targetRepo) {
80
+ // multi-repo-support-design v1.0 §4.1(cli-command-1 修复):root 解析——change 目录(含 changes/)→ 项目根;否则 git 根
81
+ const projectRoot = resolveProjectRoot(root);
82
+
83
+ // 读 repo_layout(config 已固化时)
84
+ const config = loadConfig(projectRoot);
85
+ const repoLayout = config?.repo_layout || null;
86
+
87
+ // 探测目标构造(P3 自查补全 + P4 validator W1 放宽,2026-08-21):
88
+ // --target-repo 精确 > repo_layout 清单聚合(repos 非空即聚合,不限 multi-repo——
89
+ // 壳仓库含 package.json 误判 monorepo 时也应聚合,否则 cli-command-1 在真实项目失效)>
90
+ // root 有技术栈(探测 root,如 detect(svcA))>
91
+ // root 无技术栈(change 文档目录/容器根)→ 探测解析后项目根(单仓库项目根有 pom.xml)
92
+ let repos = null;
93
+ let probeRoot = root;
94
+ if (targetRepo) {
95
+ probeRoot = targetRepo;
96
+ } else if (repoLayout?.repos && Object.keys(repoLayout.repos).length > 0) {
97
+ repos = Object.values(repoLayout.repos);
98
+ } else if (!detectTechStack(root).language) {
99
+ probeRoot = projectRoot;
100
+ }
101
+ const detection = detectGlaf4Delegation(probeRoot, { delegationMode, repos });
77
102
 
78
- // 复评 C1 嵌套工程根盲区(2026-08-18):git root target_root(monorepo 布局)时,
79
- // loadConfig(changeDir) 只查 changeDir→git root→home,不查 target_root → 委托链静默断裂。
80
- // 写 git root 冗余副本保证从任意 changeDir 都能读到探测结果。gitRoot 提前解析供 mode 优先级使用。
103
+ // git root(冗余副本判断 + mode 优先级)
81
104
  let gitRoot = null;
82
105
  try {
83
- gitRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
84
- cwd: root, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],
85
- }).trim();
106
+ gitRoot = getGitRoot(projectRoot);
86
107
  } catch {
87
108
  // 非 git 仓库,跳过
88
109
  }
89
110
 
90
- // 第四轮复评 Important(2026-08-18):delegation_mode 优先级链补全——显式 > 目标 root 已有 > git root 已有 > auto
91
- // 上轮只查目标 root,非 Java 服务无本地 config → 默认 auto → 覆盖 git root 副本的 off(用户 off 意图被静默翻转)。
111
+ // delegation_mode 优先级链:显式 > 目标 root 已有 > git root 已有 > auto
92
112
  let effectiveMode = delegationMode;
93
113
  if (!effectiveMode) {
94
- effectiveMode = readGlaf4DelegationMode(root)
114
+ effectiveMode = readGlaf4DelegationMode(projectRoot)
95
115
  || (gitRoot ? readGlaf4DelegationMode(gitRoot) : null)
96
116
  || 'auto';
97
117
  }
@@ -100,16 +120,17 @@ export function detectAndWriteConfig(root, delegationMode) {
100
120
  version: detection.glaf4_dev_version,
101
121
  delegationMode: effectiveMode,
102
122
  };
103
- writeGlaf4DevConfig(root, info);
123
+ // config 主副本写项目根(cli-command-1 修复:不再写 change 目录)
124
+ // multi-repo-support v1.0:OR 聚合保留已有 enabled=true——项目级 GLAF4 能力一旦声明,
125
+ // 不因后续非 Java 目标探测而覆盖丢失(非 Java change detect 不应禁用项目委托)
126
+ const existingProjEnabled = readGitRootGlaf4Enabled(projectRoot);
127
+ const projEnabled = info.enabled || existingProjEnabled;
128
+ writeGlaf4DevConfig(projectRoot, { ...info, enabled: projEnabled, delegationMode: effectiveMode });
104
129
 
105
130
  let gitRootConfig = null;
106
- if (gitRoot && gitRoot !== root) {
107
- // 第三轮复评 Important①(2026-08-18):多服务混合 monorepo 下 git root 副本 last-write-wins 污染——
108
- // 非 Java 服务 detect 会把 Java 服务的 enabled=true 覆盖成 false。改为 OR 聚合:
109
- // 项目级能力一旦声明(任一服务 enabled=true),不因后续非 Java 服务探测而丢失。
131
+ if (gitRoot && gitRoot !== projectRoot) {
110
132
  const existingEnabled = readGitRootGlaf4Enabled(gitRoot);
111
133
  const aggregatedEnabled = info.enabled || existingEnabled;
112
- // 第四轮复评:git root 副本 mode 保留已有值(显式传参才覆盖)——用户 off 意图不因新探测静默翻转。
113
134
  const gitRootMode = readGlaf4DelegationMode(gitRoot);
114
135
  const gitRootEffectiveMode = delegationMode || gitRootMode || effectiveMode;
115
136
  writeGlaf4DevConfig(gitRoot, { ...info, enabled: aggregatedEnabled, delegationMode: gitRootEffectiveMode });
@@ -119,11 +140,27 @@ export function detectAndWriteConfig(root, delegationMode) {
119
140
  return {
120
141
  ok: true,
121
142
  ...detection,
122
- configPath: join(root, '.team-flow', 'team-flow.config.json'),
143
+ configPath: join(projectRoot, '.team-flow', 'team-flow.config.json'),
123
144
  gitRootConfig,
145
+ projectRoot,
124
146
  };
125
147
  }
126
148
 
149
+ /**
150
+ * root 解析(multi-repo-support-design v1.0 §4.1):change 目录(含 changes/)→ 项目根;否则 git 根;兜底直接用 root
151
+ * @param {string} root
152
+ * @returns {string}
153
+ */
154
+ function resolveProjectRoot(root) {
155
+ const ws = detectWorkspaceRoot(root);
156
+ if (ws) return ws;
157
+ try {
158
+ return getGitRoot(root);
159
+ } catch {
160
+ return root;
161
+ }
162
+ }
163
+
127
164
  /**
128
165
  * 读 git root 现有 config 的 glaf4_dev.enabled(第三轮复评 Important① OR 聚合用)
129
166
  * @param {string} gitRoot
@@ -394,7 +431,7 @@ export function resetDelegation(changeDir) {
394
431
 
395
432
  export async function run(args) {
396
433
  const positionals = args.filter(a => !a.startsWith('--'));
397
- const flags = new Set(args.filter(a => a.startsWith('--') && a !== '--mode' && a !== '--write-set' && a !== '--run-dir' && a !== '--target-root' && a !== '--json'));
434
+ const flags = new Set(args.filter(a => a.startsWith('--') && a !== '--mode' && a !== '--write-set' && a !== '--run-dir' && a !== '--target-root' && a !== '--target-repo' && a !== '--delegation-mode' && a !== '--json'));
398
435
  const opt = (name) => {
399
436
  const i = args.indexOf(`--${name}`);
400
437
  return i >= 0 ? args[i + 1] : undefined;
@@ -404,7 +441,7 @@ export async function run(args) {
404
441
  const json = flags.has('--json') || args.includes('--json');
405
442
 
406
443
  const usage = `Usage:
407
- tf glaf4-delegation detect <root> [--delegation-mode <auto|manual|off>]
444
+ tf glaf4-delegation detect <root> [--delegation-mode <auto|manual|off>] [--target-repo <模块路径>]
408
445
  tf glaf4-delegation confirm <change-dir> --mode <mode> --write-set <json-file>
409
446
  tf glaf4-delegation verify-write-set <change-dir> --run-dir <run-dir>
410
447
  tf glaf4-delegation verify-tasks <change-dir>
@@ -424,15 +461,16 @@ export async function run(args) {
424
461
  try {
425
462
  if (subcommand === 'detect') {
426
463
  const mode = opt('delegation-mode');
464
+ const targetRepo = opt('target-repo');
427
465
  // 第四轮复评 Minor-1(2026-08-18):枚举校验——非法值(如 'foo')等同 auto 放行会让用户配置失真
428
466
  if (mode !== undefined && !['auto', 'manual', 'off'].includes(mode)) {
429
467
  console.error(`--delegation-mode 必须为 auto/manual/off 之一(实际: ${mode})`);
430
468
  process.exit(2);
431
469
  }
432
- const result = detectAndWriteConfig(changeDir, mode);
470
+ const result = detectAndWriteConfig(changeDir, mode, targetRepo);
433
471
  const msg = result.glaf4_dev_available
434
- ? `探测: is_glaf4_java=${result.is_glaf4_java}, glaf4-dev v${result.glaf4_dev_version} 可用, delegation_mode=${result.delegation_mode} → config 已写 ${result.configPath}`
435
- : `探测: is_glaf4_java=${result.is_glaf4_java}, glaf4-dev 不可用 → config 已写 ${result.configPath}`;
472
+ ? `探测: is_glaf4_java=${result.is_glaf4_java}, glaf4-dev v${result.glaf4_dev_version} 可用, delegation_mode=${result.delegation_mode} → config 已写 ${result.configPath}${result.projectRoot ? `(项目根 ${result.projectRoot})` : ''}`
473
+ : `探测: is_glaf4_java=${result.is_glaf4_java}, glaf4-dev 不可用 → config 已写 ${result.configPath}${result.projectRoot ? `(项目根 ${result.projectRoot})` : ''}`;
436
474
  print(result.ok, result, msg);
437
475
  } else if (subcommand === 'confirm') {
438
476
  const mode = opt('mode');
@@ -42,6 +42,7 @@ const COMMANDS = {
42
42
  'test-matrix-export': () => import('./lib/test-matrix-export.mjs'),
43
43
  'glaf4-evidence-export': () => import('./lib/glaf4-evidence-export.mjs'),
44
44
  'glaf4-delegation': () => import('./lib/glaf4-delegation.mjs'),
45
+ 'repo-layout': () => import('./lib/cmd-repo-layout.mjs'),
45
46
  test: () => import('./lib/test-record.mjs'),
46
47
  };
47
48
 
@@ -76,6 +77,8 @@ Commands:
76
77
  Aggregate glaf4-dev run PASS evidence → surefire line (v2.1 §7; feed test record --from)
77
78
  glaf4-delegation <sub> <dir> [--mode <m> --write-set <json> | --run-dir <run> | --delegation-mode <mode>]
78
79
  GLAF4 委托协议 (v2.1 §4/6.3/6.6/6.7): detect / confirm / verify-write-set / verify-tasks / record-partial / reset
80
+ repo-layout detect <root>
81
+ Detect project layout (single/monorepo/multi-repo) + code repos, write repo_layout config (v1.0 §3)
79
82
  test record <dir> --from <runner-output> [--runner auto|maven-surefire|jest|pytest]
80
83
  Record programmatic test evidence (v0.13 §50; feeds tests-passing gate)
81
84
  config [options] Display or modify configuration
@@ -9,17 +9,19 @@
9
9
  contract-builder 产出 execution-contract 时(DP-4 前)实时探测——**显式运行 CLI 命令**(第三轮复评接线统一:探测必须写 config,纯库函数不落盘):
10
10
 
11
11
  ```bash
12
- tf glaf4-delegation detect <target_root> [--delegation-mode <auto|manual|off>]
12
+ tf glaf4-delegation detect <target_root> [--delegation-mode <auto|manual|off>] [--target-repo <模块路径>]
13
13
  ```
14
14
 
15
+ **target_root 语义(multi-repo-support-design v1.0 §4.1,cli-command-1 修复)**:传入**项目根或 change 目录均可**——detect 自动解析:change 目录(含 `changes/`)→ 项目根,config 主副本写**项目根** `.team-flow/team-flow.config.json`(不写 change 目录)。**多仓库项目(`repo_layout: multi-repo`)推荐传 `--target-repo <模块路径>`**(如 change 涉及 `batch-fytx-msg`),或依赖自动扫描:按 `repo_layout.repos` 清单聚合判定——任一代码仓库是 Java → 项目级 `is_glaf4_java=true`。
16
+
15
17
  `detect` 内部调用 `conventions-generator.mjs` 的 `detectGlaf4Delegation(root)` 解析 `~/.claude/plugins/installed_plugins.json`(glaf4-dev 条目含 installPath + version),产出三态:
16
18
 
17
- - `is_glaf4_java`(技术栈命中:pom.xml/build.gradle + Spring Boot/JUnit5/Mockito
19
+ - `is_glaf4_java`(技术栈命中:pom.xml/build.gradle + Spring Boot/JUnit5/Mockito;**多仓库下按 repos 清单聚合,任一仓库 Java → true**)
18
20
  - `glaf4_dev_available`(插件可用,含 version)
19
21
  - `delegation_mode`(auto/manual/off,用户可开关)
20
22
 
21
- 探测结果写 `team-flow.config.json` 的 `glaf4_dev: {enabled, version, delegation_mode}` 段
22
- (git root ≠ target_root 时写 git root 冗余副本,monorepo 下多服务 OR 聚合;未传 `--delegation-mode` 保留已有值)。
23
+ 探测结果写 `<项目根>/.team-flow/team-flow.config.json` 的 `glaf4_dev: {enabled, version, delegation_mode}` 段
24
+ (git root ≠ target_root 时写 git root 冗余副本;未传 `--delegation-mode` 保留已有值)。
23
25
 
24
26
  **判定**:`is_glaf4_java && glaf4_dev_available && delegation_mode !== 'off'` → 产出 GLAF4 Delegation 段。
25
27
  **依赖**:`recommendExecutionModesForChange` 读 `config.glaf4_dev.enabled` 决定是否注入 glaf4-delegation——**必须**先跑 detect 写 config,否则委托链不可达。
@@ -42,6 +42,13 @@ Do NOT invoke for:
42
42
  **conventions 注入(v0.11 §33)**:
43
43
  - 读取 conventions 配置,注入为需求分析上下文
44
44
 
45
+ **项目模式确认(multi-repo-support-design v1.0 §3.3,2026-08-21)**:S1 路由时确认项目布局,写 config 供 detect/review/isolate 按模式路由——
46
+ 1. 定位项目根(`detectWorkspaceRoot` / `getGitRoot`);`<项目根>/.team-flow/team-flow.config.json` 已有 `repo_layout` 段 → 直接读取(已固化跳过)
47
+ 2. 否则运行 `tf repo-layout detect <项目根>`:判定 `single`/`monorepo`/`multi-repo` + 代码仓库清单,写 `<项目根>/.team-flow/team-flow.config.json` 的 `repo_layout` 段
48
+ 3. 多仓库项目向用户展示判定结果(AskUserQuestion 确认);单仓库自动;修正 repos 清单编辑 config 的 `repo_layout.repos`
49
+ 4. 影响:detect(按仓库清单探测 GLAF4)/ review(`--repo` 放宽 git 约束)/ isolate(共享分支检测)
50
+ 5. 边界:本步骤识别存量结构;全新项目骨架引导归 workflow-bootstrap B1.5
51
+
45
52
  ### S2: PRD + 原型阶段
46
53
 
47
54
  **⛔ MANDATORY:执行S2阶段前,必须先读取 `references/s2-prd-prototype-loop.md`**
@@ -34,6 +34,16 @@ Run DP-0 when: change folder doesn't exist, planning artifacts missing/empty, or
34
34
 
35
35
  若 `change-brief.md` 存在且 `upstream_source == orchestrator`(本 change 由 orchestrator S4 分发),**继承** brief 的 scope/约束/AC 为默认值,DP-0 从"从零问"改为"一次确认继承或修正",**不**重新问"你想做什么"。否则(手动新建 / hotfix / 单 change 快速通道 / 存量 change 无 brief)照常 DP-0。**主信号 = brief 文件存在**(非 yaml 字段——可天然排除无 brief 的快速通道,且对存量手动 change 零误伤);双源冲突以 `requirement/vN/plan.md` 为准并触发 Brief drift(见「Staleness Detection」)。完整判定伪代码与主信号理由见 `references/routing-rules.md`「DP-0」。
36
36
 
37
+ ### 项目模式确认(multi-repo-support-design v1.0 §3.3,2026-08-21)
38
+
39
+ DP-0 时确认项目布局(`single`/`monorepo`/`multi-repo`),写 config 供 detect/review/isolate 按模式路由:
40
+ 1. **定位项目根**:`detectWorkspaceRoot(changeDir)`(change 目录 → `changes/` 父目录);非标准布局回退 `getGitRoot`
41
+ 2. **已固化跳过**:`<项目根>/.team-flow/team-flow.config.json` 已有 `repo_layout` 段 → 直接读取,跳过 3-4
42
+ 3. **运行 `tf repo-layout detect <项目根>`**:判定 `single`/`monorepo`/`multi-repo` + 代码仓库清单,写 `<项目根>/.team-flow/team-flow.config.json` 的 `repo_layout` 段
43
+ 4. **多仓库项目首次确认**:向用户展示判定结果(`multi-repo + N 个代码仓库`),AskUserQuestion 确认;单仓库自动。**修正 repos 清单**:确认后编辑 `<项目根>/.team-flow/team-flow.config.json` 的 `repo_layout.repos`(缺省接受检测结果)
44
+ 5. **与 workflow-bootstrap 边界**:本步骤识别**存量结构**(single/monorepo/multi-repo 探测 + repos 清单);全新项目骨架引导(生成 pom.xml/package.json)归 workflow-bootstrap B1.5
45
+ 6. 判定结果影响:detect(按仓库清单探测 GLAF4)/ review(`--repo` 放宽 git 约束)/ isolate(共享分支检测)
46
+
37
47
  Ask (manual path): change name + one-sentence intent, known constraints, related optimizations (include or stay focused?), communication preference (ask per decision or draft for review).
38
48
 
39
49
  After confirmation: