@xulthekl/team-flow 0.39.1 → 0.41.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.
Files changed (41) hide show
  1. package/.claude/always/phase-guard.md +1 -1
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +1 -1
  4. package/.codex-plugin/plugin.json +1 -1
  5. package/.cursor-plugin/marketplace.json +1 -1
  6. package/.cursor-plugin/plugin.json +1 -1
  7. package/.github/plugin/marketplace.json +2 -2
  8. package/AGENTS.md +2 -2
  9. package/CHANGELOG.md +9 -0
  10. package/GEMINI.md +1 -1
  11. package/INSTALL.md +1 -1
  12. package/README.md +1 -1
  13. package/docs/README_en.md +1 -1
  14. package/docs/solutions/INDEX.md +1 -0
  15. package/docs/solutions/cross-phase/2026-08-07-no-summary.md +17 -0
  16. package/gemini-extension.json +1 -1
  17. package/hooks/session-start +2 -2
  18. package/llms.txt +1 -1
  19. package/package.json +1 -1
  20. package/plugin.json +1 -1
  21. package/scripts/ensure-branch.mjs +2 -8
  22. package/scripts/lib/arch-merge.mjs +11 -10
  23. package/scripts/lib/cmd-deisolate.mjs +1 -5
  24. package/scripts/lib/cmd-execution.mjs +3 -2
  25. package/scripts/lib/cmd-prototype.mjs +30 -13
  26. package/scripts/lib/cmd-publish.mjs +16 -4
  27. package/scripts/lib/execution-plan.mjs +78 -18
  28. package/scripts/lib/git-utils.mjs +90 -0
  29. package/skills/ce-brainstorm/SKILL.md +65 -2
  30. package/skills/ce-brainstorm/references/brainstorm-sections.md +53 -9
  31. package/skills/ce-brainstorm/references/business-processes.md +140 -0
  32. package/skills/ce-brainstorm/references/business-scenarios.md +122 -0
  33. package/skills/ce-brainstorm/references/evidence-chain-validation.md +114 -0
  34. package/skills/ce-brainstorm/references/phase0-routing.md +7 -1
  35. package/skills/ce-brainstorm/references/prd-mapping.md +36 -8
  36. package/skills/ce-brainstorm/references/synthesis-summary.md +21 -0
  37. package/skills/workflow-bootstrap/SKILL.md +29 -5
  38. package/skills/workflow-bootstrap/references/agents/codebase-recon-analyst.md +13 -3
  39. package/skills/workflow-bootstrap/references/b1-reconnaissance.md +18 -2
  40. package/skills/workflow-bootstrap/scripts/recon-probe.sh +79 -2
  41. package/skills/workflow-bootstrap/templates/claude-md-team-flow.md +60 -0
@@ -1,3 +1,3 @@
1
- # team-flow v0.39.1 | 阶段: {{state}} | 工作流: {{workflow}}
1
+ # team-flow v0.41.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. 24 skills + 15 agents with embedded TDD, SDD, code review, debugging, delta spec sync, and design-system-driven prototyping.",
12
- "version": "0.39.1",
12
+ "version": "0.41.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.39.1",
3
+ "version": "0.41.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). 24 skills + 15 agents, one install.",
5
5
  "source": "./",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-flow",
3
- "version": "0.39.1",
3
+ "version": "0.41.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.39.1"
8
+ "version": "0.41.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). 24 skills + 15 agents, one install.",
5
- "version": "0.39.1",
5
+ "version": "0.41.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.39.1"
9
+ "version": "0.41.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, and local HTML prototyping.",
15
- "version": "0.39.1",
15
+ "version": "0.41.0",
16
16
  "source": ".",
17
17
  "author": {
18
18
  "name": "LT",
package/AGENTS.md CHANGED
@@ -68,8 +68,8 @@ spec 驱动开发过程。8 态变更机:`exploring → specifying → bridgin
68
68
  - 与 workflow-start 分层:orchestrator 管"做什么、什么顺序"(产品级策略),workflow-start 管"怎么做"(变更级执行)
69
69
 
70
70
  ### 7. workflow-bootstrap(1 skill,既有项目接入,v0.15.0 脚本+子代理侦察)
71
- - 一次性"侦察 + 基线建立":代码库侦察 → 架构基线文档化 → 领域词汇提取 → 目录初始化 → 进入 workflow-orchestrator
72
- - **B1 侦察(v0.15.0)**:先跑确定性脚本 `scripts/recon-probe.sh`(可复现固定化采集)→ 并行派发 `codebase-recon-analyst` 子代理语义增强 主代理汇总写 baseline.md
71
+ - 一次性"侦察 + 基线建立":代码库侦察 → 架构基线文档化 → 领域词汇提取 → 目录初始化 → CLAUDE.md 初始化(B4.5,v0.41.0)→ 进入 workflow-orchestrator
72
+ - **B1 侦察(v0.15.0)**:先跑确定性脚本 `scripts/recon-probe.sh`(可复现固定化采集,含 Git 子仓库结构 v0.41.0)→ 并行派发 `codebase-recon-analyst` 子代理语义增强(7 维度含 git-structure)→ 主代理汇总写 baseline.md(维度闭合校验 v0.41.0)
73
73
  - 仅首次使用时执行;`docs/architecture/baseline.md` 已存在则跳过
74
74
 
75
75
  ### 8. session-handoff(1 skill,会话交接,v0.16.0 新增)
package/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ The format loosely follows Keep a Changelog.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ### Added(workflow-bootstrap CLAUDE.md 初始化 + Git 多子仓库识别,v0.41.0)
10
+
11
+ - **B4.5 CLAUDE.md 初始化**(参考 Claude Code /init):将项目基本信息(项目概况/开发命令/工作区结构/Git 结构)+ team-flow 产物结构索引写入工作区 CLAUDE.md;维护原则=索引级+结构级;已有 CLAUDE.md 追加模式(产物结构 + Git 管理规则章节),无则从 `templates/claude-md-team-flow.md` 新建
12
+ - **CLAUDE.md 标准模板**:`skills/workflow-bootstrap/templates/claude-md-team-flow.md`(新建),覆盖 /init 内容 + team-flow 产物结构表(代码强制 + 设计层面)
13
+ - **recon-probe.sh ⑧ Git 子仓库扫描**:识别嵌套 git 仓库 / submodule / .gitignore 忽略规则,JSON 新增 `git_structure` 字段(is_git_repo / sub_repos[{path,type,has_remote}] / submodules / gitignore_ignores_subrepos)
14
+ - **codebase-recon-analyst git-structure 维度**:侦察维度 6→7,识别子仓库用途(代码库/文档/工具)+ git 操作约束(提交/推送顺序、版本联动、隔离)
15
+ - **B1.3 维度闭合校验**:汇总前核对已派发维度 vs 已返回 handoff(status + deliverable 非空),缺失维度标 INCOMPLETE(advisory 不阻断,Success Output 警告)
16
+ - **AGENTS.md 同步**:workflow-bootstrap 流程描述补 B4.5 + git-structure + 闭合校验
17
+
9
18
  ## [0.39.0] - 2026-08-06
10
19
 
11
20
  ### Added(workflow-feedback 环境版本记录)
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.39.1 | 阶段: {{state}} | 工作流: {{workflow}}
11
+ # team-flow v0.41.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.39.1**。
10
+ 当前发布版本:**v0.41.0**。
11
11
 
12
12
  ---
13
13
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # team-flow
2
2
 
3
- > 当前版本:`v0.39.1`
3
+ > 当前版本:`v0.41.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.39.1`
129
+ - Current: `v0.41.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)
@@ -2,6 +2,7 @@
2
2
  <!-- 每条一行,按 severity 降序,≤150 行硬上限 -->
3
3
  | date | phase | domain | type | severity | summary | file |
4
4
  |------|-------|--------|------|----------|---------|------|
5
+ | 2026-08-07 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-07-no-summary.md |
5
6
  | 2026-08-06 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-06-no-summary.md |
6
7
  | 2026-08-05 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-05-no-summary.md |
7
8
  | 2026-08-04 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-04-no-summary.md |
