@inerrata-corporation/errata 2.0.2-dev.881 → 2.0.2-dev.902

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 +118 -56
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -22197,7 +22197,10 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
22197
22197
  return mechanisms.map((d) => {
22198
22198
  const fed = evaluateFed(store, d);
22199
22199
  const inv = invocations.get(d.pass);
22200
- const effectCount = inv?.totals[d.effectCounter] ?? 0;
22200
+ const effectCount = d.effectIsLevel ? Math.max(
22201
+ 0,
22202
+ (inv?.lastTotals?.[d.effectCounter] ?? 0) - (inv?.firstTotals?.[d.effectCounter] ?? 0)
22203
+ ) : inv?.totals[d.effectCounter] ?? 0;
22201
22204
  const backlog = d.backlogCounter ? inv?.lastTotals?.[d.backlogCounter] : void 0;
22202
22205
  const backlogWas = d.backlogCounter ? inv?.firstTotals?.[d.backlogCounter] : void 0;
22203
22206
  const span = inv?.firstTs === void 0 ? 0 : inv.lastTs - inv.firstTs;
@@ -22394,7 +22397,11 @@ var init_mechanism_liveness = __esm({
22394
22397
  // this store's measured state on 2026-08-09, day one of WM-labels.
22395
22398
  fed: { labels: ["Problem"], attr: "lastReinforceExposure", minFraction: 0 },
22396
22399
  // A LEVEL, not an increment: nonzero once any node ever carried an outcome.
22400
+ // Which is precisely why it must be read as movement — measured across the
22401
+ // 103 retained rows it never left 1, and the summed reading called that
22402
+ // "effect 103, ok".
22397
22403
  effectCounter: "reinforcedNodes",
22404
+ effectIsLevel: true,
22398
22405
  note: "levels ride the wm-calibration row; expect no-effect until outcome data accrues"
22399
22406
  },
22400
22407
  {
@@ -49850,19 +49857,32 @@ function summarizeWitnessLedger(configDir, nowMs) {
49850
49857
  if (entries.length === 0) return [];
49851
49858
  const byChannel = /* @__PURE__ */ new Map();
49852
49859
  for (const e of entries) {
49853
- const c = byChannel.get(e.channel) ?? { recorded: 0, selfSkipped: 0, selfGated: 0, unmatched: 0, lastTs: 0 };
49860
+ const c = byChannel.get(e.channel) ?? {
49861
+ recorded: 0,
49862
+ selfSkipped: 0,
49863
+ selfGated: 0,
49864
+ unmatchedAttempts: 0,
49865
+ parked: -1,
49866
+ awaitingDrain: -1,
49867
+ lastTs: 0
49868
+ };
49854
49869
  c.recorded += e.recorded ?? 0;
49855
49870
  c.selfSkipped += e.clientSelfSkipped ?? 0;
49856
49871
  c.selfGated += e.selfGated ?? 0;
49857
- c.unmatched += e.unmatched ?? 0;
49872
+ c.unmatchedAttempts += e.unmatched ?? 0;
49873
+ if (e.ts >= c.lastTs) {
49874
+ if (e.parked !== void 0) c.parked = e.parked;
49875
+ if (e.awaitingDrain !== void 0) c.awaitingDrain = e.awaitingDrain;
49876
+ }
49858
49877
  c.lastTs = Math.max(c.lastTs, e.ts);
49859
49878
  byChannel.set(e.channel, c);
49860
49879
  }
49861
49880
  const out2 = [];
49862
49881
  for (const [channel, c] of byChannel) {
49863
49882
  const ageH = Math.round((nowMs - c.lastTs) / 36e5);
49883
+ const depth = c.parked < 0 ? "parked ?" : `parked ${c.parked}${c.awaitingDrain > 0 ? ` (${c.awaitingDrain} awaiting drain)` : ""}`;
49864
49884
  out2.push(
49865
- `${channel}: recorded ${c.recorded} \xB7 self-gated ${c.selfSkipped + c.selfGated} \xB7 unmatched ${c.unmatched} \xB7 last activity ${ageH}h ago`
49885
+ `${channel}: recorded ${c.recorded} \xB7 self-gated ${c.selfSkipped + c.selfGated} \xB7 ${depth} \xB7 ${c.unmatchedAttempts} unmatched attempt(s) \xB7 last activity ${ageH}h ago`
49866
49886
  );
49867
49887
  }
49868
49888
  return out2;
@@ -56036,53 +56056,6 @@ function maybeFlushDigests() {
56036
56056
 
56037
56057
  // src/liveness-watch.ts
56038
56058
  init_src5();
56039
- var LIVENESS_WATCH_INTERVAL_MS = 60 * 60 * 1e3;
56040
- var ALARM_RENOTIFY_MS = 24 * 60 * 60 * 1e3;
56041
- function createLivenessWatch(deps) {
56042
- let lastRunAt = 0;
56043
- const lastAlarmedAt = /* @__PURE__ */ new Map();
56044
- return {
56045
- maybeRun(nowMs = Date.now()) {
56046
- if (nowMs - lastRunAt < LIVENESS_WATCH_INTERVAL_MS) return null;
56047
- lastRunAt = nowMs;
56048
- try {
56049
- const started2 = Date.now();
56050
- const invocations = /* @__PURE__ */ new Map();
56051
- for (const [kind, s] of summarizePassLedger(deps.configDir)) {
56052
- invocations.set(kind, {
56053
- lastTs: s.lastTs,
56054
- firstTs: s.firstTs,
56055
- runs: s.runs,
56056
- totals: s.totals,
56057
- firstTotals: s.firstTotals,
56058
- lastTotals: s.lastTotals
56059
- });
56060
- }
56061
- const rows = evaluateMechanisms(deps.store, invocations);
56062
- const workspaceActive = invocations.has("capture") || invocations.has("render");
56063
- const bad = workspaceActive ? rows.filter((r) => hasStarvedMechanism([r])) : [];
56064
- appendPassLedger(deps.configDir, "liveness-watch", Date.now() - started2, {
56065
- mechanisms: rows.length,
56066
- alarms: bad.length,
56067
- ...Object.fromEntries(bad.map((r) => [`starved:${r.id}`, 1]))
56068
- });
56069
- if (bad.length > 0) {
56070
- const lines = formatMechanismStatus(rows, nowMs);
56071
- for (const r of bad) {
56072
- const at = lastAlarmedAt.get(r.id) ?? 0;
56073
- if (nowMs - at < ALARM_RENOTIFY_MS) continue;
56074
- lastAlarmedAt.set(r.id, nowMs);
56075
- const line = lines.find((l) => l.includes(r.id)) ?? `${r.verdict} ${r.id}`;
56076
- deps.onAlarm(r.id, `${line.trim()} \u2014 ${r.what}`);
56077
- }
56078
- }
56079
- return rows;
56080
- } catch {
56081
- return null;
56082
- }
56083
- }
56084
- };
56085
- }
56086
56059
 
56087
56060
  // src/loop-lag.ts
56088
56061
  var HEARTBEAT_MS = 500;
@@ -56157,8 +56130,69 @@ function watchCensusLine(c = watchCensus()) {
56157
56130
  return base;
56158
56131
  }
56159
56132
 
56133
+ // src/liveness-watch.ts
56134
+ var LIVENESS_WATCH_INTERVAL_MS = 60 * 60 * 1e3;
56135
+ var ALARM_RENOTIFY_MS = 24 * 60 * 60 * 1e3;
56136
+ function createLivenessWatch(deps) {
56137
+ let lastRunAt = 0;
56138
+ const lastAlarmedAt = /* @__PURE__ */ new Map();
56139
+ return {
56140
+ maybeRun(nowMs = Date.now()) {
56141
+ if (nowMs - lastRunAt < LIVENESS_WATCH_INTERVAL_MS) return null;
56142
+ lastRunAt = nowMs;
56143
+ try {
56144
+ const started2 = Date.now();
56145
+ const invocations = /* @__PURE__ */ new Map();
56146
+ for (const [kind, s] of summarizePassLedger(deps.configDir)) {
56147
+ invocations.set(kind, {
56148
+ lastTs: s.lastTs,
56149
+ firstTs: s.firstTs,
56150
+ runs: s.runs,
56151
+ totals: s.totals,
56152
+ firstTotals: s.firstTotals,
56153
+ lastTotals: s.lastTotals
56154
+ });
56155
+ }
56156
+ const rows = evaluateMechanisms(deps.store, invocations);
56157
+ const workspaceActive = invocations.has("capture") || invocations.has("render");
56158
+ const bad = workspaceActive ? rows.filter((r) => hasStarvedMechanism([r])) : [];
56159
+ const watch2 = watchCensus();
56160
+ const pass = passState();
56161
+ appendPassLedger(deps.configDir, "liveness-watch", Date.now() - started2, {
56162
+ mechanisms: rows.length,
56163
+ alarms: bad.length,
56164
+ ...Object.fromEntries(bad.map((r) => [`starved:${r.id}`, 1])),
56165
+ ...deps.witnessParked ? { witnessParked: deps.witnessParked() } : {},
56166
+ watchDispatched: watch2.dispatched,
56167
+ watchEmitted: watch2.emitted,
56168
+ watchLogged: watch2.logged,
56169
+ watchRejected: watch2.rejected,
56170
+ // Concurrency and the longest single holder — the two readings that
56171
+ // named the 6017s zombie pass. A pass legitimately running for hours
56172
+ // and one wedged forever look identical without a trend.
56173
+ passesActive: pass.active.length,
56174
+ passLongestRunningMs: pass.active.reduce((m, p) => Math.max(m, p.runningMs), 0)
56175
+ });
56176
+ if (bad.length > 0) {
56177
+ const lines = formatMechanismStatus(rows, nowMs);
56178
+ for (const r of bad) {
56179
+ const at = lastAlarmedAt.get(r.id) ?? 0;
56180
+ if (nowMs - at < ALARM_RENOTIFY_MS) continue;
56181
+ lastAlarmedAt.set(r.id, nowMs);
56182
+ const line = lines.find((l) => l.includes(r.id)) ?? `${r.verdict} ${r.id}`;
56183
+ deps.onAlarm(r.id, `${line.trim()} \u2014 ${r.what}`);
56184
+ }
56185
+ }
56186
+ return rows;
56187
+ } catch {
56188
+ return null;
56189
+ }
56190
+ }
56191
+ };
56192
+ }
56193
+
56160
56194
  // src/engine.ts
56161
- var DAEMON_VERSION = true ? "2.0.2-dev.881" : "2.0.0-alpha.0";
56195
+ var DAEMON_VERSION = true ? "2.0.2-dev.902" : "2.0.0-alpha.0";
56162
56196
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
56163
56197
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
56164
56198
  var GIT_OP_MUTE_MS = 4e3;
@@ -56504,7 +56538,11 @@ function createWorkspaceEngine(opts) {
56504
56538
  onAlarm: (id, line) => {
56505
56539
  console.warn(`[errata] mechanism not working: ${line}`);
56506
56540
  notifyEvent("mechanism-stalled", line, { key: id });
56507
- }
56541
+ },
56542
+ // Read through a closure, not captured once: `witnessQueue` is reassigned
56543
+ // on every harvest, so a snapshot would freeze the depth at boot — which is
56544
+ // the same in-memory-only blindness this counter exists to end.
56545
+ witnessParked: () => witnessQueue.length
56508
56546
  });
56509
56547
  const intents = createIntentState();
56510
56548
  const toolRuns = createToolRunState();
@@ -60435,7 +60473,11 @@ async function startMultiDaemon(opts = {}) {
60435
60473
  ...compositionCounters(composition),
60436
60474
  accepted: 0,
60437
60475
  rejected: 0,
60438
- blocked: 0
60476
+ blocked: 0,
60477
+ // Same shape as the drained row: a first/last trend reading must not
60478
+ // straddle rows where the counter is merely absent.
60479
+ blockedRepeat: 0,
60480
+ rejectedRepeat: 0
60439
60481
  });
60440
60482
  }
60441
60483
  if (instances) {
@@ -60476,15 +60518,29 @@ async function startMultiDaemon(opts = {}) {
60476
60518
  if (sh) return { s: sharedStore, n: sh };
60477
60519
  return null;
60478
60520
  };
60521
+ let blockedRepeat = 0;
60522
+ let rejectedRepeat = 0;
60523
+ const noteRefused = (id, repeat) => {
60524
+ const owner = owningStore(id);
60525
+ if (!owner) return;
60526
+ if (owner.n.attrs["shipRefusedSinceSeq"] !== void 0) repeat();
60527
+ else
60528
+ owner.s.updateNode(id, {
60529
+ attrs: { ...owner.n.attrs, shipRefusedSinceSeq: seq }
60530
+ });
60531
+ };
60532
+ for (const id of blocked) noteRefused(id, () => blockedRepeat++);
60533
+ for (const id of rejected.keys()) noteRefused(id, () => rejectedRepeat++);
60479
60534
  for (const n of instances.nodes) {
60480
60535
  const owner = owningStore(n.id);
60481
60536
  if (!owner || !["Problem", "Solution", "RootCause"].includes(owner.n.label)) continue;
60482
60537
  if (blocked.has(n.id)) continue;
60483
60538
  if (rejected.has(n.id)) continue;
60484
60539
  const cloudNodeId = cloudIdByLocal.get(n.id);
60540
+ const { shipRefusedSinceSeq: _cleared, ...carried } = owner.n.attrs;
60485
60541
  owner.s.updateNode(n.id, {
60486
60542
  attrs: {
60487
- ...owner.n.attrs,
60543
+ ...carried,
60488
60544
  contributedAtSeq: seq,
60489
60545
  ...cloudNodeId && cloudNodeId !== n.id ? { cloudNodeId } : {}
60490
60546
  }
@@ -60510,7 +60566,13 @@ async function startMultiDaemon(opts = {}) {
60510
60566
  ...compositionCounters(instances.composition),
60511
60567
  accepted: res.accepted,
60512
60568
  rejected: rejected.size,
60513
- blocked: blocked.size
60569
+ blocked: blocked.size,
60570
+ // The half of the refusal count that is NOT news. `blocked` flat
60571
+ // at 1 with `blockedRepeat` also 1 is one permanently stranded
60572
+ // node; flat at 1 with `blockedRepeat` 0 is a different node
60573
+ // failing every pass. Same total, different bug.
60574
+ blockedRepeat,
60575
+ rejectedRepeat
60514
60576
  });
60515
60577
  return res.accepted;
60516
60578
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.881",
3
+ "version": "2.0.2-dev.902",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {