@namewta/speculo 0.8.8 → 0.8.9

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namewta/speculo",
3
- "version": "0.8.8",
3
+ "version": "0.8.9",
4
4
  "description": "Workflow-packaged AI collaboration assets with state-safe refresh tooling.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -560,6 +560,7 @@ SpecDev 通过分层工件避免同一决策被多个模型反复重做。每个
560
560
  | Implementation Plan | `specdev/changes/{change}/implementation-plan.md` | 父 Lead、全局 workspace/实现上限、frontier/Wave/locks/integration queue 和可恢复进度投影 | 改写子 change 权威或伪造完成 |
561
561
  | Implementation Orchestration Evidence | `specdev/changes/{change}/evidence/implementation-orchestration.md` | 成员完成、组合 Ticket 顺序/锁、repository integration、整体验证、漂移和残余风险 | 新产品/架构决定或单 Ticket Evidence 替代品 |
562
562
  | Evidence | `specdev/changes/{change}/evidence/T-NN.md` | 实际修改、命令、结果、验收映射、偏差、风险和提交引用 | 新的产品或架构决策 |
563
+ | Change 学习图解 | `specdev/changes/{change}/learning/index.md` 与 `specdev/changes/{change}/learning/{number}_{topic}.md` | 面向零专业背景读者解释当前 change 的已验证工件、实现和测试事实;索引按序号持续追加 | 产品决定、架构决定、实现授权或 Learning workflow 知识 |
563
564
  | 代码审查 | `specdev/changes/{change}/reviews/CR-###.md` | 固定点、标准轴和规范轴 finding | 实施修复或合并两轴排名 |
564
565
  | UI 设计包 | `specdev/changes/{change}/prototypes/{design-id}/design-system.md`、`specdev/changes/{change}/prototypes/{design-id}/comparison/` 与 `specdev/changes/{change}/prototypes/{design-id}/final/` | 项目 UI 证据、功能风格候选、逐层用户决定、设计 token、交互合同和可运行 HTML/CSS/JS 投影 | 生产 UI 实现或替用户确认高影响偏好 |
565
566
  | Stakeholder 问卷 | `specdev/changes/{change}/questionnaires/{slug}.md` | 第三方原始回答和恢复条件 | 未经转录确认的产品/架构决定 |
@@ -378,6 +378,7 @@ SpecDev 通过分层工件避免同一决策被多个模型反复重做。每个
378
378
  | Implementation Plan | `specdev/changes/{change}/implementation-plan.md` | 父 Lead、全局 workspace/实现上限、frontier/Wave/locks/integration queue 和可恢复进度投影 | 改写子 change 权威或伪造完成 |
379
379
  | Implementation Orchestration Evidence | `specdev/changes/{change}/evidence/implementation-orchestration.md` | 成员完成、组合 Ticket 顺序/锁、repository integration、整体验证、漂移和残余风险 | 新产品/架构决定或单 Ticket Evidence 替代品 |
380
380
  | Evidence | `specdev/changes/{change}/evidence/T-NN.md` | 实际修改、命令、结果、验收映射、偏差、风险和提交引用 | 新的产品或架构决策 |
381
+ | Change 学习图解 | `specdev/changes/{change}/learning/index.md` 与 `specdev/changes/{change}/learning/{number}_{topic}.md` | 面向零专业背景读者解释当前 change 的已验证工件、实现和测试事实;索引按序号持续追加 | 产品决定、架构决定、实现授权或 Learning workflow 知识 |
381
382
  | 代码审查 | `specdev/changes/{change}/reviews/CR-###.md` | 固定点、标准轴和规范轴 finding | 实施修复或合并两轴排名 |
382
383
  | UI 设计包 | `specdev/changes/{change}/prototypes/{design-id}/design-system.md`、`specdev/changes/{change}/prototypes/{design-id}/comparison/` 与 `specdev/changes/{change}/prototypes/{design-id}/final/` | 项目 UI 证据、功能风格候选、逐层用户决定、设计 token、交互合同和可运行 HTML/CSS/JS 投影 | 生产 UI 实现或替用户确认高影响偏好 |
383
384
  | Stakeholder 问卷 | `specdev/changes/{change}/questionnaires/{slug}.md` | 第三方原始回答和恢复条件 | 未经转录确认的产品/架构决定 |
@@ -953,6 +953,7 @@ SpecDev 通过分层工件避免同一决策被多个模型反复重做。每个
953
953
  | Implementation Plan | `specdev/changes/{change}/implementation-plan.md` | 父 Lead、全局 workspace/实现上限、frontier/Wave/locks/integration queue 和可恢复进度投影 | 改写子 change 权威或伪造完成 |
954
954
  | Implementation Orchestration Evidence | `specdev/changes/{change}/evidence/implementation-orchestration.md` | 成员完成、组合 Ticket 顺序/锁、repository integration、整体验证、漂移和残余风险 | 新产品/架构决定或单 Ticket Evidence 替代品 |
955
955
  | Evidence | `specdev/changes/{change}/evidence/T-NN.md` | 实际修改、命令、结果、验收映射、偏差、风险和提交引用 | 新的产品或架构决策 |
956
+ | Change 学习图解 | `specdev/changes/{change}/learning/index.md` 与 `specdev/changes/{change}/learning/{number}_{topic}.md` | 面向零专业背景读者解释当前 change 的已验证工件、实现和测试事实;索引按序号持续追加 | 产品决定、架构决定、实现授权或 Learning workflow 知识 |
956
957
  | 代码审查 | `specdev/changes/{change}/reviews/CR-###.md` | 固定点、标准轴和规范轴 finding | 实施修复或合并两轴排名 |
957
958
  | UI 设计包 | `specdev/changes/{change}/prototypes/{design-id}/design-system.md`、`specdev/changes/{change}/prototypes/{design-id}/comparison/` 与 `specdev/changes/{change}/prototypes/{design-id}/final/` | 项目 UI 证据、功能风格候选、逐层用户决定、设计 token、交互合同和可运行 HTML/CSS/JS 投影 | 生产 UI 实现或替用户确认高影响偏好 |
958
959
  | Stakeholder 问卷 | `specdev/changes/{change}/questionnaires/{slug}.md` | 第三方原始回答和恢复条件 | 未经转录确认的产品/架构决定 |
@@ -369,6 +369,7 @@ SpecDev 通过分层工件避免同一决策被多个模型反复重做。每个
369
369
  | Implementation Plan | `specdev/changes/{change}/implementation-plan.md` | 父 Lead、全局 workspace/实现上限、frontier/Wave/locks/integration queue 和可恢复进度投影 | 改写子 change 权威或伪造完成 |
370
370
  | Implementation Orchestration Evidence | `specdev/changes/{change}/evidence/implementation-orchestration.md` | 成员完成、组合 Ticket 顺序/锁、repository integration、整体验证、漂移和残余风险 | 新产品/架构决定或单 Ticket Evidence 替代品 |
371
371
  | Evidence | `specdev/changes/{change}/evidence/T-NN.md` | 实际修改、命令、结果、验收映射、偏差、风险和提交引用 | 新的产品或架构决策 |
372
+ | Change 学习图解 | `specdev/changes/{change}/learning/index.md` 与 `specdev/changes/{change}/learning/{number}_{topic}.md` | 面向零专业背景读者解释当前 change 的已验证工件、实现和测试事实;索引按序号持续追加 | 产品决定、架构决定、实现授权或 Learning workflow 知识 |
372
373
  | 代码审查 | `specdev/changes/{change}/reviews/CR-###.md` | 固定点、标准轴和规范轴 finding | 实施修复或合并两轴排名 |
373
374
  | UI 设计包 | `specdev/changes/{change}/prototypes/{design-id}/design-system.md`、`specdev/changes/{change}/prototypes/{design-id}/comparison/` 与 `specdev/changes/{change}/prototypes/{design-id}/final/` | 项目 UI 证据、功能风格候选、逐层用户决定、设计 token、交互合同和可运行 HTML/CSS/JS 投影 | 生产 UI 实现或替用户确认高影响偏好 |
374
375
  | Stakeholder 问卷 | `specdev/changes/{change}/questionnaires/{slug}.md` | 第三方原始回答和恢复条件 | 未经转录确认的产品/架构决定 |
@@ -656,6 +656,7 @@ SpecDev 通过分层工件避免同一决策被多个模型反复重做。每个
656
656
  | Implementation Plan | `specdev/changes/{change}/implementation-plan.md` | 父 Lead、全局 workspace/实现上限、frontier/Wave/locks/integration queue 和可恢复进度投影 | 改写子 change 权威或伪造完成 |
657
657
  | Implementation Orchestration Evidence | `specdev/changes/{change}/evidence/implementation-orchestration.md` | 成员完成、组合 Ticket 顺序/锁、repository integration、整体验证、漂移和残余风险 | 新产品/架构决定或单 Ticket Evidence 替代品 |
658
658
  | Evidence | `specdev/changes/{change}/evidence/T-NN.md` | 实际修改、命令、结果、验收映射、偏差、风险和提交引用 | 新的产品或架构决策 |
659
+ | Change 学习图解 | `specdev/changes/{change}/learning/index.md` 与 `specdev/changes/{change}/learning/{number}_{topic}.md` | 面向零专业背景读者解释当前 change 的已验证工件、实现和测试事实;索引按序号持续追加 | 产品决定、架构决定、实现授权或 Learning workflow 知识 |
659
660
  | 代码审查 | `specdev/changes/{change}/reviews/CR-###.md` | 固定点、标准轴和规范轴 finding | 实施修复或合并两轴排名 |
660
661
  | UI 设计包 | `specdev/changes/{change}/prototypes/{design-id}/design-system.md`、`specdev/changes/{change}/prototypes/{design-id}/comparison/` 与 `specdev/changes/{change}/prototypes/{design-id}/final/` | 项目 UI 证据、功能风格候选、逐层用户决定、设计 token、交互合同和可运行 HTML/CSS/JS 投影 | 生产 UI 实现或替用户确认高影响偏好 |
661
662
  | Stakeholder 问卷 | `specdev/changes/{change}/questionnaires/{slug}.md` | 第三方原始回答和恢复条件 | 未经转录确认的产品/架构决定 |
@@ -0,0 +1,99 @@
1
+ ---
2
+ id: specdev/learn-change
3
+ type: workflow-entry
4
+ workflow: specdev
5
+ name: Change 学习
6
+ description: 在开发完成后围绕当前 SpecDev change 回答问题,并用面向零专业背景读者的 Markdown 与 ASCII 图解持续记录理解。
7
+ keywords: [learn-change, change 学习, 开发后提问, 零基础, 大一新生, Markdown, ASCII]
8
+ ---
9
+
10
+ # Change 学习:给零基础新生的图解
11
+
12
+ > 激活本 Work 后,先读取 `<Path>{roots.workflows}/specdev/README.md</Path>`,再执行本入口。
13
+
14
+ ## 读者与职责
15
+
16
+ 读者是刚入大学、没有专业背景(零专业背景)的新生。读者能理解日常因果和简单流程,但不应被假定知道代码、网络、数学或行业背景。
17
+
18
+ 本 Work 用于在 change 开发完成后回答与该 change 有关的问题。它只解释,不作产品决定、架构决定或实现授权;它把当前 change 中已验证的工件、实现和测试事实写成可恢复的 Markdown 图解。图比段落更先出现,文字只负责读懂图。
19
+
20
+ ```text
21
+ 已完成 change 的已验证事实
22
+ |
23
+ v
24
+ 用户关于 change 的问题
25
+ |
26
+ v
27
+ ASCII 全图 + 分步图 + 简短说明
28
+ |
29
+ v
30
+ learning/01_<topic>.md、02_<topic>.md、...
31
+ |
32
+ v
33
+ learning/index.md(图解目录)
34
+ ```
35
+
36
+ 主题:`$ARGUMENTS`
37
+
38
+ ## 输出格式
39
+
40
+ 在当前 change 的 `<Path>{roots.state}/specdev/changes/{change}/learning/</Path>` 内原子写入一份新的 `<Path>{roots.state}/specdev/changes/{change}/learning/{number}_{topic}.md</Path>`,并原子更新索引 `<Path>{roots.state}/specdev/changes/{change}/learning/index.md</Path>`。这些产物属于 SpecDev change,不写入 `<Path>{roots.state}/learning/</Path>`。文档必须是纯 Markdown,不生成 HTML、CSS、SVG、图片链接或浏览器专属交互。
41
+
42
+ `<number>` 是两位起始、持续递增的序号:先读取索引和同目录已有的图解文件,取最大序号加一,因此第一次为 `01`,下一次为 `02`;不为旧文件重编号。`<topic>` 是主题的简短、可作文件名的标签,可使用中文、字母、数字、`-` 或 `_`,但不能含空格、`/`、`\\` 或 `..`。同主题再次解释也创建新编号文件。
43
+
44
+ 索引是唯一目录,使用下列 Markdown 表格;每新增一份图解就在表末追加一行,并保留既有行。文件列只写同目录的文件名:
45
+
46
+ ```markdown
47
+ # Change 学习图解索引
48
+
49
+ | 编号 | 文件 | 主题 | 简介 |
50
+ | --- | --- | --- | --- |
51
+ | 01 | 01_<topic>.md | <主题> | <一句话说明它解释什么> |
52
+ ```
53
+
54
+ 按主题选择最贴切的图,但优先用多个短小 ASCII 图代替长文字:
55
+
56
+ ```text
57
+ 结构图:
58
+ [系统]
59
+ |
60
+ +-- [部件 A]
61
+ +-- [部件 B]
62
+
63
+ 数据流图:
64
+ [输入] -> [处理] -> [结果]
65
+
66
+ 调用流图:
67
+ [用户动作] -> [入口] -> [服务] -> [回应]
68
+
69
+ 状态变化图:
70
+ [等待] -> [进行中] -> [完成]
71
+ ```
72
+
73
+ 每份图解至少包含以下四节:
74
+
75
+ 1. `## 先看全图`:一个能说清“谁和谁有关”的 ASCII 图。
76
+ 2. `## 一步一步看`:按箭头顺序解释。流程、数据或调用会移动时,再给对应的 ASCII 图。
77
+ 3. `## 术语小词典`:只保留读图必需的词。每个词先用日常语言解释,再给它的专业名字。例如:`临时便签(缓存)`,意思是“把常用结果先放在手边,下一次不用重新找”。
78
+ 4. `## 你现在能复述什么`:用短句归纳“它是什么、为什么需要它、它怎样流动或被调用”。
79
+
80
+ 图中的方框名称使用普通名词和动词,不用缩写;箭头必须有方向。一个图只讲一个问题。确有边界、失败或例外时,单独画一张小图说明,不把它塞进主图。
81
+
82
+ ## 执行
83
+
84
+ 1. 按 `<Path>{roots.workflows}/specdev/README.md</Path>` 读取全局状态和当前 change 状态。只选择用户指定或唯一未归档的现有 change;没有可用 change 时说明必须先完成或指定一个 SpecDev change,不创建空 change。已归档 change 保持只读,不在归档目录追加学习产物。`current_work` 为空时设为 `specdev/learn-change`;若指向其他 Work,先完成显式交接。`change_status=completed` 不因本 Work 被重新打开为开发中。
85
+ 2. 将调用中的 `$ARGUMENTS` 解析为主题;直接提出的问题以用户最新消息为主题。主题缺失时只询问问题或主题,不猜测。先写下读者要带走的三个答案:它是什么、为什么需要它、它怎样流动或被调用。
86
+ 3. 按需读取当前 change 的 Source、Spec、Ticket、Evidence、review、项目实现、测试和可靠来源。区分已验证事实、便于理解的类比和未知处;实现事实与旧计划冲突时以当前代码、测试和 Evidence 为准,并显式指出差异。类比只能帮助理解,不能替代事实或掩盖边界。
87
+ 4. 先画 `先看全图`,再按实际关系补充结构图、数据流图、调用流图或状态变化图。每张图旁只用短句解释箭头;避免长段落、术语堆叠、缩写和先备知识。
88
+ 5. 首次使用术语时,先写日常解释,再在括号中给专业名字。读完后从读者角度检查:没有背景知识的人能否仅靠图和短句复述三个答案;若不能,拆图或替换术语,不增加大段说明。
89
+ 6. 读取 `<Path>{roots.state}/specdev/changes/{change}/learning/index.md</Path>` 和 `<Path>{roots.state}/specdev/changes/{change}/learning/</Path>` 内已有图解文件。从两者的最大序号计算下一个编号,先原子创建新的图解文件,再原子更新索引;不覆盖、重命名或重排已有图解。重读确认新文件是 Markdown,包含四个必需章节、至少一个 ASCII 图且没有 HTML 标记或图片依赖;索引的文件名、主题和简介都与新文件对应。
90
+ 7. 运行 `<Path>{roots.workflows}/specdev/common/tools/validate-specdev.mjs</Path>` 的 `--stage learn-change`。成功后把 `specdev/learn-change` 去重加入 `works_run`,清空 `current_work`,并返回新 Markdown 与索引的完整路径;失败时保留 `current_work` 和阻塞原因,便于恢复,但不改变 change 的开发完成状态。
91
+
92
+ ## 完成标准
93
+
94
+ - `<Path>{roots.state}/specdev/changes/{change}/learning/index.md</Path>` 存在,按序列出每份图解的编号、文件、主题和简介;每个文件名都对应同目录真实文件。
95
+ - 新的 `<Path>{roots.state}/specdev/changes/{change}/learning/{number}_{topic}.md</Path>` 存在,是纯 Markdown,并含有全部四个必需章节和至少一个 ASCII 图;编号比既有最大编号大一,旧文件未被重排或覆盖。
96
+ - 文档面向刚上大一、没有专业背景的读者;用图和短句回答当前 change 的问题,而不是把专业长文换成更简单的字。
97
+ - 图解覆盖主题需要的结构、数据流、调用流或状态变化;能画图的地方优先画图,且每张图的箭头方向与事实一致。
98
+ - 术语首次出现前有日常解释;类比不把读者带向相反结论;计划与最终实现的差异没有被隐藏。
99
+ - 状态已原子更新;所有学习产物只写入当前 SpecDev change 的 `learning/` namespace,没有修改项目代码、永久知识、Learning workflow state 或远程系统。
@@ -32,6 +32,8 @@ Implement 在既定契约内设计、TDD、审查、验证和交接
32
32
 
