openspec-cn 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +153 -0
  3. package/bin/openspec.js +3 -0
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +480 -0
  6. package/dist/commands/change.d.ts +35 -0
  7. package/dist/commands/change.js +277 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +257 -0
  10. package/dist/commands/config.d.ts +8 -0
  11. package/dist/commands/config.js +198 -0
  12. package/dist/commands/feedback.d.ts +9 -0
  13. package/dist/commands/feedback.js +183 -0
  14. package/dist/commands/schema.d.ts +6 -0
  15. package/dist/commands/schema.js +869 -0
  16. package/dist/commands/show.d.ts +14 -0
  17. package/dist/commands/show.js +132 -0
  18. package/dist/commands/spec.d.ts +15 -0
  19. package/dist/commands/spec.js +225 -0
  20. package/dist/commands/validate.d.ts +24 -0
  21. package/dist/commands/validate.js +294 -0
  22. package/dist/commands/workflow/index.d.ts +17 -0
  23. package/dist/commands/workflow/index.js +12 -0
  24. package/dist/commands/workflow/instructions.d.ts +29 -0
  25. package/dist/commands/workflow/instructions.js +381 -0
  26. package/dist/commands/workflow/new-change.d.ts +11 -0
  27. package/dist/commands/workflow/new-change.js +44 -0
  28. package/dist/commands/workflow/schemas.d.ts +10 -0
  29. package/dist/commands/workflow/schemas.js +34 -0
  30. package/dist/commands/workflow/shared.d.ts +52 -0
  31. package/dist/commands/workflow/shared.js +111 -0
  32. package/dist/commands/workflow/status.d.ts +14 -0
  33. package/dist/commands/workflow/status.js +58 -0
  34. package/dist/commands/workflow/templates.d.ts +16 -0
  35. package/dist/commands/workflow/templates.js +68 -0
  36. package/dist/core/archive.d.ts +11 -0
  37. package/dist/core/archive.js +280 -0
  38. package/dist/core/artifact-graph/graph.d.ts +56 -0
  39. package/dist/core/artifact-graph/graph.js +141 -0
  40. package/dist/core/artifact-graph/index.d.ts +7 -0
  41. package/dist/core/artifact-graph/index.js +13 -0
  42. package/dist/core/artifact-graph/instruction-loader.d.ts +143 -0
  43. package/dist/core/artifact-graph/instruction-loader.js +214 -0
  44. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  45. package/dist/core/artifact-graph/resolver.js +257 -0
  46. package/dist/core/artifact-graph/schema.d.ts +13 -0
  47. package/dist/core/artifact-graph/schema.js +108 -0
  48. package/dist/core/artifact-graph/state.d.ts +12 -0
  49. package/dist/core/artifact-graph/state.js +54 -0
  50. package/dist/core/artifact-graph/types.d.ts +45 -0
  51. package/dist/core/artifact-graph/types.js +43 -0
  52. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  53. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  54. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  55. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  56. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  57. package/dist/core/command-generation/adapters/auggie.js +27 -0
  58. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  59. package/dist/core/command-generation/adapters/claude.js +50 -0
  60. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  61. package/dist/core/command-generation/adapters/cline.js +27 -0
  62. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  63. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  64. package/dist/core/command-generation/adapters/codex.d.ts +13 -0
  65. package/dist/core/command-generation/adapters/codex.js +27 -0
  66. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  67. package/dist/core/command-generation/adapters/continue.js +28 -0
  68. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/costrict.js +27 -0
  70. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/crush.js +30 -0
  72. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  73. package/dist/core/command-generation/adapters/cursor.js +44 -0
  74. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  75. package/dist/core/command-generation/adapters/factory.js +27 -0
  76. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  77. package/dist/core/command-generation/adapters/gemini.js +26 -0
  78. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  79. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  80. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/iflow.js +29 -0
  82. package/dist/core/command-generation/adapters/index.d.ts +27 -0
  83. package/dist/core/command-generation/adapters/index.js +27 -0
  84. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  85. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  86. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/opencode.js +26 -0
  88. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  89. package/dist/core/command-generation/adapters/qoder.js +30 -0
  90. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  91. package/dist/core/command-generation/adapters/qwen.js +26 -0
  92. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  93. package/dist/core/command-generation/adapters/roocode.js +27 -0
  94. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  95. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  96. package/dist/core/command-generation/generator.d.ts +21 -0
  97. package/dist/core/command-generation/generator.js +27 -0
  98. package/dist/core/command-generation/index.d.ts +22 -0
  99. package/dist/core/command-generation/index.js +24 -0
  100. package/dist/core/command-generation/registry.d.ts +36 -0
  101. package/dist/core/command-generation/registry.js +88 -0
  102. package/dist/core/command-generation/types.d.ts +55 -0
  103. package/dist/core/command-generation/types.js +8 -0
  104. package/dist/core/completions/command-registry.d.ts +7 -0
  105. package/dist/core/completions/command-registry.js +456 -0
  106. package/dist/core/completions/completion-provider.d.ts +60 -0
  107. package/dist/core/completions/completion-provider.js +102 -0
  108. package/dist/core/completions/factory.d.ts +64 -0
  109. package/dist/core/completions/factory.js +75 -0
  110. package/dist/core/completions/generators/bash-generator.d.ts +32 -0
  111. package/dist/core/completions/generators/bash-generator.js +174 -0
  112. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  113. package/dist/core/completions/generators/fish-generator.js +157 -0
  114. package/dist/core/completions/generators/powershell-generator.d.ts +33 -0
  115. package/dist/core/completions/generators/powershell-generator.js +207 -0
  116. package/dist/core/completions/generators/zsh-generator.d.ts +44 -0
  117. package/dist/core/completions/generators/zsh-generator.js +250 -0
  118. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  119. package/dist/core/completions/installers/bash-installer.js +318 -0
  120. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  121. package/dist/core/completions/installers/fish-installer.js +143 -0
  122. package/dist/core/completions/installers/powershell-installer.d.ts +88 -0
  123. package/dist/core/completions/installers/powershell-installer.js +327 -0
  124. package/dist/core/completions/installers/zsh-installer.d.ts +125 -0
  125. package/dist/core/completions/installers/zsh-installer.js +449 -0
  126. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  127. package/dist/core/completions/templates/bash-templates.js +24 -0
  128. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  129. package/dist/core/completions/templates/fish-templates.js +39 -0
  130. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  131. package/dist/core/completions/templates/powershell-templates.js +25 -0
  132. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  133. package/dist/core/completions/templates/zsh-templates.js +36 -0
  134. package/dist/core/completions/types.d.ts +79 -0
  135. package/dist/core/completions/types.js +2 -0
  136. package/dist/core/config-prompts.d.ts +9 -0
  137. package/dist/core/config-prompts.js +34 -0
  138. package/dist/core/config-schema.d.ts +76 -0
  139. package/dist/core/config-schema.js +200 -0
  140. package/dist/core/config.d.ts +17 -0
  141. package/dist/core/config.js +30 -0
  142. package/dist/core/converters/json-converter.d.ts +6 -0
  143. package/dist/core/converters/json-converter.js +51 -0
  144. package/dist/core/global-config.d.ts +39 -0
  145. package/dist/core/global-config.js +115 -0
  146. package/dist/core/index.d.ts +2 -0
  147. package/dist/core/index.js +3 -0
  148. package/dist/core/init.d.ts +32 -0
  149. package/dist/core/init.js +433 -0
  150. package/dist/core/legacy-cleanup.d.ts +162 -0
  151. package/dist/core/legacy-cleanup.js +501 -0
  152. package/dist/core/list.d.ts +9 -0
  153. package/dist/core/list.js +171 -0
  154. package/dist/core/parsers/change-parser.d.ts +13 -0
  155. package/dist/core/parsers/change-parser.js +193 -0
  156. package/dist/core/parsers/markdown-parser.d.ts +22 -0
  157. package/dist/core/parsers/markdown-parser.js +187 -0
  158. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  159. package/dist/core/parsers/requirement-blocks.js +201 -0
  160. package/dist/core/project-config.d.ts +64 -0
  161. package/dist/core/project-config.js +223 -0
  162. package/dist/core/schemas/base.schema.d.ts +13 -0
  163. package/dist/core/schemas/base.schema.js +13 -0
  164. package/dist/core/schemas/change.schema.d.ts +73 -0
  165. package/dist/core/schemas/change.schema.js +31 -0
  166. package/dist/core/schemas/index.d.ts +4 -0
  167. package/dist/core/schemas/index.js +4 -0
  168. package/dist/core/schemas/spec.schema.d.ts +18 -0
  169. package/dist/core/schemas/spec.schema.js +15 -0
  170. package/dist/core/shared/index.d.ts +8 -0
  171. package/dist/core/shared/index.js +8 -0
  172. package/dist/core/shared/skill-generation.d.ts +41 -0
  173. package/dist/core/shared/skill-generation.js +74 -0
  174. package/dist/core/shared/tool-detection.d.ts +66 -0
  175. package/dist/core/shared/tool-detection.js +140 -0
  176. package/dist/core/specs-apply.d.ts +73 -0
  177. package/dist/core/specs-apply.js +384 -0
  178. package/dist/core/styles/palette.d.ts +7 -0
  179. package/dist/core/styles/palette.js +8 -0
  180. package/dist/core/templates/index.d.ts +8 -0
  181. package/dist/core/templates/index.js +9 -0
  182. package/dist/core/templates/skill-templates.d.ts +112 -0
  183. package/dist/core/templates/skill-templates.js +2893 -0
  184. package/dist/core/update.d.ts +42 -0
  185. package/dist/core/update.js +306 -0
  186. package/dist/core/validation/constants.d.ts +34 -0
  187. package/dist/core/validation/constants.js +40 -0
  188. package/dist/core/validation/types.d.ts +18 -0
  189. package/dist/core/validation/types.js +2 -0
  190. package/dist/core/validation/validator.d.ts +33 -0
  191. package/dist/core/validation/validator.js +409 -0
  192. package/dist/core/view.d.ts +8 -0
  193. package/dist/core/view.js +168 -0
  194. package/dist/index.d.ts +3 -0
  195. package/dist/index.js +3 -0
  196. package/dist/prompts/searchable-multi-select.d.ts +27 -0
  197. package/dist/prompts/searchable-multi-select.js +149 -0
  198. package/dist/telemetry/config.d.ts +32 -0
  199. package/dist/telemetry/config.js +68 -0
  200. package/dist/telemetry/index.d.ts +31 -0
  201. package/dist/telemetry/index.js +145 -0
  202. package/dist/ui/ascii-patterns.d.ts +16 -0
  203. package/dist/ui/ascii-patterns.js +133 -0
  204. package/dist/ui/welcome-screen.d.ts +10 -0
  205. package/dist/ui/welcome-screen.js +146 -0
  206. package/dist/utils/change-metadata.d.ts +51 -0
  207. package/dist/utils/change-metadata.js +147 -0
  208. package/dist/utils/change-utils.d.ts +62 -0
  209. package/dist/utils/change-utils.js +121 -0
  210. package/dist/utils/file-system.d.ts +36 -0
  211. package/dist/utils/file-system.js +281 -0
  212. package/dist/utils/index.d.ts +5 -0
  213. package/dist/utils/index.js +7 -0
  214. package/dist/utils/interactive.d.ts +18 -0
  215. package/dist/utils/interactive.js +21 -0
  216. package/dist/utils/item-discovery.d.ts +4 -0
  217. package/dist/utils/item-discovery.js +72 -0
  218. package/dist/utils/match.d.ts +3 -0
  219. package/dist/utils/match.js +22 -0
  220. package/dist/utils/shell-detection.d.ts +20 -0
  221. package/dist/utils/shell-detection.js +41 -0
  222. package/dist/utils/task-progress.d.ts +8 -0
  223. package/dist/utils/task-progress.js +36 -0
  224. package/package.json +84 -0
  225. package/schemas/spec-driven/schema.yaml +148 -0
  226. package/schemas/spec-driven/templates/design.md +19 -0
  227. package/schemas/spec-driven/templates/proposal.md +23 -0
  228. package/schemas/spec-driven/templates/spec.md +8 -0
  229. package/schemas/spec-driven/templates/tasks.md +9 -0
  230. package/schemas/tdd/schema.yaml +213 -0
  231. package/schemas/tdd/templates/docs.md +15 -0
  232. package/schemas/tdd/templates/implementation.md +11 -0
  233. package/schemas/tdd/templates/spec.md +11 -0
  234. package/schemas/tdd/templates/test.md +11 -0
  235. package/scripts/postinstall.js +147 -0
@@ -0,0 +1,148 @@
1
+ name: spec-driven
2
+ version: 1
3
+ description: 默认 OpenSpec 工作流 - proposal → specs → design → tasks
4
+ artifacts:
5
+ - id: proposal
6
+ generates: proposal.md
7
+ description: 概述变更的初始提案文档
8
+ template: proposal.md
9
+ instruction: |
10
+ 创建提案文档,说明本次变更为何需要。
11
+
12
+ Sections:
13
+ - **Why**: 用 1-2 句话描述问题或机会。它解决什么问题?为何现在?
14
+ - **What Changes**: 变更清单(项目符号)。明确说明新增能力、修改或移除的内容。破坏性变更用 **BREAKING** 标记。
15
+ - **Capabilities**: 标明将创建或修改哪些规范:
16
+ - **New Capabilities**: 列出引入的新能力。每项生成 `specs/<name>/spec.md`。使用 kebab-case 命名(例如 `user-auth`、`data-export`)。
17
+ - **Modified Capabilities**: 列出 REQUIREMENTS 有变化的既有能力。仅在规范层面的行为变化时包含(不含纯实现细节)。每项需要一个增量规范文件。参考 `openspec/specs/` 中已有名称。若无需求变化则留空。
18
+ - **Impact**: 影响到的代码、API、依赖或系统。
19
+
20
+ IMPORTANT: Capabilities 部分至关重要,它建立了
21
+ proposal 与 specs 阶段的契约。在填写前先研究现有规范。
22
+ 这里列出的每个能力都需要对应的规范文件。
23
+
24
+ 保持简洁(1-2 页)。聚焦“为什么”,而非“如何实现”——
25
+ 实现细节应放在 design.md。
26
+
27
+ 这是基础文档——specs、design 与 tasks 都建立在它之上。
28
+ requires: []
29
+
30
+ - id: specs
31
+ generates: "specs/**/*.md"
32
+ description: 变更的详细规范
33
+ template: spec.md
34
+ instruction: |
35
+ 创建规范文件,定义系统应做什么(WHAT)。
36
+
37
+ 每个能力/功能领域创建一个规范文件:`specs/<name>/spec.md`。
38
+
39
+ 增量操作(使用 ## 标题):
40
+ - **ADDED Requirements**: New capabilities
41
+ - **MODIFIED Requirements**: Changed behavior - MUST include full updated content
42
+ - **REMOVED Requirements**: Deprecated features - MUST include **Reason** and **Migration**
43
+ - **RENAMED Requirements**: Name changes only - use FROM:/TO: format
44
+
45
+ 需求格式:
46
+ - 每条需求:`### Requirement: <name>`,后接描述
47
+ - 规范性需求使用 SHALL/MUST(避免 should/may)
48
+ - 每个场景:`#### Scenario: <name>`,使用 WHEN/THEN 格式
49
+ - **CRITICAL**: 场景必须使用 4 个井号(`####`)。使用 3 个井号或列表会静默失败。
50
+ - 每条需求必须至少包含一个场景。
51
+
52
+ MODIFIED 需求流程:
53
+ 1. 在 openspec/specs/<capability>/spec.md 中定位现有需求
54
+ 2. 复制完整需求块(从 `### Requirement:` 到所有场景)
55
+ 3. 粘贴到 `## MODIFIED Requirements` 下并编辑为新行为
56
+ 4. 确保标题文本完全一致(忽略空白)
57
+
58
+ 常见误区:用 MODIFIED 只写部分内容会在归档时丢失细节。
59
+ 如果只是新增关注点而不改变现有行为,请改用 ADDED。
60
+
61
+ Example:
62
+ ```
63
+ ## ADDED Requirements
64
+
65
+ ### Requirement: User can export data
66
+ The system SHALL allow users to export their data in CSV format.
67
+
68
+ #### Scenario: Successful export
69
+ - **WHEN** user clicks "Export" button
70
+ - **THEN** system downloads a CSV file with all user data
71
+
72
+ ## REMOVED Requirements
73
+
74
+ ### Requirement: Legacy export
75
+ **Reason**: Replaced by new export system
76
+ **Migration**: Use new export endpoint at /api/v2/export
77
+ ```
78
+
79
+ 规范应可测试——每个场景都是潜在测试用例。
80
+ requires:
81
+ - proposal
82
+
83
+ - id: design
84
+ generates: design.md
85
+ description: 包含实现细节的技术设计文档
86
+ template: design.md
87
+ instruction: |
88
+ 创建设计文档,说明如何实现本次变更(HOW)。
89
+
90
+ 何时需要 design.md(满足任一项才创建):
91
+ - 跨模块/跨服务变更或新的架构模式
92
+ - 新的外部依赖或显著的数据模型变更
93
+ - 安全、性能或迁移复杂度较高
94
+ - 存在需要先做技术决策的歧义
95
+
96
+ Sections:
97
+ - **Context**: 背景、现状、约束与相关方
98
+ - **Goals / Non-Goals**: 设计要达成的目标与明确排除的范围
99
+ - **Decisions**: 关键技术选择及其理由(为何选 X 而非 Y)。每项决策需包含考虑过的替代方案。
100
+ - **Risks / Trade-offs**: 已知限制与可能出错之处。格式:[风险] → 缓解措施
101
+ - **Migration Plan**: 上线步骤与回滚策略(如适用)
102
+ - **Open Questions**: 待解决的决策或未知点
103
+
104
+ 聚焦架构与方案,而非逐行实现细节。
105
+ 动机参考 proposal,需求参考 specs。
106
+
107
+ 优秀的设计文档应解释技术决策背后的“why”。
108
+ requires:
109
+ - proposal
110
+
111
+ - id: tasks
112
+ generates: tasks.md
113
+ description: 从规格与设计中拆解出的实现任务
114
+ template: tasks.md
115
+ instruction: |
116
+ 创建任务列表,拆解实现工作。
117
+
118
+ Guidelines:
119
+ - 使用 ## 编号标题分组相关任务
120
+ - 每项任务为复选框:- [ ] X.Y 任务描述
121
+ - 任务应足够小,便于一次会话内完成
122
+ - 按依赖顺序排列任务(先做哪些)
123
+
124
+ Example:
125
+ ```
126
+ ## 1. Setup
127
+
128
+ - [ ] 1.1 Create new module structure
129
+ - [ ] 1.2 Add dependencies to package.json
130
+
131
+ ## 2. Core Implementation
132
+
133
+ - [ ] 2.1 Implement data export function
134
+ - [ ] 2.2 Add CSV formatting utilities
135
+ ```
136
+
137
+ 依据 specs 确定要做什么,依据 design 确定如何做。
138
+ 每项任务应可验证——完成与否清晰可判断。
139
+ requires:
140
+ - specs
141
+ - design
142
+
143
+ apply:
144
+ requires: [tasks]
145
+ tracks: tasks.md
146
+ instruction: |
147
+ 阅读上下文文件,逐项完成待办任务,完成后立即标记。
148
+ 若遇到阻塞或需要澄清,暂停并说明情况。
@@ -0,0 +1,19 @@
1
+ ## Context
2
+
3
+ <!-- 背景与现状 -->
4
+
5
+ ## Goals / Non-Goals
6
+
7
+ **Goals:**
8
+ <!-- 该设计要达成的目标 -->
9
+
10
+ **Non-Goals:**
11
+ <!-- 明确不在范围内的内容 -->
12
+
13
+ ## Decisions
14
+
15
+ <!-- 关键设计决策与理由 -->
16
+
17
+ ## Risks / Trade-offs
18
+
19
+ <!-- 已知风险与权衡 -->
@@ -0,0 +1,23 @@
1
+ ## Why
2
+
3
+ <!-- 说明本次变更的动机。它解决什么问题?为何现在要做? -->
4
+
5
+ ## What Changes
6
+
7
+ <!-- 描述将发生的变化。明确说明新增能力、修改或移除的内容。 -->
8
+
9
+ ## Capabilities
10
+
11
+ ### New Capabilities
12
+ <!-- 引入的新能力。将 <name> 替换为 kebab-case 标识符(例如 user-auth、data-export、api-rate-limiting)。每项都会生成 specs/<name>/spec.md -->
13
+ - `<name>`: <此能力涵盖内容的简要说明>
14
+
15
+ ### Modified Capabilities
16
+ <!-- 需求发生变化的既有能力(不仅是实现变化)。
17
+ 仅在规范层面的行为发生变化时列出。每项都需要一个增量规范文件。
18
+ 使用 openspec/specs/ 中已有的规范名称。若无需求变化则留空。 -->
19
+ - `<existing-name>`: <变更的需求是什么>
20
+
21
+ ## Impact
22
+
23
+ <!-- 影响到的代码、API、依赖或系统 -->
@@ -0,0 +1,8 @@
1
+ ## ADDED Requirements
2
+
3
+ ### Requirement: <!-- 需求名称 -->
4
+ <!-- 需求描述 -->
5
+
6
+ #### Scenario: <!-- 场景名称 -->
7
+ - **WHEN** <!-- 条件 -->
8
+ - **THEN** <!-- 预期结果 -->
@@ -0,0 +1,9 @@
1
+ ## 1. <!-- 任务分组名称 -->
2
+
3
+ - [ ] 1.1 <!-- 任务描述 -->
4
+ - [ ] 1.2 <!-- 任务描述 -->
5
+
6
+ ## 2. <!-- 任务分组名称 -->
7
+
8
+ - [ ] 2.1 <!-- 任务描述 -->
9
+ - [ ] 2.2 <!-- 任务描述 -->
@@ -0,0 +1,213 @@
1
+ name: tdd
2
+ version: 1
3
+ description: 测试驱动开发工作流 - tests → implementation → docs
4
+ artifacts:
5
+ - id: spec
6
+ generates: spec.md
7
+ description: 定义需求的功能规范
8
+ template: spec.md
9
+ instruction: |
10
+ 创建功能规范,定义要构建的内容(WHAT)。
11
+
12
+ Sections:
13
+ - **Feature**: 功能名称与高层描述(目的与用户价值)
14
+ - **Requirements**: 具体需求列表,规范性表述使用 SHALL/MUST
15
+ - **Acceptance Criteria**: 采用 WHEN/THEN 格式的可测试标准
16
+
17
+ 需求格式:
18
+ - 每条需求应具体且可测试
19
+ - 验收标准使用 `#### Scenario: <name>` 并采用 WHEN/THEN 格式
20
+ - 明确列出边界情况与错误场景
21
+ - 每条需求必须至少包含一个场景
22
+
23
+ Example:
24
+ ```
25
+ ## Feature: User Authentication
26
+
27
+ Users can securely log into the application.
28
+
29
+ ## Requirements
30
+
31
+ ### Requirement: Password validation
32
+ The system SHALL validate passwords meet minimum security requirements.
33
+
34
+ #### Scenario: Valid password accepted
35
+ - **WHEN** password has 8+ chars, uppercase, lowercase, and number
36
+ - **THEN** password is accepted
37
+
38
+ #### Scenario: Weak password rejected
39
+ - **WHEN** password is less than 8 characters
40
+ - **THEN** system displays "Password too short" error
41
+ ```
42
+
43
+ 此规范驱动测试编写——每个场景都会成为一个测试用例。
44
+ requires: []
45
+
46
+ - id: tests
47
+ generates: "tests/*.test.ts"
48
+ description: 在实现前编写的测试文件
49
+ template: test.md
50
+ instruction: |
51
+ 在实现前编写测试(TDD 红阶段)。
52
+
53
+ 文件命名:
54
+ - 测试文件命名为 `tests/<feature>.test.ts`
55
+ - 每个功能/能力对应一个测试文件
56
+ - 使用与规范一致的描述性名称
57
+
58
+ 测试结构:
59
+ - 使用 Given/When/Then 格式,与规范场景保持一致
60
+ - 相关测试使用 `describe()` 分组
61
+ - 规范中的每个场景至少对应一个 `it()` 测试
62
+
63
+ 覆盖要求:
64
+ - 覆盖规范中的每条需求
65
+ - 包含正常路径(成功案例)
66
+ - 包含边界情况(临界条件)
67
+ - 包含错误场景(非法输入、失败)
68
+ - 初始测试应失败(尚未实现)
69
+
70
+ Example:
71
+ ```typescript
72
+ describe('Password validation', () => {
73
+ it('accepts valid password with all requirements', () => {
74
+ // GIVEN a password meeting all requirements
75
+ const password = 'SecurePass1';
76
+ // WHEN validating
77
+ const result = validatePassword(password);
78
+ // THEN it should be accepted
79
+ expect(result.valid).toBe(true);
80
+ });
81
+
82
+ it('rejects password shorter than 8 characters', () => {
83
+ // GIVEN a short password
84
+ const password = 'Short1';
85
+ // WHEN validating
86
+ const result = validatePassword(password);
87
+ // THEN it should be rejected with message
88
+ expect(result.valid).toBe(false);
89
+ expect(result.error).toBe('Password too short');
90
+ });
91
+ });
92
+ ```
93
+
94
+ 严格遵循规范需求——测试用于验证规范。
95
+ requires:
96
+ - spec
97
+
98
+ - id: implementation
99
+ generates: "src/*.ts"
100
+ description: 让测试通过的实现代码
101
+ template: implementation.md
102
+ instruction: |
103
+ 实现功能以让测试通过(TDD 绿阶段)。
104
+
105
+ TDD 工作流:
106
+ 1. 运行测试,确认失败(红)
107
+ 2. 编写最少代码让一个测试通过
108
+ 3. 运行测试,确认通过(绿)
109
+ 4. 需要时重构,同时保持测试通过
110
+ 5. 对下一个失败测试重复
111
+
112
+ 实现准则:
113
+ - 为通过测试写最少代码——不多不少
114
+ - 频繁运行测试以验证进度
115
+ - 函数保持小而专注
116
+ - 使用清晰、可读的名称
117
+
118
+ 代码组织:
119
+ - 在 `src/<feature>.ts` 中创建源文件
120
+ - 清晰导出公共 API
121
+ - 实现细节保持私有
122
+ - 为公共函数添加 JSDoc 注释
123
+
124
+ Example structure:
125
+ ```typescript
126
+ /**
127
+ * Validates a password meets security requirements.
128
+ * @param password - The password to validate
129
+ * @returns Validation result with valid flag and optional error
130
+ */
131
+ export function validatePassword(password: string): ValidationResult {
132
+ if (password.length < 8) {
133
+ return { valid: false, error: 'Password too short' };
134
+ }
135
+ // ... additional checks
136
+ return { valid: true };
137
+ }
138
+ ```
139
+
140
+ 不要过度设计——只实现测试要求的内容。
141
+ requires:
142
+ - tests
143
+
144
+ - id: docs
145
+ generates: "docs/*.md"
146
+ description: 已实现功能的文档
147
+ template: docs.md
148
+ instruction: |
149
+ 为已实现的功能编写文档。
150
+
151
+ Sections:
152
+ - **Overview**: 功能说明与存在原因(1-2 段)
153
+ - **Getting Started**: 可立即使用的快速上手指南
154
+ - **Examples**: 展示常见用例的代码示例
155
+ - **Reference**: 详细 API 文档与配置选项
156
+
157
+ Guidelines:
158
+ - 面向用户,而非开发者
159
+ - 从最常见用例开始
160
+ - 提供可复制粘贴的代码示例
161
+ - 记录所有配置项及其默认值
162
+ - 说明限制、边界情况与注意事项
163
+ - 链接相关功能或规范
164
+
165
+ Example structure:
166
+ ```markdown
167
+ ## Overview
168
+
169
+ Password validation ensures user passwords meet security requirements
170
+ before account creation or password changes.
171
+
172
+ ## Getting Started
173
+
174
+ Import and use the validation function:
175
+
176
+ ```typescript
177
+ import { validatePassword } from './password';
178
+
179
+ const result = validatePassword('MySecurePass1');
180
+ if (!result.valid) {
181
+ console.error(result.error);
182
+ }
183
+ ```
184
+
185
+ ## Examples
186
+
187
+ ### Basic validation
188
+ ...
189
+
190
+ ### Custom error handling
191
+ ...
192
+
193
+ ## Reference
194
+
195
+ ### validatePassword(password)
196
+
197
+ | Parameter | Type | Description |
198
+ |-----------|------|-------------|
199
+ | password | string | The password to validate |
200
+
201
+ **Returns**: `{ valid: boolean, error?: string }`
202
+ ```
203
+
204
+ 需求参考规范,细节参考实现。
205
+ requires:
206
+ - implementation
207
+
208
+ apply:
209
+ requires: [tests]
210
+ tracks: null
211
+ instruction: |
212
+ 运行测试查看失败项。编写最少代码逐一通过。
213
+ 重构时保持测试通过。
@@ -0,0 +1,15 @@
1
+ ## Overview
2
+
3
+ <!-- 功能概述 -->
4
+
5
+ ## Getting Started
6
+
7
+ <!-- 快速上手指南 -->
8
+
9
+ ## Examples
10
+
11
+ <!-- 代码示例 -->
12
+
13
+ ## Reference
14
+
15
+ <!-- API 参考或补充细节 -->
@@ -0,0 +1,11 @@
1
+ ## Implementation Notes
2
+
3
+ <!-- 技术实现细节 -->
4
+
5
+ ## API
6
+
7
+ <!-- 公共 API 文档 -->
8
+
9
+ ## Usage
10
+
11
+ <!-- 使用示例 -->
@@ -0,0 +1,11 @@
1
+ ## Feature: <!-- 功能名称 -->
2
+
3
+ <!-- 功能描述 -->
4
+
5
+ ## Requirements
6
+
7
+ <!-- 需求列表 -->
8
+
9
+ ## Acceptance Criteria
10
+
11
+ <!-- 验收标准列表 -->
@@ -0,0 +1,11 @@
1
+ ## Test Plan
2
+
3
+ <!-- 描述测试策略 -->
4
+
5
+ ## Test Cases
6
+
7
+ ### <!-- 测试用例名称 -->
8
+
9
+ - **Given:** <!-- 前置条件 -->
10
+ - **When:** <!-- 操作 -->
11
+ - **Then:** <!-- 预期结果 -->
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Postinstall script for auto-installing shell completions
5
+ *
6
+ * This script runs automatically after npm install unless:
7
+ * - CI=true environment variable is set
8
+ * - OPENSPEC_NO_COMPLETIONS=1 environment variable is set
9
+ * - dist/ directory doesn't exist (dev setup scenario)
10
+ *
11
+ * The script never fails npm install - all errors are caught and handled gracefully.
12
+ */
13
+
14
+ import { promises as fs } from 'fs';
15
+ import path from 'path';
16
+ import { fileURLToPath } from 'url';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+
21
+ /**
22
+ * Check if we should skip installation
23
+ */
24
+ function shouldSkipInstallation() {
25
+ // Skip in CI environments
26
+ if (process.env.CI === 'true' || process.env.CI === '1') {
27
+ return { skip: true, reason: 'CI environment detected' };
28
+ }
29
+
30
+ // Skip if user opted out
31
+ if (process.env.OPENSPEC_NO_COMPLETIONS === '1') {
32
+ return { skip: true, reason: 'OPENSPEC_NO_COMPLETIONS=1 set' };
33
+ }
34
+
35
+ return { skip: false };
36
+ }
37
+
38
+ /**
39
+ * Check if dist/ directory exists
40
+ */
41
+ async function distExists() {
42
+ const distPath = path.join(__dirname, '..', 'dist');
43
+ try {
44
+ const stat = await fs.stat(distPath);
45
+ return stat.isDirectory();
46
+ } catch {
47
+ return false;
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Detect the user's shell
53
+ */
54
+ async function detectShell() {
55
+ try {
56
+ const { detectShell } = await import('../dist/utils/shell-detection.js');
57
+ const result = detectShell();
58
+ return result.shell;
59
+ } catch (error) {
60
+ // Fail silently if detection module doesn't exist
61
+ return undefined;
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Install completions for the detected shell
67
+ */
68
+ async function installCompletions(shell) {
69
+ try {
70
+ const { CompletionFactory } = await import('../dist/core/completions/factory.js');
71
+ const { COMMAND_REGISTRY } = await import('../dist/core/completions/command-registry.js');
72
+
73
+ // Check if shell is supported
74
+ if (!CompletionFactory.isSupported(shell)) {
75
+ console.log(`\nTip: Run 'openspec completion install' for shell completions`);
76
+ return;
77
+ }
78
+
79
+ // Generate completion script
80
+ const generator = CompletionFactory.createGenerator(shell);
81
+ const script = generator.generate(COMMAND_REGISTRY);
82
+
83
+ // Install completion script
84
+ const installer = CompletionFactory.createInstaller(shell);
85
+ const result = await installer.install(script);
86
+
87
+ if (result.success) {
88
+ // Show success message based on installation type
89
+ if (result.isOhMyZsh) {
90
+ console.log(`✓ Shell completions installed`);
91
+ console.log(` Restart shell: exec zsh`);
92
+ } else if (result.zshrcConfigured) {
93
+ console.log(`✓ Shell completions installed and configured`);
94
+ console.log(` Restart shell: exec zsh`);
95
+ } else {
96
+ console.log(`✓ Shell completions installed to ~/.zsh/completions/`);
97
+ console.log(` Add to ~/.zshrc: fpath=(~/.zsh/completions $fpath)`);
98
+ console.log(` Then: exec zsh`);
99
+ }
100
+ } else {
101
+ // Installation failed, show tip for manual install
102
+ console.log(`\nTip: Run 'openspec completion install' for shell completions`);
103
+ }
104
+ } catch (error) {
105
+ // Fail gracefully - show tip for manual install
106
+ console.log(`\nTip: Run 'openspec completion install' for shell completions`);
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Main function
112
+ */
113
+ async function main() {
114
+ try {
115
+ // Check if we should skip
116
+ const skipCheck = shouldSkipInstallation();
117
+ if (skipCheck.skip) {
118
+ // Silent skip - no output
119
+ return;
120
+ }
121
+
122
+ // Check if dist/ exists (skip silently if not - expected during dev setup)
123
+ if (!(await distExists())) {
124
+ return;
125
+ }
126
+
127
+ // Detect shell
128
+ const shell = await detectShell();
129
+ if (!shell) {
130
+ console.log(`\nTip: Run 'openspec completion install' for shell completions`);
131
+ return;
132
+ }
133
+
134
+ // Install completions
135
+ await installCompletions(shell);
136
+ } catch (error) {
137
+ // Fail gracefully - never break npm install
138
+ // Show tip for manual install
139
+ console.log(`\nTip: Run 'openspec completion install' for shell completions`);
140
+ }
141
+ }
142
+
143
+ // Run main and handle any unhandled errors
144
+ main().catch(() => {
145
+ // Silent failure - never break npm install
146
+ process.exit(0);
147
+ });