@xulthekl/team-flow 0.55.0 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- # team-flow v0.55.0 | 阶段: {{state}} | 工作流: {{workflow}}
1
+ # team-flow v0.56.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.55.0",
12
+ "version": "0.56.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.55.0",
3
+ "version": "0.56.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). 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.55.0",
3
+ "version": "0.56.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.55.0"
8
+ "version": "0.56.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.55.0",
5
+ "version": "0.56.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.55.0"
9
+ "version": "0.56.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.55.0",
15
+ "version": "0.56.0",
16
16
  "source": ".",
17
17
  "author": {
18
18
  "name": "LT",
package/AGENTS.md CHANGED
@@ -110,7 +110,7 @@ docs/
110
110
  ├── architecture/ 全局架构三层(v0.36.0):L1 当前态(ARCHITECTURE.md marker 区 / PHYSICAL-MODEL.md / DATABASE.md / API-INDEX.md / INDEX.md / domains/<bc>.md / diagrams/ / schema-baseline.sql / baseline.md)+ L2 changelog/ + L3 iterations/vN/architecture.md(产品级快照,archived 退役)
111
111
  └── solutions/ 复利经验库(v0.5 新增,三层索引)
112
112
  ├── INDEX.md # L1 轻量索引(≤150行,每条一行摘要+标签)
113
- ├── requirement/ plan/ architecture/ prototype/ spec/ build/ review/ cross-phase/ # L2 分阶段目录(v0.36.0 加 architecture)
113
+ ├── prd/ plan/ architecture/ prototype/ spec/ build/ review/ cross-phase/ # L2 分阶段目录(枚举权威:scripts/lib/solutions-phases.mjs)
114
114
  └── <file>.md # L3 经验文件(YAML frontmatter: phase/domain/type/severity)
115
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
116
  specs/<cap>/ 每变更规格:spec.md(v0.49.0 §83.3.5:learnings.md 归 change 根,不在此目录)
@@ -253,7 +253,7 @@ STRATEGY.md CONCEPTS.md 产品策略(BA) / 领域词汇
253
253
  ```
254
254
  docs/solutions/
255
255
  ├── INDEX.md # L1:轻量索引(≤150行,每条一行摘要+标签,按 severity 降序)
256
- ├── requirement/ plan/ prototype/ spec/ build/ review/ cross-phase/ # L2:分阶段目录
256
+ ├── prd/ plan/ architecture/ prototype/ spec/ build/ review/ cross-phase/ # L2:分阶段目录(枚举权威:scripts/lib/solutions-phases.mjs)
257
257
  └── <date>-<summary>.md # L3:经验文件(YAML frontmatter: phase/domain/type/severity/date/source)
258
258
  ```
259
259
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,35 @@ 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.56.0] - 2026-09-12
8
+
9
+ ### Fixed(复利产物文件名退化 + 索引丢条目;来源:emp-auth 复利膨胀调查)
10
+
11
+ 设计来源:`docs/plan/compound-lifecycle-governance-design.md` v1.0。输入 = **emp-auth v1 迭代(5 change)的复利产物实测**——发现"复利条目随迭代膨胀/重复"的表象下,实为**存储层无上限 + 身份层去重键选错 + 索引层无门禁**三层缺口(完整证据链见该方案附录 A;P1/P2 待实施)。
12
+
13
+ 本版处置其中两个**确定性缺陷**(P0):
14
+
15
+ - **PHASES 枚举三处定义互相矛盾**(`solutions-capture` 8 项含 `architecture` / `solutions-index-gen` 7 项缺 / 文档树写 `requirement`):`tf solutions capture --phase architecture` 写入的条目在 `tf solutions index-gen` 重建后**从 INDEX.md 消失**——文件仍在磁盘,但对所有注入与检索通道不可见。新增 `scripts/lib/solutions-phases.mjs` 作唯一真相源,两处消费点收敛。
16
+ - **slug 规则三套并存,两处不保留 CJK 且逐字符替换**:`test-merge.mjs` 的 `replace(/[^a-z0-9-]/g,'-')` 与 `sdd-overlay.mjs` 的 `replace(/[^A-Za-z0-9._-]/g,'_')` 把中文标题**逐字符**替换为分隔符,产生 `--------------------.md`(原名「执行结果(三仓实测,命令 + 实际输出)」)这类无信息量文件名(emp-auth 实测 17 个文件受影响);叠加 baselines 的 `moduleName` 取自 test-matrix 三级标题原文(每轮自由命名)⇒ 文件名不稳定 ⇒ `existsSync` 不命中 ⇒ **新建而非增量合并**(`demohome` 三次 merge 全为 `A(Added)`,攒出 3 个文件)。新增 `scripts/lib/slug.mjs` 作唯一真相源(`slugify` / `safeName` / `CJK_CLASS`),4 处消费点收敛。
17
+
18
+ **关键陷阱(已写入模块注释守护)**:字面「一-鿿」拼进字符类时,**前一个字符若为 `-` 会构成范围**——`[^..._-一-鿿]` 里的 `_-一` 是 U+005F–U+4E00 范围,U+4E00 以上的汉字(如「任务」U+4EFB)仍被替换。故 `CJK_CLASS` 以转义写法导出,`safeName` 的 `-` 置于字符类末尾。
19
+
20
+ ### Added
21
+
22
+ - `scripts/lib/slug.mjs`(文件名/路径段安全化唯一真相源)、`scripts/lib/solutions-phases.mjs`(复利 phase 枚举唯一真相源)
23
+ - `tests/lib/slug.test.mjs`(13 用例,含 U+4E00 以上汉字的范围陷阱守护)、`tests/lib/solutions-phases.test.mjs`(6 用例,含"capture 能写但 index-gen 扫不到"的行为级守护)、`tests/lib/test-merge.test.mjs` +1 用例(中文模块名不退化为短横线)
24
+
25
+ ### Changed
26
+
27
+ - `AGENTS.md` ×2、`skills/ce-compound/references/three-tier-index.md` ×2:phase 目录列表同口径同步,顺带修正 `requirement/` → `prd/`(与脚本实际写入目录对齐),并补注"CLI 通道 phase 目录"与"ce-compound category 目录"两套词表互不兼容
28
+
29
+ ### 验证
30
+
31
+ - 全量测试 **1108/1108 通过**
32
+ - **4 项变异验证**确认新增测试具备判别力(去掉 `architecture` / index-gen 写死列表 / `safeName` 的 `-` 置中 / test-merge 还原旧正则——每项均使对应测试失败并报出原缺陷形态)
33
+ - **行为等价实证**:以 emp-auth 真实 learnings 标题跑新 `slugify`,与既有条目文件名 **4/4 一致**(无回归)
34
+ - 提交可见性:4 个新增文件未被 `.gitignore` 吞掉,2 个脚本进入 `npm pack` 白名单
35
+
7
36
  ## [0.55.0] - 2026-09-11
8
37
 
9
38
  ### Added(首次真实使用反馈处置:棕地机制 + 解析层加固)
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.55.0 | 阶段: {{state}} | 工作流: {{workflow}}
11
+ # team-flow v0.56.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.55.0**。
10
+ 当前发布版本:**v0.56.0**。
11
11
 
12
12
  ---
13
13
 
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # team-flow
2
2
 
3
- > 当前版本:`v0.55.0`
3
+ > 当前版本:`v0.56.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.55.0`
129
+ - Current: `v0.56.0`
130
130
  - v0.9.1 highlights: DP-4 execution-mode recommendations, a portable runtime across 17 platforms, and a raw-package smoke with no plugin-root variable.
131
131
  - Self-contained — no OpenSpec or Superpowers runtime required
132
132
  - Upstream: [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec), [obra/superpowers](https://github.com/obra/superpowers)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "team-flow",
3
3
  "description": "Unified workflow plugin: team-flow (spec-driven dev) + compound-engineering core subset + architecture-design (4A/DDD) + prototype (local HTML) + business-analysis (independent requirement/scenario artifact). 26 skills, one install.",
4
- "version": "0.55.0",
4
+ "version": "0.56.0",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bash
2
- # v0.55.0: auto-sync CLI version with plugin version
2
+ # v0.56.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.55.0"
8
+ PLUGIN_VERSION="0.56.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.55.0.
6
+ Current version: v0.56.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.55.0",
3
+ "version": "0.56.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.55.0",
3
+ "version": "0.56.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). 26 skills + 17 agents, one install.",
5
5
  "author": {
6
6
  "name": "LT"
@@ -6,6 +6,7 @@ import { dirname, join } from 'node:path';
6
6
  import { computeArtifactsHash, normalizeCheckboxes } from './hash.mjs';
7
7
  import { parseTaskLine } from './md-normalize.mjs';
8
8
  import { readState } from './state-loader.mjs';
9
+ import { safeName } from './slug.mjs';
9
10
 
10
11
  export const HANDOFF_TYPES = new Set(['prototype', 'research', 'experiment']);
11
12
  export const HANDOFF_DECISIONS = new Set(['accept', 'reject', 'defer']);
@@ -270,6 +271,4 @@ function requireText(value, field) {
270
271
  if (typeof value !== 'string' || !value.trim()) throw new Error(`${field} is required`);
271
272
  }
272
273
 
273
- function safeName(value) {
274
- return String(value).replace(/[^A-Za-z0-9._-]/g, '_');
275
- }
274
+ // safeName 已收敛到 slug.mjs(保留 CJK;`. _ -` 语义不变,如 taskId `1.1` 原样保留)
@@ -0,0 +1,68 @@
1
+ /**
2
+ * slug — 文件名 / 路径段安全化的唯一真相源(2026-09-12,emp-auth 复利膨胀调查)
3
+ *
4
+ * 背景:同一插件内曾存在 3 套文件名安全化规则,其中两套**未保留 CJK 且逐字符替换**,
5
+ * 导致中文标题退化为纯短横线序列。实证(emp-auth v1 迭代):
6
+ * - `docs/test-ledger/baselines/--------------------.md`(原名「执行结果(三仓实测,命令 + 实际输出)」)
7
+ * - 同目录 17 个文件名受影响,其中多份已无法从文件名辨识内容
8
+ * - 叠加第二个因素:baselines 的 moduleName 取自 test-matrix 三级标题原文(每轮由 LLM
9
+ * 自由命名,如 `DemoHome 当前应用(demo-ui,medium)` vs `DemoHome(demo-ui,medium,revision 3)`)
10
+ * ⇒ 文件名每轮变化 ⇒ `existsSync` 不命中 ⇒ **新建而非增量合并**(demohome 三次 merge
11
+ * 产出 3 个文件,git 记录全为 A)
12
+ *
13
+ * 约定:
14
+ * - 字符集统一为 **ASCII 字母数字 + CJK 统一表意文字(U+4E00–U+9FFF)**;其余字符折叠为分隔符
15
+ * - 一律使用 `+` 量词折叠连续非法字符——**禁止逐字符替换**(一个中文 = 一个分隔符是退化根因)
16
+ * - 两类用途语义不同,**不要互串**:
17
+ * · slugify() 标题 → 文件名(小写、`.`/`_`/`-` 均折叠为分隔符、可截断)
18
+ * · safeName() ID → 路径段(保留大小写与 `.` `_` `-`,不截断)——ID 自身以这些字符作分隔,
19
+ * 例如 taskId `1.1` MUST 保持为 `1.1`(折叠成 `1_1` 会失配既有 checkpoint 文件)
20
+ *
21
+ * @module slug
22
+ */
23
+
24
+ /**
25
+ * CJK 统一表意文字区间字符类(U+4E00–U+9FFF)。
26
+ *
27
+ * 用 `\u` 转义写法而非字面「一-鿿」:字面写法拼进字符类时,**前一个字符若为 `-`
28
+ * 会被解析成范围**——`[^..._-一-鿿]` 里的 `_-一` 是 U+005F–U+4E00 范围,
29
+ * 结果 U+4E00 以上的汉字(如「任务」U+4EFB)仍被替换。转义写法无此风险。
30
+ */
31
+ export const CJK_CLASS = '\\u4e00-\\u9fff';
32
+
33
+ /** 转义正则元字符(separator 由调用方传入,可能是 `-` / `_` 等) */
34
+ function escapeRe(s) {
35
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
36
+ }
37
+
38
+ /**
39
+ * 标题 → 文件名 slug。
40
+ *
41
+ * 保留 ASCII 小写字母数字与 CJK;其余连续字符折叠为一个 separator;去掉首尾 separator。
42
+ *
43
+ * @param {string} value 原始文本(通常是条目标题 / 模块名)
44
+ * @param {{separator?: string, maxLength?: number}} [options]
45
+ * separator 默认 `-`;maxLength > 0 时才截断(默认不截断,由调用方按场景显式传入)
46
+ * @returns {string}
47
+ */
48
+ export function slugify(value, { separator = '-', maxLength = 0 } = {}) {
49
+ const esc = escapeRe(separator);
50
+ let s = String(value ?? '').toLowerCase();
51
+ s = s.replace(new RegExp(`[^a-z0-9${CJK_CLASS}]+`, 'g'), separator);
52
+ s = s.replace(new RegExp(`^(?:${esc})+|(?:${esc})+$`, 'g'), '');
53
+ return maxLength > 0 ? s.slice(0, maxLength) : s;
54
+ }
55
+
56
+ /**
57
+ * ID → 路径段安全名。
58
+ *
59
+ * 保留 ASCII 字母数字(含大小写)与 `.` `_` `-`,以及 CJK;其余连续字符折叠为一个 `_`。
60
+ * 不截断、不改大小写——ID 的既有语义(如 `1.1`、`W4-1`)MUST 原样保留。
61
+ *
62
+ * @param {string} value
63
+ * @returns {string}
64
+ */
65
+ export function safeName(value) {
66
+ // `-` MUST 置于字符类末尾(否则与相邻字符构成范围)
67
+ return String(value ?? '').replace(new RegExp(`[^A-Za-z0-9._${CJK_CLASS}-]+`, 'g'), '_');
68
+ }
@@ -16,17 +16,11 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync, appendFileSync } fr
16
16
  import { join } from 'node:path';
17
17
  import { pathToFileURL } from 'node:url';
18
18
  import { SEVERITY_VALUES, isSeverity } from './severity.mjs';
19
+ import { SOLUTION_PHASES } from './solutions-phases.mjs';
20
+ import { slugify } from './slug.mjs';
19
21
 
20
- const PHASES = ['prd', 'plan', 'architecture', 'prototype', 'spec', 'build', 'review', 'cross-phase'];
21
22
  const MAX_INDEX_LINES = 150;
22
-
23
- function slugify(text) {
24
- return text
25
- .toLowerCase()
26
- .replace(/[^a-z0-9一-鿿]+/g, '-')
27
- .replace(/^-|-$/g, '')
28
- .slice(0, 40);
29
- }
23
+ const SLUG_MAX_LENGTH = 40;
30
24
 
31
25
  export function run(args = {}) {
32
26
  const phase = args.phase || 'cross-phase';
@@ -42,8 +36,8 @@ export function run(args = {}) {
42
36
 
43
37
  // 注:process.exit 后补 return——真实 CLI 下 exit 即终止;测试环境 mock exit 时
44
38
  // 不得继续执行(否则校验失败仍会写入文件,v0.23 §91.3.4 横展)。
45
- if (!PHASES.includes(phase)) {
46
- console.error(`Invalid phase: ${phase}. Valid: ${PHASES.join(', ')}`);
39
+ if (!SOLUTION_PHASES.includes(phase)) {
40
+ console.error(`Invalid phase: ${phase}. Valid: ${SOLUTION_PHASES.join(', ')}`);
47
41
  process.exit(1);
48
42
  return;
49
43
  }
@@ -61,7 +55,7 @@ export function run(args = {}) {
61
55
 
62
56
  // 生成文件名
63
57
  const date = new Date().toISOString().slice(0, 10);
64
- const slug = slugify(summary);
58
+ const slug = slugify(summary, { maxLength: SLUG_MAX_LENGTH });
65
59
  const fileName = `${date}-${slug}.md`;
66
60
  const filePath = join(phaseDir, fileName);
67
61
 
@@ -17,8 +17,8 @@ import { readFileSync, writeFileSync, readdirSync, statSync, existsSync } from '
17
17
  import { join } from 'node:path';
18
18
  import { pathToFileURL } from 'node:url';
19
19
  import { severityRank } from './severity.mjs';
20
+ import { SOLUTION_PHASES } from './solutions-phases.mjs';
20
21
 
21
- const PHASES = ['prd', 'plan', 'prototype', 'spec', 'build', 'review', 'cross-phase'];
22
22
  const MAX_INDEX_LINES = 150;
23
23
 
24
24
  function parseFrontmatter(content) {
@@ -54,7 +54,7 @@ export function run(args = {}) {
54
54
 
55
55
  const entries = [];
56
56
 
57
- for (const phase of PHASES) {
57
+ for (const phase of SOLUTION_PHASES) {
58
58
  const phaseDir = join(dir, phase);
59
59
  if (!existsSync(phaseDir) || !statSync(phaseDir).isDirectory()) continue;
60
60
 
@@ -0,0 +1,32 @@
1
+ /**
2
+ * solutions-phases — 复利条目 phase 目录的唯一真相源(2026-09-12)
3
+ *
4
+ * 背景:PHASES 枚举曾在 3 处各自定义且互相矛盾——
5
+ * - `solutions-capture.mjs` 8 项(含 `architecture`,v0.36.3 加入)
6
+ * - `solutions-index-gen.mjs` 7 项(**缺 `architecture`**)
7
+ * - 文档树(three-tier-index.md / AGENTS.md)写 `requirement`,而 frontmatter 示例写 `prd`
8
+ *
9
+ * 后果(实证,emp-auth):`tf solutions capture --phase architecture` 写入的条目在
10
+ * `tf solutions index-gen` 重建后会**从 INDEX.md 消失**——文件仍在磁盘,但对所有
11
+ * 注入 / 检索通道不可见。任何新增 phase 只改本文件。
12
+ *
13
+ * 注意:`docs/solutions/` 下另有 ce-compound 通道写入的 **category 目录**
14
+ * (`workflow-issues/` 等,见 skills/ce-compound/references/yaml-schema.md),
15
+ * 那套词表与本 phase 词表**互不兼容**,本模块不覆盖。
16
+ *
17
+ * @module solutions-phases
18
+ */
19
+
20
+ /** 合法 phase 取值(同时是 docs/solutions/ 下的子目录名) */
21
+ export const SOLUTION_PHASES = Object.freeze([
22
+ 'prd', 'plan', 'architecture', 'prototype', 'spec', 'build', 'review', 'cross-phase',
23
+ ]);
24
+
25
+ /**
26
+ * 是否为合法 phase 取值。
27
+ * @param {string} phase
28
+ * @returns {boolean}
29
+ */
30
+ export function isSolutionPhase(phase) {
31
+ return SOLUTION_PHASES.includes(phase);
32
+ }
@@ -23,6 +23,10 @@ import { join, basename } from 'node:path';
23
23
  import { pathToFileURL } from 'node:url';
24
24
  import { meetsMinSeverity, nextSeverity } from './severity.mjs';
25
25
  import { normalizeInline } from './md-normalize.mjs';
26
+ import { slugify } from './slug.mjs';
27
+
28
+ /** 文件名 slug 截断长度(与 solutions-capture 一致) */
29
+ const SLUG_MAX_LENGTH = 40;
26
30
 
27
31
  /**
28
32
  * 剥离 YAML 行尾注释(空格 + `#` 起始)——v0.23 §91 硬化:
@@ -188,7 +192,7 @@ export function run(args = {}) {
188
192
  mkdirSync(phaseDir, { recursive: true });
189
193
  }
190
194
 
191
- const slug = learning.title.toLowerCase().replace(/[^a-z0-9一-鿿]+/g, '-').slice(0, 40);
195
+ const slug = slugify(learning.title, { maxLength: SLUG_MAX_LENGTH });
192
196
  const fileName = `${date}-${slug}.md`;
193
197
  const filePath = join(phaseDir, fileName);
194
198
 
@@ -27,6 +27,7 @@
27
27
  import { readFileSync, writeFileSync, existsSync, cpSync, mkdirSync, readdirSync } from 'node:fs';
28
28
  import { join, basename, relative, resolve } from 'node:path';
29
29
  import { execSync } from 'node:child_process';
30
+ import { slugify } from './slug.mjs';
30
31
 
31
32
  /**
32
33
  * 解析 CLI 参数数组为结构化对象
@@ -197,7 +198,9 @@ export function mergeBaselines(ledgerDir, changeName, moduleSections, candidateL
197
198
  const today = new Date().toISOString().slice(0, 10);
198
199
 
199
200
  for (const [moduleName, sectionContent] of Object.entries(moduleSections)) {
200
- const safeName = moduleName.toLowerCase().replace(/[^a-z0-9-]/g, '-');
201
+ // 统一走 slug.mjs(保留 CJK)——原 `[^a-z0-9-]` 逐字符替换会把中文标题退化成纯短横线,
202
+ // 实证 emp-auth `baselines/--------------------.md`(2026-09-12)
203
+ const safeName = slugify(moduleName);
201
204
  const baselinePath = join(baselinesDir, `${safeName}.md`);
202
205
  const moduleCandidates = candidateLedger.filter(c =>
203
206
  c.candidate.toLowerCase().includes(moduleName.toLowerCase())
@@ -5,8 +5,9 @@
5
5
  ```
6
6
  docs/solutions/
7
7
  ├── INDEX.md # L1:轻量索引(≤150行,每条一行摘要+标签)
8
- ├── requirement/ # 按阶段分目录
8
+ ├── prd/ # 按阶段分目录(枚举权威:scripts/lib/solutions-phases.mjs)
9
9
  ├── plan/
10
+ ├── architecture/
10
11
  ├── prototype/
11
12
  ├── spec/
12
13
  ├── build/
@@ -14,6 +15,9 @@ docs/solutions/
14
15
  └── cross-phase/ # 跨阶段通用经验
15
16
  ```
16
17
 
18
+ > 注意:目录树中**只有上述 phase 目录**由 `tf solutions` CLI 通道维护;`workflow-issues/`、
19
+ > `build-errors/` 等 category 目录由 `/ce-compound` 通道写入,两套词表互不兼容。
20
+
17
21
  ## INDEX.md 格式
18
22
 
19
23
  ```markdown
@@ -29,7 +33,7 @@ docs/solutions/
29
33
 
30
34
  ```yaml
31
35
  ---
32
- phase: prd # 阶段标签:prd | plan | prototype | spec | build | review | cross-phase
36
+ phase: prd # 阶段标签:prd | plan | architecture | prototype | spec | build | review | cross-phase
33
37
  domain: auth # 领域标签(与 PRD/change 的领域对应)
34
38
  type: pitfall # pitfall | pattern | decision | insight
35
39
  severity: high # critical | high | medium | low(序定义于 scripts/lib/severity.mjs)