33
33
  Evidence 实际修改、命令、结果、偏差和残余风险
34
34
 
35
+ Learn Change 围绕已完成实现提问并追加零基础 Markdown / ASCII 图解(按需)
36
+
35
37
  Triage 本地完成后按确认回写/关闭支持的远程 Issue
36
38
 
37
39
  Archive 归档历史并将经验证知识提升为当前长期知识
@@ -58,8 +60,9 @@ Archive 归档历史并将经验证知识提升为当前长期知识
58
60
  - `<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/comparison/</Path>`
59
61
  - `<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/final/</Path>`
60
62
  - `<Path>{roots.state}/specdev/changes/{change}/questionnaires/</Path>`
63
+ - `<Path>{roots.state}/specdev/changes/{change}/learning/index.md</Path>` 与 `<Path>{roots.state}/specdev/changes/{change}/learning/{number}_{topic}.md</Path>`
61
64
 
62
- `{design-id}` 由 P-prototype 在当前 change 内分配为最小未占用的 `UI-NNN`;设计系统文档是设计权威,comparison 与 final 是其可运行投影。
65
+ `{design-id}` 由 P-prototype 在当前 change 内分配为最小未占用的 `UI-NNN`;设计系统文档是设计权威,comparison 与 final 是其可运行投影。`{number}` 与 `{topic}` 由 L-learn-change 根据已有学习索引和当前问题分配,不属于 Learning workflow 的知识编号。
63
66
 
64
67
  工件职责和冲突裁决位于 `<Path>{roots.workflows}/specdev/common/rules/artifact-contract.md</Path>`。
65
68
 
@@ -112,6 +115,7 @@ Archive 归档历史并将经验证知识提升为当前长期知识
112
115
  - `<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/comparison/</Path>`
113
116
  - `<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/final/</Path>`
114
117
  - `<Path>{roots.state}/specdev/changes/{change}/questionnaires/</Path>`
118
+ - `<Path>{roots.state}/specdev/changes/{change}/learning/index.md</Path>` 与 `<Path>{roots.state}/specdev/changes/{change}/learning/{number}_{topic}.md</Path>`
115
119
 
116
120
  ## 全局治理原则
117
121
 
@@ -207,6 +211,7 @@ Change 从 active/blocked 转为 completed 时加载 `<Path>{roots.workflows}/sp
207
211
  | 多 Ticket 协调 | P-goal-plan | I / Triage / A |
208
212
  | 多个 Ready change 的持续实现 | O-orchestrate-implementation | I-implement 循环 / completed / blocked |
209
213
  | Ready 执行 | I-implement | Triage / A / blocked / deviation |
214
+ | 开发完成后需要理解当前 change 或追问实现 | L-learn-change | 返回用户 / 继续提问 / Triage / A |
210
215
  | 架构健康扫描 | R-review-architecture | G / T |
211
216
 
212
217
  同 change 下一阶段需要当前一手推理且上下文健康时继续;切换 repo/person/harness 或旁路时使用 `<Path>{roots.commands}/handoff.md</Path>`;严格限定且可独立派单时使用 Dispatch Packet;其他长上下文以权威工件路径恢复。平台不支持 clear/compact 时不虚构操作。
@@ -221,6 +226,7 @@ Change 从 active/blocked 转为 completed 时加载 `<Path>{roots.workflows}/sp
221
226
  - **G-grill-with-docs** — 设计访谈(带文档):以完整 frontier 逐轮推进设计树,直到每个决策分支都已关闭并获得用户共识,同时持续维护当前 change 的设计树、日志、领域上下文和架构决策。
222
227
  - **I-implement** — 实现:基于 Ready Ticket 或获批小型 Spec 执行设计检查、TDD、动态派单、双轴审查、按 Goal Plan 选择的 current workspace 或 Ticket worktree 提交、直接父分支或候选合并验证和 Lead Evidence 回写。
223
228
  - **I-init-setup** — 初始化设置:初始化 SpecDev 的语言、配置、全局状态、本地 change 追踪、领域知识布局、验证命令和并发治理。
229
+ - **L-learn-change** — Change 学习:在开发完成后围绕当前 SpecDev change 回答问题,并用面向零专业背景读者的 Markdown 与 ASCII 图解持续记录理解。
224
230
  - **O-orchestrate-implementation** — 编排实现:将两个或以上已完成 Ready Spec 与 Ready Tickets 的 change 编译为跨 change implementation super-DAG,并由单一 Lead 在一个会话中持续调度实现、验证和集成。
225
231
  - **P-goal-plan** — 目标规划:在跨 Ticket 协调复杂度需要时,以固定 Lead、动态派单、DAG/Gate 和候选合并门禁生成决策完备且可恢复的执行计划。
226
232
  - **P-prototype** — UI 设计原型:检测现有项目的 UI 事实,按产品任务推荐并逐步选择设计风格,生成持久化设计系统文档、多风格 HTML 对照和可运行 HTML/CSS/JS 原型。
@@ -246,7 +252,7 @@ Change 从 active/blocked 转为 completed 时加载 `<Path>{roots.workflows}/sp
246
252
 
247
253
  ```bash
248
254
  node <Path>{roots.workflows}/specdev/common/tools/validate-specdev.mjs</Path> \
249
- --stage <triage|diagnosis|grill|eli5|spec|tickets|goal-plan|implement|review|prototype|wayfinder|complete> \
255
+ --stage <triage|diagnosis|grill|spec|tickets|goal-plan|implement|learn-change|review|prototype|wayfinder|orchestrate-implementation|complete> \
250
256
  <Path>{roots.state}/specdev/changes/{change}</Path>
251
257
  ```
252
258
 
@@ -21,6 +21,7 @@ SpecDev 通过分层工件避免同一决策被多个模型反复重做。每个
21
21
  | Implementation Plan | `<Path>{roots.state}/specdev/changes/{change}/implementation-plan.md</Path>` | 父 Lead、全局 workspace/实现上限、frontier/Wave/locks/integration queue 和可恢复进度投影 | 改写子 change 权威或伪造完成 |
22
22
  | Implementation Orchestration Evidence | `<Path>{roots.state}/specdev/changes/{change}/evidence/implementation-orchestration.md</Path>` | 成员完成、组合 Ticket 顺序/锁、repository integration、整体验证、漂移和残余风险 | 新产品/架构决定或单 Ticket Evidence 替代品 |
23
23
  | Evidence | `<Path>{roots.state}/specdev/changes/{change}/evidence/{ticket-id}.md</Path>` | 实际修改、命令、结果、验收映射、偏差、风险和提交引用 | 新的产品或架构决策 |
24
+ | Change 学习图解 | `<Path>{roots.state}/specdev/changes/{change}/learning/index.md</Path>` 与 `<Path>{roots.state}/specdev/changes/{change}/learning/{number}_{topic}.md</Path>` | 面向零专业背景读者解释当前 change 的已验证工件、实现和测试事实;索引按序号持续追加 | 产品决定、架构决定、实现授权或 Learning workflow 知识 |
24
25
  | 代码审查 | `<Path>{roots.state}/specdev/changes/{change}/reviews/CR-###.md</Path>` | 固定点、标准轴和规范轴 finding | 实施修复或合并两轴排名 |
25
26
  | UI 设计包 | `<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/design-system.md</Path>`、`<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/comparison/</Path>` 与 `<Path>{roots.state}/specdev/changes/{change}/prototypes/{design-id}/final/</Path>` | 项目 UI 证据、功能风格候选、逐层用户决定、设计 token、交互合同和可运行 HTML/CSS/JS 投影 | 生产 UI 实现或替用户确认高影响偏好 |
26
27
  | Stakeholder 问卷 | `<Path>{roots.state}/specdev/changes/{change}/questionnaires/{slug}.md</Path>` | 第三方原始回答和恢复条件 | 未经转录确认的产品/架构决定 |
@@ -4,7 +4,7 @@
4
4
 
5
5
  ```bash
6
6
  node <Path>{roots.workflows}/specdev/common/tools/validate-specdev.mjs</Path> \
7
- --stage <triage|diagnosis|grill|spec|tickets|goal-plan|implement|review|prototype|wayfinder|orchestrate-implementation|complete> \
7
+ --stage <triage|diagnosis|grill|spec|tickets|goal-plan|implement|learn-change|review|prototype|wayfinder|orchestrate-implementation|complete> \
8
8
  --repo <project-root> \
9
9
  <Path>{roots.state}/specdev/changes/{change}</Path>
10
10
  ```
@@ -11,6 +11,7 @@
11
11
 
12
12
  import {
13
13
  existsSync,
14
+ lstatSync,
14
15
  readFileSync,
15
16
  readdirSync,
16
17
  statSync,
@@ -40,6 +41,7 @@ const EXPECTED_WORKS = new Set([
40
41
  "G-grill-with-docs",
41
42
  "I-implement",
42
43
  "I-init-setup",
44
+ "L-learn-change",
43
45
  "O-orchestrate-implementation",
44
46
  "P-goal-plan",
45
47
  "P-prototype",
@@ -105,6 +107,7 @@ const VALID_STAGES = new Set([
105
107
  "tickets",
106
108
  "goal-plan",
107
109
  "implement",
110
+ "learn-change",
108
111
  "review",
109
112
  "prototype",
110
113
  "wayfinder",
@@ -873,6 +876,13 @@ function capabilityChecks(root) {
873
876
  ["设计定向", "风格", "design-system.md", "comparison", "HTML/CSS/JS", "design-library/INDEX.md"],
874
877
  ],
875
878
  ],
879
+ [
880
+ "learn-change",
881
+ [
882
+ join(root, "L-learn-change", "L-learn-change.md"),
883
+ ["开发完成后", "零专业背景", "$ARGUMENTS", "ASCII", "learning/index.md", "{number}_{topic}.md", "{roots.state}/learning/"],
884
+ ],
885
+ ],
876
886
  [
877
887
  "wayfinder",
878
888
  [
@@ -1332,6 +1342,100 @@ function validatePrototypes(change, required, errors) {
1332
1342
  return paths;
1333
1343
  }
1334
1344
 
1345
+ function validateChangeLearning(change, required, errors) {
1346
+ const learningRoot = join(change, "learning");
1347
+ const indexPath = join(learningRoot, "index.md");
1348
+ const diagramName = /^\d{2,}_[\p{L}\p{N}_-]+\.md$/u;
1349
+
1350
+ if (!existsSync(learningRoot)) {
1351
+ if (required) errors.push("learn-change stage requires learning/index.md");
1352
+ return null;
1353
+ }
1354
+ if (lstatSync(learningRoot).isSymbolicLink() || !isDirectory(learningRoot)) {
1355
+ errors.push("learning/: change learning directory must be a real directory");
1356
+ return null;
1357
+ }
1358
+
1359
+ const diagramFiles = [];
1360
+ for (const entry of readdirSync(learningRoot, { withFileTypes: true })) {
1361
+ if (entry.isSymbolicLink()) {
1362
+ errors.push(`learning/${entry.name}: learning artifacts must not be symlinks`);
1363
+ } else if (entry.isFile() && diagramName.test(entry.name)) {
1364
+ diagramFiles.push(entry.name);
1365
+ }
1366
+ }
1367
+ diagramFiles.sort();
1368
+
1369
+ if (!isFile(indexPath)) {
1370
+ errors.push("learn-change stage requires learning/index.md");
1371
+ return null;
1372
+ }
1373
+
1374
+ const index = readText(indexPath);
1375
+ if (!index.includes("# Change 学习图解索引")) {
1376
+ errors.push("learning/index.md: missing index heading");
1377
+ }
1378
+ const entries = Array.from(
1379
+ index.matchAll(/^\|\s*(\d{2,})\s*\|\s*([^|\s]+\.md)\s*\|\s*([^|]+)\|\s*([^|]+)\|\s*$/gm),
1380
+ );
1381
+ if (!entries.length && required) {
1382
+ errors.push("learning/index.md: requires at least one diagram entry");
1383
+ }
1384
+
1385
+ const indexedFiles = new Set();
1386
+ let previousNumber = 0;
1387
+ for (const entry of entries) {
1388
+ const [, number, fileName, topic, summary] = entry;
1389
+ const numericNumber = Number(number);
1390
+ if (!diagramName.test(fileName)) {
1391
+ errors.push(`learning/index.md: invalid diagram filename '${fileName}'`);
1392
+ continue;
1393
+ }
1394
+ if (numericNumber <= previousNumber) {
1395
+ errors.push("learning/index.md: diagram numbers must increase");
1396
+ }
1397
+ if (numericNumber !== previousNumber + 1) {
1398
+ errors.push("learning/index.md: diagram numbers must start at 01 and be continuous");
1399
+ }
1400
+ previousNumber = numericNumber;
1401
+ if (!fileName.startsWith(`${number}_`)) {
1402
+ errors.push(`learning/index.md: '${fileName}' must start with '${number}_'`);
1403
+ }
1404
+ if (!topic.trim() || !summary.trim()) {
1405
+ errors.push(`learning/index.md: '${fileName}' requires a topic and summary`);
1406
+ }
1407
+ indexedFiles.add(fileName);
1408
+ }
1409
+
1410
+ for (const fileName of diagramFiles) {
1411
+ if (!indexedFiles.has(fileName)) {
1412
+ errors.push(`learning/index.md: missing entry for '${fileName}'`);
1413
+ }
1414
+ }
1415
+ for (const fileName of indexedFiles) {
1416
+ if (!diagramFiles.includes(fileName)) {
1417
+ errors.push(`learning/index.md: '${fileName}' does not exist`);
1418
+ }
1419
+ }
1420
+
1421
+ for (const fileName of diagramFiles) {
1422
+ const markdown = readText(join(learningRoot, fileName));
1423
+ for (const heading of ["## 先看全图", "## 一步一步看", "## 术语小词典", "## 你现在能复述什么"]) {
1424
+ if (!markdown.includes(heading)) errors.push(`learning/${fileName}: missing '${heading}'`);
1425
+ }
1426
+ if (!/```(?:text)?\s*[\s\S]*?(?:->|\||\+--)[\s\S]*?```/.test(markdown)) {
1427
+ errors.push(`learning/${fileName}: requires an ASCII diagram in a fenced code block`);
1428
+ }
1429
+ if (
1430
+ /<\/?(?:html|head|body|svg|canvas|img|picture)\b/i.test(markdown) ||
1431
+ /!\[[^\]]*\]\([^)]+\)/.test(markdown)
1432
+ ) {
1433
+ errors.push(`learning/${fileName}: must be pure Markdown without HTML or image dependencies`);
1434
+ }
1435
+ }
1436
+ return indexPath;
1437
+ }
1438
+
1335
1439
  function validateSpec(path, errors, warnings) {
1336
1440
  if (!isFile(path)) {
1337
1441
  warnings.push("Spec is missing; contract traceability cannot be fully checked");
@@ -2625,6 +2729,7 @@ function validateChange(change, stage = null, repoRoot = null) {
2625
2729
  }
2626
2730
  validateReviews(change, stage === "review", errors);
2627
2731
  validatePrototypes(change, stage === "prototype", errors);
2732
+ validateChangeLearning(change, stage === "learn-change", errors);
2628
2733
 
2629
2734
  const specRequired = new Set(["spec", "tickets", "goal-plan", "implement", "complete"]).has(stage) && !isFile(join(change, "implementation-map.md"));
2630
2735
  const specPath = join(change, "spec.md");