@@ -0,0 +1,17 @@
1
+ ---
2
+ phase: cross-phase
3
+ domain: general
4
+ type: insight
5
+ severity: medium
6
+ date: 2026-08-07
7
+ source:
8
+ ---
9
+
10
+ ## 问题描述
11
+ (no summary)
12
+
13
+ ## 根因/模式
14
+ (待补充)
15
+
16
+ ## 预防措施/应用方式
17
+ (待补充)
@@ -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). 24 skills, one install.",
4
- "version": "0.39.1",
4
+ "version": "0.41.0",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bash
2
- # v0.39.1: auto-sync CLI version with plugin version
2
+ # v0.41.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.39.1"
8
+ PLUGIN_VERSION="0.41.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.39.1.
6
+ Current version: v0.41.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.39.1",
3
+ "version": "0.41.0",
4
4
  "description": "Unified plugin (24 skills + 15 agents) integrating team-flow, compound-engineering, architecture-design, prototype, design-system, workflow-orchestrator, workflow-bootstrap, e2e, session-handoff, workflow-feedback 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.39.1",
3
+ "version": "0.41.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). 24 skills + 15 agents, one install.",
5
5
  "author": {
6
6
  "name": "LT"
@@ -24,7 +24,8 @@
24
24
  // names) and are passed as array elements, never interpolated into a shell string;
25
25
  // branch names are additionally sanitized to git-legal characters before use.
26
26
  import { execFileSync } from 'node:child_process';
27
- import { resolve, basename, dirname, join } from 'node:path';
27
+ import { resolve, basename, join } from 'node:path';
28
+ import { detectWorkspaceRoot } from './lib/git-utils.mjs';
28
29
  import { readdirSync, existsSync, appendFileSync, readFileSync } from 'node:fs';
29
30
 
30
31
  const rawChangeDir = process.argv[2];
@@ -59,13 +60,6 @@ function sanitizeBranchName(raw) {
59
60
  return cleaned || 'change';
60
61
  }
61
62
 
62
- // 若 change-dir 形如 <root>/changes/<name>,返回 <root>;否则返回 null。
63
- function detectWorkspaceRoot(absChangeDir) {
64
- const parent = dirname(absChangeDir); // <root>/changes
65
- if (basename(parent) !== 'changes') return null;
66
- return dirname(parent); // <root>
67
- }
68
-
69
63
  // 枚举 root 下含 .git 的直接子目录(= 代码仓库),按目录名排序保证确定性。
70
64
  // .git 可能是目录(普通仓库)或文件(worktree/submodule 链接),existsSync 均覆盖。
71
65
  function listCodeRepos(root) {
@@ -18,13 +18,14 @@
18
18
  import {
19
19
  readFileSync, writeFileSync as fsWriteFileSync, existsSync, mkdirSync, readdirSync, rmdirSync, cpSync,
20
20
  } from 'node:fs';
21
- import { join, basename, dirname, resolve, sep } from 'node:path';
22
- import { execSync } from 'node:child_process';
21
+ import { join, basename, dirname, resolve } from 'node:path';
22
+ import { execFileSync } from 'node:child_process';
23
23
  import { pathToFileURL } from 'node:url';
24
24
  import {
25
25
  parseTableAfter, extractEndpoints, extractAggregates,
26
26
  extractTablesFromSql, extractTablesFromDatabaseMd, readFrontmatter,
27
27
  } from './arch-parse.mjs';
28
+ import { detectWorkspaceRoot, getGitRoot } from './git-utils.mjs';
28
29
 
29
30
  const MARKER_BEGIN = '<!-- arch:current-state:begin -->';
30
31
  const MARKER_END = '<!-- arch:current-state:end -->';
@@ -417,9 +418,9 @@ function gitCommit(projectRoot, globalArchDir, touchedFiles, changeName, dryRun)
417
418
  try {
418
419
  // 白名单:只 add 本次 touch 的文件(防卷走他人未提交工作)
419
420
  for (const f of touchedFiles) {
420
- execSync(`git add "${f}"`, { stdio: 'pipe' });
421
+ execFileSync('git', ['add', f], { cwd: projectRoot, stdio: 'pipe' });
421
422
  }
422
- execSync(`git commit -m "${commitMsg}"`, { stdio: 'pipe' });
423
+ execFileSync('git', ['commit', '-m', commitMsg], { cwd: projectRoot, stdio: 'pipe' });
423
424
  return { committed: true, message: commitMsg };
424
425
  } catch (e) {
425
426
  return { committed: false, error: e.message };
@@ -427,9 +428,11 @@ function gitCommit(projectRoot, globalArchDir, touchedFiles, changeName, dryRun)
427
428
  }
428
429
 
429
430
  /** 检测 docs/architecture/ 下非本次 touch 的脏文件(团队协作安全底线)。 */
430
- function detectUntouchedDirtyFiles(globalArchDir, touchedFiles) {
431
+ function detectUntouchedDirtyFiles(projectRoot, globalArchDir, touchedFiles) {
431
432
  try {
432
- const status = execSync(`git status --porcelain -- ${globalArchDir}`, { stdio: 'pipe' }).toString();
433
+ const status = execFileSync('git', ['status', '--porcelain', '--', globalArchDir], {
434
+ cwd: projectRoot, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'],
435
+ });
433
436
  const dirty = status.split('\n').filter(Boolean)
434
437
  .map(line => line.replace(/^\S+\s+/, '').trim())
435
438
  .filter(p => p && !touchedFiles.includes(resolve(p)) && !touchedFiles.includes(p));
@@ -461,9 +464,7 @@ export function run(args = {}) {
461
464
 
462
465
  let projectRoot = args.projectRoot;
463
466
  if (!projectRoot) {
464
- const abs = resolve(changeDir);
465
- const changesIdx = abs.lastIndexOf(sep + 'changes' + sep);
466
- projectRoot = changesIdx > 0 ? abs.slice(0, changesIdx) : process.cwd();
467
+ projectRoot = detectWorkspaceRoot(changeDir) || getGitRoot(changeDir);
467
468
  }
468
469
 
469
470
  const changeName = basename(changeDir.replace(/\/$/, ''));
@@ -530,7 +531,7 @@ export function run(args = {}) {
530
531
  join(globalArchDir, 'INDEX.md'),
531
532
  ...(archiveResult.files || []), // v0.36.3:changelog/ 复制文件入白名单
532
533
  ].filter(p => existsSync(p));
533
- const dirty = detectUntouchedDirtyFiles(globalArchDir, touchedFiles);
534
+ const dirty = detectUntouchedDirtyFiles(projectRoot, globalArchDir, touchedFiles);
534
535
  if (dirty.length > 0) {
535
536
  console.warn(` [WARN] docs/architecture/ 存在非本次 touch 的脏文件(${dirty.length} 个):${dirty.slice(0, 5).join(', ')} — 白名单 git add 不卷走它们,但请确认是否他人未提交工作`);
536
537
  }
@@ -18,6 +18,7 @@ import { execFileSync } from 'node:child_process';
18
18
  import { existsSync, readdirSync, rmSync } from 'node:fs';
19
19
  import { basename, dirname, join, resolve } from 'node:path';
20
20
  import { parseArgs } from 'node:util';
21
+ import { detectWorkspaceRoot } from './git-utils.mjs';
21
22
 
22
23
  export async function run(args) {
23
24
  const { positionals, values } = parseArgs({
@@ -70,11 +71,6 @@ export async function run(args) {
70
71
  }
71
72
  }
72
73
 
73
- function detectWorkspaceRoot(absChangeDir) {
74
- const parent = dirname(absChangeDir);
75
- if (basename(parent) !== 'changes') return null;
76
- return dirname(parent);
77
- }
78
74
 
79
75
  // Case A: <root>/.worktrees/<change>/<repo>/
80
76
  function detectCaseA(root, changeName) {
@@ -28,6 +28,7 @@ export async function run(args) {
28
28
  'tests-failed': { type: 'string' },
29
29
  json: { type: 'boolean', default: false },
30
30
  help: { type: 'boolean', default: false },
31
+ repo: { type: 'string' },
31
32
  },
32
33
  allowPositionals: true,
33
34
  });
@@ -144,7 +145,7 @@ function recordAndPrintReview(changeDir, values) {
144
145
  head: values.head,
145
146
  report: values.report,
146
147
  tests: parseTestsStats(values),
147
- });
148
+ }, values.repo);
148
149
  print(values.json, { ok: true, wave: values.wave[0], receipt }, `Review for ${values.wave[0]} recorded: ${receipt.status}.`);
149
150
  }
150
151
 
@@ -237,6 +238,6 @@ function printHelp() {
237
238
  tf execution plan <dir> --mode <mode> --confirm --reason <text> --wave <id>:<strategy>:<task,...>[:<depends-on,...>] [--acknowledge-recommendation]
238
239
  tf execution show <dir> [--json]
239
240
  tf execution revise <dir> --mode sdd --confirm --reason <text> --wave <id>:<strategy>:<task,...>[:<depends-on,...>] [--acknowledge-recommendation]
240
- tf execution review <dir> --wave <id> --base <sha> --head <sha> --report <path> --verdict pass|fail [--tests-total N --tests-passed N --tests-failed N]
241
+ tf execution review <dir> --wave <id> --base <sha> --head <sha> --report <path> --verdict pass|fail [--repo <path>] [--tests-total N --tests-passed N --tests-failed N]
241
242
  tf execution refresh-hash <dir> [--json] # refresh artifacts/contract hash without bumping revision`);
242
243
  }
@@ -20,6 +20,7 @@
20
20
  import { execFileSync } from 'node:child_process';
21
21
  import { existsSync, readdirSync, rmSync, appendFileSync, readFileSync } from 'node:fs';
22
22
  import { join, resolve, basename } from 'node:path';
23
+ import { detectWorkspaceRoot } from './git-utils.mjs';
23
24
 
24
25
  const PROTECTED = ['main', 'master'];
25
26
 
@@ -39,12 +40,20 @@ function normalizeBranchName(raw) {
39
40
  }
40
41
 
41
42
  /** 定位 workspace root(cwd 在主仓库内)与原型仓库路径。 */
42
- function resolveLayout() {
43
+ function resolveLayout(projectRootArg) {
43
44
  let workspaceRoot;
44
- try {
45
- workspaceRoot = git(process.cwd(), 'rev-parse', '--show-toplevel');
46
- } catch {
47
- throw new Error('无法定位 workspace root:cwd 不在 git 仓库内?');
45
+ if (projectRootArg) {
46
+ workspaceRoot = resolve(projectRootArg);
47
+ } else {
48
+ // 优先从 changes/ 布局推断(worktree cwd 可能不是主仓库)
49
+ workspaceRoot = detectWorkspaceRoot(process.cwd());
50
+ if (!workspaceRoot) {
51
+ try {
52
+ workspaceRoot = git(process.cwd(), 'rev-parse', '--show-toplevel');
53
+ } catch {
54
+ throw new Error('无法定位 workspace root:cwd 不在 git 仓库内?请使用 --project-root 指定');
55
+ }
56
+ }
48
57
  }
49
58
  const protoRepo = join(workspaceRoot, 'prototype');
50
59
  if (!existsSync(join(protoRepo, '.git'))) {
@@ -84,8 +93,8 @@ function localBranchExists(protoRepo, branch) {
84
93
  }
85
94
 
86
95
  /** 子命令 branch:创建/复用原型版本 worktree。 */
87
- function cmdBranch(branchName) {
88
- const { workspaceRoot, protoRepo } = resolveLayout();
96
+ function cmdBranch(branchName, projectRootArg) {
97
+ const { workspaceRoot, protoRepo } = resolveLayout(projectRootArg);
89
98
  const wtPath = join(workspaceRoot, '.worktrees', branchName, basename(protoRepo));
90
99
 
91
100
  // 幂等:worktree 已存在 → 复用
@@ -118,8 +127,8 @@ function cmdBranch(branchName) {
118
127
  }
119
128
 
120
129
  /** 子命令 deisolate:版本收尾 merge 回主干 + 清理 worktree。 */
121
- function cmdDeisolate(branchName, opts) {
122
- const { workspaceRoot, protoRepo } = resolveLayout();
130
+ function cmdDeisolate(branchName, opts, projectRootArg) {
131
+ const { workspaceRoot, protoRepo } = resolveLayout(projectRootArg);
123
132
  const wtPath = join(workspaceRoot, '.worktrees', branchName, basename(protoRepo));
124
133
  const result = { branch: branchName, worktreePath: wtPath };
125
134
 
@@ -181,8 +190,9 @@ function usage() {
181
190
  console.log(`tf prototype — 原型仓库版本 worktree 隔离(v0.37.0 §68.4)
182
191
 
183
192
  用法:
184
- tf prototype branch <prd-vN> # 创建/复用原型版本 worktree(隔离 + 团队拉取)
185
- tf prototype deisolate <prd-vN> [--merge] [--clean]
193
+ tf prototype branch <prd-vN> [--project-root <path>]
194
+ # 创建/复用原型版本 worktree(隔离 + 团队拉取)
195
+ tf prototype deisolate <prd-vN> [--merge] [--clean] [--project-root <path>]
186
196
  # 版本收尾:merge 回主干 + 清理 worktree
187
197
 
188
198
  示例:
@@ -210,13 +220,20 @@ export async function run(args = []) {
210
220
  try { branchName = normalizeBranchName(rawVersion); }
211
221
  catch (e) { console.error(e.message); process.exit(2); }
212
222
 
223
+ // Extract --project-root from remaining args
224
+ let projectRootArg;
225
+ const projectRootIdx = rest.indexOf('--project-root');
226
+ if (projectRootIdx !== -1 && rest[projectRootIdx + 1]) {
227
+ projectRootArg = rest[projectRootIdx + 1];
228
+ }
229
+
213
230
  try {
214
231
  if (sub === 'branch') {
215
- return cmdBranch(branchName);
232
+ return cmdBranch(branchName, projectRootArg);
216
233
  }
217
234
  if (sub === 'deisolate') {
218
235
  const opts = { merge: rest.includes('--merge'), clean: rest.includes('--clean') };
219
- return cmdDeisolate(branchName, opts);
236
+ return cmdDeisolate(branchName, opts, projectRootArg);
220
237
  }
221
238
  console.error(`未知子命令:${sub}(可用:branch / deisolate)`);
222
239
  process.exit(2);
@@ -19,16 +19,18 @@
19
19
  import { execFileSync } from 'node:child_process';
20
20
  import { existsSync, mkdirSync, readdirSync, rmdirSync } from 'node:fs';
21
21
  import { join, resolve, isAbsolute } from 'node:path';
22
+ import { detectWorkspaceRoot } from './git-utils.mjs';
22
23
 
23
24
  const LOCK_PATH = '.publish.lock';
24
25
 
25
26
  /** 解析 CLI 参数。 */
26
27
  function parseArgv(argv) {
27
- const parsed = { targets: [], push: false, dryRun: false, changeDir: null };
28
+ const parsed = { targets: [], push: false, dryRun: false, changeDir: null, projectRoot: null };
28
29
  for (let i = 0; i < argv.length; i++) {
29
30
  const a = argv[i];
30
31
  if (a === '--push') parsed.push = true;
31
32
  else if (a === '--dry-run') parsed.dryRun = true;
33
+ else if (a === '--project-root') { parsed.projectRoot = argv[++i]; }
32
34
  else if (a === '--prd') parsed.targets.push('prd');
33
35
  else if (a === '--arch') parsed.targets.push('arch');
34
36
  else if (a === '--changes') {
@@ -179,17 +181,27 @@ export async function run(args = []) {
179
181
  if (parsed.help) {
180
182
  console.log(`tf publish — 阶段产物白名单提交 + 可选推送(v0.37.0 §68.3)
181
183
 
182
- 用法:tf publish <target> [--push] [--dry-run]
184
+ 用法:tf publish <target> [--push] [--dry-run] [--project-root <path>]
183
185
  --prd 提交 PRD + orchestrator.yaml + registry.yaml + 主仓库 prototype/
184
186
  --arch 提交 docs/architecture/(迭代快照)
185
187
  --changes 提交整个 changes/(或 --changes <change-dir> 指定单个 change)
186
188
  --all 提交全部上述
187
189
  --push 同时推送到远程当前分支(默认只提交不推送)
188
- --dry-run 只打印将执行的 git 动作,不落盘不 commit`);
190
+ --dry-run 只打印将执行的 git 动作,不落盘不 commit
191
+ --project-root <path>
192
+ 显式指定主仓库根目录(多仓库 worktree 场景下自动检测失败时使用)`);
189
193
  return;
190
194
  }
191
195
 
192
- const projectRoot = git(process.cwd(), 'rev-parse', '--show-toplevel');
196
+ let projectRoot;
197
+ if (parsed.projectRoot) {
198
+ projectRoot = resolve(parsed.projectRoot);
199
+ } else {
200
+ projectRoot = detectWorkspaceRoot(process.cwd());
201
+ if (!projectRoot) {
202
+ projectRoot = git(process.cwd(), 'rev-parse', '--show-toplevel');
203
+ }
204
+ }
193
205
  const whitelist = collectWhitelist(projectRoot, parsed.targets, parsed.changeDir);
194
206
 
195
207
  if (whitelist.length === 0) {