@xulthekl/team-flow 0.63.0 → 0.64.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 (53) 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/.github/workflows/ci.yml +2 -0
  9. package/CHANGELOG.md +28 -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/state-machine.md +4 -1
  15. package/docs/team-flow /344/275/277/347/224/250/350/257/264/346/230/216/357/274/210/347/240/224/345/217/221/345/233/242/351/230/237/347/211/210/357/274/211.md" +2 -2
  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/guard/checks/_fs-utils.mjs +18 -0
  22. package/scripts/guard/checks/arch-design-light.mjs +39 -0
  23. package/scripts/guard/checks/arch-merged-light.mjs +67 -0
  24. package/scripts/guard/checks/arch-snapshot-light.mjs +30 -0
  25. package/scripts/guard/checks/artifacts-planned.mjs +38 -0
  26. package/scripts/guard/checks/compound-writeback-light.mjs +45 -0
  27. package/scripts/guard/checks/cross-change-consistency-light.mjs +75 -0
  28. package/scripts/guard/checks/direct-short-path.mjs +52 -0
  29. package/scripts/guard/checks/direct-test-result.mjs +30 -0
  30. package/scripts/guard/checks/execution-plan-ready.mjs +7 -1
  31. package/scripts/guard/checks/execution-reviews-passed-light.mjs +28 -0
  32. package/scripts/guard/checks/lightweight-completion-evidence.mjs +27 -0
  33. package/scripts/guard/checks/specs-merged.mjs +25 -1
  34. package/scripts/guard/checks/test-matrix-complete.mjs +27 -1
  35. package/scripts/guard/checks/test-matrix-ready.mjs +28 -1
  36. package/scripts/guard/checks/test-merged-light.mjs +36 -0
  37. package/scripts/guard/guard.mjs +102 -12
  38. package/scripts/infer-workflow.mjs +35 -4
  39. package/scripts/lib/arch-merge.mjs +20 -4
  40. package/scripts/lib/cmd-execution.mjs +44 -1
  41. package/scripts/lib/cmd-state.mjs +94 -4
  42. package/scripts/lib/execution-plan.mjs +3 -1
  43. package/scripts/lib/state-loader.mjs +43 -0
  44. package/scripts/lib/surface-scan.mjs +156 -0
  45. package/scripts/lib/test-merge.mjs +10 -2
  46. package/scripts/team-flow.mjs +3 -3
  47. package/skills/clean-code/SKILL.md +1 -1
  48. package/skills/jarvis/SKILL.md +2 -0
  49. package/skills/release-archivist/SKILL.md +39 -13
  50. package/skills/session-handoff/SKILL.md +1 -0
  51. package/skills/test-strategy/SKILL.md +1 -1
  52. package/skills/workflow-start/SKILL.md +63 -5
  53. package/skills/workflow-start/references/routing-rules.md +4 -4
@@ -1,3 +1,3 @@
1
- # team-flow v0.63.0 | 阶段: {{state}} | 工作流: {{workflow}}
1
+ # team-flow v0.64.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. 28 skills + 17 agents with embedded TDD, SDD, code review, debugging, delta spec sync, and design-system-driven prototyping.",
12
- "version": "0.63.0",
12
+ "version": "0.64.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.63.0",
3
+ "version": "0.64.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) + design-system (design tokens + component contract + AI primer + showcase) + test-strategy (test strategy design) + project-initialize (new service onboarding) + jarvis (team-flow decision agent, opt-in). 28 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.63.0",
3
+ "version": "0.64.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.63.0"
8
+ "version": "0.64.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) + jarvis (team-flow decision agent, opt-in). 28 skills + 17 agents, one install.",
5
- "version": "0.63.0",
5
+ "version": "0.64.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.63.0"
9
+ "version": "0.64.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.63.0",
15
+ "version": "0.64.0",
16
16
  "source": ".",
