@inerrata-corporation/errata 2.0.22-dev.4669 → 2.0.22-dev.4676
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/consolidate-worker.mjs +148 -38
- package/errata.mjs +339 -68
- package/generalize-worker.mjs +148 -38
- package/package.json +1 -1
- package/pass-worker.mjs +250 -43
- package/resources/context-plugin/.codex-plugin/plugin.json +1 -1
- package/resources/context-plugin/SHA256SUMS +1 -1
package/errata.mjs
CHANGED
|
@@ -18932,6 +18932,41 @@ var init_wm_calibration = __esm({
|
|
|
18932
18932
|
}
|
|
18933
18933
|
});
|
|
18934
18934
|
|
|
18935
|
+
// ../../packages/local-graph/src/exposure-attrs.ts
|
|
18936
|
+
function pickExposure(attrs) {
|
|
18937
|
+
const out2 = {};
|
|
18938
|
+
for (const k of EXPOSURE_ATTRS) if (attrs[k] !== void 0) out2[k] = attrs[k];
|
|
18939
|
+
return out2;
|
|
18940
|
+
}
|
|
18941
|
+
function exposureDocSql(key) {
|
|
18942
|
+
return `coalesce((SELECT x.attrs_json FROM node_exposure x WHERE x.id = nodes.id AND json_type(x.attrs_json, '$.${key}') IS NOT NULL), attrs_json)`;
|
|
18943
|
+
}
|
|
18944
|
+
var EXPOSURE_ATTRS, EXPOSURE_SCOPE, EXPOSURE_KEYS, isExposureAttr;
|
|
18945
|
+
var init_exposure_attrs = __esm({
|
|
18946
|
+
"../../packages/local-graph/src/exposure-attrs.ts"() {
|
|
18947
|
+
"use strict";
|
|
18948
|
+
EXPOSURE_ATTRS = [
|
|
18949
|
+
"shownCount",
|
|
18950
|
+
"evictedCount",
|
|
18951
|
+
"firstShownAt",
|
|
18952
|
+
"firstEvictedAt",
|
|
18953
|
+
"firstShownAtSeq",
|
|
18954
|
+
"lastShownAtSeq",
|
|
18955
|
+
"lastEvictedAtSeq",
|
|
18956
|
+
"shownSinceTouch",
|
|
18957
|
+
"shownSinceTouchAt",
|
|
18958
|
+
"exposureLog",
|
|
18959
|
+
"exposureLogStart",
|
|
18960
|
+
"exposureLogSince",
|
|
18961
|
+
"exposureFirst",
|
|
18962
|
+
"exposureTrimmed"
|
|
18963
|
+
];
|
|
18964
|
+
EXPOSURE_SCOPE = "exposure";
|
|
18965
|
+
EXPOSURE_KEYS = new Set(EXPOSURE_ATTRS);
|
|
18966
|
+
isExposureAttr = (key) => EXPOSURE_KEYS.has(key);
|
|
18967
|
+
}
|
|
18968
|
+
});
|
|
18969
|
+
|
|
18935
18970
|
// ../../packages/local-graph/src/history-cache-floor.ts
|
|
18936
18971
|
function installHistoryCacheFloor(db) {
|
|
18937
18972
|
const key = HISTORY_CACHE_FLOOR_KEY;
|
|
@@ -19252,31 +19287,6 @@ var init_text_index = __esm({
|
|
|
19252
19287
|
}
|
|
19253
19288
|
});
|
|
19254
19289
|
|
|
19255
|
-
// ../../packages/local-graph/src/exposure-attrs.ts
|
|
19256
|
-
var EXPOSURE_ATTRS, EXPOSURE_SCOPE;
|
|
19257
|
-
var init_exposure_attrs = __esm({
|
|
19258
|
-
"../../packages/local-graph/src/exposure-attrs.ts"() {
|
|
19259
|
-
"use strict";
|
|
19260
|
-
EXPOSURE_ATTRS = [
|
|
19261
|
-
"shownCount",
|
|
19262
|
-
"evictedCount",
|
|
19263
|
-
"firstShownAt",
|
|
19264
|
-
"firstEvictedAt",
|
|
19265
|
-
"firstShownAtSeq",
|
|
19266
|
-
"lastShownAtSeq",
|
|
19267
|
-
"lastEvictedAtSeq",
|
|
19268
|
-
"shownSinceTouch",
|
|
19269
|
-
"shownSinceTouchAt",
|
|
19270
|
-
"exposureLog",
|
|
19271
|
-
"exposureLogStart",
|
|
19272
|
-
"exposureLogSince",
|
|
19273
|
-
"exposureFirst",
|
|
19274
|
-
"exposureTrimmed"
|
|
19275
|
-
];
|
|
19276
|
-
EXPOSURE_SCOPE = "exposure";
|
|
19277
|
-
}
|
|
19278
|
-
});
|
|
19279
|
-
|
|
19280
19290
|
// ../../packages/local-graph/src/change-feed.ts
|
|
19281
19291
|
function installChangeFeed(db) {
|
|
19282
19292
|
if (changeFeedInstalled(db)) return;
|
|
@@ -19335,6 +19345,16 @@ function readChangedNodeIds(db, sinceSeq, labels) {
|
|
|
19335
19345
|
const rows = db.prepare(`SELECT DISTINCT id FROM change_log WHERE change_seq > ? AND kind = 'node' AND label IN (${labels.map(() => "?").join(",")})`).all(sinceSeq, ...labels);
|
|
19336
19346
|
return rows.map((r) => r.id);
|
|
19337
19347
|
}
|
|
19348
|
+
function readChangedAmong(db, sinceSeq, ids) {
|
|
19349
|
+
if (!changeLogCovers(db, sinceSeq)) return null;
|
|
19350
|
+
const out2 = [];
|
|
19351
|
+
for (let i2 = 0; i2 < ids.length; i2 += 500) {
|
|
19352
|
+
const chunk = ids.slice(i2, i2 + 500);
|
|
19353
|
+
const rows = db.prepare(`SELECT DISTINCT id FROM change_log WHERE change_seq > ? AND kind = 'node' AND id IN (${chunk.map(() => "?").join(",")})`).all(sinceSeq, ...chunk);
|
|
19354
|
+
for (const r of rows) out2.push(r.id);
|
|
19355
|
+
}
|
|
19356
|
+
return out2;
|
|
19357
|
+
}
|
|
19338
19358
|
function readLineageChangedFiles(db, sinceSeq) {
|
|
19339
19359
|
if (!changeLogCovers(db, sinceSeq)) return null;
|
|
19340
19360
|
const rows = db.prepare(LINEAGE_CHANGED_FILES_SQL).all({ s: sinceSeq });
|
|
@@ -20536,8 +20556,11 @@ function compileNodeWhere(q) {
|
|
|
20536
20556
|
}
|
|
20537
20557
|
return { where: conds.join(" AND "), params };
|
|
20538
20558
|
}
|
|
20539
|
-
function attrValueSql(p) {
|
|
20540
|
-
return `CASE json_type(
|
|
20559
|
+
function attrValueSql(p, doc = "attrs_json") {
|
|
20560
|
+
return `CASE json_type(${doc}, ${p}) WHEN 'integer' THEN CAST(json_extract(${doc}, ${p}) AS REAL) ELSE json_extract(${doc}, ${p}) END`;
|
|
20561
|
+
}
|
|
20562
|
+
function attrDocSql(key) {
|
|
20563
|
+
return isExposureAttr(key) ? exposureDocSql(key) : "attrs_json";
|
|
20541
20564
|
}
|
|
20542
20565
|
function nodeSelectFrom(q) {
|
|
20543
20566
|
if (q.indexedBy) return `nodes INDEXED BY ${selectIndex(q.indexedBy)}`;
|
|
@@ -20550,7 +20573,7 @@ function nodeSelectFrom(q) {
|
|
|
20550
20573
|
function compileNodeSelect(q) {
|
|
20551
20574
|
const { where, params } = compileNodeWhere(q);
|
|
20552
20575
|
const attrs = q.attrs ?? [];
|
|
20553
|
-
const attrCols = attrs.map((k, i2) => `, ${attrValueSql(path(k))} AS a${i2}, json_type(
|
|
20576
|
+
const attrCols = attrs.map((k, i2) => `, ${attrValueSql(path(k), attrDocSql(k))} AS a${i2}, json_type(${attrDocSql(k)}, ${path(k)}) AS t${i2}`).join("");
|
|
20554
20577
|
let order;
|
|
20555
20578
|
if (q.orderBy && "column" in q.orderBy) {
|
|
20556
20579
|
order = `${column(q.orderBy.column)} ${q.orderBy.desc ? "DESC" : "ASC"}, rowid`;
|
|
@@ -20616,6 +20639,7 @@ var SELECT_INDEXES, EMBEDDING_DIM_SQL, KEY, COLUMNS;
|
|
|
20616
20639
|
var init_node_select = __esm({
|
|
20617
20640
|
"../../packages/local-graph/src/node-select.ts"() {
|
|
20618
20641
|
"use strict";
|
|
20642
|
+
init_exposure_attrs();
|
|
20619
20643
|
SELECT_INDEXES = [
|
|
20620
20644
|
"nodes_live_local_community",
|
|
20621
20645
|
"nodes_live_fold_candidate",
|
|
@@ -20668,7 +20692,7 @@ function graphStoreNeedsPreparation(path3) {
|
|
|
20668
20692
|
if (!indexes.has(match2[1])) return true;
|
|
20669
20693
|
}
|
|
20670
20694
|
if (!changeFeedInstalled(db)) return true;
|
|
20671
|
-
return [SESSION_REPAIR_KEY, HISTORY_CACHE_FLOOR_KEY, EDIT_PLACEHOLDER_FLOOR_KEY, CLOUD_ATTR_COMPACTION_KEY, HISTORY_ATTR_SLIM_KEY, TEXT_INDEX_KEY, LINEAGE_INTEGRITY_KEY].some((key) => !db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
20695
|
+
return [SESSION_REPAIR_KEY, HISTORY_CACHE_FLOOR_KEY, EDIT_PLACEHOLDER_FLOOR_KEY, CLOUD_ATTR_COMPACTION_KEY, HISTORY_ATTR_SLIM_KEY, TEXT_INDEX_KEY, LINEAGE_INTEGRITY_KEY, EXPOSURE_SIDE_KEY].some((key) => !db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key));
|
|
20672
20696
|
} catch {
|
|
20673
20697
|
return true;
|
|
20674
20698
|
} finally {
|
|
@@ -20735,13 +20759,14 @@ function rowToEdge(r) {
|
|
|
20735
20759
|
function openGraphStore(opts) {
|
|
20736
20760
|
return new SqliteGraphStore(opts);
|
|
20737
20761
|
}
|
|
20738
|
-
var PAGE_RANK_SCALE_KEY, TEXT_SEARCH_COLUMNS, LOCAL_RULE_OVERRIDES, SCHEMA_VERSION, SESSION_REPAIR_KEY, SESSION_EVIDENCE_PREDICATE, SCHEMA_SQL, TEMPORAL_INDEX_SQL, FINGERPRINT_INDEXED_LABELS, NODE_LABELS_CHUNK, PRIOR_TAG_MARKER, SqliteGraphStore;
|
|
20762
|
+
var PAGE_RANK_SCALE_KEY, TEXT_SEARCH_COLUMNS, LOCAL_RULE_OVERRIDES, SCHEMA_VERSION, SESSION_REPAIR_KEY, EXPOSURE_SIDE_KEY, SESSION_EVIDENCE_PREDICATE, SCHEMA_SQL, TEMPORAL_INDEX_SQL, FINGERPRINT_INDEXED_LABELS, NODE_LABELS_CHUNK, PRIOR_TAG_MARKER, SqliteGraphStore;
|
|
20739
20763
|
var init_store = __esm({
|
|
20740
20764
|
"../../packages/local-graph/src/store.ts"() {
|
|
20741
20765
|
"use strict";
|
|
20742
20766
|
init_src2();
|
|
20743
20767
|
init_src();
|
|
20744
20768
|
init_wm_calibration();
|
|
20769
|
+
init_exposure_attrs();
|
|
20745
20770
|
init_history_cache_floor();
|
|
20746
20771
|
init_session_evidence();
|
|
20747
20772
|
init_edit_placeholder_retirement();
|
|
@@ -20786,6 +20811,7 @@ var init_store = __esm({
|
|
|
20786
20811
|
};
|
|
20787
20812
|
SCHEMA_VERSION = 6;
|
|
20788
20813
|
SESSION_REPAIR_KEY = "session-evidence-v1";
|
|
20814
|
+
EXPOSURE_SIDE_KEY = "exposure-side-rows-1";
|
|
20789
20815
|
SESSION_EVIDENCE_PREDICATE = SESSION_EVIDENCE_FIELDS.map((field) => `instr(attrs_json, '${JSON.stringify(field)}') > 0`).join(" OR ");
|
|
20790
20816
|
SCHEMA_SQL = `
|
|
20791
20817
|
CREATE TABLE IF NOT EXISTS schema_version (
|
|
@@ -20849,8 +20875,13 @@ CREATE TABLE IF NOT EXISTS nodes (
|
|
|
20849
20875
|
);
|
|
20850
20876
|
|
|
20851
20877
|
CREATE INDEX IF NOT EXISTS nodes_label ON nodes(label);
|
|
20852
|
-
|
|
20853
|
-
|
|
20878
|
+
-- Dropped: no query plans through them (every prepared statement across the
|
|
20879
|
+
-- local-graph, indexer, context-writer, generalizer and daemon suites was
|
|
20880
|
+
-- planned with and without them, 2026-10-21), and each write that touches
|
|
20881
|
+
-- memory_tier / page_rank (every node upsert, every rescore) paid to maintain
|
|
20882
|
+
-- them. nodes_live_page_rank serves the live page-rank orderings.
|
|
20883
|
+
DROP INDEX IF EXISTS nodes_memory_tier;
|
|
20884
|
+
DROP INDEX IF EXISTS nodes_page_rank;
|
|
20854
20885
|
|
|
20855
20886
|
CREATE TABLE IF NOT EXISTS edges (
|
|
20856
20887
|
id TEXT PRIMARY KEY,
|
|
@@ -20872,7 +20903,10 @@ CREATE TABLE IF NOT EXISTS edges (
|
|
|
20872
20903
|
FOREIGN KEY (to_id) REFERENCES nodes(id) ON DELETE CASCADE
|
|
20873
20904
|
);
|
|
20874
20905
|
|
|
20875
|
-
|
|
20906
|
+
-- Dropped: a prefix of edges_triple (from_id, type, to_id), which every
|
|
20907
|
+
-- from-side lookup and foreign-key check already plans through; it cost 47 MB
|
|
20908
|
+
-- and an index write on every edge write.
|
|
20909
|
+
DROP INDEX IF EXISTS edges_from;
|
|
20876
20910
|
CREATE INDEX IF NOT EXISTS edges_to ON edges(to_id, type);
|
|
20877
20911
|
CREATE INDEX IF NOT EXISTS edges_type ON edges(type);
|
|
20878
20912
|
CREATE UNIQUE INDEX IF NOT EXISTS edges_triple ON edges(from_id, type, to_id);
|
|
@@ -20894,6 +20928,12 @@ CREATE INDEX IF NOT EXISTS nodes_live_local_community ON nodes(label, valid_to,
|
|
|
20894
20928
|
-- Problems parked for the fold judge (read every settle boundary): ~1 in 5 open
|
|
20895
20929
|
-- Problems; without it every live Problem was read to find them (56 MB).
|
|
20896
20930
|
CREATE INDEX IF NOT EXISTS nodes_live_fold_candidate ON nodes(label, valid_to) WHERE valid_to IS NULL AND json_type(attrs_json, '$.foldCandidate') IS NOT NULL;
|
|
20931
|
+
-- Render impressions, one row per node id (exposure-attrs.ts): a render bumps
|
|
20932
|
+
-- ~40 of these, which in the node row rewrote each whole row and its indexes.
|
|
20933
|
+
CREATE TABLE IF NOT EXISTS node_exposure (
|
|
20934
|
+
id TEXT PRIMARY KEY,
|
|
20935
|
+
attrs_json TEXT NOT NULL DEFAULT '{}'
|
|
20936
|
+
) WITHOUT ROWID;
|
|
20897
20937
|
-- The semantic-maintenance sweeps' own filters (closed, asked, hinted): each read
|
|
20898
20938
|
-- every Problem row (~30 MB on a 1.1 GB store) for the few hundred that match,
|
|
20899
20939
|
-- several times a run, and a run follows most writes (2026-10-20).
|
|
@@ -21000,6 +21040,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21000
21040
|
constructor(opts) {
|
|
21001
21041
|
this.db = openDatabase(opts.path);
|
|
21002
21042
|
this.db.exec("PRAGMA cache_size = -32768");
|
|
21043
|
+
this.db.exec("PRAGMA mmap_size = 2147483648");
|
|
21003
21044
|
this.db.exec(SCHEMA_SQL);
|
|
21004
21045
|
const versionRow = this.db.prepare("SELECT version FROM schema_version LIMIT 1").get();
|
|
21005
21046
|
if (!versionRow) {
|
|
@@ -21063,7 +21104,10 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21063
21104
|
last_reinforced_at_seq = excluded.last_reinforced_at_seq,
|
|
21064
21105
|
attrs_json = excluded.attrs_json
|
|
21065
21106
|
`),
|
|
21066
|
-
getNode: this.db.prepare("SELECT
|
|
21107
|
+
getNode: this.db.prepare("SELECT nodes.*, (SELECT x.attrs_json FROM node_exposure x WHERE x.id = nodes.id) AS exposure_json FROM nodes WHERE id = ?"),
|
|
21108
|
+
exposureOf: this.db.prepare("SELECT attrs_json FROM node_exposure WHERE id = ?"),
|
|
21109
|
+
writeExposure: this.db.prepare("INSERT INTO node_exposure(id, attrs_json) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET attrs_json = excluded.attrs_json"),
|
|
21110
|
+
lastUpdatedOf: this.db.prepare("SELECT last_updated_at AS t, attrs_json FROM nodes WHERE id = ?"),
|
|
21067
21111
|
labelOf: this.db.prepare("SELECT label FROM nodes WHERE id = ?"),
|
|
21068
21112
|
nodeContent: this.db.prepare(
|
|
21069
21113
|
"SELECT label, description, extraction_confidence, extraction_source, stability, valid_to, attrs_json FROM nodes WHERE id = ?"
|
|
@@ -21227,6 +21271,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21227
21271
|
"INSERT INTO store_meta (key, value) VALUES ('ingest_seq', :v) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
21228
21272
|
)
|
|
21229
21273
|
};
|
|
21274
|
+
this.moveExposureToSideRows();
|
|
21230
21275
|
const seqRow = this.db.prepare("SELECT value FROM store_meta WHERE key = 'ingest_seq'").get();
|
|
21231
21276
|
this.ingestSeq = seqRow ? Number(seqRow.value) : 0;
|
|
21232
21277
|
}
|
|
@@ -21287,21 +21332,35 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21287
21332
|
`SELECT rowid AS rid, logical_id, version, valid_to, label, ${WM_CALIBRATION_KEYS.map((k, i2) => `${wmCounterSql(k)} AS c${i2}`).join(", ")}
|
|
21288
21333
|
FROM nodes INDEXED BY nodes_wm_counted WHERE ${WM_COUNTED_PREDICATE}`
|
|
21289
21334
|
).all();
|
|
21335
|
+
const exposed = this.db.prepare(
|
|
21336
|
+
`SELECT n.rowid AS rid, n.logical_id, n.version, n.valid_to, n.label, x.attrs_json AS exposure
|
|
21337
|
+
FROM node_exposure x JOIN nodes n ON n.id = x.id`
|
|
21338
|
+
).all();
|
|
21290
21339
|
const others = this.db.prepare(
|
|
21291
21340
|
`SELECT rowid AS rid, logical_id, version, valid_to, label FROM nodes WHERE rowid IN (
|
|
21292
21341
|
SELECT n.rowid FROM nodes AS n INDEXED BY nodes_logical
|
|
21293
|
-
WHERE n.logical_id IN (SELECT logical_id FROM nodes INDEXED BY nodes_wm_counted WHERE ${WM_COUNTED_PREDICATE}
|
|
21294
|
-
|
|
21342
|
+
WHERE n.logical_id IN (SELECT logical_id FROM nodes INDEXED BY nodes_wm_counted WHERE ${WM_COUNTED_PREDICATE}
|
|
21343
|
+
UNION SELECT n2.logical_id FROM node_exposure x2 JOIN nodes n2 ON n2.id = x2.id)
|
|
21344
|
+
EXCEPT SELECT rowid FROM nodes INDEXED BY nodes_wm_counted WHERE ${WM_COUNTED_PREDICATE}
|
|
21345
|
+
EXCEPT SELECT n3.rowid FROM node_exposure x3 JOIN nodes n3 ON n3.id = x3.id)`
|
|
21295
21346
|
).all();
|
|
21296
|
-
const
|
|
21297
|
-
|
|
21347
|
+
const byRid = /* @__PURE__ */ new Map();
|
|
21348
|
+
for (const r of [...counted, ...others]) {
|
|
21298
21349
|
const attrs = {};
|
|
21299
21350
|
WM_CALIBRATION_KEYS.forEach((k, i2) => {
|
|
21300
21351
|
const v = r[`c${i2}`];
|
|
21301
21352
|
if (typeof v === "number") attrs[k] = v;
|
|
21302
21353
|
});
|
|
21303
|
-
|
|
21304
|
-
}
|
|
21354
|
+
byRid.set(r.rid, { row: r, attrs });
|
|
21355
|
+
}
|
|
21356
|
+
for (const r of exposed) {
|
|
21357
|
+
const side = JSON.parse(r.exposure);
|
|
21358
|
+
const entry = byRid.get(r.rid) ?? { row: r, attrs: {} };
|
|
21359
|
+
for (const k of WM_CALIBRATION_KEYS) if (typeof side[k] === "number" && Number.isFinite(side[k])) entry.attrs[k] = side[k];
|
|
21360
|
+
byRid.set(r.rid, entry);
|
|
21361
|
+
}
|
|
21362
|
+
const order = new Map(labels.map((l, i2) => [l, i2]));
|
|
21363
|
+
return [...byRid.values()].filter(({ row }) => order.has(row.label)).sort((a, b) => order.get(a.row.label) - order.get(b.row.label) || a.row.rid - b.row.rid).map(({ row, attrs }) => ({ logicalId: row.logical_id, version: Number(row.version), validTo: row.valid_to ?? null, attrs }));
|
|
21305
21364
|
}
|
|
21306
21365
|
liveCommentsAttachedTo(name2) {
|
|
21307
21366
|
return this.db.prepare(
|
|
@@ -21439,7 +21498,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21439
21498
|
logical_id: node2.logicalId ?? node2.id,
|
|
21440
21499
|
created_at_seq: node2.createdAtSeq ?? null,
|
|
21441
21500
|
last_reinforced_at_seq: node2.lastReinforcedAtSeq ?? null,
|
|
21442
|
-
attrs_json:
|
|
21501
|
+
attrs_json: this.nodeAttrsJson(node2.id, node2.attrs ?? {})
|
|
21443
21502
|
});
|
|
21444
21503
|
}
|
|
21445
21504
|
/** mergeNode, unless the live row already holds this content. Content is what
|
|
@@ -21451,7 +21510,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21451
21510
|
* whether it wrote. */
|
|
21452
21511
|
mergeNodeIfChanged(node2) {
|
|
21453
21512
|
const row = this.stmts.nodeContent.get(node2.id);
|
|
21454
|
-
if (row && row.valid_to === null && row.label === node2.label && row.description === node2.description && row.extraction_confidence === node2.extractionConfidence && row.stability === node2.stability && row.attrs_json === JSON.stringify(node2.attrs ?? {})) return false;
|
|
21513
|
+
if (row && row.valid_to === null && row.label === node2.label && row.description === node2.description && row.extraction_confidence === node2.extractionConfidence && row.stability === node2.stability && !EXPOSURE_ATTRS.some((k) => node2.attrs?.[k] !== void 0) && row.attrs_json === JSON.stringify(node2.attrs ?? {})) return false;
|
|
21455
21514
|
this.mergeNode(node2);
|
|
21456
21515
|
return true;
|
|
21457
21516
|
}
|
|
@@ -21478,7 +21537,37 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21478
21537
|
logical_id: patch.logicalId ?? null,
|
|
21479
21538
|
created_at_seq: patch.createdAtSeq ?? null,
|
|
21480
21539
|
last_reinforced_at_seq: patch.lastReinforcedAtSeq ?? null,
|
|
21481
|
-
attrs_json: patch.attrs ?
|
|
21540
|
+
attrs_json: patch.attrs ? this.nodeAttrsJson(id, patch.attrs) : null
|
|
21541
|
+
});
|
|
21542
|
+
}
|
|
21543
|
+
/**
|
|
21544
|
+
* The node-row attrs of a write, after handing any exposure keys to the side
|
|
21545
|
+
* row (exposure-attrs.ts). `getNode` returns exposure merged into attrs, so a
|
|
21546
|
+
* read-modify-write carries it; kept in the row it would re-bloat the row and
|
|
21547
|
+
* drift from the side row. Unchanged exposure costs no write.
|
|
21548
|
+
*/
|
|
21549
|
+
nodeAttrsJson(id, attrs) {
|
|
21550
|
+
if (!EXPOSURE_ATTRS.some((k) => attrs[k] !== void 0)) return JSON.stringify(attrs);
|
|
21551
|
+
const current = this.stmts.exposureOf.get(id);
|
|
21552
|
+
const next = JSON.stringify({ ...current ? JSON.parse(current.attrs_json) : {}, ...pickExposure(attrs) });
|
|
21553
|
+
if (current?.attrs_json !== next) this.stmts.writeExposure.run(id, next);
|
|
21554
|
+
const rest2 = { ...attrs };
|
|
21555
|
+
for (const k of EXPOSURE_ATTRS) delete rest2[k];
|
|
21556
|
+
return JSON.stringify(rest2);
|
|
21557
|
+
}
|
|
21558
|
+
/** One-time: exposure keys written to node rows before the side table existed
|
|
21559
|
+
* move to it. Only rows carrying a counter can carry exposure, and those are
|
|
21560
|
+
* what nodes_wm_counted holds, so this reads the index, not the table. */
|
|
21561
|
+
moveExposureToSideRows() {
|
|
21562
|
+
if (this.db.prepare("SELECT value FROM store_meta WHERE key = ?").get(EXPOSURE_SIDE_KEY)) return;
|
|
21563
|
+
const rows = this.db.prepare(`SELECT id, attrs_json FROM nodes INDEXED BY nodes_wm_counted WHERE ${WM_COUNTED_PREDICATE}`).all();
|
|
21564
|
+
const move = this.db.prepare("UPDATE nodes SET attrs_json = ? WHERE id = ?");
|
|
21565
|
+
this.db.transaction(() => {
|
|
21566
|
+
for (const r of rows) {
|
|
21567
|
+
const stripped = this.nodeAttrsJson(r.id, JSON.parse(r.attrs_json));
|
|
21568
|
+
if (stripped !== r.attrs_json) move.run(stripped, r.id);
|
|
21569
|
+
}
|
|
21570
|
+
this.db.prepare("INSERT OR REPLACE INTO store_meta(key, value) VALUES (?, 'done')").run(EXPOSURE_SIDE_KEY);
|
|
21482
21571
|
});
|
|
21483
21572
|
}
|
|
21484
21573
|
/** Fast single-column writes for the nightly pass (avoid the 18-column COALESCE
|
|
@@ -21641,7 +21730,27 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21641
21730
|
}
|
|
21642
21731
|
getNode(id) {
|
|
21643
21732
|
const row = this.stmts.getNode.get(id);
|
|
21644
|
-
|
|
21733
|
+
if (!row) return null;
|
|
21734
|
+
const node2 = rowToNode(row);
|
|
21735
|
+
if (row.exposure_json) Object.assign(node2.attrs, JSON.parse(row.exposure_json));
|
|
21736
|
+
return node2;
|
|
21737
|
+
}
|
|
21738
|
+
/** A node's render exposure: the side row's keys over the node row's own
|
|
21739
|
+
* (exposure-attrs.ts), plus the node's `lastUpdatedAt` (the "shown since
|
|
21740
|
+
* touch" counter is relative to it) — without reading the node's attrs. */
|
|
21741
|
+
exposureOf(id) {
|
|
21742
|
+
const row = this.stmts.lastUpdatedOf.get(id);
|
|
21743
|
+
if (!row) return null;
|
|
21744
|
+
const side = this.stmts.exposureOf.get(id);
|
|
21745
|
+
return {
|
|
21746
|
+
attrs: { ...pickExposure(JSON.parse(row.attrs_json)), ...side ? JSON.parse(side.attrs_json) : {} },
|
|
21747
|
+
lastUpdatedAt: row.t
|
|
21748
|
+
};
|
|
21749
|
+
}
|
|
21750
|
+
/** Replace a node's exposure (only EXPOSURE_ATTRS keys belong here). Touches
|
|
21751
|
+
* neither the node row nor its indexes, nor the change feed. */
|
|
21752
|
+
writeExposure(id, attrs) {
|
|
21753
|
+
this.stmts.writeExposure.run(id, JSON.stringify(attrs));
|
|
21645
21754
|
}
|
|
21646
21755
|
nodeLabels(ids) {
|
|
21647
21756
|
const width = NODE_LABELS_CHUNK;
|
|
@@ -21692,7 +21801,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21692
21801
|
findNodeStampsByLabel(label, attrKey) {
|
|
21693
21802
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(attrKey)) throw new Error(`findNodeStampsByLabel: bad attr key ${attrKey}`);
|
|
21694
21803
|
const rows = this.db.prepare(
|
|
21695
|
-
`SELECT id, created_at, created_at_seq, json_type(
|
|
21804
|
+
`SELECT id, created_at, created_at_seq, json_type(${attrDocSql(attrKey)}, '$.${attrKey}') IS NOT NULL AS has,
|
|
21696
21805
|
COALESCE(json_extract(attrs_json, '$.source') = 'cloud', 0) AS cloud
|
|
21697
21806
|
FROM nodes WHERE label = ? AND valid_to IS NULL`
|
|
21698
21807
|
).all(label);
|
|
@@ -21709,7 +21818,7 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21709
21818
|
const keys = [...new Set(attrKeys)];
|
|
21710
21819
|
const rows = this.db.prepare(
|
|
21711
21820
|
`SELECT id, created_at, created_at_seq,
|
|
21712
|
-
${keys.map((k, i2) => `json_type(
|
|
21821
|
+
${keys.map((k, i2) => `json_type(${attrDocSql(k)}, '$.${k}') IS NOT NULL AS h${i2}`).join(", ")}${keys.length ? "," : ""}
|
|
21713
21822
|
COALESCE(json_extract(attrs_json, '$.source') = 'cloud', 0) AS cloud
|
|
21714
21823
|
FROM nodes WHERE label = ? AND valid_to IS NULL`
|
|
21715
21824
|
).all(label);
|
|
@@ -21969,6 +22078,9 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
|
|
|
21969
22078
|
changedNodeIds(sinceSeq, labels) {
|
|
21970
22079
|
return readChangedNodeIds(this.db, sinceSeq, labels);
|
|
21971
22080
|
}
|
|
22081
|
+
changedAmong(sinceSeq, ids) {
|
|
22082
|
+
return readChangedAmong(this.db, sinceSeq, ids);
|
|
22083
|
+
}
|
|
21972
22084
|
pruneChangeLog() {
|
|
21973
22085
|
return pruneChangeLog(this.db);
|
|
21974
22086
|
}
|
|
@@ -24931,9 +25043,11 @@ function recordRenderLedger(store, ledger, seq, ts) {
|
|
|
24931
25043
|
const bump = (ids, field) => {
|
|
24932
25044
|
let n = 0;
|
|
24933
25045
|
for (const id of new Set(ids.map((i2) => i2.id))) {
|
|
24934
|
-
const
|
|
24935
|
-
|
|
24936
|
-
|
|
25046
|
+
const side = store.exposureOf?.(id);
|
|
25047
|
+
const node2 = side ? null : store.getNode(id);
|
|
25048
|
+
if (!side && !node2) continue;
|
|
25049
|
+
const lastUpdatedAt = side ? side.lastUpdatedAt : node2.lastUpdatedAt;
|
|
25050
|
+
const attrs = side ? { ...side.attrs } : { ...node2.attrs };
|
|
24937
25051
|
if (field === "shownCount" && attrs["firstShownAt"] === void 0) {
|
|
24938
25052
|
attrs["firstShownAt"] = attrs["firstShownAtSeq"] !== void 0 || attrs["lastShownAtSeq"] !== void 0 ? 0 : ts;
|
|
24939
25053
|
}
|
|
@@ -24944,15 +25058,16 @@ function recordRenderLedger(store, ledger, seq, ts) {
|
|
|
24944
25058
|
if (field === "shownCount") {
|
|
24945
25059
|
attrs["lastShownAtSeq"] = seq;
|
|
24946
25060
|
if (attrs["firstShownAtSeq"] === void 0) attrs["firstShownAtSeq"] = seq;
|
|
24947
|
-
const counted = attrs["shownSinceTouchAt"] ===
|
|
25061
|
+
const counted = attrs["shownSinceTouchAt"] === lastUpdatedAt ? Number(attrs["shownSinceTouch"] ?? 0) : 0;
|
|
24948
25062
|
attrs["shownSinceTouch"] = counted + 1;
|
|
24949
|
-
attrs["shownSinceTouchAt"] =
|
|
25063
|
+
attrs["shownSinceTouchAt"] = lastUpdatedAt;
|
|
24950
25064
|
logImpression(attrs, ts, retrieved.has(id) ? "r" : "c");
|
|
24951
25065
|
} else {
|
|
24952
25066
|
attrs["lastEvictedAtSeq"] = seq;
|
|
24953
25067
|
logImpression(attrs, ts, "e");
|
|
24954
25068
|
}
|
|
24955
|
-
store.
|
|
25069
|
+
if (side) store.writeExposure(id, pickExposure(attrs));
|
|
25070
|
+
else store.updateNode(id, { attrs, lastUpdatedAt });
|
|
24956
25071
|
n++;
|
|
24957
25072
|
}
|
|
24958
25073
|
return n;
|
|
@@ -25061,6 +25176,7 @@ var init_design_problem = __esm({
|
|
|
25061
25176
|
init_src();
|
|
25062
25177
|
init_src();
|
|
25063
25178
|
init_problem_package_link();
|
|
25179
|
+
init_exposure_attrs();
|
|
25064
25180
|
init_src4();
|
|
25065
25181
|
init_src2();
|
|
25066
25182
|
init_problem_package_link();
|
|
@@ -27808,6 +27924,95 @@ var init_src5 = __esm({
|
|
|
27808
27924
|
}
|
|
27809
27925
|
});
|
|
27810
27926
|
|
|
27927
|
+
// ../../packages/context-writer/src/snapshot-inputs.ts
|
|
27928
|
+
function guardSnapshotReads(store) {
|
|
27929
|
+
const fail = (what) => {
|
|
27930
|
+
throw new Error(`buildSnapshot read ${what}, outside SNAPSHOT_NODE_LABELS/SNAPSHOT_EDGE_TYPES (snapshot-inputs.ts)`);
|
|
27931
|
+
};
|
|
27932
|
+
const label = (l, via) => {
|
|
27933
|
+
if (typeof l === "string" && !LABELS.has(l)) fail(`label ${l} via ${via}`);
|
|
27934
|
+
};
|
|
27935
|
+
const types = (t, via) => {
|
|
27936
|
+
if (!Array.isArray(t) || t.length === 0) fail(`every edge type via ${via}`);
|
|
27937
|
+
for (const x of t) if (!EDGES.has(String(x))) fail(`edge type ${String(x)} via ${via}`);
|
|
27938
|
+
};
|
|
27939
|
+
const nodes = (r, via) => {
|
|
27940
|
+
for (const n of Array.isArray(r) ? r : r ? [r] : []) label(n.label, via);
|
|
27941
|
+
return r;
|
|
27942
|
+
};
|
|
27943
|
+
const allowed = {
|
|
27944
|
+
getNode: (id) => nodes(store.getNode(id), "getNode"),
|
|
27945
|
+
selectNodes: (q) => {
|
|
27946
|
+
for (const l of q.labels) label(l, "selectNodes");
|
|
27947
|
+
return store.selectNodes(q);
|
|
27948
|
+
},
|
|
27949
|
+
countNodes: (q) => {
|
|
27950
|
+
for (const l of q.labels) label(l, "countNodes");
|
|
27951
|
+
return store.countNodes(q);
|
|
27952
|
+
},
|
|
27953
|
+
findLiveNodesByAttr: (l, ...rest2) => {
|
|
27954
|
+
label(l, "findLiveNodesByAttr");
|
|
27955
|
+
return store.findLiveNodesByAttr(l, ...rest2);
|
|
27956
|
+
},
|
|
27957
|
+
outEdges: (id, t) => {
|
|
27958
|
+
types(t, "outEdges");
|
|
27959
|
+
return store.outEdges(id, t);
|
|
27960
|
+
},
|
|
27961
|
+
inEdges: (id, t) => {
|
|
27962
|
+
types(t, "inEdges");
|
|
27963
|
+
return store.inEdges(id, t);
|
|
27964
|
+
},
|
|
27965
|
+
inDegreeByType: (t) => {
|
|
27966
|
+
types(t, "inDegreeByType");
|
|
27967
|
+
return store.inDegreeByType(t);
|
|
27968
|
+
},
|
|
27969
|
+
nodesAsOfWhereTrue: (asOf, attr) => {
|
|
27970
|
+
if (attr !== "revisit") fail(`nodesAsOfWhereTrue(${String(attr)})`);
|
|
27971
|
+
return store.nodesAsOfWhereTrue(asOf, attr);
|
|
27972
|
+
}
|
|
27973
|
+
};
|
|
27974
|
+
return new Proxy(store, {
|
|
27975
|
+
get(target, prop) {
|
|
27976
|
+
if (typeof prop === "string" && prop in allowed) return allowed[prop];
|
|
27977
|
+
const v = Reflect.get(target, prop, target);
|
|
27978
|
+
if (typeof v === "function") return () => fail(`store.${String(prop)}()`);
|
|
27979
|
+
return v;
|
|
27980
|
+
}
|
|
27981
|
+
});
|
|
27982
|
+
}
|
|
27983
|
+
var SNAPSHOT_NODE_LABELS, SNAPSHOT_EDGE_TYPES, SNAPSHOT_READ_GUARD, LABELS, EDGES;
|
|
27984
|
+
var init_snapshot_inputs = __esm({
|
|
27985
|
+
"../../packages/context-writer/src/snapshot-inputs.ts"() {
|
|
27986
|
+
"use strict";
|
|
27987
|
+
SNAPSHOT_NODE_LABELS = [
|
|
27988
|
+
"Problem",
|
|
27989
|
+
"Vulnerability",
|
|
27990
|
+
"Solution",
|
|
27991
|
+
"Pattern",
|
|
27992
|
+
"Technique",
|
|
27993
|
+
"AntiPattern",
|
|
27994
|
+
"Language",
|
|
27995
|
+
"Package",
|
|
27996
|
+
"Tool"
|
|
27997
|
+
];
|
|
27998
|
+
SNAPSHOT_EDGE_TYPES = [
|
|
27999
|
+
"ANCHORED_AT",
|
|
28000
|
+
"CAUSED_BY",
|
|
28001
|
+
"CONCERNS",
|
|
28002
|
+
"DEPENDS_ON",
|
|
28003
|
+
"EVIDENCED_BY",
|
|
28004
|
+
"MANIFESTED_IN",
|
|
28005
|
+
"OCCURS_IN",
|
|
28006
|
+
"PERTAIN_TO",
|
|
28007
|
+
"REGRESSION_OF",
|
|
28008
|
+
"SOLVED_BY"
|
|
28009
|
+
];
|
|
28010
|
+
SNAPSHOT_READ_GUARD = typeof process !== "undefined" && Boolean(process.env["VITEST"]);
|
|
28011
|
+
LABELS = new Set(SNAPSHOT_NODE_LABELS);
|
|
28012
|
+
EDGES = new Set(SNAPSHOT_EDGE_TYPES);
|
|
28013
|
+
}
|
|
28014
|
+
});
|
|
28015
|
+
|
|
27811
28016
|
// ../../packages/context-writer/src/render.ts
|
|
27812
28017
|
function isPassiveInjectable(node2, atCommit) {
|
|
27813
28018
|
if (!historyReadPolicy(node2, { mode: "passive", atCommit }).allow) return false;
|
|
@@ -27833,6 +28038,8 @@ function passiveAllowed(row, atCommit) {
|
|
|
27833
28038
|
return historyReadPolicy({ extractionSource: row.extractionSource, attrs: row.attrs }, { mode: "passive", atCommit }).allow;
|
|
27834
28039
|
}
|
|
27835
28040
|
function buildSnapshot(opts) {
|
|
28041
|
+
const codeStore = opts.store;
|
|
28042
|
+
if (SNAPSHOT_READ_GUARD) opts = { ...opts, store: guardSnapshotReads(opts.store) };
|
|
27836
28043
|
const hydrate = (id) => opts.store.getNode(id);
|
|
27837
28044
|
const problems = opts.store.selectNodes({ labels: ["Problem", "Vulnerability"], attrs: PROBLEM_BAND_ATTRS }).filter((p) => p.attrs["mergedInto"] === void 0 && passiveAllowed(p, opts.atCommit));
|
|
27838
28045
|
const stillOpen = problems.filter((p) => p.attrs["resolvedAt"] == null);
|
|
@@ -27868,7 +28075,7 @@ function buildSnapshot(opts) {
|
|
|
27868
28075
|
const recentResolved = resolvedPool.slice(0, RECENT_RESOLVED);
|
|
27869
28076
|
const motifPool = opts.store.selectNodes({ labels: ["Pattern", "Technique", "AntiPattern"], attrs: ["missedRuns", ...HISTORY_POLICY_ATTRS] }).filter((n) => passiveAllowed(n, opts.atCommit)).filter((n) => !(Number(n.attrs["missedRuns"] ?? 0) > 0)).sort((a, b) => b.pageRank - a.pageRank).slice(0, MOTIF_POOL).map((r) => hydrate(r.id)).map((n) => n.embedding.length > 0 ? { ...n, embedding: [] } : n);
|
|
27870
28077
|
const motifs = rankMotifs(motifPool, void 0);
|
|
27871
|
-
const workingFile = opts.workingFile ? sliceForFile(
|
|
28078
|
+
const workingFile = opts.workingFile ? sliceForFile(codeStore, opts.workingFile, opts.atCommit) : void 0;
|
|
27872
28079
|
const byEpisode = /* @__PURE__ */ new Map();
|
|
27873
28080
|
for (const sol of opts.store.findLiveNodesByAttr("Solution", "enrichmentPending", 1)) {
|
|
27874
28081
|
if (!historyReadPolicy(sol, { mode: "passive", atCommit: opts.atCommit }).allow) continue;
|
|
@@ -28549,6 +28756,7 @@ var init_render = __esm({
|
|
|
28549
28756
|
init_src5();
|
|
28550
28757
|
init_src2();
|
|
28551
28758
|
init_src();
|
|
28759
|
+
init_snapshot_inputs();
|
|
28552
28760
|
MOTIF_BAND = 10;
|
|
28553
28761
|
MOTIF_POOL = 1e3;
|
|
28554
28762
|
MOTIF_SEEDS = 8;
|
|
@@ -28878,6 +29086,7 @@ var init_src6 = __esm({
|
|
|
28878
29086
|
init_context_file();
|
|
28879
29087
|
init_redirectors();
|
|
28880
29088
|
init_render();
|
|
29089
|
+
init_snapshot_inputs();
|
|
28881
29090
|
init_bleed_memory();
|
|
28882
29091
|
init_bleed_rules();
|
|
28883
29092
|
init_select_durable_memory();
|
|
@@ -38882,10 +39091,20 @@ function isReExportBarrel(relPath) {
|
|
|
38882
39091
|
function graphExportMap(store, workspaceId2, relPath) {
|
|
38883
39092
|
const out2 = /* @__PURE__ */ new Map();
|
|
38884
39093
|
const fileId = fileNodeId(workspaceId2, relPath);
|
|
38885
|
-
if (
|
|
38886
|
-
|
|
38887
|
-
|
|
38888
|
-
|
|
39094
|
+
if (store.nodeLabels([fileId]).size === 0) return out2;
|
|
39095
|
+
const defines = store.outEdges(fileId, ["DEFINES"]);
|
|
39096
|
+
const rows = /* @__PURE__ */ new Map();
|
|
39097
|
+
for (let i2 = 0; i2 < defines.length; i2 += 500) {
|
|
39098
|
+
for (const r of store.selectNodes({
|
|
39099
|
+
labels: [...EXPORTABLE_LABELS],
|
|
39100
|
+
attrs: ["workspaceId", "name"],
|
|
39101
|
+
where: [{ idIn: defines.slice(i2, i2 + 500).map((e) => e.to) }],
|
|
39102
|
+
includeClosed: true
|
|
39103
|
+
})) rows.set(r.id, r);
|
|
39104
|
+
}
|
|
39105
|
+
for (const e of defines) {
|
|
39106
|
+
const n = rows.get(e.to);
|
|
39107
|
+
if (!n) continue;
|
|
38889
39108
|
if (n.attrs["workspaceId"] !== workspaceId2) continue;
|
|
38890
39109
|
const name2 = n.attrs["name"] ?? n.description;
|
|
38891
39110
|
if (!name2 || name2.startsWith("<") || name2.includes(":")) continue;
|
|
@@ -80474,6 +80693,13 @@ init_session_registry();
|
|
|
80474
80693
|
import { readFileSync as readFileSync18, renameSync as renameSync3, statSync as statSync8, writeFileSync as writeFileSync14 } from "node:fs";
|
|
80475
80694
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
80476
80695
|
import { dirname as dirname11, join as join22 } from "node:path";
|
|
80696
|
+
function revisitFlagsUnchanged(store, held, flaggedNow) {
|
|
80697
|
+
if (held.anySeq === void 0 || held.revisitIds === void 0 || !store.changedAmong) return false;
|
|
80698
|
+
const watched = [.../* @__PURE__ */ new Set([...held.revisitIds, ...flaggedNow])];
|
|
80699
|
+
if (watched.length === 0) return true;
|
|
80700
|
+
const changed = store.changedAmong(held.anySeq, watched);
|
|
80701
|
+
return changed !== null && changed.length === 0;
|
|
80702
|
+
}
|
|
80477
80703
|
function snapshotReusable(held, want) {
|
|
80478
80704
|
return held !== null && held.key === want.key && held.atCommit === want.atCommit;
|
|
80479
80705
|
}
|
|
@@ -83326,12 +83552,40 @@ function withHeavyPassSlot(label, fn) {
|
|
|
83326
83552
|
return run3;
|
|
83327
83553
|
}
|
|
83328
83554
|
|
|
83555
|
+
// src/warm-worker.ts
|
|
83556
|
+
var WARM_HEAP_CEILING_BYTES = 256 * 1024 * 1024;
|
|
83557
|
+
var WARM_IDLE_MS = 2 * 60 * 1e3;
|
|
83558
|
+
async function mayStayWarm(worker, ceiling = WARM_HEAP_CEILING_BYTES) {
|
|
83559
|
+
const stats = await worker.getHeapStatistics?.().catch(() => void 0);
|
|
83560
|
+
return stats !== void 0 && stats.total_heap_size <= ceiling;
|
|
83561
|
+
}
|
|
83562
|
+
var IdleRecycle = class {
|
|
83563
|
+
constructor(recycle, idleMs = WARM_IDLE_MS) {
|
|
83564
|
+
this.recycle = recycle;
|
|
83565
|
+
this.idleMs = idleMs;
|
|
83566
|
+
}
|
|
83567
|
+
timer = null;
|
|
83568
|
+
arm() {
|
|
83569
|
+
this.clear();
|
|
83570
|
+
this.timer = setTimeout(() => {
|
|
83571
|
+
this.timer = null;
|
|
83572
|
+
this.recycle();
|
|
83573
|
+
}, this.idleMs);
|
|
83574
|
+
this.timer.unref?.();
|
|
83575
|
+
}
|
|
83576
|
+
clear() {
|
|
83577
|
+
if (this.timer) clearTimeout(this.timer);
|
|
83578
|
+
this.timer = null;
|
|
83579
|
+
}
|
|
83580
|
+
};
|
|
83581
|
+
|
|
83329
83582
|
// src/pass-worker-client.ts
|
|
83330
83583
|
var PassWorker = class {
|
|
83331
83584
|
constructor(init2) {
|
|
83332
83585
|
this.init = init2;
|
|
83333
83586
|
}
|
|
83334
83587
|
worker = null;
|
|
83588
|
+
idle = new IdleRecycle(() => void this.recycleIdle());
|
|
83335
83589
|
ready = null;
|
|
83336
83590
|
pending = /* @__PURE__ */ new Map();
|
|
83337
83591
|
nextId = 1;
|
|
@@ -83378,6 +83632,7 @@ var PassWorker = class {
|
|
|
83378
83632
|
if (this.stopped) return Promise.reject(new Error("pass worker stopped"));
|
|
83379
83633
|
return withHeavyPassSlot(`${kind}:${this.init.workspaceId}`, async () => {
|
|
83380
83634
|
if (this.stopped) throw new Error("pass worker stopped");
|
|
83635
|
+
this.idle.clear();
|
|
83381
83636
|
this.ensureWorker();
|
|
83382
83637
|
const id = this.nextId++;
|
|
83383
83638
|
try {
|
|
@@ -83387,7 +83642,8 @@ var PassWorker = class {
|
|
|
83387
83642
|
this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
|
|
83388
83643
|
});
|
|
83389
83644
|
} finally {
|
|
83390
|
-
await this.
|
|
83645
|
+
if (this.worker && this.pending.size === 0 && !this.stopped && await mayStayWarm(this.worker)) this.idle.arm();
|
|
83646
|
+
else await this.recycleIdle();
|
|
83391
83647
|
}
|
|
83392
83648
|
});
|
|
83393
83649
|
}
|
|
@@ -83451,6 +83707,7 @@ var PassWorker = class {
|
|
|
83451
83707
|
}
|
|
83452
83708
|
async stop() {
|
|
83453
83709
|
this.stopped = true;
|
|
83710
|
+
this.idle.clear();
|
|
83454
83711
|
const w = this.worker;
|
|
83455
83712
|
this.worker = null;
|
|
83456
83713
|
this.ready = null;
|
|
@@ -87137,7 +87394,7 @@ function createWatchBreaker(deps) {
|
|
|
87137
87394
|
}
|
|
87138
87395
|
|
|
87139
87396
|
// src/engine.ts
|
|
87140
|
-
var DAEMON_VERSION = true ? "2.0.22-dev.
|
|
87397
|
+
var DAEMON_VERSION = true ? "2.0.22-dev.4676" : "2.0.0-alpha.0";
|
|
87141
87398
|
var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
|
|
87142
87399
|
var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
|
|
87143
87400
|
var GIT_OP_MUTE_MS = 4e3;
|
|
@@ -87563,6 +87820,7 @@ function createWorkspaceEngine(opts) {
|
|
|
87563
87820
|
let ctxRefreshInFlight = false;
|
|
87564
87821
|
let ctxRefreshQueued = false;
|
|
87565
87822
|
let lastWorkerSnapshot = null;
|
|
87823
|
+
const SNAPSHOT_SCOPES = [...SNAPSHOT_NODE_LABELS.map(nodeScope), ...SNAPSHOT_EDGE_TYPES.map(edgeScope)];
|
|
87566
87824
|
let lastSelfCiteSkips = 0;
|
|
87567
87825
|
const refreshContextNow = () => {
|
|
87568
87826
|
void refreshContextAsync().catch((err2) => {
|
|
@@ -87648,21 +87906,30 @@ function createWorkspaceEngine(opts) {
|
|
|
87648
87906
|
skills: readSkillManifest(paths.skillsManifest),
|
|
87649
87907
|
...lastSelfCiteSkips > 0 ? { selfCiteSkips: lastSelfCiteSkips } : {}
|
|
87650
87908
|
};
|
|
87651
|
-
const changes = store.changeSeq ? store.changeSeq()
|
|
87909
|
+
const changes = store.changeSeq ? store.changeSeq(SNAPSHOT_SCOPES) : store.changeStamp();
|
|
87910
|
+
const anySeq = store.changeSeq?.();
|
|
87652
87911
|
const { id, name: name2, stack, languages, domains, goals } = snapOpts.profile;
|
|
87653
87912
|
const { workingFile: _workingFile, ...keyedOpts } = snapOpts;
|
|
87654
87913
|
const snapshotKey = `${snapshotCodeIdentity(DAEMON_VERSION)}|${changes}|${JSON.stringify({ ...keyedOpts, profile: { id, name: name2, stack, languages, domains, goals } })}`;
|
|
87655
87914
|
lastWorkerSnapshot ??= loadHeldSnapshot(heldSnapshotPath(paths.configDir));
|
|
87656
87915
|
const held = lastWorkerSnapshot;
|
|
87657
|
-
const withWorkingFile = (snap,
|
|
87658
|
-
if (builtFor === want) return snap;
|
|
87916
|
+
const withWorkingFile = (snap, want, atCommit) => {
|
|
87659
87917
|
const slice = want ? sliceForFile(store, want, atCommit) : void 0;
|
|
87660
87918
|
if (slice) snap.workingFile = slice;
|
|
87661
87919
|
else delete snap.workingFile;
|
|
87662
87920
|
return snap;
|
|
87663
87921
|
};
|
|
87664
|
-
const
|
|
87665
|
-
|
|
87922
|
+
const revisitIds = store.nodesAsOfWhereTrue(Date.now(), "revisit").map((n) => n.id);
|
|
87923
|
+
const prebuilt = snapshotReusable(held, { key: snapshotKey, atCommit: snapOpts.atCommit }) && revisitFlagsUnchanged(store, held, revisitIds) ? withWorkingFile(structuredClone(held.snapshot), snapOpts.workingFile, snapOpts.atCommit) : passWorker ? await passWorker.snapshot(snapOpts).then((snapshot2) => {
|
|
87924
|
+
lastWorkerSnapshot = {
|
|
87925
|
+
key: snapshotKey,
|
|
87926
|
+
at: Date.now(),
|
|
87927
|
+
atCommit: snapOpts.atCommit,
|
|
87928
|
+
workingFile: snapOpts.workingFile,
|
|
87929
|
+
...anySeq !== void 0 ? { anySeq } : {},
|
|
87930
|
+
revisitIds,
|
|
87931
|
+
snapshot: structuredClone(snapshot2)
|
|
87932
|
+
};
|
|
87666
87933
|
saveHeldSnapshot(heldSnapshotPath(paths.configDir), lastWorkerSnapshot);
|
|
87667
87934
|
return snapshot2;
|
|
87668
87935
|
}).catch((err2) => {
|
|
@@ -91686,6 +91953,7 @@ init_session_registry();
|
|
|
91686
91953
|
import { Worker as Worker2 } from "node:worker_threads";
|
|
91687
91954
|
var ConsolidateWorker = class {
|
|
91688
91955
|
worker = null;
|
|
91956
|
+
idle = new IdleRecycle(() => void this.recycleIdle());
|
|
91689
91957
|
ready = null;
|
|
91690
91958
|
pending = /* @__PURE__ */ new Map();
|
|
91691
91959
|
nextId = 1;
|
|
@@ -91696,6 +91964,7 @@ var ConsolidateWorker = class {
|
|
|
91696
91964
|
if (this.stopped) return Promise.reject(new Error("consolidate worker stopped"));
|
|
91697
91965
|
return withHeavyPassSlot(`consolidate:${req.kind ?? "pass"}`, async () => {
|
|
91698
91966
|
if (this.stopped) throw new Error("consolidate worker stopped");
|
|
91967
|
+
this.idle.clear();
|
|
91699
91968
|
this.ensureWorker();
|
|
91700
91969
|
const id = this.nextId++;
|
|
91701
91970
|
try {
|
|
@@ -91705,7 +91974,8 @@ var ConsolidateWorker = class {
|
|
|
91705
91974
|
this.worker.postMessage({ ...req, id });
|
|
91706
91975
|
});
|
|
91707
91976
|
} finally {
|
|
91708
|
-
await this.
|
|
91977
|
+
if (this.worker && this.pending.size === 0 && !this.stopped && await mayStayWarm(this.worker)) this.idle.arm();
|
|
91978
|
+
else await this.recycleIdle();
|
|
91709
91979
|
}
|
|
91710
91980
|
});
|
|
91711
91981
|
}
|
|
@@ -91768,6 +92038,7 @@ var ConsolidateWorker = class {
|
|
|
91768
92038
|
}
|
|
91769
92039
|
async stop() {
|
|
91770
92040
|
this.stopped = true;
|
|
92041
|
+
this.idle.clear();
|
|
91771
92042
|
if (this.worker) {
|
|
91772
92043
|
await this.worker.terminate().catch(() => {
|
|
91773
92044
|
});
|
|
@@ -93614,7 +93885,7 @@ var GitBlobReader = class {
|
|
|
93614
93885
|
init_src11();
|
|
93615
93886
|
init_src();
|
|
93616
93887
|
import { extname as extname4 } from "node:path";
|
|
93617
|
-
var
|
|
93888
|
+
var LABELS2 = {
|
|
93618
93889
|
function: "Function",
|
|
93619
93890
|
class: "Class",
|
|
93620
93891
|
method: "Method",
|
|
@@ -93648,7 +93919,7 @@ async function historicalAnchors(input) {
|
|
|
93648
93919
|
const source = await input.readBlob(spec);
|
|
93649
93920
|
if (source === null || source.includes("\0") || Buffer.byteLength(source) > MAX_SOURCE_BYTES) return null;
|
|
93650
93921
|
await provider.preload?.();
|
|
93651
|
-
const symbols = provider.extractSymbols(source, path3).filter((s) =>
|
|
93922
|
+
const symbols = provider.extractSymbols(source, path3).filter((s) => LABELS2[s.kind] && s.startByte >= 0 && s.endByte > s.startByte);
|
|
93652
93923
|
const offsets = [0];
|
|
93653
93924
|
for (let i2 = 0; i2 < source.length; i2++) if (source[i2] === "\n") offsets.push(i2 + 1);
|
|
93654
93925
|
offsets.push(source.length + 1);
|
|
@@ -93683,7 +93954,7 @@ async function historicalAnchors(input) {
|
|
|
93683
93954
|
const symbols = file2.symbols.filter((s) => s.startByte < stop2 && s.endByte > start2).sort((a, b) => a.endByte - a.startByte - (b.endByte - b.startByte));
|
|
93684
93955
|
const symbol2 = symbols[0];
|
|
93685
93956
|
if (symbol2) {
|
|
93686
|
-
const kind =
|
|
93957
|
+
const kind = LABELS2[symbol2.kind];
|
|
93687
93958
|
const symbolId = projectSymbolId(input.salt, input.projectId, input.bundle.pathTokens[token], symbol2.qname ?? symbol2.name, kind);
|
|
93688
93959
|
const prev = list.at(-1);
|
|
93689
93960
|
if (prev?.symbolId === symbolId && prev.historical?.side === side && prev.historical.blockDigest === block.digest && prev.historical.endByte + 1 === offset) {
|