@winspan/claude-forge 0.3.9 → 0.4.1

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 (72) hide show
  1. package/README.md +12 -7
  2. package/dist/autopilot/quality-gate.d.ts +11 -1
  3. package/dist/autopilot/quality-gate.d.ts.map +1 -1
  4. package/dist/autopilot/quality-gate.js +84 -27
  5. package/dist/autopilot/quality-gate.js.map +1 -1
  6. package/dist/daemon/engine-registry.d.ts.map +1 -1
  7. package/dist/daemon/engine-registry.js +3 -0
  8. package/dist/daemon/engine-registry.js.map +1 -1
  9. package/dist/daemon/handler-context.d.ts +4 -2
  10. package/dist/daemon/handler-context.d.ts.map +1 -1
  11. package/dist/daemon/handlers/session-cleanup.d.ts +6 -0
  12. package/dist/daemon/handlers/session-cleanup.d.ts.map +1 -1
  13. package/dist/daemon/handlers/session-cleanup.js +107 -0
  14. package/dist/daemon/handlers/session-cleanup.js.map +1 -1
  15. package/dist/daemon/handlers/stop-handler.d.ts.map +1 -1
  16. package/dist/daemon/handlers/stop-handler.js +15 -0
  17. package/dist/daemon/handlers/stop-handler.js.map +1 -1
  18. package/dist/daemon/handlers/user-prompt-handler.d.ts +5 -0
  19. package/dist/daemon/handlers/user-prompt-handler.d.ts.map +1 -1
  20. package/dist/daemon/handlers/user-prompt-handler.js +86 -0
  21. package/dist/daemon/handlers/user-prompt-handler.js.map +1 -1
  22. package/dist/pipeline/artifact-generator.d.ts +35 -0
  23. package/dist/pipeline/artifact-generator.d.ts.map +1 -0
  24. package/dist/pipeline/artifact-generator.js +287 -0
  25. package/dist/pipeline/artifact-generator.js.map +1 -0
  26. package/dist/pipeline/index.d.ts +57 -0
  27. package/dist/pipeline/index.d.ts.map +1 -1
  28. package/dist/pipeline/index.js +146 -0
  29. package/dist/pipeline/index.js.map +1 -1
  30. package/dist/pipeline/phase-manager.d.ts +14 -1
  31. package/dist/pipeline/phase-manager.d.ts.map +1 -1
  32. package/dist/pipeline/phase-manager.js +61 -10
  33. package/dist/pipeline/phase-manager.js.map +1 -1
  34. package/dist/pipeline/store.d.ts +5 -0
  35. package/dist/pipeline/store.d.ts.map +1 -1
  36. package/dist/pipeline/store.js +8 -0
  37. package/dist/pipeline/store.js.map +1 -1
  38. package/dist/retrospective/failure-detector.d.ts +17 -0
  39. package/dist/retrospective/failure-detector.d.ts.map +1 -0
  40. package/dist/retrospective/failure-detector.js +67 -0
  41. package/dist/retrospective/failure-detector.js.map +1 -0
  42. package/dist/retrospective/index.d.ts +69 -0
  43. package/dist/retrospective/index.d.ts.map +1 -0
  44. package/dist/retrospective/index.js +189 -0
  45. package/dist/retrospective/index.js.map +1 -0
  46. package/dist/retrospective/metrics-extractor.d.ts +27 -0
  47. package/dist/retrospective/metrics-extractor.d.ts.map +1 -0
  48. package/dist/retrospective/metrics-extractor.js +71 -0
  49. package/dist/retrospective/metrics-extractor.js.map +1 -0
  50. package/dist/retrospective/pattern-learner.d.ts +29 -0
  51. package/dist/retrospective/pattern-learner.d.ts.map +1 -0
  52. package/dist/retrospective/pattern-learner.js +159 -0
  53. package/dist/retrospective/pattern-learner.js.map +1 -0
  54. package/dist/retrospective/report-writer.d.ts +33 -0
  55. package/dist/retrospective/report-writer.d.ts.map +1 -0
  56. package/dist/retrospective/report-writer.js +173 -0
  57. package/dist/retrospective/report-writer.js.map +1 -0
  58. package/dist/retrospective/strategy-advisor.d.ts +21 -0
  59. package/dist/retrospective/strategy-advisor.d.ts.map +1 -0
  60. package/dist/retrospective/strategy-advisor.js +63 -0
  61. package/dist/retrospective/strategy-advisor.js.map +1 -0
  62. package/dist/retrospective/types.d.ts +107 -0
  63. package/dist/retrospective/types.d.ts.map +1 -0
  64. package/dist/retrospective/types.js +7 -0
  65. package/dist/retrospective/types.js.map +1 -0
  66. package/dist/storage/index.d.ts +12 -0
  67. package/dist/storage/index.d.ts.map +1 -1
  68. package/dist/storage/sqlite.d.ts +57 -0
  69. package/dist/storage/sqlite.d.ts.map +1 -1
  70. package/dist/storage/sqlite.js +126 -1
  71. package/dist/storage/sqlite.js.map +1 -1
  72. package/package.json +1 -1