17
17
  "author": {
18
18
  "name": "LT",
@@ -24,6 +24,7 @@ jobs:
24
24
  - run: npm ci
25
25
  - run: npm run build
26
26
  - run: npm test
27
+ - run: npm run test:e2e
27
28
  - name: Check version consistency
28
29
  run: node scripts/check-version-consistency.mjs
29
30
  - name: CLI smoke
@@ -83,6 +84,7 @@ jobs:
83
84
  - run: npm ci
84
85
  - run: npm run build
85
86
  - run: npm test
87
+ - run: npm run test:e2e
86
88
  - name: Check version consistency
87
89
  run: node scripts/check-version-consistency.mjs
88
90
  - name: Token efficiency lint (warning only)
package/CHANGELOG.md CHANGED
@@ -4,6 +4,34 @@ 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.64.0] - 2026-09-24
8
+
9
+ ### Added(spec-superflow 2.0 同步:双前门 + 轻路径 + 轻量全局态闸门;设计 = docs/plan/spec-superflow-2.0-implementation-plan.md v2.1,P1.5 两轮独立评审 13+13 组全闭合)
10
+
11
+ **双前门(`workflow_variant` 与 `workflow` 正交)**
12
+ - direct(→`quick`):零文档零契约,`exploring→approved-for-build→executing→closing` 捷径;planned(→`full`):proposal+tasks 两份 + `tf execution plan --derive`(tasks.md 派生单 wave,免 recommend/receipt/DP-4)+ 一次最终审查。
13
+ - legacy/null 走既有全量流程零破坏(null≡legacy + TTY 单次提示 / headless 不挂起);`workflow` 枚举扩为五值(+`quick`/`lightweight`)。
14
+ - 新子命令:`tf state upgrade <dir> <planned|full>`(升档唯一机械入口:方向向上 + `variant_source=upgrade` + 回退 approved-for-build + 重算 hash;**降档拒绝**)。
15
+ - 新 CLI 参数:`tf execution plan --derive`、`tf arch-merge --light`、`tf test-merge --light`(changelog 归因锚 `change:<name>`)、guard `--workflow-variant`/`--planned-arch`。
16
+
17
+ **11 个新 guard 维度(CHECK_RUNNERS 20→31)+ 共享扫描层**
18
+ - `surface-scan.mjs`:三源合并(committed diff + 工作区 + untracked)+ `base_sha` 基线(缺省 origin merge-base,再缺 fail-closed)+ 架构 surface 路径模式表 + `.team-flow/aggregate-dirs.txt` 聚合清单(**缺失 FAIL,显式空文件 = 确认无聚合**)+ `.team-flow/scan-ignore` 排除。
19
+ - direct 侧:`direct-short-path`(碰 API/DB/聚合 → FAIL+升档指引,G1)、`direct-test-result`/`lightweight-completion-evidence`(只读 `tf test record` 程序化证据,guard 不现场跑测试)。
20
+ - planned 侧 closing「轻回写四灯」:`arch-merged-light`(同 sink:最小 architecture.md/api.md/database.md 持久源 + 全局台账 `change:<name>` 归因)、`compound-writeback-light`(禁 `compound_skipped` 自清)、`test-merged-light`、`cross-change-consistency-light`(**确定性扫描 runner**,语义级仍由 checker agent 兜底)+ `execution-reviews-passed-light`(≥5 行内容契约)+ `artifacts-planned`(proposal≥10 行 + checkbox,反空壳)+ `arch-design-light`/`arch-snapshot-light`(`planned_arch=true` 条件挂载)。
21
+ - 既有 4 维加轻分支:`test-matrix-ready/complete` 无契约轻判据(D4)、`execution-plan-ready` planned 豁免 DP-4、`specs-merged` planned 无 specs 即过/有 specs 无 delta 头 FAIL。
22
+
23
+ **状态机 schema(三环齐全)**
24
+ - `workflow_variant` / `variant_source` / `variant_direction` / `planned_arch` / `model_profile`(接入既有 `models` 键四档,非新配置)/ `base_sha` / `arch_design_light_skipped(+reason)`;`workflow_variant` 经 `tf state set` 通用通道**仅 exploring 态可写**。
25
+
26
+ **SKILL 层**
27
+ - workflow-start:Front Doors 三分支路由 + infer 双通道(`suggested_path` 绝不写入 workflow;arch 信号→建议 planned 而非 full)+ 架构门/Guardrails 按 variant 分叉(direct/planned 结构性不经 `exploring:specifying`,Q3 零代码满足的限定条件落地)。
28
+ - release-archivist:关门序列按 variant 三分叉(planned 回写+审查全前置、transition 最后——防 closing 维度死锁;direct 仅 transition)+ Verdict 新增 **ACCEPTED-RISK**(仅非 guard 维度、禁自判、不伪造通过、不自动合并)。
29
+ - jarvis/session-handoff:variant 回显;test-strategy/clean-code description 收紧(§3.8 静态复核)。
30
+
31
+ **测试(npm test 1237 + test:e2e 103 全绿;CI 补 `npm run test:e2e` 步骤)**
32
+ - `light-paths.test.mjs`(21 用例,每新维度正/负例)、`light-merge-survival.test.mjs`(D8 same-sink 存活三断言:marker 聚合行 + 演进归因 + API 端点经 full merge 存活)、`light-pilot.test.mjs`(P7 双路径真实 CLI 全链 + 升档/禁降档试点)。
33
+ - e2e test-matrix 登记 L1–L5。
34
+
7
35
  ## [0.63.0] - 2026-09-23
8
36
 
9
37
  ### Added(sop-flow 效率八项改进 S1–S6 + E1/E2;来源:emp-auth workflow-feedback 20260923-013114,经 308 行独立专家评审定稿)
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.63.0 | 阶段: {{state}} | 工作流: {{workflow}}
11
+ # team-flow v0.64.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.63.0**。
10
+ 当前发布版本:**v0.64.0**。
11
11
 
12
12
  ---
13
13
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # team-flow
2
2
 
3
- > 当前版本:`v0.63.0`
3
+ > 当前版本:`v0.64.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.63.0`
129
+ - Current: `v0.64.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)
@@ -112,6 +112,8 @@ eight core states.
112
112
  exploring ──── hotfix ─────────> bridging (fast-path)
113
113
  bridging ──── hotfix ─────────> approved-for-build
114
114
  exploring ──── tweak ──────────> approved-for-build (fast-path)
115
+ exploring ──── quick/lightweight ─> approved-for-build > executing > closing (direct 前门, v0.64.0)
116
+ exploring ──── full+planned ───> approved-for-build > executing > closing (planned 前门, v0.64.0)
115
117
 
116
118
  exploring -> specifying -> bridging -> approved-for-build -> executing -> closing
117
119
  ^ ^ | ^ |
@@ -159,4 +161,5 @@ If the contract changed, the artifacts changed.
159
161
  - `hotfix` follows `exploring -> bridging -> approved-for-build -> executing`.
160
162
  - `hotfix` may skip full planning artifacts such as `proposal.md`, `design.md`, and `specs/`; `tasks.md` requires an explicit `tasks_skipped=true` + `tasks_skip_reason` (v0.22 §85) rather than a silent skip. The key is rejected for `full`/`auto` workflows — declare the mode first (`tf state set <dir> workflow hotfix|tweak`) or produce `tasks.md`.
161
163
  - `hotfix` still requires a fresh minimal `execution-contract.md` and explicit DP-3 approval before implementation.
162
- - `tweak` remains the only path that can jump directly from `exploring` to `approved-for-build`.
164
+ - `tweak` is **no longer the only** path from `exploring` to `approved-for-build` (v0.64.0)——`quick`/`lightweight`(direct 前门)与 `full`+`workflow_variant=planned`(planned 前门)同样走该捷径,维度表分别由 `QUICK_TRANSITION_CHECKS` / `PLANNED_TRANSITION_CHECKS` 管辖(见 workflow-start SKILL「Front Doors」与 guard.mjs)。`workflow_variant` 与 `workflow` 是两个正交维度:direct→`quick`、planned→`full`,**不是 workflow 取值**。
165
+ - 升档唯一机械入口 `tf state upgrade <dir> <planned|full>`(方向向上 + `variant_source=upgrade`;降档拒绝)。`executing → debugging → executing` 对 quick/planned 按档分支(direct: `direct-test-result`;planned: `execution-plan-ready`+`tests-passing`),**不回落 full 表**。
@@ -1,6 +1,6 @@
1
1
  # team-flow 使用说明(研发团队版)
2
2
 
3
- > 版本锚点:v0.63.0(28 skills + 17 agents)· 更新日期:2026-09-21
3
+ > 版本锚点:v0.64.0(28 skills + 17 agents)· 更新日期:2026-09-21
4
4
  > 读者:使用 team-flow 做日常研发的工程师。不需要你懂插件内部实现,只需要照着路径走。
5
5
  > 配套文档:安装细节见 [INSTALL.md](../INSTALL.md);状态机细节见 [state-machine.md](state-machine.md);决策点细节见 [decision-points.md](decision-points.md);平台差异见 [platform-matrix.md](platform-matrix.md)。
6
6
 
@@ -232,7 +232,7 @@ workflow-start 在初始化时自动推断(`tf runtime infer`),你也可
232
232
  tf runtime guard check <change-dir> <from-state> <to-state> [--workflow full|hotfix|tweak]
233
233
  ```
234
234
 
235
- **full 模式的完整转换矩阵**(20 个维度 + 1 个 workflow 限制维度):
235
+ **full 模式的完整转换矩阵**(31 个维度 + 1 个 workflow 限制维度;v0.64.0 增 quick/lightweight/planned 轻路径 11 维):
236
236
 
237
237
  | 转换 | 维度 |
238
238
  |------|------|
@@ -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) + jarvis (team-flow decision agent, opt-in). 28 skills, one install.",
4
- "version": "0.63.0",
4
+ "version": "0.64.0",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bash
2
- # v0.63.0: auto-sync CLI version with plugin version
2
+ # v0.64.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.63.0"
8
+ PLUGIN_VERSION="0.64.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.63.0.
6
+ Current version: v0.64.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.63.0",
3
+ "version": "0.64.0",
4
4
  "description": "Unified plugin (28 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.63.0",
3
+ "version": "0.64.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) + design-system (design tokens + component contract + AI primer + showcase) + test-strategy (test strategy design) + project-initialize (new service onboarding) + jarvis (team-flow decision agent, opt-in). 28 skills + 17 agents, one install.",
5
5
  "author": {
6
6
  "name": "LT"
@@ -0,0 +1,18 @@
1
+ // scripts/guard/checks/_fs-utils.mjs — light check 共享的文件系统小工具
2
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+
5
+ /** 递归扫描 dir 下所有 .md,文件名或内容任一含 needle 即 true(dir 不存在 → false) */
6
+ export function filesContainDir(dir, needle) {
7
+ if (!existsSync(dir)) return false;
8
+ const entries = readdirSync(dir, { recursive: true, withFileTypes: true });
9
+ for (const e of entries) {
10
+ if (!e.isFile() || !/\.md$/i.test(e.name)) continue;
11
+ if (e.name.includes(needle)) return true;
12
+ const parent = typeof e.parentPath === 'string' ? e.parentPath : dir;
13
+ try {
14
+ if (readFileSync(join(parent, e.name), 'utf-8').includes(needle)) return true;
15
+ } catch { /* skip unreadable */ }
16
+ }
17
+ return false;
18
+ }
@@ -0,0 +1,39 @@
1
+ // scripts/guard/checks/arch-design-light.mjs — 轻架构说明(§4,可选维度)
2
+ // v0.64.0:挂 planned 且 planned_arch=true(exploring→approved-for-build / approved-for-build→executing)。
3
+ // 判据:architecture/light-note.md 存在非空,或显式 skip-with-reason(arch_design_light_skipped
4
+ // + arch_design_light_skip_reason 两键齐全)。不要求 4A+DDD 全套 + 契约 + DP。
5
+ import { existsSync, readFileSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { readState } from '../../lib/state-loader.mjs';
8
+
9
+ export function checkArchDesignLight(changeDir) {
10
+ const state = readState(changeDir);
11
+
12
+ if (state.arch_design_light_skipped === 'true') {
13
+ const reason = (state.arch_design_light_skip_reason || '').trim();
14
+ if (!reason || reason === 'null') {
15
+ return {
16
+ pass: false,
17
+ failures: ['arch_design_light_skipped=true but no skip reason — set arch_design_light_skip_reason via tf state set'],
18
+ };
19
+ }
20
+ return { pass: true, failures: [], reason: `skipped: ${reason}` };
21
+ }
22
+
23
+ const notePath = join(changeDir, 'architecture', 'light-note.md');
24
+ if (!existsSync(notePath)) {
25
+ return {
26
+ pass: false,
27
+ failures: [
28
+ 'architecture/light-note.md missing — write a short light architecture note '
29
+ + '(touched surfaces, key decisions; no 4A+DDD suite needed), or skip explicitly: '
30
+ + 'tf state set <dir> arch_design_light_skipped true + arch_design_light_skip_reason "<reason>"',
31
+ ],
32
+ };
33
+ }
34
+ const content = readFileSync(notePath, 'utf-8').trim();
35
+ if (!content) {
36
+ return { pass: false, failures: ['architecture/light-note.md is empty — write the light architecture note'] };
37
+ }
38
+ return { pass: true, failures: [] };
39
+ }
@@ -0,0 +1,67 @@
1
+ // scripts/guard/checks/arch-merged-light.mjs — 架构台账轻回写(§4,非 negotiable 底线)
2
+ // v0.64.0(D8/D10):
3
+ // - 无架构 surface → 过(G4)
4
+ // - 有 surface → 最小持久源齐(architecture.md 必产;触及 API/DB 另需 api.md/database.md)
5
+ // + 全局台账(docs/architecture/**)含归因 `change:<name>`(归因锚 = 扫描 + 条目,非快照)
6
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
7
+ import { join } from 'node:path';
8
+ import { readState } from '../../lib/state-loader.mjs';
9
+ import { scanArchitectureSurface } from '../../lib/surface-scan.mjs';
10
+
11
+ function filesContain(dir, needle) {
12
+ if (!existsSync(dir)) return false;
13
+ const entries = readdirSync(dir, { recursive: true, withFileTypes: true });
14
+ for (const e of entries) {
15
+ if (!e.isFile() || !/\.md$/i.test(e.name)) continue;
16
+ const parent = typeof e.parentPath === 'string' ? e.parentPath : dir;
17
+ try {
18
+ if (readFileSync(join(parent, e.name), 'utf-8').includes(needle)) return true;
19
+ } catch { /* skip unreadable */ }
20
+ }
21
+ return false;
22
+ }
23
+
24
+ function minSourceOk(changeDir, rel) {
25
+ const p = join(changeDir, 'architecture', rel);
26
+ return existsSync(p) && readFileSync(p, 'utf-8').trim().length > 0;
27
+ }
28
+
29
+ export function checkArchMergedLight(changeDir) {
30
+ const state = readState(changeDir);
31
+ const changeName = state.change_name || changeDir.split('/').filter(Boolean).pop();
32
+ const scan = scanArchitectureSurface(changeDir, state);
33
+
34
+ if (scan.error === 'no-baseline' || scan.error === 'diff-failed') {
35
+ return { pass: false, failures: [`surface scan failed (${scan.error}) — cannot verify ledger writeback, fail-closed`] };
36
+ }
37
+ if (scan.error === 'aggregate-list-missing') {
38
+ return {
39
+ pass: false,
40
+ failures: ['aggregate list missing (.team-flow/aggregate-dirs.txt) — cannot classify architecture surface, fail-closed'],
41
+ };
42
+ }
43
+
44
+ if (scan.architectureSurface.length === 0) {
45
+ return { pass: true, failures: [], reason: 'no architecture surface touched — ledger writeback N/A (G4)' };
46
+ }
47
+
48
+ const failures = [];
49
+ // D8 最小持久源:architecture.md 必产(聚合注册行 + 演进日志段 = marker 区投影输入)
50
+ if (!minSourceOk(changeDir, 'architecture.md')) {
51
+ failures.push('changes/<name>/architecture/architecture.md missing/empty — minimal persistent source required (aggregate lines + ### change:<name> evolution entry); run the light arch writeback');
52
+ }
53
+ if (scan.apiFiles.length > 0 && !minSourceOk(changeDir, 'api.md')) {
54
+ failures.push('API surface touched but architecture/api.md missing/empty — minimal endpoint delta required (feeds arch-merge rebuild)');
55
+ }
56
+ if (scan.dbFiles.length > 0 && !minSourceOk(changeDir, 'database.md')) {
57
+ failures.push('DB surface touched but architecture/database.md missing/empty — minimal schema delta required');
58
+ }
59
+
60
+ const anchor = `change:${changeName}`;
61
+ const globalLedger = join(scan.projectRoot, 'docs', 'architecture');
62
+ if (!filesContain(globalLedger, anchor)) {
63
+ failures.push(`global ledger (docs/architecture/**) has no '${anchor}' attribution — run: tf arch-merge --light <change-dir>`);
64
+ }
65
+
66
+ return failures.length ? { pass: false, failures } : { pass: true, failures: [] };
67
+ }
@@ -0,0 +1,30 @@
1
+ // scripts/guard/checks/arch-snapshot-light.mjs — 轻架构快照(§4,条件维度)
2
+ // v0.64.0(D10 裁决):仅当 light-note 产出时需要快照(供演进日志 diff 展示);
3
+ // arch-merged-light 的归因锚 = 扫描 + 台账条目,不依赖本快照——无 note / 已 skip → N/A 通过。
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { readState } from '../../lib/state-loader.mjs';
7
+
8
+ export function checkArchSnapshotLight(changeDir) {
9
+ const state = readState(changeDir);
10
+
11
+ const notePath = join(changeDir, 'architecture', 'light-note.md');
12
+ const hasNote = existsSync(notePath) && readFileSync(notePath, 'utf-8').trim().length > 0;
13
+ const skipped = state.arch_design_light_skipped === 'true';
14
+
15
+ if (!hasNote || skipped) {
16
+ return { pass: true, failures: [], reason: 'no light architecture note — snapshot N/A (D10: anchor is scan+ledger, not snapshot)' };
17
+ }
18
+
19
+ const snapPath = join(changeDir, 'architecture', 'snapshot-light.md');
20
+ if (!existsSync(snapPath)) {
21
+ return {
22
+ pass: false,
23
+ failures: ['light note present but architecture/snapshot-light.md missing — snapshot the touched surfaces before closing'],
24
+ };
25
+ }
26
+ if (!readFileSync(snapPath, 'utf-8').trim()) {
27
+ return { pass: false, failures: ['architecture/snapshot-light.md is empty'] };
28
+ }
29
+ return { pass: true, failures: [] };
30
+ }
@@ -0,0 +1,38 @@
1
+ // scripts/guard/checks/artifacts-planned.mjs — planned 的规划制品判据(§4.5②,替代四件套)
2
+ // v0.64.0(B-01 强化):不止「存在」——防空壳套餐:
3
+ // proposal.md 非空(≥10 个非空行)+ tasks.md ≥1 条 checkbox。
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+ import { parseTaskLine } from '../../lib/md-normalize.mjs';
7
+
8
+ function nonEmptyLines(text) {
9
+ return text.split('\n').filter(l => l.trim()).length;
10
+ }
11
+
12
+ export function checkArtifactsPlanned(changeDir) {
13
+ const failures = [];
14
+ const proposalPath = join(changeDir, 'proposal.md');
15
+ const tasksPath = join(changeDir, 'tasks.md');
16
+
17
+ if (!existsSync(proposalPath)) {
18
+ failures.push('proposal.md is missing — planned path requires proposal.md + tasks.md');
19
+ } else {
20
+ const proposal = readFileSync(proposalPath, 'utf-8');
21
+ const lines = nonEmptyLines(proposal);
22
+ if (lines < 10) {
23
+ failures.push(`proposal.md too thin (${lines} non-empty lines, need ≥10) — state intent, scope, and acceptance criteria`);
24
+ }
25
+ }
26
+
27
+ if (!existsSync(tasksPath)) {
28
+ failures.push('tasks.md is missing — planned path requires proposal.md + tasks.md');
29
+ } else {
30
+ const tasks = readFileSync(tasksPath, 'utf-8');
31
+ const taskCount = tasks.split('\n').map(l => parseTaskLine(l)).filter(Boolean).length;
32
+ if (taskCount < 1) {
33
+ failures.push('tasks.md has no task checkboxes — add at least one `- [ ]` task');
34
+ }
35
+ }
36
+
37
+ return failures.length ? { pass: false, failures } : { pass: true, failures: [] };
38
+ }
@@ -0,0 +1,45 @@
1
+ // scripts/guard/checks/compound-writeback-light.mjs — 复利轻回写(§4,同 sink 不另起台账)
2
+ // v0.64.0:planned closing 必执行(含「无新增决策」的显式空捕获记录),
3
+ // **不走 compound_skipped 自清**(§3.7——自清会让 closed 后的全局库漏写无兜底)。
4
+ // 判据:docs/solutions/** 存在归因 `change:<name>` 的条目(INDEX 单写入口 tf solutions 系列产出)。
5
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
6
+ import { join } from 'node:path';
7
+ import { readState } from '../../lib/state-loader.mjs';
8
+ import { findProjectRoot } from '../../lib/surface-scan.mjs';
9
+
10
+ function filesContain(dir, needle) {
11
+ if (!existsSync(dir)) return false;
12
+ const entries = readdirSync(dir, { recursive: true, withFileTypes: true });
13
+ for (const e of entries) {
14
+ if (!e.isFile() || !/\.md$/i.test(e.name)) continue;
15
+ const parent = typeof e.parentPath === 'string' ? e.parentPath : dir;
16
+ try {
17
+ if (readFileSync(join(parent, e.name), 'utf-8').includes(needle)) return true;
18
+ } catch { /* skip */ }
19
+ }
20
+ return false;
21
+ }
22
+
23
+ export function checkCompoundWritebackLight(changeDir) {
24
+ const state = readState(changeDir);
25
+ const changeName = state.change_name || changeDir.split('/').filter(Boolean).pop();
26
+
27
+ // 自清通道对本维度无效(planned 禁 compound_skipped,§3.7)
28
+ if (state.compound_skipped === true || state.compound_skipped === 'true') {
29
+ return {
30
+ pass: false,
31
+ failures: ['compound_skipped is not accepted on the planned light path — capture into the global library (empty capture "no new decisions" is fine): tf solutions capture / ce-compound with change:<name> attribution'],
32
+ };
33
+ }
34
+
35
+ const projectRoot = findProjectRoot(changeDir);
36
+ const solutionsDir = join(projectRoot, 'docs', 'solutions');
37
+ const anchor = `change:${changeName}`;
38
+ if (filesContain(solutionsDir, anchor) || filesContain(solutionsDir, changeName)) {
39
+ return { pass: true, failures: [] };
40
+ }
41
+ return {
42
+ pass: false,
43
+ failures: [`no solution entry attributed '${anchor}' (or '${changeName}') in docs/solutions/** — run compound capture (tf solutions capture / ce-compound), INDEX single-writer + dedup; an explicit 'no new decisions' entry satisfies this gate`],
44
+ };
45
+ }
@@ -0,0 +1,75 @@
1
+ // scripts/guard/checks/cross-change-consistency-light.mjs — 跨 change 冲突确定性初筛(§3.3)
2
+ // v0.64.0(A-14/S-07 重定义):guard runner 是 10s 内确定性 Node 函数,**不能调 LLM agent**。
3
+ // 本 runner 做机械初筛:其他在途 change(state ∈ executing/debugging/approved-for-build)
4
+ // 的 minimal api.md 端点路径 / architecture.md 聚合行 与本 change 的最小源求交——
5
+ // 交集非空 = 共享 surface 冲突。语义级冲突由 release-archivist 关门序列派发
6
+ // cross-change-consistency-checker agent 兜底(分工见 §3.3)。
7
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
8
+ import { join, basename, dirname } from 'node:path';
9
+ import { readState } from '../../lib/state-loader.mjs';
10
+ import { findProjectRoot } from '../../lib/surface-scan.mjs';
11
+
12
+ const IN_FLIGHT = new Set(['approved-for-build', 'executing', 'debugging']);
13
+
14
+ function extractApiPaths(file) {
15
+ if (!existsSync(file)) return new Set();
16
+ const text = readFileSync(file, 'utf-8');
17
+ // 端点表单元格里的路径 token(/api/xxx、/v1/xxx、{id} 形态)
18
+ const out = new Set();
19
+ for (const m of text.matchAll(/(\/[A-Za-z0-9_\-{}./]+)/g)) {
20
+ const p = m[1];
21
+ if (p.length > 1 && !p.endsWith('.md')) out.add(p.replace(/\/+$/, ''));
22
+ }
23
+ return out;
24
+ }
25
+
26
+ function extractAggregateNames(file) {
27
+ if (!existsSync(file)) return new Set();
28
+ const text = readFileSync(file, 'utf-8');
29
+ const out = new Set();
30
+ for (const m of text.matchAll(/聚合[::\s*`]+[`*]*([A-Za-z][A-Za-z0-9_\-]*)/g)) out.add(m[1]);
31
+ return out;
32
+ }
33
+
34
+ export function checkCrossChangeConsistencyLight(changeDir) {
35
+ const state = readState(changeDir);
36
+ const projectRoot = findProjectRoot(changeDir);
37
+ const changesDir = join(projectRoot, 'changes');
38
+ if (!existsSync(changesDir)) return { pass: true, failures: [], reason: 'no changes/ dir' };
39
+
40
+ const selfName = state.change_name || basename(changeDir);
41
+ const selfApi = extractApiPaths(join(changeDir, 'architecture', 'api.md'));
42
+ const selfAgg = extractAggregateNames(join(changeDir, 'architecture', 'architecture.md'));
43
+
44
+ const conflicts = [];
45
+ for (const entry of readdirSync(changesDir, { withFileTypes: true })) {
46
+ if (!entry.isDirectory() || entry.name === selfName) continue;
47
+ const otherDir = join(changesDir, entry.name);
48
+ const otherStatePath = join(otherDir, '.team-flow.yaml');
49
+ if (!existsSync(otherStatePath)) continue;
50
+ const other = readState(otherDir);
51
+ if (!IN_FLIGHT.has(other.state)) continue;
52
+
53
+ const otherApi = extractApiPaths(join(otherDir, 'architecture', 'api.md'));
54
+ const otherAgg = extractAggregateNames(join(otherDir, 'architecture', 'architecture.md'));
55
+
56
+ const apiOverlap = [...selfApi].filter(p => otherApi.has(p));
57
+ const aggOverlap = [...selfAgg].filter(a => otherAgg.has(a));
58
+ if (apiOverlap.length || aggOverlap.length) {
59
+ conflicts.push(
60
+ `${entry.name}: api=[${apiOverlap.slice(0, 5).join(', ')}] aggregates=[${aggOverlap.slice(0, 5).join(', ')}]`
61
+ );
62
+ }
63
+ }
64
+
65
+ if (conflicts.length) {
66
+ return {
67
+ pass: false,
68
+ failures: [
69
+ `shared surface conflicts with in-flight change(s):\n ${conflicts.join('\n ')} `
70
+ + '— resolve ownership or stagger closing; semantic-level review via cross-change-consistency-checker agent',
71
+ ],
72
+ };
73
+ }
74
+ return { pass: true, failures: [] };
75
+ }
@@ -0,0 +1,52 @@
1
+ // scripts/guard/checks/direct-short-path.mjs — direct/lightweight 短路径 + 架构 surface 扫描
2
+ // v0.64.0(实施计划 §4,G1 加固):
3
+ // - 挂 quick/lightweight 的 exploring→approved-for-build / approved-for-build→executing / closing
4
+ // - G4 前提保障:无架构 surface(API/DB/聚合)→ 过(真琐碎零负担)
5
+ // - 命中架构 surface → FAIL 并给升级指引(禁止静默过);扫描失败/清单缺失一律 fail-closed
6
+ import { readState } from '../../lib/state-loader.mjs';
7
+ import { scanArchitectureSurface } from '../../lib/surface-scan.mjs';
8
+
9
+ const UPGRADE_HINT =
10
+ 'architecture surface (API/DB/aggregate) touched — upgrade to planned: '
11
+ + 'tf state upgrade <change-dir> planned (keeps code/test evidence, rolls back to approved-for-build, '
12
+ + 're-runs planned gates + light writeback sequence; downgrades rejected)';
13
+
14
+ export function checkDirectShortPath(changeDir) {
15
+ const state = readState(changeDir);
16
+ const scan = scanArchitectureSurface(changeDir, state);
17
+
18
+ if (scan.error === 'no-baseline') {
19
+ return {
20
+ pass: false,
21
+ failures: [
22
+ 'no scan baseline: base_sha missing and no origin/<default> to derive merge-base — '
23
+ + 'run inside a git repo with at least one commit (tf state init stamps base_sha), fail-closed',
24
+ ],
25
+ };
26
+ }
27
+ if (scan.error === 'diff-failed') {
28
+ return {
29
+ pass: false,
30
+ failures: [`git diff against base failed (base=${scan.base ?? 'unknown'}) — cannot verify architecture surface, fail-closed`],
31
+ };
32
+ }
33
+ if (scan.error === 'aggregate-list-missing') {
34
+ return {
35
+ pass: false,
36
+ failures: [
37
+ 'aggregate list missing: create .team-flow/aggregate-dirs.txt (one dir prefix per line; '
38
+ + 'empty file = explicitly no aggregates) or run workflow-bootstrap — fail-closed, aggregate surface is blind otherwise',
39
+ ],
40
+ };
41
+ }
42
+
43
+ if (scan.architectureSurface.length > 0) {
44
+ return {
45
+ pass: false,
46
+ failures: [
47
+ `${UPGRADE_HINT}\n touched: ${scan.architectureSurface.slice(0, 10).join(', ')}`,
48
+ ],
49
+ };
50
+ }
51
+ return { pass: true, failures: [] };
52
+ }