@inerrata-corporation/errata 2.0.2-dev.336 → 2.0.2-dev.338

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 (3) hide show
  1. package/errata.mjs +53 -22
  2. package/package.json +1 -1
  3. package/pass-worker.mjs +45 -57
package/errata.mjs CHANGED
@@ -18744,6 +18744,28 @@ function closeDesignProblem(store, problemId, fixNote, t) {
18744
18744
  });
18745
18745
  return true;
18746
18746
  }
18747
+ function reopenAutoClosedProblems(store, t) {
18748
+ const report = { reopened: 0, alreadySuspect: 0, agentDescribed: 0 };
18749
+ for (const p of store.findNodesByLabel("Problem")) {
18750
+ if (p.attrs["resolvedAt"] == null) continue;
18751
+ if (p.attrs["resolvedAs"] != null) continue;
18752
+ if (p.attrs["mergedInto"] !== void 0) continue;
18753
+ const sols = store.outEdges(p.id, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
18754
+ if (sols.length === 0) continue;
18755
+ if (!sols.every((s) => String(s.description ?? "").startsWith(AUTO_MINT_PREFIX))) {
18756
+ report.agentDescribed++;
18757
+ continue;
18758
+ }
18759
+ if (p.attrs["resolutionSuspect"] === true) report.alreadySuspect++;
18760
+ const attrs = { ...p.attrs };
18761
+ delete attrs["resolvedAt"];
18762
+ attrs["reopenedFrom"] = "auto-close";
18763
+ attrs["reopenedAt"] = t;
18764
+ store.updateNode(p.id, { attrs, lastUpdatedAt: t });
18765
+ report.reopened++;
18766
+ }
18767
+ return report;
18768
+ }
18747
18769
  function designProblemId(statement) {
18748
18770
  return identityId({ kind: "DesignProblem", statement });
18749
18771
  }
@@ -18773,7 +18795,7 @@ function retractDesignProblem(store, problemId, resolvedAs, reason, t) {
18773
18795
  }
18774
18796
  return true;
18775
18797
  }
18776
- function resolveDesignProblems(store, t) {
18798
+ function markFixCandidates(store, t) {
18777
18799
  let resolved = 0;
18778
18800
  for (const p of store.findNodesByLabel("Problem")) {
18779
18801
  if (!p.id.startsWith("dprob_")) continue;
@@ -18784,6 +18806,7 @@ function resolveDesignProblems(store, t) {
18784
18806
  let edited = false;
18785
18807
  for (const e of store.outEdges(p.id, ["ANCHORED_AT"])) {
18786
18808
  if (e.attrs?.["mention"] === true) continue;
18809
+ if (e.attrs?.["anchorProvenance"] === "legacy") continue;
18787
18810
  const sym = store.getNode(e.to);
18788
18811
  if (sym && sym.lastUpdatedAt > p.createdAt) {
18789
18812
  edited = true;
@@ -18793,24 +18816,21 @@ function resolveDesignProblems(store, t) {
18793
18816
  }
18794
18817
  }
18795
18818
  if (!edited) continue;
18796
- if (store.outEdges(p.id, ["SOLVED_BY"]).length === 0) {
18797
- const solId = `dfix_${digest({ problemId: p.id, edit: t })}`.slice(0, 56);
18798
- store.mergeNode(
18799
- buildNode(solId, "Solution", `${AUTO_MINT_PREFIX}${symName}`, t, {
18800
- source: "convo",
18801
- provisional: false,
18802
- // AC-resolution-attrs: the resolving symbol/file as STRUCTURED data, not
18803
- // just prose — the F2 join key downstream backfills and the viz read.
18804
- resolvedSymbols: [symName],
18805
- ...symRelPath ? { resolvedRelPath: symRelPath } : {}
18806
- })
18807
- );
18808
- mergeEdge(store, p.id, solId, "SOLVED_BY", t);
18809
- for (const ae of store.outEdges(p.id, ["ANCHORED_AT"]))
18810
- mergeEdge(store, solId, ae.to, "ANCHORED_AT", t);
18811
- }
18819
+ if (p.attrs["fixCandidateAt"] !== void 0) continue;
18820
+ if (store.outEdges(p.id, ["SOLVED_BY"]).some((e) => {
18821
+ const s = store.getNode(e.to);
18822
+ return s !== null && !String(s.description ?? "").startsWith(AUTO_MINT_PREFIX);
18823
+ }))
18824
+ continue;
18812
18825
  store.updateNode(p.id, {
18813
- attrs: { ...p.attrs, provisional: false, resolvedAt: t },
18826
+ attrs: {
18827
+ ...p.attrs,
18828
+ // The cue, kept as structured data so the render can name the file it is
18829
+ // asking about. Deliberately NOT `resolvedAt` — this is a question.
18830
+ fixCandidateAt: t,
18831
+ fixCandidateSymbol: symName,
18832
+ ...symRelPath ? { fixCandidateFile: symRelPath } : {}
18833
+ },
18814
18834
  lastUpdatedAt: t
18815
18835
  });
18816
18836
  resolved++;
@@ -21150,6 +21170,7 @@ __export(src_exports2, {
21150
21170
  listNeedsRevisit: () => listNeedsRevisit,
21151
21171
  localEdgeViolation: () => localEdgeViolation,
21152
21172
  markDiscriminatorAsked: () => markDiscriminatorAsked,
21173
+ markFixCandidates: () => markFixCandidates,
21153
21174
  markRevisit: () => markRevisit,
21154
21175
  matchLanguagesInText: () => matchLanguagesInText,
21155
21176
  matchPackagesInText: () => matchPackagesInText,
@@ -21179,10 +21200,10 @@ __export(src_exports2, {
21179
21200
  recordTriageObservation: () => recordTriageObservation,
21180
21201
  reinforceSameAnchorProblem: () => reinforceSameAnchorProblem,
21181
21202
  relateClaims: () => relateClaims,
21203
+ reopenAutoClosedProblems: () => reopenAutoClosedProblems,
21182
21204
  repairLegacyAnchorsFromStatement: () => repairLegacyAnchorsFromStatement,
21183
21205
  resolveDesignProblemById: () => resolveDesignProblemById,
21184
21206
  resolveDesignProblemByStatement: () => resolveDesignProblemByStatement,
21185
- resolveDesignProblems: () => resolveDesignProblems,
21186
21207
  resolveOsNode: () => resolveOsNode,
21187
21208
  retractDesignProblemById: () => retractDesignProblemById,
21188
21209
  retractDesignProblemByStatement: () => retractDesignProblemByStatement,
@@ -21362,7 +21383,11 @@ function sliceForFile(store, relPath) {
21362
21383
  }
21363
21384
  const fp = priorsForFile(store, relPath);
21364
21385
  const priors = fp ? {
21365
- openProblems: fp.openProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
21386
+ openProblems: fp.openProblems.slice(0, 3).map((p) => ({
21387
+ id: p.id,
21388
+ description: p.description,
21389
+ ...typeof p.attrs["fixCandidateFile"] === "string" ? { fixCandidateFile: p.attrs["fixCandidateFile"] } : {}
21390
+ })),
21366
21391
  constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
21367
21392
  resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
21368
21393
  related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),
@@ -21543,6 +21568,11 @@ function renderSnapshot(s) {
21543
21568
  );
21544
21569
  for (const p of w.priors.openProblems) {
21545
21570
  lines.push(` - ${p.description} \u2192 \`(fix:[${p.id}])\` \xB7 \`([${p.id}])\``);
21571
+ if (p.fixCandidateFile) {
21572
+ lines.push(
21573
+ ` - \`${p.fixCandidateFile}\` was edited after this was flagged. If that change fixed it, say so \u2014 \`(fix:[${p.id}])\`. If it did not, leave it open; nothing closes this but you.`
21574
+ );
21575
+ }
21546
21576
  const sols = w.priors.solutionsByProblem[p.id] ?? [];
21547
21577
  for (const s2 of sols) {
21548
21578
  lines.push(
@@ -27909,7 +27939,8 @@ function runNightlyPipeline(store) {
27909
27939
  for (const [id, c] of comm.community) store.updateNode(id, { community: c });
27910
27940
  });
27911
27941
  const motifs = promoteMotifs(store, started2);
27912
- const designResolved = resolveDesignProblems(store, started2);
27942
+ reopenAutoClosedProblems(store, started2);
27943
+ const designResolved = markFixCandidates(store, started2);
27913
27944
  const cry = crystallize(store, { ts: started2 });
27914
27945
  return {
27915
27946
  scoredNodes: scored,
@@ -53116,7 +53147,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53116
53147
  }
53117
53148
 
53118
53149
  // src/engine.ts
53119
- var DAEMON_VERSION = true ? "2.0.2-dev.336" : "2.0.0-alpha.0";
53150
+ var DAEMON_VERSION = true ? "2.0.2-dev.338" : "2.0.0-alpha.0";
53120
53151
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53121
53152
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53122
53153
  var GIT_OP_MUTE_MS = 4e3;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.336",
3
+ "version": "2.0.2-dev.338",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -25266,43 +25266,6 @@ function backfillProblemContext(store2, ts) {
25266
25266
  function isConstraintProblem(node) {
25267
25267
  return node.attrs["kind"] === "constraint";
25268
25268
  }
25269
- function buildNode(id, label, description, ts, attrs) {
25270
- return {
25271
- id,
25272
- label,
25273
- description,
25274
- extractionConfidence: 0.4,
25275
- // provisional: below the error-path's 0.6+
25276
- extractionSource: "agent-observed",
25277
- embedding: [],
25278
- cumulativeSurprise: 0,
25279
- peakSurprise: 0,
25280
- cumulativeHits: 1,
25281
- lastUpdatedAt: ts,
25282
- createdAt: ts,
25283
- memoryTier: "short-term",
25284
- pageRank: 0,
25285
- isLandmark: false,
25286
- community: null,
25287
- stability: "unstable",
25288
- attrs
25289
- };
25290
- }
25291
- function mergeEdge(store2, from, to, type, ts) {
25292
- store2.mergeEdge({
25293
- id: `edge_${digest({ from, type, to })}`.slice(0, 24),
25294
- from,
25295
- to,
25296
- type,
25297
- confidence: 0.4,
25298
- extractionSource: "agent-observed",
25299
- createdAt: ts,
25300
- lastSeenAt: ts,
25301
- navSuccesses: 0,
25302
- navFailures: 0,
25303
- attrs: { provisional: true }
25304
- });
25305
- }
25306
25269
  var CITABLE_PRIOR_LABELS = /* @__PURE__ */ new Set([
25307
25270
  "Solution",
25308
25271
  "RootCause",
@@ -25381,8 +25344,30 @@ function recordAnchorHint(store2, problemId, relPath, provenance, ts) {
25381
25344
  });
25382
25345
  return true;
25383
25346
  }
25347
+ function reopenAutoClosedProblems(store2, t) {
25348
+ const report = { reopened: 0, alreadySuspect: 0, agentDescribed: 0 };
25349
+ for (const p of store2.findNodesByLabel("Problem")) {
25350
+ if (p.attrs["resolvedAt"] == null) continue;
25351
+ if (p.attrs["resolvedAs"] != null) continue;
25352
+ if (p.attrs["mergedInto"] !== void 0) continue;
25353
+ const sols = store2.outEdges(p.id, ["SOLVED_BY"]).map((e) => store2.getNode(e.to)).filter((n) => n !== null);
25354
+ if (sols.length === 0) continue;
25355
+ if (!sols.every((s) => String(s.description ?? "").startsWith(AUTO_MINT_PREFIX))) {
25356
+ report.agentDescribed++;
25357
+ continue;
25358
+ }
25359
+ if (p.attrs["resolutionSuspect"] === true) report.alreadySuspect++;
25360
+ const attrs = { ...p.attrs };
25361
+ delete attrs["resolvedAt"];
25362
+ attrs["reopenedFrom"] = "auto-close";
25363
+ attrs["reopenedAt"] = t;
25364
+ store2.updateNode(p.id, { attrs, lastUpdatedAt: t });
25365
+ report.reopened++;
25366
+ }
25367
+ return report;
25368
+ }
25384
25369
  var AUTO_MINT_PREFIX = "addressed by an edit to ";
25385
- function resolveDesignProblems(store2, t) {
25370
+ function markFixCandidates(store2, t) {
25386
25371
  let resolved = 0;
25387
25372
  for (const p of store2.findNodesByLabel("Problem")) {
25388
25373
  if (!p.id.startsWith("dprob_")) continue;
@@ -25393,6 +25378,7 @@ function resolveDesignProblems(store2, t) {
25393
25378
  let edited = false;
25394
25379
  for (const e of store2.outEdges(p.id, ["ANCHORED_AT"])) {
25395
25380
  if (e.attrs?.["mention"] === true) continue;
25381
+ if (e.attrs?.["anchorProvenance"] === "legacy") continue;
25396
25382
  const sym = store2.getNode(e.to);
25397
25383
  if (sym && sym.lastUpdatedAt > p.createdAt) {
25398
25384
  edited = true;
@@ -25402,24 +25388,21 @@ function resolveDesignProblems(store2, t) {
25402
25388
  }
25403
25389
  }
25404
25390
  if (!edited) continue;
25405
- if (store2.outEdges(p.id, ["SOLVED_BY"]).length === 0) {
25406
- const solId = `dfix_${digest({ problemId: p.id, edit: t })}`.slice(0, 56);
25407
- store2.mergeNode(
25408
- buildNode(solId, "Solution", `${AUTO_MINT_PREFIX}${symName}`, t, {
25409
- source: "convo",
25410
- provisional: false,
25411
- // AC-resolution-attrs: the resolving symbol/file as STRUCTURED data, not
25412
- // just prose — the F2 join key downstream backfills and the viz read.
25413
- resolvedSymbols: [symName],
25414
- ...symRelPath ? { resolvedRelPath: symRelPath } : {}
25415
- })
25416
- );
25417
- mergeEdge(store2, p.id, solId, "SOLVED_BY", t);
25418
- for (const ae of store2.outEdges(p.id, ["ANCHORED_AT"]))
25419
- mergeEdge(store2, solId, ae.to, "ANCHORED_AT", t);
25420
- }
25391
+ if (p.attrs["fixCandidateAt"] !== void 0) continue;
25392
+ if (store2.outEdges(p.id, ["SOLVED_BY"]).some((e) => {
25393
+ const s = store2.getNode(e.to);
25394
+ return s !== null && !String(s.description ?? "").startsWith(AUTO_MINT_PREFIX);
25395
+ }))
25396
+ continue;
25421
25397
  store2.updateNode(p.id, {
25422
- attrs: { ...p.attrs, provisional: false, resolvedAt: t },
25398
+ attrs: {
25399
+ ...p.attrs,
25400
+ // The cue, kept as structured data so the render can name the file it is
25401
+ // asking about. Deliberately NOT `resolvedAt` — this is a question.
25402
+ fixCandidateAt: t,
25403
+ fixCandidateSymbol: symName,
25404
+ ...symRelPath ? { fixCandidateFile: symRelPath } : {}
25405
+ },
25423
25406
  lastUpdatedAt: t
25424
25407
  });
25425
25408
  resolved++;
@@ -26219,7 +26202,8 @@ function runNightlyPipeline(store2) {
26219
26202
  for (const [id, c] of comm.community) store2.updateNode(id, { community: c });
26220
26203
  });
26221
26204
  const motifs = promoteMotifs(store2, started);
26222
- const designResolved = resolveDesignProblems(store2, started);
26205
+ reopenAutoClosedProblems(store2, started);
26206
+ const designResolved = markFixCandidates(store2, started);
26223
26207
  const cry = crystallize(store2, { ts: started });
26224
26208
  return {
26225
26209
  scoredNodes: scored,
@@ -26412,7 +26396,11 @@ function sliceForFile(store2, relPath) {
26412
26396
  }
26413
26397
  const fp = priorsForFile(store2, relPath);
26414
26398
  const priors = fp ? {
26415
- openProblems: fp.openProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
26399
+ openProblems: fp.openProblems.slice(0, 3).map((p) => ({
26400
+ id: p.id,
26401
+ description: p.description,
26402
+ ...typeof p.attrs["fixCandidateFile"] === "string" ? { fixCandidateFile: p.attrs["fixCandidateFile"] } : {}
26403
+ })),
26416
26404
  constraints: fp.constraints.slice(0, 2).map((c) => ({ id: c.id, description: c.description })),
26417
26405
  resolvedProblems: fp.resolvedProblems.slice(0, 3).map((p) => ({ id: p.id, description: p.description })),
26418
26406
  related: fp.related.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description })),