@inerrata-corporation/errata 2.0.13-dev.3043 → 2.0.13-dev.3063

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.
@@ -16141,6 +16141,54 @@ import { parentPort } from "node:worker_threads";
16141
16141
  // ../../packages/local-graph/src/store.ts
16142
16142
  init_src2();
16143
16143
  init_src();
16144
+
16145
+ // ../../packages/local-graph/src/history-cache-floor.ts
16146
+ function installHistoryCacheFloor(db) {
16147
+ const key = "history-cache-withdrawal-floor-2";
16148
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key)) return;
16149
+ db.transaction(() => {
16150
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get("history-cache-withdrawal-floor-1")) {
16151
+ db.exec("DROP INDEX IF EXISTS nodes_cloud_id");
16152
+ }
16153
+ db.exec(`
16154
+ CREATE VIEW IF NOT EXISTS history_cache_withdrawals AS
16155
+ SELECT n.id, json_extract(m.value, '$.action') = 'quarantine' AS privacy,
16156
+ json_extract(m.value, '$.nodeId') AS cloud_id,
16157
+ json_extract(m.value, '$.seq') AS seq,
16158
+ CASE WHEN json_extract(m.value, '$.action') = 'quarantine' THEN 'quarantined' ELSE 'contradicted' END AS support
16159
+ FROM nodes n JOIN store_meta m
16160
+ ON m.key = 'history-correction:' || coalesce(json_extract(n.attrs_json, '$.cloudNodeId'), n.id)
16161
+ WHERE json_extract(n.attrs_json, '$.source') = 'cloud' AND json_valid(m.value)
16162
+ AND json_extract(m.value, '$.seq') >= coalesce(json_extract(n.attrs_json, '$.historyCorrectionSeq'), 0)
16163
+ AND (json_extract(m.value, '$.action') = 'quarantine' OR json_extract(m.value, '$.sourceSupport') = 'contradicted');
16164
+ `);
16165
+ const lookup = (field) => `(SELECT ${field} FROM history_cache_withdrawals w WHERE w.id = nodes.id)`;
16166
+ const privacy = `coalesce(${lookup("privacy")}, 0)`;
16167
+ const description = `CASE WHEN ${privacy} THEN 'History source withdrawn.' ELSE description END`;
16168
+ const attrs = `CASE WHEN ${privacy} THEN json_object(
16169
+ 'source', 'cloud', 'cloudNodeId', ${lookup("cloud_id")}, 'extractionSource', 'history-mined',
16170
+ 'historyQuality', json_object('sourceSupport', 'quarantined', 'applicability', 'unknown'),
16171
+ 'historyCorrectionSeq', ${lookup("seq")})
16172
+ ELSE json_set(json_remove(attrs_json, '$.embeddingVersion'),
16173
+ '$.historyQuality.sourceSupport', coalesce(${lookup("support")}, json_extract(attrs_json, '$.historyQuality.sourceSupport')),
16174
+ '$.historyQuality.applicability', 'unknown',
16175
+ '$.historyCorrectionSeq', coalesce(${lookup("seq")}, json_extract(attrs_json, '$.historyCorrectionSeq'), 0)) END`;
16176
+ const repair = (scope) => `UPDATE nodes SET description = ${description},
16177
+ embedding_blob = NULL, embedding_json = '[]', is_landmark = 0, attrs_json = ${attrs}
16178
+ WHERE (${scope}) AND (json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')
16179
+ OR EXISTS(SELECT 1 FROM history_cache_withdrawals w WHERE w.id = nodes.id))
16180
+ AND (embedding_blob IS NOT NULL OR embedding_json <> '[]' OR is_landmark <> 0
16181
+ OR description <> ${description} OR attrs_json <> ${attrs});`;
16182
+ for (const operation of ["INSERT", "UPDATE"]) {
16183
+ db.exec(`CREATE TRIGGER IF NOT EXISTS history_cache_nodes_${operation.toLowerCase()}
16184
+ AFTER ${operation} ON nodes BEGIN ${repair("id = NEW.id")} END;`);
16185
+ }
16186
+ db.exec(repair("json_extract(attrs_json, '$.source') = 'cloud' OR json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')"));
16187
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(key, "installed");
16188
+ });
16189
+ }
16190
+
16191
+ // ../../packages/local-graph/src/store.ts
16144
16192
  var LOCAL_RULE_OVERRIDES = {
16145
16193
  ANCHORED_AT: {
16146
16194
  from: EDGE_RULES["ANCHORED_AT"]?.from,
@@ -16383,6 +16431,7 @@ var SqliteGraphStore = class {
16383
16431
  );
16384
16432
  }
16385
16433
  this.db.exec(TEMPORAL_INDEX_SQL);
16434
+ installHistoryCacheFloor(this.db);
16386
16435
  this.stmts = {
16387
16436
  insertNode: this.db.prepare(`
16388
16437
  INSERT INTO nodes (
package/errata.mjs CHANGED
@@ -17951,6 +17951,57 @@ var init_src2 = __esm({
17951
17951
  }
17952
17952
  });
17953
17953
 
17954
+ // ../../packages/local-graph/src/history-cache-floor.ts
17955
+ function installHistoryCacheFloor(db) {
17956
+ const key = "history-cache-withdrawal-floor-2";
17957
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key)) return;
17958
+ db.transaction(() => {
17959
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get("history-cache-withdrawal-floor-1")) {
17960
+ db.exec("DROP INDEX IF EXISTS nodes_cloud_id");
17961
+ }
17962
+ db.exec(`
17963
+ CREATE VIEW IF NOT EXISTS history_cache_withdrawals AS
17964
+ SELECT n.id, json_extract(m.value, '$.action') = 'quarantine' AS privacy,
17965
+ json_extract(m.value, '$.nodeId') AS cloud_id,
17966
+ json_extract(m.value, '$.seq') AS seq,
17967
+ CASE WHEN json_extract(m.value, '$.action') = 'quarantine' THEN 'quarantined' ELSE 'contradicted' END AS support
17968
+ FROM nodes n JOIN store_meta m
17969
+ ON m.key = 'history-correction:' || coalesce(json_extract(n.attrs_json, '$.cloudNodeId'), n.id)
17970
+ WHERE json_extract(n.attrs_json, '$.source') = 'cloud' AND json_valid(m.value)
17971
+ AND json_extract(m.value, '$.seq') >= coalesce(json_extract(n.attrs_json, '$.historyCorrectionSeq'), 0)
17972
+ AND (json_extract(m.value, '$.action') = 'quarantine' OR json_extract(m.value, '$.sourceSupport') = 'contradicted');
17973
+ `);
17974
+ const lookup = (field) => `(SELECT ${field} FROM history_cache_withdrawals w WHERE w.id = nodes.id)`;
17975
+ const privacy = `coalesce(${lookup("privacy")}, 0)`;
17976
+ const description = `CASE WHEN ${privacy} THEN 'History source withdrawn.' ELSE description END`;
17977
+ const attrs = `CASE WHEN ${privacy} THEN json_object(
17978
+ 'source', 'cloud', 'cloudNodeId', ${lookup("cloud_id")}, 'extractionSource', 'history-mined',
17979
+ 'historyQuality', json_object('sourceSupport', 'quarantined', 'applicability', 'unknown'),
17980
+ 'historyCorrectionSeq', ${lookup("seq")})
17981
+ ELSE json_set(json_remove(attrs_json, '$.embeddingVersion'),
17982
+ '$.historyQuality.sourceSupport', coalesce(${lookup("support")}, json_extract(attrs_json, '$.historyQuality.sourceSupport')),
17983
+ '$.historyQuality.applicability', 'unknown',
17984
+ '$.historyCorrectionSeq', coalesce(${lookup("seq")}, json_extract(attrs_json, '$.historyCorrectionSeq'), 0)) END`;
17985
+ const repair = (scope) => `UPDATE nodes SET description = ${description},
17986
+ embedding_blob = NULL, embedding_json = '[]', is_landmark = 0, attrs_json = ${attrs}
17987
+ WHERE (${scope}) AND (json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')
17988
+ OR EXISTS(SELECT 1 FROM history_cache_withdrawals w WHERE w.id = nodes.id))
17989
+ AND (embedding_blob IS NOT NULL OR embedding_json <> '[]' OR is_landmark <> 0
17990
+ OR description <> ${description} OR attrs_json <> ${attrs});`;
17991
+ for (const operation of ["INSERT", "UPDATE"]) {
17992
+ db.exec(`CREATE TRIGGER IF NOT EXISTS history_cache_nodes_${operation.toLowerCase()}
17993
+ AFTER ${operation} ON nodes BEGIN ${repair("id = NEW.id")} END;`);
17994
+ }
17995
+ db.exec(repair("json_extract(attrs_json, '$.source') = 'cloud' OR json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')"));
17996
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(key, "installed");
17997
+ });
17998
+ }
17999
+ var init_history_cache_floor = __esm({
18000
+ "../../packages/local-graph/src/history-cache-floor.ts"() {
18001
+ "use strict";
18002
+ }
18003
+ });
18004
+
17954
18005
  // ../../packages/local-graph/src/store.ts
17955
18006
  function localEdgeViolation(fromLabel, type, toLabel) {
17956
18007
  if (type in LOCAL_RULE_OVERRIDES) {
@@ -18033,6 +18084,7 @@ var init_store = __esm({
18033
18084
  "use strict";
18034
18085
  init_src2();
18035
18086
  init_src();
18087
+ init_history_cache_floor();
18036
18088
  LOCAL_RULE_OVERRIDES = {
18037
18089
  ANCHORED_AT: {
18038
18090
  from: EDGE_RULES["ANCHORED_AT"]?.from,
@@ -18203,6 +18255,7 @@ CREATE INDEX IF NOT EXISTS nodes_anchor_hint_path ON nodes(json_extract(attrs_js
18203
18255
  );
18204
18256
  }
18205
18257
  this.db.exec(TEMPORAL_INDEX_SQL);
18258
+ installHistoryCacheFloor(this.db);
18206
18259
  this.stmts = {
18207
18260
  insertNode: this.db.prepare(`
18208
18261
  INSERT INTO nodes (
@@ -33231,6 +33284,7 @@ var init_nightly = __esm({
33231
33284
  });
33232
33285
 
33233
33286
  // ../../packages/generalizer/src/embed-code.ts
33287
+ import { createHash as createHash5 } from "node:crypto";
33234
33288
  function embedCodeNodes(store, opts = {}) {
33235
33289
  return embedNodesByLabels(store, CODE_LABELS, opts);
33236
33290
  }
@@ -33239,9 +33293,15 @@ function embedSemanticNodes(store, opts = {}) {
33239
33293
  }
33240
33294
  async function ensureNodeEmbedded(store, nodeId, opts = {}) {
33241
33295
  const node2 = store.getNode(nodeId);
33242
- if (!node2 || node2.embedding.length > 0) return false;
33296
+ if (!node2) return false;
33297
+ if (!eligibleForEmbedding(store, node2)) {
33298
+ clearWithdrawnVector(store, node2.id);
33299
+ return false;
33300
+ }
33301
+ if (node2.embedding.length > 0) return false;
33243
33302
  const text = buildText(store, node2);
33244
33303
  if (!text) return false;
33304
+ const before = embeddingSnapshot(node2, text);
33245
33305
  let result;
33246
33306
  try {
33247
33307
  if (opts.mode === "hash") {
@@ -33255,12 +33315,41 @@ async function ensureNodeEmbedded(store, nodeId, opts = {}) {
33255
33315
  } catch {
33256
33316
  return false;
33257
33317
  }
33258
- store.updateNode(nodeId, {
33318
+ return store.transaction(() => writeIfUnchanged(store, before, result));
33319
+ }
33320
+ function embeddingState(node2) {
33321
+ return createHash5("sha256").update(JSON.stringify([node2.attrs["embeddingVersion"] ?? null, node2.embedding])).digest("hex");
33322
+ }
33323
+ function embeddingSnapshot(node2, text) {
33324
+ return { id: node2.id, text, validTo: node2.validTo, vectorState: embeddingState(node2) };
33325
+ }
33326
+ function writeIfUnchanged(store, before, result) {
33327
+ const current = store.getNode(before.id);
33328
+ if (!current || !eligibleForEmbedding(store, current) || buildText(store, current) !== before.text || current.validTo !== before.validTo || embeddingState(current) !== before.vectorState)
33329
+ return false;
33330
+ store.updateNode(current.id, {
33259
33331
  embedding: result.vector,
33260
- attrs: { ...node2.attrs, embeddingVersion: result.version }
33332
+ attrs: { ...current.attrs, embeddingVersion: result.version }
33261
33333
  });
33262
33334
  return true;
33263
33335
  }
33336
+ function eligibleForEmbedding(store, node2) {
33337
+ const cloudId = node2.attrs["cloudNodeId"];
33338
+ const raw2 = node2.attrs["source"] === "cloud" ? store.getMeta?.(`history-correction:${typeof cloudId === "string" ? cloudId : node2.id}`) : null;
33339
+ const correction = raw2 ? JSON.parse(raw2) : null;
33340
+ const withdrawn = correction && Number(correction.seq) >= Number(node2.attrs["historyCorrectionSeq"] ?? 0) && (correction.action === "quarantine" || correction.sourceSupport === "contradicted");
33341
+ return !withdrawn && historyReadPolicy(node2).allow && !node2.attrs["mergedInto"] && !node2.attrs["fusedInto"];
33342
+ }
33343
+ function clearWithdrawnVector(store, nodeId) {
33344
+ store.transaction(() => {
33345
+ const node2 = store.getNode(nodeId);
33346
+ if (!node2 || eligibleForEmbedding(store, node2)) return;
33347
+ if (node2.embedding.length || node2.attrs["embeddingVersion"] !== void 0) {
33348
+ const { embeddingVersion: _version, ...attrs } = node2.attrs;
33349
+ store.mergeNode({ ...node2, embedding: [], attrs });
33350
+ }
33351
+ });
33352
+ }
33264
33353
  async function embedNodesByLabels(store, labels, opts = {}) {
33265
33354
  const started2 = Date.now();
33266
33355
  const report = {
@@ -33275,8 +33364,14 @@ async function embedNodesByLabels(store, labels, opts = {}) {
33275
33364
  const currentVersion = hashOnly ? EMBEDDING_VERSION : (await embedBatchWithModelOrHash(["probe"]))[0]?.version ?? "unknown";
33276
33365
  const todo = [];
33277
33366
  for (const label of labels) {
33278
- for (const node2 of store.findNodesByLabel(label)) {
33367
+ for (const node2 of store.findNodesByLabel(
33368
+ label
33369
+ )) {
33279
33370
  report.scanned++;
33371
+ if (!eligibleForEmbedding(store, node2)) {
33372
+ clearWithdrawnVector(store, node2.id);
33373
+ continue;
33374
+ }
33280
33375
  const existingVersion = node2.attrs["embeddingVersion"] ?? null;
33281
33376
  if (existingVersion) {
33282
33377
  report.versionsSeen[existingVersion] = (report.versionsSeen[existingVersion] ?? 0) + 1;
@@ -33291,7 +33386,7 @@ async function embedNodesByLabels(store, labels, opts = {}) {
33291
33386
  }
33292
33387
  const text = buildText(store, node2);
33293
33388
  if (!text) continue;
33294
- todo.push({ id: node2.id, text });
33389
+ todo.push(embeddingSnapshot(node2, text));
33295
33390
  }
33296
33391
  }
33297
33392
  for (let i2 = 0; i2 < todo.length; i2 += BATCH_SIZE) {
@@ -33308,17 +33403,12 @@ async function embedNodesByLabels(store, labels, opts = {}) {
33308
33403
  }
33309
33404
  store.transaction(() => {
33310
33405
  for (let j = 0; j < batch.length; j++) {
33311
- const node2 = store.getNode(batch[j].id);
33312
- if (!node2) continue;
33313
- const newAttrs = {
33314
- ...node2.attrs,
33315
- embeddingVersion: results[j].version
33316
- };
33317
- store.updateNode(batch[j].id, {
33318
- embedding: results[j].vector,
33319
- attrs: newAttrs
33320
- });
33321
- report.embedded++;
33406
+ const result = results[j];
33407
+ if (!result) {
33408
+ report.failed++;
33409
+ continue;
33410
+ }
33411
+ if (writeIfUnchanged(store, batch[j], result)) report.embedded++;
33322
33412
  }
33323
33413
  });
33324
33414
  if (opts.progress) opts.progress(report.embedded, todo.length);
@@ -33347,6 +33437,7 @@ var CODE_LABELS, SEMANTIC_LABELS, BATCH_SIZE;
33347
33437
  var init_embed_code = __esm({
33348
33438
  "../../packages/generalizer/src/embed-code.ts"() {
33349
33439
  "use strict";
33440
+ init_src();
33350
33441
  init_src3();
33351
33442
  CODE_LABELS = ["Function", "Method", "Class", "Const"];
33352
33443
  SEMANTIC_LABELS = ["Problem", "RootCause", "Solution", "Pattern", "Claim"];
@@ -33510,7 +33601,7 @@ var init_src10 = __esm({
33510
33601
  });
33511
33602
 
33512
33603
  // ../../packages/indexer/src/parse-cache.ts
33513
- import { createHash as createHash5 } from "node:crypto";
33604
+ import { createHash as createHash6 } from "node:crypto";
33514
33605
  import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync10, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync9 } from "node:fs";
33515
33606
  import { homedir as homedir3 } from "node:os";
33516
33607
  import { join as join11 } from "node:path";
@@ -33518,7 +33609,7 @@ function parseCacheDir() {
33518
33609
  return process.env["ERRATA_PARSE_CACHE"] ?? join11(homedir3(), ".errata", "parse-cache");
33519
33610
  }
33520
33611
  function parseCacheKey(source, providerId) {
33521
- return createHash5("sha256").update(`${PARSE_CACHE_VERSION}:${providerId}:${source}`).digest("hex");
33612
+ return createHash6("sha256").update(`${PARSE_CACHE_VERSION}:${providerId}:${source}`).digest("hex");
33522
33613
  }
33523
33614
  function entryPath(dir, key) {
33524
33615
  return join11(dir, key.slice(0, 2), `${key.slice(2)}.json`);
@@ -33816,7 +33907,7 @@ var init_identity3 = __esm({
33816
33907
  import { appendFileSync, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
33817
33908
  import { readdir } from "node:fs/promises";
33818
33909
  import { extname, join as join12, relative as relative2, sep } from "node:path";
33819
- import { createHash as createHash6 } from "node:crypto";
33910
+ import { createHash as createHash7 } from "node:crypto";
33820
33911
  import { execFileSync } from "node:child_process";
33821
33912
  function nowTs() {
33822
33913
  return indexNow ?? Date.now();
@@ -33825,7 +33916,7 @@ function fingerprintOf(signature, bodyHash) {
33825
33916
  return `${signature ?? ""}|${bodyHash ?? ""}`;
33826
33917
  }
33827
33918
  function sha(s) {
33828
- return createHash6("sha256").update(s).digest("hex").slice(0, 16);
33919
+ return createHash7("sha256").update(s).digest("hex").slice(0, 16);
33829
33920
  }
33830
33921
  function fileNodeId(workspaceId2, relPath) {
33831
33922
  return `file_${sha(workspaceId2 + ":" + relPath.replace(/\\/g, "/"))}`;
@@ -33953,7 +34044,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
33953
34044
  for (const rel of [...changedRelPaths]) {
33954
34045
  let h;
33955
34046
  try {
33956
- h = createHash6("sha256").update(readFileSync11(join12(rootPath, rel))).digest("hex");
34047
+ h = createHash7("sha256").update(readFileSync11(join12(rootPath, rel))).digest("hex");
33957
34048
  } catch {
33958
34049
  continue;
33959
34050
  }
@@ -34876,7 +34967,7 @@ function upsertFile(store, id, f, workspaceId2, skip) {
34876
34967
  if (existing && fileUnchanged(existing.attrs, f, skip)) return;
34877
34968
  let contentHash;
34878
34969
  try {
34879
- contentHash = createHash6("sha256").update(readFileSync11(f.absPath)).digest("hex");
34970
+ contentHash = createHash7("sha256").update(readFileSync11(f.absPath)).digest("hex");
34880
34971
  } catch {
34881
34972
  }
34882
34973
  const carried = { ...existing?.attrs ?? {} };
@@ -39405,7 +39496,7 @@ var init_tree_sitter_loader = __esm({
39405
39496
  });
39406
39497
 
39407
39498
  // ../../packages/indexer/src/languages/typescript-treesitter.ts
39408
- import { createHash as createHash7 } from "node:crypto";
39499
+ import { createHash as createHash8 } from "node:crypto";
39409
39500
  function extractNode(node2, source, containerQname, containerKind) {
39410
39501
  switch (node2.type) {
39411
39502
  case "function_declaration":
@@ -39618,7 +39709,7 @@ function scopeRecord(kind, name2, qname, node2, body2, source) {
39618
39709
  const sig = header.replace(/\s+/g, " ").trim();
39619
39710
  if (sig) rec.signature = sig;
39620
39711
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
39621
- rec.bodyHash = createHash7("sha256").update(bodyText).digest("hex").slice(0, 16);
39712
+ rec.bodyHash = createHash8("sha256").update(bodyText).digest("hex").slice(0, 16);
39622
39713
  rec.bodySimhash = toHex(simhash(bodyText));
39623
39714
  }
39624
39715
  }
@@ -40060,14 +40151,14 @@ var init_typescript_treesitter = __esm({
40060
40151
  });
40061
40152
 
40062
40153
  // ../../packages/indexer/src/languages/python-treesitter.ts
40063
- import { createHash as createHash8 } from "node:crypto";
40154
+ import { createHash as createHash9 } from "node:crypto";
40064
40155
  function sigAndHash(node2, body2, source) {
40065
40156
  if (!body2) return {};
40066
40157
  const out2 = {};
40067
40158
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
40068
40159
  if (sig) out2.signature = sig;
40069
40160
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
40070
- out2.bodyHash = createHash8("sha256").update(bodyText).digest("hex").slice(0, 16);
40161
+ out2.bodyHash = createHash9("sha256").update(bodyText).digest("hex").slice(0, 16);
40071
40162
  out2.bodySimhash = toHex(simhash(bodyText));
40072
40163
  return out2;
40073
40164
  }
@@ -40480,7 +40571,7 @@ var init_python_treesitter = __esm({
40480
40571
  });
40481
40572
 
40482
40573
  // ../../packages/indexer/src/languages/cpp-treesitter.ts
40483
- import { createHash as createHash9 } from "node:crypto";
40574
+ import { createHash as createHash10 } from "node:crypto";
40484
40575
  function extractNode3(node2, containerQname, containerIsClass, source) {
40485
40576
  switch (node2.type) {
40486
40577
  case "function_definition":
@@ -40664,7 +40755,7 @@ function sigAndHash2(node2, body2, source) {
40664
40755
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
40665
40756
  if (sig) out2.signature = sig;
40666
40757
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
40667
- out2.bodyHash = createHash9("sha256").update(bodyText).digest("hex").slice(0, 16);
40758
+ out2.bodyHash = createHash10("sha256").update(bodyText).digest("hex").slice(0, 16);
40668
40759
  out2.bodySimhash = toHex(simhash(bodyText));
40669
40760
  return out2;
40670
40761
  }
@@ -40825,7 +40916,7 @@ var init_cpp_treesitter = __esm({
40825
40916
  });
40826
40917
 
40827
40918
  // ../../packages/indexer/src/languages/go-treesitter.ts
40828
- import { createHash as createHash10 } from "node:crypto";
40919
+ import { createHash as createHash11 } from "node:crypto";
40829
40920
  function extractNode4(node2, containerQname, source) {
40830
40921
  switch (node2.type) {
40831
40922
  case "function_declaration": {
@@ -40987,7 +41078,7 @@ function sigAndHash3(node2, body2, source) {
40987
41078
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
40988
41079
  if (sig) out2.signature = sig;
40989
41080
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
40990
- out2.bodyHash = createHash10("sha256").update(bodyText).digest("hex").slice(0, 16);
41081
+ out2.bodyHash = createHash11("sha256").update(bodyText).digest("hex").slice(0, 16);
40991
41082
  out2.bodySimhash = toHex(simhash(bodyText));
40992
41083
  return out2;
40993
41084
  }
@@ -41131,7 +41222,7 @@ var init_go_treesitter = __esm({
41131
41222
  });
41132
41223
 
41133
41224
  // ../../packages/indexer/src/languages/rust-treesitter.ts
41134
- import { createHash as createHash11 } from "node:crypto";
41225
+ import { createHash as createHash12 } from "node:crypto";
41135
41226
  function extractNode5(node2, containerQname, containerIsClass, source) {
41136
41227
  switch (node2.type) {
41137
41228
  case "function_item":
@@ -41346,7 +41437,7 @@ function sigAndHash4(node2, body2, source) {
41346
41437
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
41347
41438
  if (sig) out2.signature = sig;
41348
41439
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
41349
- out2.bodyHash = createHash11("sha256").update(bodyText).digest("hex").slice(0, 16);
41440
+ out2.bodyHash = createHash12("sha256").update(bodyText).digest("hex").slice(0, 16);
41350
41441
  out2.bodySimhash = toHex(simhash(bodyText));
41351
41442
  return out2;
41352
41443
  }
@@ -41497,7 +41588,7 @@ var init_rust_treesitter = __esm({
41497
41588
  });
41498
41589
 
41499
41590
  // ../../packages/indexer/src/languages/ruby-treesitter.ts
41500
- import { createHash as createHash12 } from "node:crypto";
41591
+ import { createHash as createHash13 } from "node:crypto";
41501
41592
  function sigAndHash5(node2, body2, source) {
41502
41593
  if (!body2) {
41503
41594
  const sig2 = source.slice(node2.startIndex, node2.endIndex).replace(/\s+/g, " ").trim();
@@ -41507,7 +41598,7 @@ function sigAndHash5(node2, body2, source) {
41507
41598
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
41508
41599
  if (sig) out2.signature = sig;
41509
41600
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
41510
- out2.bodyHash = createHash12("sha256").update(bodyText).digest("hex").slice(0, 16);
41601
+ out2.bodyHash = createHash13("sha256").update(bodyText).digest("hex").slice(0, 16);
41511
41602
  out2.bodySimhash = toHex(simhash(bodyText));
41512
41603
  return out2;
41513
41604
  }
@@ -41853,7 +41944,7 @@ var init_ruby_treesitter = __esm({
41853
41944
  });
41854
41945
 
41855
41946
  // ../../packages/indexer/src/languages/csharp-treesitter.ts
41856
- import { createHash as createHash13 } from "node:crypto";
41947
+ import { createHash as createHash14 } from "node:crypto";
41857
41948
  function extractNode7(node2, containerQname, containerIsType, source, eof) {
41858
41949
  switch (node2.type) {
41859
41950
  case "method_declaration":
@@ -42055,7 +42146,7 @@ function sigAndHash6(node2, body2, source) {
42055
42146
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
42056
42147
  if (sig) out2.signature = sig;
42057
42148
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
42058
- out2.bodyHash = createHash13("sha256").update(bodyText).digest("hex").slice(0, 16);
42149
+ out2.bodyHash = createHash14("sha256").update(bodyText).digest("hex").slice(0, 16);
42059
42150
  out2.bodySimhash = toHex(simhash(bodyText));
42060
42151
  return out2;
42061
42152
  }
@@ -51971,10 +52062,10 @@ import {
51971
52062
  writeFileSync as writeFileSync11
51972
52063
  } from "node:fs";
51973
52064
  import { join as join16 } from "node:path";
51974
- import { createHash as createHash14 } from "node:crypto";
52065
+ import { createHash as createHash15 } from "node:crypto";
51975
52066
  function enqueueOutbox(paths, payload) {
51976
52067
  ensureDir(paths.outbox);
51977
- const id = createHash14("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
52068
+ const id = createHash15("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
51978
52069
  const file2 = join16(paths.outbox, `${Date.now()}-${id}.json`);
51979
52070
  writeFileSync11(file2, JSON.stringify(payload, null, 2), "utf8");
51980
52071
  return file2;
@@ -74713,7 +74804,7 @@ init_checkout_root();
74713
74804
  import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
74714
74805
  import { basename as basename5, delimiter, dirname as dirname10, join as join20, normalize as normalize3 } from "node:path";
74715
74806
  import { homedir as homedir4 } from "node:os";
74716
- import { createHash as createHash15 } from "node:crypto";
74807
+ import { createHash as createHash16 } from "node:crypto";
74717
74808
  function readFrom(path2, fromByte, maxBytes) {
74718
74809
  let fd;
74719
74810
  try {
@@ -75022,7 +75113,7 @@ function parseCodexAssistantTurns(raw2, skipFirstLineParseFailure = false, start
75022
75113
  turns.push({
75023
75114
  // Slice-local line numbers repeat on every Stop. Position distinguishes
75024
75115
  // identical messages; the digest distinguishes a replaced row at that position.
75025
- uuid: typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : `codex-${lineByte}-${createHash15("sha256").update(line.trimEnd()).digest("hex")}`,
75116
+ uuid: typeof payload["id"] === "string" && payload["id"].length > 0 ? payload["id"] : `codex-${lineByte}-${createHash16("sha256").update(line.trimEnd()).digest("hex")}`,
75026
75117
  text: parts2.join("\n\n"),
75027
75118
  hostHarness: "codex"
75028
75119
  });
@@ -75271,7 +75362,7 @@ function geminiSessionRoots(env2 = process.env, home = homedir4()) {
75271
75362
  return [...roots];
75272
75363
  }
75273
75364
  function geminiProjectHash(cwd) {
75274
- return createHash15("sha256").update(cwd).digest("hex");
75365
+ return createHash16("sha256").update(cwd).digest("hex");
75275
75366
  }
75276
75367
  function geminiHashesFor(cwd) {
75277
75368
  const variants = /* @__PURE__ */ new Set([cwd, cwd.replace(/\/+$/, "")]);
@@ -78592,7 +78683,7 @@ var TelemetryRecorder = class {
78592
78683
  // src/file-activity.ts
78593
78684
  import { readFileSync as readFileSync22 } from "node:fs";
78594
78685
  import { join as join28 } from "node:path";
78595
- import { createHash as createHash16 } from "node:crypto";
78686
+ import { createHash as createHash17 } from "node:crypto";
78596
78687
 
78597
78688
  // ../../packages/privacy/src/patterns/credentials.ts
78598
78689
  var CREDENTIAL_PATTERNS = [
@@ -79764,7 +79855,7 @@ var FileActivityReporter = class {
79764
79855
  const current = this.options.binding();
79765
79856
  if (!identity || this.stopped || !current.enabled || current.projectId !== binding.projectId)
79766
79857
  return false;
79767
- const hash2 = createHash16("sha256").update(JSON.stringify([identity, source, at, clean, operation, branch, previousBranch])).digest("hex");
79858
+ const hash2 = createHash17("sha256").update(JSON.stringify([identity, source, at, clean, operation, branch, previousBranch])).digest("hex");
79768
79859
  const id = `${hash2.slice(0, 8)}-${hash2.slice(8, 12)}-5${hash2.slice(13, 16)}-8${hash2.slice(17, 20)}-${hash2.slice(20, 32)}`;
79769
79860
  if (!this.pending.some((item) => item.event.id === id))
79770
79861
  this.pending.push({
@@ -80821,7 +80912,7 @@ function createWatchBreaker(deps) {
80821
80912
  }
80822
80913
 
80823
80914
  // src/engine.ts
80824
- var DAEMON_VERSION = true ? "2.0.13-dev.3043" : "2.0.0-alpha.0";
80915
+ var DAEMON_VERSION = true ? "2.0.13-dev.3063" : "2.0.0-alpha.0";
80825
80916
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
80826
80917
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
80827
80918
  var GIT_OP_MUTE_MS = 4e3;
@@ -83280,10 +83371,10 @@ init_registry();
83280
83371
  init_identity2();
83281
83372
 
83282
83373
  // src/instance-receipts.ts
83283
- import { createHash as createHash17 } from "node:crypto";
83374
+ import { createHash as createHash18 } from "node:crypto";
83284
83375
  var FIELDS = ["contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
83285
83376
  function instanceDestinationKey(input) {
83286
- return createHash17("sha256").update(JSON.stringify([
83377
+ return createHash18("sha256").update(JSON.stringify([
83287
83378
  input.workspace,
83288
83379
  input.cloudUrl.replace(/\/+$/, ""),
83289
83380
  input.installationId ?? input.profileName ?? "default",
@@ -86234,7 +86325,7 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
86234
86325
 
86235
86326
  // src/link-flow.ts
86236
86327
  init_cloud_auth();
86237
- import { createHash as createHash18 } from "node:crypto";
86328
+ import { createHash as createHash19 } from "node:crypto";
86238
86329
  import { execFileSync as execFileSync5 } from "node:child_process";
86239
86330
  import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
86240
86331
  import { join as join38 } from "node:path";
@@ -86528,7 +86619,7 @@ async function loginOAuthLoopback(opts) {
86528
86619
 
86529
86620
  // src/link-flow.ts
86530
86621
  function remoteFingerprint(locator) {
86531
- return createHash18("sha256").update(locator).digest("hex");
86622
+ return createHash19("sha256").update(locator).digest("hex");
86532
86623
  }
86533
86624
  function isDecision(value) {
86534
86625
  if (!value || typeof value !== "object") return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.13-dev.3043",
3
+ "version": "2.0.13-dev.3063",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -24558,6 +24558,54 @@ import { parentPort, workerData } from "node:worker_threads";
24558
24558
  // ../../packages/local-graph/src/store.ts
24559
24559
  init_src2();
24560
24560
  init_src();
24561
+
24562
+ // ../../packages/local-graph/src/history-cache-floor.ts
24563
+ function installHistoryCacheFloor(db) {
24564
+ const key = "history-cache-withdrawal-floor-2";
24565
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key)) return;
24566
+ db.transaction(() => {
24567
+ if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get("history-cache-withdrawal-floor-1")) {
24568
+ db.exec("DROP INDEX IF EXISTS nodes_cloud_id");
24569
+ }
24570
+ db.exec(`
24571
+ CREATE VIEW IF NOT EXISTS history_cache_withdrawals AS
24572
+ SELECT n.id, json_extract(m.value, '$.action') = 'quarantine' AS privacy,
24573
+ json_extract(m.value, '$.nodeId') AS cloud_id,
24574
+ json_extract(m.value, '$.seq') AS seq,
24575
+ CASE WHEN json_extract(m.value, '$.action') = 'quarantine' THEN 'quarantined' ELSE 'contradicted' END AS support
24576
+ FROM nodes n JOIN store_meta m
24577
+ ON m.key = 'history-correction:' || coalesce(json_extract(n.attrs_json, '$.cloudNodeId'), n.id)
24578
+ WHERE json_extract(n.attrs_json, '$.source') = 'cloud' AND json_valid(m.value)
24579
+ AND json_extract(m.value, '$.seq') >= coalesce(json_extract(n.attrs_json, '$.historyCorrectionSeq'), 0)
24580
+ AND (json_extract(m.value, '$.action') = 'quarantine' OR json_extract(m.value, '$.sourceSupport') = 'contradicted');
24581
+ `);
24582
+ const lookup = (field) => `(SELECT ${field} FROM history_cache_withdrawals w WHERE w.id = nodes.id)`;
24583
+ const privacy = `coalesce(${lookup("privacy")}, 0)`;
24584
+ const description = `CASE WHEN ${privacy} THEN 'History source withdrawn.' ELSE description END`;
24585
+ const attrs = `CASE WHEN ${privacy} THEN json_object(
24586
+ 'source', 'cloud', 'cloudNodeId', ${lookup("cloud_id")}, 'extractionSource', 'history-mined',
24587
+ 'historyQuality', json_object('sourceSupport', 'quarantined', 'applicability', 'unknown'),
24588
+ 'historyCorrectionSeq', ${lookup("seq")})
24589
+ ELSE json_set(json_remove(attrs_json, '$.embeddingVersion'),
24590
+ '$.historyQuality.sourceSupport', coalesce(${lookup("support")}, json_extract(attrs_json, '$.historyQuality.sourceSupport')),
24591
+ '$.historyQuality.applicability', 'unknown',
24592
+ '$.historyCorrectionSeq', coalesce(${lookup("seq")}, json_extract(attrs_json, '$.historyCorrectionSeq'), 0)) END`;
24593
+ const repair = (scope) => `UPDATE nodes SET description = ${description},
24594
+ embedding_blob = NULL, embedding_json = '[]', is_landmark = 0, attrs_json = ${attrs}
24595
+ WHERE (${scope}) AND (json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')
24596
+ OR EXISTS(SELECT 1 FROM history_cache_withdrawals w WHERE w.id = nodes.id))
24597
+ AND (embedding_blob IS NOT NULL OR embedding_json <> '[]' OR is_landmark <> 0
24598
+ OR description <> ${description} OR attrs_json <> ${attrs});`;
24599
+ for (const operation of ["INSERT", "UPDATE"]) {
24600
+ db.exec(`CREATE TRIGGER IF NOT EXISTS history_cache_nodes_${operation.toLowerCase()}
24601
+ AFTER ${operation} ON nodes BEGIN ${repair("id = NEW.id")} END;`);
24602
+ }
24603
+ db.exec(repair("json_extract(attrs_json, '$.source') = 'cloud' OR json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')"));
24604
+ db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(key, "installed");
24605
+ });
24606
+ }
24607
+
24608
+ // ../../packages/local-graph/src/store.ts
24561
24609
  var LOCAL_RULE_OVERRIDES = {
24562
24610
  ANCHORED_AT: {
24563
24611
  from: EDGE_RULES["ANCHORED_AT"]?.from,
@@ -24800,6 +24848,7 @@ var SqliteGraphStore = class {
24800
24848
  );
24801
24849
  }
24802
24850
  this.db.exec(TEMPORAL_INDEX_SQL);
24851
+ installHistoryCacheFloor(this.db);
24803
24852
  this.stmts = {
24804
24853
  insertNode: this.db.prepare(`
24805
24854
  INSERT INTO nodes (
@@ -27465,6 +27514,9 @@ function codeAnchorProjection(store2, semanticIds, opts = {}) {
27465
27514
  return out2;
27466
27515
  }
27467
27516
 
27517
+ // ../../packages/generalizer/src/embed-code.ts
27518
+ init_src();
27519
+
27468
27520
  // ../../packages/context-writer/src/agents-md.ts
27469
27521
  init_src();
27470
27522