@winspan/claude-forge 1.52.0 → 1.53.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.
- package/README.md +4 -4
- package/dist/config/defaults.js +1 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.js +2 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/convention/convention-manager.d.ts.map +1 -1
- package/dist/convention/convention-manager.js +4 -1
- package/dist/convention/convention-manager.js.map +1 -1
- package/dist/daemon/handlers/stages/09-pipeline-active.d.ts.map +1 -1
- package/dist/daemon/handlers/stages/09-pipeline-active.js +18 -12
- package/dist/daemon/handlers/stages/09-pipeline-active.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +0 -8
- package/dist/daemon/index.js.map +1 -1
- package/dist/pipeline/index.d.ts +2 -6
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +86 -64
- package/dist/pipeline/index.js.map +1 -1
- package/dist/storage/sqlite.d.ts.map +1 -1
- package/dist/storage/sqlite.js +9 -1
- package/dist/storage/sqlite.js.map +1 -1
- package/dist/web/routes/node-types.d.ts.map +1 -1
- package/dist/web/routes/node-types.js +20 -1
- package/dist/web/routes/node-types.js.map +1 -1
- package/dist/web-static/assets/index-Bv6kBfyq.css +1 -0
- package/dist/web-static/assets/index-IOh9Pj5N.js +76 -0
- package/dist/web-static/index.html +2 -2
- package/package.json +1 -1
- package/dist/pipeline/store.legacy.d.ts +0 -48
- package/dist/pipeline/store.legacy.d.ts.map +0 -1
- package/dist/pipeline/store.legacy.js +0 -163
- package/dist/pipeline/store.legacy.js.map +0 -1
- package/dist/scripts/auto-migrate.d.ts +0 -9
- package/dist/scripts/auto-migrate.d.ts.map +0 -1
- package/dist/scripts/auto-migrate.js +0 -161
- package/dist/scripts/auto-migrate.js.map +0 -1
- package/dist/scripts/migrate-to-event-sourcing.d.ts +0 -16
- package/dist/scripts/migrate-to-event-sourcing.d.ts.map +0 -1
- package/dist/scripts/migrate-to-event-sourcing.js +0 -179
- package/dist/scripts/migrate-to-event-sourcing.js.map +0 -1
- package/dist/web-static/assets/index-B-S02jXH.css +0 -1
- package/dist/web-static/assets/index-BG4bejVq.js +0 -76
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>Claude Forge - 管理后台</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-IOh9Pj5N.js"></script>
|
|
8
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Bv6kBfyq.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import type { Pipeline, PipelineTask, PipelinePhase } from './types.js';
|
|
2
|
-
import type { SQLiteStorage } from '../storage/sqlite.js';
|
|
3
|
-
export declare class PipelineStore {
|
|
4
|
-
private db;
|
|
5
|
-
constructor(storage: SQLiteStorage);
|
|
6
|
-
createPipeline(requirement: string, projectPath: string, sessionId: string, techStack?: string, complexity?: 'simple' | 'moderate' | 'complex', taskType?: 'bugfix' | 'feature' | 'refactor' | 'performance' | 'documentation' | 'other', plannedPhases?: PipelinePhase[], phaseArtifacts?: Record<string, string[]>, reasoning?: string): Pipeline;
|
|
7
|
-
addTasks(pipelineId: string, tasks: Array<Omit<PipelineTask, 'id'>>): PipelineTask[];
|
|
8
|
-
getActivePipeline(projectPath: string): Pipeline | null;
|
|
9
|
-
getTasks(pipelineId: string): PipelineTask[];
|
|
10
|
-
updatePhase(pipelineId: string, phase: PipelinePhase): void;
|
|
11
|
-
/** 按 ID 关闭单个 Pipeline */
|
|
12
|
-
closeById(pipelineId: string): void;
|
|
13
|
-
/**
|
|
14
|
-
* 关闭超过 ttlMs 未更新的所有活跃 Pipeline,返回被关闭的数量。
|
|
15
|
-
* 默认 2 小时(7200000ms)。
|
|
16
|
-
*/
|
|
17
|
-
closeExpired(ttlMs?: number): number;
|
|
18
|
-
/** 列出所有非 done 的 Pipeline(跨项目,供 CLI 展示) */
|
|
19
|
-
listActive(): Array<{
|
|
20
|
-
id: string;
|
|
21
|
-
requirement: string;
|
|
22
|
-
projectPath: string;
|
|
23
|
-
phase: PipelinePhase;
|
|
24
|
-
updatedAt: string;
|
|
25
|
-
}>;
|
|
26
|
-
/**
|
|
27
|
-
* 将指定 Pipeline 中所有 in_progress 任务重置为 pending。
|
|
28
|
-
* 用于 ESC 中断后恢复:in_progress 表示"开始但未完成",中断后需重新检测。
|
|
29
|
-
*/
|
|
30
|
-
resetInProgressTasks(pipelineId: string): number;
|
|
31
|
-
getPhaseProgress(pipelineId: string, phase: PipelinePhase): {
|
|
32
|
-
total: number;
|
|
33
|
-
completed: number;
|
|
34
|
-
};
|
|
35
|
-
/**
|
|
36
|
-
* 更新任务状态
|
|
37
|
-
*/
|
|
38
|
-
updateTaskStatus(taskId: string, status: 'pending' | 'in_progress' | 'completed' | 'failed', output?: string): boolean;
|
|
39
|
-
/**
|
|
40
|
-
* 获取单个任务
|
|
41
|
-
*/
|
|
42
|
-
getTask(taskId: string): PipelineTask | null;
|
|
43
|
-
/**
|
|
44
|
-
* 根据任务 ID 获取 Pipeline ID
|
|
45
|
-
*/
|
|
46
|
-
getPipelineIdByTask(taskId: string): string | null;
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=store.legacy.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.legacy.d.ts","sourceRoot":"","sources":["../../src/pipeline/store.legacy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAI1D,qBAAa,aAAa;IACxB,OAAO,CAAC,EAAE,CAAoB;gBAElB,OAAO,EAAE,aAAa;IAKlC,cAAc,CACZ,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,EAC9C,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,eAAe,GAAG,OAAO,EACxF,aAAa,CAAC,EAAE,aAAa,EAAE,EAC/B,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACzC,SAAS,CAAC,EAAE,MAAM,GACjB,QAAQ;IAgCX,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,GAAG,YAAY,EAAE;IAwBpF,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI;IA2BvD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE;IAiB5C,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI;IAM3D,yBAAyB;IACzB,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAMnC;;;OAGG;IACH,YAAY,CAAC,KAAK,SAAqB,GAAG,MAAM;IAQhD,0CAA0C;IAC1C,UAAU,IAAI,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IActH;;;OAGG;IACH,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM;IAOhD,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAWhG;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO;IActH;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAgB5C;;OAEG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;CAInD"}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'crypto';
|
|
2
|
-
import { logger } from '../utils/logger.js';
|
|
3
|
-
import { PIPELINE } from '../constants.js';
|
|
4
|
-
export class PipelineStore {
|
|
5
|
-
db;
|
|
6
|
-
constructor(storage) {
|
|
7
|
-
this.db = storage.getDatabase();
|
|
8
|
-
// Schema 已在 SQLiteStorage 初始化时通过 schema.sql 创建,无需重复初始化
|
|
9
|
-
}
|
|
10
|
-
createPipeline(requirement, projectPath, sessionId, techStack, complexity, taskType, plannedPhases, phaseArtifacts, reasoning) {
|
|
11
|
-
const id = randomUUID();
|
|
12
|
-
const now = new Date().toISOString();
|
|
13
|
-
this.db.prepare(`
|
|
14
|
-
INSERT INTO pipelines (
|
|
15
|
-
id, requirement, project_path, session_id, phase, tech_stack,
|
|
16
|
-
complexity, task_type, planned_phases, phase_artifacts, reasoning,
|
|
17
|
-
created_at, updated_at
|
|
18
|
-
)
|
|
19
|
-
VALUES (?, ?, ?, ?, 'analyze', ?, ?, ?, ?, ?, ?, ?, ?)
|
|
20
|
-
`).run(id, requirement, projectPath, sessionId, techStack || null, complexity || 'moderate', taskType || 'other', plannedPhases ? JSON.stringify(plannedPhases) : null, phaseArtifacts ? JSON.stringify(phaseArtifacts) : null, reasoning || null, now, now);
|
|
21
|
-
logger.info(`Pipeline 已创建:${id} — ${requirement} (${complexity || 'moderate'} ${taskType || 'other'})`);
|
|
22
|
-
return {
|
|
23
|
-
id, requirement, projectPath, sessionId,
|
|
24
|
-
phase: 'analyze', tasks: [], techStack,
|
|
25
|
-
complexity, taskType, plannedPhases, phaseArtifacts, reasoning,
|
|
26
|
-
createdAt: now, updatedAt: now,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
addTasks(pipelineId, tasks) {
|
|
30
|
-
const insertStmt = this.db.prepare(`
|
|
31
|
-
INSERT INTO pipeline_tasks (id, pipeline_id, title, phase, status, description, dependencies, output, source)
|
|
32
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
33
|
-
`);
|
|
34
|
-
const result = [];
|
|
35
|
-
const insertAll = this.db.transaction((items) => {
|
|
36
|
-
for (const task of items) {
|
|
37
|
-
const id = randomUUID();
|
|
38
|
-
insertStmt.run(id, pipelineId, task.title, task.phase, task.status, task.description, JSON.stringify(task.dependencies), task.output || null, task.source || null);
|
|
39
|
-
result.push({ ...task, id });
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
insertAll(tasks);
|
|
43
|
-
return result;
|
|
44
|
-
}
|
|
45
|
-
getActivePipeline(projectPath) {
|
|
46
|
-
const row = this.db.prepare("SELECT * FROM pipelines WHERE project_path = ? AND phase != 'done' ORDER BY updated_at DESC LIMIT 1").get(projectPath);
|
|
47
|
-
if (!row)
|
|
48
|
-
return null;
|
|
49
|
-
const tasks = this.getTasks(row.id);
|
|
50
|
-
return {
|
|
51
|
-
id: row.id,
|
|
52
|
-
requirement: row.requirement,
|
|
53
|
-
projectPath: row.project_path,
|
|
54
|
-
sessionId: row.session_id,
|
|
55
|
-
phase: row.phase,
|
|
56
|
-
tasks,
|
|
57
|
-
techStack: row.tech_stack,
|
|
58
|
-
complexity: row.complexity || 'moderate',
|
|
59
|
-
taskType: row.task_type || 'other',
|
|
60
|
-
plannedPhases: row.planned_phases ? JSON.parse(row.planned_phases) : undefined,
|
|
61
|
-
phaseArtifacts: row.phase_artifacts ? JSON.parse(row.phase_artifacts) : undefined,
|
|
62
|
-
reasoning: row.reasoning,
|
|
63
|
-
createdAt: row.created_at,
|
|
64
|
-
updatedAt: row.updated_at,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
getTasks(pipelineId) {
|
|
68
|
-
const rows = this.db.prepare('SELECT * FROM pipeline_tasks WHERE pipeline_id = ? ORDER BY phase, rowid').all(pipelineId);
|
|
69
|
-
return rows.map(row => ({
|
|
70
|
-
id: row.id,
|
|
71
|
-
title: row.title,
|
|
72
|
-
phase: row.phase,
|
|
73
|
-
status: row.status,
|
|
74
|
-
description: row.description,
|
|
75
|
-
dependencies: JSON.parse(row.dependencies || '[]'),
|
|
76
|
-
output: row.output,
|
|
77
|
-
source: row.source,
|
|
78
|
-
}));
|
|
79
|
-
}
|
|
80
|
-
updatePhase(pipelineId, phase) {
|
|
81
|
-
this.db.prepare('UPDATE pipelines SET phase = ?, updated_at = ? WHERE id = ?').run(phase, new Date().toISOString(), pipelineId);
|
|
82
|
-
}
|
|
83
|
-
/** 按 ID 关闭单个 Pipeline */
|
|
84
|
-
closeById(pipelineId) {
|
|
85
|
-
this.db.prepare("UPDATE pipelines SET phase = 'done', updated_at = ? WHERE id = ?").run(new Date().toISOString(), pipelineId);
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* 关闭超过 ttlMs 未更新的所有活跃 Pipeline,返回被关闭的数量。
|
|
89
|
-
* 默认 2 小时(7200000ms)。
|
|
90
|
-
*/
|
|
91
|
-
closeExpired(ttlMs = PIPELINE.EXPIRE_MS) {
|
|
92
|
-
const cutoff = new Date(Date.now() - ttlMs).toISOString();
|
|
93
|
-
const result = this.db.prepare("UPDATE pipelines SET phase = 'done', updated_at = ? WHERE phase != 'done' AND updated_at < ?").run(new Date().toISOString(), cutoff);
|
|
94
|
-
return result.changes;
|
|
95
|
-
}
|
|
96
|
-
/** 列出所有非 done 的 Pipeline(跨项目,供 CLI 展示) */
|
|
97
|
-
listActive() {
|
|
98
|
-
const rows = this.db.prepare("SELECT id, requirement, project_path, phase, updated_at FROM pipelines WHERE phase != 'done' ORDER BY updated_at DESC").all();
|
|
99
|
-
return rows.map(r => ({
|
|
100
|
-
id: r.id,
|
|
101
|
-
requirement: r.requirement,
|
|
102
|
-
projectPath: r.project_path,
|
|
103
|
-
phase: r.phase,
|
|
104
|
-
updatedAt: r.updated_at,
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* 将指定 Pipeline 中所有 in_progress 任务重置为 pending。
|
|
109
|
-
* 用于 ESC 中断后恢复:in_progress 表示"开始但未完成",中断后需重新检测。
|
|
110
|
-
*/
|
|
111
|
-
resetInProgressTasks(pipelineId) {
|
|
112
|
-
const result = this.db.prepare("UPDATE pipeline_tasks SET status = 'pending' WHERE pipeline_id = ? AND status = 'in_progress'").run(pipelineId);
|
|
113
|
-
return result.changes;
|
|
114
|
-
}
|
|
115
|
-
getPhaseProgress(pipelineId, phase) {
|
|
116
|
-
const row = this.db.prepare(`
|
|
117
|
-
SELECT
|
|
118
|
-
COUNT(*) as total,
|
|
119
|
-
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed
|
|
120
|
-
FROM pipeline_tasks WHERE pipeline_id = ? AND phase = ?
|
|
121
|
-
`).get(pipelineId, phase);
|
|
122
|
-
return { total: row.total || 0, completed: row.completed || 0 };
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* 更新任务状态
|
|
126
|
-
*/
|
|
127
|
-
updateTaskStatus(taskId, status, output) {
|
|
128
|
-
if (output) {
|
|
129
|
-
const result = this.db.prepare("UPDATE pipeline_tasks SET status = ?, output = ?, updated_at = datetime('now') WHERE id = ?").run(status, output, taskId);
|
|
130
|
-
return result.changes > 0;
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
const result = this.db.prepare("UPDATE pipeline_tasks SET status = ?, updated_at = datetime('now') WHERE id = ?").run(status, taskId);
|
|
134
|
-
return result.changes > 0;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* 获取单个任务
|
|
139
|
-
*/
|
|
140
|
-
getTask(taskId) {
|
|
141
|
-
const row = this.db.prepare('SELECT * FROM pipeline_tasks WHERE id = ?').get(taskId);
|
|
142
|
-
if (!row)
|
|
143
|
-
return null;
|
|
144
|
-
return {
|
|
145
|
-
id: row.id,
|
|
146
|
-
title: row.title,
|
|
147
|
-
description: row.description,
|
|
148
|
-
phase: row.phase,
|
|
149
|
-
status: row.status,
|
|
150
|
-
dependencies: [],
|
|
151
|
-
source: row.source,
|
|
152
|
-
output: row.output,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* 根据任务 ID 获取 Pipeline ID
|
|
157
|
-
*/
|
|
158
|
-
getPipelineIdByTask(taskId) {
|
|
159
|
-
const row = this.db.prepare('SELECT pipeline_id FROM pipeline_tasks WHERE id = ?').get(taskId);
|
|
160
|
-
return row?.pipeline_id || null;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
//# sourceMappingURL=store.legacy.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.legacy.js","sourceRoot":"","sources":["../../src/pipeline/store.legacy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Auto Migration: Legacy Tables → Event Sourcing
|
|
4
|
-
*
|
|
5
|
-
* 在 daemon 启动时自动检测并迁移历史数据
|
|
6
|
-
* 使用 schema_migrations 表记录迁移状态,避免重复执行
|
|
7
|
-
*/
|
|
8
|
-
export declare function autoMigrate(dbPath: string): Promise<void>;
|
|
9
|
-
//# sourceMappingURL=auto-migrate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auto-migrate.d.ts","sourceRoot":"","sources":["../../src/scripts/auto-migrate.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AA6BH,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmD/D"}
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Auto Migration: Legacy Tables → Event Sourcing
|
|
4
|
-
*
|
|
5
|
-
* 在 daemon 启动时自动检测并迁移历史数据
|
|
6
|
-
* 使用 schema_migrations 表记录迁移状态,避免重复执行
|
|
7
|
-
*/
|
|
8
|
-
import Database from 'better-sqlite3';
|
|
9
|
-
import { EventStore } from '../pipeline/event-store.js';
|
|
10
|
-
import { SnapshotStore } from '../pipeline/snapshot-store.js';
|
|
11
|
-
import { OptimizedAggregator } from '../pipeline/optimized-aggregator.js';
|
|
12
|
-
import { PipelineEventType } from '../pipeline/events.js';
|
|
13
|
-
import { logger } from '../utils/logger.js';
|
|
14
|
-
const MIGRATION_ID = 'pipeline-event-sourcing-v1';
|
|
15
|
-
export async function autoMigrate(dbPath) {
|
|
16
|
-
const db = new Database(dbPath);
|
|
17
|
-
// 1. 确保 schema_migrations 表存在
|
|
18
|
-
db.exec(`
|
|
19
|
-
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
20
|
-
id TEXT PRIMARY KEY,
|
|
21
|
-
executed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
22
|
-
)
|
|
23
|
-
`);
|
|
24
|
-
// 2. 检查是否已执行过此迁移
|
|
25
|
-
const migrationRecord = db.prepare(`
|
|
26
|
-
SELECT id FROM schema_migrations WHERE id = ?
|
|
27
|
-
`).get(MIGRATION_ID);
|
|
28
|
-
if (migrationRecord) {
|
|
29
|
-
logger.debug('[Migration] 迁移已执行,跳过');
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
// 3. 检查是否有历史数据需要迁移
|
|
33
|
-
const hasLegacyData = db.prepare(`SELECT COUNT(*) as count FROM pipelines`).get();
|
|
34
|
-
if (hasLegacyData.count === 0) {
|
|
35
|
-
logger.info('[Migration] 无历史数据,标记迁移完成');
|
|
36
|
-
db.prepare(`INSERT INTO schema_migrations (id) VALUES (?)`).run(MIGRATION_ID);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
logger.info(`[Migration] 检测到 ${hasLegacyData.count} 条历史数据,开始迁移...`);
|
|
40
|
-
const eventStore = new EventStore(dbPath);
|
|
41
|
-
const snapshotStore = new SnapshotStore(dbPath);
|
|
42
|
-
const aggregator = new OptimizedAggregator(eventStore, snapshotStore);
|
|
43
|
-
const pipelines = db.prepare(`SELECT * FROM pipelines ORDER BY created_at ASC`).all();
|
|
44
|
-
const tasks = db.prepare(`SELECT * FROM pipeline_tasks ORDER BY updated_at ASC`).all();
|
|
45
|
-
let migratedCount = 0;
|
|
46
|
-
for (const pipeline of pipelines) {
|
|
47
|
-
const pipelineTasks = tasks.filter(t => t.pipeline_id === pipeline.id);
|
|
48
|
-
await migratePipeline(eventStore, aggregator, pipeline, pipelineTasks);
|
|
49
|
-
migratedCount++;
|
|
50
|
-
}
|
|
51
|
-
// 4. 标记迁移完成
|
|
52
|
-
db.prepare(`INSERT INTO schema_migrations (id) VALUES (?)`).run(MIGRATION_ID);
|
|
53
|
-
logger.info(`[Migration] ✅ 迁移完成:${migratedCount} 个 Pipeline`);
|
|
54
|
-
}
|
|
55
|
-
async function migratePipeline(eventStore, aggregator, pipeline, tasks) {
|
|
56
|
-
let currentTimestamp = new Date(pipeline.created_at).getTime();
|
|
57
|
-
// 1. PIPELINE_CREATED
|
|
58
|
-
eventStore.append({
|
|
59
|
-
pipelineId: pipeline.id,
|
|
60
|
-
type: PipelineEventType.PIPELINE_CREATED,
|
|
61
|
-
payload: {
|
|
62
|
-
requirement: '',
|
|
63
|
-
projectPath: pipeline.project_path,
|
|
64
|
-
sessionId: pipeline.session_id,
|
|
65
|
-
plannedPhases: ['analyze', 'design', 'code', 'test', 'review'],
|
|
66
|
-
},
|
|
67
|
-
metadata: { sessionId: pipeline.session_id },
|
|
68
|
-
});
|
|
69
|
-
// 2. Tasks
|
|
70
|
-
const phaseOrder = ['analyze', 'design', 'code', 'test', 'review'];
|
|
71
|
-
const tasksByPhase = new Map();
|
|
72
|
-
for (const task of tasks) {
|
|
73
|
-
if (!tasksByPhase.has(task.phase))
|
|
74
|
-
tasksByPhase.set(task.phase, []);
|
|
75
|
-
tasksByPhase.get(task.phase).push(task);
|
|
76
|
-
}
|
|
77
|
-
for (let i = 0; i < phaseOrder.length; i++) {
|
|
78
|
-
const phase = phaseOrder[i];
|
|
79
|
-
const phaseTasks = tasksByPhase.get(phase) || [];
|
|
80
|
-
if (phaseTasks.length === 0)
|
|
81
|
-
continue;
|
|
82
|
-
if (i > 0) {
|
|
83
|
-
currentTimestamp += 1000;
|
|
84
|
-
eventStore.append({
|
|
85
|
-
pipelineId: pipeline.id,
|
|
86
|
-
type: PipelineEventType.PHASE_ADVANCED,
|
|
87
|
-
payload: {
|
|
88
|
-
fromPhase: phaseOrder[i - 1],
|
|
89
|
-
toPhase: phase,
|
|
90
|
-
reason: 'task_complete',
|
|
91
|
-
completedTasks: [],
|
|
92
|
-
},
|
|
93
|
-
metadata: { sessionId: pipeline.session_id },
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
for (const task of phaseTasks) {
|
|
97
|
-
currentTimestamp += 500;
|
|
98
|
-
eventStore.append({
|
|
99
|
-
pipelineId: pipeline.id,
|
|
100
|
-
type: PipelineEventType.TASK_CREATED,
|
|
101
|
-
payload: {
|
|
102
|
-
taskId: task.id,
|
|
103
|
-
title: task.title,
|
|
104
|
-
phase: task.phase,
|
|
105
|
-
},
|
|
106
|
-
metadata: { sessionId: pipeline.session_id },
|
|
107
|
-
});
|
|
108
|
-
if (task.status !== 'pending') {
|
|
109
|
-
currentTimestamp += 500;
|
|
110
|
-
eventStore.append({
|
|
111
|
-
pipelineId: pipeline.id,
|
|
112
|
-
type: PipelineEventType.TASK_STARTED,
|
|
113
|
-
payload: { taskId: task.id },
|
|
114
|
-
metadata: { sessionId: pipeline.session_id },
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
if (task.status === 'completed') {
|
|
118
|
-
currentTimestamp += 500;
|
|
119
|
-
eventStore.append({
|
|
120
|
-
pipelineId: pipeline.id,
|
|
121
|
-
type: PipelineEventType.TASK_COMPLETED,
|
|
122
|
-
payload: {
|
|
123
|
-
taskId: task.id,
|
|
124
|
-
title: task.title,
|
|
125
|
-
phase: task.phase,
|
|
126
|
-
artifact: '',
|
|
127
|
-
detectionMethod: 'heuristic',
|
|
128
|
-
},
|
|
129
|
-
metadata: { sessionId: pipeline.session_id },
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
else if (task.status === 'failed') {
|
|
133
|
-
currentTimestamp += 500;
|
|
134
|
-
eventStore.append({
|
|
135
|
-
pipelineId: pipeline.id,
|
|
136
|
-
type: PipelineEventType.TASK_FAILED,
|
|
137
|
-
payload: { taskId: task.id, reason: 'migrated from legacy' },
|
|
138
|
-
metadata: { sessionId: pipeline.session_id },
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
// 3. PIPELINE_CLOSED
|
|
144
|
-
if (pipeline.status === 'closed') {
|
|
145
|
-
currentTimestamp += 1000;
|
|
146
|
-
eventStore.append({
|
|
147
|
-
pipelineId: pipeline.id,
|
|
148
|
-
type: PipelineEventType.PIPELINE_CLOSED,
|
|
149
|
-
payload: {
|
|
150
|
-
reason: 'manual',
|
|
151
|
-
totalTasks: tasks.length,
|
|
152
|
-
completedTasks: tasks.filter(t => t.status === 'completed').length,
|
|
153
|
-
failedTasks: tasks.filter(t => t.status === 'failed').length,
|
|
154
|
-
},
|
|
155
|
-
metadata: { sessionId: pipeline.session_id },
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
// 4. Build snapshot
|
|
159
|
-
aggregator.rebuildAndSnapshot(pipeline.id);
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=auto-migrate.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auto-migrate.js","sourceRoot":"","sources":["../../src/scripts/auto-migrate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Data Migration Script: Legacy Tables → Event Sourcing
|
|
4
|
-
*
|
|
5
|
-
* Converts existing pipeline data from `pipelines` and `pipeline_tasks` tables
|
|
6
|
-
* into event streams in `pipeline_events` table.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* npx tsx src/scripts/migrate-to-event-sourcing.ts [--dry-run] [--force]
|
|
10
|
-
*
|
|
11
|
-
* Options:
|
|
12
|
-
* --dry-run: Preview migration without writing to database
|
|
13
|
-
* --force: Skip confirmation prompt
|
|
14
|
-
*/
|
|
15
|
-
export {};
|
|
16
|
-
//# sourceMappingURL=migrate-to-event-sourcing.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-to-event-sourcing.d.ts","sourceRoot":"","sources":["../../src/scripts/migrate-to-event-sourcing.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG"}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Data Migration Script: Legacy Tables → Event Sourcing
|
|
4
|
-
*
|
|
5
|
-
* Converts existing pipeline data from `pipelines` and `pipeline_tasks` tables
|
|
6
|
-
* into event streams in `pipeline_events` table.
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* npx tsx src/scripts/migrate-to-event-sourcing.ts [--dry-run] [--force]
|
|
10
|
-
*
|
|
11
|
-
* Options:
|
|
12
|
-
* --dry-run: Preview migration without writing to database
|
|
13
|
-
* --force: Skip confirmation prompt
|
|
14
|
-
*/
|
|
15
|
-
import Database from 'better-sqlite3';
|
|
16
|
-
import { resolve } from 'path';
|
|
17
|
-
import { homedir } from 'os';
|
|
18
|
-
import { EventStore } from '../pipeline/event-store.js';
|
|
19
|
-
import { SnapshotStore } from '../pipeline/snapshot-store.js';
|
|
20
|
-
import { OptimizedAggregator } from '../pipeline/optimized-aggregator.js';
|
|
21
|
-
import { PipelineEventType } from '../pipeline/events.js';
|
|
22
|
-
class MigrationRunner {
|
|
23
|
-
db;
|
|
24
|
-
eventStore;
|
|
25
|
-
snapshotStore;
|
|
26
|
-
aggregator;
|
|
27
|
-
dryRun;
|
|
28
|
-
constructor(dbPath, dryRun = false) {
|
|
29
|
-
this.db = new Database(dbPath);
|
|
30
|
-
this.eventStore = new EventStore(dbPath);
|
|
31
|
-
this.snapshotStore = new SnapshotStore(dbPath);
|
|
32
|
-
this.aggregator = new OptimizedAggregator(this.eventStore, this.snapshotStore);
|
|
33
|
-
this.dryRun = dryRun;
|
|
34
|
-
}
|
|
35
|
-
async run() {
|
|
36
|
-
console.log('🔍 Scanning legacy data...\n');
|
|
37
|
-
const pipelines = this.getLegacyPipelines();
|
|
38
|
-
const tasks = this.getLegacyTasks();
|
|
39
|
-
console.log(`Found ${pipelines.length} pipelines and ${tasks.length} tasks\n`);
|
|
40
|
-
if (pipelines.length === 0) {
|
|
41
|
-
console.log('✅ No data to migrate');
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (this.dryRun) {
|
|
45
|
-
console.log('🔎 DRY RUN MODE - No changes will be written\n');
|
|
46
|
-
}
|
|
47
|
-
let migratedCount = 0;
|
|
48
|
-
let skippedCount = 0;
|
|
49
|
-
for (const pipeline of pipelines) {
|
|
50
|
-
const pipelineTasks = tasks.filter(t => t.pipeline_id === pipeline.id);
|
|
51
|
-
// Check if already migrated
|
|
52
|
-
const existingEvents = this.eventStore.getEvents(pipeline.id);
|
|
53
|
-
if (existingEvents.length > 0) {
|
|
54
|
-
console.log(`⏭️ Skipping ${pipeline.id} (already has ${existingEvents.length} events)`);
|
|
55
|
-
skippedCount++;
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
console.log(`📦 Migrating pipeline ${pipeline.id}...`);
|
|
59
|
-
await this.migratePipeline(pipeline, pipelineTasks);
|
|
60
|
-
migratedCount++;
|
|
61
|
-
}
|
|
62
|
-
console.log(`\n✅ Migration complete: ${migratedCount} migrated, ${skippedCount} skipped`);
|
|
63
|
-
}
|
|
64
|
-
getLegacyPipelines() {
|
|
65
|
-
return this.db.prepare(`
|
|
66
|
-
SELECT id, session_id, project_path, current_phase, status, created_at, updated_at
|
|
67
|
-
FROM pipelines
|
|
68
|
-
ORDER BY created_at ASC
|
|
69
|
-
`).all();
|
|
70
|
-
}
|
|
71
|
-
getLegacyTasks() {
|
|
72
|
-
return this.db.prepare(`
|
|
73
|
-
SELECT id, pipeline_id, phase, description, status, created_at, updated_at
|
|
74
|
-
FROM pipeline_tasks
|
|
75
|
-
ORDER BY created_at ASC
|
|
76
|
-
`).all();
|
|
77
|
-
}
|
|
78
|
-
async migratePipeline(pipeline, tasks) {
|
|
79
|
-
let currentTimestamp = new Date(pipeline.created_at).getTime();
|
|
80
|
-
const dryRunEvents = [];
|
|
81
|
-
const emit = (type, payload, ts) => {
|
|
82
|
-
if (this.dryRun) {
|
|
83
|
-
dryRunEvents.push(type);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
this.eventStore.append({ pipelineId: pipeline.id, type, payload, metadata: { sessionId: pipeline.session_id } });
|
|
87
|
-
};
|
|
88
|
-
// 1. PIPELINE_CREATED
|
|
89
|
-
emit(PipelineEventType.PIPELINE_CREATED, {
|
|
90
|
-
requirement: '',
|
|
91
|
-
projectPath: pipeline.project_path,
|
|
92
|
-
sessionId: pipeline.session_id,
|
|
93
|
-
plannedPhases: ['analyze', 'design', 'code', 'test', 'review'],
|
|
94
|
-
}, currentTimestamp);
|
|
95
|
-
// 2. Tasks grouped by phase
|
|
96
|
-
const phaseOrder = ['analyze', 'design', 'code', 'test', 'review'];
|
|
97
|
-
const tasksByPhase = new Map();
|
|
98
|
-
for (const task of tasks) {
|
|
99
|
-
if (!tasksByPhase.has(task.phase))
|
|
100
|
-
tasksByPhase.set(task.phase, []);
|
|
101
|
-
tasksByPhase.get(task.phase).push(task);
|
|
102
|
-
}
|
|
103
|
-
for (let i = 0; i < phaseOrder.length; i++) {
|
|
104
|
-
const phase = phaseOrder[i];
|
|
105
|
-
const phaseTasks = tasksByPhase.get(phase) || [];
|
|
106
|
-
if (phaseTasks.length === 0)
|
|
107
|
-
continue;
|
|
108
|
-
if (i > 0) {
|
|
109
|
-
currentTimestamp += 1000;
|
|
110
|
-
emit(PipelineEventType.PHASE_ADVANCED, {
|
|
111
|
-
fromPhase: phaseOrder[i - 1],
|
|
112
|
-
toPhase: phase,
|
|
113
|
-
reason: 'task_complete',
|
|
114
|
-
completedTasks: [],
|
|
115
|
-
}, currentTimestamp);
|
|
116
|
-
}
|
|
117
|
-
for (const task of phaseTasks) {
|
|
118
|
-
currentTimestamp += 500;
|
|
119
|
-
emit(PipelineEventType.TASK_CREATED, {
|
|
120
|
-
taskId: task.id,
|
|
121
|
-
title: task.description,
|
|
122
|
-
phase: task.phase,
|
|
123
|
-
}, currentTimestamp);
|
|
124
|
-
if (task.status !== 'pending') {
|
|
125
|
-
currentTimestamp += 500;
|
|
126
|
-
emit(PipelineEventType.TASK_STARTED, { taskId: task.id }, currentTimestamp);
|
|
127
|
-
}
|
|
128
|
-
if (task.status === 'completed') {
|
|
129
|
-
currentTimestamp += 500;
|
|
130
|
-
emit(PipelineEventType.TASK_COMPLETED, {
|
|
131
|
-
taskId: task.id,
|
|
132
|
-
title: task.description,
|
|
133
|
-
phase: task.phase,
|
|
134
|
-
artifact: '',
|
|
135
|
-
detectionMethod: 'heuristic',
|
|
136
|
-
}, currentTimestamp);
|
|
137
|
-
}
|
|
138
|
-
else if (task.status === 'failed') {
|
|
139
|
-
currentTimestamp += 500;
|
|
140
|
-
emit(PipelineEventType.TASK_FAILED, { taskId: task.id, reason: 'migrated from legacy' }, currentTimestamp);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// 3. PIPELINE_CLOSED
|
|
145
|
-
if (pipeline.status === 'closed') {
|
|
146
|
-
currentTimestamp += 1000;
|
|
147
|
-
emit(PipelineEventType.PIPELINE_CLOSED, {
|
|
148
|
-
reason: 'manual',
|
|
149
|
-
totalTasks: tasks.length,
|
|
150
|
-
completedTasks: tasks.filter(t => t.status === 'completed').length,
|
|
151
|
-
failedTasks: tasks.filter(t => t.status === 'failed').length,
|
|
152
|
-
}, currentTimestamp);
|
|
153
|
-
}
|
|
154
|
-
if (this.dryRun) {
|
|
155
|
-
console.log(` → Would write ${dryRunEvents.length} events: ${dryRunEvents.join(', ')}`);
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
this.aggregator.rebuildAndSnapshot(pipeline.id);
|
|
159
|
-
console.log(` ✓ Wrote events + snapshot`);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
async function main() {
|
|
163
|
-
const args = process.argv.slice(2);
|
|
164
|
-
const dryRun = args.includes('--dry-run');
|
|
165
|
-
const force = args.includes('--force');
|
|
166
|
-
const dbPath = resolve(homedir(), '.claude-forge', 'data.db');
|
|
167
|
-
console.log(`Database: ${dbPath}\n`);
|
|
168
|
-
if (!dryRun && !force) {
|
|
169
|
-
console.log('⚠️ This will write events to the database. Use --dry-run to preview, or --force to skip this prompt.');
|
|
170
|
-
process.exit(0);
|
|
171
|
-
}
|
|
172
|
-
const runner = new MigrationRunner(dbPath, dryRun);
|
|
173
|
-
await runner.run();
|
|
174
|
-
}
|
|
175
|
-
main().catch(err => {
|
|
176
|
-
console.error('Migration failed:', err);
|
|
177
|
-
process.exit(1);
|
|
178
|
-
});
|
|
179
|
-
//# sourceMappingURL=migrate-to-event-sourcing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate-to-event-sourcing.js","sourceRoot":"","sources":["../../src/scripts/migrate-to-event-sourcing.ts"],"names":[],"mappings":"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"}
|