@inerrata-corporation/errata 2.0.2-dev.506 → 2.0.2-dev.509

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.
@@ -16562,6 +16562,19 @@ var SqliteGraphStore = class {
16562
16562
  const rows = this.db.prepare("SELECT from_id, to_id, type FROM edges WHERE valid_to IS NULL").all();
16563
16563
  return rows.map((r) => ({ from: r.from_id, to: r.to_id, type: r.type }));
16564
16564
  }
16565
+ liveNodeIds(ids) {
16566
+ const live = /* @__PURE__ */ new Set();
16567
+ const CHUNK = 900;
16568
+ for (let i = 0; i < ids.length; i += CHUNK) {
16569
+ const slice = ids.slice(i, i + CHUNK);
16570
+ if (slice.length === 0) continue;
16571
+ const rows = this.db.prepare(
16572
+ `SELECT id FROM nodes WHERE valid_to IS NULL AND id IN (${slice.map(() => "?").join(",")})`
16573
+ ).all(...slice);
16574
+ for (const r of rows) live.add(r.id);
16575
+ }
16576
+ return live;
16577
+ }
16565
16578
  /**
16566
16579
  * Live edges WITH their endpoint labels and ids, resolved in ONE join.
16567
16580
  *
package/errata.mjs CHANGED
@@ -17237,6 +17237,19 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
17237
17237
  const rows = this.db.prepare("SELECT from_id, to_id, type FROM edges WHERE valid_to IS NULL").all();
17238
17238
  return rows.map((r) => ({ from: r.from_id, to: r.to_id, type: r.type }));
17239
17239
  }
17240
+ liveNodeIds(ids) {
17241
+ const live = /* @__PURE__ */ new Set();
17242
+ const CHUNK = 900;
17243
+ for (let i2 = 0; i2 < ids.length; i2 += CHUNK) {
17244
+ const slice = ids.slice(i2, i2 + CHUNK);
17245
+ if (slice.length === 0) continue;
17246
+ const rows = this.db.prepare(
17247
+ `SELECT id FROM nodes WHERE valid_to IS NULL AND id IN (${slice.map(() => "?").join(",")})`
17248
+ ).all(...slice);
17249
+ for (const r of rows) live.add(r.id);
17250
+ }
17251
+ return live;
17252
+ }
17240
17253
  /**
17241
17254
  * Live edges WITH their endpoint labels and ids, resolved in ONE join.
17242
17255
  *
@@ -37796,9 +37809,13 @@ function* walkSource(dir) {
37796
37809
  function listSourceFiles(root) {
37797
37810
  return gitSourceFiles(root) ?? walkSource(root);
37798
37811
  }
37799
- function findStaleFiles(store, rootPath, workspaceId2) {
37812
+ async function findStaleFiles(store, rootPath, workspaceId2) {
37800
37813
  const stale = [];
37814
+ const pending = [];
37815
+ const allTargets = [];
37816
+ let scanned = 0;
37801
37817
  for (const abs of listSourceFiles(rootPath)) {
37818
+ if (++scanned % SCAN_YIELD_EVERY === 0) await new Promise((r) => setImmediate(r));
37802
37819
  let mtimeMs;
37803
37820
  try {
37804
37821
  mtimeMs = statSync2(abs).mtimeMs;
@@ -37815,11 +37832,21 @@ function findStaleFiles(store, rootPath, workspaceId2) {
37815
37832
  const edges = store.outEdges(fnode.id, ["DEFINES", "CONTAINS"]);
37816
37833
  if (edges.length === 0) {
37817
37834
  stale.push(abs);
37818
- } else if (edges.some((e) => !isLive(store.getNode(e.to)))) {
37819
- stale.push(abs);
37835
+ } else {
37836
+ const targets = edges.map((e) => e.to);
37837
+ pending.push({ abs, targets });
37838
+ allTargets.push(...targets);
37820
37839
  }
37821
37840
  }
37822
37841
  }
37842
+ const live = /* @__PURE__ */ new Set();
37843
+ for (let i2 = 0; i2 < allTargets.length; i2 += LIVENESS_CHUNK) {
37844
+ for (const id of store.liveNodeIds(allTargets.slice(i2, i2 + LIVENESS_CHUNK))) live.add(id);
37845
+ if (i2 + LIVENESS_CHUNK < allTargets.length) await new Promise((r) => setImmediate(r));
37846
+ }
37847
+ for (const { abs, targets } of pending) {
37848
+ if (targets.some((id) => !live.has(id))) stale.push(abs);
37849
+ }
37823
37850
  return stale;
37824
37851
  }
37825
37852
  function isLive(n) {
@@ -37835,7 +37862,7 @@ function findStrandedSymbols(store) {
37835
37862
  return stranded;
37836
37863
  }
37837
37864
  async function reconcileStaleFiles(store, rootPath, workspaceId2) {
37838
- const stale = findStaleFiles(store, rootPath, workspaceId2);
37865
+ const stale = await findStaleFiles(store, rootPath, workspaceId2);
37839
37866
  if (stale.length === 0) return 0;
37840
37867
  let total = 0;
37841
37868
  const BATCH = 20;
@@ -37846,13 +37873,15 @@ async function reconcileStaleFiles(store, rootPath, workspaceId2) {
37846
37873
  }
37847
37874
  return total;
37848
37875
  }
37849
- var IGNORED, SOURCE_RE;
37876
+ var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, LIVENESS_CHUNK;
37850
37877
  var init_reconcile = __esm({
37851
37878
  "src/reconcile.ts"() {
37852
37879
  "use strict";
37853
37880
  init_src11();
37854
37881
  IGNORED = /[\\/](?:\.git|node_modules|\.errata|dist|__pycache__)(?:[\\/]|$)/;
37855
37882
  SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
37883
+ SCAN_YIELD_EVERY = 100;
37884
+ LIVENESS_CHUNK = 4e3;
37856
37885
  }
37857
37886
  });
37858
37887
 
@@ -53812,7 +53841,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53812
53841
  }
53813
53842
 
53814
53843
  // src/engine.ts
53815
- var DAEMON_VERSION = true ? "2.0.2-dev.506" : "2.0.0-alpha.0";
53844
+ var DAEMON_VERSION = true ? "2.0.2-dev.509" : "2.0.0-alpha.0";
53816
53845
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53817
53846
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53818
53847
  var GIT_OP_MUTE_MS = 4e3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.506",
3
+ "version": "2.0.2-dev.509",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -24889,6 +24889,19 @@ var SqliteGraphStore = class {
24889
24889
  const rows = this.db.prepare("SELECT from_id, to_id, type FROM edges WHERE valid_to IS NULL").all();
24890
24890
  return rows.map((r) => ({ from: r.from_id, to: r.to_id, type: r.type }));
24891
24891
  }
24892
+ liveNodeIds(ids) {
24893
+ const live = /* @__PURE__ */ new Set();
24894
+ const CHUNK = 900;
24895
+ for (let i2 = 0; i2 < ids.length; i2 += CHUNK) {
24896
+ const slice = ids.slice(i2, i2 + CHUNK);
24897
+ if (slice.length === 0) continue;
24898
+ const rows = this.db.prepare(
24899
+ `SELECT id FROM nodes WHERE valid_to IS NULL AND id IN (${slice.map(() => "?").join(",")})`
24900
+ ).all(...slice);
24901
+ for (const r of rows) live.add(r.id);
24902
+ }
24903
+ return live;
24904
+ }
24892
24905
  /**
24893
24906
  * Live edges WITH their endpoint labels and ids, resolved in ONE join.
24894
24907
  *
@@ -26708,9 +26721,15 @@ function* walkSource(dir) {
26708
26721
  function listSourceFiles(root) {
26709
26722
  return gitSourceFiles(root) ?? walkSource(root);
26710
26723
  }
26711
- function findStaleFiles(store2, rootPath, workspaceId) {
26724
+ var SCAN_YIELD_EVERY = 100;
26725
+ var LIVENESS_CHUNK = 4e3;
26726
+ async function findStaleFiles(store2, rootPath, workspaceId) {
26712
26727
  const stale = [];
26728
+ const pending = [];
26729
+ const allTargets = [];
26730
+ let scanned = 0;
26713
26731
  for (const abs of listSourceFiles(rootPath)) {
26732
+ if (++scanned % SCAN_YIELD_EVERY === 0) await new Promise((r) => setImmediate(r));
26714
26733
  let mtimeMs;
26715
26734
  try {
26716
26735
  mtimeMs = statSync2(abs).mtimeMs;
@@ -26727,18 +26746,25 @@ function findStaleFiles(store2, rootPath, workspaceId) {
26727
26746
  const edges = store2.outEdges(fnode.id, ["DEFINES", "CONTAINS"]);
26728
26747
  if (edges.length === 0) {
26729
26748
  stale.push(abs);
26730
- } else if (edges.some((e) => !isLive(store2.getNode(e.to)))) {
26731
- stale.push(abs);
26749
+ } else {
26750
+ const targets = edges.map((e) => e.to);
26751
+ pending.push({ abs, targets });
26752
+ allTargets.push(...targets);
26732
26753
  }
26733
26754
  }
26734
26755
  }
26756
+ const live = /* @__PURE__ */ new Set();
26757
+ for (let i2 = 0; i2 < allTargets.length; i2 += LIVENESS_CHUNK) {
26758
+ for (const id of store2.liveNodeIds(allTargets.slice(i2, i2 + LIVENESS_CHUNK))) live.add(id);
26759
+ if (i2 + LIVENESS_CHUNK < allTargets.length) await new Promise((r) => setImmediate(r));
26760
+ }
26761
+ for (const { abs, targets } of pending) {
26762
+ if (targets.some((id) => !live.has(id))) stale.push(abs);
26763
+ }
26735
26764
  return stale;
26736
26765
  }
26737
- function isLive(n) {
26738
- return n != null && (n.validTo ?? null) === null;
26739
- }
26740
26766
  async function reconcileStaleFiles(store2, rootPath, workspaceId) {
26741
- const stale = findStaleFiles(store2, rootPath, workspaceId);
26767
+ const stale = await findStaleFiles(store2, rootPath, workspaceId);
26742
26768
  if (stale.length === 0) return 0;
26743
26769
  let total = 0;
26744
26770
  const BATCH = 20;