@inerrata-corporation/errata 2.0.2-dev.720 → 2.0.2-dev.723

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 +191 -55
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -52305,33 +52305,34 @@ function readFrom(path2, fromByte, maxBytes) {
52305
52305
  try {
52306
52306
  fd = openSync(path2, "r");
52307
52307
  } catch {
52308
- return { text: "", nextOffset: fromByte, more: false };
52308
+ return { text: "", nextOffset: fromByte, more: false, ioFailed: true };
52309
52309
  }
52310
52310
  try {
52311
52311
  const size = fstatSync(fd).size;
52312
52312
  const start2 = fromByte > 0 && fromByte <= size ? fromByte : 0;
52313
52313
  const remaining = size - start2;
52314
- if (remaining <= 0) return { text: "", nextOffset: size, more: false };
52314
+ if (remaining <= 0) return { text: "", nextOffset: size, more: false, ioFailed: false };
52315
52315
  let cap = maxBytes && maxBytes > 0 ? maxBytes : remaining;
52316
52316
  for (; ; ) {
52317
52317
  const len = Math.min(cap, remaining);
52318
52318
  const buf = Buffer.allocUnsafe(len);
52319
52319
  readSync(fd, buf, 0, len, start2);
52320
52320
  if (len >= remaining) {
52321
- return { text: buf.toString("utf8"), nextOffset: size, more: false };
52321
+ return { text: buf.toString("utf8"), nextOffset: size, more: false, ioFailed: false };
52322
52322
  }
52323
52323
  const nl = buf.lastIndexOf(10);
52324
52324
  if (nl >= 0) {
52325
52325
  return {
52326
52326
  text: buf.subarray(0, nl + 1).toString("utf8"),
52327
52327
  nextOffset: start2 + nl + 1,
52328
- more: true
52328
+ more: true,
52329
+ ioFailed: false
52329
52330
  };
52330
52331
  }
52331
52332
  cap *= 2;
52332
52333
  }
52333
52334
  } catch {
52334
- return { text: "", nextOffset: fromByte, more: false };
52335
+ return { text: "", nextOffset: fromByte, more: false, ioFailed: true };
52335
52336
  } finally {
52336
52337
  closeSync(fd);
52337
52338
  }
@@ -52349,22 +52350,25 @@ function transcriptSize(path2) {
52349
52350
  }
52350
52351
  }
52351
52352
  function readTail(path2, maxBytes) {
52353
+ return readTailWithLosses(path2, maxBytes).text;
52354
+ }
52355
+ function readTailWithLosses(path2, maxBytes) {
52352
52356
  let fd;
52353
52357
  try {
52354
52358
  fd = openSync(path2, "r");
52355
52359
  } catch {
52356
- return "";
52360
+ return { text: "", bytesUnreachable: 0, ioFailed: true };
52357
52361
  }
52358
52362
  try {
52359
52363
  const size = fstatSync(fd).size;
52360
52364
  const start2 = Math.max(0, size - maxBytes);
52361
52365
  const len = size - start2;
52362
- if (len <= 0) return "";
52366
+ if (len <= 0) return { text: "", bytesUnreachable: 0, ioFailed: false };
52363
52367
  const buf = Buffer.allocUnsafe(len);
52364
52368
  readSync(fd, buf, 0, len, start2);
52365
- return buf.toString("utf8");
52369
+ return { text: buf.toString("utf8"), bytesUnreachable: start2, ioFailed: false };
52366
52370
  } catch {
52367
- return "";
52371
+ return { text: "", bytesUnreachable: 0, ioFailed: true };
52368
52372
  } finally {
52369
52373
  closeSync(fd);
52370
52374
  }
@@ -52424,15 +52428,30 @@ function isUserTurnBoundary(obj) {
52424
52428
  if (blocks.some((b) => b["type"] === "tool_result")) return false;
52425
52429
  return blocks.some((b) => b["type"] === "text");
52426
52430
  }
52427
- function readAssistantTurns(transcriptPath, includeThinking = true, maxBytes = 2e6) {
52428
- return parseAssistantTurns(readTail(transcriptPath, maxBytes), includeThinking);
52431
+ function readAssistantTurnsWithLosses(transcriptPath, includeThinking = true, maxBytes = 2e6) {
52432
+ const tail = readTailWithLosses(transcriptPath, maxBytes);
52433
+ const parsed = parseAssistantTurns(tail.text, includeThinking, false);
52434
+ return {
52435
+ turns: parsed.turns,
52436
+ losses: {
52437
+ parseFailures: parsed.parseFailures,
52438
+ ioFailed: tail.ioFailed,
52439
+ bytesUnreachable: tail.bytesUnreachable
52440
+ }
52441
+ };
52429
52442
  }
52430
52443
  function readAssistantTurnsFrom(transcriptPath, fromByte, includeThinking = true, maxBytes) {
52431
- const { text, nextOffset, more } = readFrom(transcriptPath, fromByte, maxBytes);
52432
- return { turns: parseAssistantTurns(text, includeThinking), nextOffset, more };
52444
+ const { text, nextOffset, more, ioFailed } = readFrom(transcriptPath, fromByte, maxBytes);
52445
+ const parsed = parseAssistantTurns(text, includeThinking, fromByte > 0);
52446
+ return {
52447
+ turns: parsed.turns,
52448
+ nextOffset,
52449
+ more,
52450
+ losses: { parseFailures: parsed.parseFailures, ioFailed, bytesUnreachable: 0 }
52451
+ };
52433
52452
  }
52434
- function parseAssistantTurns(raw2, includeThinking) {
52435
- if (!raw2) return [];
52453
+ function parseAssistantTurns(raw2, includeThinking, skipFirstLineParseFailure = false) {
52454
+ if (!raw2) return { turns: [], parseFailures: 0 };
52436
52455
  const turns = [];
52437
52456
  const lines = raw2.split(/\r?\n/);
52438
52457
  let lastFile;
@@ -52441,6 +52460,7 @@ function parseAssistantTurns(raw2, includeThinking) {
52441
52460
  let editedFile;
52442
52461
  let editedFileTurnSeq = 0;
52443
52462
  let turnSeq = 0;
52463
+ let parseFailures = 0;
52444
52464
  for (let i2 = 0; i2 < lines.length; i2++) {
52445
52465
  const line = lines[i2];
52446
52466
  if (!line) continue;
@@ -52448,6 +52468,7 @@ function parseAssistantTurns(raw2, includeThinking) {
52448
52468
  try {
52449
52469
  obj = JSON.parse(line);
52450
52470
  } catch {
52471
+ if (!(i2 === 0 && skipFirstLineParseFailure)) parseFailures++;
52451
52472
  continue;
52452
52473
  }
52453
52474
  if (isUserTurnBoundary(obj)) {
@@ -52489,7 +52510,7 @@ function parseAssistantTurns(raw2, includeThinking) {
52489
52510
  ...commands.length > 0 ? { commands } : {}
52490
52511
  });
52491
52512
  }
52492
- return turns;
52513
+ return { turns, parseFailures };
52493
52514
  }
52494
52515
  function turnsSince(turns, mark) {
52495
52516
  if (!mark) return turns;
@@ -52574,6 +52595,7 @@ var BUILDS_ON_PREFIX = /^\s*builds-on:(?:#([a-z][\w-]{0,63}))?\s*/i;
52574
52595
  var SUPERSEDES_PREFIX = /^\s*supersedes:(?:#([a-z][\w-]{0,63}))?\s*/i;
52575
52596
  var ALTERNATIVE_PREFIX = /^\s*alternative:(?:#([a-z][\w-]{0,63}))?\s*/i;
52576
52597
  var INSTANCE_PREFIX = /^\s*instance:\s*/i;
52598
+ var BRACKETED_TOKEN_RE = /\[[^\]\n]{1,120}\]/;
52577
52599
  var CONFIRM_PREFIX = /^\s*confirm:\s*/i;
52578
52600
  var REFUTE_PREFIX = /^\s*refute:\s*/i;
52579
52601
  var REFUTE_REASON_MIN = 4;
@@ -52611,18 +52633,44 @@ function deriveFixRationale(sentence, startIdx, endIdx) {
52611
52633
  if (before.length >= FIX_RATIONALE_MIN) return before;
52612
52634
  return fixRationaleAfter(sentence, endIdx);
52613
52635
  }
52636
+ function emptyTagDispositions() {
52637
+ return {
52638
+ oversizeSegments: 0,
52639
+ codeSpanNeutralized: 0,
52640
+ refuteTooShort: 0,
52641
+ causeTooShort: 0,
52642
+ negated: 0,
52643
+ unparseable: 0
52644
+ };
52645
+ }
52646
+ function addTagDispositions(a, b) {
52647
+ a.oversizeSegments += b.oversizeSegments;
52648
+ a.codeSpanNeutralized += b.codeSpanNeutralized;
52649
+ a.refuteTooShort += b.refuteTooShort;
52650
+ a.causeTooShort += b.causeTooShort;
52651
+ a.negated += b.negated;
52652
+ a.unparseable += b.unparseable;
52653
+ }
52614
52654
  function parseInlineTags(text) {
52655
+ return parseInlineTagsWithDispositions(text).tags;
52656
+ }
52657
+ function parseInlineTagsWithDispositions(text) {
52615
52658
  const out2 = [];
52659
+ const dispositions = emptyTagDispositions();
52616
52660
  const deFenced = text.replace(/```[\s\S]*?```/g, " ");
52617
52661
  let seqNo = -1;
52618
52662
  for (const raw2 of deFenced.split(/(?<=[.!?])\s+|\n+/)) {
52619
52663
  seqNo++;
52620
- if (raw2.length > 2e4) continue;
52664
+ if (raw2.length > 2e4) {
52665
+ dispositions.oversizeSegments++;
52666
+ continue;
52667
+ }
52621
52668
  const seqStart = out2.length;
52622
- const sentence = raw2.replace(
52623
- /`[^`]*`/g,
52624
- (m) => /\[[!?]|\((?:fix|cause|constraint|tried|failed|confirm|refute):|\(\[/.test(m) ? " " : m
52625
- );
52669
+ const sentence = raw2.replace(/`[^`]*`/g, (m) => {
52670
+ if (!/\[[!?]|\((?:fix|cause|constraint|tried|failed|confirm|refute):|\(\[/.test(m)) return m;
52671
+ dispositions.codeSpanNeutralized++;
52672
+ return " ";
52673
+ });
52626
52674
  const sfield = sentence.replace(/\s+/g, " ").trim().slice(0, 160);
52627
52675
  const citeMatched = /* @__PURE__ */ new Set();
52628
52676
  CITE_GROUP_RE.lastIndex = 0;
@@ -52672,6 +52720,7 @@ function parseInlineTags(text) {
52672
52720
  if (refuteM) {
52673
52721
  const reason = body2.replace(new RegExp(HANDLE_RE.source, "gi"), " ").replace(/\s+/g, " ").trim();
52674
52722
  if (reason.length >= REFUTE_REASON_MIN) out2.push({ kind: "refute", handle: handle2, statement: reason, sentence: sfield });
52723
+ else dispositions.refuteTooShort++;
52675
52724
  } else {
52676
52725
  out2.push({ kind: "confirm", handle: handle2, sentence: sfield });
52677
52726
  }
@@ -52692,11 +52741,14 @@ function parseInlineTags(text) {
52692
52741
  if (raw3.length >= CAUSE_TEXT_MIN) {
52693
52742
  const causeText = raw3;
52694
52743
  out2.push({ kind: "triage", causeText, sentence: sfield, ...verbThread ? { threadId: verbThread } : {} });
52695
- }
52744
+ } else dispositions.causeTooShort++;
52696
52745
  }
52697
52746
  continue;
52698
52747
  }
52699
- if (!isFix && NEG.test(clauseBefore(sentence, g.index))) continue;
52748
+ if (!isFix && NEG.test(clauseBefore(sentence, g.index))) {
52749
+ dispositions.negated++;
52750
+ continue;
52751
+ }
52700
52752
  let fixRationale;
52701
52753
  if (isFix) {
52702
52754
  const r = deriveFixRationale(sentence, g.index, g.index + g[0].length);
@@ -52722,6 +52774,9 @@ function parseInlineTags(text) {
52722
52774
  const note = content.replace(/\s+/g, " ").trim();
52723
52775
  if (note.length >= FIX_RATIONALE_MIN)
52724
52776
  out2.push({ kind: "fix", fixRationale: note, sentence: sfield, ...verbThread ? { threadId: verbThread } : {} });
52777
+ else dispositions.unparseable++;
52778
+ } else if (!isFix && !emittedHandle && BRACKETED_TOKEN_RE.test(content)) {
52779
+ dispositions.unparseable++;
52725
52780
  }
52726
52781
  }
52727
52782
  for (const pass of [
@@ -52889,7 +52944,7 @@ function parseInlineTags(text) {
52889
52944
  }
52890
52945
  for (let i2 = seqStart; i2 < out2.length; i2++) out2[i2].seq = seqNo;
52891
52946
  }
52892
- return out2;
52947
+ return { tags: out2, dispositions };
52893
52948
  }
52894
52949
  var LABEL_PAIR = {
52895
52950
  "Problem>RootCause": "CAUSED_BY",
@@ -53045,8 +53100,10 @@ function harvestInlineTags(store, text, opts) {
53045
53100
  const source = opts.sourceId ? store.getNode(opts.sourceId) : null;
53046
53101
  const mintPriors = opts.mintPriors ?? true;
53047
53102
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
53048
- const plan = { priorEdges: 0, corroboratedEdges: 0, exposureShown: 0, exposureEvicted: 0, exposureUnshown: 0, problems: [], fixes: [], triages: [], causalLinks: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
53049
- const tags = parseInlineTags(text);
53103
+ const plan = { priorEdges: 0, corroboratedEdges: 0, exposureShown: 0, exposureEvicted: 0, exposureUnshown: 0, problems: [], fixes: [], triages: [], causalLinks: [], attempts: [], unresolvedFixes: [], unresolvedHandles: [], priorEdgesSuppressed: { flagOff: 0, noSource: 0 }, dispositions: emptyTagDispositions(), transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
53104
+ const parsed = parseInlineTagsWithDispositions(text);
53105
+ const tags = parsed.tags;
53106
+ plan.dispositions = parsed.dispositions;
53050
53107
  const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement, threadId: t.threadId })).sort((a, b) => a.seq - b.seq);
53051
53108
  const bindSymptom = (seq, threadId) => {
53052
53109
  if (threadId) {
@@ -53068,6 +53125,11 @@ function harvestInlineTags(store, text, opts) {
53068
53125
  if (symptomSeqs.length === 1) return { statement: best.statement, evidence: "witnessed" };
53069
53126
  return { statement: best.statement, evidence: "inferred" };
53070
53127
  };
53128
+ const resolveCited = (kind, handle2) => {
53129
+ const id = resolveHandle(store, handle2, opts.handleMap) ?? null;
53130
+ if (!id) plan.unresolvedHandles.push({ kind, handle: handle2 });
53131
+ return id;
53132
+ };
53071
53133
  for (const tag of tags) {
53072
53134
  if (tag.kind === "problem" || tag.kind === "todo") {
53073
53135
  plan.problems.push({
@@ -53109,7 +53171,7 @@ function harvestInlineTags(store, text, opts) {
53109
53171
  evidence: b.evidence
53110
53172
  };
53111
53173
  if (tag.handle) {
53112
- const causeId = resolveHandle(store, tag.handle, opts.handleMap);
53174
+ const causeId = resolveCited("triage", tag.handle);
53113
53175
  const node2 = causeId ? store.getNode(causeId) : null;
53114
53176
  if (node2) plan.triages.push({ causeId: node2.id, causeDescription: node2.description, ...bound });
53115
53177
  } else if (tag.causeText) {
@@ -53128,7 +53190,7 @@ function harvestInlineTags(store, text, opts) {
53128
53190
  } else if (tag.kind === "transfer") {
53129
53191
  const targetIds = [];
53130
53192
  for (const h of tag.handles ?? []) {
53131
- const id = resolveHandle(store, h, opts.handleMap);
53193
+ const id = resolveCited("transfer", h);
53132
53194
  if (id && !targetIds.includes(id)) targetIds.push(id);
53133
53195
  }
53134
53196
  if (targetIds.length > 0) {
@@ -53142,7 +53204,7 @@ function harvestInlineTags(store, text, opts) {
53142
53204
  } else if (tag.kind === "builds-on" || tag.kind === "supersedes" || tag.kind === "alternative") {
53143
53205
  const targetIds = [];
53144
53206
  for (const h of tag.handles ?? []) {
53145
- const id = resolveHandle(store, h, opts.handleMap);
53207
+ const id = resolveCited(tag.kind, h);
53146
53208
  if (id && !targetIds.includes(id)) targetIds.push(id);
53147
53209
  }
53148
53210
  if (targetIds.length > 0) {
@@ -53158,7 +53220,7 @@ function harvestInlineTags(store, text, opts) {
53158
53220
  } else if (tag.kind === "instance") {
53159
53221
  const targetIds = [];
53160
53222
  for (const h of tag.handles ?? []) {
53161
- const id = resolveHandle(store, h, opts.handleMap);
53223
+ const id = resolveCited("instance", h);
53162
53224
  if (id && !targetIds.includes(id)) targetIds.push(id);
53163
53225
  }
53164
53226
  if (targetIds.length > 0) {
@@ -53180,7 +53242,7 @@ function harvestInlineTags(store, text, opts) {
53180
53242
  evidence: b.evidence
53181
53243
  };
53182
53244
  if (tag.handle) {
53183
- const patternId = resolveHandle(store, tag.handle, opts.handleMap);
53245
+ const patternId = resolveCited("pattern", tag.handle);
53184
53246
  if (patternId) plan.patterns.push({ patternId, ...bound });
53185
53247
  } else if (tag.patternText) {
53186
53248
  plan.patterns.push({ patternText: tag.patternText, ...bound });
@@ -53206,7 +53268,7 @@ function harvestInlineTags(store, text, opts) {
53206
53268
  else plan.components.push({ componentText: tag.componentText, ...bound });
53207
53269
  } else if (tag.kind === "attempt" || tag.kind === "failure") {
53208
53270
  for (const h of tag.refuteHandles ?? []) {
53209
- const nodeId = resolveHandle(store, h, opts.handleMap);
53271
+ const nodeId = resolveCited("refute", h);
53210
53272
  if (nodeId) {
53211
53273
  const witnessKey = `refute:${nodeId}:${digest({ s: tag.statement ?? "" })}`.slice(0, 72);
53212
53274
  if (!plan.refutes.some((r) => r.witnessKey === witnessKey)) {
@@ -53229,7 +53291,7 @@ function harvestInlineTags(store, text, opts) {
53229
53291
  });
53230
53292
  }
53231
53293
  } else if (tag.kind === "confirm" || tag.kind === "refute") {
53232
- const targetId = resolveHandle(store, tag.handle, opts.handleMap);
53294
+ const targetId = resolveCited(tag.kind, tag.handle);
53233
53295
  const target = targetId ? store.getNode(targetId) : null;
53234
53296
  const citedLabel = target?.label ?? opts.handleMap[tag.handle]?.label;
53235
53297
  if (targetId && citedLabel && CORROBORATABLE_LABELS.has(citedLabel)) {
@@ -53250,7 +53312,7 @@ function harvestInlineTags(store, text, opts) {
53250
53312
  }
53251
53313
  }
53252
53314
  } else if (tag.kind === "prior") {
53253
- const targetId = resolveHandle(store, tag.handle, opts.handleMap);
53315
+ const targetId = resolveCited("prior", tag.handle);
53254
53316
  const target = targetId ? store.getNode(targetId) : null;
53255
53317
  const citedLabel = target?.label ?? opts.handleMap[tag.handle]?.label;
53256
53318
  if (targetId && citedLabel && CORROBORATABLE_LABELS.has(citedLabel)) {
@@ -53269,9 +53331,12 @@ function harvestInlineTags(store, text, opts) {
53269
53331
  plan.priorEdges++;
53270
53332
  if (m.corroborated) plan.corroboratedEdges++;
53271
53333
  }
53334
+ } else if (target) {
53335
+ if (!mintPriors) plan.priorEdgesSuppressed.flagOff++;
53336
+ else if (!source) plan.priorEdgesSuppressed.noSource++;
53272
53337
  }
53273
53338
  } else if (mintPriors && source) {
53274
- const targetId = resolveHandle(store, tag.handle, opts.handleMap);
53339
+ const targetId = resolveCited(tag.kind, tag.handle);
53275
53340
  const target = targetId ? store.getNode(targetId) : null;
53276
53341
  if (target) {
53277
53342
  const m = mintPriorEdge(store, source, target, tag.sentence, touched, opts.ts);
@@ -53280,6 +53345,9 @@ function harvestInlineTags(store, text, opts) {
53280
53345
  if (m.corroborated) plan.corroboratedEdges++;
53281
53346
  }
53282
53347
  }
53348
+ } else if (tag.handle) {
53349
+ if (!mintPriors) plan.priorEdgesSuppressed.flagOff++;
53350
+ else if (!source) plan.priorEdgesSuppressed.noSource++;
53283
53351
  }
53284
53352
  }
53285
53353
  return plan;
@@ -55256,16 +55324,19 @@ var WITNESS_MAX_ATTEMPTS = 5;
55256
55324
  function witnessQueuePath(workspaceConfigDir) {
55257
55325
  return join25(workspaceConfigDir, "witness-queue.json");
55258
55326
  }
55259
- function loadWitnessQueue(path2) {
55327
+ function loadWitnessQueueWithLosses(path2) {
55328
+ let raw2;
55260
55329
  try {
55261
- const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
55262
- if (!Array.isArray(raw2)) return [];
55263
- return raw2.filter(
55264
- (w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
55265
- );
55266
- } catch {
55267
- return [];
55330
+ raw2 = JSON.parse(readFileSync20(path2, "utf8"));
55331
+ } catch (err2) {
55332
+ const absent = err2?.code === "ENOENT";
55333
+ return { queue: [], fileUnreadable: !absent, malformedEntries: 0 };
55268
55334
  }
55335
+ if (!Array.isArray(raw2)) return { queue: [], fileUnreadable: true, malformedEntries: 0 };
55336
+ const queue = raw2.filter(
55337
+ (w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
55338
+ );
55339
+ return { queue, fileUnreadable: false, malformedEntries: raw2.length - queue.length };
55269
55340
  }
55270
55341
  function saveWitnessQueue(path2, queue) {
55271
55342
  try {
@@ -55276,10 +55347,21 @@ function saveWitnessQueue(path2, queue) {
55276
55347
  }
55277
55348
  }
55278
55349
  function pruneWitnessQueue(queue, now) {
55279
- const live2 = queue.filter(
55280
- (w) => now - w.ts < WITNESS_TTL_MS && w.attempts < WITNESS_MAX_ATTEMPTS
55281
- );
55282
- return live2.length > WITNESS_QUEUE_CAP ? live2.slice(live2.length - WITNESS_QUEUE_CAP) : live2;
55350
+ return pruneWitnessQueueWithDispositions(queue, now).queue;
55351
+ }
55352
+ function pruneWitnessQueueWithDispositions(queue, now) {
55353
+ const dropped = { expiredTtl: 0, exhaustedAttempts: 0, cappedOverflow: 0 };
55354
+ const live2 = [];
55355
+ for (const w of queue) {
55356
+ if (now - w.ts >= WITNESS_TTL_MS) dropped.expiredTtl++;
55357
+ else if (w.attempts >= WITNESS_MAX_ATTEMPTS) dropped.exhaustedAttempts++;
55358
+ else live2.push(w);
55359
+ }
55360
+ if (live2.length > WITNESS_QUEUE_CAP) {
55361
+ dropped.cappedOverflow = live2.length - WITNESS_QUEUE_CAP;
55362
+ return { queue: live2.slice(live2.length - WITNESS_QUEUE_CAP), dropped };
55363
+ }
55364
+ return { queue: live2, dropped };
55283
55365
  }
55284
55366
  function enqueueWitnesses(queue, fresh, now) {
55285
55367
  const byKey = new Map(queue.map((w) => [`${w.channel}:${w.witnessKey}`, w]));
@@ -55611,7 +55693,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
55611
55693
  }
55612
55694
 
55613
55695
  // src/engine.ts
55614
- var DAEMON_VERSION = true ? "2.0.2-dev.720" : "2.0.0-alpha.0";
55696
+ var DAEMON_VERSION = true ? "2.0.2-dev.723" : "2.0.0-alpha.0";
55615
55697
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
55616
55698
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
55617
55699
  var GIT_OP_MUTE_MS = 4e3;
@@ -55718,10 +55800,19 @@ function createWorkspaceEngine(opts) {
55718
55800
  refreshRepoLocator(opts.workspaceRoot, profile);
55719
55801
  }
55720
55802
  const store = openGraphStore({ path: paths.castalia });
55721
- let witnessQueue = pruneWitnessQueue(
55722
- loadWitnessQueue(witnessQueuePath(paths.configDir)),
55723
- Date.now()
55724
- );
55803
+ const witnessLoad = loadWitnessQueueWithLosses(witnessQueuePath(paths.configDir));
55804
+ const witnessPrune = pruneWitnessQueueWithDispositions(witnessLoad.queue, Date.now());
55805
+ let witnessQueue = witnessPrune.queue;
55806
+ if (witnessLoad.fileUnreadable || witnessLoad.malformedEntries > 0 || witnessPrune.dropped.expiredTtl > 0 || witnessPrune.dropped.exhaustedAttempts > 0 || witnessPrune.dropped.cappedOverflow > 0) {
55807
+ appendPassLedger(paths.configDir, "witness-queue", 0, {
55808
+ loaded: witnessQueue.length,
55809
+ fileUnreadable: witnessLoad.fileUnreadable ? 1 : 0,
55810
+ malformedEntries: witnessLoad.malformedEntries,
55811
+ prunedExpiredTtl: witnessPrune.dropped.expiredTtl,
55812
+ prunedExhaustedAttempts: witnessPrune.dropped.exhaustedAttempts,
55813
+ prunedCappedOverflow: witnessPrune.dropped.cappedOverflow
55814
+ });
55815
+ }
55725
55816
  const log = openEventLog({ path: paths.eventLog });
55726
55817
  const bundled = import.meta.url.endsWith(".mjs");
55727
55818
  const passWorker = bundled && paths.castalia !== ":memory:" ? new PassWorker({
@@ -56352,6 +56443,7 @@ function createWorkspaceEngine(opts) {
56352
56443
  const turnCursorPath = join27(paths.configDir, "turn-cursors.json");
56353
56444
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
56354
56445
  const turnOffset = loadTurnOffsets(turnCursorPath);
56446
+ const readLosses = { parseFailures: 0, ioFailures: 0, bytesUnreachable: 0, sliceGuardHits: 0 };
56355
56447
  const sessionLastProblem = /* @__PURE__ */ new Map();
56356
56448
  const sessionThreads = /* @__PURE__ */ new Map();
56357
56449
  const harvestTexts = async (sessionId, items) => {
@@ -56373,6 +56465,10 @@ function createWorkspaceEngine(opts) {
56373
56465
  let exposureEvicted = 0;
56374
56466
  let exposureUnshown = 0;
56375
56467
  let corroboratedEdges = 0;
56468
+ const dispositions = emptyTagDispositions();
56469
+ let unresolvedHandles = 0;
56470
+ let priorEdgesFlagOff = 0;
56471
+ let priorEdgesNoSource = 0;
56376
56472
  let touchedFileTurns = 0;
56377
56473
  let touchedToolTurns = 0;
56378
56474
  let anchorHintsUpgraded = 0;
@@ -56506,6 +56602,10 @@ function createWorkspaceEngine(opts) {
56506
56602
  });
56507
56603
  priorEdges += plan.priorEdges;
56508
56604
  corroboratedEdges += plan.corroboratedEdges;
56605
+ addTagDispositions(dispositions, plan.dispositions);
56606
+ unresolvedHandles += plan.unresolvedHandles.length;
56607
+ priorEdgesFlagOff += plan.priorEdgesSuppressed.flagOff;
56608
+ priorEdgesNoSource += plan.priorEdgesSuppressed.noSource;
56509
56609
  exposureShown += plan.exposureShown;
56510
56610
  exposureEvicted += plan.exposureEvicted;
56511
56611
  exposureUnshown += plan.exposureUnshown;
@@ -56941,8 +57041,32 @@ function createWorkspaceEngine(opts) {
56941
57041
  // touchedToolTurns 0 with this >0 = the hook and harvest disagree on
56942
57042
  // the session key; 0 with 0 = records never happen.
56943
57043
  toolSessionsTracked: toolRuns.sessions(),
56944
- seqAdvanced: store.currentIngestSeq() - seqAtStart
57044
+ seqAdvanced: store.currentIngestSeq() - seqAtStart,
57045
+ // TEL T1.1/T1.2/T1.3 — the capture path's drops. `tagsCodeSpan` and
57046
+ // `tagsUnparseable` rising means the vocabulary and the writer disagree
57047
+ // (our bug); `tagsRefuteTooShort` means a demotion verdict was lost;
57048
+ // `unresolvedHandles` means an agent cited a prior we could no longer
57049
+ // name. Every one of these used to be a silent `continue`.
57050
+ tagsOversize: dispositions.oversizeSegments,
57051
+ tagsCodeSpan: dispositions.codeSpanNeutralized,
57052
+ tagsRefuteTooShort: dispositions.refuteTooShort,
57053
+ tagsCauseTooShort: dispositions.causeTooShort,
57054
+ tagsNegated: dispositions.negated,
57055
+ tagsUnparseable: dispositions.unparseable,
57056
+ unresolvedHandles,
57057
+ priorEdgesFlagOff,
57058
+ priorEdgesNoSource,
57059
+ // TEL T1.7/T1.8 — transcript-read losses. `harvestBytesUnreachable` is
57060
+ // the only counter here measuring knowledge that can never be recovered.
57061
+ harvestParseFailures: readLosses.parseFailures,
57062
+ harvestIoFailures: readLosses.ioFailures,
57063
+ harvestBytesUnreachable: readLosses.bytesUnreachable,
57064
+ harvestSliceGuardHits: readLosses.sliceGuardHits
56945
57065
  });
57066
+ readLosses.parseFailures = 0;
57067
+ readLosses.ioFailures = 0;
57068
+ readLosses.bytesUnreachable = 0;
57069
+ readLosses.sliceGuardHits = 0;
56946
57070
  }
56947
57071
  };
56948
57072
  const harvestTurns = async (sessionId, transcriptPath) => {
@@ -56951,12 +57075,20 @@ function createWorkspaceEngine(opts) {
56951
57075
  let nextOffset;
56952
57076
  try {
56953
57077
  if (known === void 0) {
56954
- turns = readAssistantTurns(transcriptPath);
57078
+ const first = readAssistantTurnsWithLosses(transcriptPath);
57079
+ turns = first.turns;
56955
57080
  nextOffset = transcriptSize(transcriptPath);
57081
+ readLosses.bytesUnreachable += first.losses.bytesUnreachable;
57082
+ readLosses.parseFailures += first.losses.parseFailures;
57083
+ if (first.losses.ioFailed) readLosses.ioFailures++;
56956
57084
  } else {
56957
- ({ turns, nextOffset } = readAssistantTurnsFrom(transcriptPath, known, true, HARVEST_SLICE_BYTES));
57085
+ const slice = readAssistantTurnsFrom(transcriptPath, known, true, HARVEST_SLICE_BYTES);
57086
+ ({ turns, nextOffset } = slice);
57087
+ readLosses.parseFailures += slice.losses.parseFailures;
57088
+ if (slice.losses.ioFailed) readLosses.ioFailures++;
56958
57089
  }
56959
57090
  } catch {
57091
+ readLosses.ioFailures++;
56960
57092
  return;
56961
57093
  }
56962
57094
  for (let slice = 0; ; slice++) {
@@ -56968,6 +57100,7 @@ function createWorkspaceEngine(opts) {
56968
57100
  }
56969
57101
  saveTurnCursors(turnCursorPath, lastTurnUuid, turnOffset);
56970
57102
  if (slice >= 256) {
57103
+ readLosses.sliceGuardHits++;
56971
57104
  console.warn("[errata] harvest slice guard hit \u2014 backlog resumes next tick");
56972
57105
  break;
56973
57106
  }
@@ -56975,8 +57108,11 @@ function createWorkspaceEngine(opts) {
56975
57108
  try {
56976
57109
  next = readAssistantTurnsFrom(transcriptPath, nextOffset, true, HARVEST_SLICE_BYTES);
56977
57110
  } catch {
57111
+ readLosses.ioFailures++;
56978
57112
  break;
56979
57113
  }
57114
+ readLosses.parseFailures += next.losses.parseFailures;
57115
+ if (next.losses.ioFailed) readLosses.ioFailures++;
56980
57116
  if (next.turns.length === 0 && !next.more) {
56981
57117
  turnOffset.set(sessionId, next.nextOffset);
56982
57118
  saveTurnCursors(turnCursorPath, lastTurnUuid, turnOffset);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.720",
3
+ "version": "2.0.2-dev.723",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {