@inerrata-corporation/errata 2.0.2-dev.1189 → 2.0.2-dev.1203

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
@@ -19495,6 +19495,21 @@ function markResolvedRecurrence(store, nodeId, ts, source) {
19495
19495
  const reopened = source ? maybeReopenFromRegression(store, nodeId, ts) : false;
19496
19496
  return { marked: true, reopened };
19497
19497
  }
19498
+ function confirmFixHeld(store, solutionId, ts) {
19499
+ let acknowledged = 0;
19500
+ for (const e of store.inEdges(solutionId, ["SOLVED_BY", "FIXED_BY"])) {
19501
+ const p = store.getNode(e.from);
19502
+ if (!p || p.label !== "Problem") continue;
19503
+ if (p.attrs["resolutionSuspect"] !== true || p.attrs["resolvedAt"] == null) continue;
19504
+ const attrs = { ...p.attrs };
19505
+ delete attrs["resolutionSuspect"];
19506
+ attrs["fixHeldConfirmedAt"] = ts;
19507
+ delete attrs["recurrenceSources"];
19508
+ store.updateNode(p.id, { attrs, lastUpdatedAt: ts });
19509
+ acknowledged++;
19510
+ }
19511
+ return acknowledged;
19512
+ }
19498
19513
  function isFragmentFixNote(note) {
19499
19514
  const t = note.trim();
19500
19515
  if (t.length === 0) return true;
@@ -22793,6 +22808,7 @@ __export(src_exports2, {
22793
22808
  communityInductionRequests: () => communityInductionRequests,
22794
22809
  communitySeeds: () => communitySeeds,
22795
22810
  compareSemver: () => compareSemver,
22811
+ confirmFixHeld: () => confirmFixHeld,
22796
22812
  corroborateClaim: () => corroborateClaim,
22797
22813
  creditAssignment: () => creditAssignment,
22798
22814
  crystallize: () => crystallize,
@@ -22937,7 +22953,19 @@ function buildSnapshot(opts) {
22937
22953
  anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
22938
22954
  }));
22939
22955
  const recentConstraints = stillOpen.filter((p) => isConstraintProblem(p)).sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, 3);
22940
- const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
22956
+ const regressions = problems.filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0).flatMap(
22957
+ (open2) => opts.store.outEdges(open2.id, ["REGRESSION_OF"]).flatMap((e) => {
22958
+ const closed = opts.store.getNode(e.to);
22959
+ if (!closed || closed.attrs["resolutionSuspect"] !== true || closed.attrs["resolvedAt"] == null) {
22960
+ return [];
22961
+ }
22962
+ const solEdge = opts.store.outEdges(closed.id, ["SOLVED_BY"])[0];
22963
+ const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
22964
+ return [{ open: open2, closed, ...solution ? { solution } : {} }];
22965
+ })
22966
+ ).sort((a, b) => Number(b.closed.attrs["recurredAt"] ?? 0) - Number(a.closed.attrs["recurredAt"] ?? 0)).slice(0, 2);
22967
+ const regressionClosedIds = new Set(regressions.map((r) => r.closed.id));
22968
+ const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).filter((p) => !regressionClosedIds.has(p.id)).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
22941
22969
  const solEdge = opts.store.outEdges(p.id, ["SOLVED_BY"])[0];
22942
22970
  const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
22943
22971
  return { node: p, ...solution ? { solution } : {} };
@@ -23007,6 +23035,7 @@ function buildSnapshot(opts) {
23007
23035
  recentProblems: recent2,
23008
23036
  recentResolved,
23009
23037
  recentConstraints,
23038
+ regressions,
23010
23039
  ...causalNudge ? { causalNudge } : {},
23011
23040
  ...opts.selfCiteSkips && opts.selfCiteSkips > 0 ? { selfCiteSkips: opts.selfCiteSkips } : {},
23012
23041
  ...domainNudge ? { domainNudge } : {},
@@ -23171,7 +23200,7 @@ function renderSnapshot(s) {
23171
23200
  lines.push("");
23172
23201
  }
23173
23202
  lines.push("### Recently observed problems in this workspace");
23174
- if (s.recentProblems.length === 0 && s.recentResolved.length === 0 && s.recentConstraints.length === 0) {
23203
+ if (s.recentProblems.length === 0 && s.recentResolved.length === 0 && s.recentConstraints.length === 0 && s.regressions.length === 0) {
23175
23204
  lines.push("- _none yet \u2014 errata is still building its model_");
23176
23205
  } else {
23177
23206
  if (s.recentProblems.length > 0) {
@@ -23193,6 +23222,22 @@ function renderSnapshot(s) {
23193
23222
  );
23194
23223
  }
23195
23224
  }
23225
+ if (s.regressions.length > 0) {
23226
+ lines.push("_\u{1F501} RECURRED \u2014 a previously-solved problem appears to be back; did the fix hold?_");
23227
+ for (const g of s.regressions) {
23228
+ lines.push(`- **${g.open.description}** \u2014 \`${g.open.id}\`${tagOf(g.open)}`);
23229
+ lines.push(` - previously resolved as: ${g.closed.description.slice(0, 120)} \u2014 \`${g.closed.id}\``);
23230
+ if (g.solution) {
23231
+ lines.push(
23232
+ ` - the fix on record: ${g.solution.description.slice(0, 120)} \u2014 \`${g.solution.id}\` \xB7 fix still holds \u2192 (confirm:[${g.solution.id}]) \xB7 hitting it again \u2192 flag it (a second independent witness reopens the close)`
23233
+ );
23234
+ } else {
23235
+ lines.push(
23236
+ ` - no fix prose on record \xB7 hitting it again \u2192 flag it (a second independent witness reopens the close)`
23237
+ );
23238
+ }
23239
+ }
23240
+ }
23196
23241
  if (s.recentConstraints.length > 0) {
23197
23242
  lines.push("_Design tensions \u2014 constraints this work is shaped around, not defects to fix:_");
23198
23243
  for (const c of s.recentConstraints) {
@@ -40023,6 +40068,8 @@ var init_reconcile = __esm({
40023
40068
  var mcp_exports = {};
40024
40069
  __export(mcp_exports, {
40025
40070
  INSTRUCTIONS: () => INSTRUCTIONS,
40071
+ RG_REFUTED_DAMP: () => RG_REFUTED_DAMP,
40072
+ RG_SUSPECT_BOOST: () => RG_SUSPECT_BOOST,
40026
40073
  createMcpHandler: () => createMcpHandler,
40027
40074
  runMcpServer: () => runMcpServer,
40028
40075
  runTool: () => runTool,
@@ -40094,6 +40141,22 @@ function takeDiscriminatorNudge(path2) {
40094
40141
  shared.close();
40095
40142
  }
40096
40143
  }
40144
+ function hitState(n) {
40145
+ const reasons = n.attrs["refuteReasons"];
40146
+ if (n.attrs["resolutionSuspect"] === true && n.attrs["resolvedAt"] != null) {
40147
+ return { state: "regression-suspect", factor: RG_SUSPECT_BOOST };
40148
+ }
40149
+ if (n.attrs["refutedAt"] != null) {
40150
+ return { state: "refuted", ...reasons?.[0] ? { refutedWhy: reasons[0] } : {}, factor: RG_REFUTED_DAMP };
40151
+ }
40152
+ if (n.attrs["reopenedFrom"] === "regression") {
40153
+ return { state: "reopened-regression", factor: RG_SUSPECT_BOOST };
40154
+ }
40155
+ if (n.attrs["resolvedAt"] != null && n.attrs["resolvedAs"] == null) {
40156
+ return { state: "resolved", factor: 1 };
40157
+ }
40158
+ return { factor: 1 };
40159
+ }
40097
40160
  function commentAnchorId(store, commentId) {
40098
40161
  const out2 = store.outEdges(commentId, ["EXPLAINS", "ANNOTATES"]);
40099
40162
  if (out2.length > 0) return out2[0].to;
@@ -40158,14 +40221,16 @@ function searchGraph(store, query, limit) {
40158
40221
  }
40159
40222
  add(node2, matched);
40160
40223
  }
40161
- return [...merged.values()].sort(
40162
- (a, b) => rankTier(a.node) - rankTier(b.node) || b.matched - a.matched || b.node.pageRank - a.node.pageRank
40163
- ).slice(0, limit).map(({ node: node2, via }) => ({
40224
+ return [...merged.values()].map((e) => ({ ...e, rg: hitState(e.node) })).sort(
40225
+ (a, b) => rankTier(a.node) - rankTier(b.node) || b.matched - a.matched || b.node.pageRank * b.rg.factor - a.node.pageRank * a.rg.factor
40226
+ ).slice(0, limit).map(({ node: node2, via, rg }) => ({
40164
40227
  id: node2.id,
40165
40228
  label: node2.label,
40166
40229
  description: node2.description,
40167
40230
  pageRank: node2.pageRank,
40168
- ...via ? { via } : {}
40231
+ ...via ? { via } : {},
40232
+ ...rg.state ? { state: rg.state } : {},
40233
+ ...rg.refutedWhy ? { refutedWhy: rg.refutedWhy } : {}
40169
40234
  }));
40170
40235
  }
40171
40236
  function runTool(name2, args2, store, ctx = {}) {
@@ -40458,7 +40523,7 @@ async function runMcpServer(workspaceRoot) {
40458
40523
  if (resp) process.stdout.write(JSON.stringify(resp) + "\n");
40459
40524
  }
40460
40525
  }
40461
- var INSTRUCTIONS, AUDIT_RUN_THRESHOLD, AUDIT_NUDGE_COOLDOWN, DISCRIMINATOR_NUDGE_COOLDOWN, AUDIT_FLAG_NUDGE, TOOLS;
40526
+ var INSTRUCTIONS, AUDIT_RUN_THRESHOLD, AUDIT_NUDGE_COOLDOWN, DISCRIMINATOR_NUDGE_COOLDOWN, AUDIT_FLAG_NUDGE, RG_REFUTED_DAMP, RG_SUSPECT_BOOST, TOOLS;
40462
40527
  var init_mcp = __esm({
40463
40528
  "src/mcp.ts"() {
40464
40529
  "use strict";
@@ -40522,6 +40587,8 @@ var init_mcp = __esm({
40522
40587
  AUDIT_NUDGE_COOLDOWN = 12;
40523
40588
  DISCRIMINATOR_NUDGE_COOLDOWN = 40;
40524
40589
  AUDIT_FLAG_NUDGE = "\u26A1 errata \u2014 reading/auditing? anything you notice that's off, flag it inline as `[!one line]` (`[?\u2026]` = TODO) \u2014 no tool call, we harvest it.";
40590
+ RG_REFUTED_DAMP = 0.75;
40591
+ RG_SUSPECT_BOOST = 1.25;
40525
40592
  TOOLS = [
40526
40593
  {
40527
40594
  name: "errata.switch_context",
@@ -56998,7 +57065,7 @@ function createWatchBreaker(deps) {
56998
57065
  }
56999
57066
 
57000
57067
  // src/engine.ts
57001
- var DAEMON_VERSION = true ? "2.0.2-dev.1189" : "2.0.0-alpha.0";
57068
+ var DAEMON_VERSION = true ? "2.0.2-dev.1203" : "2.0.0-alpha.0";
57002
57069
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
57003
57070
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
57004
57071
  var GIT_OP_MUTE_MS = 4e3;
@@ -57836,6 +57903,7 @@ function createWorkspaceEngine(opts) {
57836
57903
  let refutesStamped = 0;
57837
57904
  let recurrencesMarked = 0;
57838
57905
  let reopenedFromRegression = 0;
57906
+ let fixHeldConfirmed = 0;
57839
57907
  const dispositions = emptyTagDispositions();
57840
57908
  let unresolvedHandles = 0;
57841
57909
  let priorEdgesFlagOff = 0;
@@ -57992,6 +58060,15 @@ function createWorkspaceEngine(opts) {
57992
58060
  corroboratedEdges += plan.corroboratedEdges;
57993
58061
  const refuteResult = applyLocalRefutations(store, plan.refutes, t);
57994
58062
  refutesStamped += refuteResult.stamped;
58063
+ for (const c of plan.corroborations) {
58064
+ const node2 = store.getNode(c.nodeId);
58065
+ if (node2?.label !== "Solution") continue;
58066
+ const held = confirmFixHeld(store, c.nodeId, t);
58067
+ if (held > 0) {
58068
+ fixHeldConfirmed += held;
58069
+ console.log(`[errata] fix-held confirmed: ${node2.id} \u2014 ${held} regression question(s) acknowledged`);
58070
+ }
58071
+ }
57995
58072
  for (const id of refuteResult.stampedIds) {
57996
58073
  const node2 = store.getNode(id);
57997
58074
  if (node2?.label !== "Solution") continue;
@@ -58488,6 +58565,8 @@ function createWorkspaceEngine(opts) {
58488
58565
  recurrencesMarked,
58489
58566
  // RG-reopen: closes flipped open on the two-touch evidence bar.
58490
58567
  reopenedFromRegression,
58568
+ // RG-prime: regression questions acknowledged by a fix-held confirm.
58569
+ fixHeldConfirmed,
58491
58570
  // WM-labels calibration cells (see prior-tags exposure split).
58492
58571
  exposureShown,
58493
58572
  exposureEvicted,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.1189",
3
+ "version": "2.0.2-dev.1203",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -27052,7 +27052,19 @@ function buildSnapshot(opts) {
27052
27052
  anchors: opts.store.outEdges(p.id, ["MANIFESTED_IN", "EVIDENCED_BY"])
27053
27053
  }));
27054
27054
  const recentConstraints = stillOpen.filter((p) => isConstraintProblem(p)).sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, 3);
27055
- const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
27055
+ const regressions = problems.filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0).flatMap(
27056
+ (open) => opts.store.outEdges(open.id, ["REGRESSION_OF"]).flatMap((e) => {
27057
+ const closed = opts.store.getNode(e.to);
27058
+ if (!closed || closed.attrs["resolutionSuspect"] !== true || closed.attrs["resolvedAt"] == null) {
27059
+ return [];
27060
+ }
27061
+ const solEdge = opts.store.outEdges(closed.id, ["SOLVED_BY"])[0];
27062
+ const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
27063
+ return [{ open, closed, ...solution ? { solution } : {} }];
27064
+ })
27065
+ ).sort((a, b) => Number(b.closed.attrs["recurredAt"] ?? 0) - Number(a.closed.attrs["recurredAt"] ?? 0)).slice(0, 2);
27066
+ const regressionClosedIds = new Set(regressions.map((r) => r.closed.id));
27067
+ const recentResolved = problems.filter((p) => p.attrs["resolvedAt"] != null && p.attrs["resolvedAs"] == null).filter((p) => !regressionClosedIds.has(p.id)).sort((a, b) => Number(b.attrs["resolvedAt"] ?? 0) - Number(a.attrs["resolvedAt"] ?? 0)).slice(0, 4).map((p) => {
27056
27068
  const solEdge = opts.store.outEdges(p.id, ["SOLVED_BY"])[0];
27057
27069
  const solution = solEdge ? opts.store.getNode(solEdge.to) ?? void 0 : void 0;
27058
27070
  return { node: p, ...solution ? { solution } : {} };
@@ -27122,6 +27134,7 @@ function buildSnapshot(opts) {
27122
27134
  recentProblems: recent,
27123
27135
  recentResolved,
27124
27136
  recentConstraints,
27137
+ regressions,
27125
27138
  ...causalNudge ? { causalNudge } : {},
27126
27139
  ...opts.selfCiteSkips && opts.selfCiteSkips > 0 ? { selfCiteSkips: opts.selfCiteSkips } : {},
27127
27140
  ...domainNudge ? { domainNudge } : {},