@inerrata-corporation/errata 2.0.2-dev.344 → 2.0.2-dev.352

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.
package/errata.mjs CHANGED
@@ -20513,6 +20513,24 @@ function recordTriageObservation(l2, obs, ts) {
20513
20513
  });
20514
20514
  return { triageId, routeId };
20515
20515
  }
20516
+ function recordCauseChainLink(l2, link, ts, attrs = {}) {
20517
+ if (link.fromId === link.toId) return false;
20518
+ let created = false;
20519
+ l2.transaction(() => {
20520
+ for (const [id, description] of [
20521
+ [link.fromId, link.fromDescription],
20522
+ [link.toId, link.toDescription]
20523
+ ]) {
20524
+ if (!l2.getNode(id)) l2.mergeNode(semNode(id, "RootCause", description, ts, { ...attrs }));
20525
+ }
20526
+ const edgeId2 = `edge_cb_${link.fromId}_${link.toId}`;
20527
+ if (!l2.getEdge(edgeId2)) {
20528
+ l2.mergeEdge(semEdge(edgeId2, link.fromId, link.toId, "CAUSED_BY", ts, { witnessed: true, viaFold: true }));
20529
+ created = true;
20530
+ }
20531
+ });
20532
+ return created;
20533
+ }
20516
20534
  function recordMisreadPrior(shared, problem, context, contributor, ts) {
20517
20535
  if (problem.attrs["resolvedAs"] !== PROBLEM_RESOLUTION.FALSE_POSITIVE) return false;
20518
20536
  if (Number(problem.attrs["corroborations"] ?? 0) < 1) return false;
@@ -21248,6 +21266,7 @@ __export(src_exports2, {
21248
21266
  propagateVersionChange: () => propagateVersionChange,
21249
21267
  rankToolsForHandles: () => rankToolsForHandles,
21250
21268
  recordAnchorHint: () => recordAnchorHint,
21269
+ recordCauseChainLink: () => recordCauseChainLink,
21251
21270
  recordClaim: () => recordClaim,
21252
21271
  recordMisreadPrior: () => recordMisreadPrior,
21253
21272
  recordTriageObservation: () => recordTriageObservation,
@@ -21386,6 +21405,7 @@ function buildSnapshot(opts) {
21386
21405
  recentResolved,
21387
21406
  recentConstraints,
21388
21407
  ...causalNudge ? { causalNudge } : {},
21408
+ ...opts.selfCiteSkips && opts.selfCiteSkips > 0 ? { selfCiteSkips: opts.selfCiteSkips } : {},
21389
21409
  ...domainNudge ? { domainNudge } : {},
21390
21410
  motifs,
21391
21411
  reviewCount: opts.reviewCount,
@@ -21533,6 +21553,12 @@ function renderSnapshot(s) {
21533
21553
  lines.push("");
21534
21554
  }
21535
21555
  const tagOf = (n) => s.edgeElicitation ? ` \`[${priorHandle(n)}]\`` : "";
21556
+ if (s.selfCiteSkips) {
21557
+ lines.push(
21558
+ `_**${s.selfCiteSkips} of your citations last turn were dropped** \u2014 they named priors this same session captured, and corroboration counts independent sessions, so citing your own capture is void by construction. It still records the link; it just cannot corroborate. To corroborate, cite a prior you were SHOWN (the collective block, or a problem from an earlier session) \u2014 that is the evidence the graph is short of._`
21559
+ );
21560
+ lines.push("");
21561
+ }
21536
21562
  lines.push("### Recently observed problems in this workspace");
21537
21563
  if (s.recentProblems.length === 0 && s.recentResolved.length === 0 && s.recentConstraints.length === 0) {
21538
21564
  lines.push("- _none yet \u2014 errata is still building its model_");
@@ -50811,10 +50837,18 @@ function parseInlineTags(text) {
50811
50837
  sentence: sfield
50812
50838
  });
50813
50839
  if (f[1] === "!" && segs.length > 1) {
50840
+ let prevLink = null;
50814
50841
  for (const seg of segs.slice(1)) {
50815
50842
  const causeText = seg.replace(/\s+/g, " ").trim();
50816
50843
  if (causeText.length >= CAUSE_TEXT_MIN) {
50817
- out2.push({ kind: "triage", causeText, sentence: sfield, ...flagThread ? { threadId: flagThread } : {} });
50844
+ out2.push({
50845
+ kind: "triage",
50846
+ causeText,
50847
+ sentence: sfield,
50848
+ ...prevLink ? { causeOf: prevLink } : {},
50849
+ ...flagThread ? { threadId: flagThread } : {}
50850
+ });
50851
+ prevLink = causeText;
50818
50852
  }
50819
50853
  }
50820
50854
  }
@@ -51024,7 +51058,7 @@ function harvestInlineTags(store, text, opts) {
51024
51058
  const source = opts.sourceId ? store.getNode(opts.sourceId) : null;
51025
51059
  const mintPriors = opts.mintPriors ?? true;
51026
51060
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
51027
- const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
51061
+ const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], causalLinks: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
51028
51062
  const tags = parseInlineTags(text);
51029
51063
  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);
51030
51064
  const bindSymptom = (seq, threadId) => {
@@ -51093,7 +51127,16 @@ function harvestInlineTags(store, text, opts) {
51093
51127
  if (node2) plan.triages.push({ causeId: node2.id, causeDescription: node2.description, ...bound });
51094
51128
  } else if (tag.causeText) {
51095
51129
  const causeId = `dcause_${digest({ statement: tag.causeText })}`.slice(0, 56);
51096
- plan.triages.push({ causeId, causeDescription: tag.causeText, ...bound });
51130
+ if (tag.causeOf) {
51131
+ plan.causalLinks.push({
51132
+ fromId: `dcause_${digest({ statement: tag.causeOf })}`.slice(0, 56),
51133
+ fromDescription: tag.causeOf,
51134
+ toId: causeId,
51135
+ toDescription: tag.causeText
51136
+ });
51137
+ } else {
51138
+ plan.triages.push({ causeId, causeDescription: tag.causeText, ...bound });
51139
+ }
51097
51140
  }
51098
51141
  } else if (tag.kind === "transfer") {
51099
51142
  const targetIds = [];
@@ -53200,7 +53243,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53200
53243
  }
53201
53244
 
53202
53245
  // src/engine.ts
53203
- var DAEMON_VERSION = true ? "2.0.2-dev.344" : "2.0.0-alpha.0";
53246
+ var DAEMON_VERSION = true ? "2.0.2-dev.352" : "2.0.0-alpha.0";
53204
53247
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53205
53248
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53206
53249
  var GIT_OP_MUTE_MS = 4e3;
@@ -53513,6 +53556,7 @@ function createWorkspaceEngine(opts) {
53513
53556
  const REMOTE_REFRESH_MS = 5 * 6e4;
53514
53557
  let ctxRefreshInFlight = false;
53515
53558
  let ctxRefreshQueued = false;
53559
+ let lastSelfCiteSkips = 0;
53516
53560
  const refreshContextNow = () => {
53517
53561
  void refreshContextAsync().catch((err2) => {
53518
53562
  console.warn("[errata] context refresh failed:", err2 instanceof Error ? err2.message : err2);
@@ -53542,7 +53586,8 @@ function createWorkspaceEngine(opts) {
53542
53586
  reviewCount: pendingCount(paths),
53543
53587
  reviewUiUrl: opts.reviewUrl(),
53544
53588
  workingFile: workingFiles.mostRecent() ?? void 0,
53545
- skills: readSkillManifest(paths.skillsManifest)
53589
+ skills: readSkillManifest(paths.skillsManifest),
53590
+ ...lastSelfCiteSkips > 0 ? { selfCiteSkips: lastSelfCiteSkips } : {}
53546
53591
  };
53547
53592
  const prebuilt = passWorker ? await passWorker.snapshot(snapOpts).catch(() => null) : null;
53548
53593
  const doneRender = prebuilt ? null : markPass(`context-render-inline:${profile.name}`);
@@ -54038,6 +54083,17 @@ function createWorkspaceEngine(opts) {
54038
54083
  }
54039
54084
  }
54040
54085
  }
54086
+ if (opts.sharedStore) {
54087
+ for (const link of plan.causalLinks) {
54088
+ try {
54089
+ if (recordCauseChainLink(opts.sharedStore, link, t, { contributor: sessionId })) {
54090
+ triaged++;
54091
+ }
54092
+ } catch (err2) {
54093
+ console.warn("[errata] causal chain link failed:", err2);
54094
+ }
54095
+ }
54096
+ }
54041
54097
  for (const at of plan.attempts) {
54042
54098
  const pid = at.problemId ?? (at.threadId ? threads.get(at.threadId) : void 0) ?? (at.boundStatement ? designProblemId(at.boundStatement) : void 0);
54043
54099
  const node2 = pid ? store.getNode(pid) : void 0;
@@ -54238,6 +54294,8 @@ function createWorkspaceEngine(opts) {
54238
54294
  if (skipped > 0) {
54239
54295
  console.log(`[errata] corroborate: ${skipped} skipped (this session authored the node)`);
54240
54296
  appendWitnessLedger(paths.configDir, { ts: Date.now(), channel: "corroborate", clientSelfSkipped: skipped });
54297
+ lastSelfCiteSkips = skipped;
54298
+ refreshContextNow();
54241
54299
  }
54242
54300
  await sendWitnesses(
54243
54301
  "corroborate",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.344",
3
+ "version": "2.0.2-dev.352",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -26396,6 +26396,7 @@ function buildSnapshot(opts) {
26396
26396
  recentResolved,
26397
26397
  recentConstraints,
26398
26398
  ...causalNudge ? { causalNudge } : {},
26399
+ ...opts.selfCiteSkips && opts.selfCiteSkips > 0 ? { selfCiteSkips: opts.selfCiteSkips } : {},
26399
26400
  ...domainNudge ? { domainNudge } : {},
26400
26401
  motifs,
26401
26402
  reviewCount: opts.reviewCount,