@inerrata-corporation/errata 2.0.2-dev.545 → 2.0.2-dev.548

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.
@@ -16580,6 +16580,16 @@ var SqliteGraphStore = class {
16580
16580
  if (revived > 0) this.mutations++;
16581
16581
  return revived;
16582
16582
  }
16583
+ recentEdgeAttrCoverage(marker, attr, limit) {
16584
+ const r = this.db.prepare(
16585
+ `SELECT COUNT(*) AS total,
16586
+ COALESCE(SUM(CASE WHEN json_extract(attrs_json, '$.' || ?) = 1 THEN 1 ELSE 0 END), 0) AS count
16587
+ FROM (SELECT attrs_json FROM edges
16588
+ WHERE valid_to IS NULL AND attrs_json LIKE ?
16589
+ ORDER BY created_at DESC LIMIT ?)`
16590
+ ).get(attr, `%${marker}%`, limit);
16591
+ return { count: Number(r.count), total: Number(r.total) };
16592
+ }
16583
16593
  liveNodeIds(ids) {
16584
16594
  const live = /* @__PURE__ */ new Set();
16585
16595
  const CHUNK = 900;
package/errata.mjs CHANGED
@@ -17255,6 +17255,16 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
17255
17255
  if (revived > 0) this.mutations++;
17256
17256
  return revived;
17257
17257
  }
17258
+ recentEdgeAttrCoverage(marker, attr, limit) {
17259
+ const r = this.db.prepare(
17260
+ `SELECT COUNT(*) AS total,
17261
+ COALESCE(SUM(CASE WHEN json_extract(attrs_json, '$.' || ?) = 1 THEN 1 ELSE 0 END), 0) AS count
17262
+ FROM (SELECT attrs_json FROM edges
17263
+ WHERE valid_to IS NULL AND attrs_json LIKE ?
17264
+ ORDER BY created_at DESC LIMIT ?)`
17265
+ ).get(attr, `%${marker}%`, limit);
17266
+ return { count: Number(r.count), total: Number(r.total) };
17267
+ }
17258
17268
  liveNodeIds(ids) {
17259
17269
  const live = /* @__PURE__ */ new Set();
17260
17270
  const CHUNK = 900;
@@ -21850,14 +21860,24 @@ var init_principle_sync = __esm({
21850
21860
 
21851
21861
  // ../../packages/local-graph/src/mechanism-liveness.ts
21852
21862
  function evaluateFed(store, d) {
21863
+ if (d.fedEdges) {
21864
+ const { count: count2, total } = store.recentEdgeAttrCoverage(
21865
+ d.fedEdges.marker,
21866
+ d.fedEdges.attr,
21867
+ d.fedEdges.recent
21868
+ );
21869
+ return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
21870
+ }
21871
+ if (!d.fed) return { count: 0, total: 0, fraction: 0 };
21853
21872
  const column = COLUMN_INPUTS[d.fed.attr];
21854
- const has = (n) => column ? column(n) : n.attrs[d.fed.attr] !== void 0;
21855
- const nodes = d.fed.labels.flatMap((label) => store.findNodesByLabel(label));
21873
+ const fed = d.fed;
21874
+ const has = (n) => column ? column(n) : n.attrs[fed.attr] !== void 0;
21875
+ const nodes = fed.labels.flatMap((label) => store.findNodesByLabel(label));
21856
21876
  let window2 = nodes;
21857
- if (d.fed.recent !== void 0) {
21858
- window2 = [...nodes].sort((a, b) => b.createdAt - a.createdAt).slice(0, d.fed.recent);
21877
+ if (fed.recent !== void 0) {
21878
+ window2 = [...nodes].sort((a, b) => b.createdAt - a.createdAt).slice(0, fed.recent);
21859
21879
  }
21860
- if (d.fed.sinceFirstStamp) {
21880
+ if (fed.sinceFirstStamp) {
21861
21881
  let anchor = Infinity;
21862
21882
  for (const n of window2) if (has(n) && n.createdAt < anchor) anchor = n.createdAt;
21863
21883
  window2 = anchor === Infinity ? [] : window2.filter((n) => n.createdAt >= anchor);
@@ -21877,7 +21897,7 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
21877
21897
  const stalled = backlog !== void 0 && backlog > 0 && effectCount === 0 && (inv?.runs ?? 0) >= STALL_MIN_RUNS && span >= STALL_MIN_SPAN_MS && (backlogWas === void 0 || backlog >= backlogWas);
21878
21898
  let verdict;
21879
21899
  if (!inv || inv.runs === 0) verdict = "never-invoked";
21880
- else if (fed.fraction < d.fed.minFraction) verdict = "starved";
21900
+ else if (fed.fraction < (d.fedEdges?.minFraction ?? d.fed?.minFraction ?? 0)) verdict = "starved";
21881
21901
  else if (stalled) verdict = "stalled";
21882
21902
  else if (effectCount === 0) verdict = "no-effect";
21883
21903
  else verdict = "ok";
@@ -21888,7 +21908,7 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
21888
21908
  fedCount: fed.count,
21889
21909
  fedTotal: fed.total,
21890
21910
  fedFraction: fed.fraction,
21891
- minFraction: d.fed.minFraction,
21911
+ minFraction: d.fedEdges?.minFraction ?? d.fed?.minFraction ?? 0,
21892
21912
  ...inv ? { lastInvokedMs: inv.lastTs } : {},
21893
21913
  runs: inv?.runs ?? 0,
21894
21914
  effectCount,
@@ -22004,6 +22024,20 @@ var init_mechanism_liveness = __esm({
22004
22024
  fed: { labels: ["File"], attr: "relPath", minFraction: 0.9 },
22005
22025
  effectCounter: "reaped"
22006
22026
  },
22027
+ {
22028
+ id: "prior-corroboration",
22029
+ what: "grounds a cited prior by overlap with what the session actually touched",
22030
+ // CAPTURE mints the edges and stamps the verdict; the fed metric is the
22031
+ // corroborated fraction of the newest priorTag edges. Measured 2026-08-08:
22032
+ // 1 of 139 recent despite 84 having a live grounding path — reading STARVED
22033
+ // is the honest state until the touched-set plumbing is fixed
22034
+ // (VS-corroboration-rate); an alarm on a genuinely broken channel is what
22035
+ // alarms are for.
22036
+ pass: "capture",
22037
+ fedEdges: { marker: '"priorTag":true', attr: "corroborated", minFraction: 0.02, recent: 100 },
22038
+ effectCounter: "corroboratedEdges",
22039
+ note: "expected STARVED until VS-corroboration-rate lands \u2014 the channel is genuinely starved"
22040
+ },
22007
22041
  {
22008
22042
  id: "liveness-watch",
22009
22043
  what: "the daemon-side schedule of this very verdict \u2014 alarms when a mechanism stops working",
@@ -51964,13 +51998,13 @@ function mintPriorEdge(store, source, target, sentence, touched, ts) {
51964
51998
  } catch {
51965
51999
  }
51966
52000
  }
51967
- return true;
52001
+ return { corroborated };
51968
52002
  }
51969
52003
  function harvestInlineTags(store, text, opts) {
51970
52004
  const source = opts.sourceId ? store.getNode(opts.sourceId) : null;
51971
52005
  const mintPriors = opts.mintPriors ?? true;
51972
52006
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
51973
- const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], causalLinks: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
52007
+ const plan = { priorEdges: 0, corroboratedEdges: 0, problems: [], fixes: [], triages: [], causalLinks: [], attempts: [], unresolvedFixes: [], transfers: [], solutionLinks: [], instances: [], patterns: [], domains: [], packages: [], components: [], refutes: [], corroborations: [] };
51974
52008
  const tags = parseInlineTags(text);
51975
52009
  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);
51976
52010
  const bindSymptom = (seq, threadId) => {
@@ -52163,11 +52197,23 @@ function harvestInlineTags(store, text, opts) {
52163
52197
  plan.corroborations.push({ nodeId: targetId, witnessKey });
52164
52198
  }
52165
52199
  }
52166
- if (mintPriors && source && target && mintPriorEdge(store, source, target, tag.sentence, touched, opts.ts)) plan.priorEdges++;
52200
+ if (mintPriors && source && target) {
52201
+ const m = mintPriorEdge(store, source, target, tag.sentence, touched, opts.ts);
52202
+ if (m) {
52203
+ plan.priorEdges++;
52204
+ if (m.corroborated) plan.corroboratedEdges++;
52205
+ }
52206
+ }
52167
52207
  } else if (mintPriors && source) {
52168
52208
  const targetId = resolveHandle(store, tag.handle, opts.handleMap);
52169
52209
  const target = targetId ? store.getNode(targetId) : null;
52170
- if (target && mintPriorEdge(store, source, target, tag.sentence, touched, opts.ts)) plan.priorEdges++;
52210
+ if (target) {
52211
+ const m = mintPriorEdge(store, source, target, tag.sentence, touched, opts.ts);
52212
+ if (m) {
52213
+ plan.priorEdges++;
52214
+ if (m.corroborated) plan.corroboratedEdges++;
52215
+ }
52216
+ }
52171
52217
  }
52172
52218
  }
52173
52219
  return plan;
@@ -54328,7 +54374,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
54328
54374
  }
54329
54375
 
54330
54376
  // src/engine.ts
54331
- var DAEMON_VERSION = true ? "2.0.2-dev.545" : "2.0.0-alpha.0";
54377
+ var DAEMON_VERSION = true ? "2.0.2-dev.548" : "2.0.0-alpha.0";
54332
54378
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
54333
54379
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
54334
54380
  var GIT_OP_MUTE_MS = 4e3;
@@ -55001,6 +55047,9 @@ function createWorkspaceEngine(opts) {
55001
55047
  let abstracted = 0;
55002
55048
  let triaged = 0;
55003
55049
  let priorEdges = 0;
55050
+ let corroboratedEdges = 0;
55051
+ let touchedFileTurns = 0;
55052
+ let touchedToolTurns = 0;
55004
55053
  let linked = 0;
55005
55054
  const t = Date.now();
55006
55055
  let processedTurns = 0;
@@ -55120,6 +55169,9 @@ function createWorkspaceEngine(opts) {
55120
55169
  ...touched.size > 0 ? { sessionTouchedIds: touched } : {}
55121
55170
  });
55122
55171
  priorEdges += plan.priorEdges;
55172
+ corroboratedEdges += plan.corroboratedEdges;
55173
+ if (touchedFileId) touchedFileTurns++;
55174
+ if ((toolRuns.get(sessionId)?.size ?? 0) > 0) touchedToolTurns++;
55123
55175
  const wf = workingFiles.get(sessionId);
55124
55176
  let inScopeProblemId;
55125
55177
  const threads = sessionThreads.get(sessionId) ?? /* @__PURE__ */ new Map();
@@ -55529,6 +55581,9 @@ function createWorkspaceEngine(opts) {
55529
55581
  resolved,
55530
55582
  triaged,
55531
55583
  priorEdges,
55584
+ corroboratedEdges,
55585
+ touchedFileTurns,
55586
+ touchedToolTurns,
55532
55587
  seqAdvanced: store.currentIngestSeq() - seqAtStart
55533
55588
  });
55534
55589
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.545",
3
+ "version": "2.0.2-dev.548",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -24921,6 +24921,16 @@ var SqliteGraphStore = class {
24921
24921
  if (revived > 0) this.mutations++;
24922
24922
  return revived;
24923
24923
  }
24924
+ recentEdgeAttrCoverage(marker, attr, limit) {
24925
+ const r = this.db.prepare(
24926
+ `SELECT COUNT(*) AS total,
24927
+ COALESCE(SUM(CASE WHEN json_extract(attrs_json, '$.' || ?) = 1 THEN 1 ELSE 0 END), 0) AS count
24928
+ FROM (SELECT attrs_json FROM edges
24929
+ WHERE valid_to IS NULL AND attrs_json LIKE ?
24930
+ ORDER BY created_at DESC LIMIT ?)`
24931
+ ).get(attr, `%${marker}%`, limit);
24932
+ return { count: Number(r.count), total: Number(r.total) };
24933
+ }
24924
24934
  liveNodeIds(ids) {
24925
24935
  const live = /* @__PURE__ */ new Set();
24926
24936
  const CHUNK = 900;