@@ -0,0 +1,173 @@
1
+ /**
2
+ * 复盘报告写入器
3
+ *
4
+ * 生成 .claude-forge/retrospective.md,自动轮换归档
5
+ */
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ const MAX_ENTRIES = 20;
9
+ const ARCHIVE_FILENAME = 'retrospective-archive.md';
10
+ export class RetrospectiveReportWriter {
11
+ projectPath;
12
+ reportPath;
13
+ archivePath;
14
+ constructor(projectPath) {
15
+ this.projectPath = projectPath;
16
+ const forgeDir = path.join(projectPath, '.claude-forge');
17
+ this.reportPath = path.join(forgeDir, 'retrospective.md');
18
+ this.archivePath = path.join(forgeDir, ARCHIVE_FILENAME);
19
+ // 确保目录存在
20
+ if (!fs.existsSync(forgeDir)) {
21
+ fs.mkdirSync(forgeDir, { recursive: true });
22
+ }
23
+ }
24
+ /**
25
+ * 写入任务复盘条目
26
+ */
27
+ write(session) {
28
+ const entry = this.formatEntry(session);
29
+ // 读取现有内容
30
+ let content = '';
31
+ if (fs.existsSync(this.reportPath)) {
32
+ content = fs.readFileSync(this.reportPath, 'utf-8');
33
+ }
34
+ else {
35
+ content = '# 任务复盘日志\n\n';
36
+ }
37
+ // 插入新条目(在标题后的第一个分隔符之后)
38
+ const lines = content.split('\n');
39
+ const headerEndIndex = lines.findIndex((line, i) => i > 0 && line.startsWith('---'));
40
+ if (headerEndIndex > 0) {
41
+ // 在分隔符后插入(即第一条记录之前)
42
+ lines.splice(headerEndIndex + 1, 0, entry);
43
+ }
44
+ else {
45
+ // 若无分隔符,在标题后插入
46
+ const titleIndex = lines.findIndex(l => l.startsWith('# '));
47
+ if (titleIndex >= 0) {
48
+ lines.splice(titleIndex + 2, 0, entry); // 标题后空一行
49
+ }
50
+ else {
51
+ lines.push(entry);
52
+ }
53
+ }
54
+ content = lines.join('\n');
55
+ // 检查条目数量,超过阈值则归档
56
+ const entryCount = (content.match(/^## \d{4}-\d{2}-\d{2}/gm) || []).length;
57
+ if (entryCount > MAX_ENTRIES) {
58
+ this.rotateArchive(content);
59
+ }
60
+ else {
61
+ fs.writeFileSync(this.reportPath, content, 'utf-8');
62
+ }
63
+ }
64
+ /**
65
+ * 格式化单条复盘记录
66
+ */
67
+ formatEntry(session) {
68
+ const { metrics, failure_signals } = session;
69
+ const date = session.started_at.split('T')[0];
70
+ const title = this.extractTitle(session.requirement);
71
+ const outcomeLabel = this.getOutcomeLabel(session.outcome);
72
+ const durationMin = Math.round(metrics.duration_ms / 60000);
73
+ let entry = `---\n## ${date} | ${title} | 类型: ${session.task_type} | 结果: ${outcomeLabel}\n\n`;
74
+ // 执行指标
75
+ entry += '**执行指标**\n';
76
+ entry += `- 总轮次: ${metrics.total_rounds} | 工具调用: ${metrics.total_tool_calls} | 修复尝试: ${metrics.fix_attempt_count} | 耗时: ${durationMin}min\n`;
77
+ entry += `- 质量门禁: 通过 ${metrics.quality_pass_count} 次 / 失败 ${metrics.quality_fail_count} 次\n`;
78
+ // 失败信号
79
+ if (failure_signals.length > 0) {
80
+ const dissatisfied = failure_signals.filter(s => s.signal_type === 'dissatisfied').length;
81
+ const iteration = failure_signals.filter(s => s.signal_type === 'iteration').length;
82
+ entry += `- 失败信号: ${failure_signals.length} 次`;
83
+ if (dissatisfied > 0)
84
+ entry += `(不满意 ${dissatisfied} 次`;
85
+ if (iteration > 0)
86
+ entry += `${dissatisfied > 0 ? ',' : '('}迭代 ${iteration} 次`;
87
+ entry += ')\n';
88
+ // 详细信号列表
89
+ const firstSignal = failure_signals[0];
90
+ if (firstSignal) {
91
+ entry += ` - 首次信号: "${firstSignal.matched_pattern}"`;
92
+ if (firstSignal.context_phase)
93
+ entry += ` 发生在 ${firstSignal.context_phase} 阶段`;
94
+ entry += '\n';
95
+ }
96
+ }
97
+ else {
98
+ entry += '- 失败信号: 无\n';
99
+ }
100
+ // 阶段分布
101
+ if (metrics.phase_distribution.length > 0) {
102
+ entry += '\n**阶段分布**\n';
103
+ for (const phase of metrics.phase_distribution) {
104
+ entry += `- ${phase.phase}: ${phase.tool_call_count} 次工具调用`;
105
+ if (phase.fix_attempt_count > 0)
106
+ entry += `(修复 ${phase.fix_attempt_count} 次)`;
107
+ entry += '\n';
108
+ }
109
+ }
110
+ entry += '\n';
111
+ return entry;
112
+ }
113
+ /**
114
+ * 归档旧条目
115
+ */
116
+ rotateArchive(content) {
117
+ const lines = content.split('\n');
118
+ const entries = [];
119
+ let currentEntry = [];
120
+ for (const line of lines) {
121
+ if (line.startsWith('## ') && currentEntry.length > 0) {
122
+ entries.push(currentEntry.join('\n'));
123
+ currentEntry = [line];
124
+ }
125
+ else {
126
+ currentEntry.push(line);
127
+ }
128
+ }
129
+ if (currentEntry.length > 0) {
130
+ entries.push(currentEntry.join('\n'));
131
+ }
132
+ // 保留最新的 MAX_ENTRIES 条
133
+ const keep = entries.slice(0, MAX_ENTRIES);
134
+ const archive = entries.slice(MAX_ENTRIES);
135
+ // 写入主文件
136
+ const newContent = '# 任务复盘日志\n\n' + keep.join('\n---\n');
137
+ fs.writeFileSync(this.reportPath, newContent, 'utf-8');
138
+ // 追加到归档文件
139
+ if (archive.length > 0) {
140
+ let archiveContent = '';
141
+ if (fs.existsSync(this.archivePath)) {
142
+ archiveContent = fs.readFileSync(this.archivePath, 'utf-8');
143
+ }
144
+ else {
145
+ archiveContent = '# 任务复盘归档\n\n';
146
+ }
147
+ archiveContent += archive.join('\n---\n') + '\n';
148
+ fs.writeFileSync(this.archivePath, archiveContent, 'utf-8');
149
+ }
150
+ }
151
+ /**
152
+ * 从需求文本提取简短标题
153
+ */
154
+ extractTitle(requirement) {
155
+ // 取第一句话或前 30 个字符
156
+ const firstLine = requirement.split('\n')[0];
157
+ const title = firstLine.length > 30 ? firstLine.slice(0, 30) + '...' : firstLine;
158
+ return title.trim();
159
+ }
160
+ /**
161
+ * 获取结果标签
162
+ */
163
+ getOutcomeLabel(outcome) {
164
+ const labels = {
165
+ success: '成功',
166
+ partial: '部分完成',
167
+ abandoned: '中止',
168
+ in_progress: '进行中',
169
+ };
170
+ return labels[outcome] || outcome;
171
+ }
172
+ }
173
+ //# sourceMappingURL=report-writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-writer.js","sourceRoot":"","sources":["../../src/retrospective/report-writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * StrategyAdvisor — 预防策略推荐器
3
+ *
4
+ * 读取 task_patterns 表中已学习的失败模式,
5
+ * 在 UserPromptHandler 检测到同类任务时注入预防建议。
6
+ */
7
+ import type { StorageEngine } from '../storage/index.js';
8
+ export declare class StrategyAdvisor {
9
+ private storage;
10
+ constructor(storage: StorageEngine);
11
+ /**
12
+ * 根据用户需求文本,查找相关历史失败模式并返回预防建议。
13
+ * 无相关模式时返回 null。
14
+ */
15
+ getRelevantStrategies(requirement: string): string | null;
16
+ /**
17
+ * 加载指定任务类型的高置信度模式,按置信度降序排列。
18
+ */
19
+ private loadPatterns;
20
+ }
21
+ //# sourceMappingURL=strategy-advisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy-advisor.d.ts","sourceRoot":"","sources":["../../src/retrospective/strategy-advisor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAUzD,qBAAa,eAAe;IACd,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAE1C;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAmBzD;;OAEG;IACH,OAAO,CAAC,YAAY;CAqBrB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * StrategyAdvisor — 预防策略推荐器
3
+ *
4
+ * 读取 task_patterns 表中已学习的失败模式,
5
+ * 在 UserPromptHandler 检测到同类任务时注入预防建议。
6
+ */
7
+ import { classifyTaskType } from './metrics-extractor.js';
8
+ import { logger } from '../utils/logger.js';
9
+ /** 注入建议的最低置信度阈值 */
10
+ const MIN_INJECT_CONFIDENCE = 0.5;
11
+ /** 每次最多注入的建议条数 */
12
+ const MAX_STRATEGIES = 2;
13
+ export class StrategyAdvisor {
14
+ storage;
15
+ constructor(storage) {
16
+ this.storage = storage;
17
+ }
18
+ /**
19
+ * 根据用户需求文本,查找相关历史失败模式并返回预防建议。
20
+ * 无相关模式时返回 null。
21
+ */
22
+ getRelevantStrategies(requirement) {
23
+ const taskType = classifyTaskType(requirement);
24
+ const patterns = this.loadPatterns(taskType);
25
+ if (patterns.length === 0)
26
+ return null;
27
+ const lines = [
28
+ `[Forge 历史经验] 检测到 ${taskType} 类型任务,以下是历史失败模式和预防建议:`,
29
+ ];
30
+ for (const p of patterns) {
31
+ lines.push(`- ⚠️ 常见问题:${p.failure_pattern}`);
32
+ lines.push(` 建议:${p.prevention_strategy}`);
33
+ }
34
+ logger.info(`[Forge:策略建议] 注入 ${patterns.length} 条 ${taskType} 类型预防建议`);
35
+ return lines.join('\n');
36
+ }
37
+ /**
38
+ * 加载指定任务类型的高置信度模式,按置信度降序排列。
39
+ */
40
+ loadPatterns(taskType) {
41
+ try {
42
+ const raw = this.storage.getTaskPatterns(taskType);
43
+ return raw
44
+ .map(r => ({
45
+ id: String(r['id'] ?? ''),
46
+ task_type: String(r['task_type'] ?? ''),
47
+ failure_pattern: String(r['failure_pattern'] ?? ''),
48
+ prevention_strategy: String(r['prevention_strategy'] ?? ''),
49
+ confidence_score: Number(r['confidence_score'] ?? 0),
50
+ sample_count: Number(r['sample_count'] ?? 0),
51
+ last_updated: String(r['last_updated'] ?? ''),
52
+ }))
53
+ .filter(p => p.confidence_score >= MIN_INJECT_CONFIDENCE)
54
+ .sort((a, b) => b.confidence_score - a.confidence_score)
55
+ .slice(0, MAX_STRATEGIES);
56
+ }
57
+ catch (err) {
58
+ logger.warn(`[Forge:策略建议] 加载模式失败:${err}`);
59
+ return [];
60
+ }
61
+ }
62
+ }
63
+ //# sourceMappingURL=strategy-advisor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy-advisor.js","sourceRoot":"","sources":["../../src/retrospective/strategy-advisor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,mBAAmB;AACnB,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,kBAAkB;AAClB,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,OAAsB;QAAtB,YAAO,GAAP,OAAO,CAAe;IAAG,CAAC;IAE9C;;;OAGG;IACH,qBAAqB,CAAC,WAAmB;QACvC,MAAM,QAAQ,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEvC,MAAM,KAAK,GAAa;YACtB,oBAAoB,QAAQ,uBAAuB;SACpD,CAAC;QAEF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,eAAe,EAAE,CAAC,CAAC;YAC7C,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,mBAAmB,EAAE,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,mBAAmB,QAAQ,CAAC,MAAM,MAAM,QAAQ,SAAS,CAAC,CAAC;QACvE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,QAAkB;QACrC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;YACnD,OAAO,GAAG;iBACP,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACT,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACzB,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAa;gBACnD,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;gBACnD,mBAAmB,EAAE,MAAM,CAAC,CAAC,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;gBAC3D,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;gBACpD,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBAC5C,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;aAC9C,CAAC,CAAC;iBACF,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB,IAAI,qBAAqB,CAAC;iBACxD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,gBAAgB,CAAC;iBACvD,KAAK,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAC;YAC1C,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * 任务复盘分析器 - 类型定义
3
+ *
4
+ * 定义任务执行质量度量、失败信号检测、模式学习的核心数据结构
5
+ */
6
+ /**
7
+ * 任务类型分类
8
+ */
9
+ export type TaskType = 'refactor' | 'feature' | 'bugfix' | 'review' | 'design' | 'other';
10
+ /**
11
+ * 任务执行结果
12
+ */
13
+ export type TaskOutcome = 'success' | 'partial' | 'abandoned' | 'in_progress';
14
+ /**
15
+ * 任务复杂度评估
16
+ */
17
+ export type TaskComplexity = 'simple' | 'moderate' | 'complex';
18
+ /**
19
+ * 失败信号类型
20
+ */
21
+ export type SignalType = 'dissatisfied' | 'iteration';
22
+ /**
23
+ * 失败信号记录
24
+ */
25
+ export interface FailureSignal {
26
+ id: string;
27
+ session_id: string;
28
+ project_path: string;
29
+ task_session_id?: string;
30
+ signal_type: SignalType;
31
+ raw_prompt: string;
32
+ matched_pattern: string;
33
+ context_phase?: string;
34
+ is_iteration: 0 | 1;
35
+ preceding_tool_count: number;
36
+ timestamp: string;
37
+ }
38
+ /**
39
+ * 阶段执行快照
40
+ */
41
+ export interface PhaseSnapshot {
42
+ phase: string;
43
+ tool_call_count: number;
44
+ write_edit_count: number;
45
+ fix_attempt_count: number;
46
+ }
47
+ /**
48
+ * 任务质量指标
49
+ */
50
+ export interface TaskQualityMetrics {
51
+ total_rounds: number;
52
+ total_tool_calls: number;
53
+ write_edit_count: number;
54
+ fix_attempt_count: number;
55
+ quality_pass_count: number;
56
+ quality_fail_count: number;
57
+ phase_distribution: PhaseSnapshot[];
58
+ duration_ms: number;
59
+ completed: boolean;
60
+ }
61
+ /**
62
+ * 任务会话记录
63
+ */
64
+ export interface TaskSession {
65
+ id: string;
66
+ session_id: string;
67
+ project_path: string;
68
+ pipeline_id?: string;
69
+ requirement: string;
70
+ task_type: TaskType;
71
+ complexity: TaskComplexity;
72
+ outcome: TaskOutcome;
73
+ metrics: TaskQualityMetrics;
74
+ failure_signals: FailureSignal[];
75
+ started_at: string;
76
+ ended_at?: string;
77
+ }
78
+ /**
79
+ * 任务失败模式
80
+ */
81
+ export interface TaskPattern {
82
+ id: string;
83
+ task_type: TaskType;
84
+ failure_pattern: string;
85
+ prevention_strategy: string;
86
+ confidence_score: number;
87
+ sample_count: number;
88
+ last_updated: string;
89
+ }
90
+ /**
91
+ * 失败信号检测上下文
92
+ */
93
+ export interface FailureDetectionContext {
94
+ preceding_tool_count: number;
95
+ current_phase?: string;
96
+ timestamp: string;
97
+ }
98
+ /**
99
+ * 失败信号检测结果
100
+ */
101
+ export interface DetectedSignal {
102
+ signal_type: SignalType;
103
+ matched_text: string;
104
+ matched_pattern: string;
105
+ is_iteration: 0 | 1;
106
+ }
107
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/retrospective/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEzF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;AAE9E;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,WAAW,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,UAAU,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,aAAa,EAAE,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,QAAQ,CAAC;IACpB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,QAAQ,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,UAAU,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC;CACrB"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 任务复盘分析器 - 类型定义
3
+ *
4
+ * 定义任务执行质量度量、失败信号检测、模式学习的核心数据结构
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/retrospective/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -28,6 +28,18 @@ export interface StorageEngine {
28
28
  getStorageSize(): number;
29
29
  /** FTS5 全文检索:按关键词搜索相关历史事件,返回最近 limit 条 */
30
30
  searchByKeywords(keywords: string[], projectPath: string, limit?: number): ForgeEvent[];
31
+ insertTaskSession(data: Record<string, unknown>): void;
32
+ updateTaskSession(id: string, updates: Record<string, unknown>): void;
33
+ getTaskSession(id: string): Record<string, unknown> | null;
34
+ getTaskSessionsByType(taskType: string, limit?: number): Record<string, unknown>[];
35
+ insertFailureSignal(data: Record<string, unknown>): void;
36
+ getFailureSignals(query: {
37
+ session_id?: string;
38
+ project_path?: string;
39
+ limit?: number;
40
+ }): Record<string, unknown>[];
41
+ upsertTaskPattern(data: Record<string, unknown>): void;
42
+ getTaskPatterns(taskType?: string): Record<string, unknown>[];
31
43
  close(): void;
32
44
  }
33
45
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;IAC/C,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAAC;IACzC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE9C,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACpE,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,EAAE,CAAC;IAChD,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5G,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5E,cAAc,IAAI,MAAM,CAAC;IAEzB,0CAA0C;IAC1C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;IAExF,KAAK,IAAI,IAAI,CAAC;CACf"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,CAAC;IAC/C,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM,CAAC;IACzC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAE9C,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACpE,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,EAAE,CAAC;IAChD,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5G,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5E,cAAc,IAAI,MAAM,CAAC;IAEzB,0CAA0C;IAC1C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC;IAGxF,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACvD,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtE,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC3D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAEnF,mBAAmB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,iBAAiB,CAAC,KAAK,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAEpH,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACvD,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IAE9D,KAAK,IAAI,IAAI,CAAC;CACf"}
@@ -56,6 +56,63 @@ export declare class SQLiteStorage implements StorageEngine {
56
56
  /** FTS5 全文检索:按关键词搜索相关历史事件,返回最近 limit 条 */
57
57
  searchByKeywords(keywords: string[], projectPath: string, limit?: number): ForgeEvent[];
58
58
  close(): void;
59
+ insertTaskSession(data: {
60
+ id: string;
61
+ session_id: string;
62
+ project_path: string;
63
+ pipeline_id?: string;
64
+ requirement: string;
65
+ task_type: string;
66
+ complexity: string;
67
+ total_rounds: number;
68
+ total_tool_calls: number;
69
+ write_edit_count: number;
70
+ fix_attempt_count: number;
71
+ quality_fail_count: number;
72
+ quality_pass_count: number;
73
+ failure_signal_count: number;
74
+ phase_distribution?: Record<string, number>;
75
+ outcome: string;
76
+ duration_ms?: number;
77
+ started_at: string;
78
+ ended_at?: string;
79
+ }): void;
80
+ updateTaskSession(id: string, updates: Partial<{
81
+ outcome: string;
82
+ ended_at: string;
83
+ failure_signal_count: number;
84
+ total_rounds: number;
85
+ total_tool_calls: number;
86
+ }>): void;
87
+ getTaskSession(id: string): Record<string, unknown> | null;
88
+ getTaskSessionsByType(taskType: string, limit?: number): Record<string, unknown>[];
89
+ insertFailureSignal(data: {
90
+ id: string;
91
+ session_id: string;
92
+ project_path: string;
93
+ task_session_id?: string;
94
+ signal_type: string;
95
+ raw_prompt: string;
96
+ matched_pattern?: string;
97
+ context_phase?: string;
98
+ is_iteration: number;
99
+ preceding_tool_count: number;
100
+ timestamp: string;
101
+ }): void;
102
+ getFailureSignals(query: {
103
+ session_id?: string;
104
+ project_path?: string;
105
+ limit?: number;
106
+ }): Record<string, unknown>[];
107
+ upsertTaskPattern(data: {
108
+ id: string;
109
+ task_type: string;
110
+ failure_pattern: string;
111
+ prevention_strategy: string;
112
+ confidence_score: number;
113
+ sample_count: number;
114
+ }): void;
115
+ getTaskPatterns(taskType?: string): Record<string, unknown>[];
59
116
  /**
60
117
  * 获取底层数据库连接(供需要直接操作的模块使用,如 PipelineStore)
61
118
  * 注意:调用方需自行管理事务和错误处理
@@ -1 +1 @@
1
- {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAGtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,qBAAa,aAAc,YAAW,aAAa;IACjD,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,MAAM,CAAS;IAEvB,oCAAoC;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAQ9B;gBAES,MAAM,EAAE,MAAM;IAkB1B,8BAA8B;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAK;IAE3C,qCAAqC;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAkBhC;IAEF,OAAO,CAAC,aAAa;IAkCrB,OAAO,CAAC,UAAU;IA0DlB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAuDnC,OAAO,CAAC,aAAa;IAiCrB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE;IAgD9C,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,MAAM;IAqBxC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAmB7C,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;IAcnE,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,EAAE;IAwB/C,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAa3G,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE;IAW3E,cAAc,IAAI,MAAM;IAOxB;;;OAGG;IACH,oBAAoB,CAAC,aAAa,GAAE,MAAU,GAAG,MAAM;IAQvD;;OAEG;IACH,gBAAgB,CAAC,aAAa,GAAE,MAAW,GAAG,MAAM;IAQpD;;;;OAIG;IACH,cAAc,CAAC,SAAS,SAAO,GAAG;QAChC,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;KAClB;IA0BD,oBAAoB;IACpB,WAAW,IAAI,MAAM;IASrB,sEAAsE;IACtE,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI;IAsBrD,2BAA2B;IAC3B,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,gBAAgB,EAAE;IAuBzE,yCAAyC;IACzC,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAM1E,0CAA0C;IAC1C,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,UAAU,EAAE;IAgCnF,KAAK,IAAI,IAAI;IAIb;;;OAGG;IACH,WAAW,IAAI,QAAQ,CAAC,QAAQ;IAKhC,OAAO,CAAC,UAAU;IAiBlB,OAAO,CAAC,YAAY;CAWrB"}
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/storage/sqlite.ts"],"names":[],"mappings":"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"}
@@ -30,7 +30,7 @@ export class SQLiteStorage {
30
30
  this.runMigrations();
31
31
  }
32
32
  /** 当前 schema 版本号,每次新增迁移时递增 */
33
- static SCHEMA_VERSION = 2;
33
+ static SCHEMA_VERSION = 3;
34
34
  /** 增量迁移函数表:key 为目标版本号,value 为迁移函数 */
35
35
  static MIGRATIONS = {
36
36
  // v1: 基线版本(initSchema 已创建所有表),无需额外操作
@@ -50,6 +50,65 @@ export class SQLiteStorage {
50
50
  )
51
51
  `);
52
52
  },
53
+ // v3: 任务复盘分析器 — task_sessions, failure_signals, task_patterns
54
+ 3: (db) => {
55
+ db.exec(`
56
+ CREATE TABLE IF NOT EXISTS task_sessions (
57
+ id TEXT PRIMARY KEY,
58
+ session_id TEXT NOT NULL,
59
+ project_path TEXT NOT NULL,
60
+ pipeline_id TEXT,
61
+ requirement TEXT NOT NULL,
62
+ task_type TEXT NOT NULL DEFAULT 'other',
63
+ complexity TEXT NOT NULL DEFAULT 'moderate',
64
+ total_rounds INTEGER NOT NULL DEFAULT 0,
65
+ total_tool_calls INTEGER NOT NULL DEFAULT 0,
66
+ write_edit_count INTEGER NOT NULL DEFAULT 0,
67
+ fix_attempt_count INTEGER NOT NULL DEFAULT 0,
68
+ quality_fail_count INTEGER NOT NULL DEFAULT 0,
69
+ quality_pass_count INTEGER NOT NULL DEFAULT 0,
70
+ failure_signal_count INTEGER NOT NULL DEFAULT 0,
71
+ phase_distribution TEXT,
72
+ outcome TEXT NOT NULL DEFAULT 'in_progress',
73
+ duration_ms INTEGER,
74
+ started_at TEXT NOT NULL,
75
+ ended_at TEXT,
76
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
77
+ );
78
+ CREATE INDEX IF NOT EXISTS idx_ts_session ON task_sessions(session_id);
79
+ CREATE INDEX IF NOT EXISTS idx_ts_project ON task_sessions(project_path);
80
+ CREATE INDEX IF NOT EXISTS idx_ts_task_type ON task_sessions(task_type);
81
+
82
+ CREATE TABLE IF NOT EXISTS failure_signals (
83
+ id TEXT PRIMARY KEY,
84
+ session_id TEXT NOT NULL,
85
+ project_path TEXT NOT NULL,
86
+ task_session_id TEXT,
87
+ signal_type TEXT NOT NULL,
88
+ raw_prompt TEXT NOT NULL,
89
+ matched_pattern TEXT,
90
+ context_phase TEXT,
91
+ is_iteration INTEGER NOT NULL DEFAULT 0,
92
+ preceding_tool_count INTEGER NOT NULL DEFAULT 0,
93
+ timestamp TEXT NOT NULL,
94
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
95
+ );
96
+ CREATE INDEX IF NOT EXISTS idx_fs_session ON failure_signals(session_id);
97
+ CREATE INDEX IF NOT EXISTS idx_fs_project ON failure_signals(project_path);
98
+
99
+ CREATE TABLE IF NOT EXISTS task_patterns (
100
+ id TEXT PRIMARY KEY,
101
+ task_type TEXT NOT NULL,
102
+ failure_pattern TEXT NOT NULL,
103
+ prevention_strategy TEXT NOT NULL,
104
+ confidence_score REAL NOT NULL DEFAULT 0.0,
105
+ sample_count INTEGER NOT NULL DEFAULT 0,
106
+ last_updated TEXT NOT NULL DEFAULT (datetime('now')),
107
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
108
+ );
109
+ CREATE INDEX IF NOT EXISTS idx_tp_task_type ON task_patterns(task_type);
110
+ `);
111
+ },
53
112
  };
54
113
  runMigrations() {
55
114
  // 确保 schema_version 表存在
@@ -446,6 +505,72 @@ export class SQLiteStorage {
446
505
  close() {
447
506
  this.db.close();
448
507
  }
508
+ // ── 任务复盘分析器查询方法 ──────────────────────────────────────────────────
509
+ insertTaskSession(data) {
510
+ this.db.prepare(`
511
+ INSERT INTO task_sessions (
512
+ id, session_id, project_path, pipeline_id, requirement, task_type, complexity,
513
+ total_rounds, total_tool_calls, write_edit_count, fix_attempt_count,
514
+ quality_fail_count, quality_pass_count, failure_signal_count,
515
+ phase_distribution, outcome, duration_ms, started_at, ended_at
516
+ ) VALUES (
517
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
518
+ )
519
+ `).run(data.id, data.session_id, data.project_path, data.pipeline_id ?? null, data.requirement, data.task_type, data.complexity, data.total_rounds, data.total_tool_calls, data.write_edit_count, data.fix_attempt_count, data.quality_fail_count, data.quality_pass_count, data.failure_signal_count, data.phase_distribution ? JSON.stringify(data.phase_distribution) : null, data.outcome, data.duration_ms ?? null, data.started_at, data.ended_at ?? null);
520
+ }
521
+ updateTaskSession(id, updates) {
522
+ const fields = Object.keys(updates).map(k => `${k} = ?`).join(', ');
523
+ if (!fields)
524
+ return;
525
+ this.db.prepare(`UPDATE task_sessions SET ${fields} WHERE id = ?`)
526
+ .run(...Object.values(updates), id);
527
+ }
528
+ getTaskSession(id) {
529
+ return this.db.prepare('SELECT * FROM task_sessions WHERE id = ?').get(id) ?? null;
530
+ }
531
+ getTaskSessionsByType(taskType, limit = 20) {
532
+ return this.db.prepare('SELECT * FROM task_sessions WHERE task_type = ? ORDER BY started_at DESC LIMIT ?').all(taskType, limit);
533
+ }
534
+ insertFailureSignal(data) {
535
+ this.db.prepare(`
536
+ INSERT INTO failure_signals (
537
+ id, session_id, project_path, task_session_id, signal_type, raw_prompt,
538
+ matched_pattern, context_phase, is_iteration, preceding_tool_count, timestamp
539
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
540
+ `).run(data.id, data.session_id, data.project_path, data.task_session_id ?? null, data.signal_type, data.raw_prompt, data.matched_pattern ?? null, data.context_phase ?? null, data.is_iteration, data.preceding_tool_count, data.timestamp);
541
+ }
542
+ getFailureSignals(query) {
543
+ const conditions = ['1=1'];
544
+ const params = [];
545
+ if (query.session_id) {
546
+ conditions.push('session_id = ?');
547
+ params.push(query.session_id);
548
+ }
549
+ if (query.project_path) {
550
+ conditions.push('project_path = ?');
551
+ params.push(query.project_path);
552
+ }
553
+ params.push(query.limit ?? 100);
554
+ return this.db.prepare(`SELECT * FROM failure_signals WHERE ${conditions.join(' AND ')} ORDER BY timestamp ASC LIMIT ?`).all(...params);
555
+ }
556
+ upsertTaskPattern(data) {
557
+ this.db.prepare(`
558
+ INSERT INTO task_patterns (id, task_type, failure_pattern, prevention_strategy, confidence_score, sample_count)
559
+ VALUES (?, ?, ?, ?, ?, ?)
560
+ ON CONFLICT(id) DO UPDATE SET
561
+ failure_pattern = excluded.failure_pattern,
562
+ prevention_strategy = excluded.prevention_strategy,
563
+ confidence_score = excluded.confidence_score,
564
+ sample_count = excluded.sample_count,
565
+ last_updated = datetime('now')
566
+ `).run(data.id, data.task_type, data.failure_pattern, data.prevention_strategy, data.confidence_score, data.sample_count);
567
+ }
568
+ getTaskPatterns(taskType) {
569
+ if (taskType) {
570
+ return this.db.prepare('SELECT * FROM task_patterns WHERE task_type = ? ORDER BY confidence_score DESC').all(taskType);
571
+ }
572
+ return this.db.prepare('SELECT * FROM task_patterns ORDER BY confidence_score DESC').all();
573
+ }
449
574
  /**
450
575
  * 获取底层数据库连接(供需要直接操作的模块使用,如 PipelineStore)
451
576
  * 注意:调用方需自行管理事务和错误处理