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,243 @@
1
+ /**
2
+ * specdo init <agent> [-g] [-y]
3
+ *
4
+ * agent 是必传位置参数。运行流程(更严格的契约):
5
+ * 1. agent 缺失 → exit 2,不做任何事
6
+ * 2. 解析 agent;任意失败('all' / typo / unknown)→ exit 2,不创建骨架
7
+ * 3. agent 完全合法后才创建/修复骨架
8
+ * 4. 导出 skill
9
+ *
10
+ * 关键不变量:
11
+ * - 仅当 agent 完全合法时,骨架才被创建(agent 错误不留下任何痕迹)
12
+ * - config.yaml 永不覆盖(仅缺失时写入)
13
+ * - 错误提示不引导用户去手填 'universal';交互层(cli/index.ts)会在
14
+ * 未知无近似词时主动 prompt 是否走通用目录
15
+ * - 任何 FS 写入失败 → exit 3
16
+ */
17
+ import * as fs from 'node:fs';
18
+ import * as path from 'node:path';
19
+ import { fail, findSpecdoConfig, getSpecdoDir, ok, safeExists, safeIsDir, } from './_shared.js';
20
+ import { ALL_AGENTS, exportSkills, isAgentName, suggestAgents, } from '../core/skill-exporter.js';
21
+ /** 供错误提示与 --help 复用的可读字符串,例:"claude | qoder | cursor | ..." */
22
+ const SUPPORTED_AGENTS_HELP = ALL_AGENTS.join(' | ');
23
+ const CONFIG_TEMPLATE = `# specdo configuration
24
+ # Generated by 'specdo init'. Edit to add config.overrides for project-specific
25
+ # domain customization. See specdo/specs/ for accumulated specifications, and
26
+ # specdo/changes/ for in-flight change proposals.
27
+
28
+ domainVersion: "1.0"
29
+ overrides: {}
30
+ `;
31
+ export async function handleInit(options) {
32
+ const { cwd, agent, global = false } = options;
33
+ if (!safeIsDir(cwd)) {
34
+ return fail(1, [`init failed: cwd is not a directory: ${cwd}`]);
35
+ }
36
+ // ── 1. 必传 agent 校验 ─────────────────────────────────
37
+ if (agent === undefined || agent.trim().length === 0) {
38
+ return fail(2, [
39
+ 'init failed: an agent name is required.',
40
+ 'Usage: specdo init <agent>[,<agent>...]',
41
+ `Supported agents: ${SUPPORTED_AGENTS_HELP}.`,
42
+ 'Examples:',
43
+ ' specdo init claude',
44
+ ' specdo init claude,cursor',
45
+ ' specdo init -g claude # install skills globally',
46
+ ]);
47
+ }
48
+ // ── 2. 解析 agent(任何错误立即返回,绝不创建骨架)────
49
+ const parsed = parseAgents(agent);
50
+ if (!parsed.ok) {
51
+ return fail(2, parsed.stderr);
52
+ }
53
+ const agents = parsed.agents;
54
+ // 极端:trim/split 后为空(例如 ",,,")
55
+ if (agents.length === 0) {
56
+ return fail(2, [
57
+ 'init failed: an agent name is required.',
58
+ 'Usage: specdo init <agent>[,<agent>...]',
59
+ `Supported agents: ${SUPPORTED_AGENTS_HELP}.`,
60
+ ]);
61
+ }
62
+ // ── 3. agent 已全部合法 → 创建/修复骨架(-g 跳过) ────
63
+ const stdout = [];
64
+ if (!global) {
65
+ const specdoDir = getSpecdoDir(cwd);
66
+ const existingConfig = findSpecdoConfig(cwd);
67
+ const skeletonExists = safeIsDir(specdoDir);
68
+ if (existingConfig && !skeletonExists) {
69
+ return fail(1, [
70
+ `Existing specdo config detected at ${existingConfig} but specdo/ is not a directory. Aborting.`,
71
+ ]);
72
+ }
73
+ try {
74
+ ensureDirs(cwd);
75
+ const configPath = path.join(specdoDir, 'config.yaml');
76
+ if (!safeExists(configPath)) {
77
+ fs.writeFileSync(configPath, CONFIG_TEMPLATE, 'utf-8');
78
+ }
79
+ }
80
+ catch (err) {
81
+ return fail(3, [`init failed: ${err.message}`]);
82
+ }
83
+ if (skeletonExists) {
84
+ stdout.push(`✓ specdo/ already initialized at ${path.relative(cwd, specdoDir) || '.'} — refreshed skeleton (config.yaml preserved)`);
85
+ }
86
+ else {
87
+ stdout.push(`✓ Initialized specdo workspace at ${path.relative(cwd, specdoDir) || '.'}`);
88
+ }
89
+ }
90
+ // ── 4. Skill 导出 ──────────────────────────────────────
91
+ const scope = global ? 'user' : 'project';
92
+ try {
93
+ const result = exportSkills({ cwd, agents, scope });
94
+ const scopeLabel = scope === 'user' ? 'user-global' : 'project';
95
+ stdout.push(`✓ Exported ${result.skillCount} core workflow skill packages (${result.filesWritten.length} files) to ${scopeLabel} ${result.agents.length === 1 ? '' : 'agents '}${result.agents.join(', ')}`);
96
+ for (const agentName of result.agents) {
97
+ const sample = result.filesWritten.find((p) => p.includes(`/.${agentName}/skills/`));
98
+ if (sample) {
99
+ const root = path.dirname(path.dirname(sample));
100
+ stdout.push(` • ${agentName}: ${root}`);
101
+ }
102
+ }
103
+ if (result.pruned.length > 0) {
104
+ stdout.push(`✓ Removed ${result.pruned.length} orphan skill director${result.pruned.length === 1 ? 'y' : 'ies'} (legacy specdo-domain-* / specdo-protocol-*)`);
105
+ for (const prunedPath of result.pruned) {
106
+ stdout.push(` • removed: ${path.basename(prunedPath)}`);
107
+ }
108
+ }
109
+ }
110
+ catch (err) {
111
+ return fail(3, [`init failed during skill export: ${err.message}`]);
112
+ }
113
+ // ── 5. Next steps 提示 ────────────────────────────────
114
+ stdout.push('');
115
+ if (global) {
116
+ stdout.push('Skills installed globally. Restart your AI tool to pick them up.');
117
+ }
118
+ else {
119
+ stdout.push('Next:');
120
+ stdout.push(" 1. specdo explore '<idea>' # capture intent + domain matches");
121
+ stdout.push(' 2. specdo propose --change <n> # generate proposal/specs/design/tasks');
122
+ stdout.push(' 3. specdo apply --change <n> # iterate with TDD discipline');
123
+ stdout.push(' 4. specdo sync --change <n> # promote specs to specdo/specs/');
124
+ stdout.push(' 5. specdo archive --change <n> # finalize and record evidence');
125
+ }
126
+ return ok(stdout);
127
+ }
128
+ function ensureDirs(cwd) {
129
+ const dirs = [
130
+ 'specdo',
131
+ 'specdo/specs',
132
+ 'specdo/changes',
133
+ 'specdo/archive',
134
+ ];
135
+ for (const rel of dirs) {
136
+ const abs = path.join(cwd, rel);
137
+ if (!safeExists(abs)) {
138
+ fs.mkdirSync(abs, { recursive: true });
139
+ }
140
+ }
141
+ for (const rel of ['specdo/specs', 'specdo/changes', 'specdo/archive']) {
142
+ const keepFile = path.join(cwd, rel, '.gitkeep');
143
+ if (!safeExists(keepFile)) {
144
+ fs.writeFileSync(keepFile, '', 'utf-8');
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * 检查 raw 是否为「单一未知 agent 且无近似词候选」——
150
+ * CLI 层在此场景下会主动 prompt 用户是否写到通用目录 (.agents/skills/)。
151
+ *
152
+ * 返回 null 表示不属于此场景(合法 agent / 'all' / typo / 多 agent / 空);
153
+ * 返回字符串则是被识别出来的未知名(已 trim+lowercase)。
154
+ */
155
+ export function detectUnknownAgentForPrompt(raw) {
156
+ if (raw === undefined)
157
+ return null;
158
+ const trimmed = raw.trim().toLowerCase();
159
+ if (trimmed.length === 0 || trimmed === 'all')
160
+ return null;
161
+ const parts = trimmed.split(',').map((s) => s.trim()).filter(Boolean);
162
+ if (parts.length !== 1)
163
+ return null;
164
+ const only = parts[0];
165
+ if (isAgentName(only))
166
+ return null;
167
+ if (suggestAgents(only).length > 0)
168
+ return null;
169
+ return only;
170
+ }
171
+ /**
172
+ * 检查 raw 是否为「单一未知 agent 且有近似词候选」——
173
+ * CLI 层在此场景下会 prompt 用户是否直接使用建议的 agent。
174
+ *
175
+ * 返回 null 表示不属于此场景(合法 agent / 'all' / 多 agent / 空 / 无近似词);
176
+ * 返回 { input, suggestion } 则是识别出的 typo 和建议修正。
177
+ */
178
+ export function detectTypoAgentForPrompt(raw) {
179
+ if (raw === undefined)
180
+ return null;
181
+ const trimmed = raw.trim().toLowerCase();
182
+ if (trimmed.length === 0 || trimmed === 'all')
183
+ return null;
184
+ const parts = trimmed.split(',').map((s) => s.trim()).filter(Boolean);
185
+ if (parts.length !== 1)
186
+ return null;
187
+ const only = parts[0];
188
+ if (isAgentName(only))
189
+ return null;
190
+ const suggestions = suggestAgents(only);
191
+ if (suggestions.length === 0)
192
+ return null;
193
+ return { input: only, suggestion: suggestions[0] };
194
+ }
195
+ function parseAgents(raw) {
196
+ const trimmed = raw.trim().toLowerCase();
197
+ if (trimmed === 'all') {
198
+ return {
199
+ ok: false,
200
+ stderr: [
201
+ "init failed: 'all' is not supported (potentially writes to multiple IDE directories at once).",
202
+ 'List the agents explicitly, e.g. specdo init claude,cursor,codex.',
203
+ `Supported agents: ${SUPPORTED_AGENTS_HELP}.`,
204
+ ],
205
+ };
206
+ }
207
+ const parts = trimmed.split(',').map((s) => s.trim()).filter(Boolean);
208
+ const result = [];
209
+ const seen = new Set();
210
+ for (const part of parts) {
211
+ if (!isAgentName(part)) {
212
+ return { ok: false, stderr: buildUnknownAgentMessage(part) };
213
+ }
214
+ if (!seen.has(part)) {
215
+ seen.add(part);
216
+ result.push(part);
217
+ }
218
+ }
219
+ return { ok: true, agents: result };
220
+ }
221
+ /**
222
+ * 组装未知 agent 的多行 stderr。
223
+ *
224
+ * 分两种场景:
225
+ * 1. 近似词命中(Levenshtein ≤ 1)→ "Did you mean: <name>?" 并给出重跑命令
226
+ * 2. 无近似词 → 简单提示:交互式重跑(会调 prompt)。
227
+ * 绝不引导用户手填 'universal'。
228
+ */
229
+ function buildUnknownAgentMessage(input) {
230
+ const lines = [`init failed: unknown agent '${input}'.`];
231
+ const suggestions = suggestAgents(input);
232
+ if (suggestions.length > 0) {
233
+ const list = suggestions.map((s) => `'${s}'`).join(' or ');
234
+ lines.push(`Did you mean: ${list}?`);
235
+ lines.push(`Run: specdo init ${suggestions[0]}`);
236
+ }
237
+ else {
238
+ lines.push(`Supported agents: ${SUPPORTED_AGENTS_HELP}.`);
239
+ lines.push('Run interactively to be prompted for the community fallback (.agents/skills/, picked up by Cursor / Goose / Kilo / Roo Code).');
240
+ }
241
+ return lines;
242
+ }
243
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * specdo list [--changes | --specs | --archived] [--json] [--sort recent|name]
3
+ *
4
+ * 默认列出 active changes(specdo/changes/<name>/)。
5
+ * 行为遵循 phases/03-phase2-commands.md §`list`。
6
+ */
7
+ import { CommandResult } from './_shared.js';
8
+ export interface ListOptions {
9
+ cwd: string;
10
+ mode?: 'changes' | 'specs' | 'archived';
11
+ sort?: 'recent' | 'name';
12
+ json?: boolean;
13
+ }
14
+ export interface ChangeListEntry {
15
+ name: string;
16
+ stage: string;
17
+ tasksCompleted: number;
18
+ tasksTotal: number;
19
+ updatedAt: string | null;
20
+ hasConflicts: boolean;
21
+ }
22
+ export declare function handleList(options: ListOptions): Promise<CommandResult>;
23
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EACL,aAAa,EAMd,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;IACxC,IAAI,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAa7E"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * specdo list [--changes | --specs | --archived] [--json] [--sort recent|name]
3
+ *
4
+ * 默认列出 active changes(specdo/changes/<name>/)。
5
+ * 行为遵循 phases/03-phase2-commands.md §`list`。
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import { ContextStore } from '../core/context-store.js';
10
+ import { fail, findSpecdoConfig, getSpecdoDir, ok, safeIsDir, } from './_shared.js';
11
+ export async function handleList(options) {
12
+ const { cwd } = options;
13
+ if (!findSpecdoConfig(cwd)) {
14
+ return fail(1, ["Not initialized. Run 'specdo init' first."]);
15
+ }
16
+ const mode = options.mode ?? 'changes';
17
+ if (mode === 'specs') {
18
+ return listSpecs(cwd, options);
19
+ }
20
+ if (mode === 'archived') {
21
+ return listChangeDir(cwd, path.join(getSpecdoDir(cwd), 'archive'), options, 'archived');
22
+ }
23
+ return listChangeDir(cwd, path.join(getSpecdoDir(cwd), 'changes'), options, 'active');
24
+ }
25
+ function listChangeDir(cwd, baseDir, options, label) {
26
+ if (!safeIsDir(baseDir)) {
27
+ return ok(emptyOutput(label, options.json));
28
+ }
29
+ const entries = [];
30
+ for (const name of fs.readdirSync(baseDir)) {
31
+ const dir = path.join(baseDir, name);
32
+ if (!safeIsDir(dir))
33
+ continue;
34
+ const store = new ContextStore({ changeDir: dir });
35
+ const ctx = store.read();
36
+ entries.push({
37
+ name,
38
+ stage: deriveStage(ctx),
39
+ tasksCompleted: ctx.apply?.tasksCompleted ?? 0,
40
+ tasksTotal: ctx.apply?.tasksTotal ?? 0,
41
+ updatedAt: ctx.change?.updatedAt ?? null,
42
+ hasConflicts: (ctx.sync?.conflicts ?? []).length > 0,
43
+ });
44
+ }
45
+ const sort = options.sort ?? 'recent';
46
+ entries.sort((a, b) => {
47
+ if (sort === 'name')
48
+ return a.name.localeCompare(b.name);
49
+ const ta = a.updatedAt ? new Date(a.updatedAt).getTime() : 0;
50
+ const tb = b.updatedAt ? new Date(b.updatedAt).getTime() : 0;
51
+ return tb - ta;
52
+ });
53
+ if (options.json) {
54
+ return ok([JSON.stringify({ kind: label, entries }, null, 2)]);
55
+ }
56
+ const stdout = [];
57
+ if (entries.length === 0) {
58
+ stdout.push(`No ${label} changes found in ${path.relative(cwd, baseDir)}/.`);
59
+ return ok(stdout);
60
+ }
61
+ stdout.push(`${label === 'active' ? 'Active' : 'Archived'} changes (${entries.length}):`);
62
+ stdout.push('');
63
+ stdout.push(` ${'NAME'.padEnd(28)} ${'STAGE'.padEnd(10)} ${'TASKS'.padEnd(8)} ${'UPDATED'.padEnd(20)}`);
64
+ for (const e of entries) {
65
+ const tasks = e.tasksTotal > 0 ? `${e.tasksCompleted}/${e.tasksTotal}` : '-';
66
+ const updated = e.updatedAt ? e.updatedAt.replace('T', ' ').slice(0, 19) : '(unknown)';
67
+ const flag = e.hasConflicts ? ' ⚠' : '';
68
+ stdout.push(` ${e.name.padEnd(28)} ${e.stage.padEnd(10)} ${tasks.padEnd(8)} ${updated}${flag}`);
69
+ }
70
+ if (entries.some((e) => e.hasConflicts)) {
71
+ stdout.push('');
72
+ stdout.push('⚠ = unresolved sync conflicts; run `specdo sync --change <name>` to inspect.');
73
+ }
74
+ return ok(stdout);
75
+ }
76
+ function listSpecs(cwd, options) {
77
+ const specsDir = path.join(getSpecdoDir(cwd), 'specs');
78
+ if (!safeIsDir(specsDir)) {
79
+ return ok(['No specs directory found. Run `specdo init` then sync a change to populate it.']);
80
+ }
81
+ const files = walkMarkdown(specsDir, specsDir);
82
+ const sorted = [...files].sort();
83
+ if (options.json) {
84
+ return ok([JSON.stringify({ kind: 'specs', entries: sorted }, null, 2)]);
85
+ }
86
+ const stdout = [];
87
+ if (sorted.length === 0) {
88
+ stdout.push(`No spec files in ${path.relative(cwd, specsDir)}/.`);
89
+ return ok(stdout);
90
+ }
91
+ stdout.push(`Specs in ${path.relative(cwd, specsDir)}/ (${sorted.length}):`);
92
+ stdout.push('');
93
+ for (const rel of sorted) {
94
+ const abs = path.join(specsDir, rel);
95
+ const sizeKb = (fs.statSync(abs).size / 1024).toFixed(1);
96
+ stdout.push(` ${rel.padEnd(40)} ${sizeKb} KB`);
97
+ }
98
+ return ok(stdout);
99
+ }
100
+ function deriveStage(ctx) {
101
+ if (ctx.archive)
102
+ return 'archive';
103
+ if (ctx.sync?.completedAt)
104
+ return 'synced';
105
+ if (ctx.apply) {
106
+ if (ctx.apply.completedAt)
107
+ return 'apply✓';
108
+ return 'apply';
109
+ }
110
+ if (ctx.propose)
111
+ return 'propose';
112
+ if (ctx.explore)
113
+ return 'explore';
114
+ return 'init';
115
+ }
116
+ function walkMarkdown(root, base) {
117
+ const out = [];
118
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
119
+ const abs = path.join(root, entry.name);
120
+ if (entry.isDirectory()) {
121
+ out.push(...walkMarkdown(abs, base));
122
+ continue;
123
+ }
124
+ if (entry.isFile() && entry.name.endsWith('.md')) {
125
+ out.push(path.relative(base, abs).split(path.sep).join('/'));
126
+ }
127
+ }
128
+ return out;
129
+ }
130
+ function emptyOutput(label, json) {
131
+ if (json)
132
+ return [JSON.stringify({ kind: label, entries: [] }, null, 2)];
133
+ return [`No ${label} changes found.`];
134
+ }
135
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * specdo propose [--change <name>] [--force]
3
+ *
4
+ * 行为:
5
+ * 1. 前置检查:specdo/config.yaml 必须存在;--change 必须提供或可从
6
+ * cwd 路径推导
7
+ * 2. 读取 context.json → 取 explore.matchedDomains / answers / flaggedConcerns
8
+ * 3. 无 explore 数据时,domainsUsed = ALL_DOMAINS 的 name 列表,并在
9
+ * stdout 警告"使用全部领域作为兜底"
10
+ * 4. 渲染 4 个 artifact:proposal.md / specs/<capability>/spec.md / design.md / tasks.md
11
+ * 5. 已存在的非空文件默认跳过(warn);--force 时整段覆盖
12
+ * 6. 更新 context.propose.{artifacts, domainsUsed, capabilities, completedAt}
13
+ */
14
+ import { CommandResult } from './_shared.js';
15
+ export interface ProposeOptions {
16
+ cwd: string;
17
+ change?: string;
18
+ force?: boolean;
19
+ now?: () => string;
20
+ }
21
+ export declare function handlePropose(options: ProposeOptions): Promise<CommandResult>;
22
+ //# sourceMappingURL=propose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"propose.d.ts","sourceRoot":"","sources":["../../src/commands/propose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH,OAAO,EACL,aAAa,EASd,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA+MnF"}