@inerrata-corporation/errata 2.0.0-dev.23 → 2.0.0-dev.24

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 (3) hide show
  1. package/consolidate-worker.mjs +11565 -10638
  2. package/errata.mjs +106 -49
  3. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -24982,7 +24982,7 @@ var init_motifs = __esm({
24982
24982
 
24983
24983
  // ../../packages/generalizer/src/nightly.ts
24984
24984
  function runNightlyPipeline(store) {
24985
- const started = Date.now();
24985
+ const started2 = Date.now();
24986
24986
  const allowedTypes = new Set(pagerankEdgeTypes());
24987
24987
  const nodeIds = [];
24988
24988
  const meta3 = /* @__PURE__ */ new Map();
@@ -25063,9 +25063,9 @@ function runNightlyPipeline(store) {
25063
25063
  store.transaction(() => {
25064
25064
  for (const [id, c] of comm.community) store.updateNode(id, { community: c });
25065
25065
  });
25066
- const motifs = promoteMotifs(store, started);
25067
- const designResolved = resolveDesignProblems(store, started);
25068
- const cry = crystallize(store, { ts: started });
25066
+ const motifs = promoteMotifs(store, started2);
25067
+ const designResolved = resolveDesignProblems(store, started2);
25068
+ const cry = crystallize(store, { ts: started2 });
25069
25069
  return {
25070
25070
  scoredNodes: scored,
25071
25071
  iterations: result.iterations,
@@ -25081,7 +25081,7 @@ function runNightlyPipeline(store) {
25081
25081
  designResolved,
25082
25082
  claimsEvaluated: cry.evaluated,
25083
25083
  claimsDerived: cry.derived.length,
25084
- durationMs: Date.now() - started
25084
+ durationMs: Date.now() - started2
25085
25085
  };
25086
25086
  }
25087
25087
  function codeAnchorProjection(store, semanticIds, opts = {}) {
@@ -25124,7 +25124,7 @@ function embedSemanticNodes(store, opts = {}) {
25124
25124
  return embedNodesByLabels(store, SEMANTIC_LABELS, opts);
25125
25125
  }
25126
25126
  async function embedNodesByLabels(store, labels, opts = {}) {
25127
- const started = Date.now();
25127
+ const started2 = Date.now();
25128
25128
  const report = {
25129
25129
  scanned: 0,
25130
25130
  embedded: 0,
@@ -25178,7 +25178,7 @@ async function embedNodesByLabels(store, labels, opts = {}) {
25178
25178
  });
25179
25179
  if (opts.progress) opts.progress(report.embedded, todo.length);
25180
25180
  }
25181
- report.durationMs = Date.now() - started;
25181
+ report.durationMs = Date.now() - started2;
25182
25182
  return report;
25183
25183
  }
25184
25184
  function buildText(store, node2) {
@@ -25898,16 +25898,16 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
25898
25898
  };
25899
25899
  }
25900
25900
  async function runIndexer(store, opts) {
25901
- const started = Date.now();
25901
+ const started2 = Date.now();
25902
25902
  indexNow = opts.now ?? Date.now();
25903
25903
  const ignores = /* @__PURE__ */ new Set([...DEFAULT_IGNORES, ...opts.ignoreDirs ?? []]);
25904
25904
  const maxBytes = opts.maxFileBytes ?? 1024 * 1024;
25905
- let perfLast = started;
25905
+ let perfLast = started2;
25906
25906
  const perfFile = process.env["ERRATA_PERF"];
25907
25907
  const perf = (label) => {
25908
25908
  if (!perfFile) return;
25909
25909
  const now = Date.now();
25910
- const line = `[perf] ${label}: ${now - perfLast}ms (total ${now - started}ms)
25910
+ const line = `[perf] ${label}: ${now - perfLast}ms (total ${now - started2}ms)
25911
25911
  `;
25912
25912
  perfLast = now;
25913
25913
  try {
@@ -26382,7 +26382,7 @@ async function runIndexer(store, opts) {
26382
26382
  }
26383
26383
  }
26384
26384
  perf("flush cross-file edges");
26385
- report.durationMs = Date.now() - started;
26385
+ report.durationMs = Date.now() - started2;
26386
26386
  indexNow = null;
26387
26387
  return report;
26388
26388
  }
@@ -41091,7 +41091,7 @@ function maybeFlushDigests() {
41091
41091
  }
41092
41092
 
41093
41093
  // src/engine.ts
41094
- var DAEMON_VERSION = true ? "2.0.0-dev.23" : "2.0.0-alpha.0";
41094
+ var DAEMON_VERSION = true ? "2.0.0-dev.24" : "2.0.0-alpha.0";
41095
41095
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
41096
41096
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
41097
41097
  var GIT_OP_MUTE_MS = 4e3;
@@ -42803,6 +42803,32 @@ var ConsolidateWorker = class {
42803
42803
  }
42804
42804
  };
42805
42805
 
42806
+ // src/loop-lag.ts
42807
+ var HEARTBEAT_MS = 500;
42808
+ var currentPass = "idle";
42809
+ var started = false;
42810
+ function markPass(name2) {
42811
+ const prev = currentPass;
42812
+ currentPass = name2;
42813
+ return () => {
42814
+ currentPass = prev;
42815
+ };
42816
+ }
42817
+ function startLoopLagMonitor(thresholdMs = 1e3) {
42818
+ if (started) return;
42819
+ started = true;
42820
+ let last = Date.now();
42821
+ const timer = setInterval(() => {
42822
+ const now = Date.now();
42823
+ const lag = now - last - HEARTBEAT_MS;
42824
+ if (lag > thresholdMs) {
42825
+ console.warn(`[loop-lag] event loop held ~${(lag / 1e3).toFixed(1)}s during "${currentPass}"`);
42826
+ }
42827
+ last = now;
42828
+ }, HEARTBEAT_MS);
42829
+ timer.unref();
42830
+ }
42831
+
42806
42832
  // src/multi.ts
42807
42833
  init_paths();
42808
42834
 
@@ -42889,6 +42915,7 @@ async function startMultiDaemon(opts = {}) {
42889
42915
  const sharedStore = openGraphStore({ path: sharedDbPath });
42890
42916
  const bundledRun = import.meta.url.endsWith(".mjs");
42891
42917
  const consolidateWorker = bundledRun && sharedDbPath !== ":memory:" ? new ConsolidateWorker() : null;
42918
+ startLoopLagMonitor();
42892
42919
  let baseUrl = "";
42893
42920
  const records = [];
42894
42921
  const boundaryListeners = [];
@@ -43013,12 +43040,43 @@ async function startMultiDaemon(opts = {}) {
43013
43040
  );
43014
43041
  const STRANDED_TTL_MS = 6e4;
43015
43042
  const strandedCache = /* @__PURE__ */ new Map();
43043
+ const strandedRefreshing = /* @__PURE__ */ new Set();
43016
43044
  const strandedCount = (r) => {
43017
43045
  const hit = strandedCache.get(r.id);
43018
43046
  if (hit && Date.now() - hit.at < STRANDED_TTL_MS) return hit.count;
43019
- const count = findStrandedSymbols(r.engine.store).length;
43020
- strandedCache.set(r.id, { at: Date.now(), count });
43021
- return count;
43047
+ if (!strandedRefreshing.has(r.id)) {
43048
+ strandedRefreshing.add(r.id);
43049
+ const finish = (count) => {
43050
+ strandedCache.set(r.id, { at: Date.now(), count });
43051
+ strandedRefreshing.delete(r.id);
43052
+ };
43053
+ if (consolidateWorker && r.engine.paths.castalia !== ":memory:") {
43054
+ consolidateWorker.run({ kind: "strandedCount", sharedDbPath, castaliaPath: r.engine.paths.castalia }).then((n) => finish(Number(n))).catch(() => {
43055
+ setImmediate(() => {
43056
+ const done = markPass(`stranded-scan:${r.entry.name}`);
43057
+ try {
43058
+ finish(findStrandedSymbols(r.engine.store).length);
43059
+ } catch {
43060
+ strandedRefreshing.delete(r.id);
43061
+ } finally {
43062
+ done();
43063
+ }
43064
+ });
43065
+ });
43066
+ } else {
43067
+ setImmediate(() => {
43068
+ const done = markPass(`stranded-scan:${r.entry.name}`);
43069
+ try {
43070
+ finish(findStrandedSymbols(r.engine.store).length);
43071
+ } catch {
43072
+ strandedRefreshing.delete(r.id);
43073
+ } finally {
43074
+ done();
43075
+ }
43076
+ });
43077
+ }
43078
+ }
43079
+ return hit?.count ?? -1;
43022
43080
  };
43023
43081
  app.get(
43024
43082
  "/health",
@@ -43047,13 +43105,18 @@ async function startMultiDaemon(opts = {}) {
43047
43105
  const owner = ownerOf(records, pathInBody(body2));
43048
43106
  if (!owner) return c.json({ error: "no-matching-project" }, 404);
43049
43107
  const sub = c.req.path;
43050
- return owner.webApp.fetch(
43051
- new Request(`http://local${sub}`, {
43052
- method: "POST",
43053
- headers: { "content-type": "application/json" },
43054
- body: raw2
43055
- })
43056
- );
43108
+ const done = markPass(`${sub}:${owner.entry.name}`);
43109
+ try {
43110
+ return await owner.webApp.fetch(
43111
+ new Request(`http://local${sub}`, {
43112
+ method: "POST",
43113
+ headers: { "content-type": "application/json" },
43114
+ body: raw2
43115
+ })
43116
+ );
43117
+ } finally {
43118
+ done();
43119
+ }
43057
43120
  };
43058
43121
  app.post(
43059
43122
  "/api/hook",
@@ -43071,10 +43134,11 @@ async function startMultiDaemon(opts = {}) {
43071
43134
  return typeof loc === "string" ? fileUriToFsPath(loc) : void 0;
43072
43135
  })
43073
43136
  );
