openspec-mcp 0.3.0 → 0.3.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 (106) hide show
  1. package/README.md +22 -6
  2. package/README.zh.md +36 -1
  3. package/dist/api/routes/changes.d.ts.map +1 -1
  4. package/dist/api/routes/changes.js +42 -0
  5. package/dist/api/routes/changes.js.map +1 -1
  6. package/dist/api/routes/context.d.ts +8 -0
  7. package/dist/api/routes/context.d.ts.map +1 -0
  8. package/dist/api/routes/context.js +45 -0
  9. package/dist/api/routes/context.js.map +1 -0
  10. package/dist/api/routes/kanban.d.ts +8 -0
  11. package/dist/api/routes/kanban.d.ts.map +1 -0
  12. package/dist/api/routes/kanban.js +181 -0
  13. package/dist/api/routes/kanban.js.map +1 -0
  14. package/dist/api/routes/qa.d.ts +8 -0
  15. package/dist/api/routes/qa.d.ts.map +1 -0
  16. package/dist/api/routes/qa.js +98 -0
  17. package/dist/api/routes/qa.js.map +1 -0
  18. package/dist/api/server.d.ts +1 -0
  19. package/dist/api/server.d.ts.map +1 -1
  20. package/dist/api/server.js +7 -0
  21. package/dist/api/server.js.map +1 -1
  22. package/dist/core/approval-manager.d.ts.map +1 -1
  23. package/dist/core/approval-manager.js +9 -1
  24. package/dist/core/approval-manager.js.map +1 -1
  25. package/dist/core/approval-manager.test.js +14 -0
  26. package/dist/core/approval-manager.test.js.map +1 -1
  27. package/dist/core/context-analyzer.d.ts +116 -0
  28. package/dist/core/context-analyzer.d.ts.map +1 -0
  29. package/dist/core/context-analyzer.js +495 -0
  30. package/dist/core/context-analyzer.js.map +1 -0
  31. package/dist/core/prompt-manager.d.ts +50 -0
  32. package/dist/core/prompt-manager.d.ts.map +1 -0
  33. package/dist/core/prompt-manager.js +186 -0
  34. package/dist/core/prompt-manager.js.map +1 -0
  35. package/dist/core/qa-runner.d.ts +134 -0
  36. package/dist/core/qa-runner.d.ts.map +1 -0
  37. package/dist/core/qa-runner.js +299 -0
  38. package/dist/core/qa-runner.js.map +1 -0
  39. package/dist/core/spec-critic.d.ts +118 -0
  40. package/dist/core/spec-critic.d.ts.map +1 -0
  41. package/dist/core/spec-critic.js +478 -0
  42. package/dist/core/spec-critic.js.map +1 -0
  43. package/dist/core/spec-critic.test.d.ts +5 -0
  44. package/dist/core/spec-critic.test.d.ts.map +1 -0
  45. package/dist/core/spec-critic.test.js +152 -0
  46. package/dist/core/spec-critic.test.js.map +1 -0
  47. package/dist/core/task-parser.d.ts.map +1 -1
  48. package/dist/core/task-parser.js +39 -14
  49. package/dist/core/task-parser.js.map +1 -1
  50. package/dist/index.js +33 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/server/tools/ai-context.d.ts +13 -0
  53. package/dist/server/tools/ai-context.d.ts.map +1 -0
  54. package/dist/server/tools/ai-context.js +212 -0
  55. package/dist/server/tools/ai-context.js.map +1 -0
  56. package/dist/server/tools/approval.d.ts.map +1 -1
  57. package/dist/server/tools/approval.js +33 -18
  58. package/dist/server/tools/approval.js.map +1 -1
  59. package/dist/server/tools/archive.d.ts.map +1 -1
  60. package/dist/server/tools/archive.js +9 -6
  61. package/dist/server/tools/archive.js.map +1 -1
  62. package/dist/server/tools/context.d.ts +12 -0
  63. package/dist/server/tools/context.d.ts.map +1 -0
  64. package/dist/server/tools/context.js +145 -0
  65. package/dist/server/tools/context.js.map +1 -0
  66. package/dist/server/tools/critique.d.ts +12 -0
  67. package/dist/server/tools/critique.d.ts.map +1 -0
  68. package/dist/server/tools/critique.js +194 -0
  69. package/dist/server/tools/critique.js.map +1 -0
  70. package/dist/server/tools/cross-service.d.ts.map +1 -1
  71. package/dist/server/tools/cross-service.js +11 -5
  72. package/dist/server/tools/cross-service.js.map +1 -1
  73. package/dist/server/tools/generator.d.ts.map +1 -1
  74. package/dist/server/tools/generator.js +27 -18
  75. package/dist/server/tools/generator.js.map +1 -1
  76. package/dist/server/tools/guides.d.ts.map +1 -1
  77. package/dist/server/tools/guides.js +8 -2
  78. package/dist/server/tools/guides.js.map +1 -1
  79. package/dist/server/tools/hooks.d.ts.map +1 -1
  80. package/dist/server/tools/hooks.js +7 -4
  81. package/dist/server/tools/hooks.js.map +1 -1
  82. package/dist/server/tools/management.d.ts.map +1 -1
  83. package/dist/server/tools/management.js +26 -14
  84. package/dist/server/tools/management.js.map +1 -1
  85. package/dist/server/tools/qa.d.ts +12 -0
  86. package/dist/server/tools/qa.d.ts.map +1 -0
  87. package/dist/server/tools/qa.js +248 -0
  88. package/dist/server/tools/qa.js.map +1 -0
  89. package/dist/server/tools/reviews.d.ts.map +1 -1
  90. package/dist/server/tools/reviews.js +55 -37
  91. package/dist/server/tools/reviews.js.map +1 -1
  92. package/dist/server/tools/tasks.d.ts.map +1 -1
  93. package/dist/server/tools/tasks.js +29 -17
  94. package/dist/server/tools/tasks.js.map +1 -1
  95. package/dist/server/tools/templates.d.ts.map +1 -1
  96. package/dist/server/tools/templates.js +26 -17
  97. package/dist/server/tools/templates.js.map +1 -1
  98. package/dist/server/tools/validation.d.ts.map +1 -1
  99. package/dist/server/tools/validation.js +31 -22
  100. package/dist/server/tools/validation.js.map +1 -1
  101. package/package.json +1 -1
  102. package/web/dist/assets/index-Bf5mzJti.css +1 -0
  103. package/web/dist/assets/index-W9UMaaAn.js +244 -0
  104. package/web/dist/index.html +2 -2
  105. package/web/dist/assets/index-CCYunmpc.css +0 -1
  106. package/web/dist/assets/index-wgGN6sVJ.js +0 -244
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Spec Critic - 规格自审模块
3
+ *
4
+ * 在人工审批前自动评审 proposal/design 文档,识别潜在问题:
5
+ * - 完整性检查:问题描述、解决方案、影响范围
6
+ * - 技术可行性:代码引用、依赖兼容性
7
+ * - 安全考量:认证、授权、数据验证
8
+ * - 边界条件:错误处理、空值、并发
9
+ * - 清晰度:术语一致性、表述歧义
10
+ */
11
+ /**
12
+ * 评审类别
13
+ */
14
+ export type CritiqueCategory = 'completeness' | 'feasibility' | 'security' | 'edge_case' | 'clarity';
15
+ /**
16
+ * 严重程度
17
+ */
18
+ export type CritiqueSeverity = 'critical' | 'warning' | 'info';
19
+ /**
20
+ * 单条评审意见
21
+ */
22
+ export interface Critique {
23
+ id: string;
24
+ category: CritiqueCategory;
25
+ severity: CritiqueSeverity;
26
+ title: string;
27
+ description: string;
28
+ location?: {
29
+ section: string;
30
+ lineRange?: [number, number];
31
+ };
32
+ suggestion?: string;
33
+ }
34
+ /**
35
+ * 评审结果
36
+ */
37
+ export interface CritiqueResult {
38
+ changeName: string;
39
+ documentType: 'proposal' | 'design' | 'all';
40
+ overallScore: number;
41
+ critiques: Critique[];
42
+ suggestions: string[];
43
+ summary: {
44
+ total: number;
45
+ critical: number;
46
+ warning: number;
47
+ info: number;
48
+ byCategory: Record<CritiqueCategory, number>;
49
+ };
50
+ createdAt: string;
51
+ }
52
+ /**
53
+ * SpecCritic 主类
54
+ */
55
+ export declare class SpecCritic {
56
+ private cwd;
57
+ private rules;
58
+ constructor(options?: {
59
+ cwd?: string;
60
+ });
61
+ /**
62
+ * 获取评审结果存储目录
63
+ */
64
+ private getCritiquesDir;
65
+ /**
66
+ * 获取变更目录
67
+ */
68
+ private getChangeDir;
69
+ /**
70
+ * ID 安全校验
71
+ */
72
+ private ensureSafeId;
73
+ /**
74
+ * 确保目录存在
75
+ */
76
+ private ensureDir;
77
+ /**
78
+ * 评审 Proposal
79
+ */
80
+ critiqueProposal(changeName: string): Promise<CritiqueResult>;
81
+ /**
82
+ * 评审 Design
83
+ */
84
+ critiqueDesign(changeName: string): Promise<CritiqueResult>;
85
+ /**
86
+ * 评审所有文档(proposal + design)
87
+ */
88
+ critiqueAll(changeName: string): Promise<CritiqueResult>;
89
+ /**
90
+ * 执行评审
91
+ */
92
+ private performCritique;
93
+ /**
94
+ * 解析文档章节
95
+ */
96
+ private parseSections;
97
+ /**
98
+ * 生成综合建议
99
+ */
100
+ private generateSuggestions;
101
+ /**
102
+ * 保存评审结果
103
+ */
104
+ saveCritiqueResult(result: CritiqueResult): Promise<void>;
105
+ /**
106
+ * 获取评审历史
107
+ */
108
+ getCritiqueHistory(changeName: string): Promise<CritiqueResult[]>;
109
+ /**
110
+ * 获取最新评审结果
111
+ */
112
+ getLatestCritique(changeName: string): Promise<CritiqueResult | null>;
113
+ /**
114
+ * 初始化评审规则
115
+ */
116
+ private initializeRules;
117
+ }
118
+ //# sourceMappingURL=spec-critic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-critic.d.ts","sourceRoot":"","sources":["../../src/core/spec-critic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACxB,cAAc,GACd,aAAa,GACb,UAAU,GACV,WAAW,GACX,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;KAC9C,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;CACnB;AAqBD;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,KAAK,CAAiB;gBAElB,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE;IAKtC;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;YACW,SAAS;IAIvB;;OAEG;IACG,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAYnE;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAYjE;;OAEG;IACG,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA8B9D;;OAEG;IACH,OAAO,CAAC,eAAe;IAgEvB;;OAEG;IACH,OAAO,CAAC,aAAa;IA6BrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+B3B;;OAEG;IACG,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAY/D;;OAEG;IACG,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA2BvE;;OAEG;IACG,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAK3E;;OAEG;IACH,OAAO,CAAC,eAAe;CAyNxB"}
@@ -0,0 +1,478 @@
1
+ /**
2
+ * Spec Critic - 规格自审模块
3
+ *
4
+ * 在人工审批前自动评审 proposal/design 文档,识别潜在问题:
5
+ * - 完整性检查:问题描述、解决方案、影响范围
6
+ * - 技术可行性:代码引用、依赖兼容性
7
+ * - 安全考量:认证、授权、数据验证
8
+ * - 边界条件:错误处理、空值、并发
9
+ * - 清晰度:术语一致性、表述歧义
10
+ */
11
+ import * as fs from 'fs/promises';
12
+ import * as path from 'path';
13
+ import { randomUUID } from 'crypto';
14
+ /**
15
+ * SpecCritic 主类
16
+ */
17
+ export class SpecCritic {
18
+ cwd;
19
+ rules;
20
+ constructor(options) {
21
+ this.cwd = options?.cwd || process.cwd();
22
+ this.rules = this.initializeRules();
23
+ }
24
+ /**
25
+ * 获取评审结果存储目录
26
+ */
27
+ getCritiquesDir() {
28
+ return path.join(this.cwd, 'openspec', 'critiques');
29
+ }
30
+ /**
31
+ * 获取变更目录
32
+ */
33
+ getChangeDir(changeName) {
34
+ const safeId = this.ensureSafeId(changeName);
35
+ return path.join(this.cwd, 'openspec', 'changes', safeId);
36
+ }
37
+ /**
38
+ * ID 安全校验
39
+ */
40
+ ensureSafeId(id) {
41
+ const trimmed = id.trim();
42
+ if (!trimmed || trimmed.includes('..') || trimmed.includes('/') || trimmed.includes('\\')) {
43
+ throw new Error(`Invalid id: ${id}`);
44
+ }
45
+ return trimmed;
46
+ }
47
+ /**
48
+ * 确保目录存在
49
+ */
50
+ async ensureDir(dirPath) {
51
+ await fs.mkdir(dirPath, { recursive: true });
52
+ }
53
+ /**
54
+ * 评审 Proposal
55
+ */
56
+ async critiqueProposal(changeName) {
57
+ const changeDir = this.getChangeDir(changeName);
58
+ const proposalPath = path.join(changeDir, 'proposal.md');
59
+ try {
60
+ const content = await fs.readFile(proposalPath, 'utf-8');
61
+ return this.performCritique(changeName, 'proposal', content);
62
+ }
63
+ catch (error) {
64
+ throw new Error(`Failed to read proposal for ${changeName}: ${error instanceof Error ? error.message : 'Unknown error'}`);
65
+ }
66
+ }
67
+ /**
68
+ * 评审 Design
69
+ */
70
+ async critiqueDesign(changeName) {
71
+ const changeDir = this.getChangeDir(changeName);
72
+ const designPath = path.join(changeDir, 'design.md');
73
+ try {
74
+ const content = await fs.readFile(designPath, 'utf-8');
75
+ return this.performCritique(changeName, 'design', content);
76
+ }
77
+ catch (error) {
78
+ throw new Error(`Failed to read design for ${changeName}: ${error instanceof Error ? error.message : 'Unknown error'}`);
79
+ }
80
+ }
81
+ /**
82
+ * 评审所有文档(proposal + design)
83
+ */
84
+ async critiqueAll(changeName) {
85
+ const changeDir = this.getChangeDir(changeName);
86
+ let combinedContent = '';
87
+ // 读取 proposal
88
+ try {
89
+ const proposalPath = path.join(changeDir, 'proposal.md');
90
+ const proposal = await fs.readFile(proposalPath, 'utf-8');
91
+ combinedContent += '# PROPOSAL\n\n' + proposal + '\n\n';
92
+ }
93
+ catch {
94
+ // proposal 可能不存在,跳过
95
+ }
96
+ // 读取 design
97
+ try {
98
+ const designPath = path.join(changeDir, 'design.md');
99
+ const design = await fs.readFile(designPath, 'utf-8');
100
+ combinedContent += '# DESIGN\n\n' + design;
101
+ }
102
+ catch {
103
+ // design 可能不存在,跳过
104
+ }
105
+ if (!combinedContent.trim()) {
106
+ throw new Error(`No proposal or design found for ${changeName}`);
107
+ }
108
+ return this.performCritique(changeName, 'all', combinedContent);
109
+ }
110
+ /**
111
+ * 执行评审
112
+ */
113
+ performCritique(changeName, documentType, content) {
114
+ const sections = this.parseSections(content);
115
+ const critiques = [];
116
+ // 应用所有规则
117
+ for (const rule of this.rules) {
118
+ const match = rule.check(content, sections);
119
+ if (match?.matched) {
120
+ critiques.push({
121
+ id: randomUUID().substring(0, 8),
122
+ category: rule.category,
123
+ severity: rule.severity,
124
+ title: rule.title,
125
+ description: match.details || rule.description,
126
+ location: match.section ? { section: match.section } : undefined,
127
+ suggestion: match.suggestion,
128
+ });
129
+ }
130
+ }
131
+ // 计算统计
132
+ const summary = {
133
+ total: critiques.length,
134
+ critical: critiques.filter(c => c.severity === 'critical').length,
135
+ warning: critiques.filter(c => c.severity === 'warning').length,
136
+ info: critiques.filter(c => c.severity === 'info').length,
137
+ byCategory: {
138
+ completeness: critiques.filter(c => c.category === 'completeness').length,
139
+ feasibility: critiques.filter(c => c.category === 'feasibility').length,
140
+ security: critiques.filter(c => c.category === 'security').length,
141
+ edge_case: critiques.filter(c => c.category === 'edge_case').length,
142
+ clarity: critiques.filter(c => c.category === 'clarity').length,
143
+ },
144
+ };
145
+ // 计算总分 (10 - penalties)
146
+ const penalties = summary.critical * 2 + summary.warning * 1 + summary.info * 0.2;
147
+ const overallScore = Math.max(1, Math.min(10, 10 - penalties));
148
+ // 生成建议
149
+ const suggestions = this.generateSuggestions(critiques);
150
+ const result = {
151
+ changeName,
152
+ documentType,
153
+ overallScore: Math.round(overallScore * 10) / 10,
154
+ critiques,
155
+ suggestions,
156
+ summary,
157
+ createdAt: new Date().toISOString(),
158
+ };
159
+ // 异步保存结果
160
+ this.saveCritiqueResult(result).catch(() => {
161
+ // 忽略保存错误
162
+ });
163
+ return result;
164
+ }
165
+ /**
166
+ * 解析文档章节
167
+ */
168
+ parseSections(content) {
169
+ const sections = new Map();
170
+ const lines = content.split('\n');
171
+ let currentSection = 'preamble';
172
+ let sectionContent = [];
173
+ for (const line of lines) {
174
+ const headerMatch = line.match(/^(#{1,3})\s+(.+)$/);
175
+ if (headerMatch) {
176
+ // 保存上一个章节
177
+ if (sectionContent.length > 0) {
178
+ sections.set(currentSection.toLowerCase(), sectionContent.join('\n'));
179
+ }
180
+ currentSection = headerMatch[2];
181
+ sectionContent = [];
182
+ }
183
+ else {
184
+ sectionContent.push(line);
185
+ }
186
+ }
187
+ // 保存最后一个章节
188
+ if (sectionContent.length > 0) {
189
+ sections.set(currentSection.toLowerCase(), sectionContent.join('\n'));
190
+ }
191
+ return sections;
192
+ }
193
+ /**
194
+ * 生成综合建议
195
+ */
196
+ generateSuggestions(critiques) {
197
+ const suggestions = [];
198
+ // 按类别生成建议
199
+ const byCategory = new Map();
200
+ for (const c of critiques) {
201
+ if (!byCategory.has(c.category)) {
202
+ byCategory.set(c.category, []);
203
+ }
204
+ byCategory.get(c.category).push(c);
205
+ }
206
+ if ((byCategory.get('completeness')?.length || 0) > 0) {
207
+ suggestions.push('补充缺失的文档章节,确保问题描述、解决方案和影响范围完整');
208
+ }
209
+ if ((byCategory.get('security')?.length || 0) > 0) {
210
+ suggestions.push('审查安全相关设计,确保认证、授权和数据验证机制到位');
211
+ }
212
+ if ((byCategory.get('edge_case')?.length || 0) > 0) {
213
+ suggestions.push('增加边界条件和错误处理的说明');
214
+ }
215
+ if ((byCategory.get('clarity')?.length || 0) > 0) {
216
+ suggestions.push('改进文档清晰度,统一术语使用');
217
+ }
218
+ return suggestions;
219
+ }
220
+ /**
221
+ * 保存评审结果
222
+ */
223
+ async saveCritiqueResult(result) {
224
+ const critiquesDir = this.getCritiquesDir();
225
+ await this.ensureDir(critiquesDir);
226
+ const filePath = path.join(critiquesDir, `${result.changeName}_${result.documentType}_${Date.now()}.json`);
227
+ await fs.writeFile(filePath, JSON.stringify(result, null, 2), 'utf-8');
228
+ }
229
+ /**
230
+ * 获取评审历史
231
+ */
232
+ async getCritiqueHistory(changeName) {
233
+ const critiquesDir = this.getCritiquesDir();
234
+ const safeId = this.ensureSafeId(changeName);
235
+ try {
236
+ const files = await fs.readdir(critiquesDir);
237
+ const matchingFiles = files.filter(f => f.startsWith(safeId + '_') && f.endsWith('.json'));
238
+ const results = [];
239
+ for (const file of matchingFiles) {
240
+ try {
241
+ const content = await fs.readFile(path.join(critiquesDir, file), 'utf-8');
242
+ results.push(JSON.parse(content));
243
+ }
244
+ catch {
245
+ // 跳过无效文件
246
+ }
247
+ }
248
+ // 按时间排序
249
+ return results.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
250
+ }
251
+ catch {
252
+ return [];
253
+ }
254
+ }
255
+ /**
256
+ * 获取最新评审结果
257
+ */
258
+ async getLatestCritique(changeName) {
259
+ const history = await this.getCritiqueHistory(changeName);
260
+ return history[0] || null;
261
+ }
262
+ /**
263
+ * 初始化评审规则
264
+ */
265
+ initializeRules() {
266
+ return [
267
+ // --- 完整性检查 ---
268
+ {
269
+ id: 'missing-problem',
270
+ category: 'completeness',
271
+ severity: 'critical',
272
+ title: '缺少问题描述',
273
+ description: '文档应包含清晰的问题描述章节',
274
+ check: (content, sections) => {
275
+ const hasProb = content.toLowerCase().includes('problem') ||
276
+ content.toLowerCase().includes('issue') ||
277
+ content.toLowerCase().includes('背景') ||
278
+ content.toLowerCase().includes('问题') ||
279
+ sections.has('problem') ||
280
+ sections.has('background');
281
+ return { matched: !hasProb, suggestion: '添加 "Problem" 或 "背景" 章节描述要解决的问题' };
282
+ },
283
+ },
284
+ {
285
+ id: 'missing-solution',
286
+ category: 'completeness',
287
+ severity: 'critical',
288
+ title: '缺少解决方案',
289
+ description: '文档应包含解决方案描述',
290
+ check: (content, sections) => {
291
+ const hasSol = content.toLowerCase().includes('solution') ||
292
+ content.toLowerCase().includes('approach') ||
293
+ content.toLowerCase().includes('解决方案') ||
294
+ content.toLowerCase().includes('方案') ||
295
+ sections.has('solution') ||
296
+ sections.has('approach') ||
297
+ sections.has('design');
298
+ return { matched: !hasSol, suggestion: '添加 "Solution" 或 "解决方案" 章节' };
299
+ },
300
+ },
301
+ {
302
+ id: 'missing-impact',
303
+ category: 'completeness',
304
+ severity: 'warning',
305
+ title: '缺少影响范围',
306
+ description: '文档应描述变更的影响范围',
307
+ check: (content) => {
308
+ const hasImpact = content.toLowerCase().includes('impact') ||
309
+ content.toLowerCase().includes('scope') ||
310
+ content.toLowerCase().includes('影响') ||
311
+ content.toLowerCase().includes('范围');
312
+ return { matched: !hasImpact, suggestion: '添加 "Impact" 或 "影响范围" 说明' };
313
+ },
314
+ },
315
+ // --- 技术可行性 ---
316
+ {
317
+ id: 'no-code-reference',
318
+ category: 'feasibility',
319
+ severity: 'info',
320
+ title: '缺少代码引用',
321
+ description: '设计文档应引用相关代码文件',
322
+ check: (content) => {
323
+ const hasCodeRef = /`[A-Za-z_][\w/.-]+\.(ts|js|go|py|java|tsx|jsx)`/.test(content) ||
324
+ content.includes('file://') ||
325
+ /\b(src|lib|pkg|internal)\//.test(content);
326
+ return { matched: !hasCodeRef, suggestion: '添加相关代码文件的引用以便实现' };
327
+ },
328
+ },
329
+ {
330
+ id: 'todo-placeholder',
331
+ category: 'feasibility',
332
+ severity: 'warning',
333
+ title: '存在 TODO 占位符',
334
+ description: '文档中存在未完成的 TODO 标记',
335
+ check: (content) => {
336
+ const todoMatch = content.match(/\bTODO\b|\bFIXME\b|\bTBD\b|\bXXX\b/gi);
337
+ if (todoMatch && todoMatch.length > 0) {
338
+ return {
339
+ matched: true,
340
+ details: `发现 ${todoMatch.length} 处 TODO/TBD 标记`,
341
+ suggestion: '完成所有 TODO 项后再提交审批'
342
+ };
343
+ }
344
+ return { matched: false };
345
+ },
346
+ },
347
+ // --- 安全考量 ---
348
+ {
349
+ id: 'auth-not-mentioned',
350
+ category: 'security',
351
+ severity: 'warning',
352
+ title: '未提及认证授权',
353
+ description: 'API 或用户相关变更应说明认证授权策略',
354
+ check: (content) => {
355
+ const isApi = content.toLowerCase().includes('api') ||
356
+ content.toLowerCase().includes('endpoint') ||
357
+ content.toLowerCase().includes('接口');
358
+ const hasAuth = content.toLowerCase().includes('auth') ||
359
+ content.toLowerCase().includes('permission') ||
360
+ content.toLowerCase().includes('认证') ||
361
+ content.toLowerCase().includes('授权') ||
362
+ content.toLowerCase().includes('权限');
363
+ return {
364
+ matched: isApi && !hasAuth,
365
+ suggestion: '添加认证和授权相关说明'
366
+ };
367
+ },
368
+ },
369
+ {
370
+ id: 'sensitive-data',
371
+ category: 'security',
372
+ severity: 'critical',
373
+ title: '涉及敏感数据',
374
+ description: '涉及敏感数据的变更需要特别说明安全措施',
375
+ check: (content, sections) => {
376
+ // 如果已有安全章节,则认为已考虑(或至少不直接判为 critical)
377
+ if (sections.has('security') || sections.has('safety') || sections.has('安全')) {
378
+ return { matched: false };
379
+ }
380
+ const sensitivePatterns = [
381
+ /password/i, /secret/i, /token/i, /密码/, /密钥/,
382
+ /credit.?card/i, /信用卡/, /身份证/, /ssn/i,
383
+ /private.?key/i, /私钥/
384
+ ];
385
+ for (const pattern of sensitivePatterns) {
386
+ if (pattern.test(content)) {
387
+ return {
388
+ matched: true,
389
+ details: '文档涉及敏感数据且未发现安全章节,请确保有适当的安全措施',
390
+ suggestion: '添加 "Security" 或 "安全" 章节说明数据保护措施'
391
+ };
392
+ }
393
+ }
394
+ return { matched: false };
395
+ },
396
+ },
397
+ // --- 边界条件 ---
398
+ {
399
+ id: 'no-error-handling',
400
+ category: 'edge_case',
401
+ severity: 'warning',
402
+ title: '未提及错误处理',
403
+ description: '应说明异常和错误情况的处理方式',
404
+ check: (content) => {
405
+ const hasError = content.toLowerCase().includes('error') ||
406
+ content.toLowerCase().includes('exception') ||
407
+ content.toLowerCase().includes('failure') ||
408
+ content.toLowerCase().includes('错误') ||
409
+ content.toLowerCase().includes('异常') ||
410
+ content.toLowerCase().includes('失败');
411
+ return { matched: !hasError, suggestion: '添加错误处理和异常情况的说明' };
412
+ },
413
+ },
414
+ {
415
+ id: 'no-concurrency',
416
+ category: 'edge_case',
417
+ severity: 'info',
418
+ title: '未考虑并发场景',
419
+ description: '涉及数据更新的变更应考虑并发情况',
420
+ check: (content) => {
421
+ const isDataChange = content.toLowerCase().includes('update') ||
422
+ content.toLowerCase().includes('write') ||
423
+ content.toLowerCase().includes('修改') ||
424
+ content.toLowerCase().includes('更新');
425
+ const hasConcurrency = content.toLowerCase().includes('concurren') ||
426
+ content.toLowerCase().includes('race') ||
427
+ content.toLowerCase().includes('lock') ||
428
+ content.toLowerCase().includes('并发') ||
429
+ content.toLowerCase().includes('锁');
430
+ return {
431
+ matched: isDataChange && !hasConcurrency,
432
+ suggestion: '考虑添加并发控制相关说明'
433
+ };
434
+ },
435
+ },
436
+ // --- 清晰度 ---
437
+ {
438
+ id: 'too-short',
439
+ category: 'clarity',
440
+ severity: 'warning',
441
+ title: '文档过短',
442
+ description: '文档内容可能不够详细',
443
+ check: (content) => {
444
+ const wordCount = content.split(/\s+/).length;
445
+ return {
446
+ matched: wordCount < 100,
447
+ details: `文档仅有约 ${wordCount} 个词`,
448
+ suggestion: '补充更多细节描述'
449
+ };
450
+ },
451
+ },
452
+ {
453
+ id: 'undefined-terms',
454
+ category: 'clarity',
455
+ severity: 'info',
456
+ title: '使用了未定义的术语',
457
+ description: '文档中使用了可能需要解释的专业术语',
458
+ check: (content) => {
459
+ // 检查是否使用了缩写但没有解释
460
+ const acronyms = content.match(/\b[A-Z]{2,6}\b/g);
461
+ const explainedPattern = /([A-Z]{2,6})\s*[((]|[((]\s*([A-Z]{2,6})\s*[))]/g;
462
+ if (acronyms && acronyms.length > 3) {
463
+ const unexplained = acronyms.filter(a => !explainedPattern.test(content.slice(content.indexOf(a) - 50, content.indexOf(a) + 50)));
464
+ if (unexplained.length > 2) {
465
+ return {
466
+ matched: true,
467
+ details: `发现多个可能需要解释的缩写: ${[...new Set(unexplained)].slice(0, 5).join(', ')}`,
468
+ suggestion: '确保首次使用时解释专业术语和缩写'
469
+ };
470
+ }
471
+ }
472
+ return { matched: false };
473
+ },
474
+ },
475
+ ];
476
+ }
477
+ }
478
+ //# sourceMappingURL=spec-critic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-critic.js","sourceRoot":"","sources":["../../src/core/spec-critic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Spec Critic Tests
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=spec-critic.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-critic.test.d.ts","sourceRoot":"","sources":["../../src/core/spec-critic.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}