@xulthekl/team-flow 0.47.0 → 0.49.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 (60) 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 +54 -0
  10. package/GEMINI.md +1 -1
  11. package/INSTALL.md +2 -2
  12. package/README.md +3 -3
  13. package/docs/README_en.md +1 -1
  14. package/docs/solutions/INDEX.md +0 -14
  15. package/gemini-extension.json +1 -1
  16. package/hooks/session-start +2 -2
  17. package/llms.txt +1 -1
  18. package/package.json +1 -1
  19. package/plugin.json +1 -1
  20. package/scripts/ensure-branch.mjs +94 -4
  21. package/scripts/guard/checks/compound-captured.mjs +6 -3
  22. package/scripts/lib/cmd-repo-layout.mjs +51 -0
  23. package/scripts/lib/cmd-runtime.mjs +1 -0
  24. package/scripts/lib/config-loader.mjs +17 -1
  25. package/scripts/lib/conventions-generator.mjs +61 -2
  26. package/scripts/lib/execution-plan.mjs +82 -32
  27. package/scripts/lib/execution-recommendation.mjs +4 -18
  28. package/scripts/lib/glaf4-delegation.mjs +64 -26
  29. package/scripts/lib/hash.mjs +41 -2
  30. package/scripts/lib/prototype-sync.mjs +2 -1
  31. package/scripts/lib/sdd-overlay.mjs +3 -2
  32. package/scripts/lib/solutions-capture.mjs +2 -1
  33. package/scripts/lib/solutions-index-gen.mjs +2 -1
  34. package/scripts/lib/solutions-inject.mjs +2 -1
  35. package/scripts/lib/solutions-promote.mjs +90 -12
  36. package/scripts/lib/test-record.mjs +67 -21
  37. package/scripts/team-flow.mjs +3 -0
  38. package/skills/build-executor/SKILL.md +8 -2
  39. package/skills/ce-compound/references/promotion-rules.md +1 -1
  40. package/skills/ce-compound/references/schema.yaml +10 -1
  41. package/skills/contract-builder/references/glaf4-delegation.md +11 -7
  42. package/skills/release-archivist/SKILL.md +7 -8
  43. package/skills/release-archivist/references/closing-procedures.md +7 -2
  44. package/skills/workflow-orchestrator/SKILL.md +7 -0
  45. package/skills/workflow-start/SKILL.md +12 -1
  46. package/templates/learnings.md +51 -0
  47. package/docs/solutions/cross-phase/2026-07-28-no-summary.md +0 -17
  48. package/docs/solutions/cross-phase/2026-07-29-no-summary.md +0 -17
  49. package/docs/solutions/cross-phase/2026-07-30-no-summary.md +0 -17
  50. package/docs/solutions/cross-phase/2026-07-31-no-summary.md +0 -17
  51. package/docs/solutions/cross-phase/2026-08-01-no-summary.md +0 -17
  52. package/docs/solutions/cross-phase/2026-08-03-no-summary.md +0 -17
  53. package/docs/solutions/cross-phase/2026-08-04-no-summary.md +0 -17
  54. package/docs/solutions/cross-phase/2026-08-05-no-summary.md +0 -17
  55. package/docs/solutions/cross-phase/2026-08-06-no-summary.md +0 -17
  56. package/docs/solutions/cross-phase/2026-08-07-no-summary.md +0 -17
  57. package/docs/solutions/cross-phase/2026-08-17-no-summary.md +0 -17
  58. package/docs/solutions/cross-phase/2026-08-18-no-summary.md +0 -17
  59. package/docs/solutions/cross-phase/2026-08-19-no-summary.md +0 -17
  60. package/docs/solutions/cross-phase/2026-08-21-no-summary.md +0 -17
@@ -1,3 +1,3 @@
1
- # team-flow v0.47.0 | 阶段: {{state}} | 工作流: {{workflow}}
1
+ # team-flow v0.49.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.49.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.49.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.49.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.49.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.49.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.49.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.49.0",
16
16
  "source": ".",
17
17
  "author": {
18
18
  "name": "LT",
package/AGENTS.md CHANGED
@@ -112,8 +112,8 @@ docs/
112
112
  ├── INDEX.md # L1 轻量索引(≤150行,每条一行摘要+标签)
113
113
  ├── requirement/ plan/ architecture/ prototype/ spec/ build/ review/ cross-phase/ # L2 分阶段目录(v0.36.0 加 architecture)
114
114
  └── <file>.md # L3 经验文件(YAML frontmatter: phase/domain/type/severity)
115
- changes/<name>/ 变更脚手架(S4 创建):.team-flow.yaml(变更级状态文件)/ change-brief.md(产品级交接物,含 upstream_arch_ref)/ architecture/(变更级三件套 + sql/)
116
- specs/<cap>/ 每变更设计/任务/契约:spec.md / design.md / tasks.md / execution-contract.md / learnings.md(v0.9 architecture/ 三件套已迁至 changes/<name>/architecture/)
115
+ changes/<name>/ 变更脚手架(S4 创建):.team-flow.yaml(变更级状态文件)/ change-brief.md(产品级交接物,含 upstream_arch_ref)/ proposal.md / design.md / tasks.md / execution-contract.md / learnings.md(变更级经验台账)/ architecture/(变更级三件套 + sql/)
116
+ specs/<cap>/ 每变更规格:spec.md(v0.49.0 §83.3.5:learnings.md change 根,不在此目录)
117
117
  STRATEGY.md CONCEPTS.md 产品策略(BA) / 领域词汇
118
118
  ```
119
119
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,60 @@ 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.49.0] - 2026-09-09
8
+
9
+ ### Fixed(execution plan 冻结边界与复利链路修复)
10
+
11
+ 设计来源:`docs/architecture-api-db-design-enhancement-v0.21.md` §83(2026-09-09,fytx-gateway-parent 4 条 workflow-feedback:093305 / 093306 / 093307 / 093308)
12
+
13
+ **根因簇 A — execution plan 冻结边界错配**(3 个落点,构成闭合不可用回路)
14
+
15
+ - **A1 hash 范围修正**:`normalizeCheckboxes` 归一化 tasks.md 勾选状态后再入 `artifacts_hash` / `computeTaskHash` —— 勾选是执行进度而非规划内容。修复「勾选 → plan 过期 → recordReview 抛错 → build-executor 无法勾选 → closing 死锁」(`hash.mjs`、`sdd-overlay.mjs`)
16
+ - **A2 receipt 判据改 wave 定义指纹**:`recordReview` 写 `wave_fingerprint`(id/strategy/tasks/depends_on),`readCurrentReview` 以其为判据,`plan_hash`/`plan_revision` 降级为审计信息(存量 receipt 回退旧判据)。修复 revise / refresh-hash 后历史 receipt 全部失效且无补录路径;`describeWaves` 新增 `stale_receipt` 诊断(`execution-plan.mjs`)
17
+ - **A3 refresh-hash 同步 recommendation_receipt**:同步 receipt 的 artifacts_hash/contract_hash 并重算 receipt.hash —— 修复 refresh-hash 在其目标场景下自失败(`execution-plan.mjs`);`stableJson`/`hashObject` 抽到 `hash.mjs` 共享
18
+
19
+ **根因簇 B — 复利链路断裂**(6 个子项)
20
+
21
+ - **B1 消费通道**:build-executor Required Inputs 增加 `tf solutions inject --phase cross-phase`(标注为经验提示而非约束)
22
+ - **B2 路径统一**:5 处文档从 `specs/<cap>/learnings.md` 更正为 change 根 `learnings.md`
23
+ - **B3 契约分层**:`schema.yaml` 声明两条产出通道(ce-compound 手工 / promote 自动晋升)与共同消费面 INDEX.md
24
+ - **B4 静默丢弃可见化**:promote 输出「晋升 / 确认 / 跳过」汇总 + 逐条跳过原因
25
+ - **B5 promote 实现修复**:产出文件单 frontmatter 块(原双块,并补回 `## ` 标题前缀);重复命中真正落盘(INDEX severity 升级 + 条目 `confirmed` 计数)
26
+ - **B6 通道错配修正**:`compound-captured` guard 提示不再指向 `tf solutions capture`(它写全局目录、不创建 learnings.md);release-archivist 明确 learnings.md 写入方;新增 `templates/learnings.md`
27
+
28
+ **根因簇 C — 解析器不对称**
29
+
30
+ - **pytest junit XML 支持**:抽出通用 `parseJunitXml`(maven-surefire 与 pytest 共用);`parsePytest` 增加 XML 分支;`detectRunner` XML 优先嗅探;错误信息附输入形态指引(`test-record.mjs`)
31
+
32
+ **协议层**
33
+
34
+ - build-executor wave 完成协议增加「回写 tasks.md 勾选」;workflow-start 主动串行编排把勾选作为进下一波前置;Artifact Ownership 澄清 tasks.md 勾选状态归属
35
+ - `glaf4-delegation.md` §8 closing 时序协议同步更新
36
+
37
+ **横展修复**(P3 审查发现的既有缺陷)
38
+
39
+ - **CLI 入口守卫**:5 处 `process.argv[1]?.includes(...)` 改为 `import.meta.url === pathToFileURL(process.argv[1]).href` —— 原写法使测试文件(如 `solutions-capture.test.mjs`)在 import 时触发 CLI 执行,污染真实 `docs/solutions/`(`solutions-capture/inject/index-gen/promote.mjs`、`prototype-sync.mjs`)
40
+ - **测试隔离**:`ensure-branch.test.mjs` 的 `origin.git` 从固定 `tmpdir()` 路径改为独立随机目录 —— 原写法跨运行残留导致 push 被拒、before 钩子失败、`npm test` exit 1
41
+ - 清理 `docs/solutions/` 中 14 个历史测试污染条目
42
+
43
+ ### Tests
44
+
45
+ - 新增 18 个用例(A1 勾选归一化、A2 指纹判据与 stale 诊断、A3 refresh-hash 同步、pytest XML、promote 可见化与落盘);`npm test` 742/742,`npm run test:e2e` 68/68
46
+
47
+ ## [0.48.0] - 2026-08-21
48
+
49
+ ### Added(多仓库场景支持,v0.48.0)
50
+
51
+ 设计来源:`docs/plan/multi-repo-support-design.md` v1.0(2026-08-21,fytx-message 4 feedback:cli-command-1/2 + sop-flow-1/2)
52
+
53
+ - **repo_layout 机制**(P0):`detectRepoLayout` 判定 single/monorepo/multi-repo + 代码仓库清单;`tf repo-layout detect <root>` CLI 写 `repo_layout` 段到 `team-flow.config.json`;config-loader DEFAULTS 固化
54
+ - **detect 修复**(P1,cli-command-1):change 目录→项目根解析(detectWorkspaceRoot/getGitRoot);repos 清单聚合判定 `is_glaf4_java`(任一仓库 Java → 项目级 true);`--target-repo` 精确探测;config 主副本写项目根(不再写 change 目录)
55
+ - **review 修复**(P2,cli-command-2):overlay 目录自动创建(修 ENOENT);`--repo <代码仓库>` 提供 base/head git 校验上下文;multi-repo 下 change 目录无 git 不再报错(--repo 场景)
56
+ - **isolate 修复**(P2,sop-flow-2):`checkSharedBranch` 检测 origin tracking + ahead/behind(有 upstream 即共享);共享分支建 worktree 而非就地实施;`checkUncommitted` 报告未提交变更归属
57
+ - **流程接入**(P3):workflow-start DP-0 + orchestrator S1 项目模式确认(识别存量结构,写 repo_layout config)
58
+ - **三评审闭环**:P3 code-reviewer(2 Important + 8 Minor)+ P4 plugin-validator(7 minor)+ skill-reviewer(5 minor)全修
59
+ - 723/723 测试通过
60
+
7
61
  ## [0.47.0] - 2026-08-21
8
62
 
9
63
  ### 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.49.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.49.0**。
11
11
 
12
12
  ---
13
13
 
@@ -761,7 +761,7 @@ tf execution review changes/my-change --wave foundation --base <sha> --head <sha
761
761
  report 本身必须为普通、非空、非符号链接文件。
762
762
 
763
763
  每一个 wave 均须有当前 `pass` review receipt,才可启动依赖 wave 或进入 closing;
764
- 修订计划会废止旧 receipt。#47 所提出的恢复、切换与手动保存 slash command 尚未实现,
764
+ receipt 绑定该 wave 的定义(v0.49.0 起):wave 定义未变时,修订计划或刷新 hash 不会废止它。#47 所提出的恢复、切换与手动保存 slash command 尚未实现,
765
765
  不能假定有 `/tf:*` 命令。
766
766
 
767
767
  Delta spec 的规范路径是 `specs/<capability>/spec.md`。扁平的 `specs/<capability>.md` 和根级 `specs/spec.md` 都不会被当作合法规范静默通过。
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # team-flow
2
2
 
3
- > 当前版本:`v0.47.0`
3
+ > 当前版本:`v0.49.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
 
@@ -66,7 +66,7 @@ prototype/ 全局原型(UI 契约真相源)
66
66
  docs/
67
67
  ├── architecture/ 全局架构三层(v0.36.0):ARCHITECTURE.md / PHYSICAL-MODEL.md / DATABASE.md / API-INDEX.md / INDEX.md / domains/<bc>.md / iterations/vN/(产品级快照)/ baseline.md
68
68
  └── solutions/ 复利经验库(三层索引:INDEX.md → 分阶段目录 → 经验文件)
69
- specs/<cap>/ 每变更设计/任务/契约 + learnings.md
69
+ specs/<cap>/ 每变更规格:spec.md(learnings.md 归 change 根目录)
70
70
  STRATEGY.md CONCEPTS.md 策略 / 领域词汇
71
71
  ```
72
72
 
@@ -155,7 +155,7 @@ tf execution review changes/my-change --wave foundation --base <sha> --head <sha
155
155
  report 本身必须为普通、非空、非符号链接文件。
156
156
 
157
157
  每一个 wave 均须有当前 `pass` review receipt,才可启动依赖 wave 或进入 closing;
158
- 修订计划会废止旧 receipt。#47 所提出的恢复、切换与手动保存 slash command 尚未实现,
158
+ receipt 绑定该 wave 的定义(v0.49.0 起):wave 定义未变时,修订计划或刷新 hash 不会废止它。#47 所提出的恢复、切换与手动保存 slash command 尚未实现,
159
159
  不能假定有 `/tf:*` 命令。
160
160
 
161
161
  ## OpenAI Codex CLI 安装与升级
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.49.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,17 +2,3 @@
2
2
  <!-- 每条一行,按 severity 降序,≤150 行硬上限 -->
3
3
  | date | phase | domain | type | severity | summary | file |
4
4
  |------|-------|--------|------|----------|---------|------|
5
- | 2026-08-21 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-21-no-summary.md |
6
- | 2026-08-19 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-19-no-summary.md |
7
- | 2026-08-18 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-18-no-summary.md |
8
- | 2026-08-17 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-17-no-summary.md |
9
- | 2026-08-07 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-07-no-summary.md |
10
- | 2026-08-06 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-06-no-summary.md |
11
- | 2026-08-05 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-05-no-summary.md |
12
- | 2026-08-04 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-04-no-summary.md |
13
- | 2026-08-03 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-03-no-summary.md |
14
- | 2026-08-01 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-01-no-summary.md |
15
- | 2026-07-31 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-07-31-no-summary.md |
16
- | 2026-07-30 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-07-30-no-summary.md |
17
- | 2026-07-29 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-07-29-no-summary.md |
18
- | 2026-07-28 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-07-28-no-summary.md |
@@ -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.49.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.49.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.49.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.49.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.49.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.49.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);
@@ -61,10 +61,13 @@ export function checkCompoundCaptured(changeDir) {
61
61
  }
62
62
 
63
63
  // 3. 未捕获且未豁免 → fail
64
+ // v0.49.0 §83.3.5:修正通道错配——原提示指向 `tf solutions capture`,但该命令写的是
65
+ // 全局 docs/solutions/,不会创建 learnings.md(用户照做后 guard 仍 FAIL)。
64
66
  failures.push(
65
- 'Compound capture missing: no learnings.md found in change directory. ' +
66
- 'Run `tf solutions capture --phase review --domain <d> --type insight --severity medium --summary "..."` ' +
67
- 'to document session learnings, or `tf state set compound_skipped true` to explicitly skip.'
67
+ "Compound capture missing: no learnings.md found in change directory. "
68
+ + "Write this change's session learnings to <change-dir>/learnings.md (format: templates/learnings.md) during closing, "
69
+ + 'or `tf state set compound_skipped true` to explicitly skip. '
70
+ + 'Note: `tf solutions capture` writes to global docs/solutions/, not to learnings.md.'
68
71
  );
69
72
  return { pass: false, failures };
70
73
  }
@@ -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
+ }
@@ -15,6 +15,7 @@ const ASSETS = new Set([
15
15
  'skills/build-executor/task-reviewer-prompt.md',
16
16
  'templates/design.md',
17
17
  'templates/execution-contract.md',
18
+ 'templates/learnings.md',
18
19
  'templates/proposal.md',
19
20
  'templates/spec.md',
20
21
  'templates/tasks.md',
@@ -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');