@inerrata-corporation/errata 2.0.2-dev.220 → 2.0.2-dev.226

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 (2) hide show
  1. package/errata.mjs +69 -25
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -22012,11 +22012,26 @@ var init_client = __esm({
22012
22012
  * drain (endpoint-label validation is deferred to the service when an endpoint
22013
22013
  * isn't in-payload), so the split never orphans an edge. Sub-results concat into
22014
22014
  * one. (fix: an un-chunked >200-node backlog 413'd forever and never drained.) */
22015
- async ingest(batch) {
22015
+ async ingest(batch, opts = {}) {
22016
22016
  const runId = randomUUID();
22017
+ const startedAt = Date.now();
22018
+ const totalChunks = Math.max(1, Math.ceil(batch.nodes.length / INGEST_NODE_CHUNK)) + Math.ceil(Math.max(0, batch.edges.length - MAX_EDGES_PER_PAYLOAD) / MAX_EDGES_PER_PAYLOAD);
22019
+ let chunkIndex = 0;
22020
+ const emit = (nodeIds, accepted) => {
22021
+ chunkIndex++;
22022
+ opts.onChunk?.({
22023
+ chunkIndex,
22024
+ totalChunks,
22025
+ nodeIds,
22026
+ accepted,
22027
+ elapsedMs: Date.now() - startedAt
22028
+ });
22029
+ };
22017
22030
  if (batch.nodes.length <= INGEST_NODE_CHUNK && batch.edges.length <= MAX_EDGES_PER_PAYLOAD) {
22018
22031
  const result = await this.ingestWithSplit(batch, batch.nodes, batch.edges);
22019
- return { ...summarizeIngestResult(result), result };
22032
+ const summary = summarizeIngestResult(result);
22033
+ emit(batch.nodes.map((n) => n.id), summary.accepted);
22034
+ return { ...summary, result };
22020
22035
  }
22021
22036
  const merged = { runId, nodes: [], edges: [] };
22022
22037
  let pendingEdges = [...batch.edges];
@@ -22029,6 +22044,7 @@ var init_client = __esm({
22029
22044
  pendingEdges = pendingEdges.filter((e) => !shipped.has(e));
22030
22045
  }
22031
22046
  const r = await this.ingestWithSplit(batch, nodeChunk, inChunk);
22047
+ emit(nodeChunk.map((n) => n.id), summarizeIngestResult(r).accepted);
22032
22048
  merged.nodes.push(...r.nodes);
22033
22049
  merged.edges.push(...r.edges);
22034
22050
  for (const rn of r.nodes) {
@@ -22047,6 +22063,7 @@ var init_client = __esm({
22047
22063
  to: echoedCloudId.get(e.to) ?? e.to
22048
22064
  }));
22049
22065
  const r = await this.ingestWire(toWirePayload({ ...batch, nodes: [], edges: rewritten }, randomUUID()));
22066
+ emit([], summarizeIngestResult(r).accepted);
22050
22067
  merged.edges.push(...r.edges);
22051
22068
  }
22052
22069
  return { ...summarizeIngestResult(merged), result: merged };
@@ -52374,7 +52391,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
52374
52391
  }
52375
52392
 
52376
52393
  // src/engine.ts
52377
- var DAEMON_VERSION = true ? "2.0.2-dev.220" : "2.0.0-alpha.0";
52394
+ var DAEMON_VERSION = true ? "2.0.2-dev.226" : "2.0.0-alpha.0";
52378
52395
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
52379
52396
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
52380
52397
  var GIT_OP_MUTE_MS = 4e3;
@@ -54031,6 +54048,7 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
54031
54048
  const ignored = (s) => ignorePatterns.length > 0 && ignorePatterns.some((p) => s.toLowerCase().includes(p));
54032
54049
  const nodes = [];
54033
54050
  const seen = /* @__PURE__ */ new Set();
54051
+ const localIdByWireId = {};
54034
54052
  for (const label of labels) {
54035
54053
  for (const n of store.findNodesByLabel(label)) {
54036
54054
  if (n.attrs["source"] === "cloud") continue;
@@ -54060,6 +54078,7 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
54060
54078
  anchorVisibility: "public"
54061
54079
  });
54062
54080
  seen.add(n.id);
54081
+ localIdByWireId[nodes[nodes.length - 1].id] = n.id;
54063
54082
  }
54064
54083
  }
54065
54084
  if (nodes.length === 0) return null;
@@ -54079,7 +54098,7 @@ function buildContextIngest(store, profile, daemonVersion, ignorePatterns = [],
54079
54098
  nodes,
54080
54099
  edges
54081
54100
  };
54082
- return { ...base, payloadDigest: digest(base), localIds: [...seen] };
54101
+ return { ...base, payloadDigest: digest(base), localIds: [...seen], localIdByWireId };
54083
54102
  }
54084
54103
 
54085
54104
  // src/lockfile-auto.ts
@@ -54943,24 +54962,30 @@ async function startMultiDaemon(opts = {}) {
54943
54962
  boundaryFlushLastAdvanceAt = Date.now();
54944
54963
  boundaryFlushUnits = 0;
54945
54964
  boundaryFlushBatches = 0;
54965
+ boundaryFlushItems = 0;
54966
+ boundaryFlushDetail = "";
54946
54967
  boundaryFlushStage = stage;
54947
54968
  };
54948
54969
  const flushStage = (stage) => {
54949
54970
  boundaryFlushStage = stage;
54950
54971
  };
54951
- const noteFlushProgress = (units) => {
54972
+ let boundaryFlushItems = 0;
54973
+ let boundaryFlushDetail = "";
54974
+ const noteFlushProgress = (units, items = 0, detail = "") => {
54952
54975
  boundaryFlushBatches++;
54953
- if (units > 0) {
54954
- boundaryFlushUnits += units;
54955
- boundaryFlushLastAdvanceAt = Date.now();
54956
- }
54976
+ boundaryFlushUnits += Math.max(0, units);
54977
+ boundaryFlushItems += Math.max(0, items);
54978
+ if (detail) boundaryFlushDetail = detail;
54979
+ if (units > 0 || items > 0) boundaryFlushLastAdvanceAt = Date.now();
54957
54980
  };
54958
54981
  const flushSnapshot = () => ({
54959
54982
  running: boundaryFlushing,
54960
54983
  stage: boundaryFlushStage,
54984
+ detail: boundaryFlushDetail,
54961
54985
  ageMs: boundaryFlushStartedAt ? Date.now() - boundaryFlushStartedAt : 0,
54962
54986
  units: boundaryFlushUnits,
54963
- batches: boundaryFlushBatches,
54987
+ items: boundaryFlushItems,
54988
+ chunks: boundaryFlushBatches,
54964
54989
  stalledMs: boundaryFlushLastAdvanceAt ? Date.now() - boundaryFlushLastAdvanceAt : 0
54965
54990
  });
54966
54991
  const endFlush = () => {
@@ -55543,10 +55568,8 @@ async function startMultiDaemon(opts = {}) {
55543
55568
  const errors = [];
55544
55569
  const lane = async (name2, projectName, run3) => {
55545
55570
  try {
55546
- const accepted = await run3();
55547
- noteFlushProgress(typeof accepted === "number" ? accepted : 0);
55571
+ await run3();
55548
55572
  } catch (err2) {
55549
- noteFlushProgress(0);
55550
55573
  const msg = `[${projectName}] ${name2}: ${err2 instanceof Error ? err2.message : String(err2)}`;
55551
55574
  errors.push(msg);
55552
55575
  console.error(`[sync\u2192cloud] ${msg}`);
@@ -55560,14 +55583,19 @@ async function startMultiDaemon(opts = {}) {
55560
55583
  });
55561
55584
  if (context) {
55562
55585
  await lane("context", projectName, async () => {
55563
- const res = await client.ingest(context);
55586
+ const res = await client.ingest(context, {
55587
+ onChunk: (p) => {
55588
+ const seq = store.currentIngestSeq();
55589
+ for (const wireId of p.nodeIds) {
55590
+ const localId = context.localIdByWireId[wireId] ?? wireId;
55591
+ const local = store.getNode(localId);
55592
+ if (!local) continue;
55593
+ store.updateNode(localId, { attrs: { ...local.attrs, contributedAtSeq: seq } });
55594
+ }
55595
+ noteFlushProgress(p.accepted, p.nodeIds.length, `context ${p.chunkIndex}/${p.totalChunks}`);
55596
+ }
55597
+ });
55564
55598
  uploaded += res.accepted;
55565
- const seq = store.currentIngestSeq();
55566
- for (const localId of context.localIds) {
55567
- const local = store.getNode(localId);
55568
- if (!local) continue;
55569
- store.updateNode(localId, { attrs: { ...local.attrs, contributedAtSeq: seq } });
55570
- }
55571
55599
  return res.accepted;
55572
55600
  });
55573
55601
  }
@@ -55593,7 +55621,9 @@ async function startMultiDaemon(opts = {}) {
55593
55621
  if (instances) {
55594
55622
  if (project) instances.projectId = project.projectId;
55595
55623
  await lane("instances", projectName, async () => {
55596
- const res = await client.ingest(instances);
55624
+ const res = await client.ingest(instances, {
55625
+ onChunk: (p) => noteFlushProgress(p.accepted, p.nodeIds.length, `instances ${p.chunkIndex}/${p.totalChunks}`)
55626
+ });
55597
55627
  uploaded += res.accepted;
55598
55628
  const seq = store.currentIngestSeq();
55599
55629
  const cloudIdByLocal = new Map(
@@ -58604,16 +58634,18 @@ async function cmdSync(arg) {
58604
58634
  const dur = ageMs >= 6e4 ? `${Math.floor(ageMs / 6e4)}m` : `${Math.max(1, Math.round(ageMs / 1e3))}s`;
58605
58635
  const stage = body2?.stage ? ` \u2014 stage: ${body2.stage}` : "";
58606
58636
  const units = typeof body2?.units === "number" ? body2.units : 0;
58607
- const batches = typeof body2?.batches === "number" ? body2.batches : 0;
58637
+ const items = typeof body2?.items === "number" ? body2.items : 0;
58638
+ const chunks = typeof body2?.chunks === "number" ? body2.chunks : 0;
58608
58639
  const stalledMs = typeof body2?.stalledMs === "number" ? body2.stalledMs : 0;
58609
- const moved = batches > 0 ? ` \xB7 ${batches} batch(es), ${units} accepted` : "";
58640
+ const where = body2?.detail ? ` [${body2.detail}]` : "";
58641
+ const moved = chunks > 0 ? ` \xB7 ${chunks} chunk(s), ${items} shipped, ${units} accepted${where}` : "";
58610
58642
  console.log(
58611
58643
  ageMs > 0 ? `sync already running: the daemon has been draining for ${dur}${stage}${moved}. It will finish on its own; nothing new was started.` : "sync already running: the daemon is mid-drain \u2014 it will finish on its own. Nothing new was started."
58612
58644
  );
58613
- if (stalledMs > 12e4 && batches > 0) {
58645
+ if (stalledMs > 12e4 && chunks > 0) {
58614
58646
  const stalledMin = Math.floor(stalledMs / 6e4);
58615
58647
  console.log(
58616
- ` \u26A0 STALLED: ${batches} batch(es) shipped but nothing accepted for ${stalledMin}m \u2014 the lane is looping, not draining. Check \`errata status\` for the backlog depth and daemon.log for the failing lane.`
58648
+ ` \u26A0 STALLED: ${chunks} chunk(s) shipped but nothing has moved for ${stalledMin}m \u2014 the lane is looping, not draining. Check \`errata status\` for the backlog depth and daemon.log for the failing lane.`
58617
58649
  );
58618
58650
  }
58619
58651
  if (ageMs > 30 * 6e4) {
@@ -58696,7 +58728,19 @@ async function cmdConsent(args2) {
58696
58728
  console.log(" note: run `errata login` to actually upload (no cloud credential yet).");
58697
58729
  }
58698
58730
  }
58731
+ function installLogTimestamps() {
58732
+ const ISO_AT_START = /^\[?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
58733
+ for (const level of ["log", "warn", "error"]) {
58734
+ const original = console[level].bind(console);
58735
+ console[level] = (...args2) => {
58736
+ const first = args2[0];
58737
+ if (typeof first === "string" && ISO_AT_START.test(first)) return original(...args2);
58738
+ original(`[${(/* @__PURE__ */ new Date()).toISOString()}]`, ...args2);
58739
+ };
58740
+ }
58741
+ }
58699
58742
  async function cmdDash(args2) {
58743
+ installLogTimestamps();
58700
58744
  const portIdx = args2.indexOf("--port");
58701
58745
  const port = portIdx >= 0 && args2[portIdx + 1] ? Number(args2[portIdx + 1]) : 7891;
58702
58746
  const reindexOnStart = !args2.includes("--no-reindex");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.220",
3
+ "version": "2.0.2-dev.226",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {