@namewta/speculo 0.2.7 → 0.2.10

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 (117) hide show
  1. package/README.md +12 -9
  2. package/dist/src/cli.js +1 -1
  3. package/dist/src/cli.js.map +1 -1
  4. package/dist/src/index.js +0 -32
  5. package/dist/src/index.js.map +1 -1
  6. package/dist/src/migrate.js +0 -4
  7. package/dist/src/migrate.js.map +1 -1
  8. package/package.json +1 -1
  9. package/template/.speculo/README.md +0 -1
  10. package/template/.speculo/workspace.json +1 -2
  11. package/template/canonical/README.md +44 -70
  12. package/template/canonical/canonical-specdev-grill-with-docs.md +475 -0
  13. package/template/canonical/canonical-specdev-spec.md +82 -0
  14. package/template/canonical/canonical-specdev-tickets.md +232 -0
  15. package/template/canonical/canonical-specdev-wayfinder.md +200 -0
  16. package/template/canonical/canonical-teach.md +70 -65
  17. package/template/workflows/specdev/A-archive-and-consolidate/A-archive-and-consolidate.md +73 -0
  18. package/template/workflows/specdev/A-archive-and-consolidate/archive-rules.md +49 -0
  19. package/template/workflows/specdev/A-archive-and-consolidate/cleanup-rules.md +80 -0
  20. package/template/workflows/specdev/A-archive-and-consolidate/consolidation-rules.md +120 -0
  21. package/template/workflows/specdev/A-archive-and-consolidate/discrimination-guide.md +96 -0
  22. package/template/workflows/specdev/A-archive-and-consolidate/knowledge-graduation.md +51 -0
  23. package/template/workflows/specdev/D-diagnose-bugs/D-diagnose-bugs.md +2 -0
  24. package/template/workflows/specdev/D-diagnose-bugs/feedback-loop-techniques.md +1 -1
  25. package/template/workflows/specdev/G-grill-with-docs/G-grill-with-docs.md +8 -0
  26. package/template/workflows/specdev/G-grill-with-docs/grilling-protocol.md +12 -4
  27. package/template/workflows/specdev/G-grill-with-docs/log-format.md +8 -7
  28. package/template/workflows/specdev/I-implement/I-implement.md +9 -4
  29. package/template/workflows/specdev/I-init-setup/domain-layout.md +1 -1
  30. package/template/workflows/specdev/INDEX.md +2 -0
  31. package/template/workflows/specdev/P-goal-plan/P-goal-plan.md +84 -0
  32. package/template/workflows/specdev/P-goal-plan/execution-sections.md +103 -0
  33. package/template/workflows/specdev/P-goal-plan/governance-sections.md +103 -0
  34. package/template/workflows/specdev/P-goal-plan/input-validation.md +94 -0
  35. package/template/workflows/specdev/P-goal-plan/lead-orchestration-protocol.md +159 -0
  36. package/template/workflows/specdev/P-goal-plan/quick-reference-table.md +60 -0
  37. package/template/workflows/specdev/P-goal-plan/vision-sections.md +80 -0
  38. package/template/workflows/specdev/S-spec/S-spec.md +2 -0
  39. package/template/workflows/specdev/T-tickets/T-tickets.md +20 -53
  40. package/template/workflows/specdev/T-tickets/tickets-map-template.md +70 -0
  41. package/template/workflows/specdev/W-wayfinder/W-wayfinder.md +2 -2
  42. package/template/workflows/specdev/_state/research/.gitkeep +0 -0
  43. package/template/workflows/specdev/common/dev-worktree/SKILL.md +138 -0
  44. package/template/workflows/specdev/common/dev-worktree/references/create.md +63 -0
  45. package/template/workflows/specdev/common/dev-worktree/references/finalize.md +102 -0
  46. package/template/workflows/specdev/common/prototype/LOGIC.md +89 -0
  47. package/template/workflows/specdev/common/prototype/SKILL.md +78 -0
  48. package/template/workflows/specdev/common/prototype/UI.md +120 -0
  49. package/template/workflows/specdev/common/research/SKILL.md +54 -0
  50. package/template/canonical/canonical-domain-modeling.md +0 -289
  51. package/template/canonical/canonical-skill-example.md +0 -608
  52. package/template/skills/worktree-isolation/SKILL.md +0 -23
  53. package/template/skills/worktree-isolation/references/audit-branch-tree.md +0 -32
  54. package/template/skills/worktree-isolation/references/create-worktree.md +0 -39
  55. package/template/skills/worktree-isolation/references/merge-and-cleanup.md +0 -43
  56. package/template/vendor/README.md +0 -35
  57. package/template/vendor/matt-pocock/README.md +0 -41
  58. package/template/vendor/matt-pocock/engineering/README.md +0 -28
  59. package/template/vendor/matt-pocock/engineering/ask-matt/SKILL.md +0 -76
  60. package/template/vendor/matt-pocock/engineering/code-review/SKILL.md +0 -89
  61. package/template/vendor/matt-pocock/engineering/codebase-design/DEEPENING.md +0 -37
  62. package/template/vendor/matt-pocock/engineering/codebase-design/DESIGN-IT-TWICE.md +0 -44
  63. package/template/vendor/matt-pocock/engineering/codebase-design/SKILL.md +0 -114
  64. package/template/vendor/matt-pocock/engineering/diagnosing-bugs/SKILL.md +0 -134
  65. package/template/vendor/matt-pocock/engineering/domain-modeling/ADR-FORMAT.md +0 -47
  66. package/template/vendor/matt-pocock/engineering/domain-modeling/CONTEXT-FORMAT.md +0 -60
  67. package/template/vendor/matt-pocock/engineering/domain-modeling/SKILL.md +0 -74
  68. package/template/vendor/matt-pocock/engineering/grill-with-docs/SKILL.md +0 -7
  69. package/template/vendor/matt-pocock/engineering/implement/SKILL.md +0 -15
  70. package/template/vendor/matt-pocock/engineering/prototype/LOGIC.md +0 -79
  71. package/template/vendor/matt-pocock/engineering/prototype/SKILL.md +0 -30
  72. package/template/vendor/matt-pocock/engineering/prototype/UI.md +0 -112
  73. package/template/vendor/matt-pocock/engineering/research/SKILL.md +0 -12
  74. package/template/vendor/matt-pocock/engineering/setup-matt-pocock-skills/SKILL.md +0 -156
  75. package/template/vendor/matt-pocock/engineering/setup-matt-pocock-skills/domain.md +0 -40
  76. package/template/vendor/matt-pocock/engineering/setup-matt-pocock-skills/issue-tracker-github.md +0 -45
  77. package/template/vendor/matt-pocock/engineering/setup-matt-pocock-skills/issue-tracker-gitlab.md +0 -46
  78. package/template/vendor/matt-pocock/engineering/setup-matt-pocock-skills/issue-tracker-local.md +0 -30
  79. package/template/vendor/matt-pocock/engineering/setup-matt-pocock-skills/triage-labels.md +0 -15
  80. package/template/vendor/matt-pocock/engineering/tdd/SKILL.md +0 -36
  81. package/template/vendor/matt-pocock/engineering/tdd/mocking.md +0 -59
  82. package/template/vendor/matt-pocock/engineering/tdd/tests.md +0 -77
  83. package/template/vendor/matt-pocock/engineering/to-spec/SKILL.md +0 -75
  84. package/template/vendor/matt-pocock/engineering/to-tickets/SKILL.md +0 -113
  85. package/template/vendor/matt-pocock/engineering/wayfinder/SKILL.md +0 -127
  86. package/template/vendor/matt-pocock/in-progress/README.md +0 -10
  87. package/template/vendor/matt-pocock/in-progress/claude-handoff/SKILL.md +0 -18
  88. package/template/vendor/matt-pocock/in-progress/loop-me/SKILL.md +0 -32
  89. package/template/vendor/matt-pocock/in-progress/wizard/SKILL.md +0 -45
  90. package/template/vendor/matt-pocock/in-progress/wizard/template.sh +0 -211
  91. package/template/vendor/matt-pocock/in-progress/writing-beats/SKILL.md +0 -67
  92. package/template/vendor/matt-pocock/in-progress/writing-fragments/SKILL.md +0 -78
  93. package/template/vendor/matt-pocock/in-progress/writing-shape/SKILL.md +0 -79
  94. package/template/vendor/matt-pocock/productivity/README.md +0 -18
  95. package/template/vendor/matt-pocock/productivity/grill-me/SKILL.md +0 -7
  96. package/template/vendor/matt-pocock/productivity/grilling/SKILL.md +0 -12
  97. package/template/vendor/matt-pocock/productivity/teach/GLOSSARY-FORMAT.md +0 -35
  98. package/template/vendor/matt-pocock/productivity/teach/LEARNING-RECORD-FORMAT.md +0 -46
  99. package/template/vendor/matt-pocock/productivity/teach/MISSION-FORMAT.md +0 -31
  100. package/template/vendor/matt-pocock/productivity/teach/RESOURCES-FORMAT.md +0 -32
  101. package/template/vendor/matt-pocock/productivity/teach/SKILL.md +0 -140
  102. /package/template/{vendor/matt-pocock/productivity → skills}/writing-great-skills/GLOSSARY.md +0 -0
  103. /package/template/{vendor/matt-pocock/productivity → skills}/writing-great-skills/SKILL.md +0 -0
  104. /package/template/{vendor/matt-pocock/productivity → workflows/specdev/common}/handoff/SKILL.md +0 -0
  105. /package/template/{vendor/matt-pocock/engineering → workflows/specdev/common}/improve-codebase-architecture/HTML-REPORT.md +0 -0
  106. /package/template/{vendor/matt-pocock/engineering → workflows/specdev/common}/improve-codebase-architecture/SKILL.md +0 -0
  107. /package/template/{vendor/khazix-skills → workflows/specdev/common}/neat-freak/SKILL.md +0 -0
  108. /package/template/{vendor/khazix-skills → workflows/specdev/common}/neat-freak/references/agent-paths.md +0 -0
  109. /package/template/{vendor/khazix-skills → workflows/specdev/common}/neat-freak/references/governance.md +0 -0
  110. /package/template/{vendor/khazix-skills → workflows/specdev/common}/neat-freak/references/sync-matrix.md +0 -0
  111. /package/template/{vendor/khazix-skills → workflows/specdev/common}/neat-freak/references/verification.md +0 -0
  112. /package/template/{vendor/khazix-skills → workflows/specdev/common}/neat-freak/scripts/audit-inventory.sh +0 -0
  113. /package/template/{vendor/matt-pocock/engineering → workflows/specdev/common}/resolving-merge-conflicts/SKILL.md +0 -0
  114. /package/template/{vendor/matt-pocock/engineering/diagnosing-bugs → workflows/specdev/common}/scripts/hitl-loop.template.sh +0 -0
  115. /package/template/{vendor/matt-pocock/engineering → workflows/specdev/common}/triage/AGENT-BRIEF.md +0 -0
  116. /package/template/{vendor/matt-pocock/engineering → workflows/specdev/common}/triage/OUT-OF-SCOPE.md +0 -0
  117. /package/template/{vendor/matt-pocock/engineering → workflows/specdev/common}/triage/SKILL.md +0 -0
@@ -0,0 +1,89 @@
1
+ # 逻辑原型
2
+
3
+ 构建一个微小的交互式终端应用,让用户手动驱动状态模型。当问题涉及**业务逻辑、状态转换或数据形态**时使用——这类问题在纸面上看起来合理,但只有推进真实用例后才会暴露出不对劲的地方。
4
+
5
+ ## 适用场景
6
+
7
+ - "我不确定这个状态机能否处理先 X 后 Y 的边界情况。"
8
+ - "这个数据模型真的能表示那种情况吗……"
9
+ - "我想在写之前先感受一下 API 应该长什么样。"
10
+ - 任何用户想要**按按钮、观察状态变化**的场景。
11
+
12
+ 如果问题是"这个应该长什么样"——选错了分支。用 [UI.md](UI.md)。
13
+
14
+ ## 流程
15
+
16
+ ### 1. 陈述问题
17
+
18
+ 在写代码之前,写下你正在为哪个状态模型和哪个问题做原型。一段话即可,放在原型的 README 或文件顶部的注释中。回答了错误问题的逻辑原型是纯粹浪费——让问题显式化,这样之后可以核查,无论用户是现在看着还是稍后 AFK 回来再看。
19
+
20
+ ### 2. 选择语言
21
+
22
+ 使用宿主项目所用的语言。如果项目没有明显的运行时(如文档仓库),则询问。
23
+
24
+ 遵循项目已有的工具链约定——不要仅为原型引入新的包管理器或运行时。
25
+
26
+ ### 3. 将逻辑隔离到一个可移植模块中
27
+
28
+ 将实际逻辑——回答问题的部分——放在一个小巧、纯净的接口后面,使其之后可以被提取并放入正式代码库。围绕它的 TUI 是一次性的;逻辑模块不应该是一次性的。
29
+
30
+ 正确的形态取决于问题:
31
+
32
+ - **纯 reducer**——`(state, action) => state`。适用于动作为离散事件且状态为单一值的场景。
33
+ - **状态机**——显式的状态和转换。适用于"当前哪些操作是合法的"本身就是问题的一部分。
34
+ - **一组纯函数**操作一个纯数据类型。适用于没有隐式当前状态、只有转换的场景。
35
+ - **类或模块**——具有清晰方法接口,当逻辑确实拥有持续性内部状态时使用。
36
+
37
+ 选择最适合所问问题的形态,而*不是*最容易接入 TUI 的形态。保持纯净:无 I/O、无终端代码、无用于控制流的 `console.log`。TUI 导入它并调用它;反向不传递任何内容。
38
+
39
+ 这就是让原型在自身生命周期之后仍有价值的关键:当问题得到回答后,验证通过的 reducer / 状态机 / 函数集可以被单独提升到正式模块中。
40
+
41
+ ### 4. 构建最小的 TUI 来暴露状态
42
+
43
+ 将其构建为**轻量 TUI**——每次 tick 清屏(`console.clear()` / `print("\033[2J\033[H")` / 等价方式)并重新渲染整个帧。用户应始终看到一个稳定视图,而非不断增长的滚动回溯。
44
+
45
+ 每帧包含两部分,顺序如下:
46
+
47
+ 1. **当前状态**,pretty-print 且 diff 友好(每行一个字段,或格式化 JSON)。使用**粗体**标注字段名或节标题,**暗色**标注次要上下文(时间戳、ID、派生值)。原生 ANSI 转义码即可——`\x1b[1m` 粗体、`\x1b[2m` 暗色、`\x1b[0m` 重置。无需引入样式库,除非项目中已经存在。
48
+ 2. **键盘快捷键**,列在底部:`[a] 添加用户 [d] 删除用户 [t] 推动时钟 [q] 退出`。粗体标键、暗色标描述,或反过来——怎么读起来清晰怎么来。
49
+
50
+ 行为:
51
+
52
+ 1. **初始化状态**——单个内存中的对象/结构体。启动时渲染第一帧。
53
+ 2. **每次读取一次按键(或一行)**,分发到修改状态的处理器。
54
+ 3. **每次操作后重新渲染**完整帧——不追加,而是替换。
55
+ 4. **循环直到退出。**
56
+
57
+ 整个帧应适配一屏。
58
+
59
+ ### 5. 一条命令即可运行
60
+
61
+ 向项目已有任务运行器添加一条脚本(`package.json` scripts、`Makefile`、`justfile`、`pyproject.toml`)。用户应运行 `pnpm run <原型名称>` 或等价命令——永远不需要记住路径。
62
+
63
+ 如果宿主项目没有任务运行器,直接把命令写在原型 README 的顶部。
64
+
65
+ ### 6. 交付
66
+
67
+ 给用户运行命令。他们会自己驱动它;有趣的时刻是他们说"等等,那不应该可能"或"嗯,我以为 X 会不一样"——那些是_想法_中的 bug,这正是整个原型的目的。如果他们想添加新操作,就添加。原型会演化。
68
+
69
+ ### 7. 捕获答案并持久化
70
+
71
+ 原型回答问题后,按 [SKILL](SKILL.md) 中持久化约定的方式捕获答案:
72
+
73
+ 1. **提升验证过的逻辑**:将验证通过的 reducer / 状态机 / 函数集提升到正式模块中(决策已被吸收)。
74
+ 2. **持久化答案记录**:在 `<Path>{roots.state}/<workflow>/changes/{change}/prototype/logic-<topic>.md</Path>` 创建答案文件,记录:
75
+ - 所回答的问题
76
+ - 结论——什么可行、什么不可行
77
+ - 被验证的逻辑模块的描述
78
+ - throwaway 分支指针(TUI 外壳代码所在位置)
79
+ 3. **更新索引**:将新答案追加到 `prototype/index.md` 表格中。
80
+
81
+ TUI 外壳代码仍提交到 throwaway 分支——它是一次性的交互壳,真正有价值的部分(逻辑模块)已经提升到正式代码中。
82
+
83
+ ## 反模式
84
+
85
+ - **不要加测试。** 需要测试的原型不再是原型。
86
+ - **不要接入真实数据库。** 使用内存存储,除非问题本身就是关于持久化的。
87
+ - **不要泛化。** 不要"如果我们以后想支持 X 呢"。原型只回答一个问题。
88
+ - **不要把逻辑和 TUI 混在一起。** 如果 reducer / 状态机引用了 `console.log`、提示符或终端转义码,它就不可移植了。让 TUI 成为纯模块外面的薄壳。
89
+ - **不要把 TUI 外壳发布到生产环境。** 外壳是为在终端中手动驱动而优化的。背后的逻辑模块才是值得保留的部分。
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: prototype
3
+ description: 构建一个一次性原型来回答设计问题。当用户想要快速验证某个状态模型或逻辑是否正确,或探索 UI 应该长什么样时使用。
4
+ ---
5
+
6
+ # 原型
7
+
8
+ 原型是**回答问题的 disposable 代码**。问题决定形态。
9
+
10
+ ## 选择分支
11
+
12
+ 确定正在回答哪个问题——从用户的提示、周围代码中推断,或用户在场时直接询问:
13
+
14
+ - **"这个逻辑 / 状态模型对吗?"** → [LOGIC.md](LOGIC.md)。构建一个微小的交互式终端应用,推动状态机经过那些在纸面上难以推理的用例。
15
+ - **"这个应该长什么样?"** → [UI.md](UI.md)。在单个路由上生成几个截然不同的 UI 变体,通过 URL 查询参数和底部浮动栏切换。
16
+
17
+ 两条分支产生的产物截然不同——选错会浪费整个原型。如果问题确实模糊且无法联系用户,默认选择与周围代码更匹配的分支(后端模块 → logic;页面或组件 → UI),并在原型顶部声明假设。
18
+
19
+ ## 通用规则
20
+
21
+ 1. **从第一天起就是 disposable,并明确标注。** 将原型代码放在离实际使用位置近的地方(紧邻它正在为哪个模块或页面做原型),这样上下文一目了然——但命名要让随便一个读者都能看出这是原型而非生产代码。对于 disposable UI 路由,遵循项目已有的路由约定,不要发明新的顶层结构。
22
+ 2. **一条命令即可运行。** 使用项目已有任务运行器支持的方式——`pnpm <名称>`、`python <路径>`、`bun <路径>` 等。用户必须能不加思考就启动它。
23
+ 3. **默认无持久化。** 状态存在于内存中。持久化是原型正在_检查_的东西,而非原型应该依赖的东西。如果问题明确涉及数据库,用一个临时库或本地文件,名称要清楚标注"PROTOTYPE — 可随时清除"。
24
+ 4. **跳过打磨。** 不写测试,不做超出让原型_可运行_范围的错误处理,不建抽象。目的是快速学习。
25
+ 5. **展示状态。** 每次操作后(logic)或每次变体切换时(UI),打印或渲染完整的相关状态,让用户能看到什么发生了变化。
26
+ 6. **完成后捕获结论。** 将验证通过的决策融入正式代码。然后将答案和结论持久化到变更目录:
27
+ - 在 `<Path>{roots.state}/<workflow>/changes/{change}/prototype/</Path>` 下创建答案文件
28
+ - 维护 `prototype/index.md` 索引表
29
+ - 原型代码本身仍为一次性代码:提交到 throwaway 分支,保持脱离主分支。答案文件中记录该分支的引用指针
30
+ - 具体持久化规范见下方「持久化约定」章节
31
+
32
+ ## 持久化约定
33
+
34
+ ### 产物位置
35
+
36
+ 原型答案写入当前 change 目录下的 `prototype/` 子目录:
37
+
38
+ ```
39
+ <Path>{roots.state}/<workflow>/changes/{change}/prototype/<type>-<topic>.md</Path>
40
+ ```
41
+
42
+ - `<type>` 为 `logic` 或 `ui`,对应原型分支类型
43
+ - `<topic>` 为 kebab-case 主题名,概括原型所回答的问题,如 `auth-state-machine.md`、`settings-page-layout.md`
44
+ - `<workflow>` 为当前 workflow 目录名(如 `specdev`)
45
+ - `<change>` 为当前活跃变更目录名(格式 `<YYYY-MM-DD>-<topic>`,从 `<Path>{roots.state}/<workflow>/status.json</Path>` 的 `active` 数组中获取)
46
+
47
+ ### 答案文件内容
48
+
49
+ 每个答案文件包含以下信息:
50
+
51
+ - **问题**:原型所回答的具体问题
52
+ - **结论**:验证后的结论——什么可行、什么不可行、为什么
53
+ - **验证内容**(仅 logic 原型):被验证的 reducer / 状态机 / 函数集的描述
54
+ - **UI 评估记录**(仅 UI 原型):哪个变体胜出及原因、各变体的结构差异分析、从落选变体中提取的有价值元素
55
+ - **原型代码引用**:throwaway 分支名称,指向原型代码所在的 git 分支
56
+
57
+ ### 维护 prototype/index.md
58
+
59
+ 在 `prototype/` 目录下维护一个索引文件 `<Path>{roots.state}/<workflow>/changes/{change}/prototype/index.md</Path>`,仅包含一张表格:
60
+
61
+ | 类型 | 文件 | 问题概述 | 结论摘要 |
62
+ |------|------|---------|---------|
63
+ | logic | `auth-state-machine.md` | 认证状态机能否正确处理 token 过期 + 并发刷新 | 可行;需增加 TOKEN_EXPIRED 中间态 |
64
+ | ui | `settings-layout.md` | 设置页三种布局方案对比 | B 方案(侧边栏布局)胜出;吸收 C 的面包屑导航 |
65
+
66
+ - 表格四列:类型(`logic` / `ui`)、文件(`prototype/` 下的相对路径)、问题概述(一句话概括)、结论摘要(一句话概括结论)
67
+ - 每次新增答案文件后,向表格追加一行
68
+ - `index.md` 除表格外无需其它内容
69
+
70
+ ### 去重与增量更新
71
+
72
+ 在开始新原型之前:
73
+
74
+ 1. 先读取 `<Path>{roots.state}/<workflow>/changes/{change}/prototype/index.md</Path>`,检查是否已有同名或高度相关的原型记录
75
+ 2. 如已存在对应 `.md` 文件,先读取其完整内容
76
+ 3. 如现有结论已覆盖当前问题,直接引用,无需重复原型
77
+ 4. 如需更新(新发现补充、结论修正),在原文件基础上增删改,并同步更新 `index.md` 中对应行的概述
78
+ 5. 如需回答全新问题,创建新文件并追加到 `index.md` 表格
@@ -0,0 +1,120 @@
1
+ # UI 原型
2
+
3
+ 在单个路由上生成**几个截然不同的 UI 变体**,通过底部浮动栏切换。用户在浏览器中翻看变体,选一个(或从每个中偷一些元素),然后丢弃其余。
4
+
5
+ 如果问题是关于逻辑/状态而非界面外观——选错了分支。用 [LOGIC.md](LOGIC.md)。
6
+
7
+ ## 适用场景
8
+
9
+ - "这个页面应该长什么样?"
10
+ - "我想在提交之前看几个仪表盘方案。"
11
+ - "给设置页试一种不同的布局。"
12
+ - 任何用户本来会在脑子里花一天时间在三个模糊线框图之间犹豫不决的场景。
13
+
14
+ ## 两种子形态 —— 强烈偏好子形态 A
15
+
16
+ UI 原型在**与应用的其余部分产生摩擦**时才最容易评判——真实的 header、真实的 sidebar、真实的数据、真实的信息密度。单独的一次性路由是真空:每个变体在隔离状态下看起来都不错。只要有合理的现有页面可以承载变体,就默认使用子形态 A。只有当原型确实没有邻近的宿主时才使用子形态 B。
17
+
18
+ ### 子形态 A — 调整现有页面(首选)
19
+
20
+ 路由已存在。变体在**同一路由**上渲染,通过 `?variant=` URL 查询参数控制。现有的数据获取、参数和认证全部保留——只替换渲染部分。这是默认选项;除非有明确的理由不这样做,否则选它。
21
+
22
+ 如果原型针对的东西还没有页面,但*自然地应该存在于某个页面内部*(仪表盘的新区域、设置页的新卡片、现有流程中的新步骤)——这仍然是子形态 A。将变体挂载在宿主页面内部。
23
+
24
+ ### 子形态 B — 新建页面(最后手段)
25
+
26
+ 仅当被原型化的事物确实没有现成页面可以嵌入时使用——例如一个全新的顶层界面,或一个无法合理嵌入任何地方的流程。
27
+
28
+ 按照项目已有的路由约定创建一个**一次性路由**——不要发明新的顶层结构。命名要让人一眼看出是原型(例如在路径或文件名中包含 `prototype` 字样)。同样使用 `?variant=` 模式。
29
+
30
+ 在提交子形态 B 之前,做一个合理性检查:真的没有现成页面可以嵌入吗?空路由会隐藏有内容的页面能够暴露的设计问题。
31
+
32
+ 两种子形态下,底部浮动栏完全相同。
33
+
34
+ ## 流程
35
+
36
+ ### 1. 陈述问题并确定变体数量 N
37
+
38
+ 默认 **3 个变体**。超过 5 个就不再是截然不同,而是噪音——以此为上限。
39
+
40
+ 将计划写在一行内,放在原型所在位置或文件顶部注释中:
41
+
42
+ > "设置页的三个变体,通过 `?variant=` 切换,在现有 `/settings` 路由上。"
43
+
44
+ 无论用户是否在场反对,这都能成立。
45
+
46
+ ### 2. 生成截然不同的变体
47
+
48
+ 起草每个变体。每个变体必须满足:
49
+
50
+ - 页面的目的和它能访问的数据。
51
+ - 项目的组件库 / 样式系统(TailwindCSS、shadcn、MUI、纯 CSS,等等)。
52
+ - 清晰的导出组件名,例如 `VariantA`、`VariantB`、`VariantC`。
53
+
54
+ 变体必须在**结构上不同**——不同的布局、不同的信息层次、不同的主要操作入口,而不仅仅是不同的颜色。三个微调过的卡片网格不是 UI 原型,是壁纸。如果两份草稿太相似,用明确的"不要用卡片网格"指引重做其中一个。
55
+
56
+ ### 3. 将它们串接起来
57
+
58
+ 在路由上创建一个单一的切换器组件:
59
+
60
+ ```tsx
61
+ // 伪代码 —— 根据项目框架调整
62
+ const variant = searchParams.get('variant') ?? 'A';
63
+ return (
64
+ <>
65
+ {variant === 'A' && <VariantA {...data} />}
66
+ {variant === 'B' && <VariantB {...data} />}
67
+ {variant === 'C' && <VariantC {...data} />}
68
+ <PrototypeSwitcher variants={['A','B','C']} current={variant} />
69
+ </>
70
+ );
71
+ ```
72
+
73
+ 对于子形态 A(现有页面):将现有数据获取保持在切换器上方;每个变体只替换渲染的子树。
74
+
75
+ 对于子形态 B(新建页面):`/prototype/<名称>` 下的一次性路由挂载同一个切换器。
76
+
77
+ ### 4. 构建浮动切换器
78
+
79
+ 一个位于屏幕底部中央的固定定位小栏,包含三个元素:
80
+
81
+ - **左箭头**——切换到上一个变体(循环)。
82
+ - **变体标签**——显示当前变体标识,如果变体导出了名称,也显示名称。例如 `B — 侧边栏布局`。
83
+ - **右箭头**——切换到下一个(循环)。
84
+
85
+ 行为:
86
+
87
+ - 点击箭头更新 URL 查询参数(使用框架的路由器——Next 上用 `router.replace`、React Router 上用 `navigate`,等等),使变体可分享且在刷新后保持。
88
+ - 键盘:`←` 和 `→` 方向键也可切换。当 `<input>`、`<textarea>` 或 `[contenteditable]` 元素聚焦时不要拦截方向键。
89
+ - 在视觉上与页面区分(如高对比度胶囊形、微妙阴影),使其明显不是被评估的设计的一部分。
90
+ - 在生产构建中隐藏——通过 `process.env.NODE_ENV !== 'production'` 或等价检查进行门控,这样即使原型不小心合入也不会把切换器发布给用户。
91
+
92
+ 将切换器放在一个共享组件中,供两种子形态复用。放置在项目中共享 UI 组件的通常位置。
93
+
94
+ ### 5. 交付
95
+
96
+ 给出 URL(以及 `?variant=` 的各个键值)。用户会在有空时翻看。最有趣的反馈通常是**"我想要 B 方案的头和 C 方案的侧边栏"**——那才是他们真正想要的设计。
97
+
98
+ ### 6. 捕获答案并清理
99
+
100
+ 一旦某个变体胜出,按 [SKILL](SKILL.md) 中持久化约定的方式捕获答案:
101
+
102
+ 1. **融入正式代码**:
103
+ - **子形态 A** — 将胜出变体融入现有页面;从主分支移除落选变体和切换器。
104
+ - **子形态 B** — 将胜出变体提升为正式路由;从主分支移除一次性路由和切换器。
105
+ 2. **持久化评估记录**:在 `<Path>{roots.state}/<workflow>/changes/{change}/prototype/ui-<topic>.md</Path>` 创建答案文件,记录:
106
+ - 所回答的 UI 问题
107
+ - 哪个变体胜出及原因——完整的评估推理
108
+ - 各变体的结构差异分析
109
+ - 从落选变体中提取的有价值元素(如果适用)
110
+ - throwaway 分支指针
111
+ 3. **UI 规范沉淀**:将评估过程中产生的 UI 规范洞察(如布局原则、信息层次、交互模式选择理由)写入答案文件,供后续 spec 编写引用。
112
+ 4. **清理原型代码**:将完整变体集(包括落选变体和切换器)提交到 throwaway 分支,不进入主分支。变体组件和切换器留在主分支会快速腐烂并误导后续读者。
113
+ 5. **更新索引**:将新答案追加到 `prototype/index.md` 表格中。
114
+
115
+ ## 反模式
116
+
117
+ - **变体仅颜色或文案不同。** 那是微调,不是原型。真正的变体在结构上存在分歧。
118
+ - **变体之间共享过多代码。** 共享一个 `<Header>` 没问题;共享一个 `<Layout>` 就失去了意义。每个变体应该能够自由地抛弃布局。
119
+ - **将变体接入真实的数据变更。** 只读原型完全没问题。如果变体需要变更数据,将其指向一个桩——问题是"这个应该长什么样",不是"后端是否正常工作"。
120
+ - **将原型直接提升到生产环境。** 变体代码是在原型约束下编写的(无测试、最小错误处理)。融入时要正确重写。
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: research
3
+ description: "针对高可信度一手来源调查问题,并将发现结果以 Markdown 文件持久化到变更目录的 research/ 子目录中。适用于需要研究某个主题、收集文档或 API 信息、或委托阅读工作给后台 Agent 的场景。"
4
+ ---
5
+
6
+ 启动一个**后台 Agent** 来进行研究,这样你可以在它阅读时继续工作。
7
+
8
+ 其工作内容:
9
+
10
+ 1. 针对**一手来源**调查问题 —— 官方文档、源代码、规范、第一方 API —— 而不是基于这些来源的二次编写材料。将每个声明追溯到拥有该声明的来源。
11
+ 2. 将发现结果写入单个 Markdown 文件,为每个声明标注来源。
12
+ 3. 将文件持久化到当前变更目录的 `research/` 子目录中,并维护同目录下的 `index.md` 索引。
13
+
14
+ ## 持久化约定
15
+
16
+ ### 产物位置
17
+
18
+ 研究产物写入当前 change 目录下的 `research/` 子目录:
19
+
20
+ ```
21
+ <Path>{roots.state}/<workflow>/changes/{change}/research/<research_topic_name>.md</Path>
22
+ ```
23
+
24
+ - `<research_topic_name>` 为 kebab-case,如 `react-19-upgrade-guide.md`、`prisma-v6-migration.md`
25
+ - `<workflow>` 为当前 workflow 目录名(如 `specdev`)
26
+ - `<change>` 为当前活跃变更目录名(格式 `<YYYY-MM-DD>-<topic>`,从 `<Path>{roots.state}/<workflow>/status.json</Path>` 的 `active` 数组中获取)
27
+
28
+ ### 维护 research/index.md
29
+
30
+ 在 `research/` 目录下维护一个索引文件 `<Path>{roots.state}/<workflow>/changes/{change}/research/index.md</Path>`,仅包含一张表格:
31
+
32
+ | 文件 | 概述 |
33
+ |------|------|
34
+ | `react-19-upgrade-guide.md` | React 19 升级要点、breaking changes、迁移路径 |
35
+ | `prisma-v6-changes.md` | Prisma v6 新增 API、废弃项、性能改进 |
36
+
37
+ - 表格两列:文件(`research/` 下的相对路径)、概述(一句话概括研究主题和关键发现)
38
+ - 每次新增 research 文件后,向表格追加一行
39
+ - 每次修改 research 文件后,检查对应概述是否仍准确,必要时更新
40
+ - `index.md` 除表格外无需其它内容
41
+
42
+ ### 去重与增量更新
43
+
44
+ 在开始新研究之前:
45
+
46
+ 1. 先读取 `<Path>{roots.state}/<workflow>/changes/{change}/research/index.md</Path>`,检查是否已有同名或高度相关的 research topic
47
+ 2. 如已存在对应 `.md` 文件,先读取其完整内容
48
+ 3. 如现有内容已满足当前需求,直接引用,无需重新研究
49
+ 4. 如现有内容不满足需求(信息过时、覆盖不全、结论有误),在原文件基础上进行增删改:
50
+ - **增**:补充新的发现、新增来源、追加未覆盖的子主题
51
+ - **删**:删除已被证伪的结论、过时的信息
52
+ - **改**:修正错误结论、更新版本号/API 签名
53
+ - 修改后同步更新 `index.md` 中对应行的概述
54
+ 5. 如需研究的是全新 topic,创建新文件并追加到 `index.md` 表格
@@ -1,289 +0,0 @@
1
- # 领域建模
2
-
3
- ---
4
-
5
- name: domain-modeling
6
- description: 通过无情面试打磨领域模型。挑战术语、发明边界场景、在决策结晶的瞬间写入 CONTEXT.md、ADR.md 和 LOG.md。当用户想要确定领域术语或通用语言、记录架构决策,或当其他技能需要维护领域模型时使用。
7
-
8
- ---
9
-
10
- ## 1. 面试(Grilling)
11
-
12
- 请对我进行无情的面试,深入探讨该方案的每一个方面,直到我们达成共识。沿设计树的每个分支逐步推进,逐个解决决策之间的依赖关系。每个问题都给出你的推荐答案。
13
-
14
- 一次只问一个问题,等待我对每个问题给出反馈后再继续。一次问多个问题会让人困惑。
15
-
16
- 如果某个*事实*可以通过探索代码库找到,请自行查找,不要来问我。但*决策*由我来做 —— 将每个决策提交给我并等待我的回答。
17
-
18
- 在我确认我们已达成共识之前,不要执行该方案。
19
-
20
- ## 2. 领域建模规程
21
-
22
- 在设计过程中积极构建和精炼项目的领域模型。这是*主动*规程 — 挑战术语、发明边界场景、并在决策结晶的那一刻立即写下词汇表和决策。仅仅_阅读_ `CONTEXT.md` 获取词汇不是本技能 — 那是任何技能都可以做到的一行习惯。本技能用于当你正在_改变_模型,而不仅仅是消费它时。
23
-
24
- ### 文件结构
25
-
26
- ```
27
- /
28
- ├── CONTEXT.md
29
- ├── ADR.md
30
- └── LOG.md
31
- ```
32
-
33
- 只维护这三个文件。没有 `docs/adr/` 目录下的编号文件,没有 `CONTEXT-MAP.md`。随着模型演进,在文件内部增、删、改条目。
34
-
35
- ### 对照词汇表挑战
36
-
37
- 当用户使用的术语与 `CONTEXT.md` 中的现有语言冲突时,立即指出。"你的词汇表将 'cancellation' 定义为 X,但你似乎指的是 Y — 到底是哪个?"
38
-
39
- ### 精炼模糊语言
40
-
41
- 当用户使用含糊或重载的术语时,提出一个精确的规范术语。"你在说 'account' — 你指的是 Customer 还是 User?它们是不同的东西。"
42
-
43
- ### 讨论具体场景
44
-
45
- 当讨论领域关系时,用具体场景进行压力测试。发明探索边界情况的场景,迫使用户精确界定概念之间的边界。"你说订单可以部分取消 — 未取消的商品怎么办?它们还能发货吗?"
46
-
47
- ### 与代码交叉引用
48
-
49
- 当用户陈述某事如何工作时,检查代码是否一致。如果发现矛盾,指出来:"你的代码取消的是整个 Order,但你刚才说部分取消是可能的 — 哪个是正确的?"
50
-
51
- ### 及时更新 LOG.md
52
-
53
- 当设计问答中形成任何结论时,当场更新 `LOG.md`。它是完整的设计轨迹 — 记录"当时讨论了什么、最终固定了什么行为以及对应哪个 ADR"。
54
-
55
- **三个文件的分工**:
56
-
57
- | 文件 | 职责 | 维护方式 |
58
- |------|------|----------|
59
- | `LOG.md` | 完整设计轨迹 — 所有确认、延后、被替代的结论 | 持续增删改,条目可被后续决定修订 |
60
- | `CONTEXT.md` | 精炼的规范词汇表 — 只保留当前有效的术语 | 增删改,保持精炼 |
61
- | `ADR.md` | 难以逆转、令人意外、存在真实权衡的架构决策 | 只追加不删除,可标记废弃 |
62
-
63
- 三者关系:LOG.md 是最完整的记录 → CONTEXT.md 从中提取术语定义 → ADR.md 从中筛选同时满足三个条件的架构决策。
64
-
65
- **日志条目格式**:每条日志使用 `## LOG-XXXX: {标题}` 二级标题,编号从 `0001` 开始顺序递增。
66
-
67
- **状态标记**:
68
- - `Status: accepted` — 已确认的现行结论
69
- - `Status: deferred` — 暂不决定,留待后续讨论
70
- - `Status: superseded` — 被后续决定替代,标注 `Superseded by: LOG-XXXX`
71
-
72
- **维护规则**:
73
- - 每次完成设计问答,同步更新 `LOG.md`、`CONTEXT.md` 与 `ADR.md`。
74
- - 后续确认改变既有结论时,直接修订原日志条目,并记录替代关系,不保留互相矛盾的"现行规则"。
75
- - 日志可以记录具体交互和边界场景;词汇表保持精炼;ADR 只记录难以逆转、令人意外且存在真实权衡的决定。
76
- - 每个日志条目应关联对应的 ADR(如有):`Related: ADR-XXXX`。
77
- - 状态为 `deferred` 的条目保留,以便后续恢复讨论时知道从什么问题开始。
78
-
79
- ### 及时更新 CONTEXT.md
80
-
81
- 当术语确定时,当场更新 `CONTEXT.md`。不要批量处理 — 发生时立即捕获。
82
-
83
- `CONTEXT.md` 应该完全不包含实现细节。不要将 `CONTEXT.md` 当作规范、草稿纸或实现决策的仓库。它只是词汇表,别无其他。
84
-
85
- - **新增术语**:在合适的子标题下追加条目。
86
- - **修改术语**:直接更新定义文本和 `_Avoid_` 列表。
87
- - **删除术语**:移除整个条目。
88
- - **术语更名**:删除旧条目,新增新条目。
89
-
90
- ### 谨慎更新 ADR.md
91
-
92
- 仅在以下三个条件全部满足时才向 `ADR.md` 追加一条决策记录:
93
-
94
- 1. **难以逆转** — 以后改变主意的成本是有意义的
95
- 2. **没有上下文会令人惊讶** — 未来的读者会疑惑"他们为什么这样做?"
96
- 3. **真实权衡的结果** — 存在真正的替代方案,你出于特定原因选择了一个
97
-
98
- 如果缺少任何一个条件,跳过 ADR。
99
-
100
- `ADR.md` 中每个决策是一个 `## NNNN: {标题}` 二级标题,编号顺序递增,条目之间用 `---` 分隔。可以修改已有条目、标记废弃 — 但不要删除。
101
-
102
- ### 什么算 ADR
103
-
104
- - **架构形态。** "我们使用 monorepo。" "写模型采用事件溯源,读模型投影到 Postgres。"
105
- - **上下文间的集成模式。** "Ordering 和 Billing 通过领域事件通信,而非同步 HTTP。"
106
- - **带来锁定效应的技术选择。** 数据库、消息总线、认证提供商、部署目标。不是每个库 — 只是那些需要花一个季度才能替换的。
107
- - **边界和范围决策。** "客户数据由 Customer 上下文拥有;其他上下文仅通过 ID 引用它。"明确的"不做"和"要做"同样有价值。
108
- - **有意偏离显而易见路径的决策。** "我们使用手动 SQL 而不是 ORM,因为 X。"
109
- - **代码中不可见的约束。** "由于合规要求,我们不能使用 AWS。" "由于合作伙伴 API 合同,响应时间必须低于 200ms。"
110
- - **拒绝的原因不明显的被拒绝替代方案。** 如果你考虑了 GraphQL 而因微妙原因选择了 REST,记录下来 — 否则 6 个月后有人会再次建议 GraphQL。
111
-
112
- ## 3. CONTEXT.md 格式
113
-
114
- ### 规则
115
-
116
- - **要有主见。** 当同一概念存在多个词时,选择最好的那个,并将其他的列在 `_Avoid_` 下。
117
- - **定义保持精炼。** 最多一两句话。定义它是什么,而不是它做什么。
118
- - **仅包含特定于该项目上下文的术语。** 通用的编程概念(超时、错误类型、工具模式)即使项目广泛使用也不属于这里。添加术语前自问:这是该上下文独有的概念,还是一个通用编程概念?只有前者才属于这里。
119
- - **当自然形成聚类时,用子标题分组术语。** 如果所有术语属于一个单一的凝聚领域,扁平列表也可以。
120
- - **随时增删改。** 模型演进时,直接修改文件:添加新术语、删除废弃术语、修正定义、术语更名。不要堆积 — 保持词汇表精炼且反映当前模型。
121
-
122
- ### 模板
123
-
124
- <context_template>
125
- # {项目名称} 领域词汇表
126
-
127
- {对该上下文是什么以及为什么存在的一两句话描述。}
128
-
129
- ## {术语分组}
130
-
131
- **Order**:
132
- {对该术语的一两句话描述}
133
- _Avoid_: Purchase, transaction
134
-
135
- **Invoice**:
136
- 发货后发送给客户的付款请求。
137
- _Avoid_: Bill, payment request
138
-
139
- **Customer**:
140
- 下订单的个人或组织。
141
- _Avoid_: Client, buyer, account
142
- </context_template>
143
-
144
- ## 4. ADR.md 格式
145
-
146
- 所有架构决策记录存放在仓库根目录的单一 `ADR.md` 文件中。
147
-
148
- ### 模板
149
-
150
- <adr_template>
151
- # 架构决策记录
152
-
153
- ## 0001: {决策的简短标题}
154
-
155
- {1-3 句话:背景是什么,我们做了什么决策,以及为什么。}
156
-
157
- ---
158
-
159
- ## 0002: {另一决策标题}
160
-
161
- {1-3 句话描述。}
162
-
163
- ---
164
- </adr_template>
165
-
166
- 每个决策是一个 `##` 二级标题,编号从 `0001` 开始顺序递增。决策之间用 `---` 分隔。
167
-
168
- 就这样。一个 ADR 条目可以就是一个段落。其价值在于记录*已经*做出了决策以及*为什么* — 而不是填满各个部分。
169
-
170
- ### 追加新决策
171
-
172
- 1. 读取 `ADR.md`,找到最高现有编号
173
- 2. 编号加 1
174
- 3. 在文件末尾追加新条目
175
-
176
- ### 可选附加元素
177
-
178
- 仅当它们真正增加价值时才包含这些。大多数 ADR 不需要它们:
179
-
180
- - **日期** — 在标题行的 `{标题}` 后面加 `(YYYY-MM-DD)`
181
- - **Status** — `**Status**: proposed | accepted | deprecated | superseded by ADR-NNNN`。当决策被重新审视时,直接修改状态标记
182
- - **Considered Options** — 仅当被拒绝的替代方案值得记住时
183
- - **Consequences** — 仅当需要指出非显而易见的下游影响时
184
-
185
- ### 带可选元素的示例
186
-
187
- <adr_example>
188
- ## 0003: 写模型采用事件溯源(2025-03-15)
189
-
190
- **Status**: accepted
191
-
192
- Order 聚合需要完整的变更历史用于审计和补偿。我们选择事件溯源 —
193
- 所有状态变更作为不可变事件存储,当前状态从中投影。
194
-
195
- **Considered Options**:
196
- - 事件溯源(已选)— 天然审计日志,支持时间旅行调试
197
- - CRUD + 审计表 — 更简单,但审计日志与业务逻辑解耦,容易不同步
198
- - 仅 CRUD — 无审计历史,不满足合规要求
199
-
200
- **Consequences**:
201
- - 写路径复杂度增加;读路径需要投影
202
- - 事件 schema 演进需要显式版本策略
203
- </adr_example>
204
-
205
- ### 修改已有决策
206
-
207
- - **澄清或补充后果** — 直接编辑条目正文
208
- - **改变状态** — 修改 `**Status**` 字段(如 accepted → deprecated)
209
- - **废弃** — 将状态改为 `deprecated`,如被新决策替代则加上 `superseded by ADR-NNNN`
210
- - **不要删除** — 即使决策被废弃,保留条目作为历史上下文
211
-
212
- ### 何时提供 ADR
213
-
214
- 以下三个条件必须同时为真:
215
-
216
- 1. **难以逆转** — 以后改变主意的成本是实质性的
217
- 2. **没有上下文的话令人惊讶** — 未来的读者会看着代码想"他们到底为什么这样做?"
218
- 3. **真实权衡的结果** — 确实存在替代方案,你基于特定原因选择了一个
219
-
220
- 如果决策容易逆转,跳过它 — 你反正会逆转的。如果不令人惊讶,没人会想为什么。如果没有真正的替代方案,那就没有可记录的,除了"我们做了显而易见的事"。
221
-
222
- ### 什么算作
223
-
224
- - **架构形态。** "我们使用 monorepo。" "写模型采用事件溯源,读模型投影到 Postgres。"
225
- - **上下文间的集成模式。** "Ordering 和 Billing 通过领域事件通信,而非同步 HTTP。"
226
- - **带来锁定效应的技术选择。** 数据库、消息总线、认证提供商、部署目标。不是每个库 — 只是那些需要花一个季度才能替换的。
227
- - **边界和范围决策。** "客户数据由 Customer 上下文拥有;其他上下文仅通过 ID 引用它。"明确的"不做"和"要做"同样有价值。
228
- - **有意偏离显而易见路径的决策。** "我们使用手动 SQL 而不是 ORM,因为 X。"
229
- - **代码中不可见的约束。** "由于合规要求,我们不能使用 AWS。" "由于合作伙伴 API 合同,响应时间必须低于 200ms。"
230
- - **拒绝的原因不明显的被拒绝替代方案。** 如果你考虑了 GraphQL 而因微妙原因选择了 REST,记录下来 — 否则 6 个月后有人会再次建议 GraphQL。
231
-
232
- ## 5. LOG.md 格式
233
-
234
- ### 规则
235
-
236
- - **记录每一次设计结论。** 无论大小,只要在访谈中确认、延后或被替代,都写入 LOG.md。宁可多记,不要遗漏。
237
- - **状态驱动。** 每个条目明确标记 `accepted`、`deferred` 或 `superseded`,让读者一眼知道当前有效性。
238
- - **关联 ADR。** 如果该结论同时满足 ADR 的三个条件,在 LOG 中标注 `Related: ADR-XXXX`,并在对应 ADR 条目中也关联回 LOG。
239
- - **保持可修订。** 后续决定改变既有结论时,直接更新原条目状态和正文,不要新建一条矛盾的条目。标注 `Superseded by: LOG-XXXX`。
240
- - **不堆积废弃条目。** 被替代的条目保留但标记清楚;延后(deferred)的条目保留以便后续恢复讨论。
241
- - **记录具体交互和边界。** 与 CONTEXT.md 的精炼不同,LOG.md 可以记录讨论中的具体场景、边界条件和交互细节。
242
-
243
- ### 模板
244
-
245
- <log_template>
246
- # 设计决策日志
247
-
248
- 本文件记录设计访谈中已经确认、延后或被替代的具体结论。它保存"当时讨论了什么、最终固定了什么行为以及对应哪个 ADR";`CONTEXT.md` 是规范词汇表,`ADR.md` 是难以逆转的架构决策,本文件则是可持续增删改的完整设计轨迹。
249
-
250
- ## 维护规则
251
-
252
- - 每次完成一个设计问答,同步更新 `LOG.md`、`CONTEXT.md` 与 `ADR.md`。
253
- - 已确认结论使用 `accepted`;暂不决定使用 `deferred`;被后续决定替代使用 `superseded`。
254
- - 后续确认改变既有结论时,直接修订原日志条目,并记录替代关系,不保留互相矛盾的"现行规则"。
255
- - 日志可以记录具体交互和边界;词汇表保持精炼;ADR 只记录难以逆转、令人意外且存在真实权衡的决定。
256
-
257
- ## LOG-0001: {决策的简短标题}
258
-
259
- Status: accepted
260
- Related: ADR-0001
261
-
262
- {背景:讨论了什么问题,做出了什么决定,以及为什么。可以记录具体的交互过程、边界场景和固定行为。}
263
-
264
- ## LOG-0002: {另一决策标题}
265
-
266
- Status: deferred
267
-
268
- {为什么暂不决定,以及后续恢复讨论时应从什么问题开始。}
269
-
270
- ## LOG-0003: {被替代的决策标题}
271
-
272
- Status: superseded
273
- Superseded by: LOG-0004
274
-
275
- {原决策内容,以及为什么被替代。保留作为设计演进的历史上下文。}
276
- </log_template>
277
-
278
- ### 追加新日志
279
-
280
- 1. 读取 `LOG.md`,找到最高现有编号
281
- 2. 编号加 1
282
- 3. 在文件末尾追加新条目
283
-
284
- ### 修改已有日志
285
-
286
- - **改变结论** — 将原条目状态改为 `superseded`,标注 `Superseded by: LOG-XXXX`,在新条目中说明替代原因
287
- - **延后决定被重新讨论** — 将状态从 `deferred` 改为 `accepted`,或新建条目替代原条目
288
- - **补充细节** — 直接编辑条目正文,不改变状态
289
- - **不要删除** — 即使结论被替代,保留条目作为设计演进的历史上下文