specdo 1.0.2

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 (161) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +308 -0
  3. package/README.zh-CN.md +306 -0
  4. package/bin/specdo.js +3 -0
  5. package/dist/cli/index.d.ts +15 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +297 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/commands/_shared.d.ts +45 -0
  10. package/dist/commands/_shared.d.ts.map +1 -0
  11. package/dist/commands/_shared.js +124 -0
  12. package/dist/commands/_shared.js.map +1 -0
  13. package/dist/commands/apply.d.ts +30 -0
  14. package/dist/commands/apply.d.ts.map +1 -0
  15. package/dist/commands/apply.js +393 -0
  16. package/dist/commands/apply.js.map +1 -0
  17. package/dist/commands/archive.d.ts +25 -0
  18. package/dist/commands/archive.d.ts.map +1 -0
  19. package/dist/commands/archive.js +362 -0
  20. package/dist/commands/archive.js.map +1 -0
  21. package/dist/commands/doctor.d.ts +21 -0
  22. package/dist/commands/doctor.d.ts.map +1 -0
  23. package/dist/commands/doctor.js +180 -0
  24. package/dist/commands/doctor.js.map +1 -0
  25. package/dist/commands/domains.d.ts +14 -0
  26. package/dist/commands/domains.d.ts.map +1 -0
  27. package/dist/commands/domains.js +107 -0
  28. package/dist/commands/domains.js.map +1 -0
  29. package/dist/commands/explore.d.ts +48 -0
  30. package/dist/commands/explore.d.ts.map +1 -0
  31. package/dist/commands/explore.js +378 -0
  32. package/dist/commands/explore.js.map +1 -0
  33. package/dist/commands/init.d.ts +45 -0
  34. package/dist/commands/init.d.ts.map +1 -0
  35. package/dist/commands/init.js +243 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/list.d.ts +23 -0
  38. package/dist/commands/list.d.ts.map +1 -0
  39. package/dist/commands/list.js +135 -0
  40. package/dist/commands/list.js.map +1 -0
  41. package/dist/commands/propose.d.ts +22 -0
  42. package/dist/commands/propose.d.ts.map +1 -0
  43. package/dist/commands/propose.js +316 -0
  44. package/dist/commands/propose.js.map +1 -0
  45. package/dist/commands/show.d.ts +15 -0
  46. package/dist/commands/show.d.ts.map +1 -0
  47. package/dist/commands/show.js +214 -0
  48. package/dist/commands/show.js.map +1 -0
  49. package/dist/commands/status.d.ts +17 -0
  50. package/dist/commands/status.d.ts.map +1 -0
  51. package/dist/commands/status.js +146 -0
  52. package/dist/commands/status.js.map +1 -0
  53. package/dist/commands/sync.d.ts +21 -0
  54. package/dist/commands/sync.d.ts.map +1 -0
  55. package/dist/commands/sync.js +113 -0
  56. package/dist/commands/sync.js.map +1 -0
  57. package/dist/commands/validate.d.ts +117 -0
  58. package/dist/commands/validate.d.ts.map +1 -0
  59. package/dist/commands/validate.js +446 -0
  60. package/dist/commands/validate.js.map +1 -0
  61. package/dist/core/apply-brief-renderer.d.ts +35 -0
  62. package/dist/core/apply-brief-renderer.d.ts.map +1 -0
  63. package/dist/core/apply-brief-renderer.js +242 -0
  64. package/dist/core/apply-brief-renderer.js.map +1 -0
  65. package/dist/core/config-store.d.ts +190 -0
  66. package/dist/core/config-store.d.ts.map +1 -0
  67. package/dist/core/config-store.js +280 -0
  68. package/dist/core/config-store.js.map +1 -0
  69. package/dist/core/context-store.d.ts +96 -0
  70. package/dist/core/context-store.d.ts.map +1 -0
  71. package/dist/core/context-store.js +426 -0
  72. package/dist/core/context-store.js.map +1 -0
  73. package/dist/core/json-schemas.d.ts +349 -0
  74. package/dist/core/json-schemas.d.ts.map +1 -0
  75. package/dist/core/json-schemas.js +125 -0
  76. package/dist/core/json-schemas.js.map +1 -0
  77. package/dist/core/skill-content/cross-domain.d.ts +12 -0
  78. package/dist/core/skill-content/cross-domain.d.ts.map +1 -0
  79. package/dist/core/skill-content/cross-domain.js +291 -0
  80. package/dist/core/skill-content/cross-domain.js.map +1 -0
  81. package/dist/core/skill-content/protocol-examples.d.ts +13 -0
  82. package/dist/core/skill-content/protocol-examples.d.ts.map +1 -0
  83. package/dist/core/skill-content/protocol-examples.js +190 -0
  84. package/dist/core/skill-content/protocol-examples.js.map +1 -0
  85. package/dist/core/skill-content/workflow-content.d.ts +25 -0
  86. package/dist/core/skill-content/workflow-content.d.ts.map +1 -0
  87. package/dist/core/skill-content/workflow-content.js +1572 -0
  88. package/dist/core/skill-content/workflow-content.js.map +1 -0
  89. package/dist/core/skill-exporter.d.ts +186 -0
  90. package/dist/core/skill-exporter.d.ts.map +1 -0
  91. package/dist/core/skill-exporter.js +922 -0
  92. package/dist/core/skill-exporter.js.map +1 -0
  93. package/dist/core/spec-sync.d.ts +65 -0
  94. package/dist/core/spec-sync.d.ts.map +1 -0
  95. package/dist/core/spec-sync.js +226 -0
  96. package/dist/core/spec-sync.js.map +1 -0
  97. package/dist/core/task-parser.d.ts +58 -0
  98. package/dist/core/task-parser.d.ts.map +1 -0
  99. package/dist/core/task-parser.js +244 -0
  100. package/dist/core/task-parser.js.map +1 -0
  101. package/dist/core/template-renderer.d.ts +51 -0
  102. package/dist/core/template-renderer.d.ts.map +1 -0
  103. package/dist/core/template-renderer.js +362 -0
  104. package/dist/core/template-renderer.js.map +1 -0
  105. package/dist/domains/architecture.d.ts +34 -0
  106. package/dist/domains/architecture.d.ts.map +1 -0
  107. package/dist/domains/architecture.js +341 -0
  108. package/dist/domains/architecture.js.map +1 -0
  109. package/dist/domains/backend.d.ts +35 -0
  110. package/dist/domains/backend.d.ts.map +1 -0
  111. package/dist/domains/backend.js +367 -0
  112. package/dist/domains/backend.js.map +1 -0
  113. package/dist/domains/frontend.d.ts +36 -0
  114. package/dist/domains/frontend.d.ts.map +1 -0
  115. package/dist/domains/frontend.js +373 -0
  116. package/dist/domains/frontend.js.map +1 -0
  117. package/dist/domains/index.d.ts +49 -0
  118. package/dist/domains/index.d.ts.map +1 -0
  119. package/dist/domains/index.js +255 -0
  120. package/dist/domains/index.js.map +1 -0
  121. package/dist/domains/operations.d.ts +37 -0
  122. package/dist/domains/operations.d.ts.map +1 -0
  123. package/dist/domains/operations.js +344 -0
  124. package/dist/domains/operations.js.map +1 -0
  125. package/dist/domains/pool-ranking.d.ts +43 -0
  126. package/dist/domains/pool-ranking.d.ts.map +1 -0
  127. package/dist/domains/pool-ranking.js +153 -0
  128. package/dist/domains/pool-ranking.js.map +1 -0
  129. package/dist/domains/quality.d.ts +45 -0
  130. package/dist/domains/quality.d.ts.map +1 -0
  131. package/dist/domains/quality.js +368 -0
  132. package/dist/domains/quality.js.map +1 -0
  133. package/dist/domains/security.d.ts +19 -0
  134. package/dist/domains/security.d.ts.map +1 -0
  135. package/dist/domains/security.js +364 -0
  136. package/dist/domains/security.js.map +1 -0
  137. package/dist/domains/signal-match.d.ts +25 -0
  138. package/dist/domains/signal-match.d.ts.map +1 -0
  139. package/dist/domains/signal-match.js +67 -0
  140. package/dist/domains/signal-match.js.map +1 -0
  141. package/dist/domains/types.d.ts +354 -0
  142. package/dist/domains/types.d.ts.map +1 -0
  143. package/dist/domains/types.js +12 -0
  144. package/dist/domains/types.js.map +1 -0
  145. package/dist/index.d.ts +9 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +9 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/protocols/index.d.ts +36 -0
  150. package/dist/protocols/index.d.ts.map +1 -0
  151. package/dist/protocols/index.js +85 -0
  152. package/dist/protocols/index.js.map +1 -0
  153. package/dist/protocols/review-to-solid.d.ts +32 -0
  154. package/dist/protocols/review-to-solid.d.ts.map +1 -0
  155. package/dist/protocols/review-to-solid.js +309 -0
  156. package/dist/protocols/review-to-solid.js.map +1 -0
  157. package/dist/utils/prompt.d.ts +37 -0
  158. package/dist/utils/prompt.d.ts.map +1 -0
  159. package/dist/utils/prompt.js +81 -0
  160. package/dist/utils/prompt.js.map +1 -0
  161. package/package.json +80 -0
@@ -0,0 +1,306 @@
1
+ <div align="center">
2
+
3
+ # SpecDo
4
+
5
+ **通过结构化规范、领域专家知识和证据驱动的执行,将想法转化为生产级交付物。**
6
+
7
+ [![npm version](https://img.shields.io/npm/v/specdo.svg)](https://www.npmjs.com/package/specdo)
8
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
9
+ [![Node.js](https://img.shields.io/badge/node-%E2%89%A5%2020.19-brightgreen)](https://nodejs.org)
10
+
11
+ </div>
12
+
13
+ > [English](README.md)
14
+
15
+ ---
16
+
17
+ <p align="center">
18
+ <img src="./assets/specdo-architecture.png" alt="SpecDo 架构图" width="100%">
19
+ </p>
20
+
21
+
22
+ ## 为什么选择 SpecDo?
23
+
24
+ 大多数 AI 编码工作流止步于代码生成。
25
+
26
+ SpecDo 专注于**交付**。
27
+
28
+ 与其让 AI"帮我做个东西",不如让 SpecDo 引导人和 AI Agent 走完一条结构化、证据驱动的工作流:
29
+
30
+ ```text
31
+ Explore → Propose → Apply → Sync → Archive
32
+ ```
33
+
34
+ 每一步都产出可审查、可版本化、可审计、可改进的制品。
35
+
36
+ - **本地优先** — 在你本机运行,兼容任何 AI 编码工具
37
+ - **Agent 主导的探索** — AI Agent 按领域索引逐题访谈你(每次变更至少 8 题,典型 10–30 题),再生成方案
38
+ - **全领域覆盖** — 六个工程领域的 checklist 在每个阶段都会注入,即便是你没聊过的领域
39
+ - **证据驱动** — 任务必须附带证据才能归档;每次变更都留下审计轨迹
40
+ - **项目可定制** — 通过 `config.yaml` 用你团队的标准覆盖任意领域阶段
41
+
42
+
43
+
44
+ ---
45
+
46
+ ## 核心概念
47
+
48
+ SpecDo 构建于三个基元之上。
49
+
50
+ ### 工作流
51
+
52
+ 一条闭环流水线,把每次变更从想法一路带到归档证据:
53
+
54
+ ```text
55
+ explore → propose → apply → sync → archive
56
+ ```
57
+
58
+ 每个阶段产出不可变的制品——`proposal.md`、`design.md`、`tasks.md`、`specs/`、`apply-brief.md`——共同构成变更的**唯一事实来源**。
59
+
60
+ ### 领域知识引擎
61
+
62
+ 六个内置领域模块在每个步骤注入阶段适配的专家知识。底层实现上,每个领域是一个带类型的 `DomainModule` 常量——静态编译进 TypeScript,不从文件系统动态加载。
63
+
64
+ | 领域 | 关注点 |
65
+ |--------|-------|
66
+ | **Security(安全)** | 威胁、风险、OWASP Top 10、认证、加密、输入校验 |
67
+ | **Architecture(架构)** | 系统边界、API 设计、ADR、集成模式 |
68
+ | **Operations(运维)** | 发布管理、CI/CD、可观测性、依赖升级 |
69
+ | **Backend(后端)** | 数据模型、查询优化、迁移、错误处理 |
70
+ | **Quality(质量)** | TDD、代码审查、调试、性能分析 |
71
+ | **Frontend(前端)** | 组件、无障碍、Core Web Vitals、响应式设计 |
72
+
73
+ 每个领域提供 **4 个阶段的预编知识**:
74
+
75
+ ```
76
+ explore → signals(触发关键词)+ clarifying questions(澄清问题)
77
+ design → checklists(检查清单)+ patterns(模式)+ anti-patterns(反模式)
78
+ implement → focus areas(关注域)+ patterns(模式)+ common mistakes(常见错误)
79
+ verify → 归档前验证门禁
80
+ ```
81
+
82
+ > **核心设计决策**:`--domains` 控制 explore 阶段你对**哪些领域提问**。`propose` 始终把**全部 6 个领域的 checklist** 注入 design.md 和 tasks.md。`apply` 按任务标题动态做信号打分匹配领域,无命中时回退到 propose 时使用的领域列表。
83
+
84
+ ### 协议
85
+
86
+ 除了"关注什么"(领域),SpecDo 还定义了"怎么执行"(协议):
87
+
88
+ - **review-to-solid** — 一个 7 步循环硬化工作流:scope → audit → findings → fix → re-review → converge,包含 P1/P2/P3 严重等级评分和必填的 Delta Table 产出。
89
+
90
+ 协议在 quality 领域激活时注入 `apply-brief.md`。
91
+
92
+ ---
93
+
94
+ ## 快速开始
95
+
96
+ ```bash
97
+ # 1. 安装(需要 Node.js ≥ 20.19)
98
+ npm install specdo -g
99
+
100
+ # 2. 初始化 —— 创建 config.yaml + 导出 AI Agent skill
101
+ specdo init claude
102
+
103
+ # 3. Explore —— 捕获变更想法(使用 --domains 聚焦提问范围)
104
+ specdo explore "Add rate limiting to the public API" --domains backend
105
+
106
+ # 4. Propose —— 生成 proposal、design、tasks 和 specs
107
+ specdo propose --change add-rate-limiting-to-the-public-api
108
+
109
+ # 5. Apply —— 启动 TDD 执行循环
110
+ specdo apply --change add-rate-limiting-to-the-public-api
111
+ specdo apply --change add-rate-limiting-to-the-public-api --done 1.1 --evidence "中间件已添加,测试通过"
112
+
113
+ # 6. Sync —— 将 specs 提升到规范库
114
+ specdo sync --change add-rate-limiting-to-the-public-api
115
+
116
+ # 7. Archive —— 归档并附带证据链
117
+ specdo archive --change add-rate-limiting-to-the-public-api
118
+ ```
119
+
120
+ ---
121
+
122
+ ## 工作流产物
123
+
124
+ 一次完整的 SpecDo 变更产出以下制品:
125
+
126
+ ```text
127
+ specdo/changes/<name>/
128
+ ├── context.json ← 唯一事实来源(原子写入)
129
+ ├── proposal.md ← 为什么做 + 范围 + 风险
130
+ ├── design.md ← 怎么做(全部 6 个领域的 checklist 已注入)
131
+ ├── tasks.md ← 有序、编号的任务列表(驱动 apply 阶段)
132
+ ├── apply-brief.md ← TDD 执行指南(含领域关注域)
133
+ └── specs/ ← 变更范围的 spec 草案
134
+ ```
135
+
136
+ ---
137
+
138
+ ## 项目结构
139
+
140
+ ```text
141
+ specdo/
142
+ ├── config.yaml # 领域覆盖 + 项目设置
143
+ ├── changes/ # 进行中的变更
144
+ ├── specs/ # 规范库(跨变更的权威 spec)
145
+ └── archive/ # 已完成变更 + 证据链
146
+ ```
147
+
148
+ `context.json` 采用 write-temp → fsync → rename 机制,搭配 `.bak` 快照和文件锁——零外部依赖。
149
+
150
+ ---
151
+
152
+ ## AI Agent 集成
153
+
154
+ SpecDo 将自身导出为 **渐进式披露 skill 包**——5 个 `SKILL.md` 文件附带 `references/`——覆盖 8 个主流 AI 工具:
155
+
156
+ | Agent | 项目路径 | 全局路径 |
157
+ |-------|-------------|-------------|
158
+ | `claude` | `.claude/skills/` | `~/.claude/skills/` |
159
+ | `qoder` | `.qoder/skills/` | `~/.qoder/skills/` |
160
+ | `cursor` | `.cursor/skills/` | `~/.cursor/skills/` |
161
+ | `cline` | `.cline/skills/` | `~/.cline/skills/` |
162
+ | `codex` | `.codex/skills/` | `~/.codex/skills/` |
163
+ | `goose` | `.goose/skills/` | `~/.goose/skills/` |
164
+ | `kilo` | `.kilo/skills/` | `~/.kilo/skills/` |
165
+ | `opencode` | `.opencode/skills/` | `~/.opencode/skills/` |
166
+
167
+ 内置拼写纠错(`clude` → `claude`)和未知 agent 回退(`.agents/skills/`)。SpecDo 从不修改你的 `AGENTS.md` 或 `CLAUDE.md`。
168
+
169
+ ### 导出的 Skill
170
+
171
+ | Skill | 用途 |
172
+ |-------|---------|
173
+ | `specdo-explore` | Agent 主导的探索(含 Grill-Me 访谈方法) |
174
+ | `specdo-propose` | 渲染 proposal / specs / design / tasks(含全领域注入) |
175
+ | `specdo-apply` | TDD 执行循环(每任务附带证据) |
176
+ | `specdo-sync` | 将 specs 提升到 `specdo/specs/` 规范库 |
177
+ | `specdo-archive` | 归档并附带审计摘要 |
178
+
179
+ ---
180
+
181
+ ## 定制化
182
+
183
+ SpecDo 为全部 6 个领域内置了通用最佳实践。通过 `specdo/config.yaml` 叠加你团队自己的标准——无需改源码。
184
+
185
+ ### 速查表
186
+
187
+ | 维度 | 可选项 |
188
+ |-----------|---------|
189
+ | **领域(Domain)** | `security` `architecture` `backend` `quality` `frontend` `operations` |
190
+ | **阶段(Stage)** | `explore` `design` `implement` `verify` |
191
+ | **列表字段(List fields)** | `questions` `checklist` `focusAreas` `antiPatterns` |
192
+ | **操作(Actions)** | `prepend`(头部插入)`append`(尾部追加)`replace`(整段替换) |
193
+ | **特殊(Special)** | `enabled: false`(禁用整个阶段)`patterns`(键值对;同名 key 覆盖值,新 key 追加) |
194
+
195
+ ### 完整示例
196
+
197
+ ```yaml
198
+ # specdo/config.yaml
199
+ domainVersion: "1.0"
200
+ overrides:
201
+ security:
202
+ explore:
203
+ questions:
204
+ - prepend: "[ORG] Is SOC2 compliance required?"
205
+ - append: "[ORG] Has the last pentest report been resolved?"
206
+ design:
207
+ checklist:
208
+ - prepend: "Validate against internal threat model TM-001"
209
+ - append: "Sign-off from #sec-review channel"
210
+ verify:
211
+ enabled: false # 禁用 security 的 verify 阶段
212
+
213
+ architecture:
214
+ design:
215
+ checklist:
216
+ - replace: "[ORG] Follow RFC-0421 micro-frontend boundary rules"
217
+ patterns:
218
+ "Modular Monolith (default)": "[ORG] Mono-first + company module boundary spec"
219
+ "[ORG] Event-driven CQRS": "Use Kafka + company event schema registry"
220
+
221
+ backend:
222
+ implement:
223
+ focusAreas:
224
+ - append: "[ORG] All migrations must use the internal db-migrate-safe tool"
225
+ antiPatterns:
226
+ - append: "[ORG] Never concatenate user input into ORM raw queries"
227
+
228
+ quality:
229
+ implement:
230
+ patterns:
231
+ "Property-based testing": "Use fast-check for parser fuzz"
232
+
233
+ operations:
234
+ verify:
235
+ checklist:
236
+ - append: "[ORG] Announce releases in #sre-release channel before deploy"
237
+ ```
238
+
239
+ ### 操作规则
240
+
241
+ | 规则 | 说明 |
242
+ |------|--------|
243
+ | 每条 item 一个操作 | 每条 override item 必须且只能包含 `prepend`、`append`、`replace` 之一 |
244
+ | 同字段不可混用 | 同一字段内不能同时存在 `replace` 和 `prepend`/`append` |
245
+ | 未知域名或阶段 | Zod schema 校验失败;`specdo validate` 报错 |
246
+ | 未知字段 | 由 `strict()` 拦截——无提示静默忽略 |
247
+
248
+ ### 验证覆盖结果
249
+
250
+ ```bash
251
+ # 查看某个领域应用覆盖后的最终形态
252
+ specdo domains show security
253
+
254
+ # 校验 config.yaml 合法性
255
+ specdo validate
256
+ ```
257
+
258
+ ---
259
+
260
+ ## 全部命令
261
+
262
+ ### 工作流命令
263
+
264
+ | 命令 | 作用 |
265
+ |---------|-------------|
266
+ | `init <agent>[,<agent>...]` | 创建工作区 + `config.yaml` + 导出 skill |
267
+ | `explore [idea]` | Agent 主导的探索:`--domains`、`--context`、`--depth` |
268
+ | `propose --change <n>` | 渲染 proposal / design / tasks / `specs/<capability>/spec.md` |
269
+ | `apply --change <n>` | 执行指南;`--done 1.1 --evidence "..."` 标记进度 |
270
+ | `sync --change <n>` | 将变更 specs 提升到 `specdo/specs/` 规范库 |
271
+ | `archive --change <n>` | 校验完整性 + 移入 `specdo/archive/` |
272
+
273
+ ### 查询命令
274
+
275
+ | 命令 | 作用 |
276
+ |---------|-------------|
277
+ | `list [--specs\|--archived] [--json]` | 列出变更、specs 或归档条目 |
278
+ | `show <name> [--type spec] [--json]` | 显示变更详情或解析 specs |
279
+ | `status [--change <n>] [--json]` | 查看单个或全部变更的阶段进度 |
280
+ | `validate [--change <n>] [--json]` | Schema + 交叉引用 + tasks 一致性校验 |
281
+ | `domains list\|show <name>` | 查看解析后的领域定义 |
282
+ | `doctor [--deep] [--json]` | 工作区健康检查 |
283
+
284
+ 所有查询命令均支持 `--json` 用于自动化。
285
+
286
+ ---
287
+
288
+ ## 开发
289
+
290
+ ```bash
291
+ pnpm install
292
+ pnpm test # vitest(521 tests)
293
+ pnpm run build # TypeScript → dist/
294
+ pnpm run release:check # 全流程:lint + tsc + test + pack + smoke
295
+ ```
296
+
297
+ 运行时依赖:`chalk`、`commander`、`yaml`、`zod`——仅此而已。
298
+
299
+ ---
300
+
301
+ ## 致谢
302
+
303
+ SpecDo 改编自 [OpenSpec](https://github.com/Fission-AI/OpenSpec),一个规范驱动开发框架。感谢 OpenSpec 作者确立了 `changes/` → `specs/` → `archive/` 的核心工作流范式,SpecDo 在此基础上构建。
304
+
305
+ ---
306
+ </div>
package/bin/specdo.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import '../dist/cli/index.js';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * specdo CLI 入口
3
+ *
4
+ * 注册 12 个命令:
5
+ * init / explore / propose / apply / sync / archive
6
+ * list / show / status / validate / domains / doctor
7
+ *
8
+ * 设计要点:
9
+ * - 每个命令都是 `handle*` 纯函数的薄包装:parse options → handle*() →
10
+ * 写 stdout/stderr → process.exit(exitCode)
11
+ * - 不在此文件做任何业务逻辑;所有错误路径由命令本身返回 CommandResult
12
+ * - --no-color 由 NO_COLOR 环境变量控制
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * specdo CLI 入口
3
+ *
4
+ * 注册 12 个命令:
5
+ * init / explore / propose / apply / sync / archive
6
+ * list / show / status / validate / domains / doctor
7
+ *
8
+ * 设计要点:
9
+ * - 每个命令都是 `handle*` 纯函数的薄包装:parse options → handle*() →
10
+ * 写 stdout/stderr → process.exit(exitCode)
11
+ * - 不在此文件做任何业务逻辑;所有错误路径由命令本身返回 CommandResult
12
+ * - --no-color 由 NO_COLOR 环境变量控制
13
+ */
14
+ import { Command } from 'commander';
15
+ import { createRequire } from 'node:module';
16
+ import * as readline from 'node:readline';
17
+ import { isCanonicalTaskReference } from '../core/task-parser.js';
18
+ import { handleInit, detectUnknownAgentForPrompt, detectTypoAgentForPrompt } from '../commands/init.js';
19
+ import { handleExplore } from '../commands/explore.js';
20
+ import { handlePropose } from '../commands/propose.js';
21
+ import { handleApply } from '../commands/apply.js';
22
+ import { handleSync } from '../commands/sync.js';
23
+ import { handleArchive } from '../commands/archive.js';
24
+ import { handleList } from '../commands/list.js';
25
+ import { handleShow } from '../commands/show.js';
26
+ import { handleStatus } from '../commands/status.js';
27
+ import { handleValidate } from '../commands/validate.js';
28
+ import { handleDomains } from '../commands/domains.js';
29
+ import { handleDoctor } from '../commands/doctor.js';
30
+ import { fail } from '../commands/_shared.js';
31
+ const require = createRequire(import.meta.url);
32
+ const { version } = require('../../package.json');
33
+ const program = new Command();
34
+ program
35
+ .name('specdo')
36
+ .description('AI-native CLI for spec-driven development')
37
+ .version(version)
38
+ .option('--no-color', 'Disable color output')
39
+ .hook('preAction', (thisCommand) => {
40
+ if (thisCommand.opts().color === false)
41
+ process.env.NO_COLOR = '1';
42
+ });
43
+ program.configureOutput({
44
+ writeErr: (str) => process.stderr.write(normalizeCommanderStderr(str)),
45
+ });
46
+ // ─── workflow loop ──────────────────────────────────────────────
47
+ program
48
+ .command('init [agent]')
49
+ .description('Initialize specdo workspace and export agent skills (agent is required, e.g. claude, qoder, cursor, cline, codex, goose, kilo, opencode, universal; comma-separated combinations also accepted)')
50
+ .option('-g, --global', 'Install skills to user-global directory (~/.<agent>/skills) instead of project')
51
+ .action(async (agent, opts) => {
52
+ // 未知 agent 且无近似词 → TTY 下询问是否走 universal fallback。
53
+ // 询问逻辑放在 CLI 层以保持 handleInit 是纯函数、可测。
54
+ let effectiveAgent = agent;
55
+ const unknown = detectUnknownAgentForPrompt(agent);
56
+ if (unknown !== null && isInteractive()) {
57
+ const yn = await promptYesNo(`Unknown agent '${unknown}'. Install skills to the community fallback (.agents/skills/) instead? [y/N] `);
58
+ if (yn)
59
+ effectiveAgent = 'universal';
60
+ // 拒绝 → effectiveAgent 保持原值,handleInit 会拒绝 + 提示用户重跑
61
+ }
62
+ // 未知 agent 但有近似词(typo)→ TTY 下询问是否直接使用建议的 agent。
63
+ const typo = detectTypoAgentForPrompt(agent);
64
+ if (typo !== null && isInteractive()) {
65
+ const yn = await promptYesNo(`Unknown agent '${typo.input}'. Did you mean '${typo.suggestion}'? Use it instead? [y/N] `);
66
+ if (yn)
67
+ effectiveAgent = typo.suggestion;
68
+ // 拒绝 → effectiveAgent 保持原值,handleInit 会拒绝 + 提示用户重跑
69
+ }
70
+ // 非交互且 unknown → effectiveAgent 保持原值,handleInit 会拒绝 + 提示交互式重跑
71
+ await emit(handleInit({
72
+ cwd: process.cwd(),
73
+ agent: effectiveAgent,
74
+ global: opts.global,
75
+ }));
76
+ });
77
+ program
78
+ .command('explore [idea]')
79
+ .description('Capture a change idea and match domains')
80
+ .option('--change <name>', 'Explicit change name (overrides slug from idea)')
81
+ .option('--domains <list>', 'Comma-separated domain names (e.g. backend,security) — bypasses auto-scoring')
82
+ .option('--context <text>', 'Free-text collected context from prior discovery')
83
+ .option('--depth <level>', 'Explore depth: shallow | standard | deep')
84
+ .option('--non-interactive', 'Skip interactive prompts (use with --answers in CI)')
85
+ .option('--answers <json>', 'Preset answers as JSON object {"<domain>:<index>":"<text>"}')
86
+ .option('--llm', 'Enable LLM-driven question generation (outputs prompt JSON; use with agent)')
87
+ .option('--llm-questions <json>', 'Pre-generated LLM questions as JSON {"<domain>":["Q1","Q2"]}')
88
+ .action(async (idea, opts) => {
89
+ await emit(handleExplore({
90
+ cwd: process.cwd(),
91
+ idea,
92
+ change: opts.change,
93
+ domains: opts.domains,
94
+ context: opts.context,
95
+ depth: opts.depth,
96
+ nonInteractive: opts.nonInteractive,
97
+ answers: opts.answers,
98
+ llm: opts.llm,
99
+ llmQuestions: opts.llmQuestions,
100
+ }));
101
+ });
102
+ program
103
+ .command('propose')
104
+ .description('Generate proposal/specs/design/tasks templates with domain injection')
105
+ .requiredOption('--change <name>', 'Change name')
106
+ .option('--force', 'Overwrite user-modified artifacts')
107
+ .action(async (opts) => {
108
+ await emit(handlePropose({ cwd: process.cwd(), change: opts.change, force: opts.force }));
109
+ });
110
+ program
111
+ .command('apply')
112
+ .description('Render execution brief, mark tasks done/undone')
113
+ .requiredOption('--change <name>', 'Change name')
114
+ .option('--done <task>', 'Mark task ref complete (for example 1 or 1.1; requires --evidence)')
115
+ .option('--undo <task>', 'Revert task ref to incomplete')
116
+ .option('--evidence <text>', 'Evidence text for --done')
117
+ .action(async (opts) => {
118
+ const done = parseTaskReferenceOption(opts.done, '--done');
119
+ if (done.error) {
120
+ await emit(Promise.resolve(done.error));
121
+ return;
122
+ }
123
+ const undo = parseTaskReferenceOption(opts.undo, '--undo');
124
+ if (undo.error) {
125
+ await emit(Promise.resolve(undo.error));
126
+ return;
127
+ }
128
+ await emit(handleApply({
129
+ cwd: process.cwd(),
130
+ change: opts.change,
131
+ done: done.value,
132
+ undo: undo.value,
133
+ evidence: opts.evidence,
134
+ }));
135
+ });
136
+ program
137
+ .command('sync')
138
+ .description('Sync change specs into the canonical specs/ directory')
139
+ .requiredOption('--change <name>', 'Change name')
140
+ .option('--force', 'Overwrite conflicts (writes a backup first)')
141
+ .action(async (opts) => {
142
+ await emit(handleSync({ cwd: process.cwd(), change: opts.change, force: opts.force }));
143
+ });
144
+ program
145
+ .command('archive')
146
+ .description('Archive a completed change after validation')
147
+ .requiredOption('--change <name>', 'Change name')
148
+ .option('--skip-sync-check', 'Skip the sync completion gate (records risk note)')
149
+ .action(async (opts) => {
150
+ await emit(handleArchive({
151
+ cwd: process.cwd(),
152
+ change: opts.change,
153
+ skipSyncCheck: opts.skipSyncCheck,
154
+ }));
155
+ });
156
+ // ─── management commands ───────────────────────────────────────
157
+ program
158
+ .command('list')
159
+ .description('List active changes (default), specs, or archived changes')
160
+ .option('--specs', 'List spec files instead of changes')
161
+ .option('--archived', 'List archived changes instead of active')
162
+ .option('--sort <order>', '"recent" (default) or "name"', 'recent')
163
+ .option('--json', 'Output as JSON')
164
+ .action(async (opts) => {
165
+ const mode = opts.specs ? 'specs' : opts.archived ? 'archived' : 'changes';
166
+ const sort = opts.sort === 'name' ? 'name' : 'recent';
167
+ await emit(handleList({ cwd: process.cwd(), mode, sort, json: opts.json }));
168
+ });
169
+ program
170
+ .command('show <name>')
171
+ .description('Show details for a change or spec')
172
+ .option('--type <type>', 'Disambiguate: change | spec', 'change')
173
+ .option('--json', 'Output as JSON')
174
+ .action(async (name, opts) => {
175
+ const type = opts.type === 'spec' ? 'spec' : 'change';
176
+ await emit(handleShow({ cwd: process.cwd(), name, type, json: opts.json }));
177
+ });
178
+ program
179
+ .command('status')
180
+ .description('Show stage progress for one or all active changes')
181
+ .option('--change <name>', 'Drill into one change')
182
+ .option('--json', 'Output as JSON')
183
+ .action(async (opts) => {
184
+ await emit(handleStatus({ cwd: process.cwd(), change: opts.change, json: opts.json }));
185
+ });
186
+ program
187
+ .command('validate')
188
+ .description('Validate config schema, context.json, tasks.md and cross-references')
189
+ .option('--change <name>', 'Validate a single change instead of all active ones')
190
+ .option('--json', 'Output structured issues as JSON')
191
+ .action(async (opts) => {
192
+ await emit(handleValidate({ cwd: process.cwd(), change: opts.change, json: opts.json }));
193
+ });
194
+ const domainsCmd = program
195
+ .command('domains')
196
+ .description('Inspect available domains (after applying config.overrides)');
197
+ domainsCmd
198
+ .command('list', { isDefault: true })
199
+ .description('List all domains with override summary')
200
+ .option('--json', 'Output as JSON')
201
+ .action(async (opts) => {
202
+ await emit(handleDomains({ cwd: process.cwd(), subcommand: 'list', json: opts.json }));
203
+ });
204
+ domainsCmd
205
+ .command('show <name>')
206
+ .description('Show resolved checklist for a domain')
207
+ .option('--json', 'Output as JSON')
208
+ .action(async (name, opts) => {
209
+ await emit(handleDomains({ cwd: process.cwd(), subcommand: 'show', name, json: opts.json }));
210
+ });
211
+ program
212
+ .command('doctor')
213
+ .description('Health check: directory layout, config, conflicts, lock residuals')
214
+ .option('--deep', 'Run deeper checks (Node version, context integrity)')
215
+ .option('--json', 'Output as JSON')
216
+ .action(async (opts) => {
217
+ await emit(handleDoctor({ cwd: process.cwd(), deep: opts.deep, json: opts.json }));
218
+ });
219
+ // ─── error / help ──────────────────────────────────────────────
220
+ program.exitOverride((err) => {
221
+ if (err.code === 'commander.helpDisplayed' || err.code === 'commander.version') {
222
+ process.exit(0);
223
+ }
224
+ if (err.code === 'commander.help') {
225
+ process.exit(0);
226
+ }
227
+ if (err.code === 'commander.unknownCommand' ||
228
+ err.code === 'commander.unknownOption' ||
229
+ err.code === 'commander.missingArgument' ||
230
+ err.code === 'commander.excessArguments' ||
231
+ err.code === 'commander.invalidArgument') {
232
+ process.exit(2);
233
+ }
234
+ process.exit(typeof err.exitCode === 'number' ? err.exitCode : 1);
235
+ });
236
+ await program.parseAsync().catch((err) => {
237
+ console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
238
+ process.exit(4);
239
+ });
240
+ // ─── helpers ────────────────────────────────────────────────────
241
+ async function emit(promise) {
242
+ const result = await promise;
243
+ for (const line of result.stdout) {
244
+ process.stdout.write(line + '\n');
245
+ }
246
+ for (const line of result.stderr) {
247
+ process.stderr.write(line + '\n');
248
+ }
249
+ process.exit(result.exitCode);
250
+ }
251
+ function parseTaskReferenceOption(value, flagName) {
252
+ if (value === undefined) {
253
+ return {};
254
+ }
255
+ if (!isCanonicalTaskReference(value)) {
256
+ return {
257
+ error: fail(2, [
258
+ `Error: option '${flagName} <task>' argument '${value}' is invalid. expected task reference like "1" or "1.1" (canonical form only)`,
259
+ ]),
260
+ };
261
+ }
262
+ return { value };
263
+ }
264
+ function normalizeCommanderStderr(input) {
265
+ return input.replace(/^error:\s*/gim, 'Error: ');
266
+ }
267
+ /**
268
+ * 是否可交互。要求 stdin 与 stderr 都是 TTY,且环境未设 CI / SPECDO_NON_INTERACTIVE。
269
+ * stdin-only 检测会误报未重定向 stdin 的子进程为 TTY(造成 setRawMode EPERM)。
270
+ */
271
+ function isInteractive() {
272
+ if (process.env.CI)
273
+ return false;
274
+ if (process.env.SPECDO_NON_INTERACTIVE)
275
+ return false;
276
+ return Boolean(process.stdin.isTTY) && Boolean(process.stderr.isTTY);
277
+ }
278
+ /**
279
+ * 询问用户 yes/no。仅在 process.stdin.isTTY=true 时调用。
280
+ * 默认 false (空回车、n/N、其他 → false;y/Y/yes/Yes → true)。
281
+ */
282
+ async function promptYesNo(question) {
283
+ const rl = readline.createInterface({
284
+ input: process.stdin,
285
+ output: process.stderr, // 提示走 stderr,避免污染 stdout (便于 --json 站不受影响)
286
+ });
287
+ try {
288
+ const answer = await new Promise((resolve) => {
289
+ rl.question(question, (input) => resolve(input));
290
+ });
291
+ return /^y(es)?$/i.test(answer.trim());
292
+ }
293
+ finally {
294
+ rl.close();
295
+ }
296
+ }
297
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}