43074
- app.post("/api/turn", (c) => forward(c, (b) => b["cwd"]));
43075
- app.post("/api/message", (c) => forward(c, (b) => b["cwd"]));
43076
- app.post("/api/session-end", (c) => forward(c, (b) => b["cwd"]));
43077
- app.post("/api/context-inject", (c) => forward(c, (b) => b["cwd"]));
43137
+ const cwdOf = (b) => typeof b["cwd"] === "string" ? b["cwd"] : void 0;
43138
+ app.post("/api/turn", (c) => forward(c, cwdOf));
43139
+ app.post("/api/message", (c) => forward(c, cwdOf));
43140
+ app.post("/api/session-end", (c) => forward(c, cwdOf));
43141
+ app.post("/api/context-inject", (c) => forward(c, cwdOf));
43078
43142
  for (const r of records) app.route(`/ws/${r.id}`, r.webApp);
43079
43143
  const reindexAll = async (rOpts) => {
43080
43144
  const out2 = /* @__PURE__ */ new Map();
@@ -43089,6 +43153,7 @@ async function startMultiDaemon(opts = {}) {
43089
43153
  out2.set(r.id, r.engine.store.nodeCount());
43090
43154
  continue;
43091
43155
  }
43156
+ const done = markPass(`reindex:${r.entry.name}`);
43092
43157
  try {
43093
43158
  const idx = await r.engine.reindex({ skipEmbed: rOpts?.skipEmbed ?? true, quiet: true });
43094
43159
  out2.set(r.id, idx.nodes);
@@ -43097,6 +43162,8 @@ async function startMultiDaemon(opts = {}) {
43097
43162
  } catch (err2) {
43098
43163
  console.warn(`[errata] index failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`);
43099
43164
  out2.set(r.id, r.engine.store.nodeCount());
43165
+ } finally {
43166
+ done();
43100
43167
  }
43101
43168
  }
43102
43169
  if (toIndex.length > 0) {
@@ -43133,6 +43200,7 @@ async function startMultiDaemon(opts = {}) {
43133
43200
  const out2 = /* @__PURE__ */ new Map();
43134
43201
  for (const r of records) {
43135
43202
  await new Promise((resolve5) => setImmediate(resolve5));
43203
+ const done = markPass(`package-index:${r.entry.name}`);
43136
43204
  try {
43137
43205
  out2.set(
43138
43206
  r.id,
@@ -43146,6 +43214,8 @@ async function startMultiDaemon(opts = {}) {
43146
43214
  );
43147
43215
  } catch (err2) {
43148
43216
  console.warn(`[errata] package index failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`);
43217
+ } finally {
43218
+ done();
43149
43219
  }
43150
43220
  }
43151
43221
  return out2;
@@ -43160,10 +43230,13 @@ async function startMultiDaemon(opts = {}) {
43160
43230
  async tickAll() {
43161
43231
  const out2 = /* @__PURE__ */ new Map();
43162
43232
  for (const r of records) {
43233
+ const done = markPass(`tick:${r.entry.name}`);
43163
43234
  try {
43164
43235
  out2.set(r.id, await r.engine.tick());
43165
43236
  } catch (err2) {
43166
43237
  console.warn(`[errata] tick failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`);
43238
+ } finally {
43239
+ done();
43167
43240
  }
43168
43241
  }
43169
43242
  return out2;
@@ -43171,10 +43244,13 @@ async function startMultiDaemon(opts = {}) {
43171
43244
  async nightlyAll() {
43172
43245
  const out2 = /* @__PURE__ */ new Map();
43173
43246
  for (const r of records) {
43247
+ const done = markPass(`nightly:${r.entry.name}`);
43174
43248
  try {
43175
43249
  out2.set(r.id, await r.engine.nightly());
43176
43250
  } catch (err2) {
43177
43251
  console.warn(`[errata] nightly failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`);
43252
+ } finally {
43253
+ done();
43178
43254
  }
43179
43255
  }
43180
43256
  return out2;
@@ -43205,12 +43281,15 @@ async function startMultiDaemon(opts = {}) {
43205
43281
  }
43206
43282
  }
43207
43283
  for (const r of inlineRecords) {
43284
+ const done = markPass(`percolate-inline:${r.entry.name}`);
43208
43285
  try {
43209
43286
  out2.set(r.id, percolate(r.engine.store, sharedStore, { workspaceId: r.engine.profile.id, ts }));
43210
43287
  } catch (err2) {
43211
43288
  console.warn(
43212
43289
  `[errata] percolate failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`
43213
43290
  );
43291
+ } finally {
43292
+ done();
43214
43293
  }
43215
43294
  }
43216
43295
  return out2;
@@ -43547,28 +43626,6 @@ async function loginOAuthLoopback(opts) {
43547
43626
  // src/update.ts
43548
43627
  import { spawn as spawn2 } from "node:child_process";
43549
43628
  var PACKAGE_NAME = "@inerrata-corporation/errata";
43550
- function parse3(v) {
43551
- const m = /^(\d+)\.(\d+)\.(\d+)(?:-dev\.(\d+))?/.exec(v.trim());
43552
- if (!m) return null;
43553
- return {
43554
- base: [Number(m[1]), Number(m[2]), Number(m[3])],
43555
- pre: m[4] === void 0 ? null : Number(m[4])
43556
- };
43557
- }
43558
- function compareVersions(a, b) {
43559
- const pa = parse3(a);
43560
- const pb = parse3(b);
43561
- if (!pa || !pb) return 0;
43562
- const [aMaj, aMin, aPatch] = pa.base;
43563
- const [bMaj, bMin, bPatch] = pb.base;
43564
- if (aMaj !== bMaj) return aMaj - bMaj;
43565
- if (aMin !== bMin) return aMin - bMin;
43566
- if (aPatch !== bPatch) return aPatch - bPatch;
43567
- if (pa.pre === pb.pre) return 0;
43568
- if (pa.pre === null) return 1;
43569
- if (pb.pre === null) return -1;
43570
- return pa.pre - pb.pre;
43571
- }
43572
43629
  async function latestPublished(channel, timeoutMs = 4e3) {
43573
43630
  const ctrl = new AbortController();
43574
43631
  const timer = setTimeout(() => ctrl.abort(), timeoutMs);
@@ -43591,7 +43648,7 @@ async function checkForUpdate(channel) {
43591
43648
  return {
43592
43649
  current: DAEMON_VERSION,
43593
43650
  latest,
43594
- updateAvailable: latest !== null && compareVersions(latest, DAEMON_VERSION) > 0
43651
+ updateAvailable: latest !== null && latest !== DAEMON_VERSION
43595
43652
  };
43596
43653
  }
43597
43654
  function runNpmInstall(channel) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.23",
3
+ "version": "2.0.0-dev.24",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {