@inerrata-corporation/errata 2.0.2-dev.497 → 2.0.2-dev.503

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
@@ -19295,11 +19295,13 @@ function markFixCandidates(store, t) {
19295
19295
  let symName = "";
19296
19296
  let symRelPath;
19297
19297
  let edited = false;
19298
+ const since = Math.max(p.createdAt, Number(p.attrs["fixCandidateClearedAt"] ?? 0));
19298
19299
  for (const e of store.outEdges(p.id, ["ANCHORED_AT"])) {
19299
19300
  if (e.attrs?.["mention"] === true) continue;
19300
19301
  if (e.attrs?.["anchorProvenance"] === "legacy") continue;
19301
19302
  const sym = store.getNode(e.to);
19302
- if (sym && sym.lastUpdatedAt > p.createdAt) {
19303
+ const changedAt = sym?.label === "File" ? Number(sym.attrs["contentChangedAt"] ?? 0) : sym?.lastUpdatedAt ?? 0;
19304
+ if (sym && changedAt > since) {
19303
19305
  edited = true;
19304
19306
  symName = sym.description;
19305
19307
  symRelPath = sym.attrs["relPath"] ?? void 0;
@@ -19320,7 +19322,12 @@ function markFixCandidates(store, t) {
19320
19322
  // asking about. Deliberately NOT `resolvedAt` — this is a question.
19321
19323
  fixCandidateAt: t,
19322
19324
  fixCandidateSymbol: symName,
19323
- ...symRelPath ? { fixCandidateFile: symRelPath } : {}
19325
+ ...symRelPath ? { fixCandidateFile: symRelPath } : {},
19326
+ // Snapshot the render-ledger counter so "shown since THIS ask" is
19327
+ // measurable. `shownCount` is the node's LIFETIME count across every
19328
+ // band, so comparing it raw would retire a fresh ask on a
19329
+ // frequently-surfaced problem before anyone had seen the question once.
19330
+ fixCandidateShownBase: Number(p.attrs["shownCount"] ?? 0)
19324
19331
  },
19325
19332
  lastUpdatedAt: t
19326
19333
  });
@@ -19328,6 +19335,37 @@ function markFixCandidates(store, t) {
19328
19335
  }
19329
19336
  return resolved;
19330
19337
  }
19338
+ function clearSettledFixCandidates(store, t) {
19339
+ const report = { answered: 0, ignored: 0, unsubstantiated: 0, standing: 0 };
19340
+ for (const p of store.findNodesByLabel("Problem")) {
19341
+ if (p.attrs["fixCandidateAt"] === void 0) continue;
19342
+ const fileAnchors = store.outEdges(p.id, ["ANCHORED_AT"]).filter((e) => e.attrs?.["mention"] !== true && e.attrs?.["anchorProvenance"] !== "legacy").map((e) => store.getNode(e.to)).filter((n) => n !== null && n.label === "File");
19343
+ const unsubstantiated = fileAnchors.length > 0 && fileAnchors.every((f) => f.attrs["contentChangedAt"] === void 0);
19344
+ const answered = p.attrs["resolvedAt"] != null || store.outEdges(p.id, ["SOLVED_BY"]).some((e) => {
19345
+ const s = store.getNode(e.to);
19346
+ return s !== null && !String(s.description ?? "").startsWith(AUTO_MINT_PREFIX);
19347
+ });
19348
+ const base = Number(
19349
+ p.attrs["fixCandidateShownBase"] ?? p.attrs["shownCount"] ?? 0
19350
+ );
19351
+ const shownSinceAsk = Number(p.attrs["shownCount"] ?? 0) - base;
19352
+ const ignored = shownSinceAsk >= FIX_CANDIDATE_ASK_LIMIT;
19353
+ if (!answered && !ignored && !unsubstantiated) {
19354
+ report.standing++;
19355
+ continue;
19356
+ }
19357
+ const attrs = { ...p.attrs };
19358
+ delete attrs["fixCandidateAt"];
19359
+ delete attrs["fixCandidateSymbol"];
19360
+ delete attrs["fixCandidateFile"];
19361
+ attrs["fixCandidateClearedAt"] = t;
19362
+ store.updateNode(p.id, { attrs, lastUpdatedAt: t });
19363
+ if (answered) report.answered++;
19364
+ else if (ignored) report.ignored++;
19365
+ else report.unsubstantiated++;
19366
+ }
19367
+ return report;
19368
+ }
19331
19369
  function recordRenderLedger(store, ledger, seq, ts) {
19332
19370
  const bump = (ids, field) => {
19333
19371
  let n = 0;
@@ -19353,7 +19391,7 @@ function recordRenderLedger(store, ledger, seq, ts) {
19353
19391
  });
19354
19392
  return { shown, evicted };
19355
19393
  }
19356
- var DESIGN_PROMOTE_AT, STATEMENT_ALIAS_CAP, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, AUTO_MINT_PREFIX;
19394
+ var DESIGN_PROMOTE_AT, STATEMENT_ALIAS_CAP, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, AUTO_MINT_PREFIX, FIX_CANDIDATE_ASK_LIMIT;
19357
19395
  var init_design_problem = __esm({
19358
19396
  "../../packages/local-graph/src/design-problem.ts"() {
19359
19397
  "use strict";
@@ -19400,6 +19438,7 @@ var init_design_problem = __esm({
19400
19438
  ]);
19401
19439
  MAX_ANCHOR_FILES = 5;
19402
19440
  AUTO_MINT_PREFIX = "addressed by an edit to ";
19441
+ FIX_CANDIDATE_ASK_LIMIT = 5;
19403
19442
  }
19404
19443
  });
19405
19444
 
@@ -21723,6 +21762,7 @@ __export(src_exports2, {
21723
21762
  CITABLE_PRIOR_LABELS: () => CITABLE_PRIOR_LABELS,
21724
21763
  CODE_REACH_EDGES: () => CODE_REACH_EDGES,
21725
21764
  CREDIT_FAMILY: () => CREDIT_FAMILY,
21765
+ FIX_CANDIDATE_ASK_LIMIT: () => FIX_CANDIDATE_ASK_LIMIT,
21726
21766
  JOINT_COMMUNITY_EDGES: () => JOINT_COMMUNITY_EDGES,
21727
21767
  JOINT_COMMUNITY_LABELS: () => JOINT_COMMUNITY_LABELS,
21728
21768
  MAX_ANCHOR_FILES: () => MAX_ANCHOR_FILES,
@@ -21752,6 +21792,7 @@ __export(src_exports2, {
21752
21792
  claimId: () => claimId,
21753
21793
  clearAnsweredRevisits: () => clearAnsweredRevisits,
21754
21794
  clearRevisit: () => clearRevisit,
21795
+ clearSettledFixCandidates: () => clearSettledFixCandidates,
21755
21796
  communityInductionRequests: () => communityInductionRequests,
21756
21797
  communitySeeds: () => communitySeeds,
21757
21798
  compareSemver: () => compareSemver,
@@ -28475,6 +28516,7 @@ function runNightlyPipeline(store) {
28475
28516
  const motifs = promoteMotifs(store, started2);
28476
28517
  reopenAutoClosedProblems(store, started2);
28477
28518
  const revisits = clearAnsweredRevisits(store, started2);
28519
+ const fixCandidates = clearSettledFixCandidates(store, started2);
28478
28520
  const designResolved = markFixCandidates(store, started2);
28479
28521
  const cry = crystallize(store, { ts: started2 });
28480
28522
  return {
@@ -28491,6 +28533,7 @@ function runNightlyPipeline(store) {
28491
28533
  skillsRefreshed: 0,
28492
28534
  designResolved,
28493
28535
  revisitsCleared: revisits.cleared,
28536
+ fixCandidatesSettled: fixCandidates.answered + fixCandidates.ignored + fixCandidates.unsubstantiated,
28494
28537
  claimsEvaluated: cry.evaluated,
28495
28538
  claimsDerived: cry.derived.length,
28496
28539
  durationMs: Date.now() - started2
@@ -29686,7 +29729,15 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
29686
29729
  const h = fileHashes.get(rel);
29687
29730
  if (!h) continue;
29688
29731
  const fnode = store.getNode(fileNodeId(workspaceId2, rel));
29689
- if (fnode) store.updateNode(fnode.id, { attrs: { ...fnode.attrs, contentHash: h } });
29732
+ if (!fnode) continue;
29733
+ const contentMoved = fnode.attrs["contentHash"] !== h;
29734
+ store.updateNode(fnode.id, {
29735
+ attrs: {
29736
+ ...fnode.attrs,
29737
+ contentHash: h,
29738
+ ...contentMoved ? { contentChangedAt: t } : {}
29739
+ }
29740
+ });
29690
29741
  }
29691
29742
  return {
29692
29743
  filesReindexed: changedRelPaths.size,
@@ -53746,7 +53797,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53746
53797
  }
53747
53798
 
53748
53799
  // src/engine.ts
53749
- var DAEMON_VERSION = true ? "2.0.2-dev.497" : "2.0.0-alpha.0";
53800
+ var DAEMON_VERSION = true ? "2.0.2-dev.503" : "2.0.0-alpha.0";
53750
53801
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53751
53802
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53752
53803
  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.497",
3
+ "version": "2.0.2-dev.503",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -16139,7 +16139,15 @@ async function incrementalReindex(store2, rootPath, workspaceId, changedAbsPaths
16139
16139
  const h = fileHashes.get(rel);
16140
16140
  if (!h) continue;
16141
16141
  const fnode = store2.getNode(fileNodeId(workspaceId, rel));
16142
- if (fnode) store2.updateNode(fnode.id, { attrs: { ...fnode.attrs, contentHash: h } });
16142
+ if (!fnode) continue;
16143
+ const contentMoved = fnode.attrs["contentHash"] !== h;
16144
+ store2.updateNode(fnode.id, {
16145
+ attrs: {
16146
+ ...fnode.attrs,
16147
+ contentHash: h,
16148
+ ...contentMoved ? { contentChangedAt: t } : {}
16149
+ }
16150
+ });
16143
16151
  }
16144
16152
  return {
16145
16153
  filesReindexed: changedRelPaths.size,
@@ -25579,11 +25587,13 @@ function markFixCandidates(store2, t) {
25579
25587
  let symName = "";
25580
25588
  let symRelPath;
25581
25589
  let edited = false;
25590
+ const since = Math.max(p.createdAt, Number(p.attrs["fixCandidateClearedAt"] ?? 0));
25582
25591
  for (const e of store2.outEdges(p.id, ["ANCHORED_AT"])) {
25583
25592
  if (e.attrs?.["mention"] === true) continue;
25584
25593
  if (e.attrs?.["anchorProvenance"] === "legacy") continue;
25585
25594
  const sym = store2.getNode(e.to);
25586
- if (sym && sym.lastUpdatedAt > p.createdAt) {
25595
+ const changedAt = sym?.label === "File" ? Number(sym.attrs["contentChangedAt"] ?? 0) : sym?.lastUpdatedAt ?? 0;
25596
+ if (sym && changedAt > since) {
25587
25597
  edited = true;
25588
25598
  symName = sym.description;
25589
25599
  symRelPath = sym.attrs["relPath"] ?? void 0;
@@ -25604,7 +25614,12 @@ function markFixCandidates(store2, t) {
25604
25614
  // asking about. Deliberately NOT `resolvedAt` — this is a question.
25605
25615
  fixCandidateAt: t,
25606
25616
  fixCandidateSymbol: symName,
25607
- ...symRelPath ? { fixCandidateFile: symRelPath } : {}
25617
+ ...symRelPath ? { fixCandidateFile: symRelPath } : {},
25618
+ // Snapshot the render-ledger counter so "shown since THIS ask" is
25619
+ // measurable. `shownCount` is the node's LIFETIME count across every
25620
+ // band, so comparing it raw would retire a fresh ask on a
25621
+ // frequently-surfaced problem before anyone had seen the question once.
25622
+ fixCandidateShownBase: Number(p.attrs["shownCount"] ?? 0)
25608
25623
  },
25609
25624
  lastUpdatedAt: t
25610
25625
  });
@@ -25612,6 +25627,38 @@ function markFixCandidates(store2, t) {
25612
25627
  }
25613
25628
  return resolved;
25614
25629
  }
25630
+ var FIX_CANDIDATE_ASK_LIMIT = 5;
25631
+ function clearSettledFixCandidates(store2, t) {
25632
+ const report = { answered: 0, ignored: 0, unsubstantiated: 0, standing: 0 };
25633
+ for (const p of store2.findNodesByLabel("Problem")) {
25634
+ if (p.attrs["fixCandidateAt"] === void 0) continue;
25635
+ const fileAnchors = store2.outEdges(p.id, ["ANCHORED_AT"]).filter((e) => e.attrs?.["mention"] !== true && e.attrs?.["anchorProvenance"] !== "legacy").map((e) => store2.getNode(e.to)).filter((n) => n !== null && n.label === "File");
25636
+ const unsubstantiated = fileAnchors.length > 0 && fileAnchors.every((f) => f.attrs["contentChangedAt"] === void 0);
25637
+ const answered = p.attrs["resolvedAt"] != null || store2.outEdges(p.id, ["SOLVED_BY"]).some((e) => {
25638
+ const s = store2.getNode(e.to);
25639
+ return s !== null && !String(s.description ?? "").startsWith(AUTO_MINT_PREFIX);
25640
+ });
25641
+ const base = Number(
25642
+ p.attrs["fixCandidateShownBase"] ?? p.attrs["shownCount"] ?? 0
25643
+ );
25644
+ const shownSinceAsk = Number(p.attrs["shownCount"] ?? 0) - base;
25645
+ const ignored = shownSinceAsk >= FIX_CANDIDATE_ASK_LIMIT;
25646
+ if (!answered && !ignored && !unsubstantiated) {
25647
+ report.standing++;
25648
+ continue;
25649
+ }
25650
+ const attrs = { ...p.attrs };
25651
+ delete attrs["fixCandidateAt"];
25652
+ delete attrs["fixCandidateSymbol"];
25653
+ delete attrs["fixCandidateFile"];
25654
+ attrs["fixCandidateClearedAt"] = t;
25655
+ store2.updateNode(p.id, { attrs, lastUpdatedAt: t });
25656
+ if (answered) report.answered++;
25657
+ else if (ignored) report.ignored++;
25658
+ else report.unsubstantiated++;
25659
+ }
25660
+ return report;
25661
+ }
25615
25662
 
25616
25663
  // ../../packages/local-graph/src/intent.ts
25617
25664
  init_src();
@@ -26347,6 +26394,7 @@ function runNightlyPipeline(store2) {
26347
26394
  const motifs = promoteMotifs(store2, started);
26348
26395
  reopenAutoClosedProblems(store2, started);
26349
26396
  const revisits = clearAnsweredRevisits(store2, started);
26397
+ const fixCandidates = clearSettledFixCandidates(store2, started);
26350
26398
  const designResolved = markFixCandidates(store2, started);
26351
26399
  const cry = crystallize(store2, { ts: started });
26352
26400
  return {
@@ -26363,6 +26411,7 @@ function runNightlyPipeline(store2) {
26363
26411
  skillsRefreshed: 0,
26364
26412
  designResolved,
26365
26413
  revisitsCleared: revisits.cleared,
26414
+ fixCandidatesSettled: fixCandidates.answered + fixCandidates.ignored + fixCandidates.unsubstantiated,
26366
26415
  claimsEvaluated: cry.evaluated,
26367
26416
  claimsDerived: cry.derived.length,
26368
26417
  durationMs: Date.now() - started