@runweave/server-linux-arm64 0.0.0-stage → 0.1.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 (112) hide show
  1. package/manifest.json +1993 -0
  2. package/native.tar.gz +0 -0
  3. package/package.json +22 -4
  4. package/payload/app-server/build-info.json +8 -0
  5. package/payload/app-server/configuration-compatibility.json +1 -0
  6. package/payload/app-server/index.cjs +43560 -0
  7. package/payload/app-server/index.cjs.map +1 -0
  8. package/payload/backend/activity-sqlite-worker.cjs +6730 -0
  9. package/payload/backend/build-info.json +8 -0
  10. package/payload/backend/dev-resources/control.cjs +14727 -0
  11. package/payload/backend/evolution-sqlite-worker.cjs +2073 -0
  12. package/payload/backend/index.cjs +135617 -0
  13. package/payload/backend/ios-simulators/device_shutdown.py +22 -0
  14. package/payload/backend/ios-simulators/monitor.py +204 -0
  15. package/payload/backend/ios-simulators/pool.py +600 -0
  16. package/payload/backend/scheduled-tasks-sqlite-worker.cjs +29203 -0
  17. package/payload/bin/runtime.cjs +95 -0
  18. package/payload/frontend/dist/assets/_baseUniq-B6OtH5JH.js +1 -0
  19. package/payload/frontend/dist/assets/access-CpH3nCnI.js +1 -0
  20. package/payload/frontend/dist/assets/advanced-U5MqNTD5.js +1 -0
  21. package/payload/frontend/dist/assets/appearance-Cb8XjaOT.js +1 -0
  22. package/payload/frontend/dist/assets/arc-CEnFQNMK.js +1 -0
  23. package/payload/frontend/dist/assets/architectureDiagram-Q4EWVU46-T438RyEG.js +36 -0
  24. package/payload/frontend/dist/assets/blockDiagram-DXYQGD6D-B6Mqb9og.js +132 -0
  25. package/payload/frontend/dist/assets/browser-CIEzmzuD.js +8 -0
  26. package/payload/frontend/dist/assets/c4Diagram-AHTNJAMY-CO3eA3hw.js +10 -0
  27. package/payload/frontend/dist/assets/channel-D7VgadXd.js +1 -0
  28. package/payload/frontend/dist/assets/chunk-4BX2VUAB-1vjsV_mH.js +1 -0
  29. package/payload/frontend/dist/assets/chunk-4TB4RGXK-CtMNFDLV.js +206 -0
  30. package/payload/frontend/dist/assets/chunk-55IACEB6-DVWWqMjZ.js +1 -0
  31. package/payload/frontend/dist/assets/chunk-EDXVE4YY-BBf3C6eJ.js +1 -0
  32. package/payload/frontend/dist/assets/chunk-FMBD7UC4-BUQfXSvf.js +15 -0
  33. package/payload/frontend/dist/assets/chunk-OYMX7WX6-DM1nFyON.js +231 -0
  34. package/payload/frontend/dist/assets/chunk-QZHKN3VN-Bz3CUNpU.js +1 -0
  35. package/payload/frontend/dist/assets/chunk-YZCP3GAM-Bb6CnKMv.js +1 -0
  36. package/payload/frontend/dist/assets/classDiagram-6PBFFD2Q-DHRHkXVC.js +1 -0
  37. package/payload/frontend/dist/assets/classDiagram-v2-HSJHXN6E-DHRHkXVC.js +1 -0
  38. package/payload/frontend/dist/assets/clone-BzLTnNJj.js +1 -0
  39. package/payload/frontend/dist/assets/companion-BLgWW1ka.css +1 -0
  40. package/payload/frontend/dist/assets/companion-CRS3Tmyt.js +2 -0
  41. package/payload/frontend/dist/assets/connection-ChK196PA.js +12 -0
  42. package/payload/frontend/dist/assets/connections-1OP6Izpn.js +1 -0
  43. package/payload/frontend/dist/assets/cose-bilkent-S5V4N54A-DvX1W1oQ.js +1 -0
  44. package/payload/frontend/dist/assets/css.worker-B4z49cGk.js +93 -0
  45. package/payload/frontend/dist/assets/cytoscape.esm-DxGcaOPV.js +331 -0
  46. package/payload/frontend/dist/assets/dagre-KV5264BT-BYV7l80W.js +4 -0
  47. package/payload/frontend/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  48. package/payload/frontend/dist/assets/desktop-DKYPd_Z3.js +1 -0
  49. package/payload/frontend/dist/assets/diagram-5BDNPKRD-BU_VxMcA.js +10 -0
  50. package/payload/frontend/dist/assets/diagram-G4DWMVQ6-6jnkLcPr.js +24 -0
  51. package/payload/frontend/dist/assets/diagram-MMDJMWI5-DAjbbS4T.js +43 -0
  52. package/payload/frontend/dist/assets/diagram-TYMM5635-p2T86-Pr.js +24 -0
  53. package/payload/frontend/dist/assets/editor.worker-DyuDvpVp.js +26 -0
  54. package/payload/frontend/dist/assets/erDiagram-SMLLAGMA-DcZPoxkO.js +85 -0
  55. package/payload/frontend/dist/assets/flowDiagram-DWJPFMVM-CDB-5IUB.js +162 -0
  56. package/payload/frontend/dist/assets/ganttDiagram-T4ZO3ILL-imCnxO5S.js +292 -0
  57. package/payload/frontend/dist/assets/gitGraphDiagram-UUTBAWPF-DW7bWVfm.js +106 -0
  58. package/payload/frontend/dist/assets/graph-rPoUAwm2.js +1 -0
  59. package/payload/frontend/dist/assets/html.worker-DtiGdgqp.js +470 -0
  60. package/payload/frontend/dist/assets/image-pt4OUNUX.js +1 -0
  61. package/payload/frontend/dist/assets/index-BJDOs8Sk.css +1 -0
  62. package/payload/frontend/dist/assets/index-CpU0rt1e.js +455 -0
  63. package/payload/frontend/dist/assets/index-D9-cSGu-.js +49 -0
  64. package/payload/frontend/dist/assets/infoDiagram-42DDH7IO-C6DYDEhQ.js +2 -0
  65. package/payload/frontend/dist/assets/init-Gi6I4Gst.js +1 -0
  66. package/payload/frontend/dist/assets/ishikawaDiagram-UXIWVN3A-o3dlbDPW.js +70 -0
  67. package/payload/frontend/dist/assets/journeyDiagram-VCZTEJTY-ukG3M2cI.js +139 -0
  68. package/payload/frontend/dist/assets/json.worker-leyajbqV.js +58 -0
  69. package/payload/frontend/dist/assets/kanban-definition-6JOO6SKY-CzFLztFd.js +89 -0
  70. package/payload/frontend/dist/assets/katex-DkKDou_j.js +257 -0
  71. package/payload/frontend/dist/assets/layout-C8SEMYSj.js +1 -0
  72. package/payload/frontend/dist/assets/linear-DY8vPita.js +1 -0
  73. package/payload/frontend/dist/assets/main-B_ifx48h.js +693 -0
  74. package/payload/frontend/dist/assets/main-C-ZLrzMh.css +33 -0
  75. package/payload/frontend/dist/assets/min-9StlgeN8.js +1 -0
  76. package/payload/frontend/dist/assets/mindmap-definition-QFDTVHPH-CyJisFtS.js +96 -0
  77. package/payload/frontend/dist/assets/monitoring-Bjm0etKL.js +1 -0
  78. package/payload/frontend/dist/assets/notifications-DhRLCgMU.js +1 -0
  79. package/payload/frontend/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  80. package/payload/frontend/dist/assets/pieDiagram-DEJITSTG-DHSht7rk.js +30 -0
  81. package/payload/frontend/dist/assets/quadrantDiagram-34T5L4WZ-92xIujrE.js +7 -0
  82. package/payload/frontend/dist/assets/record-content-Cy_dPSdi.js +1 -0
  83. package/payload/frontend/dist/assets/requirementDiagram-MS252O5E-CXuOqrNd.js +84 -0
  84. package/payload/frontend/dist/assets/sankeyDiagram-XADWPNL6-DR-mjY0Y.js +10 -0
  85. package/payload/frontend/dist/assets/sequenceDiagram-FGHM5R23-DmmUpAoP.js +157 -0
  86. package/payload/frontend/dist/assets/shortcuts-BNrV46nh.js +1 -0
  87. package/payload/frontend/dist/assets/stateDiagram-FHFEXIEX-CKoqQ0-j.js +1 -0
  88. package/payload/frontend/dist/assets/stateDiagram-v2-QKLJ7IA2-BfZc0BCX.js +1 -0
  89. package/payload/frontend/dist/assets/status-B__OyRqS.js +1 -0
  90. package/payload/frontend/dist/assets/suiji-nz2Jwmpc.js +1 -0
  91. package/payload/frontend/dist/assets/svg-BpvEgtI3.js +21 -0
  92. package/payload/frontend/dist/assets/tabs-BjCNEXFA.js +1 -0
  93. package/payload/frontend/dist/assets/timeline-definition-GMOUNBTQ-CHT2sQNz.js +120 -0
  94. package/payload/frontend/dist/assets/ts.worker-59MjiAqk.js +67731 -0
  95. package/payload/frontend/dist/assets/vennDiagram-DHZGUBPP-Bvnh5q4I.js +34 -0
  96. package/payload/frontend/dist/assets/wardley-RL74JXVD-DeQXKB6h.js +162 -0
  97. package/payload/frontend/dist/assets/wardleyDiagram-NUSXRM2D-jWo5oC0L.js +20 -0
  98. package/payload/frontend/dist/assets/workbox-window.prod.es5-BIl4cyR9.js +2 -0
  99. package/payload/frontend/dist/assets/xychartDiagram-5P7HB3ND-Btji0cq9.js +7 -0
  100. package/payload/frontend/dist/build-info.json +8 -0
  101. package/payload/frontend/dist/companion.html +15 -0
  102. package/payload/frontend/dist/icons/apple-touch-icon.png +0 -0
  103. package/payload/frontend/dist/icons/icon-192.png +0 -0
  104. package/payload/frontend/dist/icons/icon-512.png +0 -0
  105. package/payload/frontend/dist/icons/maskable-icon-512.png +0 -0
  106. package/payload/frontend/dist/index.html +19 -0
  107. package/payload/frontend/dist/manifest.webmanifest +28 -0
  108. package/payload/frontend/dist/sw.js +1 -0
  109. package/payload/frontend/dist/workbox-632bafe5.js +1 -0
  110. package/payload/server/index.cjs +8620 -0
  111. package/payload/start.mjs +50 -0
  112. package/README.md +0 -3
@@ -0,0 +1,2073 @@
1
+ const __IMPORT_META_URL__ = require('url').pathToFileURL(__filename).href;
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // backend/src/evolution/storage/sqlite-worker.ts
27
+ var import_node_worker_threads = require("node:worker_threads");
28
+
29
+ // backend/src/evolution/storage/artifact-reads.ts
30
+ var PAGE_BYTES = 512 * 1024;
31
+ var EvolutionArtifactReads = class {
32
+ constructor(database2) {
33
+ this.database = database2;
34
+ }
35
+ summaries = /* @__PURE__ */ new Map();
36
+ overview(runId) {
37
+ const cacheAllowed = !this.database.inTransaction;
38
+ return this.database.transaction(() => ({
39
+ contextPack: this.summary(runId, cacheAllowed),
40
+ segmentCount: this.count("trace_segments", runId),
41
+ episodeCount: this.count("episodes", runId)
42
+ }))();
43
+ }
44
+ count(table, runId, boundary) {
45
+ return this.database.prepare(
46
+ `SELECT COUNT(*) AS n FROM ${table} WHERE run_id = ?
47
+ ${boundary === void 0 ? "" : "AND rowid <= ?"}`
48
+ ).get(...boundary === void 0 ? [runId] : [runId, boundary]).n;
49
+ }
50
+ summary(runId, cacheAllowed) {
51
+ const identity = this.database.prepare(
52
+ "SELECT context_pack_id, digest FROM context_packs WHERE run_id = ?"
53
+ ).get(runId);
54
+ if (!identity) return null;
55
+ const cached = this.summaries.get(identity.context_pack_id);
56
+ if (cacheAllowed && cached?.digest === identity.digest) return cached.value;
57
+ const row = this.database.prepare(
58
+ `SELECT
59
+ json_remove(manifest_json, '$.evidence', '$.dataQualityIssues') AS metadata,
60
+ json_array_length(manifest_json, '$.evidence') AS evidenceCount,
61
+ json_array_length(manifest_json, '$.dataQualityIssues') AS dataQualityIssueCount
62
+ FROM context_packs WHERE run_id = ?`
63
+ ).get(runId);
64
+ const workspaceCount = this.database.prepare(
65
+ `SELECT COUNT(DISTINCT json_extract(item.value, '$.origin.projectId')) AS n
66
+ FROM context_packs pack, json_each(pack.manifest_json, '$.evidence') item
67
+ WHERE pack.run_id = ? AND json_extract(item.value, '$.source') = 'activity'
68
+ AND json_extract(item.value, '$.origin.projectId') != ''`
69
+ ).get(runId).n;
70
+ const dataQualitySummary = this.database.prepare(
71
+ `SELECT json_extract(item.value, '$.code') AS code,
72
+ COUNT(*) AS count, json_extract(item.value, '$.detail') AS detail, MIN(CAST(item.key AS INTEGER)) AS firstIndex
73
+ FROM context_packs pack, json_each(pack.manifest_json, '$.dataQualityIssues') item
74
+ WHERE pack.run_id = ? GROUP BY code`
75
+ ).all(runId);
76
+ dataQualitySummary.sort(
77
+ (a, b) => b.count - a.count || a.code.localeCompare(b.code)
78
+ );
79
+ const value = {
80
+ ...JSON.parse(row.metadata),
81
+ evidenceCount: row.evidenceCount,
82
+ dataQualityIssueCount: row.dataQualityIssueCount,
83
+ workspaceCount,
84
+ dataQualitySummary: dataQualitySummary.map(({ code, count, detail }) => ({
85
+ code,
86
+ count,
87
+ detail
88
+ }))
89
+ };
90
+ if (cacheAllowed) {
91
+ if (this.summaries.size >= 32)
92
+ this.summaries.delete(this.summaries.keys().next().value);
93
+ this.summaries.set(identity.context_pack_id, {
94
+ digest: identity.digest,
95
+ value
96
+ });
97
+ }
98
+ return value;
99
+ }
100
+ page(runId, query) {
101
+ const { collection } = query;
102
+ if (!["evidence", "data-quality", "segments", "episodes"].includes(collection))
103
+ throw new Error("evolution_artifact_query_invalid");
104
+ const limit = query.limit ?? 25;
105
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)
106
+ throw new Error("evolution_artifact_query_invalid");
107
+ const cursor = query.cursor ? decodeCursor(query.cursor, runId, collection) : void 0;
108
+ return this.database.transaction(() => {
109
+ const offset = cursor?.offset ?? 0;
110
+ let boundary;
111
+ let total;
112
+ let rows;
113
+ if (collection === "evidence" || collection === "data-quality") {
114
+ const pack = this.database.prepare(
115
+ "SELECT context_pack_id, digest FROM context_packs WHERE run_id = ?"
116
+ ).get(runId);
117
+ boundary = pack ? `${pack.context_pack_id}:${pack.digest}` : "missing";
118
+ if (cursor && cursor.boundary !== boundary)
119
+ throw new Error("evolution_artifact_cursor_stale");
120
+ const field = collection === "evidence" ? "evidence" : "dataQualityIssues";
121
+ total = pack ? this.database.prepare(
122
+ `SELECT json_array_length(manifest_json, '$.${field}') AS n
123
+ FROM context_packs WHERE run_id = ?`
124
+ ).get(runId).n : 0;
125
+ rows = this.database.prepare(
126
+ `SELECT item.value AS payload FROM context_packs pack,
127
+ json_each(pack.manifest_json, '$.${field}') item WHERE pack.run_id = ? AND CAST(item.key AS INTEGER) >= ?
128
+ ORDER BY CAST(item.key AS INTEGER) LIMIT ?`
129
+ ).iterate(runId, offset, limit);
130
+ } else {
131
+ const table = collection === "segments" ? "trace_segments" : "episodes";
132
+ const order = collection === "segments" ? "sequence, segment_id" : "created_at, episode_id";
133
+ boundary = cursor?.boundary ?? this.database.prepare(
134
+ `SELECT COALESCE(MAX(rowid), 0) AS n
135
+ FROM ${table} WHERE run_id = ?`
136
+ ).get(runId).n;
137
+ if (typeof boundary !== "number")
138
+ throw new Error("evolution_artifact_query_invalid");
139
+ total = this.count(table, runId, boundary);
140
+ rows = this.database.prepare(
141
+ `SELECT payload_json AS payload FROM ${table}
142
+ WHERE run_id = ? AND rowid <= ? ORDER BY ${order} LIMIT ? OFFSET ?`
143
+ ).iterate(runId, boundary, limit, offset);
144
+ }
145
+ const items = [];
146
+ let bytes = 0;
147
+ for (const row of rows) {
148
+ const size = Buffer.byteLength(row.payload);
149
+ if (items.length > 0 && bytes + size > PAGE_BYTES) break;
150
+ items.push(JSON.parse(row.payload));
151
+ bytes += size;
152
+ }
153
+ const nextOffset = offset + items.length;
154
+ return {
155
+ collection,
156
+ items,
157
+ total,
158
+ nextCursor: nextOffset < total ? Buffer.from(
159
+ JSON.stringify({
160
+ runId,
161
+ collection,
162
+ offset: nextOffset,
163
+ boundary
164
+ })
165
+ ).toString("base64url") : null
166
+ };
167
+ })();
168
+ }
169
+ };
170
+ function decodeCursor(value, runId, collection) {
171
+ try {
172
+ const cursor = JSON.parse(
173
+ Buffer.from(value, "base64url").toString("utf8")
174
+ );
175
+ if (cursor.runId === runId && cursor.collection === collection && Number.isSafeInteger(cursor.offset) && cursor.offset >= 0 && (typeof cursor.boundary === "string" && cursor.boundary.length <= 512 || Number.isSafeInteger(cursor.boundary) && Number(cursor.boundary) >= 0))
176
+ return cursor;
177
+ } catch {
178
+ }
179
+ throw new Error("evolution_artifact_query_invalid");
180
+ }
181
+
182
+ // backend/src/evolution/storage/repository-database.ts
183
+ function initializeEvolutionRepositories(database2) {
184
+ database2.exec(`
185
+ CREATE TABLE IF NOT EXISTS evolution_repositories(repository_id TEXT PRIMARY KEY, payload_json TEXT NOT NULL);
186
+ CREATE TABLE IF NOT EXISTS evolution_repository_bindings(
187
+ kind TEXT NOT NULL, id TEXT NOT NULL, payload_json TEXT NOT NULL, PRIMARY KEY(kind,id));
188
+ CREATE TABLE IF NOT EXISTS evolution_topic_lineage(
189
+ canonical_insight_id TEXT NOT NULL, legacy_insight_id TEXT PRIMARY KEY, status TEXT NOT NULL);
190
+ CREATE TABLE IF NOT EXISTS evolution_reflection_batches(
191
+ batch_id TEXT PRIMARY KEY, idempotency_key TEXT NOT NULL UNIQUE, payload_json TEXT NOT NULL);
192
+ CREATE TABLE IF NOT EXISTS evolution_repository_migrations(
193
+ migration_id TEXT PRIMARY KEY, payload_json TEXT NOT NULL);
194
+ `);
195
+ const columns = database2.prepare("PRAGMA table_info(evolution_runs)").all();
196
+ if (!columns.some((column) => column.name === "repository_json"))
197
+ database2.exec("ALTER TABLE evolution_runs ADD COLUMN repository_json TEXT");
198
+ }
199
+ function readRepositoryAttribution(database2, kind, id) {
200
+ const row = database2.prepare(
201
+ "SELECT payload_json FROM evolution_repository_bindings WHERE kind = ? AND id = ?"
202
+ ).get(kind, id);
203
+ return row ? JSON.parse(row.payload_json) : void 0;
204
+ }
205
+ function executeRepositoryCommand(database2, foundation, command) {
206
+ switch (command.op) {
207
+ case "list":
208
+ return database2.prepare(
209
+ "SELECT payload_json FROM evolution_repositories ORDER BY repository_id"
210
+ ).all().map((row) => JSON.parse(row.payload_json));
211
+ case "put": {
212
+ return database2.transaction(() => {
213
+ const row = database2.prepare(
214
+ "SELECT payload_json FROM evolution_repositories WHERE repository_id = ?"
215
+ ).get(command.repository.repositoryId);
216
+ const previous = row ? JSON.parse(row.payload_json) : null;
217
+ if (previous && previous.commonDirectory !== command.repository.commonDirectory)
218
+ throw new Error("evolution_repository_identity_conflict");
219
+ const repository = {
220
+ ...command.repository,
221
+ paths: [
222
+ .../* @__PURE__ */ new Set([
223
+ ...previous?.paths ?? [],
224
+ ...command.repository.paths
225
+ ])
226
+ ],
227
+ projectIds: [
228
+ .../* @__PURE__ */ new Set([
229
+ ...previous?.projectIds ?? [],
230
+ ...command.repository.projectIds
231
+ ])
232
+ ]
233
+ };
234
+ database2.prepare(
235
+ "INSERT INTO evolution_repositories VALUES (?,?) ON CONFLICT(repository_id) DO UPDATE SET payload_json=excluded.payload_json"
236
+ ).run(repository.repositoryId, JSON.stringify(repository));
237
+ return true;
238
+ }).immediate();
239
+ }
240
+ case "attribution":
241
+ return readRepositoryAttribution(database2, command.kind, command.id) ?? null;
242
+ case "batch-get": {
243
+ const row = database2.prepare(
244
+ "SELECT payload_json FROM evolution_reflection_batches WHERE idempotency_key = ?"
245
+ ).get(command.key);
246
+ return row ? JSON.parse(row.payload_json) : null;
247
+ }
248
+ case "batch-create":
249
+ return database2.transaction(() => {
250
+ const previous = executeRepositoryCommand(database2, foundation, {
251
+ op: "batch-get",
252
+ key: command.batch.idempotencyKey
253
+ });
254
+ if (previous) return previous;
255
+ for (const run of command.runs) foundation.createRun(run);
256
+ database2.prepare("INSERT INTO evolution_reflection_batches VALUES (?,?,?)").run(
257
+ command.batch.batchId,
258
+ command.batch.idempotencyKey,
259
+ JSON.stringify(command.batch)
260
+ );
261
+ return command.batch;
262
+ }).immediate();
263
+ }
264
+ }
265
+
266
+ // backend/src/evolution/storage/database.ts
267
+ var import_node_fs = require("node:fs");
268
+ var import_node_path = __toESM(require("node:path"), 1);
269
+ var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
270
+
271
+ // backend/src/evolution/storage/database-helpers.ts
272
+ function insertImmutable(database2, params) {
273
+ const existing = database2.prepare(
274
+ `SELECT payload_json FROM ${params.table} WHERE ${params.idColumn} = ?`
275
+ ).get(params.id);
276
+ if (existing) {
277
+ if (existing.payload_json !== params.payload) {
278
+ throw new Error("evolution_immutable_artifact_conflict");
279
+ }
280
+ return;
281
+ }
282
+ params.insert();
283
+ }
284
+
285
+ // backend/src/evolution/storage/artifact-database.ts
286
+ var EvolutionArtifactDatabase = class {
287
+ constructor(database2) {
288
+ this.database = database2;
289
+ }
290
+ putRuntimeTrace(trace) {
291
+ this.database.transaction(() => {
292
+ this.database.prepare(
293
+ `INSERT OR IGNORE INTO runtime_traces
294
+ (trace_id, run_id, created_at, payload_json)
295
+ VALUES (?, ?, ?, ?)`
296
+ ).run(
297
+ trace.traceId,
298
+ trace.runId,
299
+ trace.createdAt,
300
+ JSON.stringify({ ...trace, events: [] })
301
+ );
302
+ for (const event of trace.events) {
303
+ this.appendRuntimeTraceEvent(event);
304
+ }
305
+ })();
306
+ }
307
+ appendRuntimeTraceEvent(event) {
308
+ this.database.prepare(
309
+ `INSERT OR IGNORE INTO runtime_trace_events
310
+ (event_id, trace_id, at, payload_json)
311
+ VALUES (?, ?, ?, ?)`
312
+ ).run(event.eventId, event.traceId, event.at, JSON.stringify(event));
313
+ }
314
+ getRuntimeTrace(traceId) {
315
+ const row = this.database.prepare("SELECT payload_json FROM runtime_traces WHERE trace_id = ?").get(traceId);
316
+ if (!row) return null;
317
+ const trace = JSON.parse(row.payload_json);
318
+ return {
319
+ ...trace,
320
+ attribution: readRepositoryAttribution(this.database, "trace", traceId),
321
+ events: this.listEvents(traceId)
322
+ };
323
+ }
324
+ listRuntimeTraces(runId) {
325
+ const rows = this.database.prepare(
326
+ "SELECT trace_id FROM runtime_traces WHERE run_id = ? ORDER BY created_at"
327
+ ).all(runId);
328
+ return rows.flatMap((row) => {
329
+ const trace = this.getRuntimeTrace(row.trace_id);
330
+ return trace ? [trace] : [];
331
+ });
332
+ }
333
+ listRecentRuntimeTraces(learningScopeId, limit) {
334
+ const rows = learningScopeId ? this.database.prepare(
335
+ `SELECT trace_id FROM runtime_traces
336
+ WHERE json_extract(payload_json, '$.learningScopeId') = ? OR EXISTS (
337
+ SELECT 1 FROM evolution_repository_bindings binding, json_each(binding.payload_json, '$.repositoryIds') repo
338
+ WHERE binding.kind='trace' AND binding.id=runtime_traces.trace_id AND repo.value=?
339
+ )
340
+ ORDER BY created_at DESC, trace_id
341
+ LIMIT ?`
342
+ ).all(learningScopeId, learningScopeId, limit) : this.database.prepare(
343
+ `SELECT trace_id FROM runtime_traces
344
+ ORDER BY created_at DESC, trace_id
345
+ LIMIT ?`
346
+ ).all(limit);
347
+ return rows.flatMap((row) => {
348
+ const trace = this.getRuntimeTrace(row.trace_id);
349
+ return trace ? [trace] : [];
350
+ });
351
+ }
352
+ listEvents(traceId) {
353
+ const rows = this.database.prepare(
354
+ `SELECT payload_json FROM runtime_trace_events
355
+ WHERE trace_id = ? ORDER BY at, rowid`
356
+ ).all(traceId);
357
+ return rows.map((row) => JSON.parse(row.payload_json));
358
+ }
359
+ putContextPack(manifest) {
360
+ const manifestJson = JSON.stringify(manifest);
361
+ this.database.transaction(() => {
362
+ const existing = this.database.prepare(
363
+ `SELECT manifest_json FROM context_packs
364
+ WHERE context_pack_id = ? OR run_id = ?
365
+ LIMIT 1`
366
+ ).get(manifest.contextPackId, manifest.runId);
367
+ if (existing) {
368
+ if (existing.manifest_json !== manifestJson) {
369
+ throw new Error("evolution_context_pack_identity_conflict");
370
+ }
371
+ return;
372
+ }
373
+ this.database.prepare(
374
+ `INSERT INTO context_packs (
375
+ context_pack_id, run_id, learning_scope_id, digest,
376
+ created_at_ms, manifest_json
377
+ ) VALUES (?, ?, ?, ?, ?, ?)`
378
+ ).run(
379
+ manifest.contextPackId,
380
+ manifest.runId,
381
+ manifest.learningScope.learningScopeId,
382
+ manifest.digest,
383
+ Date.parse(manifest.createdAt),
384
+ manifestJson
385
+ );
386
+ const insertSource = this.database.prepare(
387
+ `INSERT INTO context_pack_sources (
388
+ context_pack_id, source_id, source, boundary_json
389
+ ) VALUES (?, ?, ?, ?)`
390
+ );
391
+ for (const source of manifest.sources) {
392
+ insertSource.run(
393
+ manifest.contextPackId,
394
+ source.sourceId,
395
+ source.source,
396
+ JSON.stringify(source)
397
+ );
398
+ }
399
+ }).immediate();
400
+ }
401
+ getContextPack(contextPackId) {
402
+ return this.readContextPack("context_pack_id", contextPackId);
403
+ }
404
+ getContextPackByRun(runId) {
405
+ return this.readContextPack("run_id", runId);
406
+ }
407
+ readContextPack(column, value) {
408
+ const row = this.database.prepare(`SELECT manifest_json FROM context_packs WHERE ${column} = ?`).get(value);
409
+ return row ? JSON.parse(row.manifest_json) : null;
410
+ }
411
+ putTraceSegments(segments) {
412
+ const insert = this.database.prepare(
413
+ `INSERT INTO trace_segments (
414
+ segment_id, run_id, learning_scope_id, sequence, payload_json
415
+ ) VALUES (?, ?, ?, ?, ?)`
416
+ );
417
+ this.database.transaction(() => {
418
+ for (const segment of segments) {
419
+ insertImmutable(this.database, {
420
+ table: "trace_segments",
421
+ idColumn: "segment_id",
422
+ id: segment.segmentId,
423
+ payload: JSON.stringify(segment),
424
+ insert: () => insert.run(
425
+ segment.segmentId,
426
+ segment.runId,
427
+ segment.learningScopeId,
428
+ segment.sequence,
429
+ JSON.stringify(segment)
430
+ )
431
+ });
432
+ }
433
+ }).immediate();
434
+ }
435
+ listTraceSegments(runId) {
436
+ return this.readPayloadRows(
437
+ `SELECT payload_json FROM trace_segments
438
+ WHERE run_id = ? ORDER BY sequence, segment_id`,
439
+ runId
440
+ );
441
+ }
442
+ putEpisodes(episodes) {
443
+ const insert = this.database.prepare(
444
+ `INSERT INTO episodes (
445
+ episode_id, run_id, learning_scope_id, created_at, payload_json
446
+ ) VALUES (?, ?, ?, ?, ?)`
447
+ );
448
+ this.database.transaction(() => {
449
+ for (const episode of episodes) {
450
+ insertImmutable(this.database, {
451
+ table: "episodes",
452
+ idColumn: "episode_id",
453
+ id: episode.episodeId,
454
+ payload: JSON.stringify(episode),
455
+ insert: () => insert.run(
456
+ episode.episodeId,
457
+ episode.runId,
458
+ episode.learningScopeId,
459
+ episode.createdAt,
460
+ JSON.stringify(episode)
461
+ )
462
+ });
463
+ }
464
+ }).immediate();
465
+ }
466
+ listEpisodes(runId) {
467
+ return this.readPayloadRows(
468
+ `SELECT payload_json FROM episodes
469
+ WHERE run_id = ? ORDER BY created_at, episode_id`,
470
+ runId
471
+ );
472
+ }
473
+ putAnalysisReport(report) {
474
+ const payload = JSON.stringify(report);
475
+ insertImmutable(this.database, {
476
+ table: "analysis_reports",
477
+ idColumn: "report_id",
478
+ id: report.reportId,
479
+ payload,
480
+ insert: () => this.database.prepare(
481
+ `INSERT INTO analysis_reports (
482
+ report_id, run_id, attempt_number, role, created_at, payload_json
483
+ ) VALUES (?, ?, ?, ?, ?, ?)`
484
+ ).run(
485
+ report.reportId,
486
+ report.runId,
487
+ report.attemptNumber,
488
+ report.role,
489
+ report.createdAt,
490
+ payload
491
+ )
492
+ });
493
+ }
494
+ listAnalysisReports(runId) {
495
+ return this.readPayloadRows(
496
+ `SELECT payload_json FROM analysis_reports
497
+ WHERE run_id = ? ORDER BY attempt_number, created_at, report_id`,
498
+ runId
499
+ );
500
+ }
501
+ putRunAttempt(attempt) {
502
+ const existing = this.database.prepare(
503
+ "SELECT payload_json FROM evolution_run_attempts WHERE attempt_id = ?"
504
+ ).get(attempt.attemptId);
505
+ if (!existing) {
506
+ this.database.prepare(
507
+ `INSERT INTO evolution_run_attempts (
508
+ attempt_id, run_id, attempt_number, role, provider, status,
509
+ started_at, completed_at, payload_json
510
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
511
+ ).run(
512
+ attempt.attemptId,
513
+ attempt.runId,
514
+ attempt.attemptNumber,
515
+ attempt.role,
516
+ attempt.provider,
517
+ attempt.status,
518
+ attempt.startedAt,
519
+ attempt.completedAt,
520
+ JSON.stringify(attempt)
521
+ );
522
+ return;
523
+ }
524
+ const current = JSON.parse(existing.payload_json);
525
+ if (current.runId !== attempt.runId || current.attemptNumber !== attempt.attemptNumber || current.role !== attempt.role || current.provider !== attempt.provider || current.selectionReason !== attempt.selectionReason || current.startedAt !== attempt.startedAt) {
526
+ throw new Error("evolution_run_attempt_identity_conflict");
527
+ }
528
+ if (current.status !== "running" && current.status !== attempt.status) {
529
+ throw new Error("evolution_run_attempt_terminal");
530
+ }
531
+ this.database.prepare(
532
+ `UPDATE evolution_run_attempts
533
+ SET status = ?, completed_at = ?, payload_json = ?
534
+ WHERE attempt_id = ?`
535
+ ).run(
536
+ attempt.status,
537
+ attempt.completedAt,
538
+ JSON.stringify(attempt),
539
+ attempt.attemptId
540
+ );
541
+ }
542
+ listRunAttempts(runId) {
543
+ return this.readPayloadRows(
544
+ `SELECT payload_json FROM evolution_run_attempts
545
+ WHERE run_id = ? ORDER BY attempt_number, started_at, attempt_id`,
546
+ runId
547
+ );
548
+ }
549
+ putClaims(claims) {
550
+ const insert = this.database.prepare(
551
+ `INSERT INTO claims (
552
+ claim_id, run_id, learning_scope_id, topic_key, created_at, payload_json
553
+ ) VALUES (?, ?, ?, ?, ?, ?)`
554
+ );
555
+ this.database.transaction(() => {
556
+ for (const claim of claims) {
557
+ insertImmutable(this.database, {
558
+ table: "claims",
559
+ idColumn: "claim_id",
560
+ id: claim.claimId,
561
+ payload: JSON.stringify(claim),
562
+ insert: () => insert.run(
563
+ claim.claimId,
564
+ claim.runId,
565
+ claim.learningScopeId,
566
+ claim.topicKey,
567
+ claim.createdAt,
568
+ JSON.stringify(claim)
569
+ )
570
+ });
571
+ }
572
+ }).immediate();
573
+ }
574
+ listClaims(runId) {
575
+ return this.readPayloadRows(
576
+ `SELECT payload_json FROM claims
577
+ WHERE run_id = ? ORDER BY topic_key, claim_id`,
578
+ runId
579
+ );
580
+ }
581
+ putClaimNovelty(items) {
582
+ const insert = this.database.prepare(
583
+ `INSERT INTO claim_novelty (
584
+ claim_id, run_id, novelty, payload_json
585
+ ) VALUES (?, ?, ?, ?)`
586
+ );
587
+ this.database.transaction(() => {
588
+ for (const item of items) {
589
+ const claim = this.database.prepare("SELECT run_id FROM claims WHERE claim_id = ?").get(item.claimId);
590
+ if (!claim) throw new Error("evolution_claim_not_found");
591
+ insertImmutable(this.database, {
592
+ table: "claim_novelty",
593
+ idColumn: "claim_id",
594
+ id: item.claimId,
595
+ payload: JSON.stringify(item),
596
+ insert: () => insert.run(
597
+ item.claimId,
598
+ claim.run_id,
599
+ item.novelty,
600
+ JSON.stringify(item)
601
+ )
602
+ });
603
+ }
604
+ }).immediate();
605
+ }
606
+ listClaimNovelty(runId) {
607
+ return this.readPayloadRows(
608
+ `SELECT payload_json FROM claim_novelty
609
+ WHERE run_id = ? ORDER BY claim_id`,
610
+ runId
611
+ );
612
+ }
613
+ readPayloadRows(sql, value) {
614
+ const rows = this.database.prepare(sql).all(value);
615
+ return rows.map((row) => JSON.parse(row.payload_json));
616
+ }
617
+ };
618
+
619
+ // backend/src/evolution/storage/foundation-rules.ts
620
+ var EVOLUTION_ACTIVE_STAGES = [
621
+ "snapshotting",
622
+ "segmenting",
623
+ "independent_analysis",
624
+ "cross_questioning",
625
+ "adjudicating",
626
+ "novelty_check",
627
+ "validating"
628
+ ];
629
+ var EVOLUTION_TERMINAL_STAGES = [
630
+ "completed",
631
+ "no_material_novelty",
632
+ "partial",
633
+ "failed",
634
+ "cancelled",
635
+ "blocked"
636
+ ];
637
+ function evolutionTriggerPriority(type) {
638
+ if (type === "manual") return 0;
639
+ if (type === "event") return 1;
640
+ return 2;
641
+ }
642
+ function parseEvolutionTimestamp(value) {
643
+ const parsed = Date.parse(value);
644
+ if (!Number.isFinite(parsed)) throw new Error("evolution_invalid_timestamp");
645
+ return parsed;
646
+ }
647
+ function isAllowedEvolutionRunTransition(current, next) {
648
+ if (next === "partial" || next === "failed" || next === "blocked") {
649
+ return EVOLUTION_ACTIVE_STAGES.includes(current);
650
+ }
651
+ if (current === "snapshotting") return next === "segmenting";
652
+ if (current === "segmenting") return next === "independent_analysis";
653
+ if (current === "independent_analysis") {
654
+ return next === "cross_questioning";
655
+ }
656
+ if (current === "cross_questioning") {
657
+ return next === "adjudicating" || next === "novelty_check";
658
+ }
659
+ if (current === "adjudicating") return next === "novelty_check";
660
+ if (current === "novelty_check") return next === "validating";
661
+ if (current === "validating") {
662
+ return next === "completed" || next === "no_material_novelty";
663
+ }
664
+ return false;
665
+ }
666
+ function assertScheduleMaterialization(current, params) {
667
+ const trigger = params.run.trigger;
668
+ if (trigger.type !== "schedule" || trigger.scheduleId !== current.scheduleId || parseEvolutionTimestamp(trigger.dueAt) < parseEvolutionTimestamp(params.expectedNextDueAt) || parseEvolutionTimestamp(trigger.dueAt) > parseEvolutionTimestamp(params.now) || params.run.learningScopeId !== current.learningScopeId || params.nextSchedule.scheduleId !== current.scheduleId || params.nextSchedule.learningScopeId !== current.learningScopeId || params.nextSchedule.lastDueAt !== trigger.dueAt || params.nextSchedule.lastRunId !== params.run.runId) {
669
+ throw new Error("evolution_schedule_materialization_invalid");
670
+ }
671
+ }
672
+
673
+ // backend/src/evolution/storage/foundation-database-rows.ts
674
+ function toRun(row) {
675
+ return {
676
+ runId: row.run_id,
677
+ ...row.repository_json ? {
678
+ repository: JSON.parse(
679
+ row.repository_json
680
+ )
681
+ } : {},
682
+ learningScopeId: row.learning_scope_id,
683
+ trigger: JSON.parse(row.trigger_json),
684
+ profile: row.profile,
685
+ providerPolicy: row.provider_policy,
686
+ budget: JSON.parse(row.budget_json),
687
+ dataRange: JSON.parse(row.data_range_json),
688
+ stage: row.stage,
689
+ outcome: row.outcome,
690
+ createdAt: toIso(row.created_at_ms),
691
+ updatedAt: toIso(row.updated_at_ms),
692
+ startedAt: row.started_at_ms === null ? null : toIso(row.started_at_ms),
693
+ completedAt: row.completed_at_ms === null ? null : toIso(row.completed_at_ms),
694
+ attempt: row.attempt
695
+ };
696
+ }
697
+ function nullableTimestamp(value) {
698
+ return value === null ? null : parseEvolutionTimestamp(value);
699
+ }
700
+ function toIso(value) {
701
+ return new Date(value).toISOString();
702
+ }
703
+ function placeholders(count) {
704
+ return Array.from({ length: count }, () => "?").join(", ");
705
+ }
706
+
707
+ // backend/src/evolution/storage/foundation-database.ts
708
+ var GLOBAL_LEASE_KEY = "global-evolution-runner-v1";
709
+ var EvolutionFoundationDatabase = class {
710
+ constructor(database2) {
711
+ this.database = database2;
712
+ }
713
+ createRun(run) {
714
+ this.database.prepare(
715
+ `INSERT INTO evolution_runs (
716
+ run_id, learning_scope_id, trigger_type, priority, trigger_json,
717
+ profile, provider_policy, budget_json, data_range_json, stage,
718
+ outcome, created_at_ms, updated_at_ms, started_at_ms,
719
+ completed_at_ms, attempt, owner_id, fencing_token, repository_json
720
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?)`
721
+ ).run(
722
+ run.runId,
723
+ run.learningScopeId,
724
+ run.trigger.type,
725
+ evolutionTriggerPriority(run.trigger.type),
726
+ JSON.stringify(run.trigger),
727
+ run.profile,
728
+ run.providerPolicy,
729
+ JSON.stringify(run.budget),
730
+ JSON.stringify(run.dataRange),
731
+ run.stage,
732
+ run.outcome,
733
+ parseEvolutionTimestamp(run.createdAt),
734
+ parseEvolutionTimestamp(run.updatedAt),
735
+ nullableTimestamp(run.startedAt),
736
+ nullableTimestamp(run.completedAt),
737
+ run.attempt,
738
+ run.repository ? JSON.stringify(run.repository) : null
739
+ );
740
+ }
741
+ getRun(runId) {
742
+ const row = this.database.prepare("SELECT * FROM evolution_runs WHERE run_id = ?").get(runId);
743
+ return row ? this.presentRun(row) : null;
744
+ }
745
+ listRuns(query = {}) {
746
+ const conditions = [];
747
+ const params = [];
748
+ if (query.learningScopeId) {
749
+ conditions.push(
750
+ `(learning_scope_id = ? OR EXISTS (SELECT 1 FROM evolution_repository_bindings binding, json_each(binding.payload_json, '$.repositoryIds') item WHERE binding.kind = 'run' AND binding.id = evolution_runs.run_id AND item.value = ?))`
751
+ );
752
+ params.push(query.learningScopeId, query.learningScopeId);
753
+ }
754
+ if (query.stage) {
755
+ conditions.push("stage = ?");
756
+ params.push(query.stage);
757
+ }
758
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
759
+ const limit = Math.min(Math.max(query.limit ?? 100, 1), 200);
760
+ const rows = this.database.prepare(
761
+ `SELECT * FROM evolution_runs ${where}
762
+ ORDER BY created_at_ms DESC, run_id DESC LIMIT ?`
763
+ ).all(...params, limit);
764
+ return rows.map((row) => this.presentRun(row));
765
+ }
766
+ presentRun(row) {
767
+ const attribution = readRepositoryAttribution(
768
+ this.database,
769
+ "run",
770
+ row.run_id
771
+ );
772
+ return { ...toRun(row), ...attribution ? { attribution } : {} };
773
+ }
774
+ claimNextRun(params) {
775
+ const nowMs = parseEvolutionTimestamp(params.now);
776
+ return this.database.transaction(() => {
777
+ this.recoverExpiredRunsAt(nowMs);
778
+ const active = this.database.prepare(
779
+ `SELECT 1 FROM evolution_runs
780
+ WHERE stage IN (${placeholders(EVOLUTION_ACTIVE_STAGES.length)})
781
+ LIMIT 1`
782
+ ).get(...EVOLUTION_ACTIVE_STAGES);
783
+ if (active) return null;
784
+ const lease = this.getLease();
785
+ if (lease && lease.expires_at_ms > nowMs) return null;
786
+ const row = this.database.prepare(
787
+ `SELECT * FROM evolution_runs
788
+ WHERE stage = 'queued'
789
+ ORDER BY priority, created_at_ms, run_id
790
+ LIMIT 1`
791
+ ).get();
792
+ if (!row) return null;
793
+ const fencingToken = (lease?.fencing_token ?? 0) + 1;
794
+ const expiresAtMs = nowMs + params.leaseTtlMs;
795
+ this.database.prepare(
796
+ `INSERT INTO evolution_leases (
797
+ lease_key, owner_id, fencing_token, acquired_at_ms, expires_at_ms
798
+ ) VALUES (?, ?, ?, ?, ?)
799
+ ON CONFLICT(lease_key) DO UPDATE SET
800
+ owner_id = excluded.owner_id,
801
+ fencing_token = excluded.fencing_token,
802
+ acquired_at_ms = excluded.acquired_at_ms,
803
+ expires_at_ms = excluded.expires_at_ms`
804
+ ).run(
805
+ GLOBAL_LEASE_KEY,
806
+ params.ownerId,
807
+ fencingToken,
808
+ nowMs,
809
+ expiresAtMs
810
+ );
811
+ const result = this.database.prepare(
812
+ `UPDATE evolution_runs
813
+ SET stage = 'snapshotting', updated_at_ms = ?,
814
+ started_at_ms = COALESCE(started_at_ms, ?),
815
+ attempt = attempt + 1, owner_id = ?, fencing_token = ?
816
+ WHERE run_id = ? AND stage = 'queued'`
817
+ ).run(nowMs, nowMs, params.ownerId, fencingToken, row.run_id);
818
+ if (result.changes !== 1)
819
+ throw new Error("evolution_run_claim_conflict");
820
+ return {
821
+ run: this.requireRun(row.run_id),
822
+ ownerId: params.ownerId,
823
+ fencingToken,
824
+ leaseExpiresAt: toIso(expiresAtMs)
825
+ };
826
+ }).immediate();
827
+ }
828
+ heartbeatRunClaim(params) {
829
+ const nowMs = parseEvolutionTimestamp(params.now);
830
+ const expiresAtMs = nowMs + params.leaseTtlMs;
831
+ const result = this.database.prepare(
832
+ `UPDATE evolution_leases SET expires_at_ms = ?
833
+ WHERE lease_key = ? AND owner_id = ? AND fencing_token = ?
834
+ AND expires_at_ms > ?`
835
+ ).run(
836
+ expiresAtMs,
837
+ GLOBAL_LEASE_KEY,
838
+ params.ownerId,
839
+ params.fencingToken,
840
+ nowMs
841
+ );
842
+ if (result.changes !== 1) throw new Error("evolution_lease_lost");
843
+ return toIso(expiresAtMs);
844
+ }
845
+ transitionRun(transition) {
846
+ if (!isAllowedEvolutionRunTransition(
847
+ transition.expectedStage,
848
+ transition.nextStage
849
+ )) {
850
+ throw new Error("evolution_run_transition_invalid");
851
+ }
852
+ const nowMs = parseEvolutionTimestamp(transition.now);
853
+ return this.database.transaction(() => {
854
+ this.assertLease(transition.ownerId, transition.fencingToken, nowMs);
855
+ const current = this.requireRunRow(transition.runId);
856
+ if (current.stage !== transition.expectedStage || current.owner_id !== transition.ownerId || current.fencing_token !== transition.fencingToken) {
857
+ throw new Error("evolution_run_transition_conflict");
858
+ }
859
+ const terminal = EVOLUTION_TERMINAL_STAGES.includes(
860
+ transition.nextStage
861
+ );
862
+ const outcome = terminal ? transition.outcome ?? transition.nextStage : null;
863
+ this.database.prepare(
864
+ `UPDATE evolution_runs
865
+ SET stage = ?, outcome = ?, updated_at_ms = ?,
866
+ completed_at_ms = ?, owner_id = ?, fencing_token = ?
867
+ WHERE run_id = ?`
868
+ ).run(
869
+ transition.nextStage,
870
+ outcome,
871
+ nowMs,
872
+ terminal ? nowMs : null,
873
+ terminal ? null : transition.ownerId,
874
+ terminal ? null : transition.fencingToken,
875
+ transition.runId
876
+ );
877
+ if (terminal)
878
+ this.expireLease(transition.ownerId, transition.fencingToken, nowMs);
879
+ return this.requireRun(transition.runId);
880
+ }).immediate();
881
+ }
882
+ cancelRun(runId, now) {
883
+ const nowMs = parseEvolutionTimestamp(now);
884
+ return this.database.transaction(() => {
885
+ const current = this.requireRunRow(runId);
886
+ if (EVOLUTION_TERMINAL_STAGES.includes(current.stage)) {
887
+ return toRun(current);
888
+ }
889
+ this.database.prepare(
890
+ `UPDATE evolution_runs
891
+ SET stage = 'cancelled', outcome = 'cancelled',
892
+ updated_at_ms = ?, completed_at_ms = ?,
893
+ owner_id = NULL, fencing_token = NULL
894
+ WHERE run_id = ?`
895
+ ).run(nowMs, nowMs, runId);
896
+ if (current.owner_id && current.fencing_token) {
897
+ this.expireLease(current.owner_id, current.fencing_token, nowMs);
898
+ }
899
+ return this.requireRun(runId);
900
+ }).immediate();
901
+ }
902
+ recoverExpiredRuns(now) {
903
+ return this.database.transaction(
904
+ () => this.recoverExpiredRunsAt(parseEvolutionTimestamp(now))
905
+ ).immediate();
906
+ }
907
+ putSchedule(schedule) {
908
+ this.database.prepare(
909
+ `INSERT INTO evolution_schedules (
910
+ schedule_id, learning_scope_id, enabled, updated_at_ms, payload_json
911
+ ) VALUES (?, ?, ?, ?, ?)
912
+ ON CONFLICT(schedule_id) DO UPDATE SET
913
+ learning_scope_id = excluded.learning_scope_id,
914
+ enabled = excluded.enabled,
915
+ updated_at_ms = excluded.updated_at_ms,
916
+ payload_json = excluded.payload_json
917
+ WHERE excluded.updated_at_ms >= evolution_schedules.updated_at_ms`
918
+ ).run(
919
+ schedule.scheduleId,
920
+ schedule.learningScopeId,
921
+ schedule.enabled ? 1 : 0,
922
+ parseEvolutionTimestamp(schedule.updatedAt),
923
+ JSON.stringify(schedule)
924
+ );
925
+ }
926
+ getSchedule(scheduleId) {
927
+ const row = this.database.prepare(
928
+ "SELECT payload_json FROM evolution_schedules WHERE schedule_id = ?"
929
+ ).get(scheduleId);
930
+ return row ? JSON.parse(row.payload_json) : null;
931
+ }
932
+ listSchedules(learningScopeId) {
933
+ const rows = learningScopeId ? this.database.prepare(
934
+ `SELECT payload_json FROM evolution_schedules
935
+ WHERE learning_scope_id = ? ORDER BY updated_at_ms DESC`
936
+ ).all(learningScopeId) : this.database.prepare(
937
+ "SELECT payload_json FROM evolution_schedules ORDER BY updated_at_ms DESC"
938
+ ).all();
939
+ return rows.map((row) => JSON.parse(row.payload_json));
940
+ }
941
+ materializeDueSchedule(params) {
942
+ const nowMs = parseEvolutionTimestamp(params.now);
943
+ return this.database.transaction(() => {
944
+ const row = this.database.prepare(
945
+ "SELECT payload_json FROM evolution_schedules WHERE schedule_id = ?"
946
+ ).get(params.scheduleId);
947
+ if (!row) return false;
948
+ const current = JSON.parse(row.payload_json);
949
+ if (!current.enabled || current.nextDueAt !== params.expectedNextDueAt || parseEvolutionTimestamp(params.expectedNextDueAt) > nowMs) {
950
+ return false;
951
+ }
952
+ assertScheduleMaterialization(current, params);
953
+ this.createRun(params.run);
954
+ this.database.prepare(
955
+ `UPDATE evolution_schedules
956
+ SET learning_scope_id = ?, enabled = ?,
957
+ updated_at_ms = ?, payload_json = ?
958
+ WHERE schedule_id = ?`
959
+ ).run(
960
+ params.nextSchedule.learningScopeId,
961
+ params.nextSchedule.enabled ? 1 : 0,
962
+ parseEvolutionTimestamp(params.nextSchedule.updatedAt),
963
+ JSON.stringify(params.nextSchedule),
964
+ params.scheduleId
965
+ );
966
+ return true;
967
+ }).immediate();
968
+ }
969
+ deleteSchedule(scheduleId) {
970
+ return this.database.prepare("DELETE FROM evolution_schedules WHERE schedule_id = ?").run(scheduleId).changes === 1;
971
+ }
972
+ getWatermark(learningScopeId, source) {
973
+ const row = this.database.prepare(
974
+ `SELECT value, run_id, updated_at_ms FROM evolution_watermarks
975
+ WHERE learning_scope_id = ? AND source = ?`
976
+ ).get(learningScopeId, source);
977
+ return row ? {
978
+ learningScopeId,
979
+ source,
980
+ value: row.value,
981
+ runId: row.run_id,
982
+ updatedAt: toIso(row.updated_at_ms)
983
+ } : null;
984
+ }
985
+ putWatermark(params) {
986
+ const nowMs = parseEvolutionTimestamp(params.now);
987
+ this.database.transaction(() => {
988
+ this.assertLease(params.ownerId, params.fencingToken, nowMs);
989
+ const run = this.requireRunRow(params.watermark.runId);
990
+ if (run.stage !== "validating" || run.owner_id !== params.ownerId || run.fencing_token !== params.fencingToken || run.learning_scope_id !== params.watermark.learningScopeId) {
991
+ throw new Error("evolution_watermark_fence_mismatch");
992
+ }
993
+ this.database.prepare(
994
+ `INSERT INTO evolution_watermarks (
995
+ learning_scope_id, source, value, run_id, updated_at_ms
996
+ ) VALUES (?, ?, ?, ?, ?)
997
+ ON CONFLICT(learning_scope_id, source) DO UPDATE SET
998
+ value = excluded.value,
999
+ run_id = excluded.run_id,
1000
+ updated_at_ms = excluded.updated_at_ms`
1001
+ ).run(
1002
+ params.watermark.learningScopeId,
1003
+ params.watermark.source,
1004
+ params.watermark.value,
1005
+ params.watermark.runId,
1006
+ parseEvolutionTimestamp(params.watermark.updatedAt)
1007
+ );
1008
+ }).immediate();
1009
+ }
1010
+ finalizeRun(params, commitKnowledge) {
1011
+ const nowMs = parseEvolutionTimestamp(params.now);
1012
+ return this.database.transaction(() => {
1013
+ this.assertLease(params.ownerId, params.fencingToken, nowMs);
1014
+ const current = this.requireRunRow(params.runId);
1015
+ if (current.stage !== "validating" || current.owner_id !== params.ownerId || current.fencing_token !== params.fencingToken) {
1016
+ throw new Error("evolution_run_finalize_fence_mismatch");
1017
+ }
1018
+ commitKnowledge();
1019
+ this.database.prepare(
1020
+ `UPDATE evolution_runs
1021
+ SET stage = ?, outcome = ?, updated_at_ms = ?,
1022
+ completed_at_ms = ?, owner_id = NULL, fencing_token = NULL
1023
+ WHERE run_id = ?`
1024
+ ).run(params.outcome, params.outcome, nowMs, nowMs, params.runId);
1025
+ this.expireLease(params.ownerId, params.fencingToken, nowMs);
1026
+ return this.requireRun(params.runId);
1027
+ }).immediate();
1028
+ }
1029
+ recoverExpiredRunsAt(nowMs) {
1030
+ const result = this.database.prepare(
1031
+ `UPDATE evolution_runs
1032
+ SET stage = 'queued', updated_at_ms = ?,
1033
+ owner_id = NULL, fencing_token = NULL
1034
+ WHERE stage IN (${placeholders(EVOLUTION_ACTIVE_STAGES.length)})
1035
+ AND (
1036
+ owner_id IS NULL OR fencing_token IS NULL OR NOT EXISTS (
1037
+ SELECT 1 FROM evolution_leases
1038
+ WHERE lease_key = ? AND owner_id = evolution_runs.owner_id
1039
+ AND fencing_token = evolution_runs.fencing_token
1040
+ AND expires_at_ms > ?
1041
+ )
1042
+ )`
1043
+ ).run(nowMs, ...EVOLUTION_ACTIVE_STAGES, GLOBAL_LEASE_KEY, nowMs);
1044
+ return result.changes;
1045
+ }
1046
+ getLease() {
1047
+ return this.database.prepare(
1048
+ `SELECT owner_id, fencing_token, expires_at_ms
1049
+ FROM evolution_leases WHERE lease_key = ?`
1050
+ ).get(GLOBAL_LEASE_KEY) ?? null;
1051
+ }
1052
+ assertLease(ownerId, fencingToken, nowMs) {
1053
+ const lease = this.getLease();
1054
+ if (!lease || lease.owner_id !== ownerId || lease.fencing_token !== fencingToken || lease.expires_at_ms <= nowMs) {
1055
+ throw new Error("evolution_lease_lost");
1056
+ }
1057
+ }
1058
+ expireLease(ownerId, fencingToken, nowMs) {
1059
+ this.database.prepare(
1060
+ `UPDATE evolution_leases SET expires_at_ms = ?
1061
+ WHERE lease_key = ? AND owner_id = ? AND fencing_token = ?`
1062
+ ).run(nowMs, GLOBAL_LEASE_KEY, ownerId, fencingToken);
1063
+ }
1064
+ requireRun(runId) {
1065
+ return toRun(this.requireRunRow(runId));
1066
+ }
1067
+ requireRunRow(runId) {
1068
+ const row = this.database.prepare("SELECT * FROM evolution_runs WHERE run_id = ?").get(runId);
1069
+ if (!row) throw new Error("evolution_run_not_found");
1070
+ return row;
1071
+ }
1072
+ };
1073
+
1074
+ // backend/src/evolution/storage/knowledge-database.ts
1075
+ var EvolutionKnowledgeDatabase = class {
1076
+ constructor(database2, foundation) {
1077
+ this.database = database2;
1078
+ this.foundation = foundation;
1079
+ }
1080
+ listCandidates() {
1081
+ const rows = this.database.prepare(
1082
+ `SELECT payload_json
1083
+ FROM (
1084
+ SELECT payload_json,
1085
+ ROW_NUMBER() OVER (
1086
+ PARTITION BY asset_id
1087
+ ORDER BY updated_at DESC, rowid DESC
1088
+ ) AS current_revision
1089
+ FROM candidate_asset_revisions
1090
+ )
1091
+ WHERE current_revision = 1`
1092
+ ).all();
1093
+ const candidates = rows.map(
1094
+ (row) => JSON.parse(row.payload_json)
1095
+ );
1096
+ if (candidates.length === 0) return [];
1097
+ const bindings = this.database.prepare(
1098
+ `SELECT id, payload_json FROM evolution_repository_bindings
1099
+ WHERE kind = 'candidate' AND id IN (SELECT value FROM json_each(?))`
1100
+ ).all(
1101
+ JSON.stringify(candidates.map((candidate) => candidate.assetId))
1102
+ );
1103
+ const attributions = new Map(
1104
+ bindings.map((row) => [
1105
+ row.id,
1106
+ JSON.parse(row.payload_json)
1107
+ ])
1108
+ );
1109
+ return candidates.map((candidate) => {
1110
+ const attribution = attributions.get(candidate.assetId);
1111
+ return attribution ? { ...candidate, attribution } : candidate;
1112
+ });
1113
+ }
1114
+ putCandidate(candidate) {
1115
+ this.database.prepare(
1116
+ `INSERT OR IGNORE INTO candidate_asset_revisions
1117
+ (revision_id, asset_id, learning_scope_id, updated_at, payload_json)
1118
+ VALUES (?, ?, ?, ?, ?)`
1119
+ ).run(
1120
+ candidate.revisionId,
1121
+ candidate.assetId,
1122
+ candidate.learningScopeId,
1123
+ candidate.updatedAt,
1124
+ JSON.stringify(candidate)
1125
+ );
1126
+ }
1127
+ putInsightRevision(params) {
1128
+ this.database.transaction(() => this.insertInsightRevision(params)).immediate();
1129
+ }
1130
+ insertInsightRevision(params) {
1131
+ const current = this.database.prepare(
1132
+ `SELECT insight_id FROM insights
1133
+ WHERE learning_scope_id = ? AND topic_key = ?`
1134
+ ).get(params.insight.learningScopeId, params.insight.topicKey);
1135
+ if (current && current.insight_id !== params.insight.insightId) {
1136
+ throw new Error("evolution_insight_identity_conflict");
1137
+ }
1138
+ if (!current) {
1139
+ this.database.prepare(
1140
+ `INSERT INTO insights (
1141
+ insight_id, learning_scope_id, topic_key, current_revision_id,
1142
+ created_at, updated_at
1143
+ ) VALUES (?, ?, ?, ?, ?, ?)`
1144
+ ).run(
1145
+ params.insight.insightId,
1146
+ params.insight.learningScopeId,
1147
+ params.insight.topicKey,
1148
+ params.revision.revisionId,
1149
+ params.insight.createdAt,
1150
+ params.insight.updatedAt
1151
+ );
1152
+ }
1153
+ const revisionPayload = JSON.stringify(params.revision);
1154
+ insertImmutable(this.database, {
1155
+ table: "insight_revisions",
1156
+ idColumn: "revision_id",
1157
+ id: params.revision.revisionId,
1158
+ payload: revisionPayload,
1159
+ insert: () => this.database.prepare(
1160
+ `INSERT INTO insight_revisions (
1161
+ revision_id, insight_id, run_id, created_at, payload_json
1162
+ ) VALUES (?, ?, ?, ?, ?)`
1163
+ ).run(
1164
+ params.revision.revisionId,
1165
+ params.revision.insightId,
1166
+ params.revision.runId,
1167
+ params.revision.createdAt,
1168
+ revisionPayload
1169
+ )
1170
+ });
1171
+ for (const edge of params.contributionEdges) {
1172
+ const payload = JSON.stringify(edge);
1173
+ insertImmutable(this.database, {
1174
+ table: "contribution_edges",
1175
+ idColumn: "edge_id",
1176
+ id: edge.edgeId,
1177
+ payload,
1178
+ insert: () => this.database.prepare(
1179
+ `INSERT INTO contribution_edges (
1180
+ edge_id, insight_revision_id, evidence_id,
1181
+ availability, created_at, payload_json
1182
+ ) VALUES (?, ?, ?, ?, ?, ?)`
1183
+ ).run(
1184
+ edge.edgeId,
1185
+ edge.insightRevisionId,
1186
+ edge.evidenceId,
1187
+ edge.availability,
1188
+ edge.createdAt,
1189
+ payload
1190
+ )
1191
+ });
1192
+ }
1193
+ this.database.prepare(
1194
+ `UPDATE insights
1195
+ SET current_revision_id = ?, updated_at = ?
1196
+ WHERE insight_id = ? AND updated_at <= ?
1197
+ AND (? IS NULL OR current_revision_id = ?)`
1198
+ ).run(
1199
+ params.revision.revisionId,
1200
+ params.insight.updatedAt,
1201
+ params.insight.insightId,
1202
+ params.insight.updatedAt,
1203
+ params.previousRevisionId ?? null,
1204
+ params.previousRevisionId ?? null
1205
+ );
1206
+ }
1207
+ listInsights(learningScopeId) {
1208
+ const rows = learningScopeId ? this.database.prepare(
1209
+ `SELECT * FROM insights
1210
+ WHERE learning_scope_id = ? ORDER BY updated_at DESC`
1211
+ ).all(learningScopeId) : this.database.prepare("SELECT * FROM insights ORDER BY updated_at DESC").all();
1212
+ return rows.map((row) => this.toInsight(row));
1213
+ }
1214
+ getInsight(insightId) {
1215
+ const row = this.database.prepare("SELECT * FROM insights WHERE insight_id = ?").get(insightId);
1216
+ return row ? this.toInsight(row) : null;
1217
+ }
1218
+ listInsightRevisionsByRun(runId) {
1219
+ return this.readPayloadRows(
1220
+ `SELECT payload_json FROM insight_revisions
1221
+ WHERE run_id = ? ORDER BY created_at, revision_id`,
1222
+ runId
1223
+ );
1224
+ }
1225
+ listEvidenceDependencies() {
1226
+ const candidates = this.listCandidates();
1227
+ const candidatesByRevision = /* @__PURE__ */ new Map();
1228
+ for (const candidate of candidates) {
1229
+ const group = candidatesByRevision.get(candidate.insightRevisionId) ?? [];
1230
+ group.push(candidate);
1231
+ candidatesByRevision.set(candidate.insightRevisionId, group);
1232
+ }
1233
+ const insights = this.database.prepare("SELECT * FROM insights ORDER BY updated_at DESC").all();
1234
+ if (insights.length === 0) return [];
1235
+ const revisionIds = [
1236
+ .../* @__PURE__ */ new Set([
1237
+ ...insights.map((insight) => insight.current_revision_id),
1238
+ ...candidatesByRevision.keys()
1239
+ ])
1240
+ ];
1241
+ const rows = this.database.prepare(
1242
+ `SELECT insight_id, payload_json FROM insight_revisions
1243
+ WHERE revision_id IN (SELECT value FROM json_each(?))
1244
+ ORDER BY created_at, revision_id`
1245
+ ).all(JSON.stringify(revisionIds));
1246
+ const revisionsByInsight = /* @__PURE__ */ new Map();
1247
+ for (const row of rows) {
1248
+ const group = revisionsByInsight.get(row.insight_id) ?? [];
1249
+ group.push(JSON.parse(row.payload_json));
1250
+ revisionsByInsight.set(row.insight_id, group);
1251
+ }
1252
+ const dependencies = insights.flatMap(
1253
+ (insight) => (revisionsByInsight.get(insight.insight_id) ?? []).filter(
1254
+ (revision) => revision.insightId === insight.insight_id && (revision.revisionId === insight.current_revision_id || candidatesByRevision.has(revision.revisionId))
1255
+ ).map((revision) => ({
1256
+ insight: {
1257
+ insightId: insight.insight_id,
1258
+ learningScopeId: insight.learning_scope_id,
1259
+ topicKey: insight.topic_key,
1260
+ currentRevisionId: insight.current_revision_id,
1261
+ createdAt: insight.created_at,
1262
+ updatedAt: insight.updated_at
1263
+ },
1264
+ revision,
1265
+ candidates: candidatesByRevision.get(revision.revisionId) ?? []
1266
+ }))
1267
+ );
1268
+ if (dependencies.length === 0) return [];
1269
+ const edges = this.database.prepare(
1270
+ `SELECT insight_revision_id, payload_json FROM contribution_edges
1271
+ WHERE insight_revision_id IN (SELECT value FROM json_each(?)) ORDER BY edge_id`
1272
+ ).all(
1273
+ JSON.stringify(dependencies.map((item) => item.revision.revisionId))
1274
+ );
1275
+ const edgesByRevision = /* @__PURE__ */ new Map();
1276
+ for (const row of edges) {
1277
+ const group = edgesByRevision.get(row.insight_revision_id) ?? [];
1278
+ group.push(JSON.parse(row.payload_json));
1279
+ edgesByRevision.set(row.insight_revision_id, group);
1280
+ }
1281
+ return dependencies.map((dependency) => ({
1282
+ ...dependency,
1283
+ contributionEdges: edgesByRevision.get(dependency.revision.revisionId) ?? []
1284
+ }));
1285
+ }
1286
+ applyEvidenceReconciliation(reconciliation) {
1287
+ this.database.transaction(() => {
1288
+ for (const insight of reconciliation.insights) {
1289
+ this.insertInsightRevision(insight);
1290
+ }
1291
+ const revisionIds = new Set(
1292
+ reconciliation.insights.map((item) => item.revision.revisionId)
1293
+ );
1294
+ for (const candidate of reconciliation.candidates) {
1295
+ if (!revisionIds.has(candidate.insightRevisionId)) {
1296
+ throw new Error("evolution_reconciled_candidate_revision_mismatch");
1297
+ }
1298
+ this.putCandidate(candidate);
1299
+ }
1300
+ }).immediate();
1301
+ }
1302
+ commitRunKnowledge(params) {
1303
+ if (params.outcome === "no_material_novelty" && (params.insights.length > 0 || params.candidates.length > 0)) {
1304
+ throw new Error("evolution_no_material_novelty_has_output");
1305
+ }
1306
+ return this.foundation.finalizeRun(params, () => {
1307
+ for (const insight of params.insights) {
1308
+ if (insight.revision.runId !== params.runId) {
1309
+ throw new Error("evolution_insight_run_mismatch");
1310
+ }
1311
+ this.insertInsightRevision(insight);
1312
+ }
1313
+ const committedRevisionIds = new Set(
1314
+ params.insights.map((item) => item.revision.revisionId)
1315
+ );
1316
+ for (const candidate of params.candidates) {
1317
+ if (!committedRevisionIds.has(candidate.insightRevisionId)) {
1318
+ throw new Error("evolution_candidate_revision_mismatch");
1319
+ }
1320
+ this.putCandidate(candidate);
1321
+ }
1322
+ if (params.watermark) {
1323
+ if (params.watermark.runId !== params.runId) {
1324
+ throw new Error("evolution_watermark_run_mismatch");
1325
+ }
1326
+ this.database.prepare(
1327
+ `INSERT INTO evolution_watermarks (
1328
+ learning_scope_id, source, value, run_id, updated_at_ms
1329
+ ) VALUES (?, ?, ?, ?, ?)
1330
+ ON CONFLICT(learning_scope_id, source) DO UPDATE SET
1331
+ value = excluded.value,
1332
+ run_id = excluded.run_id,
1333
+ updated_at_ms = excluded.updated_at_ms`
1334
+ ).run(
1335
+ params.watermark.learningScopeId,
1336
+ params.watermark.source,
1337
+ params.watermark.value,
1338
+ params.watermark.runId,
1339
+ Date.parse(params.watermark.updatedAt)
1340
+ );
1341
+ }
1342
+ });
1343
+ }
1344
+ toInsight(row) {
1345
+ const membership = this.database.prepare(
1346
+ "SELECT canonical_insight_id FROM evolution_topic_lineage WHERE legacy_insight_id=?"
1347
+ ).get(row.insight_id);
1348
+ const members = membership ? this.database.prepare(
1349
+ "SELECT legacy_insight_id, status FROM evolution_topic_lineage WHERE canonical_insight_id=? ORDER BY legacy_insight_id"
1350
+ ).all(membership.canonical_insight_id) : [];
1351
+ const attribution = readRepositoryAttribution(
1352
+ this.database,
1353
+ "insight",
1354
+ row.insight_id
1355
+ );
1356
+ return {
1357
+ ...attribution ? { attribution } : {},
1358
+ ...membership ? {
1359
+ lineage: {
1360
+ canonicalInsightId: membership.canonical_insight_id,
1361
+ memberIds: members.map((member) => member.legacy_insight_id),
1362
+ status: members.some((member) => member.status === "contested") ? "contested" : "resolved"
1363
+ }
1364
+ } : {},
1365
+ insightId: row.insight_id,
1366
+ learningScopeId: row.learning_scope_id,
1367
+ .../^[a-f0-9]{64}$/u.test(row.learning_scope_id) ? { repositoryId: row.learning_scope_id } : {},
1368
+ topicKey: row.topic_key,
1369
+ currentRevisionId: row.current_revision_id,
1370
+ createdAt: row.created_at,
1371
+ updatedAt: row.updated_at,
1372
+ revisions: this.readPayloadRows(
1373
+ `SELECT payload_json FROM insight_revisions
1374
+ WHERE insight_id = ? OR insight_id IN (
1375
+ SELECT legacy_insight_id FROM evolution_topic_lineage WHERE canonical_insight_id = ?
1376
+ ) ORDER BY created_at, revision_id`,
1377
+ row.insight_id,
1378
+ row.insight_id
1379
+ )
1380
+ };
1381
+ }
1382
+ readPayloadRows(sql, ...values) {
1383
+ const rows = this.database.prepare(sql).all(...values);
1384
+ return rows.map((row) => JSON.parse(row.payload_json));
1385
+ }
1386
+ };
1387
+
1388
+ // backend/src/evolution/storage/migrations.ts
1389
+ var SCHEMA_VERSION = 6;
1390
+ var MINIMUM_WRITER_VERSION = 2;
1391
+ function migrateEvolutionDatabase(database2) {
1392
+ database2.exec(`
1393
+ CREATE TABLE IF NOT EXISTS evolution_metadata (
1394
+ key TEXT PRIMARY KEY,
1395
+ value TEXT NOT NULL
1396
+ )
1397
+ `);
1398
+ assertCompatibleWriter(database2);
1399
+ const version = database2.prepare("SELECT value FROM evolution_metadata WHERE key = ?").get("schemaVersion");
1400
+ if (version && Number(version.value) < 6) {
1401
+ for (const table of [
1402
+ "evolution_runs",
1403
+ "evolution_schedules",
1404
+ "insights",
1405
+ "candidate_asset_revisions",
1406
+ "evolution_policies",
1407
+ "evolution_watermarks"
1408
+ ]) {
1409
+ if (!database2.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(table))
1410
+ continue;
1411
+ if (database2.prepare(`SELECT 1 FROM ${table} LIMIT 1`).get())
1412
+ throw new Error("evolution_repository_migration_required");
1413
+ }
1414
+ }
1415
+ const state = database2.prepare("SELECT value FROM evolution_metadata WHERE key = ?").get("repositoryMigrationState");
1416
+ if (state && state.value !== "complete" || version && Number(version.value) >= 6 && !state)
1417
+ throw new Error("evolution_repository_migration_incomplete");
1418
+ database2.transaction(() => {
1419
+ database2.exec(`
1420
+ CREATE TABLE IF NOT EXISTS candidate_asset_revisions (
1421
+ revision_id TEXT PRIMARY KEY,
1422
+ asset_id TEXT NOT NULL,
1423
+ learning_scope_id TEXT NOT NULL,
1424
+ updated_at TEXT NOT NULL,
1425
+ payload_json TEXT NOT NULL
1426
+ );
1427
+ CREATE INDEX IF NOT EXISTS candidate_asset_scope_idx
1428
+ ON candidate_asset_revisions (learning_scope_id, asset_id, updated_at);
1429
+
1430
+ CREATE TABLE IF NOT EXISTS evolution_policies (
1431
+ learning_scope_id TEXT PRIMARY KEY,
1432
+ revision INTEGER NOT NULL,
1433
+ payload_json TEXT NOT NULL
1434
+ );
1435
+
1436
+ CREATE TABLE IF NOT EXISTS runtime_traces (
1437
+ trace_id TEXT PRIMARY KEY,
1438
+ run_id TEXT NOT NULL,
1439
+ created_at TEXT NOT NULL,
1440
+ payload_json TEXT NOT NULL
1441
+ );
1442
+ CREATE INDEX IF NOT EXISTS runtime_trace_run_idx
1443
+ ON runtime_traces (run_id, created_at);
1444
+
1445
+ CREATE TABLE IF NOT EXISTS runtime_trace_events (
1446
+ event_id TEXT PRIMARY KEY,
1447
+ trace_id TEXT NOT NULL
1448
+ REFERENCES runtime_traces(trace_id) ON DELETE CASCADE,
1449
+ at TEXT NOT NULL,
1450
+ payload_json TEXT NOT NULL
1451
+ );
1452
+ CREATE INDEX IF NOT EXISTS runtime_trace_event_trace_idx
1453
+ ON runtime_trace_events (trace_id, at);
1454
+
1455
+ CREATE TABLE IF NOT EXISTS evolution_runs (
1456
+ run_id TEXT PRIMARY KEY,
1457
+ learning_scope_id TEXT NOT NULL,
1458
+ trigger_type TEXT NOT NULL,
1459
+ priority INTEGER NOT NULL,
1460
+ trigger_json TEXT NOT NULL,
1461
+ profile TEXT NOT NULL,
1462
+ provider_policy TEXT NOT NULL,
1463
+ budget_json TEXT NOT NULL,
1464
+ data_range_json TEXT NOT NULL,
1465
+ stage TEXT NOT NULL,
1466
+ outcome TEXT,
1467
+ created_at_ms INTEGER NOT NULL,
1468
+ updated_at_ms INTEGER NOT NULL,
1469
+ started_at_ms INTEGER,
1470
+ completed_at_ms INTEGER,
1471
+ attempt INTEGER NOT NULL,
1472
+ owner_id TEXT,
1473
+ fencing_token INTEGER
1474
+ );
1475
+ CREATE INDEX IF NOT EXISTS evolution_run_queue_idx
1476
+ ON evolution_runs (stage, priority, created_at_ms);
1477
+ CREATE INDEX IF NOT EXISTS evolution_run_scope_idx
1478
+ ON evolution_runs (learning_scope_id, created_at_ms DESC);
1479
+
1480
+ CREATE TABLE IF NOT EXISTS evolution_leases (
1481
+ lease_key TEXT PRIMARY KEY,
1482
+ owner_id TEXT NOT NULL,
1483
+ fencing_token INTEGER NOT NULL,
1484
+ acquired_at_ms INTEGER NOT NULL,
1485
+ expires_at_ms INTEGER NOT NULL
1486
+ );
1487
+
1488
+ CREATE TABLE IF NOT EXISTS evolution_schedules (
1489
+ schedule_id TEXT PRIMARY KEY,
1490
+ learning_scope_id TEXT NOT NULL,
1491
+ enabled INTEGER NOT NULL,
1492
+ updated_at_ms INTEGER NOT NULL,
1493
+ payload_json TEXT NOT NULL
1494
+ );
1495
+ CREATE INDEX IF NOT EXISTS evolution_schedule_scope_idx
1496
+ ON evolution_schedules (learning_scope_id, updated_at_ms DESC);
1497
+
1498
+ CREATE TABLE IF NOT EXISTS evolution_watermarks (
1499
+ learning_scope_id TEXT NOT NULL,
1500
+ source TEXT NOT NULL,
1501
+ value TEXT NOT NULL,
1502
+ run_id TEXT NOT NULL,
1503
+ updated_at_ms INTEGER NOT NULL,
1504
+ PRIMARY KEY (learning_scope_id, source)
1505
+ );
1506
+
1507
+ CREATE TABLE IF NOT EXISTS context_packs (
1508
+ context_pack_id TEXT PRIMARY KEY,
1509
+ run_id TEXT NOT NULL UNIQUE,
1510
+ learning_scope_id TEXT NOT NULL,
1511
+ digest TEXT NOT NULL,
1512
+ created_at_ms INTEGER NOT NULL,
1513
+ manifest_json TEXT NOT NULL
1514
+ );
1515
+ CREATE INDEX IF NOT EXISTS context_pack_scope_idx
1516
+ ON context_packs (learning_scope_id, created_at_ms DESC);
1517
+ CREATE INDEX IF NOT EXISTS context_pack_digest_idx
1518
+ ON context_packs (digest);
1519
+
1520
+ CREATE TABLE IF NOT EXISTS context_pack_sources (
1521
+ context_pack_id TEXT NOT NULL
1522
+ REFERENCES context_packs(context_pack_id) ON DELETE CASCADE,
1523
+ source_id TEXT NOT NULL,
1524
+ source TEXT NOT NULL,
1525
+ boundary_json TEXT NOT NULL,
1526
+ PRIMARY KEY (context_pack_id, source_id)
1527
+ );
1528
+ CREATE TRIGGER IF NOT EXISTS context_packs_immutable_update
1529
+ BEFORE UPDATE ON context_packs
1530
+ BEGIN
1531
+ SELECT RAISE(ABORT, 'evolution_context_pack_immutable');
1532
+ END;
1533
+ CREATE TRIGGER IF NOT EXISTS context_pack_sources_immutable_update
1534
+ BEFORE UPDATE ON context_pack_sources
1535
+ BEGIN
1536
+ SELECT RAISE(ABORT, 'evolution_context_pack_source_immutable');
1537
+ END;
1538
+
1539
+ CREATE TABLE IF NOT EXISTS trace_segments (
1540
+ segment_id TEXT PRIMARY KEY,
1541
+ run_id TEXT NOT NULL,
1542
+ learning_scope_id TEXT NOT NULL,
1543
+ sequence INTEGER NOT NULL,
1544
+ payload_json TEXT NOT NULL
1545
+ );
1546
+ CREATE INDEX IF NOT EXISTS trace_segment_run_idx
1547
+ ON trace_segments (run_id, sequence);
1548
+
1549
+ CREATE TABLE IF NOT EXISTS episodes (
1550
+ episode_id TEXT PRIMARY KEY,
1551
+ run_id TEXT NOT NULL,
1552
+ learning_scope_id TEXT NOT NULL,
1553
+ created_at TEXT NOT NULL,
1554
+ payload_json TEXT NOT NULL
1555
+ );
1556
+ CREATE INDEX IF NOT EXISTS episode_run_idx
1557
+ ON episodes (run_id, created_at);
1558
+
1559
+ CREATE TABLE IF NOT EXISTS analysis_reports (
1560
+ report_id TEXT PRIMARY KEY,
1561
+ run_id TEXT NOT NULL,
1562
+ attempt_number INTEGER NOT NULL,
1563
+ role TEXT NOT NULL,
1564
+ created_at TEXT NOT NULL,
1565
+ payload_json TEXT NOT NULL
1566
+ );
1567
+ CREATE INDEX IF NOT EXISTS analysis_report_run_idx
1568
+ ON analysis_reports (run_id, attempt_number, created_at);
1569
+
1570
+ CREATE TABLE IF NOT EXISTS evolution_run_attempts (
1571
+ attempt_id TEXT PRIMARY KEY,
1572
+ run_id TEXT NOT NULL,
1573
+ attempt_number INTEGER NOT NULL,
1574
+ role TEXT NOT NULL,
1575
+ provider TEXT NOT NULL,
1576
+ status TEXT NOT NULL,
1577
+ started_at TEXT NOT NULL,
1578
+ completed_at TEXT,
1579
+ payload_json TEXT NOT NULL
1580
+ );
1581
+ CREATE INDEX IF NOT EXISTS evolution_run_attempt_run_idx
1582
+ ON evolution_run_attempts (run_id, attempt_number, started_at);
1583
+
1584
+ CREATE TABLE IF NOT EXISTS claims (
1585
+ claim_id TEXT PRIMARY KEY,
1586
+ run_id TEXT NOT NULL,
1587
+ learning_scope_id TEXT NOT NULL,
1588
+ topic_key TEXT NOT NULL,
1589
+ created_at TEXT NOT NULL,
1590
+ payload_json TEXT NOT NULL
1591
+ );
1592
+ CREATE INDEX IF NOT EXISTS claim_run_idx
1593
+ ON claims (run_id, topic_key);
1594
+
1595
+ CREATE TABLE IF NOT EXISTS claim_novelty (
1596
+ claim_id TEXT PRIMARY KEY
1597
+ REFERENCES claims(claim_id) ON DELETE CASCADE,
1598
+ run_id TEXT NOT NULL,
1599
+ novelty TEXT NOT NULL,
1600
+ payload_json TEXT NOT NULL
1601
+ );
1602
+ CREATE INDEX IF NOT EXISTS claim_novelty_run_idx
1603
+ ON claim_novelty (run_id, novelty);
1604
+
1605
+ CREATE TABLE IF NOT EXISTS insights (
1606
+ insight_id TEXT PRIMARY KEY,
1607
+ learning_scope_id TEXT NOT NULL,
1608
+ topic_key TEXT NOT NULL,
1609
+ current_revision_id TEXT NOT NULL,
1610
+ created_at TEXT NOT NULL,
1611
+ updated_at TEXT NOT NULL,
1612
+ UNIQUE (learning_scope_id, topic_key)
1613
+ );
1614
+ CREATE INDEX IF NOT EXISTS insight_scope_idx
1615
+ ON insights (learning_scope_id, updated_at DESC);
1616
+
1617
+ CREATE TABLE IF NOT EXISTS insight_revisions (
1618
+ revision_id TEXT PRIMARY KEY,
1619
+ insight_id TEXT NOT NULL
1620
+ REFERENCES insights(insight_id) ON DELETE CASCADE,
1621
+ run_id TEXT NOT NULL,
1622
+ created_at TEXT NOT NULL,
1623
+ payload_json TEXT NOT NULL
1624
+ );
1625
+ CREATE INDEX IF NOT EXISTS insight_revision_insight_idx
1626
+ ON insight_revisions (insight_id, created_at);
1627
+ CREATE INDEX IF NOT EXISTS insight_revision_run_idx
1628
+ ON insight_revisions (run_id, created_at);
1629
+
1630
+ CREATE TABLE IF NOT EXISTS contribution_edges (
1631
+ edge_id TEXT PRIMARY KEY,
1632
+ insight_revision_id TEXT NOT NULL
1633
+ REFERENCES insight_revisions(revision_id) ON DELETE CASCADE,
1634
+ evidence_id TEXT NOT NULL,
1635
+ availability TEXT NOT NULL,
1636
+ created_at TEXT NOT NULL,
1637
+ payload_json TEXT NOT NULL
1638
+ );
1639
+ CREATE INDEX IF NOT EXISTS contribution_edge_revision_idx
1640
+ ON contribution_edges (insight_revision_id, evidence_id);
1641
+
1642
+ CREATE TRIGGER IF NOT EXISTS trace_segments_immutable_update
1643
+ BEFORE UPDATE ON trace_segments
1644
+ BEGIN
1645
+ SELECT RAISE(ABORT, 'evolution_trace_segment_immutable');
1646
+ END;
1647
+ CREATE TRIGGER IF NOT EXISTS episodes_immutable_update
1648
+ BEFORE UPDATE ON episodes
1649
+ BEGIN
1650
+ SELECT RAISE(ABORT, 'evolution_episode_immutable');
1651
+ END;
1652
+ CREATE TRIGGER IF NOT EXISTS analysis_reports_immutable_update
1653
+ BEFORE UPDATE ON analysis_reports
1654
+ BEGIN
1655
+ SELECT RAISE(ABORT, 'evolution_analysis_report_immutable');
1656
+ END;
1657
+ CREATE TRIGGER IF NOT EXISTS claims_immutable_update
1658
+ BEFORE UPDATE ON claims
1659
+ BEGIN
1660
+ SELECT RAISE(ABORT, 'evolution_claim_immutable');
1661
+ END;
1662
+ CREATE TRIGGER IF NOT EXISTS claim_novelty_immutable_update
1663
+ BEFORE UPDATE ON claim_novelty
1664
+ BEGIN
1665
+ SELECT RAISE(ABORT, 'evolution_claim_novelty_immutable');
1666
+ END;
1667
+ CREATE TRIGGER IF NOT EXISTS insight_revisions_immutable_update
1668
+ BEFORE UPDATE ON insight_revisions
1669
+ BEGIN
1670
+ SELECT RAISE(ABORT, 'evolution_insight_revision_immutable');
1671
+ END;
1672
+ CREATE TRIGGER IF NOT EXISTS contribution_edges_immutable_update
1673
+ BEFORE UPDATE ON contribution_edges
1674
+ BEGIN
1675
+ SELECT RAISE(ABORT, 'evolution_contribution_edge_immutable');
1676
+ END;
1677
+ `);
1678
+ initializeEvolutionRepositories(database2);
1679
+ database2.prepare(
1680
+ "INSERT INTO evolution_metadata(key,value) VALUES (?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value"
1681
+ ).run("repositoryMigrationState", "complete");
1682
+ database2.prepare(
1683
+ `INSERT INTO evolution_metadata (key, value) VALUES (?, ?)
1684
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`
1685
+ ).run("schemaVersion", String(SCHEMA_VERSION));
1686
+ database2.prepare(
1687
+ "INSERT INTO evolution_metadata (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
1688
+ ).run("minimumWriterVersion", String(MINIMUM_WRITER_VERSION));
1689
+ }).immediate();
1690
+ }
1691
+ function assertCompatibleWriter(database2) {
1692
+ const minimumWriterVersion = database2.prepare("SELECT value FROM evolution_metadata WHERE key = ?").get("minimumWriterVersion");
1693
+ if (!minimumWriterVersion) return;
1694
+ const parsed = Number(minimumWriterVersion.value);
1695
+ if (!Number.isInteger(parsed) || parsed > MINIMUM_WRITER_VERSION) {
1696
+ throw new Error("evolution_schema_incompatible");
1697
+ }
1698
+ }
1699
+
1700
+ // backend/src/evolution/storage/database.ts
1701
+ var EvolutionActivationDatabase = class {
1702
+ database;
1703
+ foundation;
1704
+ artifactReads;
1705
+ artifacts;
1706
+ knowledge;
1707
+ constructor(databasePath) {
1708
+ (0, import_node_fs.mkdirSync)(import_node_path.default.dirname(databasePath), { recursive: true, mode: 448 });
1709
+ this.database = new import_better_sqlite3.default(databasePath);
1710
+ this.database.pragma("journal_mode = WAL");
1711
+ this.database.pragma("busy_timeout = 5000");
1712
+ this.database.pragma("foreign_keys = ON");
1713
+ try {
1714
+ migrateEvolutionDatabase(this.database);
1715
+ } catch (error) {
1716
+ this.database.close();
1717
+ throw error;
1718
+ }
1719
+ this.foundation = new EvolutionFoundationDatabase(this.database);
1720
+ this.artifacts = new EvolutionArtifactDatabase(this.database);
1721
+ this.artifactReads = new EvolutionArtifactReads(this.database);
1722
+ this.knowledge = new EvolutionKnowledgeDatabase(
1723
+ this.database,
1724
+ this.foundation
1725
+ );
1726
+ }
1727
+ repository(command) {
1728
+ return executeRepositoryCommand(this.database, this.foundation, command);
1729
+ }
1730
+ getPolicy(learningScopeId) {
1731
+ const row = this.database.prepare(
1732
+ "SELECT payload_json FROM evolution_policies WHERE learning_scope_id = ?"
1733
+ ).get(learningScopeId);
1734
+ return row ? JSON.parse(row.payload_json) : null;
1735
+ }
1736
+ putPolicy(policy) {
1737
+ const result = this.database.prepare(
1738
+ `INSERT INTO evolution_policies (learning_scope_id, revision, payload_json)
1739
+ VALUES (?, ?, ?)
1740
+ ON CONFLICT(learning_scope_id) DO UPDATE SET
1741
+ revision = excluded.revision,
1742
+ payload_json = excluded.payload_json
1743
+ WHERE excluded.revision > evolution_policies.revision`
1744
+ ).run(policy.learningScopeId, policy.revision, JSON.stringify(policy));
1745
+ if (result.changes !== 1) {
1746
+ throw new Error("evolution_policy_revision_conflict");
1747
+ }
1748
+ }
1749
+ listCandidates() {
1750
+ return this.knowledge.listCandidates();
1751
+ }
1752
+ putCandidate(candidate) {
1753
+ this.knowledge.putCandidate(candidate);
1754
+ }
1755
+ putRuntimeTrace(trace) {
1756
+ this.artifacts.putRuntimeTrace(trace);
1757
+ }
1758
+ appendRuntimeTraceEvent(event) {
1759
+ this.artifacts.appendRuntimeTraceEvent(event);
1760
+ }
1761
+ getRuntimeTrace(traceId) {
1762
+ return this.artifacts.getRuntimeTrace(traceId);
1763
+ }
1764
+ listRuntimeTraces(runId) {
1765
+ return this.artifacts.listRuntimeTraces(runId);
1766
+ }
1767
+ listRecentRuntimeTraces(learningScopeId, limit) {
1768
+ return this.artifacts.listRecentRuntimeTraces(learningScopeId, limit);
1769
+ }
1770
+ getArtifactOverview(runId) {
1771
+ return this.artifactReads.overview(runId);
1772
+ }
1773
+ getArtifactPage(runId, query) {
1774
+ return this.artifactReads.page(runId, query);
1775
+ }
1776
+ putContextPack(manifest) {
1777
+ this.artifacts.putContextPack(manifest);
1778
+ }
1779
+ getContextPack(contextPackId) {
1780
+ return this.artifacts.getContextPack(contextPackId);
1781
+ }
1782
+ getContextPackByRun(runId) {
1783
+ return this.artifacts.getContextPackByRun(runId);
1784
+ }
1785
+ putTraceSegments(segments) {
1786
+ this.artifacts.putTraceSegments(segments);
1787
+ }
1788
+ listTraceSegments(runId) {
1789
+ return this.artifacts.listTraceSegments(runId);
1790
+ }
1791
+ putEpisodes(episodes) {
1792
+ this.artifacts.putEpisodes(episodes);
1793
+ }
1794
+ listEpisodes(runId) {
1795
+ return this.artifacts.listEpisodes(runId);
1796
+ }
1797
+ putAnalysisReport(report) {
1798
+ this.artifacts.putAnalysisReport(report);
1799
+ }
1800
+ listAnalysisReports(runId) {
1801
+ return this.artifacts.listAnalysisReports(runId);
1802
+ }
1803
+ putRunAttempt(attempt) {
1804
+ this.artifacts.putRunAttempt(attempt);
1805
+ }
1806
+ listRunAttempts(runId) {
1807
+ return this.artifacts.listRunAttempts(runId);
1808
+ }
1809
+ putClaims(claims) {
1810
+ this.artifacts.putClaims(claims);
1811
+ }
1812
+ listClaims(runId) {
1813
+ return this.artifacts.listClaims(runId);
1814
+ }
1815
+ putClaimNovelty(items) {
1816
+ this.artifacts.putClaimNovelty(items);
1817
+ }
1818
+ listClaimNovelty(runId) {
1819
+ return this.artifacts.listClaimNovelty(runId);
1820
+ }
1821
+ putInsightRevision(params) {
1822
+ this.knowledge.putInsightRevision(params);
1823
+ }
1824
+ listInsights(learningScopeId) {
1825
+ return this.knowledge.listInsights(learningScopeId);
1826
+ }
1827
+ getInsight(insightId) {
1828
+ return this.knowledge.getInsight(insightId);
1829
+ }
1830
+ listInsightRevisionsByRun(runId) {
1831
+ return this.knowledge.listInsightRevisionsByRun(runId);
1832
+ }
1833
+ listEvidenceDependencies() {
1834
+ return this.knowledge.listEvidenceDependencies();
1835
+ }
1836
+ applyEvidenceReconciliation(reconciliation) {
1837
+ this.knowledge.applyEvidenceReconciliation(reconciliation);
1838
+ }
1839
+ commitRunKnowledge(params) {
1840
+ return this.knowledge.commitRunKnowledge(params);
1841
+ }
1842
+ finishRunningAttempts(runId, status, completedAt) {
1843
+ this.database.prepare(
1844
+ `UPDATE evolution_run_attempts
1845
+ SET status = ?, completed_at = ?,
1846
+ payload_json = json_set(
1847
+ payload_json,
1848
+ '$.status', ?,
1849
+ '$.completedAt', ?,
1850
+ '$.errorCode', ?
1851
+ )
1852
+ WHERE run_id = ? AND status = 'running'`
1853
+ ).run(status, completedAt, status, completedAt, "run_cancelled", runId);
1854
+ }
1855
+ createRun(run) {
1856
+ this.foundation.createRun(run);
1857
+ }
1858
+ getRun(runId) {
1859
+ return this.foundation.getRun(runId);
1860
+ }
1861
+ listRuns(query) {
1862
+ return this.foundation.listRuns(query);
1863
+ }
1864
+ claimNextRun(params) {
1865
+ return this.foundation.claimNextRun(params);
1866
+ }
1867
+ heartbeatRunClaim(params) {
1868
+ return this.foundation.heartbeatRunClaim(params);
1869
+ }
1870
+ transitionRun(transition) {
1871
+ return this.foundation.transitionRun(transition);
1872
+ }
1873
+ cancelRun(runId, now) {
1874
+ const run = this.foundation.cancelRun(runId, now);
1875
+ this.finishRunningAttempts(runId, "cancelled", now);
1876
+ return run;
1877
+ }
1878
+ recoverExpiredRuns(now) {
1879
+ const recovered = this.foundation.recoverExpiredRuns(now);
1880
+ if (recovered > 0) {
1881
+ this.database.prepare(
1882
+ `UPDATE evolution_run_attempts
1883
+ SET status = 'abandoned', completed_at = ?,
1884
+ payload_json = json_set(
1885
+ payload_json,
1886
+ '$.status', 'abandoned',
1887
+ '$.completedAt', ?,
1888
+ '$.errorCode', 'backend_recovered_unknown_call'
1889
+ )
1890
+ WHERE status = 'running'
1891
+ AND run_id IN (
1892
+ SELECT run_id FROM evolution_runs WHERE stage = 'queued'
1893
+ )`
1894
+ ).run(now, now);
1895
+ }
1896
+ return recovered;
1897
+ }
1898
+ putSchedule(schedule) {
1899
+ this.foundation.putSchedule(schedule);
1900
+ }
1901
+ getSchedule(scheduleId) {
1902
+ return this.foundation.getSchedule(scheduleId);
1903
+ }
1904
+ listSchedules(learningScopeId) {
1905
+ return this.foundation.listSchedules(learningScopeId);
1906
+ }
1907
+ materializeDueSchedule(params) {
1908
+ return this.foundation.materializeDueSchedule(params);
1909
+ }
1910
+ deleteSchedule(scheduleId) {
1911
+ return this.foundation.deleteSchedule(scheduleId);
1912
+ }
1913
+ getWatermark(learningScopeId, source) {
1914
+ return this.foundation.getWatermark(learningScopeId, source);
1915
+ }
1916
+ putWatermark(params) {
1917
+ this.foundation.putWatermark(params);
1918
+ }
1919
+ integrity() {
1920
+ const result = this.database.pragma("quick_check");
1921
+ return result.every((row) => row.quick_check === "ok");
1922
+ }
1923
+ close() {
1924
+ this.database.close();
1925
+ }
1926
+ };
1927
+
1928
+ // backend/src/evolution/storage/sqlite-worker.ts
1929
+ if (!import_node_worker_threads.parentPort) throw new Error("evolution_worker_parent_port_required");
1930
+ var port = import_node_worker_threads.parentPort;
1931
+ var database = new EvolutionActivationDatabase(
1932
+ import_node_worker_threads.workerData.databasePath
1933
+ );
1934
+ function execute(command) {
1935
+ switch (command.op) {
1936
+ case "repository":
1937
+ return database.repository(command.command);
1938
+ case "list-candidates":
1939
+ return database.listCandidates();
1940
+ case "put-candidate":
1941
+ database.putCandidate(command.candidate);
1942
+ return true;
1943
+ case "get-policy":
1944
+ return database.getPolicy(command.learningScopeId);
1945
+ case "put-policy":
1946
+ database.putPolicy(command.policy);
1947
+ return true;
1948
+ case "put-trace":
1949
+ database.putRuntimeTrace(command.trace);
1950
+ return true;
1951
+ case "append-trace-event":
1952
+ database.appendRuntimeTraceEvent(command.event);
1953
+ return true;
1954
+ case "get-trace":
1955
+ return database.getRuntimeTrace(command.traceId);
1956
+ case "list-traces":
1957
+ return database.listRuntimeTraces(command.runId);
1958
+ case "list-recent-traces":
1959
+ return database.listRecentRuntimeTraces(
1960
+ command.learningScopeId,
1961
+ command.limit
1962
+ );
1963
+ case "artifact-overview":
1964
+ return database.getArtifactOverview(command.runId);
1965
+ case "artifact-page":
1966
+ return database.getArtifactPage(command.runId, command.query);
1967
+ case "put-context-pack":
1968
+ database.putContextPack(command.manifest);
1969
+ return true;
1970
+ case "get-context-pack":
1971
+ return database.getContextPack(command.contextPackId);
1972
+ case "get-context-pack-by-run":
1973
+ return database.getContextPackByRun(command.runId);
1974
+ case "put-trace-segments":
1975
+ database.putTraceSegments(command.segments);
1976
+ return true;
1977
+ case "list-trace-segments":
1978
+ return database.listTraceSegments(command.runId);
1979
+ case "put-episodes":
1980
+ database.putEpisodes(command.episodes);
1981
+ return true;
1982
+ case "list-episodes":
1983
+ return database.listEpisodes(command.runId);
1984
+ case "put-analysis-report":
1985
+ database.putAnalysisReport(command.report);
1986
+ return true;
1987
+ case "list-analysis-reports":
1988
+ return database.listAnalysisReports(command.runId);
1989
+ case "put-run-attempt":
1990
+ database.putRunAttempt(command.attempt);
1991
+ return true;
1992
+ case "list-run-attempts":
1993
+ return database.listRunAttempts(command.runId);
1994
+ case "put-claims":
1995
+ database.putClaims(command.claims);
1996
+ return true;
1997
+ case "list-claims":
1998
+ return database.listClaims(command.runId);
1999
+ case "put-claim-novelty":
2000
+ database.putClaimNovelty(command.items);
2001
+ return true;
2002
+ case "list-claim-novelty":
2003
+ return database.listClaimNovelty(command.runId);
2004
+ case "put-insight-revision":
2005
+ database.putInsightRevision(command);
2006
+ return true;
2007
+ case "list-insights":
2008
+ return database.listInsights(command.learningScopeId);
2009
+ case "get-insight":
2010
+ return database.getInsight(command.insightId);
2011
+ case "list-insight-revisions-by-run":
2012
+ return database.listInsightRevisionsByRun(command.runId);
2013
+ case "list-evidence-dependencies":
2014
+ return database.listEvidenceDependencies();
2015
+ case "apply-evidence-reconciliation":
2016
+ database.applyEvidenceReconciliation(command.reconciliation);
2017
+ return true;
2018
+ case "commit-run-knowledge":
2019
+ return database.commitRunKnowledge(command.params);
2020
+ case "create-run":
2021
+ database.createRun(command.run);
2022
+ return true;
2023
+ case "get-run":
2024
+ return database.getRun(command.runId);
2025
+ case "list-runs":
2026
+ return database.listRuns(command.query);
2027
+ case "claim-next-run":
2028
+ return database.claimNextRun(command);
2029
+ case "heartbeat-run-claim":
2030
+ return database.heartbeatRunClaim(command);
2031
+ case "transition-run":
2032
+ return database.transitionRun(command.transition);
2033
+ case "cancel-run":
2034
+ return database.cancelRun(command.runId, command.now);
2035
+ case "recover-expired-runs":
2036
+ return database.recoverExpiredRuns(command.now);
2037
+ case "put-schedule":
2038
+ database.putSchedule(command.schedule);
2039
+ return true;
2040
+ case "get-schedule":
2041
+ return database.getSchedule(command.scheduleId);
2042
+ case "list-schedules":
2043
+ return database.listSchedules(command.learningScopeId);
2044
+ case "materialize-due-schedule":
2045
+ return database.materializeDueSchedule(command.params);
2046
+ case "delete-schedule":
2047
+ return database.deleteSchedule(command.scheduleId);
2048
+ case "get-watermark":
2049
+ return database.getWatermark(command.learningScopeId, command.source);
2050
+ case "put-watermark":
2051
+ database.putWatermark(command);
2052
+ return true;
2053
+ case "integrity":
2054
+ return database.integrity();
2055
+ case "close":
2056
+ database.close();
2057
+ return true;
2058
+ }
2059
+ }
2060
+ port.on("message", (command) => {
2061
+ let response;
2062
+ try {
2063
+ response = { id: command.id, ok: true, result: execute(command) };
2064
+ } catch (error) {
2065
+ response = {
2066
+ id: command.id,
2067
+ ok: false,
2068
+ error: error instanceof Error ? error.message : String(error)
2069
+ };
2070
+ }
2071
+ port.postMessage(response);
2072
+ if (command.op === "close") port.close();
2073
+ });