@namewta/speculo 0.2.15 → 0.3.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.
- package/dist/src/index.js +8 -1
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
- package/template/canonical/README.md +1 -0
- package/template/canonical/canonical-specdev-grill-with-docs.md +36 -45
- package/template/canonical/canonical-specdev-spec.md +9 -7
- package/template/canonical/canonical-specdev-tickets.md +91 -45
- package/template/canonical/canonical-specdev-wayfinder.md +28 -30
- package/template/commands/archive-and-consolidate.md +3 -3
- package/template/commands/docs-sync.md +3 -5
- package/template/commands/handoff.md +16 -2
- package/template/commands/retro.md +6 -9
- package/template/commands/status.md +1 -1
- package/template/skills/agents-md-builder/references/claude-redirect.md +10 -14
- package/template/skills/agents-md-builder/references/manifest-discovery.md +1 -6
- package/template/skills/agents-md-builder/references/role-classification.md +0 -12
- package/template/skills/archive-and-consolidate/SKILL.md +1 -1
- package/template/skills/docs-sync/references/agents-contract.md +4 -4
- package/template/skills/github-npm-ops/references/failure-recovery.md +4 -16
- package/template/skills/github-npm-ops/references/preflight-checklist.md +7 -7
- package/template/skills/github-npm-ops/references/release-notes-injection.md +8 -8
- package/template/skills/github-npm-ops/references/troubleshooting-playbook.md +5 -19
- package/template/skills/github-npm-ops/references/version-bump-flow.md +8 -28
- package/template/skills/github-npm-ops/references/workflow-yaml-reference.md +8 -8
- package/template/skills/writing-great-skills/SKILL.md +2 -0
- package/template/workflows/person/M-mao-zedong-cognitive-os/_templates/mao-consultation-output-template.md +32 -0
- package/template/workflows/specdev/A-archive-and-consolidate/consolidation-rules.md +4 -2
- package/template/workflows/specdev/A-archive-and-consolidate/knowledge-graduation.md +1 -1
- package/template/workflows/specdev/D-diagnose-bugs/D-diagnose-bugs.md +2 -2
- package/template/workflows/specdev/D-diagnose-bugs/cleanup-postmortem.md +2 -2
- package/template/workflows/specdev/D-diagnose-bugs/feedback-loop-techniques.md +1 -1
- package/template/workflows/specdev/G-grill-with-docs/G-grill-with-docs.md +1 -5
- package/template/workflows/specdev/G-grill-with-docs/adr-format.md +2 -0
- package/template/workflows/specdev/G-grill-with-docs/domain-modeling-rules.md +3 -13
- package/template/workflows/specdev/I-implement/I-implement.md +3 -3
- package/template/workflows/specdev/I-implement/codebase-design-glossary.md +9 -9
- package/template/workflows/specdev/I-implement/tdd-examples.md +1 -1
- package/template/workflows/specdev/I-init-setup/I-init-setup.md +1 -1
- package/template/workflows/specdev/I-init-setup/domain-layout.md +18 -53
- package/template/workflows/specdev/I-init-setup/status-labels.md +4 -5
- package/template/workflows/specdev/I-init-setup/tracking-convention.md +22 -35
- package/template/workflows/specdev/INDEX.md +7 -1
- package/template/workflows/specdev/P-goal-plan/execution-sections.md +2 -2
- package/template/workflows/specdev/P-goal-plan/governance-sections.md +3 -3
- package/template/workflows/specdev/P-goal-plan/lead-orchestration-protocol.md +5 -8
- package/template/workflows/specdev/P-goal-plan/vision-sections.md +1 -1
- package/template/workflows/specdev/R-review-architecture/R-review-architecture.md +77 -0
- package/template/workflows/specdev/R-review-architecture/exploration-guide.md +103 -0
- package/template/workflows/specdev/R-review-architecture/html-report-template.md +124 -0
- package/template/workflows/specdev/T-tickets/T-tickets.md +4 -4
- package/template/workflows/specdev/W-wayfinder/W-wayfinder.md +14 -18
- package/template/workflows/specdev/common/dev-worktree/SKILL.md +16 -106
- package/template/workflows/specdev/common/handoff/SKILL.md +42 -0
- package/template/workflows/specdev/common/triage/OUT-OF-SCOPE.md +2 -2
- package/template/workflows/specdev/common/triage/SKILL.md +3 -3
- package/template/workflows/specdev/common/improve-codebase-architecture/HTML-REPORT.md +0 -125
- package/template/workflows/specdev/common/improve-codebase-architecture/SKILL.md +0 -66
|
@@ -15,14 +15,14 @@ git log origin/main..HEAD --oneline
|
|
|
15
15
|
git tag --sort=-version:refname | head -3
|
|
16
16
|
|
|
17
17
|
# 4. CHANGELOG 顶部 [Unreleased] 段落已写好本次内容
|
|
18
|
-
head -30
|
|
18
|
+
head -30 CHANGELOG.md
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
任意一项异常先解决再发版:工作区不干净 → 先提交,或调用 docs-sync 按其清洁契约处理;`[Unreleased]` 为空 → 先做 docs-sync。禁止用 stash 隐藏待发布改动。
|
|
22
22
|
|
|
23
23
|
## 1. 维护 CHANGELOG
|
|
24
24
|
|
|
25
|
-
`
|
|
25
|
+
`CHANGELOG.md` 顶部必须始终保留 `[Unreleased]` 段落。新版本发布时:
|
|
26
26
|
|
|
27
27
|
1. 把 `[Unreleased]` 内容**整段迁移**到新建的 `## [X.Y.Z] — YYYY-MM-DD` 标题下
|
|
28
28
|
2. 重新插入空的 `[Unreleased]` 段落
|
|
@@ -67,10 +67,10 @@ npm version 0.0.10 --no-git-tag-version
|
|
|
67
67
|
|
|
68
68
|
## 3. release commit(原子提交)
|
|
69
69
|
|
|
70
|
-
把 `package.json` + `
|
|
70
|
+
把 `package.json` + `CHANGELOG.md` 一并提交,使用 Conventional Commits 的 `chore(release):` 前缀。
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
|
-
git add package.json
|
|
73
|
+
git add package.json CHANGELOG.md
|
|
74
74
|
git commit -m "chore(release): v0.0.10" \
|
|
75
75
|
-m "迁移 [Unreleased] 段落到 0.0.10:<一两句关键变更摘要>"
|
|
76
76
|
```
|
|
@@ -129,33 +129,13 @@ gh run list --workflow release.yml --limit 3 \
|
|
|
129
129
|
6. Run tests
|
|
130
130
|
7. Build
|
|
131
131
|
8. **Verify bin entry**
|
|
132
|
-
9. **Extract release notes from
|
|
132
|
+
9. **Extract release notes from CHANGELOG.md** ← v1.1.0 新增
|
|
133
133
|
10. **Publish to npm**
|
|
134
134
|
11. **Create GitHub Release**
|
|
135
135
|
|
|
136
136
|
## 7. 三端验证
|
|
137
137
|
|
|
138
|
-
|
|
139
|
-
# 1. npm 包已上线(CDN 30–60 秒延迟)
|
|
140
|
-
npm view @scope/pkg version
|
|
141
|
-
npm view @scope/pkg dist-tags
|
|
142
|
-
|
|
143
|
-
# 2. GitHub Release 存在 + 正文非空
|
|
144
|
-
gh release view v0.0.10 --json name,tagName,isDraft,isPrerelease,body \
|
|
145
|
-
--jq '{name, tagName, isDraft, isPrerelease, body_length: (.body | length), body_preview: (.body | .[0:200])}'
|
|
146
|
-
|
|
147
|
-
# 3. workflow conclusion=success 且所有步骤 success
|
|
148
|
-
gh run view <run-id> --json conclusion,jobs \
|
|
149
|
-
--jq '{conclusion, steps: [.jobs[].steps[] | {name, conclusion}]}'
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
任一缺失视为发布残次品:
|
|
153
|
-
|
|
154
|
-
| 缺失项 | 修复 |
|
|
155
|
-
|--------|------|
|
|
156
|
-
| npm 包查不到 | 等 60 秒再查;仍无 → 看 workflow `Publish to npm` 步骤日志 |
|
|
157
|
-
| Release 正文为空 / 仅一行 Full Changelog | 跑 [release-notes-injection.md](release-notes-injection.md) §3 的事后修复 |
|
|
158
|
-
| workflow `Extract release notes` 失败 | CHANGELOG 标题与 tag 不匹配,核对 `## [X.Y.Z]` 是否存在 |
|
|
138
|
+
完整命令与判定见 [release-pipeline.md](release-pipeline.md) Phase 5(`npm view` / `gh release view` / `gh run view`)。任一缺失视为发布残次品;Release 正文为空时按 [release-notes-injection.md](release-notes-injection.md) 事后修复。
|
|
159
139
|
|
|
160
140
|
## 8. 失败回滚
|
|
161
141
|
|
|
@@ -187,7 +167,7 @@ notes_file="$(mktemp -t speculo-release-notes.XXXXXX)"
|
|
|
187
167
|
trap 'rm -f "$notes_file"' EXIT
|
|
188
168
|
|
|
189
169
|
# 抽取 CHANGELOG 段落
|
|
190
|
-
awk -v v="0.0.10" '...'
|
|
170
|
+
awk -v v="0.0.10" '...' CHANGELOG.md > "$notes_file"
|
|
191
171
|
|
|
192
172
|
# 手动创建 GitHub Release
|
|
193
173
|
gh release create v0.0.10 --notes-file "$notes_file" --latest
|
|
@@ -213,7 +193,7 @@ npm view @scope/pkg@0.0.10 version
|
|
|
213
193
|
```bash
|
|
214
194
|
# bump 到下一个补丁
|
|
215
195
|
npm version 0.0.11 --no-git-tag-version
|
|
216
|
-
git add package.json
|
|
196
|
+
git add package.json CHANGELOG.md
|
|
217
197
|
git commit -m "chore(release): v0.0.11"
|
|
218
198
|
git push origin main
|
|
219
199
|
git tag v0.0.11
|
|
@@ -52,7 +52,7 @@ jobs:
|
|
|
52
52
|
- name: Verify bin entry
|
|
53
53
|
run: node scripts/verify-bin.mjs
|
|
54
54
|
|
|
55
|
-
- name: Extract release notes from
|
|
55
|
+
- name: Extract release notes from CHANGELOG.md
|
|
56
56
|
run: |
|
|
57
57
|
VERSION="${GITHUB_REF_NAME#v}"
|
|
58
58
|
awk -v v="$VERSION" '
|
|
@@ -60,11 +60,11 @@ jobs:
|
|
|
60
60
|
found && /^## \[/ { exit }
|
|
61
61
|
found && /^---[[:space:]]*$/ { next }
|
|
62
62
|
found { print }
|
|
63
|
-
'
|
|
63
|
+
' CHANGELOG.md > release-notes.md
|
|
64
64
|
|
|
65
65
|
if [ ! -s release-notes.md ]; then
|
|
66
|
-
echo "::warning::
|
|
67
|
-
echo "See [
|
|
66
|
+
echo "::warning::CHANGELOG.md 中未找到 [$VERSION] 段落,回退到自动生成。"
|
|
67
|
+
echo "See [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/main/CHANGELOG.md) for details." > release-notes.md
|
|
68
68
|
fi
|
|
69
69
|
|
|
70
70
|
- name: Publish to npm
|
|
@@ -173,10 +173,10 @@ permissions:
|
|
|
173
173
|
|
|
174
174
|
CLI 包专有:确认 `dist/cli/index.js` 存在、有 shebang、可执行。防止 tsconfig 出问题导致产物不完整。
|
|
175
175
|
|
|
176
|
-
### Extract release notes from
|
|
176
|
+
### Extract release notes from CHANGELOG.md
|
|
177
177
|
|
|
178
178
|
```yaml
|
|
179
|
-
- name: Extract release notes from
|
|
179
|
+
- name: Extract release notes from CHANGELOG.md
|
|
180
180
|
run: |
|
|
181
181
|
VERSION="${GITHUB_REF_NAME#v}"
|
|
182
182
|
awk -v v="$VERSION" '
|
|
@@ -184,11 +184,11 @@ CLI 包专有:确认 `dist/cli/index.js` 存在、有 shebang、可执行。
|
|
|
184
184
|
found && /^## \[/ { exit }
|
|
185
185
|
found && /^---[[:space:]]*$/ { next }
|
|
186
186
|
found { print }
|
|
187
|
-
'
|
|
187
|
+
' CHANGELOG.md > release-notes.md
|
|
188
188
|
|
|
189
189
|
if [ ! -s release-notes.md ]; then
|
|
190
190
|
echo "::warning::..." >&2
|
|
191
|
-
echo "See [
|
|
191
|
+
echo "See [CHANGELOG.md](...) for details." > release-notes.md
|
|
192
192
|
fi
|
|
193
193
|
```
|
|
194
194
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 咨询输出:<问题一句话概括>
|
|
2
|
+
|
|
3
|
+
<!-- 由 deliver 阶段整合四阶段产物填写。保持教员第一人称,正文为连贯的咨询答复。 -->
|
|
4
|
+
|
|
5
|
+
## 答复
|
|
6
|
+
|
|
7
|
+
<!-- 连贯的第一人称咨询答复正文。五拍论证节奏可辨识:
|
|
8
|
+
拍1【破题】用定义或反问点出根本问题 → 拍2【切割】"不是A而是B"剥掉表象 →
|
|
9
|
+
拍3【定向】抓主要矛盾分清主次 → 拍4【点睛】落一句比喻/古语/史例 → 拍5【收尾】给方法+给信心 -->
|
|
10
|
+
|
|
11
|
+
<正文>
|
|
12
|
+
|
|
13
|
+
<!-- 收尾四动作(必须齐全,融入正文结尾):
|
|
14
|
+
1. 给方向——点明主要矛盾与战略判断
|
|
15
|
+
2. 给步骤——2–3 步具体行动,"一仗一仗打"
|
|
16
|
+
3. 给检验——如何验证,"做了再看"
|
|
17
|
+
4. 给信心——战略乐观,承认"道路是曲折的" -->
|
|
18
|
+
|
|
19
|
+
## 内在张力
|
|
20
|
+
|
|
21
|
+
<!-- 若答复涉及以下张力(理论与实践 / 群众路线与精英决策 / 持久与速决 / 团结与斗争),逐条坦诚标注处理方式;无则写"无"。 -->
|
|
22
|
+
|
|
23
|
+
- <张力名称>:<本次答复中如何处理>
|
|
24
|
+
|
|
25
|
+
## 引用索引
|
|
26
|
+
|
|
27
|
+
<!-- 每条引用一行。逐字直引加引号;概括转述标"转述"。篇目编号对应 books/src/NNN-*.md。 -->
|
|
28
|
+
|
|
29
|
+
| 引用 | 篇目 | 形式 |
|
|
30
|
+
|------|------|------|
|
|
31
|
+
| "<金句原文>" | 《篇目名》(NNN) | 直引 |
|
|
32
|
+
| <概括内容> | 《篇目名》 | 转述 |
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
### 内容格式
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
永久库 ADR 与变更内 ADR(`<Path>{roots.workflows}/specdev/G-grill-with-docs/adr-format.md</Path>` 的 `## NNNN: 标题` 段落格式)格式不同——永久库使用独立文件与结构化字段:
|
|
18
18
|
|
|
19
19
|
```markdown
|
|
20
20
|
# ADR-NNNN: {标题}
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
- **后果**:{这个决策带来的影响,正面和负面}
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
从变更内 ADR 提升时:标题取 `## NNNN: {标题}` 中的标题文本,正文扩写为上述五字段;来源 change 与原编号写入「决策上下文」。
|
|
30
|
+
|
|
29
31
|
### Supersede 处理
|
|
30
32
|
|
|
31
33
|
若新 ADR 取代旧 ADR,在旧 ADR 文件**开头**添加横幅:
|
|
@@ -38,7 +40,7 @@
|
|
|
38
40
|
|
|
39
41
|
### 从 LOG 提升
|
|
40
42
|
|
|
41
|
-
若变更的 `LOG.md` 中存在 `LOG-XXXX: accepted` 条目,其结论满足 ADR
|
|
43
|
+
若变更的 `LOG.md` 中存在 `LOG-XXXX: accepted` 条目,其结论满足 ADR 三条件(难以逆转 + 令人意外 + 真实权衡)但未正式记录为 ADR,则:
|
|
42
44
|
|
|
43
45
|
1. 创建正式 ADR 文件
|
|
44
46
|
2. 在 Context 中注明"从 `<change-name>` 的 LOG-XXXX 提升"
|
|
@@ -41,7 +41,7 @@ specdev 每个变更遵循三文件模型(参见 `<Path>{roots.workflows}/spec
|
|
|
41
41
|
|
|
42
42
|
| 来源文件 | 知识类型 | 判定特征 | 目标知识库 |
|
|
43
43
|
|---------|---------|---------|-----------|
|
|
44
|
-
| **ADR.md** | 架构决策 | `## NNNN: Title`
|
|
44
|
+
| **ADR.md** | 架构决策 | `## NNNN: Title` 条目,满足三条件(难以逆转 + 令人意外 + 真实权衡) | `<Path>{roots.state}/specdev/adr/</Path>` |
|
|
45
45
|
| **CONTEXT.md** | 领域术语 | `**术语名**:定义` + `_Avoid_` 条目,项目特有概念 | `<Path>{roots.state}/specdev/context/</Path>` |
|
|
46
46
|
| **LOG.md** | 设计决策 | `LOG-XXXX: accepted` 条目,满足 ADR 三条件但未正式记录 → 提升为 ADR | `<Path>{roots.state}/specdev/adr/</Path>` |
|
|
47
47
|
| **research/** | 研究产物 | 跨变更相关的研究发现(>1 变更引用或覆盖共享技术栈) | `<Path>{roots.state}/specdev/research/</Path>` |
|
|
@@ -16,7 +16,7 @@ keywords: [诊断, 调试, bug, 反馈回路, 假设, 根因分析]
|
|
|
16
16
|
- **CONTEXT.md** —— 项目领域术语与概念:`<Path>{roots.state}/specdev/changes/{change}/CONTEXT.md</Path>`
|
|
17
17
|
- **ADR.md** —— 架构决策记录:`<Path>{roots.state}/specdev/changes/{change}/ADR.md</Path>`
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
如果这些文件不存在,静默继续——诊断不依赖设计文档,缺失的 change 在需要记录结论时按 `<Path>{roots.workflows}/specdev/INDEX.md</Path>` 启动协议创建。需要建立完整设计上下文时,运行 `<Path>{roots.workflows}/specdev/G-grill-with-docs/G-grill-with-docs.md</Path>`。
|
|
20
20
|
|
|
21
21
|
## 流程
|
|
22
22
|
|
|
@@ -60,7 +60,7 @@ keywords: [诊断, 调试, bug, 反馈回路, 假设, 根因分析]
|
|
|
60
60
|
- **最小复现场景**——阶段 3 产出的最小化复现,可直接转为回归测试
|
|
61
61
|
- **建议的修复接缝**——在哪个模块/接口处修复最合适
|
|
62
62
|
|
|
63
|
-
修复、回归测试编写和提交由 I-implement
|
|
63
|
+
修复、回归测试编写和提交由 I-implement 完成。如果不存在正确的测试接缝,将此发现记录到 `<Path>{roots.state}/specdev/changes/{change}/LOG.md</Path>` 并在步骤 7 的事后分析中提出架构改进建议。
|
|
64
64
|
|
|
65
65
|
**完成标准**:I-implement 已启动,根因描述、最小复现、建议修复接缝已移交。
|
|
66
66
|
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
|
|
30
30
|
问:什么本可以预防这个 bug?从以下维度审视:
|
|
31
31
|
|
|
32
|
-
-
|
|
32
|
+
- **测试接缝**——是否缺少合适的测试接缝?如果有好的接缝,此 bug 是否会被更早发现?
|
|
33
33
|
- **接口设计**——接口是否暴露了容易误用的契约?深度是否足够防止调用者犯错?
|
|
34
34
|
- **数据边界**——是否缺少输入校验、类型约束或边界条件处理?
|
|
35
35
|
- **耦合**——是否因模块间的隐藏耦合导致变更的连锁反应?
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
如果答案涉及架构变更(没有好的测试接缝、纠缠的调用者、隐藏的耦合),将具体情况记录到 LOG.md 的预防建议中。在修复之后提出建议——此时比诊断开始时拥有更多信息。
|
|
@@ -36,11 +36,7 @@ keywords: [设计, 访谈, 领域建模, ADR, 决策记录, 词汇表, 设计轨
|
|
|
36
36
|
|
|
37
37
|
### 3. 捕获文档
|
|
38
38
|
|
|
39
|
-
委托给 `<Path>{roots.workflows}/specdev/G-grill-with-docs/domain-modeling-rules.md</Path
|
|
40
|
-
|
|
41
|
-
- `<Path>{roots.state}/specdev/changes/{change}/LOG.md</Path>` 同步所有结论
|
|
42
|
-
- `<Path>{roots.state}/specdev/changes/{change}/CONTEXT.md</Path>` 精炼术语定义
|
|
43
|
-
- `<Path>{roots.state}/specdev/changes/{change}/ADR.md</Path>` 仅追加满足三条件的架构决策(参见 `<Path>{roots.workflows}/specdev/G-grill-with-docs/adr-format.md</Path>`)
|
|
39
|
+
委托给 `<Path>{roots.workflows}/specdev/G-grill-with-docs/domain-modeling-rules.md</Path>`。对照词汇表挑战术语、精炼模糊语言、讨论具体场景、与代码交叉引用。三文件按 grilling-protocol 规定的顺序同步(LOG → CONTEXT → ADR)。
|
|
44
40
|
|
|
45
41
|
**完成标准**:LOG.md 已同步所有结论;CONTEXT.md 已精炼术语;ADR.md 已追加满足三条件的架构决策。
|
|
46
42
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
所有架构决策记录存放在变更目录的单一 `<Path>{roots.state}/specdev/changes/{change}/ADR.md</Path>` 文件中。不使用 `docs/adr/` 目录下的编号文件,所有决策在一个文件内按二级标题分段。
|
|
4
4
|
|
|
5
|
+
> 变更内格式为 `## NNNN: 标题` 段落。经 `A-archive-and-consolidate` 提升到永久库 `<Path>{roots.state}/specdev/adr/</Path>` 后,转为独立文件 `# ADR-NNNN: 标题` + 结构化字段(见 consolidation-rules)。
|
|
6
|
+
|
|
5
7
|
## 模板
|
|
6
8
|
|
|
7
9
|
```md
|
|
@@ -43,11 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
### 维护规则
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
- 后续确认改变既有结论时,直接修订原日志条目,并记录替代关系,不保留互相矛盾的"现行规则"。
|
|
48
|
-
- 日志可以记录具体交互和边界场景;词汇表保持精炼;ADR 只记录难以逆转、令人意外且存在真实权衡的决定。
|
|
49
|
-
- 每个日志条目应关联对应的 ADR(如有):`Related: ADR-XXXX`。
|
|
50
|
-
- 状态为 `deferred` 的条目保留,以便后续恢复讨论时知道从什么问题开始。
|
|
46
|
+
完整维护规则(状态、修订、关联 ADR)见 `<Path>{roots.workflows}/specdev/G-grill-with-docs/log-format.md</Path>` 模板内的「维护规则」块;本文件只规定同步时机:每次完成设计问答后立即同步,不批量延后。
|
|
51
47
|
|
|
52
48
|
## 及时更新 CONTEXT.md
|
|
53
49
|
|
|
@@ -64,7 +60,7 @@
|
|
|
64
60
|
|
|
65
61
|
仅在以下三个条件全部满足时才向 `ADR.md` 追加一条决策记录:
|
|
66
62
|
|
|
67
|
-
1.
|
|
63
|
+
1. **难以逆转**——以后改变主意的成本是实质性的
|
|
68
64
|
2. **没有上下文会令人惊讶**——未来的读者会疑惑"他们为什么这样做?"
|
|
69
65
|
3. **真实权衡的结果**——存在真正的替代方案,你出于特定原因选择了一个
|
|
70
66
|
|
|
@@ -84,10 +80,4 @@
|
|
|
84
80
|
|
|
85
81
|
## 三文件同步规则
|
|
86
82
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
1. **LOG.md** 先更新——立即追加日志条目,记录本次讨论的结论
|
|
90
|
-
2. **CONTEXT.md** 随后更新——从日志中提取新术语或修正的术语定义
|
|
91
|
-
3. **ADR.md** 最后更新——检查是否需要满足三条件追加 ADC(架构决策记录)
|
|
92
|
-
|
|
93
|
-
如果 CONTEXT 或 ADR 的更新来自日志条目,在日志中补充 `Related: ADR-XXXX` 的关联标注。
|
|
83
|
+
访谈中每完成一轮设计问答,按顺序同步:LOG.md → CONTEXT.md → ADR.md。完整时机与触发条件见 `<Path>{roots.workflows}/specdev/G-grill-with-docs/grilling-protocol.md</Path>`「访谈中维护三文件」。
|
|
@@ -19,7 +19,7 @@ keywords: [实现, TDD, 代码审查, 模块设计, 重构]
|
|
|
19
19
|
- **永久 ADR** —— 已确认并提升到永久的架构决策,始终反映项目当前架构现状:`<Path>{roots.state}/specdev/adr/</Path>`
|
|
20
20
|
- **永久 CONTEXT** —— 已确认并提升到永久的领域词汇表,始终反映项目当前领域术语现状:`<Path>{roots.state}/specdev/context/</Path>`
|
|
21
21
|
|
|
22
|
-
如果当前 change 下的 CONTEXT.md 或 ADR.md 不存在,先运行 `<Path>{roots.workflows}/specdev/
|
|
22
|
+
如果当前 change 下的 CONTEXT.md 或 ADR.md 不存在,先运行 `<Path>{roots.workflows}/specdev/G-grill-with-docs/G-grill-with-docs.md</Path>` 或询问用户以建立上下文。永久 ADR 和 CONTEXT 目录可能为空——静默继续,不影响后续流程。
|
|
23
23
|
|
|
24
24
|
## 流程
|
|
25
25
|
|
|
@@ -65,8 +65,8 @@ keywords: [实现, TDD, 代码审查, 模块设计, 重构]
|
|
|
65
65
|
|
|
66
66
|
### 4. 提交
|
|
67
67
|
|
|
68
|
-
1.
|
|
69
|
-
2.
|
|
68
|
+
1. 运行项目自身的类型/静态检查命令——从项目脚本(package.json scripts、Makefile、CI 配置等)探测,不确定时询问用户
|
|
69
|
+
2. 运行项目自身的完整测试套件命令——探测方式同上
|
|
70
70
|
3. 将更改提交到当前分支:`git add -A && git commit -m "<描述性提交信息>"`
|
|
71
71
|
4. 更新 `<Path>{roots.state}/specdev/changes/{change}/</Path>` 下的状态文件
|
|
72
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 代码仓设计
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
设计**深层模块**:通过一个小接口承载大量行为,放置在干净的接缝处,可通过该接口进行测试。在任何设计或重构代码的地方使用这些语言和原则。目标是为调用者提供杠杆效应,为维护者提供局部性,为所有人提供可测试性。
|
|
4
4
|
|
|
5
5
|
## 术语表
|
|
6
6
|
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
|
|
11
11
|
**Interface(接口)** — 调用者正确使用模块所需了解的一切:类型签名,还包括不变量、顺序约束、错误模式、必需配置和性能特征。_避免使用_:API、signature(太窄 — 它们仅指类型层面的表面)。
|
|
12
12
|
|
|
13
|
-
**Implementation(实现)** — 模块内部的内容,它的代码体。区别于 **Adapter(适配器)**:一个东西可以是一个小适配器加一个大实现(Postgres
|
|
13
|
+
**Implementation(实现)** — 模块内部的内容,它的代码体。区别于 **Adapter(适配器)**:一个东西可以是一个小适配器加一个大实现(Postgres 仓库),也可以是一个大适配器加一个小实现(内存假实现)。当讨论接缝时用 "adapter";否则用 "implementation"。
|
|
14
14
|
|
|
15
15
|
**Depth(深度)** — 接口处的杠杆效应:调用者(或测试)每学习一个单位的接口可以驱动的行为量。当大量行为隐藏在小接口后面时,模块是**深层的**;当接口几乎和实现一样复杂时,模块是**浅层的**。
|
|
16
16
|
|
|
17
|
-
**Seam
|
|
17
|
+
**Seam(接缝)** _(Michael Feathers)_ — 一个可以在不编辑该位置的情况下改变行为的地方;模块接口所在的*位置*。接缝放在哪里本身就是一个设计决策,与接缝后面放什么不同。_避免使用_:boundary(与 DDD 的有界上下文重载)。
|
|
18
18
|
|
|
19
|
-
**Adapter(适配器)** —
|
|
19
|
+
**Adapter(适配器)** — 在接缝处满足接口的具体事物。描述的是*角色*(它填充哪个槽位),而非实质(内部是什么)。
|
|
20
20
|
|
|
21
21
|
**Leverage(杠杆效应)** — 调用者从深度中获得的好处:每学习一个单位的接口获得更多的能力。一个实现为 N 个调用点和 M 个测试带来回报。
|
|
22
22
|
|
|
@@ -54,10 +54,10 @@
|
|
|
54
54
|
|
|
55
55
|
## 原则
|
|
56
56
|
|
|
57
|
-
- **深度是接口的属性,而非实现的属性。** 一个深层模块内部可以由小型、可模拟、可替换的部分组成 —
|
|
57
|
+
- **深度是接口的属性,而非实现的属性。** 一个深层模块内部可以由小型、可模拟、可替换的部分组成 — 只是它们不属于接口的一部分。一个模块可以拥有**内部接缝**(对其实现私有,用于其自身测试)以及位于其接口处的**外部接缝**。
|
|
58
58
|
- **删除测试。** 想象删除这个模块。如果复杂性消失,它就是个透传层。如果复杂性在 N 个调用者中重新出现,它就在发挥价值。
|
|
59
|
-
- **接口就是测试表面。**
|
|
60
|
-
-
|
|
59
|
+
- **接口就是测试表面。** 调用者和测试穿过同一个接缝。如果你想测试接口_之外_的内容,模块可能形状不对。
|
|
60
|
+
- **一个适配器意味着假设的接缝。两个适配器意味着真实的接缝。** 除非有东西确实在接缝两侧变化,否则不要引入接缝。
|
|
61
61
|
|
|
62
62
|
## 为可测试性而设计
|
|
63
63
|
|
|
@@ -105,5 +105,5 @@
|
|
|
105
105
|
|
|
106
106
|
## 深入阅读
|
|
107
107
|
|
|
108
|
-
- **给定依赖的情况下深化一个集群** — 见 `<Path>{roots.workflows}/specdev/I-implement/deepening.md</Path
|
|
109
|
-
- **探索替代接口** — 见 `<Path>{roots.workflows}/specdev/I-implement/design-it-twice.md</Path>`:启动并行子 agent
|
|
108
|
+
- **给定依赖的情况下深化一个集群** — 见 `<Path>{roots.workflows}/specdev/I-implement/deepening.md</Path>`:依赖类别、接缝规程、以及替换而非分层的测试。
|
|
109
|
+
- **探索替代接口** — 见 `<Path>{roots.workflows}/specdev/I-implement/design-it-twice.md</Path>`:启动并行子 agent,以几种截然不同的方式设计接口,然后在深度、局部性和接缝位置上进行比较。
|
|
@@ -80,7 +80,7 @@ specdev 使用五个标准状态角色来追踪工作项的生命周期:
|
|
|
80
80
|
| `ready-for-human` | `ready-for-human` | 需人工处理 |
|
|
81
81
|
| `wontfix` | `wontfix` | 不处理 |
|
|
82
82
|
|
|
83
|
-
当 `T-
|
|
83
|
+
当 `T-triage` 分诊外部 issue 时,会将工作项移过一个状态机——需要评估、等待补充、可供 agent 领取、需人工处理、或不予处理。状态标签是这些状态在持久化文件中的字符串表示。默认每个角色的标签等于其名称,如果你的项目已有不同命名习惯,可以在此映射。
|
|
84
84
|
|
|
85
85
|
确认用户是否接受默认标签,或需要覆盖为自定义字符串。将映射写入 `<Path>{roots.state}/specdev/.config/status-labels.md</Path>`。
|
|
86
86
|
|
|
@@ -8,16 +8,18 @@ specdev 使用单上下文布局——整个 workflow 共享一套领域术语
|
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
{state_root}/changes/<change>/
|
|
11
|
-
├── CONTEXT.md
|
|
12
|
-
├── ADR.md
|
|
13
|
-
└── LOG.md
|
|
11
|
+
├── CONTEXT.md ← 领域词汇表
|
|
12
|
+
├── ADR.md ← 本变更相关的架构决策记录
|
|
13
|
+
└── LOG.md ← 设计决策日志
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
- **ADR.md** —— 记录本变更范围内的架构决策(格式:`## ADR-NNNN: 标题`)。如果变更跨多个上下文,决策记录在触发该决策的变更目录下。
|
|
18
|
-
- **LOG.md** —— 按时间倒序记录每次设计调整、决策变更及其原因。格式:`## YYYY-MM-DD HH:MM — 标题`,每次记录包含:**决策**(做什么)、**原因**(为什么)、**影响**(影响哪些 work/文件)。
|
|
16
|
+
三个文件的权威格式由 `G-grill-with-docs` 定义,本文件不重复:
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
- **CONTEXT.md** —— 格式见 `<Path>{roots.workflows}/specdev/G-grill-with-docs/context-format.md</Path>`(规范术语 + `_Avoid_` 同义词列表)
|
|
19
|
+
- **ADR.md** —— 格式见 `<Path>{roots.workflows}/specdev/G-grill-with-docs/adr-format.md</Path>`(单文件、`## NNNN: 标题` 分段)
|
|
20
|
+
- **LOG.md** —— 格式见 `<Path>{roots.workflows}/specdev/G-grill-with-docs/log-format.md</Path>`(`## LOG-XXXX` 编号条目、文件末尾追加)
|
|
21
|
+
|
|
22
|
+
> specdev 将变更内领域文档限定在 `changes/<change>/` 目录内。经确认后的 ADR/CONTEXT 由 `A-archive-and-consolidate` 提升到永久目录 `{roots.state}/specdev/adr/` 与 `{roots.state}/specdev/context/`,始终反映项目当前现状。
|
|
21
23
|
|
|
22
24
|
## 路径解析规则
|
|
23
25
|
|
|
@@ -27,64 +29,27 @@ specdev 使用单上下文布局——整个 workflow 共享一套领域术语
|
|
|
27
29
|
- `ADR.md` → `{state_root}/changes/<current_change>/ADR.md`
|
|
28
30
|
- `LOG.md` → `{state_root}/changes/<current_change>/LOG.md`
|
|
29
31
|
- `{state_root}` 由 runtime-context 解析为 `{roots.state}/specdev/`
|
|
30
|
-
- `<current_change>`
|
|
32
|
+
- `<current_change>` 按 INDEX 启动协议从 `status.json` 的 `active` 数组确定
|
|
31
33
|
|
|
32
34
|
## 在探索之前
|
|
33
35
|
|
|
34
36
|
当 specdev work 需要领域上下文时,按以下顺序读取:
|
|
35
37
|
|
|
36
|
-
1.
|
|
37
|
-
2. **`
|
|
38
|
-
3. **`
|
|
38
|
+
1. **永久目录**(若存在)—— `{state_root}/context/` 与 `{state_root}/adr/`,反映项目当前现状
|
|
39
|
+
2. **`CONTEXT.md`**(当前变更目录内)—— 本变更的领域语言
|
|
40
|
+
3. **`ADR.md`**(当前变更目录内)—— 涉及当前变更的架构决策
|
|
41
|
+
4. **`LOG.md`**(当前变更目录内)—— 设计决策历史
|
|
39
42
|
|
|
40
|
-
如果这些文件都不存在,静默继续。不要标记它们的缺失或预先建议创建。`G-grill-with-docs`
|
|
43
|
+
如果这些文件都不存在,静默继续。不要标记它们的缺失或预先建议创建。`G-grill-with-docs` 在领域知识或决策实际被确定时延迟创建它们。
|
|
41
44
|
|
|
42
45
|
## 使用术语表的词汇
|
|
43
46
|
|
|
44
|
-
输出中命名领域概念时,使用 `CONTEXT.md`
|
|
45
|
-
|
|
46
|
-
如果 `CONTEXT.md` 不存在,在首次需要时由当前 work 创建骨架:
|
|
47
|
-
|
|
48
|
-
```markdown
|
|
49
|
-
# CONTEXT — <change 主题>
|
|
50
|
-
|
|
51
|
-
## 领域术语
|
|
52
|
-
|
|
53
|
-
| 术语 | 定义 | 别名 / 避免使用 |
|
|
54
|
-
|------|------|----------------|
|
|
55
|
-
| ... | ... | ... |
|
|
56
|
-
|
|
57
|
-
## 边界上下文
|
|
58
|
-
|
|
59
|
-
<!-- 如有多个子域,在此划分边界 -->
|
|
60
|
-
```
|
|
47
|
+
输出中命名领域概念时,使用 `CONTEXT.md` 中定义的术语,不偏离到 `_Avoid_` 列表明确避免的同义词。如果需要的新概念尚未在术语表中,按 context-format 的增删改操作记录到 `CONTEXT.md` 并通知用户。
|
|
61
48
|
|
|
62
49
|
## 标记 ADR 冲突
|
|
63
50
|
|
|
64
51
|
如果输出与现有 ADR 矛盾,明确提出而不是默默覆盖:
|
|
65
52
|
|
|
66
|
-
> _与
|
|
67
|
-
|
|
68
|
-
同时将冲突记录追加到 `LOG.md`:
|
|
69
|
-
|
|
70
|
-
```markdown
|
|
71
|
-
## YYYY-MM-DD HH:MM — ADR 冲突标记
|
|
72
|
-
|
|
73
|
-
- **冲突**: 当前建议与 ADR-NNNN 矛盾
|
|
74
|
-
- **原因**: <重新讨论的理由>
|
|
75
|
-
- **影响**: 如采纳新方案,需更新 ADR.md 并记录迁移路径
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## 写入 LOG.md
|
|
79
|
-
|
|
80
|
-
每次设计调整或决策变更时,在 `LOG.md` 顶部追加一条记录(时间倒序):
|
|
81
|
-
|
|
82
|
-
```markdown
|
|
83
|
-
## YYYY-MM-DD HH:MM — <简短标题>
|
|
84
|
-
|
|
85
|
-
- **决策**: <做了什么设计决定>
|
|
86
|
-
- **原因**: <为什么做这个决定>
|
|
87
|
-
- **影响**: <影响哪些 work、哪些文件、哪些后续步骤>
|
|
88
|
-
```
|
|
53
|
+
> _与 ADR NNNN 矛盾 — 但值得重新讨论,因为……_
|
|
89
54
|
|
|
90
|
-
`LOG.md`
|
|
55
|
+
同时按 log-format 在 `LOG.md` 末尾追加一条日志条目(状态 `deferred`)记录冲突内容与重新讨论的理由;如采纳新方案,按 adr-format 的修改规则更新对应 ADR 状态。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 状态标签
|
|
2
2
|
|
|
3
|
-
specdev
|
|
3
|
+
specdev 的 issue 分诊(`T-triage` 及 `common/triage` skill)使用五种规范的状态角色来追踪工作项的生命周期。本文件将这些角色映射到持久化文件中使用的实际标签字符串。
|
|
4
4
|
|
|
5
5
|
| 角色 | 标签 | 含义 |
|
|
6
6
|
|------|------|------|
|
|
@@ -16,9 +16,8 @@ specdev 各 work 使用五种规范的状态角色来追踪工作项的生命周
|
|
|
16
16
|
|
|
17
17
|
标签字符串写入位置取决于具体 work:
|
|
18
18
|
|
|
19
|
-
- **T-
|
|
20
|
-
- **
|
|
21
|
-
- **其他 work** —— 在变更目录的相应产物文件中以 frontmatter 或元数据行形式记录
|
|
19
|
+
- **T-triage** —— 写入变更目录 `triage.md` 的推荐 status 字段(参见 T-triage 步骤 4)
|
|
20
|
+
- **其他 work** —— 引用这些角色时,在变更目录的相应产物文件中以元数据行形式记录
|
|
22
21
|
|
|
23
22
|
## 状态流转
|
|
24
23
|
|
|
@@ -51,4 +50,4 @@ needs-triage ──→ needs-info ──→ needs-triage ──→ ready-for-age
|
|
|
51
50
|
| `ready-for-human` | `需人工` |
|
|
52
51
|
| `wontfix` | `不处理` |
|
|
53
52
|
|
|
54
|
-
确保标签字符串在实际使用位置(
|
|
53
|
+
确保标签字符串在实际使用位置(triage.md 等产物文件)保持一致。
|
|
@@ -6,37 +6,24 @@ specdev workflow 的变更以 markdown 目录形式存储在 `{roots.state}/spec
|
|
|
6
6
|
|
|
7
7
|
- 每个变更一个目录:`{roots.state}/specdev/changes/<YYYY-MM-DD>-<topic>/`
|
|
8
8
|
- 例如:`changes/2026-07-21-add-auth-layer/`
|
|
9
|
-
- 当前活跃变更通过 `{roots.state}/specdev/status.json` 的 `active` 数组追踪,每个条目为包含 `change`、`current_work`、`works_run`、`result`
|
|
9
|
+
- 当前活跃变更通过 `{roots.state}/specdev/status.json` 的 `active` 数组追踪,每个条目为包含 `change`、`current_work`、`works_run`、`result` 等字段的对象——完整字段定义见 `<Path>{roots.workflows}/specdev/INDEX.md</Path>` 的「状态字段」一节,此处不重复
|
|
10
10
|
- 归档变更移至:`{roots.state}/specdev/archive/YYYY-MM/<change>/`
|
|
11
11
|
- 例如:`archive/2026-07/2026-07-21-add-auth-layer/`
|
|
12
12
|
- 变更目录内的工作产物由各 work 定义,典型结构:
|
|
13
13
|
```
|
|
14
14
|
changes/<YYYY-MM-DD>-<topic>/
|
|
15
|
-
├──
|
|
16
|
-
├──
|
|
17
|
-
├──
|
|
18
|
-
├──
|
|
19
|
-
├──
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"schema_version": 2,
|
|
28
|
-
"workflow": "specdev",
|
|
29
|
-
"active": [
|
|
30
|
-
{
|
|
31
|
-
"change": "2026-07-21-add-auth-layer",
|
|
32
|
-
"current_work": "specdev/grill-with-docs",
|
|
33
|
-
"works_run": [],
|
|
34
|
-
"result": null
|
|
35
|
-
}
|
|
36
|
-
],
|
|
37
|
-
"work_history": [],
|
|
38
|
-
"completed": []
|
|
39
|
-
}
|
|
15
|
+
├── .status.json ← 本 change 的个体状态(见 INDEX.md「Per-change 状态文件」)
|
|
16
|
+
├── CONTEXT.md ← 领域词汇表(G-grill-with-docs 创建/更新)
|
|
17
|
+
├── ADR.md ← 架构决策记录(G-grill-with-docs 创建/更新)
|
|
18
|
+
├── LOG.md ← 设计决策日志(各 work 追加结论)
|
|
19
|
+
├── spec.md ← 需求规格(S-spec 创建)
|
|
20
|
+
├── tickets-map.md ← ticket 总体地图与执行清单(T-tickets 创建)
|
|
21
|
+
├── ticket/ ← 独立 ticket 文件(T-tickets 创建)
|
|
22
|
+
│ └── NN-<name>.md
|
|
23
|
+
├── map.md ← 寻路地图(W-wayfinder 创建)
|
|
24
|
+
├── goal-plan.md ← 目标规划文档(P-goal-plan 创建)
|
|
25
|
+
├── research/ ← 研究产物(common/research 维护,含 index.md)
|
|
26
|
+
└── prototype/ ← 原型产物(common/prototype 维护,含 index.md)
|
|
40
27
|
```
|
|
41
28
|
|
|
42
29
|
## 当 work 说"发布到变更目录"时
|
|
@@ -47,19 +34,19 @@ specdev workflow 的变更以 markdown 目录形式存储在 `{roots.state}/spec
|
|
|
47
34
|
|
|
48
35
|
## 当 work 说"获取当前变更"时
|
|
49
36
|
|
|
50
|
-
|
|
37
|
+
按 `<Path>{roots.workflows}/specdev/INDEX.md</Path>` 启动协议执行:读取 `status.json` 的 `active` 数组——用户指定则匹配对应条目;唯一活跃则直接使用;无活跃则创建新变更目录并追加条目;多个候选则由用户消歧。
|
|
51
38
|
|
|
52
39
|
## 当 work 说"归档变更"时
|
|
53
40
|
|
|
54
|
-
将变更目录从 `{roots.state}/specdev/changes/<change>/` 移动到 `{roots.state}/specdev/archive/YYYY-MM/<change>/`(YYYY-MM 取变更日期中的年月),从 `status.json` 的 `active` 数组中移除对应条目,追加归档记录到 `completed`
|
|
41
|
+
将变更目录从 `{roots.state}/specdev/changes/<change>/` 移动到 `{roots.state}/specdev/archive/YYYY-MM/<change>/`(YYYY-MM 取变更日期中的年月),从 `status.json` 的 `active` 数组中移除对应条目,追加归档记录到 `completed` 数组。完整归档与知识沉淀规程见 `<Path>{roots.workflows}/specdev/A-archive-and-consolidate/A-archive-and-consolidate.md</Path>`。
|
|
55
42
|
|
|
56
43
|
## Wayfinding 操作
|
|
57
44
|
|
|
58
|
-
供 `W-wayfinder`
|
|
45
|
+
供 `W-wayfinder` 使用。**地图是单个文件** `{roots.state}/specdev/changes/<change>/map.md`,tickets 是地图文件内的编号小节,不是独立文件:
|
|
46
|
+
|
|
47
|
+
- **状态**:checkbox 标记——`- [ ]` 开放、`- [x]` 已解决
|
|
48
|
+
- **阻塞**:ticket 小节内的「被阻塞于」字段,以 ticket 标题引用
|
|
49
|
+
- **领取**:将 ticket 名称追加到 `status.json` 当前 change 条目的 `claimed_tickets` 数组,完成后移除
|
|
50
|
+
- **前沿**:开放、未被阻塞、未被领取的 tickets
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
- **子工单**:`{roots.state}/specdev/changes/<change>/tickets/NN-<slug>.md`,从 `01` 开始编号,正文中包含问题。`Type:` 行记录工单类型(`research` / `prototype` / `grilling` / `task`);`Status:` 行记录 `claimed` / `resolved`。
|
|
62
|
-
- **阻塞**:顶部附近的 `Blocked by: NN, NN` 行。当其列出的每个文件都处于 `resolved` 状态时,工单解除阻塞。
|
|
63
|
-
- **前沿**:扫描 `tickets/` 中处于开放、未阻塞且未认领状态的文件;按编号取第一个。
|
|
64
|
-
- **认领**:设置 `Status: claimed` 并在任何工作开始前保存。
|
|
65
|
-
- **解决**:在 `## Answer` 标题下追加答案,设置 `Status: resolved`,然后将上下文指针(gist + 链接)追加到 `map.md` 中地图的 Decisions-so-far 中。
|
|
52
|
+
完整地图结构与遍历规程见 `<Path>{roots.workflows}/specdev/W-wayfinder/W-wayfinder.md</Path>`。
|