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,362 @@
1
+ /**
2
+ * specdo archive [--change <name>] [--skip-sync-check]
3
+ *
4
+ * 行为:
5
+ * 1. 必须 init;--change 必需
6
+ * 2. 检查 tasks 全部完成 + 每个完成任务有 evidence
7
+ * 3. 实时只读检查当前 changes/<name>/specs 与 specdo/specs 的同步状态
8
+ * - 只要存在 added / conflict → 始终失败(即使 --skip-sync-check)
9
+ * - sync 未运行 → 失败(除非 --skip-sync-check)
10
+ * - sync.completedAt = null → 失败(除非 --skip-sync-check)
11
+ * 4. same-filesystem rename: changes/<name>/ → archive/<name>/
12
+ * 5. 在 archive 目录内写 archive-summary.md 与 context.archive 元数据
13
+ * - rename 失败 EXDEV → exit 3
14
+ * - 目标已存在 → exit 1
15
+ * - 元数据写入失败 → 尝试回滚 rename,避免 active change 脏状态
16
+ */
17
+ import * as fs from 'node:fs';
18
+ import * as path from 'node:path';
19
+ import { ContextStore } from '../core/context-store.js';
20
+ import { planSync, SyncError } from '../core/spec-sync.js';
21
+ import { parseTasks } from '../core/task-parser.js';
22
+ import { loadConfig, resolveDomains } from '../core/config-store.js';
23
+ import { validateChange } from './validate.js';
24
+ import { fail, findSpecdoConfig, getArchiveDir, getChangeDir, isValidChangeName, safeExists, safeIsDir, failOnInvalidConfig, } from './_shared.js';
25
+ export async function handleArchive(options) {
26
+ const { cwd } = options;
27
+ if (!findSpecdoConfig(cwd)) {
28
+ return fail(1, ["Not initialized. Run 'specdo init' first."]);
29
+ }
30
+ if (!options.change) {
31
+ return fail(1, ['archive requires --change <name>.']);
32
+ }
33
+ if (!isValidChangeName(options.change)) {
34
+ return fail(1, [`Invalid --change name: "${options.change}".`]);
35
+ }
36
+ const changeName = options.change;
37
+ const changeDir = getChangeDir(cwd, changeName);
38
+ if (!safeIsDir(changeDir)) {
39
+ return fail(1, [`Change directory not found: ${changeDir}.`]);
40
+ }
41
+ const archiveDir = getArchiveDir(cwd, changeName);
42
+ if (safeExists(archiveDir)) {
43
+ return fail(1, [
44
+ `Archive target already exists: ${archiveDir}.`,
45
+ `Remove or rename the existing archive entry before re-archiving.`,
46
+ ]);
47
+ }
48
+ const tasksPath = path.join(changeDir, 'tasks.md');
49
+ if (!safeExists(tasksPath)) {
50
+ return fail(1, [`tasks.md not found at ${tasksPath}; cannot validate completion.`]);
51
+ }
52
+ const now = options.now ?? (() => new Date().toISOString());
53
+ const configResult = loadConfig(cwd);
54
+ const configFailure = failOnInvalidConfig(configResult);
55
+ if (configFailure)
56
+ return configFailure;
57
+ const validation = validateChange(cwd, changeName);
58
+ const validationErrors = validation.issues.filter((issue) => issue.level === 'error');
59
+ if (validationErrors.length > 0) {
60
+ return fail(1, renderValidationIssues(changeName, validationErrors));
61
+ }
62
+ const store = new ContextStore({ changeDir, now });
63
+ const ctx = store.read();
64
+ const resolvedDomains = resolveDomains(configResult.config).map((r) => r.domain);
65
+ const sourceSpecsDir = path.join(changeDir, 'specs');
66
+ const specsDir = path.join(cwd, 'specdo/specs');
67
+ // ─── 1. tasks 检查 ───
68
+ let parsed;
69
+ try {
70
+ parsed = parseTasks(fs.readFileSync(tasksPath, 'utf-8'));
71
+ }
72
+ catch (err) {
73
+ return fail(1, [`tasks.md parse failed: ${err.message}`]);
74
+ }
75
+ if (parsed.tasks.length === 0) {
76
+ return fail(1, ['tasks.md has no tasks; nothing to archive.']);
77
+ }
78
+ const incomplete = parsed.tasks.filter((t) => !t.completed);
79
+ if (incomplete.length > 0) {
80
+ return fail(1, [
81
+ `Cannot archive: ${incomplete.length} task(s) still incomplete:`,
82
+ ...incomplete.map((t) => ` - ${t.number}. ${t.title}`),
83
+ ]);
84
+ }
85
+ const missingEvidence = parsed.tasks.filter((t) => t.completed && (!t.evidence || t.evidence.trim().length === 0));
86
+ if (missingEvidence.length > 0) {
87
+ return fail(1, [
88
+ `Cannot archive: ${missingEvidence.length} completed task(s) missing evidence:`,
89
+ ...missingEvidence.map((t) => ` - ${t.number}. ${t.title}`),
90
+ ]);
91
+ }
92
+ // ─── 2. apply.tasksCompleted vs tasksTotal ───
93
+ if (!validation.context?.apply) {
94
+ return fail(1, [
95
+ 'Cannot archive: context.apply is missing.',
96
+ `Run 'specdo apply --change ${changeName}' to rebuild apply state before archiving.`,
97
+ ]);
98
+ }
99
+ if (validation.context.apply.tasksCompleted !== validation.context.apply.tasksTotal ||
100
+ validation.context.apply.tasksTotal !== parsed.tasks.length) {
101
+ return fail(1, [
102
+ `context.apply is out of sync with tasks.md (parsed ${parsed.tasks.length} tasks, ` +
103
+ `context says ${validation.context.apply.tasksCompleted}/${validation.context.apply.tasksTotal}).`,
104
+ `Run 'specdo apply --change ${changeName}' to refresh state.`,
105
+ ]);
106
+ }
107
+ // ─── 3. sync 检查(实时只读比对 + 历史 completedAt 审计) ───
108
+ let liveSync;
109
+ try {
110
+ liveSync = inspectLiveSync({ changeName, sourceSpecsDir, specsDir });
111
+ }
112
+ catch (err) {
113
+ if (err instanceof ArchivePreconditionError) {
114
+ return fail(err.exitCode, err.lines);
115
+ }
116
+ return fail(3, [`Failed to inspect current sync state: ${err.message}`]);
117
+ }
118
+ if (liveSync.unsyncedAdded.length > 0 || liveSync.unsyncedConflicts.length > 0) {
119
+ return fail(1, [
120
+ `Cannot archive: change specs are not fully synced into specdo/specs.`,
121
+ ...liveSync.unsyncedAdded.map((rel) => ` + pending add: ${rel}`),
122
+ ...liveSync.unsyncedConflicts.map((rel) => ` ! pending conflict: ${rel}`),
123
+ `Re-run 'specdo sync --change ${changeName}' before archiving.`,
124
+ ]);
125
+ }
126
+ const syncSnapshot = {
127
+ completedAt: ctx.sync?.completedAt ?? null,
128
+ unresolvedConflicts: liveSync.unsyncedConflicts,
129
+ forcedConflicts: ctx.sync?.forcedConflicts ?? [],
130
+ };
131
+ // 显式校验 context.json 中的 conflicts 字段
132
+ if (ctx.sync?.conflicts && ctx.sync.conflicts.length > 0) {
133
+ return fail(1, [
134
+ `Cannot archive: ${ctx.sync.conflicts.length} unresolved sync conflict(s) recorded in context.json.`,
135
+ ...ctx.sync.conflicts.map((c) => ` - ${c}`),
136
+ `Run 'specdo sync --change ${changeName} --force' to overwrite, or hand-merge and re-sync.`,
137
+ ]);
138
+ }
139
+ const riskNotes = [];
140
+ let skippedSyncCheck = false;
141
+ let skipSyncReason;
142
+ if (!ctx.sync) {
143
+ if (!options.skipSyncCheck) {
144
+ return fail(1, [
145
+ `Cannot archive: sync has not been executed. ` +
146
+ `Run 'specdo sync --change ${changeName}' first, or pass --skip-sync-check (record-only).`,
147
+ ]);
148
+ }
149
+ skippedSyncCheck = true;
150
+ skipSyncReason = 'Sync was never executed';
151
+ riskNotes.push('Sync was never executed');
152
+ }
153
+ else if (ctx.sync.completedAt === null) {
154
+ if (!options.skipSyncCheck) {
155
+ return fail(1, [
156
+ `Cannot archive: sync is incomplete (completedAt = null).`,
157
+ `Re-run 'specdo sync --change ${changeName}' or pass --skip-sync-check (record-only).`,
158
+ ]);
159
+ }
160
+ skippedSyncCheck = true;
161
+ skipSyncReason = 'Sync started but never completed';
162
+ riskNotes.push('Sync started but never completed');
163
+ }
164
+ // ─── 4. rename 到 archive/ ───
165
+ fs.mkdirSync(path.dirname(archiveDir), { recursive: true });
166
+ try {
167
+ fs.renameSync(changeDir, archiveDir);
168
+ }
169
+ catch (err) {
170
+ const code = err.code;
171
+ if (code === 'EXDEV') {
172
+ return fail(3, [
173
+ `specdo/changes/ and specdo/archive/ must reside on the same filesystem. ` +
174
+ `Symlinks across mount points are not supported. ` +
175
+ `(${err.message})`,
176
+ ]);
177
+ }
178
+ if (code === 'ENOTEMPTY' || code === 'EEXIST') {
179
+ return fail(1, [`Archive target already exists: ${archiveDir}.`]);
180
+ }
181
+ return fail(3, [`Failed to rename change directory to archive: ${err.message}`]);
182
+ }
183
+ // ─── 5. 在 archive 目录内写 summary + context.archive;失败时回滚 rename ───
184
+ const summaryRelPath = 'archive-summary.md';
185
+ const summaryAbsPath = path.join(archiveDir, summaryRelPath);
186
+ const archivedAt = now();
187
+ const summary = renderArchiveSummary({
188
+ changeName,
189
+ tasksCount: parsed.tasks.length,
190
+ domainsUsed: ctx.propose?.domainsUsed ?? [],
191
+ syncSnapshot,
192
+ skippedSyncCheck,
193
+ skipSyncReason,
194
+ riskNotes,
195
+ archivedAt,
196
+ });
197
+ const archiveStore = new ContextStore({ changeDir: archiveDir, now });
198
+ try {
199
+ fs.writeFileSync(summaryAbsPath, summary, 'utf-8');
200
+ archiveStore.writeDeep({
201
+ archive: {
202
+ archivedAt,
203
+ archivePath: path.relative(cwd, archiveDir),
204
+ summaryPath: summaryRelPath,
205
+ skippedSyncCheck: skippedSyncCheck ? true : undefined,
206
+ skipSyncReason,
207
+ syncSnapshot,
208
+ riskNotes: riskNotes.length > 0 ? riskNotes : undefined,
209
+ },
210
+ });
211
+ }
212
+ catch (err) {
213
+ return rollbackArchivedChange({
214
+ cwd,
215
+ changeDir,
216
+ archiveDir,
217
+ summaryAbsPath,
218
+ message: `Failed to finalize archive metadata: ${err.message}`,
219
+ });
220
+ }
221
+ // ─── 6. 注入领域 verify checklist 作为 stdout 提示 ───
222
+ const stdout = [];
223
+ stdout.push(`✓ Archived '${changeName}' → ${path.relative(cwd, archiveDir)}/.`);
224
+ stdout.push(`Summary: ${path.relative(cwd, path.join(archiveDir, summaryRelPath))}`);
225
+ stdout.push('');
226
+ if (riskNotes.length > 0) {
227
+ stdout.push('Risk notes:');
228
+ for (const r of riskNotes) {
229
+ stdout.push(` ! ${r}`);
230
+ }
231
+ stdout.push('');
232
+ }
233
+ const verifyChecklist = collectVerifyChecklist(resolvedDomains, ctx.propose?.domainsUsed ?? []);
234
+ if (verifyChecklist.length > 0) {
235
+ stdout.push('Pre-archive verify checklist (cross-check before announcing the change):');
236
+ for (const item of verifyChecklist) {
237
+ stdout.push(` - [ ] ${item}`);
238
+ }
239
+ }
240
+ return { exitCode: 0, stdout, stderr: [] };
241
+ }
242
+ function renderArchiveSummary(input) {
243
+ const lines = [];
244
+ lines.push(`# Archive Summary: ${input.changeName}`);
245
+ lines.push('');
246
+ lines.push(`<!-- generatedBy: specdo archive at ${input.archivedAt} -->`);
247
+ lines.push('');
248
+ lines.push('## Outcome');
249
+ lines.push('');
250
+ lines.push(`- Tasks completed: ${input.tasksCount}`);
251
+ lines.push(`- Domains used: ${input.domainsUsed.length > 0 ? input.domainsUsed.join(', ') : '(none)'}`);
252
+ lines.push('');
253
+ lines.push('## Sync Snapshot');
254
+ lines.push('');
255
+ lines.push(`- completedAt: ${input.syncSnapshot.completedAt ?? '(none)'}`);
256
+ lines.push(`- unresolvedConflicts: ${input.syncSnapshot.unresolvedConflicts.length}`);
257
+ lines.push(`- forcedConflicts: ${input.syncSnapshot.forcedConflicts.length}`);
258
+ if (input.syncSnapshot.forcedConflicts.length > 0) {
259
+ for (const f of input.syncSnapshot.forcedConflicts) {
260
+ lines.push(` - ${f}`);
261
+ }
262
+ }
263
+ lines.push('');
264
+ if (input.skippedSyncCheck) {
265
+ lines.push('## Skipped Sync Check');
266
+ lines.push('');
267
+ lines.push(`- reason: ${input.skipSyncReason ?? 'unspecified'}`);
268
+ lines.push('');
269
+ }
270
+ if (input.riskNotes.length > 0) {
271
+ lines.push('## Risk Notes');
272
+ lines.push('');
273
+ for (const r of input.riskNotes) {
274
+ lines.push(`- ⚠️ ${r}`);
275
+ }
276
+ lines.push('');
277
+ }
278
+ return lines.join('\n');
279
+ }
280
+ function inspectLiveSync(input) {
281
+ let entries;
282
+ try {
283
+ entries = planSync({
284
+ changesSpecsDir: input.sourceSpecsDir,
285
+ specsDir: input.specsDir,
286
+ });
287
+ }
288
+ catch (err) {
289
+ if (err instanceof SyncError && err.exitCode === 1) {
290
+ throw new ArchivePreconditionError([
291
+ `Cannot archive: source specs directory not found for change '${input.changeName}'.`,
292
+ `Run 'specdo propose --change ${input.changeName}' first.`,
293
+ ]);
294
+ }
295
+ throw err;
296
+ }
297
+ return {
298
+ unsyncedAdded: entries.filter((entry) => entry.status === 'added').map((entry) => entry.relativePath),
299
+ unsyncedConflicts: entries.filter((entry) => entry.status === 'conflict').map((entry) => entry.relativePath),
300
+ };
301
+ }
302
+ function rollbackArchivedChange(input) {
303
+ const rollbackErrors = [];
304
+ try {
305
+ if (fs.existsSync(input.summaryAbsPath)) {
306
+ fs.rmSync(input.summaryAbsPath, { force: true });
307
+ }
308
+ }
309
+ catch (err) {
310
+ rollbackErrors.push(`remove summary: ${err.message}`);
311
+ }
312
+ try {
313
+ if (!safeExists(input.changeDir) && safeExists(input.archiveDir)) {
314
+ fs.renameSync(input.archiveDir, input.changeDir);
315
+ }
316
+ }
317
+ catch (err) {
318
+ rollbackErrors.push(`rename rollback: ${err.message}`);
319
+ }
320
+ if (rollbackErrors.length > 0) {
321
+ return fail(3, [
322
+ input.message,
323
+ `Rollback failed: ${rollbackErrors.join('; ')}`,
324
+ `Inspect ${path.relative(input.cwd, input.archiveDir)} manually before retrying archive.`,
325
+ ]);
326
+ }
327
+ return fail(3, [input.message, 'Archive directory was rolled back to the active change.']);
328
+ }
329
+ class ArchivePreconditionError extends Error {
330
+ lines;
331
+ exitCode = 1;
332
+ constructor(lines) {
333
+ super(lines.join('\n'));
334
+ this.lines = lines;
335
+ this.name = 'ArchivePreconditionError';
336
+ }
337
+ }
338
+ function collectVerifyChecklist(resolvedDomains, domainNames) {
339
+ const out = [];
340
+ const seen = new Set();
341
+ const byName = new Map(resolvedDomains.map((domain) => [domain.name, domain]));
342
+ for (const name of domainNames) {
343
+ const domain = byName.get(name);
344
+ if (!domain)
345
+ continue;
346
+ for (const item of domain.verify?.checklist ?? []) {
347
+ if (seen.has(item))
348
+ continue;
349
+ seen.add(item);
350
+ out.push(`(${name}) ${item}`);
351
+ }
352
+ }
353
+ return out;
354
+ }
355
+ function renderValidationIssues(changeName, issues) {
356
+ return [
357
+ `Cannot archive: validation failed for change '${changeName}'.`,
358
+ ...issues.map((issue) => ` - ${issue.path}: ${issue.message}`),
359
+ `Run 'specdo validate --change ${changeName}' to inspect the full report.`,
360
+ ];
361
+ }
362
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/commands/archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * specdo doctor [--deep]
3
+ *
4
+ * 检查工作区健康度:目录结构、config schema、active vs archive 冲突、
5
+ * .sync-backup 残留、context.json.lock 残留。失败项使用 ✗,可恢复警告
6
+ * 使用 ! ,通过项使用 ✓。任意必须项失败 → exit 1。
7
+ */
8
+ import { CommandResult } from './_shared.js';
9
+ export interface DoctorOptions {
10
+ cwd: string;
11
+ deep?: boolean;
12
+ json?: boolean;
13
+ }
14
+ export interface DoctorCheck {
15
+ label: string;
16
+ status: 'ok' | 'warn' | 'fail';
17
+ detail: string;
18
+ required: boolean;
19
+ }
20
+ export declare function handleDoctor(options: DoctorOptions): Promise<CommandResult>;
21
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,OAAO,EACL,aAAa,EAMd,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB;AAID,wBAAsB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CA0KjF"}
@@ -0,0 +1,180 @@
1
+ /**
2
+ * specdo doctor [--deep]
3
+ *
4
+ * 检查工作区健康度:目录结构、config schema、active vs archive 冲突、
5
+ * .sync-backup 残留、context.json.lock 残留。失败项使用 ✗,可恢复警告
6
+ * 使用 ! ,通过项使用 ✓。任意必须项失败 → exit 1。
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { loadConfig } from '../core/config-store.js';
11
+ import { findSpecdoConfig, getSpecdoDir, ok, safeExists, safeIsDir, } from './_shared.js';
12
+ const STALE_LOCK_THRESHOLD_MS = 30_000;
13
+ export async function handleDoctor(options) {
14
+ const { cwd } = options;
15
+ const checks = [];
16
+ const specdoDir = getSpecdoDir(cwd);
17
+ checks.push({
18
+ label: 'specdo directory',
19
+ status: safeIsDir(specdoDir) ? 'ok' : 'fail',
20
+ detail: safeIsDir(specdoDir) ? path.relative(cwd, specdoDir) || '.' : "Not found — run 'specdo init'",
21
+ required: true,
22
+ });
23
+ // config + schema
24
+ if (!findSpecdoConfig(cwd)) {
25
+ checks.push({
26
+ label: 'project config',
27
+ status: 'fail',
28
+ detail: "Not found — expected specdo/config.yaml or specdo/config.yml",
29
+ required: true,
30
+ });
31
+ }
32
+ else {
33
+ const { config, issues } = loadConfig(cwd);
34
+ if (config && issues.length === 0) {
35
+ checks.push({
36
+ label: 'project config',
37
+ status: 'ok',
38
+ detail: `domainVersion=${config.domainVersion}, overrides=${Object.keys(config.overrides ?? {}).length}`,
39
+ required: true,
40
+ });
41
+ }
42
+ else {
43
+ checks.push({
44
+ label: 'project config',
45
+ status: 'fail',
46
+ detail: issues.map((i) => `${i.path}: ${i.message}`).slice(0, 3).join('; ') || 'invalid',
47
+ required: true,
48
+ });
49
+ }
50
+ }
51
+ // 子目录
52
+ for (const sub of ['specs', 'changes', 'archive']) {
53
+ const dir = path.join(specdoDir, sub);
54
+ checks.push({
55
+ label: `specdo/${sub}`,
56
+ status: safeIsDir(dir) ? 'ok' : 'warn',
57
+ detail: safeIsDir(dir) ? path.relative(cwd, dir) : 'missing (will be re-created on demand)',
58
+ required: false,
59
+ });
60
+ }
61
+ // active vs archive 冲突
62
+ const changesDir = path.join(specdoDir, 'changes');
63
+ const archiveDir = path.join(specdoDir, 'archive');
64
+ const conflicting = [];
65
+ if (safeIsDir(changesDir) && safeIsDir(archiveDir)) {
66
+ const activeNames = fs.readdirSync(changesDir).filter((n) => safeIsDir(path.join(changesDir, n)));
67
+ const archivedNames = new Set(fs.readdirSync(archiveDir).filter((n) => safeIsDir(path.join(archiveDir, n))));
68
+ for (const name of activeNames) {
69
+ if (archivedNames.has(name))
70
+ conflicting.push(name);
71
+ }
72
+ }
73
+ checks.push({
74
+ label: 'active vs archive',
75
+ status: conflicting.length === 0 ? 'ok' : 'warn',
76
+ detail: conflicting.length === 0
77
+ ? 'no overlapping change names'
78
+ : `${conflicting.length} overlapping name(s) detected: ${conflicting.join(', ')}. Run 'specdo archive --change <name>' to retry.`,
79
+ required: false,
80
+ });
81
+ // .sync-backup 残留
82
+ const syncBackupDir = path.join(specdoDir, '.sync-backup');
83
+ checks.push({
84
+ label: 'sync backup',
85
+ status: safeExists(syncBackupDir) ? 'warn' : 'ok',
86
+ detail: safeExists(syncBackupDir)
87
+ ? `Leftover at ${path.relative(cwd, syncBackupDir)}/. Review and remove manually.`
88
+ : 'no leftover',
89
+ required: false,
90
+ });
91
+ // context.json.lock 残留
92
+ const stale = [];
93
+ if (safeIsDir(changesDir)) {
94
+ for (const name of fs.readdirSync(changesDir)) {
95
+ const lock = path.join(changesDir, name, 'context.json.lock');
96
+ if (safeExists(lock)) {
97
+ try {
98
+ const stat = fs.statSync(lock);
99
+ const ageMs = Date.now() - stat.mtimeMs;
100
+ if (ageMs > STALE_LOCK_THRESHOLD_MS) {
101
+ stale.push({ path: path.relative(cwd, lock), ageMs });
102
+ }
103
+ }
104
+ catch {
105
+ /* ignore */
106
+ }
107
+ }
108
+ }
109
+ }
110
+ checks.push({
111
+ label: 'stale locks',
112
+ status: stale.length === 0 ? 'ok' : 'warn',
113
+ detail: stale.length === 0
114
+ ? 'no stale lock files'
115
+ : stale
116
+ .map((s) => `${s.path} (age ${(s.ageMs / 1000).toFixed(0)}s)`)
117
+ .join('; '),
118
+ required: false,
119
+ });
120
+ // ─── deep checks ───
121
+ if (options.deep) {
122
+ // Node 版本(仅作信息展示)
123
+ checks.push({
124
+ label: 'Node runtime',
125
+ status: 'ok',
126
+ detail: `${process.version} (platform=${process.platform})`,
127
+ required: false,
128
+ });
129
+ // 检查 active changes 是否含损坏的 context.json
130
+ if (safeIsDir(changesDir)) {
131
+ let corrupted = 0;
132
+ for (const name of fs.readdirSync(changesDir)) {
133
+ const ctxPath = path.join(changesDir, name, 'context.json');
134
+ if (safeExists(ctxPath)) {
135
+ try {
136
+ JSON.parse(fs.readFileSync(ctxPath, 'utf-8'));
137
+ }
138
+ catch {
139
+ corrupted++;
140
+ }
141
+ }
142
+ }
143
+ checks.push({
144
+ label: 'context.json integrity',
145
+ status: corrupted === 0 ? 'ok' : 'warn',
146
+ detail: corrupted === 0 ? `all parseable` : `${corrupted} corrupted (will fall back to .bak on next read)`,
147
+ required: false,
148
+ });
149
+ }
150
+ }
151
+ // ─── render ───
152
+ const requiredFailed = checks.filter((c) => c.required && c.status === 'fail');
153
+ if (options.json) {
154
+ return {
155
+ exitCode: requiredFailed.length === 0 ? 0 : 1,
156
+ stdout: [JSON.stringify({ checks, summary: requiredFailed.length === 0 ? 'ok' : 'failed' }, null, 2)],
157
+ stderr: [],
158
+ };
159
+ }
160
+ const stdout = [];
161
+ stdout.push('SpecDo Doctor');
162
+ stdout.push('');
163
+ for (const c of checks) {
164
+ const icon = c.status === 'ok' ? '✓' : c.status === 'warn' ? '!' : '✗';
165
+ stdout.push(` ${icon} ${c.label.padEnd(22)} ${c.detail}`);
166
+ }
167
+ stdout.push('');
168
+ if (requiredFailed.length > 0) {
169
+ stdout.push('Some required checks failed. Resolve the items above.');
170
+ return { exitCode: 1, stdout, stderr: [] };
171
+ }
172
+ if (checks.some((c) => c.status === 'warn')) {
173
+ stdout.push('Core checks passed. Optional items need attention.');
174
+ }
175
+ else {
176
+ stdout.push('All checks passed.');
177
+ }
178
+ return ok(stdout);
179
+ }
180
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * specdo domains [list | show <name>] [--json]
3
+ *
4
+ * 默认 `domains list`。`show <name>` 展示 override 应用后的有效配置。
5
+ */
6
+ import { CommandResult } from './_shared.js';
7
+ export interface DomainsOptions {
8
+ cwd: string;
9
+ subcommand?: 'list' | 'show';
10
+ name?: string;
11
+ json?: boolean;
12
+ }
13
+ export declare function handleDomains(options: DomainsOptions): Promise<CommandResult>;
14
+ //# sourceMappingURL=domains.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domains.d.ts","sourceRoot":"","sources":["../../src/commands/domains.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EACL,aAAa,EAKd,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA8FnF"}