@inerrata-corporation/errata 2.0.0-dev.59 → 2.0.0-dev.61

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.
@@ -16853,6 +16853,12 @@ function recordTriageObservation(l2, obs, ts) {
16853
16853
  } else {
16854
16854
  l2.mergeEdge(semEdge(routeId, triageId, obs.causeId, wantType, ts, attrs));
16855
16855
  }
16856
+ if (obs.causal && (obs.causeLabel ?? "RootCause") === "RootCause" && obs.causeId !== presentingId) {
16857
+ const cbId = `edge_cb_${presentingId}_${obs.causeId}`;
16858
+ if (!l2.getEdge(cbId)) {
16859
+ l2.mergeEdge(semEdge(cbId, presentingId, obs.causeId, "CAUSED_BY", ts, { witnessed: true }));
16860
+ }
16861
+ }
16856
16862
  });
16857
16863
  return { triageId, routeId };
16858
16864
  }
package/errata.mjs CHANGED
@@ -19452,6 +19452,12 @@ function recordTriageObservation(l2, obs, ts) {
19452
19452
  } else {
19453
19453
  l2.mergeEdge(semEdge(routeId, triageId, obs.causeId, wantType, ts, attrs));
19454
19454
  }
19455
+ if (obs.causal && (obs.causeLabel ?? "RootCause") === "RootCause" && obs.causeId !== presentingId) {
19456
+ const cbId = `edge_cb_${presentingId}_${obs.causeId}`;
19457
+ if (!l2.getEdge(cbId)) {
19458
+ l2.mergeEdge(semEdge(cbId, presentingId, obs.causeId, "CAUSED_BY", ts, { witnessed: true }));
19459
+ }
19460
+ }
19455
19461
  });
19456
19462
  return { triageId, routeId };
19457
19463
  }
@@ -19713,7 +19719,8 @@ function harvestTriageFences(l2, text, opts) {
19713
19719
  ...f.test ? { discriminator: f.test } : {},
19714
19720
  ...f.drift ? { driftKind: f.drift } : {},
19715
19721
  context: opts.context,
19716
- ...opts.contributor ? { contributor: opts.contributor } : {}
19722
+ ...opts.contributor ? { contributor: opts.contributor } : {},
19723
+ causal: true
19717
19724
  },
19718
19725
  opts.ts
19719
19726
  );
@@ -24045,17 +24052,18 @@ function buildFileRecallInstruction(referent = "\u2026") {
24045
24052
  }
24046
24053
  function triageBullet(ref) {
24047
24054
  return [
24048
- " \u2022 you diagnosed a bug \u2014 SPLIT the symptom from the cause, don't fold both into one [!\u2026]:",
24049
- " \xB7 the SYMPTOM is what breaks observably (what a test or user would report) \u2192 [!the symptom]",
24050
- " \xB7 the CAUSE is the mechanism you'd CHANGE in the code to make it stop \u2192 (cause: the mechanism)",
24051
- " Test: if the line says WHY it breaks, it's a (cause:), not a [!problem]. e.g. [!the runner",
24052
- " deadlocks after a task rejects] (cause: await fn() has no try/finally, so a rejection never",
24053
- ` decrements running). New cause as prose, or (cause:[${ref}]) to cite one shown.`,
24054
- " State the cause in the same breath as its symptom when you can. When a diagnosis",
24055
- " UNFOLDS \u2014 symptom now, cause turns later, several problems in play \u2014 name the thread:",
24056
- " [!#slug the symptom] once, then (cause:#slug \u2026) / (fix:#slug \u2026) bind to it exactly,",
24057
- " however far apart. Same slug, your choice of word. Explaining a problem we SHOWED",
24058
- " you? bind by its handle/id directly: (cause:#the-shown-handle \u2026) / (fix:#dprob_\u2026 \u2026)."
24055
+ " \u2022 you diagnosed a bug \u2014 write the CAUSAL CHAIN in one flag with `<-` (caused-by).",
24056
+ " Don't split it into a second tag you'll skip under load; fold it the way you'd say it:",
24057
+ " \xB7 [!the symptom <- the mechanism] \u2014 leftmost is what breaks observably (what a test",
24058
+ " or user reports); the step right is what caused it. e.g. [!the runner deadlocks after",
24059
+ " a task rejects <- await fn() has no try/finally, so a rejection never decrements running].",
24060
+ " \xB7 chain it as deep as you actually diagnosed: [!symptom <- cause <- root cause] \u2014 every",
24061
+ " ` <- ` is a link we record, and the RIGHTMOST is the reusable root cause (the node other",
24062
+ " agents find). Stop at the deepest mechanism you're sure of; don't guess a link.",
24063
+ " When symptom and cause turn up FAR APART \u2014 the cause lands turns later, several problems",
24064
+ " in play \u2014 name the thread instead: [!#slug the symptom] once, then (cause:#slug the",
24065
+ " mechanism) binds to it however far away (same slug, your choice of word). Explaining a",
24066
+ ` problem we SHOWED you? bind by its handle/id: (cause:[${ref}] \u2026) / (cause:#dprob_\u2026 \u2026).`
24059
24067
  ].join("\n");
24060
24068
  }
24061
24069
  function linkBullet(ref) {
@@ -41023,6 +41031,7 @@ var HANDLE_RE = /\[([a-z0-9][\w-]{0,40})\]|((?:pat|sol|drc|dcause|dfix|dprob|pro
41023
41031
  var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
41024
41032
  var CONSTRAINT_RE = /\(\s*constraint:\s*([^()\n]{8,}?)\s*\)/gi;
41025
41033
  var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
41034
+ var CAUSE_ARROW = /\s+(?:<-|←)\s+/;
41026
41035
  var ATTEMPT_RE = /\(\s*(tried|failed):(?:#([a-z][\w-]{0,63}))?\s*((?:[^()\n]|\([^()\n]*\)){8,}?)\s*\)/gi;
41027
41036
  var AIDS_PREFIX = /^\s*aids:(?:#([a-z][\w-]{0,63}))?\s*/i;
41028
41037
  var INSTANCE_PREFIX = /^\s*instance:\s*/i;
@@ -41141,7 +41150,9 @@ function parseInlineTags(text) {
41141
41150
  const flagThread = f[2];
41142
41151
  const raw3 = f[3].trim();
41143
41152
  if (raw3.length >= 8) {
41144
- const statement = raw3.length > FLAG_MAX ? `${raw3.slice(0, FLAG_MAX - 1).trimEnd()}\u2026` : raw3;
41153
+ const segs = raw3.split(CAUSE_ARROW).map((s) => s.trim()).filter((s) => s.length > 0);
41154
+ const symptomRaw = segs.length > 1 ? segs[0] : raw3;
41155
+ const statement = symptomRaw.length > FLAG_MAX ? `${symptomRaw.slice(0, FLAG_MAX - 1).trimEnd()}\u2026` : symptomRaw;
41145
41156
  const asFix = f[1] === "!" && /^(?:fixed|resolved)\s*[:,-]\s*/i.exec(statement);
41146
41157
  if (asFix) {
41147
41158
  const note = statement.slice(asFix[0].length).trim();
@@ -41158,6 +41169,14 @@ function parseInlineTags(text) {
41158
41169
  ...flagThread ? { threadId: flagThread } : {},
41159
41170
  sentence: sfield
41160
41171
  });
41172
+ if (f[1] === "!" && segs.length > 1) {
41173
+ for (const seg of segs.slice(1)) {
41174
+ const causeText = seg.replace(/\s+/g, " ").trim();
41175
+ if (causeText.length >= CAUSE_TEXT_MIN) {
41176
+ out2.push({ kind: "triage", causeText, sentence: sfield, ...flagThread ? { threadId: flagThread } : {} });
41177
+ }
41178
+ }
41179
+ }
41161
41180
  }
41162
41181
  }
41163
41182
  ATTEMPT_RE.lastIndex = 0;
@@ -42855,7 +42874,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
42855
42874
  }
42856
42875
 
42857
42876
  // src/engine.ts
42858
- var DAEMON_VERSION = true ? "2.0.0-dev.59" : "2.0.0-alpha.0";
42877
+ var DAEMON_VERSION = true ? "2.0.0-dev.61" : "2.0.0-alpha.0";
42859
42878
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
42860
42879
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
42861
42880
  var GIT_OP_MUTE_MS = 4e3;
@@ -43577,7 +43596,8 @@ function createWorkspaceEngine(opts) {
43577
43596
  ...tr.causeDescription ? { causeDescription: tr.causeDescription } : {},
43578
43597
  context: { stack: profile.stack, domain: profile.domains[0] },
43579
43598
  contributor: sessionId,
43580
- evidence
43599
+ evidence,
43600
+ causal: true
43581
43601
  },
43582
43602
  t
43583
43603
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.59",
3
+ "version": "2.0.0-dev.61",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {