spec-manager 0.1.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 (159) hide show
  1. package/AGENTS.md +27 -0
  2. package/CODEBUDDY.md +19 -0
  3. package/LICENSE +21 -0
  4. package/README.md +531 -0
  5. package/dist/cli/audit.d.ts +10 -0
  6. package/dist/cli/audit.d.ts.map +1 -0
  7. package/dist/cli/audit.js +62 -0
  8. package/dist/cli/audit.js.map +1 -0
  9. package/dist/cli/change.d.ts +10 -0
  10. package/dist/cli/change.d.ts.map +1 -0
  11. package/dist/cli/change.js +103 -0
  12. package/dist/cli/change.js.map +1 -0
  13. package/dist/cli/common.d.ts +5 -0
  14. package/dist/cli/common.d.ts.map +1 -0
  15. package/dist/cli/common.js +17 -0
  16. package/dist/cli/common.js.map +1 -0
  17. package/dist/cli/decision.d.ts +13 -0
  18. package/dist/cli/decision.d.ts.map +1 -0
  19. package/dist/cli/decision.js +185 -0
  20. package/dist/cli/decision.js.map +1 -0
  21. package/dist/cli/dict.d.ts +10 -0
  22. package/dist/cli/dict.d.ts.map +1 -0
  23. package/dist/cli/dict.js +73 -0
  24. package/dist/cli/dict.js.map +1 -0
  25. package/dist/cli/incident.d.ts +10 -0
  26. package/dist/cli/incident.d.ts.map +1 -0
  27. package/dist/cli/incident.js +119 -0
  28. package/dist/cli/incident.js.map +1 -0
  29. package/dist/cli/index.d.ts +3 -0
  30. package/dist/cli/index.d.ts.map +1 -0
  31. package/dist/cli/index.js +30 -0
  32. package/dist/cli/index.js.map +1 -0
  33. package/dist/cli/project.d.ts +3 -0
  34. package/dist/cli/project.d.ts.map +1 -0
  35. package/dist/cli/project.js +144 -0
  36. package/dist/cli/project.js.map +1 -0
  37. package/dist/cli/spec.d.ts +3 -0
  38. package/dist/cli/spec.d.ts.map +1 -0
  39. package/dist/cli/spec.js +289 -0
  40. package/dist/cli/spec.js.map +1 -0
  41. package/dist/cli/task.d.ts +14 -0
  42. package/dist/cli/task.d.ts.map +1 -0
  43. package/dist/cli/task.js +287 -0
  44. package/dist/cli/task.js.map +1 -0
  45. package/dist/cli/usability.d.ts +3 -0
  46. package/dist/cli/usability.d.ts.map +1 -0
  47. package/dist/cli/usability.js +153 -0
  48. package/dist/cli/usability.js.map +1 -0
  49. package/dist/core/agents.d.ts +43 -0
  50. package/dist/core/agents.d.ts.map +1 -0
  51. package/dist/core/agents.js +194 -0
  52. package/dist/core/agents.js.map +1 -0
  53. package/dist/core/archive.d.ts +35 -0
  54. package/dist/core/archive.d.ts.map +1 -0
  55. package/dist/core/archive.js +360 -0
  56. package/dist/core/archive.js.map +1 -0
  57. package/dist/core/audit-events.d.ts +12 -0
  58. package/dist/core/audit-events.d.ts.map +1 -0
  59. package/dist/core/audit-events.js +16 -0
  60. package/dist/core/audit-events.js.map +1 -0
  61. package/dist/core/audit.d.ts +78 -0
  62. package/dist/core/audit.d.ts.map +1 -0
  63. package/dist/core/audit.js +157 -0
  64. package/dist/core/audit.js.map +1 -0
  65. package/dist/core/constants.d.ts +28 -0
  66. package/dist/core/constants.d.ts.map +1 -0
  67. package/dist/core/constants.js +30 -0
  68. package/dist/core/constants.js.map +1 -0
  69. package/dist/core/decision.d.ts +69 -0
  70. package/dist/core/decision.d.ts.map +1 -0
  71. package/dist/core/decision.js +210 -0
  72. package/dist/core/decision.js.map +1 -0
  73. package/dist/core/delta.d.ts +85 -0
  74. package/dist/core/delta.d.ts.map +1 -0
  75. package/dist/core/delta.js +264 -0
  76. package/dist/core/delta.js.map +1 -0
  77. package/dist/core/dict.d.ts +28 -0
  78. package/dist/core/dict.d.ts.map +1 -0
  79. package/dist/core/dict.js +57 -0
  80. package/dist/core/dict.js.map +1 -0
  81. package/dist/core/frontmatter.d.ts +19 -0
  82. package/dist/core/frontmatter.d.ts.map +1 -0
  83. package/dist/core/frontmatter.js +57 -0
  84. package/dist/core/frontmatter.js.map +1 -0
  85. package/dist/core/incident.d.ts +45 -0
  86. package/dist/core/incident.d.ts.map +1 -0
  87. package/dist/core/incident.js +128 -0
  88. package/dist/core/incident.js.map +1 -0
  89. package/dist/core/paths.d.ts +68 -0
  90. package/dist/core/paths.d.ts.map +1 -0
  91. package/dist/core/paths.js +162 -0
  92. package/dist/core/paths.js.map +1 -0
  93. package/dist/core/repository.d.ts +13 -0
  94. package/dist/core/repository.d.ts.map +1 -0
  95. package/dist/core/repository.js +29 -0
  96. package/dist/core/repository.js.map +1 -0
  97. package/dist/core/spec-io.d.ts +125 -0
  98. package/dist/core/spec-io.d.ts.map +1 -0
  99. package/dist/core/spec-io.js +260 -0
  100. package/dist/core/spec-io.js.map +1 -0
  101. package/dist/core/status.d.ts +22 -0
  102. package/dist/core/status.d.ts.map +1 -0
  103. package/dist/core/status.js +54 -0
  104. package/dist/core/status.js.map +1 -0
  105. package/dist/core/task.d.ts +118 -0
  106. package/dist/core/task.d.ts.map +1 -0
  107. package/dist/core/task.js +340 -0
  108. package/dist/core/task.js.map +1 -0
  109. package/dist/core/usability.d.ts +25 -0
  110. package/dist/core/usability.d.ts.map +1 -0
  111. package/dist/core/usability.js +136 -0
  112. package/dist/core/usability.js.map +1 -0
  113. package/dist/core/validate.d.ts +34 -0
  114. package/dist/core/validate.d.ts.map +1 -0
  115. package/dist/core/validate.js +195 -0
  116. package/dist/core/validate.js.map +1 -0
  117. package/dist/index.d.ts +11 -0
  118. package/dist/index.d.ts.map +1 -0
  119. package/dist/index.js +12 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/schemas/change.d.ts +138 -0
  122. package/dist/schemas/change.d.ts.map +1 -0
  123. package/dist/schemas/change.js +38 -0
  124. package/dist/schemas/change.js.map +1 -0
  125. package/dist/schemas/spec.d.ts +233 -0
  126. package/dist/schemas/spec.d.ts.map +1 -0
  127. package/dist/schemas/spec.js +56 -0
  128. package/dist/schemas/spec.js.map +1 -0
  129. package/package.json +66 -0
  130. package/rules/_TEMPLATE.md +20 -0
  131. package/rules/code-discipline.md +47 -0
  132. package/rules/codebase-survey.md +37 -0
  133. package/rules/delta.md +42 -0
  134. package/rules/doc-governance.md +195 -0
  135. package/rules/flow-control.md +65 -0
  136. package/rules/quality-gate.md +73 -0
  137. package/skill/SKILL.md +90 -0
  138. package/skill/subskills/adr.md +73 -0
  139. package/skill/subskills/change.md +118 -0
  140. package/skill/subskills/design.md +53 -0
  141. package/skill/subskills/impl.md +100 -0
  142. package/skill/subskills/plan.md +46 -0
  143. package/skill/subskills/postmortem.md +77 -0
  144. package/skill/subskills/prd.md +72 -0
  145. package/skill/subskills/quick.md +25 -0
  146. package/skill/subskills/release.md +50 -0
  147. package/skill/subskills/research.md +35 -0
  148. package/skill/subskills/runbook.md +44 -0
  149. package/skill/subskills/testplan.md +48 -0
  150. package/templates/L0-prd.md +43 -0
  151. package/templates/L1-prd.md +130 -0
  152. package/templates/L2-design.md +135 -0
  153. package/templates/L3-impl.md +125 -0
  154. package/templates/agent-plan.json +17 -0
  155. package/templates/agents/AGENTS.md +27 -0
  156. package/templates/agents/CLAUDE.md +11 -0
  157. package/templates/agents/CODEBUDDY.md +23 -0
  158. package/templates/agents/codebuddy-skill/SKILL.md +46 -0
  159. package/templates/decision.md +42 -0
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Spec 文件的原子读写。
3
+ *
4
+ * 写策略:写临时文件 → rename,保证并发下不会读到半截内容。
5
+ * 读策略:先解析 frontmatter,找不到时返回 null(由调用方决定 fallback)。
6
+ */
7
+ import { existsSync, renameSync, statSync } from 'node:fs';
8
+ import { readFrontmatter, writeFrontmatter, writeAtomic } from './frontmatter.js';
9
+ import { assertSafeSpecCode, assertSafeTopic, listSpecFiles, listSpecPathMigrations, specFilePath, } from './paths.js';
10
+ import { AI_SUMMARY_MAX, PLACEHOLDER_MARKER, PLACEHOLDER_CONTENT_MAX } from './constants.js';
11
+ import { recordAuditHit } from './audit-events.js';
12
+ export const DESC_MAX_LEN = 15;
13
+ /**
14
+ * 生成 spec code: 点分编号,层级自文档化。
15
+ * - L1: <topic>-L1
16
+ * - L2: <topic>-L2.1(第 1 个 L2 子 spec)
17
+ * - L3: <topic>-L3.1.1[-desc](可选描述后缀,≤15 字符)
18
+ *
19
+ * parentCode 为空时生成 <topic>-<level>;
20
+ * 非空时生成 <topic>-<level>.<N>[.M...][-desc]。
21
+ */
22
+ export function generateSpecCode(topic, level, parentCode, siblingCount, desc) {
23
+ if (!parentCode) {
24
+ return desc ? `${topic}-${level}-${desc}` : `${topic}-${level}`;
25
+ }
26
+ const idx = (siblingCount ?? 0) + 1;
27
+ const match = parentCode.match(/^(.+)-L\d+(.*)$/);
28
+ const base = match
29
+ ? `${match[1]}-${level}${match[2]}.${idx}`
30
+ : `${topic}-${level}.${idx}`;
31
+ return desc ? `${base}-${desc}` : base;
32
+ }
33
+ export function readSpec(filePath) {
34
+ try {
35
+ const { data, content } = readFrontmatter(filePath);
36
+ return { fm: data, content, filePath };
37
+ }
38
+ catch (err) {
39
+ if (err.code === 'ENOENT')
40
+ return null;
41
+ throw err;
42
+ }
43
+ }
44
+ export function findSpecByCode(paths, code) {
45
+ const all = listAllSpecs(paths);
46
+ return all.find(s => s.fm.code === code) ?? null;
47
+ }
48
+ const specCache = new Map();
49
+ /**
50
+ * 带 mtime 失效的 listAllSpecs。文件未变时复用内存里的解析结果,
51
+ * 避免每次 decision/task/archive/delta 全扫都重新 parse frontmatter。
52
+ *
53
+ * 注意:单进程内有效;多进程或显式调 invalidateSpecCache() 失效。
54
+ */
55
+ export function listAllSpecs(paths) {
56
+ const files = listSpecFiles(paths);
57
+ const out = [];
58
+ for (const f of files) {
59
+ let mtimeMs;
60
+ try {
61
+ mtimeMs = statSync(f.filePath).mtimeMs;
62
+ }
63
+ catch {
64
+ // file gone — drop from cache, skip
65
+ specCache.delete(f.filePath);
66
+ continue;
67
+ }
68
+ const cached = specCache.get(f.filePath);
69
+ if (cached && cached.mtimeMs === mtimeMs) {
70
+ out.push(cached.record);
71
+ continue;
72
+ }
73
+ const rec = readSpec(f.filePath);
74
+ if (rec) {
75
+ validateSpecFileIdentity(f, rec);
76
+ specCache.set(f.filePath, { mtimeMs, record: rec });
77
+ out.push(rec);
78
+ }
79
+ }
80
+ return out;
81
+ }
82
+ export function invalidateSpecCache(filePath) {
83
+ if (filePath) {
84
+ specCache.delete(filePath);
85
+ }
86
+ else {
87
+ specCache.clear();
88
+ }
89
+ }
90
+ /**
91
+ * 原子写:先写临时文件,再 rename。
92
+ */
93
+ export function writeSpec(record) {
94
+ const out = writeFrontmatter(record.fm, record.content);
95
+ writeAtomic(record.filePath, out);
96
+ invalidateSpecCache(record.filePath);
97
+ }
98
+ export function createSpec(args) {
99
+ let parentFilePath = null;
100
+ if (args.parentCode) {
101
+ const parent = args.parentRecord ?? findSpecByCode(args.paths, args.parentCode);
102
+ if (!parent) {
103
+ throw new Error(`parentCode 指向不存在的 spec: ${args.parentCode}`);
104
+ }
105
+ const expectedParentLevels = {
106
+ L0: [],
107
+ L1: [],
108
+ L2: ['L0', 'L1'],
109
+ L3: ['L2'],
110
+ };
111
+ if (!expectedParentLevels[args.level].includes(parent.fm.level)) {
112
+ recordAuditHit({ paths: args.paths, ruleId: 'R7', specCode: args.code }, args.auditSink);
113
+ throw new Error(`R7: ${args.level} 的 parent 必须是 ${expectedParentLevels[args.level].join('/')}, ` +
114
+ `实际是 ${parent.fm.level} (${args.parentCode})`);
115
+ }
116
+ if ((args.level === 'L2' || args.level === 'L3') && parent.fm.status === 'draft') {
117
+ recordAuditHit({ paths: args.paths, ruleId: 'R4', specCode: args.code }, args.auditSink);
118
+ throw new Error(`R4: 创建 ${args.level} 前父级 ${args.parentCode} 必须先通过独立审核(confirmed/frozen/implemented),` +
119
+ `当前 status=${parent.fm.status}`);
120
+ }
121
+ recordAuditHit({ paths: args.paths, ruleId: 'R4', specCode: args.code }, args.auditSink);
122
+ parentFilePath = parent.filePath;
123
+ }
124
+ else if (args.level === 'L2' || args.level === 'L3') {
125
+ recordAuditHit({ paths: args.paths, ruleId: 'R7', specCode: args.code }, args.auditSink);
126
+ throw new Error(`R7: ${args.level} 必须有 parentCode`);
127
+ }
128
+ const filePath = specFilePath(args.paths, parentFilePath, args.code, args.topic);
129
+ const now = new Date().toISOString();
130
+ const fm = {
131
+ code: args.code,
132
+ level: args.level,
133
+ title: args.title,
134
+ topic: args.topic,
135
+ parentCode: args.parentCode,
136
+ status: 'draft',
137
+ milestone: args.milestone,
138
+ created: now,
139
+ updated: now,
140
+ };
141
+ const rec = { fm, content: `# ${args.title}\n\n${PLACEHOLDER_MARKER}\n`, filePath };
142
+ writeSpec(rec);
143
+ if (args.level === 'L0' || args.level === 'L1') {
144
+ recordAuditHit({ paths: args.paths, ruleId: 'R4', specCode: args.code }, args.auditSink);
145
+ }
146
+ return rec;
147
+ }
148
+ export function updateSpec(paths, code, patch, opts) {
149
+ const warnings = [];
150
+ const existing = findSpecByCode(paths, code);
151
+ if (!existing) {
152
+ throw new Error(`Spec not found: ${code}`);
153
+ }
154
+ const fm = { ...existing.fm };
155
+ let content = existing.content;
156
+ if (patch.content !== undefined) {
157
+ if (patch.aiSummary === undefined || patch.aiSummary.trim().length === 0) {
158
+ recordAuditHit({ paths, ruleId: 'R13', specCode: code }, opts?.auditSink);
159
+ throw new Error(`R13: spec update --content 必须同时提供 aiSummary,禁止写正文后没有 AI 摘要`);
160
+ }
161
+ if (isPlaceholderContent(patch.content)) {
162
+ recordAuditHit({ paths, ruleId: 'R22', specCode: code }, opts?.auditSink);
163
+ throw new Error(`R22: contentTemplate 仍是占位内容,spec 创建后必须立即写正文`);
164
+ }
165
+ content = patch.content;
166
+ }
167
+ if (patch.aiSummary !== undefined) {
168
+ if (patch.aiSummary.length > AI_SUMMARY_MAX) {
169
+ recordAuditHit({ paths, ruleId: 'R21', specCode: code }, opts?.auditSink);
170
+ warnings.push(`aiSummary 超过 ${AI_SUMMARY_MAX} 字符,已自动截断(原长 ${patch.aiSummary.length})`);
171
+ fm.aiSummary = patch.aiSummary.slice(0, AI_SUMMARY_MAX);
172
+ }
173
+ else {
174
+ fm.aiSummary = patch.aiSummary;
175
+ }
176
+ }
177
+ if (patch.changeSummary !== undefined)
178
+ fm.changeSummary = patch.changeSummary;
179
+ if (patch.status !== undefined)
180
+ fm.status = patch.status;
181
+ if (patch.appendStep) {
182
+ fm.steps = [...(fm.steps ?? []), patch.appendStep];
183
+ }
184
+ if (patch.replaceStep) {
185
+ const steps = [...(fm.steps ?? [])];
186
+ const idx = steps.findIndex(s => String(s.stepNo) === String(patch.replaceStep.no));
187
+ if (idx >= 0)
188
+ steps[idx] = patch.replaceStep.step;
189
+ else
190
+ steps.push(patch.replaceStep.step);
191
+ fm.steps = steps;
192
+ }
193
+ if (patch.addRelation) {
194
+ fm.relations = [...(fm.relations ?? []), patch.addRelation];
195
+ }
196
+ fm.updated = new Date().toISOString();
197
+ const rec = { fm, content, filePath: existing.filePath };
198
+ writeSpec(rec);
199
+ if (patch.content !== undefined) {
200
+ recordAuditHit({ paths, ruleId: 'R1', specCode: code }, opts?.auditSink);
201
+ recordAuditHit({ paths, ruleId: 'R13', specCode: code }, opts?.auditSink);
202
+ recordAuditHit({ paths, ruleId: 'R22', specCode: code }, opts?.auditSink);
203
+ }
204
+ return { record: rec, warnings };
205
+ }
206
+ /**
207
+ * R22: contentTemplate 是不是只剩 createSpec 写出的占位?
208
+ * 占位 = 文件里有 marker 行,且去掉 marker 后正文长度 < PLACEHOLDER_CONTENT_MAX。
209
+ */
210
+ export function isPlaceholderContent(content) {
211
+ if (!content || !content.includes(PLACEHOLDER_MARKER))
212
+ return false;
213
+ const stripped = content.replace(PLACEHOLDER_MARKER, '').trim();
214
+ return stripped.length < PLACEHOLDER_CONTENT_MAX;
215
+ }
216
+ function validateSpecFileIdentity(entry, record) {
217
+ assertSafeTopic(entry.topic);
218
+ assertSafeSpecCode(entry.code);
219
+ if (record.fm.code !== entry.code) {
220
+ throw new Error(`Spec 文件名和 frontmatter code 不一致: ${entry.filePath} (filename=${entry.code}, fm=${record.fm.code})`);
221
+ }
222
+ if (record.fm.topic !== entry.topic) {
223
+ throw new Error(`Spec 目录和 frontmatter topic 不一致: ${entry.filePath} (dir=${entry.topic}, fm=${record.fm.topic})`);
224
+ }
225
+ }
226
+ export function migrateSpecPaths(paths, opts) {
227
+ const migrations = listSpecPathMigrations(paths);
228
+ const errors = [];
229
+ for (const m of migrations) {
230
+ try {
231
+ assertSafeTopic(m.topic);
232
+ assertSafeSpecCode(m.code);
233
+ const rec = readSpec(m.from);
234
+ if (!rec)
235
+ throw new Error('无法读取 spec');
236
+ validateSpecFileIdentity({ topic: m.topic, code: m.code, filePath: m.from }, rec);
237
+ if (existsSync(m.to))
238
+ throw new Error(`目标文件已存在: ${m.to}`);
239
+ }
240
+ catch (err) {
241
+ const reason = err instanceof Error ? err.message : String(err);
242
+ errors.push(`${m.from}: ${reason}`);
243
+ }
244
+ }
245
+ if (errors.length > 0) {
246
+ throw new Error(`spec path migration 预检失败:\n${errors.join('\n')}`);
247
+ }
248
+ if (!opts?.dryRun) {
249
+ for (const m of migrations) {
250
+ renameSync(m.from, m.to);
251
+ invalidateSpecCache(m.from);
252
+ invalidateSpecCache(m.to);
253
+ }
254
+ }
255
+ return {
256
+ dryRun: opts?.dryRun ?? false,
257
+ migrated: migrations.map(m => ({ code: m.code, from: m.from, to: m.to })),
258
+ };
259
+ }
260
+ //# sourceMappingURL=spec-io.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-io.js","sourceRoot":"","sources":["../../src/core/spec-io.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Spec 状态机:draft → confirmed → frozen → implemented
3
+ * - draft → confirmed: 用户批准
4
+ * - confirmed → frozen: 用户批准(仅 L3)
5
+ * - frozen → implemented: 仅由 task complete 触发(自动级联)
6
+ * - * → archived: supersede 时
7
+ *
8
+ * 严禁:confirmed → draft(回退),除非显式 supersede
9
+ */
10
+ export type SpecStatus = 'draft' | 'confirmed' | 'frozen' | 'implemented' | 'archived';
11
+ export declare function canTransition(from: SpecStatus, to: SpecStatus): boolean;
12
+ export declare function nextStatuses(from: SpecStatus): SpecStatus[];
13
+ export declare const ALL_STATUSES: SpecStatus[];
14
+ export declare function isActiveStatus(s: SpecStatus): boolean;
15
+ export declare function isCompleteStatus(s: SpecStatus): boolean;
16
+ export type TaskStatus = 'draft' | 'running' | 'waiting' | 'completed' | 'failed';
17
+ export declare const ALL_TASK_STATUSES: TaskStatus[];
18
+ export declare function canTaskTransition(from: TaskStatus, to: TaskStatus): boolean;
19
+ export declare function nextTaskStatuses(from: TaskStatus): TaskStatus[];
20
+ export declare function assertTaskTransition(from: TaskStatus, to: TaskStatus): void;
21
+ export declare function assertSpecTransition(from: SpecStatus, to: SpecStatus): void;
22
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/core/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,WAAW,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,CAAC;AAUvF,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAEvE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAE3D;AAED,eAAO,MAAM,YAAY,EAAE,UAAU,EAAgE,CAAC;AAEtG,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAEvD;AAED,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;AAUlF,eAAO,MAAM,iBAAiB,EAAE,UAAU,EAA2D,CAAC;AAEtG,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAE3E;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAE/D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,CAI3E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,GAAG,IAAI,CAI3E"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Spec 状态机:draft → confirmed → frozen → implemented
3
+ * - draft → confirmed: 用户批准
4
+ * - confirmed → frozen: 用户批准(仅 L3)
5
+ * - frozen → implemented: 仅由 task complete 触发(自动级联)
6
+ * - * → archived: supersede 时
7
+ *
8
+ * 严禁:confirmed → draft(回退),除非显式 supersede
9
+ */
10
+ const TRANSITIONS = {
11
+ draft: ['confirmed', 'archived'],
12
+ confirmed: ['frozen', 'archived'], // L1/L2 confirmed 后也可直接 archived(被取代)
13
+ frozen: ['implemented', 'confirmed', 'archived'], // frozen → confirmed 允许用户重审
14
+ implemented: ['archived'], // implemented → archived(被新 spec 取代)
15
+ archived: [], // 终态
16
+ };
17
+ export function canTransition(from, to) {
18
+ return TRANSITIONS[from]?.includes(to) ?? false;
19
+ }
20
+ export function nextStatuses(from) {
21
+ return TRANSITIONS[from] ?? [];
22
+ }
23
+ export const ALL_STATUSES = ['draft', 'confirmed', 'frozen', 'implemented', 'archived'];
24
+ export function isActiveStatus(s) {
25
+ return s !== 'archived';
26
+ }
27
+ export function isCompleteStatus(s) {
28
+ return s === 'implemented' || s === 'archived';
29
+ }
30
+ const TASK_TRANSITIONS = {
31
+ draft: ['running', 'failed'],
32
+ running: ['waiting', 'completed', 'failed'],
33
+ waiting: ['running', 'failed', 'completed'],
34
+ completed: [],
35
+ failed: [],
36
+ };
37
+ export const ALL_TASK_STATUSES = ['draft', 'running', 'waiting', 'completed', 'failed'];
38
+ export function canTaskTransition(from, to) {
39
+ return TASK_TRANSITIONS[from]?.includes(to) ?? false;
40
+ }
41
+ export function nextTaskStatuses(from) {
42
+ return TASK_TRANSITIONS[from] ?? [];
43
+ }
44
+ export function assertTaskTransition(from, to) {
45
+ if (!canTaskTransition(from, to)) {
46
+ throw new Error(`Task 状态非法: ${from} → ${to}`);
47
+ }
48
+ }
49
+ export function assertSpecTransition(from, to) {
50
+ if (!canTransition(from, to)) {
51
+ throw new Error(`状态非法: ${from} → ${to}`);
52
+ }
53
+ }
54
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/core/status.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,GAAqC;IACpD,KAAK,EAAO,CAAC,WAAW,EAAE,UAAU,CAAC;IACrC,SAAS,EAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAW,sCAAsC;IACnF,MAAM,EAAM,CAAC,aAAa,EAAE,WAAW,EAAE,UAAU,CAAC,EAAG,4BAA4B;IACnF,WAAW,EAAC,CAAC,UAAU,CAAC,EAAqB,qCAAqC;IAClF,QAAQ,EAAI,EAAE,EAA+B,KAAK;CACnD,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAAgB,EAAE,EAAc;IAC5D,OAAO,WAAW,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;AAEtG,MAAM,UAAU,cAAc,CAAC,CAAa;IAC1C,OAAO,CAAC,KAAK,UAAU,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,CAAa;IAC5C,OAAO,CAAC,KAAK,aAAa,IAAI,CAAC,KAAK,UAAU,CAAC;AACjD,CAAC;AAID,MAAM,gBAAgB,GAAqC;IACzD,KAAK,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC5B,OAAO,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC;IAC3C,OAAO,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC;IAC3C,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;CACX,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAiB,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AAEtG,MAAM,UAAU,iBAAiB,CAAC,IAAgB,EAAE,EAAc;IAChE,OAAO,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAgB;IAC/C,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAgB,EAAE,EAAc;IACnE,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAAgB,EAAE,EAAc;IACnE,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC;AACH,CAAC"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Agent Task 生命周期
3
+ * - task 元数据:specs/<topic>/<L1>/<L2>/<L3>/tasks/<taskId>.json
4
+ * - task 步骤:L3 spec frontmatter steps[](与 spec 同文件,原子写)
5
+ *
6
+ * 状态机:draft → running → (waiting →) running → completed | failed
7
+ * cascade: complete 时若 L3 已全 implemented → 把父 L2 也置 implemented(递归)
8
+ */
9
+ import { type ProjectPaths } from './paths.js';
10
+ import { findSpecByCode, type StepFrontmatter } from './spec-io.js';
11
+ import { type StepStatusT, type StepTypeT } from '../schemas/spec.js';
12
+ import { type AuditSink } from './audit-events.js';
13
+ import { type TaskStatus } from './status.js';
14
+ export type { TaskStatus } from './status.js';
15
+ export interface TaskRecord {
16
+ id: string;
17
+ specCode: string;
18
+ status: TaskStatus;
19
+ steps?: StepFrontmatter[];
20
+ autoConfirm: boolean;
21
+ startedAt: string | null;
22
+ finishedAt: string | null;
23
+ created: string;
24
+ waitReason: string | null;
25
+ errorCode: string | null;
26
+ errorMessage: string | null;
27
+ }
28
+ export { canTaskTransition } from './status.js';
29
+ export declare function generateTaskId(specFilePath: string, specCode: string): string;
30
+ export interface CreateTaskInput {
31
+ paths: ProjectPaths;
32
+ specCode: string;
33
+ planJson: {
34
+ coveredSpecs?: string[];
35
+ steps: Array<{
36
+ stepNo: number | string;
37
+ stepType: StepTypeT;
38
+ name: string;
39
+ }>;
40
+ };
41
+ autoConfirm: boolean;
42
+ auditSink?: AuditSink;
43
+ }
44
+ export declare function createTask(input: CreateTaskInput): {
45
+ task: TaskRecord;
46
+ taskFile: string;
47
+ };
48
+ export declare function findTask(paths: ProjectPaths, specCode: string, taskId: string): TaskRecord | null;
49
+ export declare function listTasks(paths: ProjectPaths, opts?: {
50
+ specCode?: string;
51
+ status?: TaskStatus;
52
+ topic?: string;
53
+ }): TaskRecord[];
54
+ export declare function startTask(paths: ProjectPaths, taskId: string, specCode?: string): TaskRecord;
55
+ export interface StepInput {
56
+ paths: ProjectPaths;
57
+ taskId: string;
58
+ specCode?: string;
59
+ stepNo: number | string;
60
+ status: StepStatusT;
61
+ toolName?: string;
62
+ inputJson?: string;
63
+ outputJson?: string;
64
+ errorCode?: string;
65
+ errorMessage?: string;
66
+ latencyMs?: number;
67
+ }
68
+ export declare function reportStep(input: StepInput): {
69
+ task: TaskRecord;
70
+ spec: ReturnType<typeof findSpecByCode>;
71
+ warnings: string[];
72
+ };
73
+ export interface CompleteInput {
74
+ paths: ProjectPaths;
75
+ taskId: string;
76
+ specCode?: string;
77
+ auditSink?: AuditSink;
78
+ }
79
+ export interface CompleteResult {
80
+ task: TaskRecord;
81
+ cascadedSpecs: Array<{
82
+ code: string;
83
+ oldStatus: string;
84
+ newStatus: string;
85
+ level: 'L0' | 'L1' | 'L2' | 'L3';
86
+ }>;
87
+ cascadedL1Specs: string[];
88
+ skippedSpecs: Array<{
89
+ code: string;
90
+ status: string;
91
+ reason: string;
92
+ }>;
93
+ }
94
+ export declare function completeTask(input: CompleteInput): CompleteResult;
95
+ export interface FailInput {
96
+ paths: ProjectPaths;
97
+ taskId: string;
98
+ specCode?: string;
99
+ errorCode?: string;
100
+ errorMessage?: string;
101
+ }
102
+ export declare function failTask(input: FailInput): TaskRecord;
103
+ export interface WaitInput {
104
+ paths: ProjectPaths;
105
+ taskId: string;
106
+ specCode?: string;
107
+ reason?: string;
108
+ }
109
+ export declare function waitTask(input: WaitInput): TaskRecord;
110
+ export declare function showTask(paths: ProjectPaths, taskId: string, opts?: {
111
+ full?: boolean;
112
+ specCode?: string;
113
+ }): {
114
+ task: TaskRecord;
115
+ steps: StepFrontmatter[];
116
+ truncated: boolean;
117
+ } | null;
118
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/core/task.ts"],"names":[],"mappings":"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"}