@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,189 @@
1
+ /**
2
+ * RetrospectiveEngine — 任务复盘分析器主类
3
+ *
4
+ * 组装 failure-detector、metrics-extractor、report-writer,
5
+ * 对外暴露统一接口供 StopHandler 和 UserPromptHandler 调用
6
+ */
7
+ import { randomUUID } from 'node:crypto';
8
+ import { detectFailureSignal } from './failure-detector.js';
9
+ import { extractMetrics, classifyTaskType, assessComplexity } from './metrics-extractor.js';
10
+ import { RetrospectiveReportWriter } from './report-writer.js';
11
+ import { PatternLearner } from './pattern-learner.js';
12
+ import { StrategyAdvisor } from './strategy-advisor.js';
13
+ import { logger } from '../utils/logger.js';
14
+ export class RetrospectiveEngine {
15
+ storage;
16
+ patternLearner = null;
17
+ strategyAdvisor;
18
+ constructor(storage, api) {
19
+ this.storage = storage;
20
+ this.strategyAdvisor = new StrategyAdvisor(storage);
21
+ if (api) {
22
+ this.patternLearner = new PatternLearner(storage, api);
23
+ }
24
+ }
25
+ /**
26
+ * 检测用户输入中的失败信号
27
+ * 返回检测到的信号(已写入 DB),或 null
28
+ */
29
+ detectFailureSignal(userPrompt, context) {
30
+ const detected = detectFailureSignal(userPrompt, context);
31
+ if (!detected)
32
+ return null;
33
+ return {
34
+ session_id: '', // 由调用方填充
35
+ project_path: '',
36
+ signal_type: detected.signal_type,
37
+ raw_prompt: userPrompt,
38
+ matched_pattern: detected.matched_pattern,
39
+ context_phase: context.current_phase,
40
+ is_iteration: detected.is_iteration,
41
+ preceding_tool_count: context.preceding_tool_count,
42
+ timestamp: context.timestamp,
43
+ };
44
+ }
45
+ /**
46
+ * 异步写入失败信号到 SQLite
47
+ */
48
+ async recordFailureSignal(signal) {
49
+ try {
50
+ this.storage.insertFailureSignal({
51
+ id: randomUUID(),
52
+ session_id: signal.session_id,
53
+ project_path: signal.project_path,
54
+ task_session_id: signal.task_session_id,
55
+ signal_type: signal.signal_type,
56
+ raw_prompt: signal.raw_prompt.slice(0, 500), // 截断防止过长
57
+ matched_pattern: signal.matched_pattern,
58
+ context_phase: signal.context_phase,
59
+ is_iteration: signal.is_iteration,
60
+ preceding_tool_count: signal.preceding_tool_count,
61
+ timestamp: signal.timestamp,
62
+ });
63
+ logger.debug(`[Forge:任务复盘] 记录失败信号:${signal.signal_type} — "${signal.matched_pattern}"`);
64
+ }
65
+ catch (err) {
66
+ logger.warn(`[Forge:任务复盘] 写入失败信号失败:${err}`);
67
+ }
68
+ }
69
+ /**
70
+ * 执行完整复盘分析(在 Stop 事件后调用)
71
+ *
72
+ * @param event Stop 事件
73
+ * @param events 本次会话所有事件
74
+ * @param qualityPassCount 质量门禁通过次数(reset 前捕获)
75
+ * @param qualityFailCount 质量门禁失败次数
76
+ * @param phases 阶段快照(从 PhaseManager 获取)
77
+ * @param requirement 任务需求描述(从 Pipeline 获取,可为空)
78
+ * @param pipelineId Pipeline ID(可选)
79
+ */
80
+ async analyzeSession(event, events, qualityPassCount, qualityFailCount, phases, requirement, pipelineId) {
81
+ const { session_id, project_path } = event;
82
+ try {
83
+ // 查询本 session 失败信号
84
+ const rawSignals = this.storage.getFailureSignals({ session_id, project_path });
85
+ const failureSignals = rawSignals.map(r => ({
86
+ id: String(r['id'] ?? ''),
87
+ session_id: String(r['session_id'] ?? ''),
88
+ project_path: String(r['project_path'] ?? ''),
89
+ task_session_id: r['task_session_id'] ? String(r['task_session_id']) : undefined,
90
+ signal_type: String(r['signal_type'] ?? ''),
91
+ raw_prompt: String(r['raw_prompt'] ?? ''),
92
+ matched_pattern: String(r['matched_pattern'] ?? ''),
93
+ context_phase: r['context_phase'] ? String(r['context_phase']) : undefined,
94
+ is_iteration: (Number(r['is_iteration'] ?? 0)),
95
+ preceding_tool_count: Number(r['preceding_tool_count'] ?? 0),
96
+ timestamp: String(r['timestamp'] ?? ''),
97
+ }));
98
+ // 提取质量指标
99
+ const metrics = extractMetrics(events, qualityPassCount, qualityFailCount, phases, true // Stop 事件触发 = 正常完成
100
+ );
101
+ // 分类任务类型和复杂度
102
+ const taskType = classifyTaskType(requirement);
103
+ const complexity = assessComplexity(metrics);
104
+ // 判断任务结果
105
+ const outcome = this.determineOutcome(metrics, failureSignals);
106
+ // 构建 TaskSession
107
+ const taskSessionId = randomUUID();
108
+ const taskSession = {
109
+ id: taskSessionId,
110
+ session_id,
111
+ project_path,
112
+ pipeline_id: pipelineId,
113
+ requirement: requirement || '(未记录需求)',
114
+ task_type: taskType,
115
+ complexity,
116
+ outcome,
117
+ metrics,
118
+ failure_signals: failureSignals,
119
+ started_at: events[0]?.timestamp ?? event.timestamp ?? new Date().toISOString(),
120
+ ended_at: event.timestamp ?? new Date().toISOString(),
121
+ };
122
+ // 写入 SQLite
123
+ this.storage.insertTaskSession({
124
+ id: taskSessionId,
125
+ session_id,
126
+ project_path,
127
+ pipeline_id: pipelineId,
128
+ requirement: taskSession.requirement,
129
+ task_type: taskType,
130
+ complexity,
131
+ total_rounds: metrics.total_rounds,
132
+ total_tool_calls: metrics.total_tool_calls,
133
+ write_edit_count: metrics.write_edit_count,
134
+ fix_attempt_count: metrics.fix_attempt_count,
135
+ quality_fail_count: qualityFailCount,
136
+ quality_pass_count: qualityPassCount,
137
+ failure_signal_count: failureSignals.length,
138
+ phase_distribution: Object.fromEntries(phases.map(p => [p.phase, p.tool_call_count])),
139
+ outcome,
140
+ duration_ms: metrics.duration_ms,
141
+ started_at: taskSession.started_at,
142
+ ended_at: taskSession.ended_at,
143
+ });
144
+ // 生成 retrospective.md
145
+ const writer = new RetrospectiveReportWriter(project_path);
146
+ writer.write(taskSession);
147
+ logger.info(`[Forge:任务复盘] 分析完成 — 类型: ${taskType}, 结果: ${outcome}, ` +
148
+ `工具调用: ${metrics.total_tool_calls}, 失败信号: ${failureSignals.length}`);
149
+ }
150
+ catch (err) {
151
+ logger.warn(`[Forge:任务复盘] 分析失败:${err}`);
152
+ }
153
+ }
154
+ /**
155
+ * 根据指标和失败信号判断任务结果
156
+ */
157
+ determineOutcome(metrics, failureSignals) {
158
+ const dissatisfiedCount = failureSignals.filter(s => s.signal_type === 'dissatisfied').length;
159
+ // 有明确不满意信号且质量门禁失败次数多 → 部分完成
160
+ if (dissatisfiedCount > 0 && metrics.quality_fail_count > metrics.quality_pass_count) {
161
+ return 'partial';
162
+ }
163
+ // 有明确不满意信号但最终通过 → 成功(经过修正)
164
+ if (dissatisfiedCount > 0) {
165
+ return 'success';
166
+ }
167
+ // 无失败信号 → 成功
168
+ return 'success';
169
+ }
170
+ /**
171
+ * 执行模式学习(每 10 次 Stop 触发)
172
+ * 返回提炼的模式总数
173
+ */
174
+ async learnPatterns() {
175
+ if (!this.patternLearner) {
176
+ logger.info('[Forge:模式学习] 跳过:未配置 AIProvider');
177
+ return 0;
178
+ }
179
+ return this.patternLearner.learnAll();
180
+ }
181
+ /**
182
+ * 获取任务类型相关的预防策略建议
183
+ * 供 UserPromptHandler 在检测到同类任务时注入
184
+ */
185
+ getStrategies(requirement) {
186
+ return this.strategyAdvisor.getRelevantStrategies(requirement);
187
+ }
188
+ }
189
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/retrospective/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 质量指标提取器 — 纯函数,无副作用
3
+ *
4
+ * 从事件流中提取客观的任务执行质量指标
5
+ * 不依赖 AI 自评,基于行为数据计算
6
+ */
7
+ import type { ForgeEvent } from '../types/index.js';
8
+ import type { TaskQualityMetrics, PhaseSnapshot } from './types.js';
9
+ /**
10
+ * 从事件流提取任务质量指标
11
+ *
12
+ * @param events 本次会话的所有事件(按时间排序)
13
+ * @param qualityPassCount 质量门禁通过次数(从 QualityGateEngine 在 reset 前捕获)
14
+ * @param qualityFailCount 质量门禁失败次数
15
+ * @param phases 阶段快照(从 PhaseManager 获取)
16
+ * @param completed 会话是否正常完成
17
+ */
18
+ export declare function extractMetrics(events: ForgeEvent[], qualityPassCount: number, qualityFailCount: number, phases: PhaseSnapshot[], completed: boolean): TaskQualityMetrics;
19
+ /**
20
+ * 根据需求文本推断任务类型
21
+ */
22
+ export declare function classifyTaskType(requirement: string): import('./types.js').TaskType;
23
+ /**
24
+ * 根据指标评估任务复杂度
25
+ */
26
+ export declare function assessComplexity(metrics: TaskQualityMetrics): import('./types.js').TaskComplexity;
27
+ //# sourceMappingURL=metrics-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-extractor.d.ts","sourceRoot":"","sources":["../../src/retrospective/metrics-extractor.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,UAAU,EAAE,EACpB,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,aAAa,EAAE,EACvB,SAAS,EAAE,OAAO,GACjB,kBAAkB,CA+BpB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,YAAY,EAAE,QAAQ,CAUnF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,YAAY,EAAE,cAAc,CAMjG"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * 质量指标提取器 — 纯函数,无副作用
3
+ *
4
+ * 从事件流中提取客观的任务执行质量指标
5
+ * 不依赖 AI 自评,基于行为数据计算
6
+ */
7
+ /**
8
+ * 从事件流提取任务质量指标
9
+ *
10
+ * @param events 本次会话的所有事件(按时间排序)
11
+ * @param qualityPassCount 质量门禁通过次数(从 QualityGateEngine 在 reset 前捕获)
12
+ * @param qualityFailCount 质量门禁失败次数
13
+ * @param phases 阶段快照(从 PhaseManager 获取)
14
+ * @param completed 会话是否正常完成
15
+ */
16
+ export function extractMetrics(events, qualityPassCount, qualityFailCount, phases, completed) {
17
+ const userPromptEvents = events.filter(e => e.hook_type === 'UserPromptSubmit');
18
+ const toolUseEvents = events.filter(e => e.hook_type === 'PostToolUse');
19
+ const writeEditEvents = toolUseEvents.filter(e => e.tool_name === 'Write' || e.tool_name === 'Edit');
20
+ // 修复尝试:从阶段快照汇总
21
+ const fixAttemptCount = phases.reduce((sum, p) => sum + p.fix_attempt_count, 0);
22
+ // 持续时长:最后事件时间 - 第一个事件时间
23
+ let durationMs = 0;
24
+ if (events.length >= 2) {
25
+ const first = new Date(events[0].timestamp).getTime();
26
+ const last = new Date(events[events.length - 1].timestamp).getTime();
27
+ if (!isNaN(first) && !isNaN(last) && last > first) {
28
+ durationMs = last - first;
29
+ }
30
+ }
31
+ return {
32
+ total_rounds: userPromptEvents.length,
33
+ total_tool_calls: toolUseEvents.length,
34
+ write_edit_count: writeEditEvents.length,
35
+ fix_attempt_count: fixAttemptCount,
36
+ quality_pass_count: qualityPassCount,
37
+ quality_fail_count: qualityFailCount,
38
+ phase_distribution: phases,
39
+ duration_ms: durationMs,
40
+ completed,
41
+ };
42
+ }
43
+ /**
44
+ * 根据需求文本推断任务类型
45
+ */
46
+ export function classifyTaskType(requirement) {
47
+ const lower = requirement.toLowerCase();
48
+ if (/重构|refactor|优化|cleanup|clean up/.test(lower))
49
+ return 'refactor';
50
+ if (/修复|fix|bug|错误|异常|报错/.test(lower))
51
+ return 'bugfix';
52
+ if (/审查|review|检查|check|评审/.test(lower))
53
+ return 'review';
54
+ if (/设计|design|架构|architecture|方案/.test(lower))
55
+ return 'design';
56
+ if (/新增|添加|实现|feature|功能|开发/.test(lower))
57
+ return 'feature';
58
+ return 'other';
59
+ }
60
+ /**
61
+ * 根据指标评估任务复杂度
62
+ */
63
+ export function assessComplexity(metrics) {
64
+ const { total_tool_calls, write_edit_count, total_rounds } = metrics;
65
+ if (total_tool_calls > 50 || write_edit_count > 15 || total_rounds > 10)
66
+ return 'complex';
67
+ if (total_tool_calls > 15 || write_edit_count > 5 || total_rounds > 4)
68
+ return 'moderate';
69
+ return 'simple';
70
+ }
71
+ //# sourceMappingURL=metrics-extractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics-extractor.js","sourceRoot":"","sources":["../../src/retrospective/metrics-extractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * PatternLearner — AI 驱动的失败模式提炼器
3
+ *
4
+ * 从 task_sessions + failure_signals 历史数据中提炼同类任务的共同失败模式,
5
+ * 并将结论写入 task_patterns 表供 StrategyAdvisor 使用。
6
+ *
7
+ * 触发条件:每 10 次 Stop,或同类型任务新增 >= 5 条时
8
+ */
9
+ import type { AIProvider } from '../ai-provider/types.js';
10
+ import type { StorageEngine } from '../storage/index.js';
11
+ import type { TaskType } from './types.js';
12
+ export declare class PatternLearner {
13
+ private storage;
14
+ private api;
15
+ constructor(storage: StorageEngine, api: AIProvider);
16
+ /**
17
+ * 对指定任务类型执行模式提炼。
18
+ * 若历史不足 MIN_SAMPLES 条则跳过。
19
+ */
20
+ learnPatterns(taskType: TaskType): Promise<number>;
21
+ /**
22
+ * 对所有任务类型批量执行模式学习(每 10 次 Stop 触发)。
23
+ * 返回总写入模式数。
24
+ */
25
+ learnAll(): Promise<number>;
26
+ private buildPrompt;
27
+ private parsePatterns;
28
+ }
29
+ //# sourceMappingURL=pattern-learner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-learner.d.ts","sourceRoot":"","sources":["../../src/retrospective/pattern-learner.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,YAAY,CAAC;AAYxD,qBAAa,cAAc;IAEvB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,GAAG;gBADH,OAAO,EAAE,aAAa,EACtB,GAAG,EAAE,UAAU;IAGzB;;;OAGG;IACG,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAkExD;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAcjC,OAAO,CAAC,WAAW;IAsCnB,OAAO,CAAC,aAAa;CAmCtB"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * PatternLearner — AI 驱动的失败模式提炼器
3
+ *
4
+ * 从 task_sessions + failure_signals 历史数据中提炼同类任务的共同失败模式,
5
+ * 并将结论写入 task_patterns 表供 StrategyAdvisor 使用。
6
+ *
7
+ * 触发条件:每 10 次 Stop,或同类型任务新增 >= 5 条时
8
+ */
9
+ import { randomUUID } from 'node:crypto';
10
+ import { logger } from '../utils/logger.js';
11
+ /** 最少需要多少条任务历史才触发模式提炼 */
12
+ const MIN_SAMPLES = 5;
13
+ /** 每种任务类型最多分析的历史条数 */
14
+ const MAX_HISTORY_PER_TYPE = 30;
15
+ /** 模式置信度阈值:低于此值视为噪音,不写入 */
16
+ const MIN_CONFIDENCE = 0.4;
17
+ const ALL_TASK_TYPES = ['refactor', 'feature', 'bugfix', 'review', 'design', 'other'];
18
+ export class PatternLearner {
19
+ storage;
20
+ api;
21
+ constructor(storage, api) {
22
+ this.storage = storage;
23
+ this.api = api;
24
+ }
25
+ /**
26
+ * 对指定任务类型执行模式提炼。
27
+ * 若历史不足 MIN_SAMPLES 条则跳过。
28
+ */
29
+ async learnPatterns(taskType) {
30
+ const sessions = this.storage.getTaskSessionsByType(taskType, MAX_HISTORY_PER_TYPE);
31
+ if (sessions.length < MIN_SAMPLES) {
32
+ logger.info(`[Forge:模式学习] ${taskType} 历史不足 ${MIN_SAMPLES} 条(当前 ${sessions.length}),跳过`);
33
+ return 0;
34
+ }
35
+ logger.info(`[Forge:模式学习] 开始提炼 ${taskType}(${sessions.length} 条历史)`);
36
+ // 收集所有失败信号
37
+ const failureSummaries = [];
38
+ for (const session of sessions) {
39
+ const sessionId = String(session['session_id'] ?? '');
40
+ const projectPath = String(session['project_path'] ?? '');
41
+ const signals = this.storage.getFailureSignals({ session_id: sessionId, project_path: projectPath });
42
+ if (signals.length > 0) {
43
+ const signalTexts = signals.map(s => ` - [${String(s['signal_type'] ?? '')}] "${String(s['raw_prompt'] ?? '')}" (阶段=${String(s['context_phase'] ?? '未知')}, 前置工具调用=${Number(s['preceding_tool_count'] ?? 0)})`).join('\n');
44
+ failureSummaries.push(`会话 ${sessionId.slice(0, 8)}... | 结果=${String(session['outcome'] ?? '')} | 轮次=${Number(session['total_rounds'] ?? 0)} | 工具调用=${Number(session['total_tool_calls'] ?? 0)}\n` +
45
+ `失败信号:\n${signalTexts}`);
46
+ }
47
+ }
48
+ if (failureSummaries.length === 0) {
49
+ logger.info(`[Forge:模式学习] ${taskType} 无失败信号记录,跳过模式提炼`);
50
+ return 0;
51
+ }
52
+ // 构建 AI prompt
53
+ const prompt = this.buildPrompt(taskType, sessions, failureSummaries);
54
+ let response;
55
+ try {
56
+ response = await this.api.complete(prompt, '模式学习', { timeoutMs: 60_000, maxTokens: 1000 });
57
+ }
58
+ catch (err) {
59
+ logger.warn(`[Forge:模式学习] AI 调用失败:${err}`);
60
+ return 0;
61
+ }
62
+ // 解析 AI 返回的模式列表
63
+ const patterns = this.parsePatterns(response, taskType);
64
+ if (patterns.length === 0) {
65
+ logger.info(`[Forge:模式学习] AI 未提炼出有效模式`);
66
+ return 0;
67
+ }
68
+ // 写入 task_patterns 表
69
+ for (const pattern of patterns) {
70
+ this.storage.upsertTaskPattern({
71
+ id: randomUUID(),
72
+ task_type: pattern.task_type,
73
+ failure_pattern: pattern.failure_pattern,
74
+ prevention_strategy: pattern.prevention_strategy,
75
+ confidence_score: pattern.confidence_score,
76
+ sample_count: sessions.length,
77
+ last_updated: new Date().toISOString(),
78
+ });
79
+ }
80
+ logger.info(`[Forge:模式学习] ${taskType} 提炼完成,写入 ${patterns.length} 个模式`);
81
+ return patterns.length;
82
+ }
83
+ /**
84
+ * 对所有任务类型批量执行模式学习(每 10 次 Stop 触发)。
85
+ * 返回总写入模式数。
86
+ */
87
+ async learnAll() {
88
+ let total = 0;
89
+ for (const taskType of ALL_TASK_TYPES) {
90
+ try {
91
+ total += await this.learnPatterns(taskType);
92
+ }
93
+ catch (err) {
94
+ logger.warn(`[Forge:模式学习] ${taskType} 提炼失败:${err}`);
95
+ }
96
+ }
97
+ return total;
98
+ }
99
+ // ── 私有方法 ────────────────────────────────────────────────────────────────
100
+ buildPrompt(taskType, sessions, failureSummaries) {
101
+ const totalSessions = sessions.length;
102
+ const failedCount = sessions.filter(s => {
103
+ const outcome = s['outcome'];
104
+ const failureCount = typeof s['failure_signal_count'] === 'number' ? s['failure_signal_count'] : 0;
105
+ return outcome === 'partial' || failureCount > 0;
106
+ }).length;
107
+ return `你是一位软件工程质量分析师。以下是 ${totalSessions} 条"${taskType}"类型任务的执行历史,其中 ${failedCount} 条含失败信号。
108
+
109
+ 请分析这些失败信号,提炼出 1-3 个最常见的失败模式,以及对应的预防策略。
110
+
111
+ ## 失败信号记录
112
+
113
+ ${failureSummaries.join('\n\n---\n\n')}
114
+
115
+ ## 输出格式
116
+
117
+ 请严格按以下 JSON 数组格式输出,不要包含任何其他文本:
118
+
119
+ [
120
+ {
121
+ "failure_pattern": "简短描述失败模式(20字以内)",
122
+ "prevention_strategy": "具体的预防策略(50字以内)",
123
+ "confidence": 0.7
124
+ }
125
+ ]
126
+
127
+ 要求:
128
+ - confidence 范围 0.0-1.0,表示这个模式在样本中的普遍性
129
+ - confidence < ${MIN_CONFIDENCE} 的模式请直接省略不输出
130
+ - 只输出 JSON 数组,不要 markdown 代码块,不要解释文字`;
131
+ }
132
+ parsePatterns(response, taskType) {
133
+ try {
134
+ // 提取 JSON 数组(兼容 AI 可能包裹了 markdown 代码块的情况)
135
+ const jsonMatch = response.match(/\[[\s\S]*\]/);
136
+ if (!jsonMatch)
137
+ return [];
138
+ const parsed = JSON.parse(jsonMatch[0]);
139
+ if (!Array.isArray(parsed))
140
+ return [];
141
+ return parsed
142
+ .filter(p => typeof p.failure_pattern === 'string' && p.failure_pattern.trim() &&
143
+ typeof p.prevention_strategy === 'string' && p.prevention_strategy.trim() &&
144
+ typeof p.confidence === 'number' && p.confidence >= MIN_CONFIDENCE)
145
+ .slice(0, 3) // 最多保留 3 个
146
+ .map(p => ({
147
+ task_type: taskType,
148
+ failure_pattern: p.failure_pattern.trim(),
149
+ prevention_strategy: p.prevention_strategy.trim(),
150
+ confidence_score: Math.min(1.0, Math.max(0.0, p.confidence)),
151
+ }));
152
+ }
153
+ catch (err) {
154
+ logger.warn(`[Forge:模式学习] 解析 AI 响应失败:${err}`);
155
+ return [];
156
+ }
157
+ }
158
+ }
159
+ //# sourceMappingURL=pattern-learner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-learner.js","sourceRoot":"","sources":["../../src/retrospective/pattern-learner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 复盘报告写入器
3
+ *
4
+ * 生成 .claude-forge/retrospective.md,自动轮换归档
5
+ */
6
+ import type { TaskSession } from './types.js';
7
+ export declare class RetrospectiveReportWriter {
8
+ private projectPath;
9
+ private reportPath;
10
+ private archivePath;
11
+ constructor(projectPath: string);
12
+ /**
13
+ * 写入任务复盘条目
14
+ */
15
+ write(session: TaskSession): void;
16
+ /**
17
+ * 格式化单条复盘记录
18
+ */
19
+ private formatEntry;
20
+ /**
21
+ * 归档旧条目
22
+ */
23
+ private rotateArchive;
24
+ /**
25
+ * 从需求文本提取简短标题
26
+ */
27
+ private extractTitle;
28
+ /**
29
+ * 获取结果标签
30
+ */
31
+ private getOutcomeLabel;
32
+ }
33
+ //# sourceMappingURL=report-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-writer.d.ts","sourceRoot":"","sources":["../../src/retrospective/report-writer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAK7D,qBAAa,yBAAyB;IAIxB,OAAO,CAAC,WAAW;IAH/B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;gBAER,WAAW,EAAE,MAAM;IAWvC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;IAuCjC;;OAEG;IACH,OAAO,CAAC,WAAW;IAgDnB;;OAEG;IACH,OAAO,CAAC,aAAa;IAsCrB;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,eAAe;CASxB"}