@inerrata-corporation/errata 2.0.23-dev.4821 → 2.0.23-dev.4826

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
@@ -5198,8 +5198,8 @@ var init_az = __esm({
5198
5198
  });
5199
5199
 
5200
5200
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/be.js
5201
- function getBelarusianPlural(count, one, few, many) {
5202
- const absCount = Math.abs(count);
5201
+ function getBelarusianPlural(count2, one, few, many) {
5202
+ const absCount = Math.abs(count2);
5203
5203
  const lastDigit = absCount % 10;
5204
5204
  const lastTwoDigits = absCount % 100;
5205
5205
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -7113,8 +7113,8 @@ var init_hu = __esm({
7113
7113
  });
7114
7114
 
7115
7115
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/hy.js
7116
- function getArmenianPlural(count, one, many) {
7117
- return Math.abs(count) === 1 ? one : many;
7116
+ function getArmenianPlural(count2, one, many) {
7117
+ return Math.abs(count2) === 1 ? one : many;
7118
7118
  }
7119
7119
  function withDefiniteArticle(word) {
7120
7120
  if (!word)
@@ -9229,8 +9229,8 @@ var init_pt = __esm({
9229
9229
  });
9230
9230
 
9231
9231
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/locales/ru.js
9232
- function getRussianPlural(count, one, few, many) {
9233
- const absCount = Math.abs(count);
9232
+ function getRussianPlural(count2, one, few, many) {
9233
+ const absCount = Math.abs(count2);
9234
9234
  const lastDigit = absCount % 10;
9235
9235
  const lastTwoDigits = absCount % 100;
9236
9236
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -15538,7 +15538,7 @@ function looksLikeSecretValue(raw2, quoted) {
15538
15538
  return raw2.length > 0;
15539
15539
  }
15540
15540
  function applyRule(text, rule, removed) {
15541
- let count = 0;
15541
+ let count2 = 0;
15542
15542
  const out2 = text.replace(rule.re, (...args2) => {
15543
15543
  const m = args2.slice(0, -2);
15544
15544
  const r = rule.replace(m);
@@ -15551,10 +15551,10 @@ function applyRule(text, rule, removed) {
15551
15551
  if (literal2 && !literal2.includes("[redacted:")) removed.add(literal2);
15552
15552
  }
15553
15553
  }
15554
- count += 1;
15554
+ count2 += 1;
15555
15555
  return r;
15556
15556
  });
15557
- return { text: out2, count };
15557
+ return { text: out2, count: count2 };
15558
15558
  }
15559
15559
  function scrubHistoryText(text) {
15560
15560
  return scrubText(text);
@@ -19708,20 +19708,21 @@ var init_momentum = __esm({
19708
19708
  });
19709
19709
 
19710
19710
  // ../../packages/math/src/persistence.ts
19711
- function reinforcementFactor(count) {
19712
- const n = Math.max(0, count ?? 0);
19711
+ function reinforcementFactor(count2) {
19712
+ const n = Math.max(0, count2 ?? 0);
19713
19713
  return 1 + REINFORCEMENT_ALPHA * Math.tanh(n / REINFORCEMENT_K);
19714
19714
  }
19715
19715
  function contradictionFactor(pressure) {
19716
19716
  const p = Math.max(0, pressure ?? 0);
19717
19717
  return 1 - CONTRADICTION_MAX_DAMPENER * Math.tanh(p / CONTRADICTION_K);
19718
19718
  }
19719
- var REINFORCEMENT_ALPHA, REINFORCEMENT_K, CONTRADICTION_MAX_DAMPENER, CONTRADICTION_K;
19719
+ var REINFORCEMENT_ALPHA, REINFORCEMENT_K, SUPERSESSION_DAMPENER, CONTRADICTION_MAX_DAMPENER, CONTRADICTION_K;
19720
19720
  var init_persistence = __esm({
19721
19721
  "../../packages/math/src/persistence.ts"() {
19722
19722
  "use strict";
19723
19723
  REINFORCEMENT_ALPHA = 0.3;
19724
19724
  REINFORCEMENT_K = 20;
19725
+ SUPERSESSION_DAMPENER = 0.7;
19725
19726
  CONTRADICTION_MAX_DAMPENER = 0.25;
19726
19727
  CONTRADICTION_K = 10;
19727
19728
  }
@@ -20536,7 +20537,7 @@ function rankKnowledge(input, weights) {
20536
20537
  const relevance = Math.max(own, clamp012(input.inherited ?? 0));
20537
20538
  const hop = Math.max(w.hopFloor, 1 - w.hopPenalty * Math.max(0, input.hops ?? 0));
20538
20539
  const e = input.evidence ?? {};
20539
- const persistence = reinforcementFactor(e.reinforcementCount) * contradictionFactor(e.contradictionPressure);
20540
+ const persistence = reinforcementFactor(e.reinforcementCount) * contradictionFactor(e.contradictionPressure) * supersessionFactor(e.supersededBy);
20540
20541
  const { uncertainty } = computeNodeUncertainty({
20541
20542
  id: "",
20542
20543
  acceptedCount: e.acceptedCount ?? 0,
@@ -20549,6 +20550,10 @@ function rankKnowledge(input, weights) {
20549
20550
  components: { relevance, semantic, lexical, hop, persistence, reliability, uncertainty }
20550
20551
  };
20551
20552
  }
20553
+ function supersessionFactor(supersededBy) {
20554
+ const n = Math.max(0, supersededBy ?? 0);
20555
+ return 1 - (1 - SUPERSESSION_DAMPENER) * (1 - Math.exp(-n));
20556
+ }
20552
20557
  function termCoverage(terms, text, weightOf) {
20553
20558
  if (terms.length === 0) return 0;
20554
20559
  const hay = text.toLowerCase();
@@ -20564,7 +20569,7 @@ function termCoverage(terms, text, weightOf) {
20564
20569
  function poolEvidence(a, b) {
20565
20570
  if (!a) return b;
20566
20571
  if (!b) return a;
20567
- const keys = ["acceptedCount", "corroborationCount", "failureReportCount", "contradictionPressure", "reinforcementCount"];
20572
+ const keys = ["acceptedCount", "corroborationCount", "failureReportCount", "contradictionPressure", "reinforcementCount", "supersededBy"];
20568
20573
  const out2 = {};
20569
20574
  for (const k of keys) out2[k] = Math.max(a[k] ?? 0, b[k] ?? 0);
20570
20575
  return out2;
@@ -22031,11 +22036,11 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
22031
22036
  * kept with the change-feed reading of the rows it counts — triggers bump it on
22032
22037
  * every write from any connection, so a hit is exact, not a TTL guess. */
22033
22038
  counts = /* @__PURE__ */ new Map();
22034
- countAt(key, scopes, count) {
22039
+ countAt(key, scopes, count2) {
22035
22040
  const seq = readChangeSeq(this.db, scopes);
22036
22041
  const hit = this.counts.get(key);
22037
22042
  if (hit && hit.seq === seq) return hit.n;
22038
- const n = count();
22043
+ const n = count2();
22039
22044
  this.counts.set(key, { seq, n });
22040
22045
  return n;
22041
22046
  }
@@ -24466,7 +24471,7 @@ function recordVulnerabilityCause(store, findingId, causes, ts) {
24466
24471
  const finding = store.getNode(findingId);
24467
24472
  if (finding?.label !== "Vulnerability") return 0;
24468
24473
  let from = findingId;
24469
- let count = 0;
24474
+ let count2 = 0;
24470
24475
  for (const description of causes) {
24471
24476
  if (isPlaceholderStatement(description)) continue;
24472
24477
  const id = genericCanonicalId("dcause", { findingId, description: description.trim() });
@@ -24478,9 +24483,9 @@ function recordVulnerabilityCause(store, findingId, causes, ts) {
24478
24483
  }));
24479
24484
  mergeEdge(store, from, id, "CAUSED_BY", ts);
24480
24485
  from = id;
24481
- count++;
24486
+ count2++;
24482
24487
  }
24483
- return count;
24488
+ return count2;
24484
24489
  }
24485
24490
  function canonicalizePatternText(name2) {
24486
24491
  const stripped = name2.replace(/^\s*pattern(?:\s*[×x]\s*\d+)?\s*(?:\(exemplar\))?\s*[:—–-]\s*/i, "").replace(/\s+/g, " ").trim();
@@ -24796,6 +24801,15 @@ function isFragmentFixNote(note) {
24796
24801
  function isAutoMinted(n) {
24797
24802
  return isEditPlaceholderSolution(n);
24798
24803
  }
24804
+ function sameFixStatement(a, b) {
24805
+ const words = (t) => new Set(t.toLowerCase().split(/[^a-z0-9_]+/).filter((w) => w.length >= 3));
24806
+ const x = words(a);
24807
+ const y = words(b);
24808
+ if (x.size === 0 || y.size === 0) return solutionTextKey(a) === solutionTextKey(b);
24809
+ let shared = 0;
24810
+ for (const w of x) if (y.has(w)) shared++;
24811
+ return shared / (x.size + y.size - shared) >= SAME_FIX_JACCARD;
24812
+ }
24799
24813
  function solutionTextKey(text) {
24800
24814
  return text.trim().replace(/\s+/g, " ").toLowerCase();
24801
24815
  }
@@ -24822,7 +24836,7 @@ function priorsForFile(store, relPath) {
24822
24836
  const constraints = [];
24823
24837
  const resolvedProblems = [];
24824
24838
  const seenProblem = /* @__PURE__ */ new Set();
24825
- const related = /* @__PURE__ */ new Map();
24839
+ const related2 = /* @__PURE__ */ new Map();
24826
24840
  const anchorEdges = [
24827
24841
  ...store.inEdges(file2.id, ["ANCHORED_AT"]),
24828
24842
  ...store.outEdges(file2.id, ["DEFINES"]).flatMap((d) => store.inEdges(d.to, ["ANCHORED_AT"]))
@@ -24839,14 +24853,14 @@ function priorsForFile(store, relPath) {
24839
24853
  resolvedProblems.push(n);
24840
24854
  }
24841
24855
  } else if (CITABLE_PRIOR_LABELS.has(n.label) && !isAutoMinted(n)) {
24842
- related.set(n.id, n);
24856
+ related2.set(n.id, n);
24843
24857
  }
24844
24858
  }
24845
24859
  const solutionsByProblem = /* @__PURE__ */ new Map();
24846
24860
  for (const p of [...openProblems, ...constraints, ...resolvedProblems]) {
24847
24861
  for (const e of store.outEdges(p.id, ["SOLVED_BY", "CAUSED_BY", "INSTANCE_OF"])) {
24848
24862
  const n = store.getNode(e.to);
24849
- if (n && CITABLE_PRIOR_LABELS.has(n.label) && !isAutoMinted(n)) related.set(n.id, n);
24863
+ if (n && CITABLE_PRIOR_LABELS.has(n.label) && !isAutoMinted(n)) related2.set(n.id, n);
24850
24864
  if (n && n.label === "Solution" && e.type === "SOLVED_BY" && !isAutoMinted(n)) {
24851
24865
  const list = solutionsByProblem.get(p.id) ?? [];
24852
24866
  if (!list.some((s) => s.id === n.id)) list.push(n);
@@ -24854,7 +24868,7 @@ function priorsForFile(store, relPath) {
24854
24868
  }
24855
24869
  }
24856
24870
  }
24857
- if (openProblems.length === 0 && constraints.length === 0 && resolvedProblems.length === 0 && related.size === 0)
24871
+ if (openProblems.length === 0 && constraints.length === 0 && resolvedProblems.length === 0 && related2.size === 0)
24858
24872
  return null;
24859
24873
  const recentFirst = (a, b) => (b.lastUpdatedAt ?? 0) - (a.lastUpdatedAt ?? 0);
24860
24874
  openProblems.sort(recentFirst);
@@ -24867,7 +24881,7 @@ function priorsForFile(store, relPath) {
24867
24881
  openProblems,
24868
24882
  constraints,
24869
24883
  resolvedProblems,
24870
- related: [...related.values()],
24884
+ related: [...related2.values()],
24871
24885
  solutionsByProblem
24872
24886
  };
24873
24887
  }
@@ -24895,8 +24909,13 @@ function anchorNodeToDiff(store, nodeId, expectLabel, changedPaths, workspaceId2
24895
24909
  return n;
24896
24910
  }
24897
24911
  function solutionForProblem(store, problemId) {
24898
- const e = store.outEdges(problemId, ["SOLVED_BY"])[0];
24899
- return e ? e.to : null;
24912
+ const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
24913
+ const live3 = sols.filter((s) => s.validTo == null && !isAutoMinted(s));
24914
+ const pick2 = (live3.length > 0 ? live3 : sols).reduce(
24915
+ (best, s) => !best || s.createdAt > best.createdAt ? s : best,
24916
+ null
24917
+ );
24918
+ return pick2 ? pick2.id : null;
24900
24919
  }
24901
24920
  function anchorProblemToWorkingFile(store, problemId, relPath, workspaceId2, ts, provenance = "edited", opts = {}) {
24902
24921
  const p = store.getNode(problemId);
@@ -25080,9 +25099,9 @@ function upgradeAnchorHints(store, workspaceId2, ts) {
25080
25099
  }
25081
25100
  return { upgraded, standing, unresolvable, blocked };
25082
25101
  }
25083
- function resolveDesignProblemByStatement(store, statement, fixNote, t) {
25102
+ function resolveDesignProblemByStatement(store, statement, fixNote, t, session) {
25084
25103
  const problemId = identityId({ kind: "DesignProblem", statement });
25085
- return closeDesignProblem(store, problemId, fixNote, t);
25104
+ return closeDesignProblem(store, problemId, fixNote, t, session);
25086
25105
  }
25087
25106
  function closableByCaller(node2) {
25088
25107
  if (node2.attrs["source"] !== "cloud") return true;
@@ -25092,17 +25111,19 @@ function closableByCaller(node2) {
25092
25111
  function isVerdictable(node2) {
25093
25112
  return node2.label === "Problem" && node2.attrs["resolvedAt"] == null && (node2.validTo ?? null) === null && !isConstraintProblem(node2) && node2.attrs["kind"] !== "todo";
25094
25113
  }
25095
- function resolveDesignProblemById(store, id, fixNote, t) {
25096
- return closeDesignProblem(store, id.trim(), fixNote, t);
25114
+ function resolveDesignProblemById(store, id, fixNote, t, session) {
25115
+ return closeDesignProblem(store, id.trim(), fixNote, t, session);
25097
25116
  }
25098
- function closeDesignProblem(store, problemId, fixNote, t) {
25117
+ function closeDesignProblem(store, problemId, fixNote, t, session) {
25099
25118
  const p = store.getNode(problemId);
25100
25119
  if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
25101
25120
  if (!closableByCaller(p)) return false;
25102
25121
  if (p.attrs["resolvedAs"]) return false;
25103
25122
  if (fixNote?.trim() && !isFragmentFixNote(fixNote)) {
25104
25123
  const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
25105
- if (sols.every((s) => isAutoMinted(s))) {
25124
+ const real = sols.filter((s) => !isAutoMinted(s) && s.validTo == null);
25125
+ const secondAnswer = session != null && real.length > 0 && real.every((s) => !(s.attrs["sources"] ?? []).includes(session)) && !real.some((s) => sameFixStatement(s.description, fixNote));
25126
+ if (real.length === 0 || secondAnswer) {
25106
25127
  const reuse = p.label === "Vulnerability" ? null : findReusableSolution(store, fixNote);
25107
25128
  if (reuse) {
25108
25129
  mergeEdge(store, problemId, reuse.id, "SOLVED_BY", t);
@@ -25112,7 +25133,9 @@ function closeDesignProblem(store, problemId, fixNote, t) {
25112
25133
  buildNode(store, solId, "Solution", fixNote.trim(), t, {
25113
25134
  source: "convo",
25114
25135
  provisional: false,
25115
- ...p.label === "Vulnerability" ? { privateFinding: problemId, sources: p.attrs["sources"] } : {}
25136
+ // Who stated the fix: a second answer is told from a re-witness by it,
25137
+ // and the self-corroboration belt reads it (sources[0] = the minting session).
25138
+ ...p.label === "Vulnerability" ? { privateFinding: problemId, sources: p.attrs["sources"] } : session ? { sources: [session] } : {}
25116
25139
  })
25117
25140
  );
25118
25141
  mergeEdge(store, problemId, solId, "SOLVED_BY", t);
@@ -25419,7 +25442,7 @@ function exposureOutcomeAttrs(node2, exposure, at) {
25419
25442
  lastOutcomeAt: typeof prev === "number" ? Math.max(prev, at.ts) : at.ts
25420
25443
  };
25421
25444
  }
25422
- var DESIGN_PROMOTE_AT, ANCHOR_LABELS, ANCHOR_KEYS, STATEMENT_ALIAS_CAP, RECURRENCE_DEBOUNCE_MS, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, EMPTY_FOLD_REPORT, SAME_ANCHOR_SCOUT_AUTO_COSINE, SAME_ANCHOR_SCOUT_MIN_COSINE, SAME_ANCHOR_NOMINATE_JACCARD, REOPEN_MIN_SOURCES, RECURRENCE_SOURCES_CAP, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, ENCLOSING_SYMBOL_KINDS, ENCLOSING_WALK_DEPTH, MEMBER_VISIBILITIES, FIX_CANDIDATE_ASK_LIMIT, RECENCY_BANDS, EXPOSURE_LOG_MAX, EXPOSURE_LOG_KEYS;
25445
+ var DESIGN_PROMOTE_AT, ANCHOR_LABELS, ANCHOR_KEYS, STATEMENT_ALIAS_CAP, RECURRENCE_DEBOUNCE_MS, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, EMPTY_FOLD_REPORT, SAME_ANCHOR_SCOUT_AUTO_COSINE, SAME_ANCHOR_SCOUT_MIN_COSINE, SAME_ANCHOR_NOMINATE_JACCARD, REOPEN_MIN_SOURCES, RECURRENCE_SOURCES_CAP, CITABLE_PRIOR_LABELS, SAME_FIX_JACCARD, MAX_ANCHOR_FILES, ENCLOSING_SYMBOL_KINDS, ENCLOSING_WALK_DEPTH, MEMBER_VISIBILITIES, FIX_CANDIDATE_ASK_LIMIT, RECENCY_BANDS, EXPOSURE_LOG_MAX, EXPOSURE_LOG_KEYS;
25423
25446
  var init_design_problem = __esm({
25424
25447
  "../../packages/local-graph/src/design-problem.ts"() {
25425
25448
  "use strict";
@@ -25485,6 +25508,7 @@ var init_design_problem = __esm({
25485
25508
  "Technique",
25486
25509
  "AntiPattern"
25487
25510
  ]);
25511
+ SAME_FIX_JACCARD = 0.5;
25488
25512
  MAX_ANCHOR_FILES = 5;
25489
25513
  ENCLOSING_SYMBOL_KINDS = /* @__PURE__ */ new Set([
25490
25514
  "Function",
@@ -25507,6 +25531,58 @@ var init_design_problem = __esm({
25507
25531
  }
25508
25532
  });
25509
25533
 
25534
+ // ../../packages/local-graph/src/lifecycle.ts
25535
+ function supersedersOf(store, id) {
25536
+ const out2 = [];
25537
+ for (const e of store.inEdges(id, ["SUPERSEDES"])) {
25538
+ if (e.from === id) continue;
25539
+ const s = store.getNode(e.from);
25540
+ if (!s || s.validTo != null || s.label !== "Solution" || netRefuted(s)) continue;
25541
+ out2.push(s.id);
25542
+ }
25543
+ return out2;
25544
+ }
25545
+ function lifecycleOf(store, node2) {
25546
+ const a = node2.attrs;
25547
+ const confirmations = count(a["confirmations"]);
25548
+ const refutations = refutesOf(a);
25549
+ const supersededBy = node2.label === "Solution" ? supersedersOf(store, node2.id) : [];
25550
+ const reasons = a["refuteReasons"];
25551
+ const base = { supersededBy, confirmations, refutations };
25552
+ if (supersededBy.length > 0) return { ...base, state: "superseded" };
25553
+ if (refutations > confirmations) return { ...base, state: "refuted", ...reasons?.[0] ? { refutedWhy: reasons[0] } : {} };
25554
+ if (a["resolutionSuspect"] === true && a["resolvedAt"] != null) return { ...base, state: "regression-suspect" };
25555
+ if (confirmations > 0 || a["fixHeldConfirmedAt"] != null && a["resolvedAt"] != null) return { ...base, state: "held" };
25556
+ if (a["resolvedAt"] != null && a["resolvedAs"] == null) return { ...base, state: "resolved" };
25557
+ return base;
25558
+ }
25559
+ function lifecycleNote(l, cite = (id) => id) {
25560
+ switch (l.state) {
25561
+ case "superseded":
25562
+ return `superseded by ${l.supersededBy.map(cite).join(", ")} \u2014 prefer that fix`;
25563
+ case "refuted":
25564
+ return `refuted ${l.refutations}\xD7${l.refutedWhy ? ` \u2014 ${l.refutedWhy}` : ""}`;
25565
+ case "regression-suspect":
25566
+ return "resolved, but the problem may have come back \u2014 check before relying on the fix";
25567
+ case "held":
25568
+ return l.confirmations > 0 ? `held \u2014 confirmed by ${l.confirmations} session${l.confirmations === 1 ? "" : "s"}` : "held \u2014 the fix was confirmed to still hold";
25569
+ default:
25570
+ return void 0;
25571
+ }
25572
+ }
25573
+ var count, refutesOf, netRefuted;
25574
+ var init_lifecycle = __esm({
25575
+ "../../packages/local-graph/src/lifecycle.ts"() {
25576
+ "use strict";
25577
+ count = (v) => {
25578
+ const n = Number(v);
25579
+ return Number.isFinite(n) && n > 0 ? n : 0;
25580
+ };
25581
+ refutesOf = (a) => Math.max(count(a["refutations"]), a["refutedAt"] != null ? 1 : 0);
25582
+ netRefuted = (n) => refutesOf(n.attrs) > count(n.attrs["confirmations"]);
25583
+ }
25584
+ });
25585
+
25510
25586
  // ../../packages/local-graph/src/intent.ts
25511
25587
  function parseIntentFences(text) {
25512
25588
  const out2 = [];
@@ -27494,24 +27570,24 @@ function evaluateFed(store, d, stamps) {
27494
27570
  if (d.fedIncoming && incomingRows) {
27495
27571
  const targets = new Set(store.liveEdgeTargets(d.fedIncoming.edgeTypes));
27496
27572
  const rows = d.fedIncoming.cloudOnly ? incomingRows.filter((r) => r.cloud) : incomingRows;
27497
- const count2 = rows.filter((r) => targets.has(r.id)).length;
27498
- return { count: count2, total: rows.length, fraction: rows.length === 0 ? 0 : count2 / rows.length };
27573
+ const count3 = rows.filter((r) => targets.has(r.id)).length;
27574
+ return { count: count3, total: rows.length, fraction: rows.length === 0 ? 0 : count3 / rows.length };
27499
27575
  }
27500
27576
  if (d.fedIncoming) {
27501
- const { count: count2, total } = store.incomingEdgeCoverage?.(
27577
+ const { count: count3, total } = store.incomingEdgeCoverage?.(
27502
27578
  d.fedIncoming.label,
27503
27579
  d.fedIncoming.edgeTypes,
27504
27580
  d.fedIncoming.cloudOnly
27505
27581
  ) ?? { count: 0, total: 0 };
27506
- return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
27582
+ return { count: count3, total, fraction: total === 0 ? 0 : count3 / total };
27507
27583
  }
27508
27584
  if (d.fedEdges) {
27509
- const { count: count2, total } = store.recentEdgeAttrCoverage(
27585
+ const { count: count3, total } = store.recentEdgeAttrCoverage(
27510
27586
  d.fedEdges.marker,
27511
27587
  d.fedEdges.attr,
27512
27588
  d.fedEdges.recent
27513
27589
  );
27514
- return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
27590
+ return { count: count3, total, fraction: total === 0 ? 0 : count3 / total };
27515
27591
  }
27516
27592
  if (!d.fed) return { count: 0, total: 0, fraction: 0 };
27517
27593
  const column2 = COLUMN_INPUTS[d.fed.attr];
@@ -27529,13 +27605,13 @@ function evaluateFed(store, d, stamps) {
27529
27605
  for (const n of window2) if (has(n) && n.createdAt < anchor) anchor = n.createdAt;
27530
27606
  window2 = anchor === Infinity ? [] : window2.filter((n) => n.createdAt >= anchor);
27531
27607
  }
27532
- let count = 0;
27533
- for (const n of window2) if (has(n)) count++;
27534
- return { count, total: window2.length, fraction: window2.length === 0 ? 0 : count / window2.length };
27608
+ let count2 = 0;
27609
+ for (const n of window2) if (has(n)) count2++;
27610
+ return { count: count2, total: window2.length, fraction: window2.length === 0 ? 0 : count2 / window2.length };
27535
27611
  }
27536
27612
  function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mechanisms = MECHANISMS) {
27537
27613
  const counts = /* @__PURE__ */ new Map();
27538
- const count = (label) => {
27614
+ const count2 = (label) => {
27539
27615
  if (!counts.has(label)) counts.set(label, store.countNodesByLabel(label));
27540
27616
  return counts.get(label);
27541
27617
  };
@@ -27559,8 +27635,8 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
27559
27635
  const span = inv?.firstTs === void 0 ? 0 : inv.lastTs - inv.firstTs;
27560
27636
  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);
27561
27637
  let verdict;
27562
- const hasInput = fed.total > 0 || Boolean(d.fed?.sinceFirstStamp && d.fed.labels.some((label) => count(label) > 0));
27563
- const missingRequiredNodes = d.requiresNodes?.some((label) => count(label) === 0) ?? false;
27638
+ const hasInput = fed.total > 0 || Boolean(d.fed?.sinceFirstStamp && d.fed.labels.some((label) => count2(label) > 0));
27639
+ const missingRequiredNodes = d.requiresNodes?.some((label) => count2(label) === 0) ?? false;
27564
27640
  if (d.configCounter && inv?.lastTotals?.[d.configCounter] === 0) verdict = "unconfigured";
27565
27641
  else if ((backlog ?? 0) === 0 && (!hasInput && !d.inputOptional || missingRequiredNodes)) verdict = "no-input";
27566
27642
  else if (!inv || inv.runs === 0) verdict = "never-invoked";
@@ -27647,6 +27723,21 @@ var init_mechanism_liveness = __esm({
27647
27723
  effectCounter: "confirmsStamped",
27648
27724
  note: "consumed by one-search rankKnowledge; transport to cloud corroborationCount unchanged"
27649
27725
  },
27726
+ {
27727
+ id: "supersession-ask",
27728
+ what: "asks how a just-recorded fix relates to earlier fixes for the same symptom; the agent's answer mints SUPERSEDES/BUILDS_ON/ALTERNATIVE_TO",
27729
+ pass: "capture",
27730
+ // Conditional and rare (a fix landing beside earlier ones) — written-at-all
27731
+ // bar. The consumer is supersededBy in rankKnowledge (local lifecycle.ts,
27732
+ // cloud entry-rank.ts) and the superseded/held notes agents read.
27733
+ fed: {
27734
+ labels: ["Solution"],
27735
+ attr: "supersessionAskedAt",
27736
+ minFraction: 0
27737
+ },
27738
+ effectCounter: "structureLinksMinted",
27739
+ note: "the answer is the agent's; nothing is inferred"
27740
+ },
27650
27741
  {
27651
27742
  id: "regression-recognize",
27652
27743
  what: "marks a resolved problem as resolutionSuspect when it recurs at the door",
@@ -28080,6 +28171,8 @@ __export(src_exports2, {
28080
28171
  isUnfilledPlaceholder: () => isUnfilledPlaceholder,
28081
28172
  isVerdictable: () => isVerdictable,
28082
28173
  learnedConductance: () => learnedConductance,
28174
+ lifecycleNote: () => lifecycleNote,
28175
+ lifecycleOf: () => lifecycleOf,
28083
28176
  linkProblemToLanguages: () => linkProblemToLanguages,
28084
28177
  linkProblemToPackages: () => linkProblemToPackages,
28085
28178
  linkProblemToSymbols: () => linkProblemToSymbols,
@@ -28142,12 +28235,14 @@ __export(src_exports2, {
28142
28235
  retractDesignProblemByStatement: () => retractDesignProblemByStatement,
28143
28236
  revisitContradictedPrinciples: () => revisitContradictedPrinciples,
28144
28237
  revisitStaleRoutes: () => revisitStaleRoutes,
28238
+ sameFixStatement: () => sameFixStatement,
28145
28239
  searchByIntent: () => searchByIntent,
28146
28240
  solutionForProblem: () => solutionForProblem,
28147
28241
  splittingAxis: () => splittingAxis,
28148
28242
  stampObservedOs: () => stampObservedOs,
28149
28243
  statementIdentityKey: () => statementIdentityKey,
28150
28244
  staticConductance: () => staticConductance,
28245
+ supersedersOf: () => supersedersOf,
28151
28246
  symbolCandidatesInText: () => symbolCandidatesInText,
28152
28247
  symbolIndexForText: () => symbolIndexForText,
28153
28248
  toolNodeId: () => toolNodeId,
@@ -28173,6 +28268,7 @@ var init_src5 = __esm({
28173
28268
  init_crystallize();
28174
28269
  init_aggregate();
28175
28270
  init_design_problem();
28271
+ init_lifecycle();
28176
28272
  init_intent();
28177
28273
  init_anchor_backfill();
28178
28274
  init_percolate();
@@ -28620,6 +28716,22 @@ function renderSnapshot(s) {
28620
28716
  );
28621
28717
  lines.push("");
28622
28718
  }
28719
+ if (s.supersessionAsks?.length) {
28720
+ lines.push("### \u2696\uFE0F Your fix vs earlier ones");
28721
+ lines.push(
28722
+ "_You just recorded a fix where earlier fixes for the same symptom exist. Say how they relate \u2014 otherwise the next agent is shown them as equally current answers and has to re-prove which one held:_"
28723
+ );
28724
+ for (const a of s.supersessionAsks) {
28725
+ lines.push(`- your fix: **${a.fix.description}** \u2014 \`${a.fix.id}\``);
28726
+ for (const p of a.priors) {
28727
+ lines.push(` - earlier: **${p.description}** \u2014 \`${p.id}\`${p.lifecycle ? ` _(${p.lifecycle})_` : ""}`);
28728
+ lines.push(
28729
+ ` - yours replaces it \u2192 (supersedes:[${p.id}]) \xB7 extends it \u2192 (builds-on:[${p.id}]) \xB7 both valid \u2192 (alternative:[${p.id}]) \xB7 it held too \u2192 ${TAG_VERDICT_TOKENS.confirm(p.id)} \xB7 it didn't \u2192 ${TAG_VERDICT_TOKENS.refute(p.id)}`
28730
+ );
28731
+ }
28732
+ }
28733
+ lines.push("");
28734
+ }
28623
28735
  lines.push("### Recently observed problems in this workspace");
28624
28736
  if (s.recentProblems.length === 0 && s.recentResolved.length === 0 && s.recentConstraints.length === 0 && s.regressions.length === 0) {
28625
28737
  lines.push("- _none yet \u2014 errata is still building its model_");
@@ -28742,7 +28854,7 @@ function renderSnapshot(s) {
28742
28854
  lines.push("");
28743
28855
  lines.push("_Priors that speak to it \u2014 cite one with its `[handle]` if you lean on it:_");
28744
28856
  for (const h of si.hits) {
28745
- lines.push(`- **${h.description}** \u2014 \`${h.id}\``);
28857
+ lines.push(`- **${h.description}** \u2014 \`${h.id}\`${h.lifecycle ? ` _(${h.lifecycle})_` : ""}`);
28746
28858
  if (h.verdict === "own") {
28747
28859
  lines.push(
28748
28860
  ` - still open \u2014 did this work settle it? fixed \u2192 (fix:[${h.id}]) \xB7 not a real problem \u2192 an \`errata-resolved\` block with \`id: ` + h.id + "`, `disposition: false_positive`, `reason: \u2026` \xB7 still open \u2192 say nothing"
@@ -28922,6 +29034,7 @@ function isolateSnapshot(s) {
28922
29034
  workingFile: _workingFile,
28923
29035
  statedIntent: _statedIntent,
28924
29036
  selfCiteSkips: _selfCiteSkips,
29037
+ supersessionAsks: _supersessionAsks,
28925
29038
  pendingUpdate: _pendingUpdate,
28926
29039
  daemonDistress: _daemonDistress,
28927
29040
  reviewItems: _reviewItems,
@@ -29479,14 +29592,14 @@ function sidecarForNodes(sidecar, nodes) {
29479
29592
  const present = /* @__PURE__ */ new Set();
29480
29593
  for (const n of nodes) for (const tok of extractIdentifierTokens(n.description)) present.add(tok);
29481
29594
  const filtered = {};
29482
- let count = 0;
29595
+ let count2 = 0;
29483
29596
  for (const [symbol2, entry] of Object.entries(sidecar)) {
29484
29597
  if (present.has(symbol2)) {
29485
29598
  filtered[symbol2] = entry;
29486
- count++;
29599
+ count2++;
29487
29600
  }
29488
29601
  }
29489
- return count > 0 ? filtered : void 0;
29602
+ return count2 > 0 ? filtered : void 0;
29490
29603
  }
29491
29604
  function wireVia(value) {
29492
29605
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -36301,9 +36414,9 @@ function contextCard(store, snapshot) {
36301
36414
  for (const r of snapshot.recentProblems) add(r.node);
36302
36415
  for (const n of snapshot.remote ?? []) add(n);
36303
36416
  for (const m of snapshot.motifs) add(m);
36304
- const count = plural(delivered.length, "prior");
36417
+ const count2 = plural(delivered.length, "prior");
36305
36418
  const intent = snapshot.statedIntent?.text;
36306
- return deliveredCard(store, intent ? `${count} for \u201C${clipIntent(intent)}\u201D` : `${count} in context`, delivered);
36419
+ return deliveredCard(store, intent ? `${count2} for \u201C${clipIntent(intent)}\u201D` : `${count2} in context`, delivered);
36307
36420
  }
36308
36421
  function writeContextCard(root, hash2, card) {
36309
36422
  writeFileSync6(join8(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({
@@ -36326,7 +36439,7 @@ function openProblemCount(store, now = Date.now()) {
36326
36439
  const hit = openProblemsCache.get(store);
36327
36440
  const seq = store.changeSeq?.(OPEN_PROBLEM_SCOPES);
36328
36441
  if (hit && (seq !== void 0 ? hit.seq === seq : now - hit.at < OPEN_PROBLEMS_TTL_MS)) return hit.count;
36329
- let count = 0;
36442
+ let count2 = 0;
36330
36443
  const labels = ["Problem", "Vulnerability"];
36331
36444
  const plain = store.selectNodes({
36332
36445
  labels,
@@ -36348,10 +36461,10 @@ function openProblemCount(store, now = Date.now()) {
36348
36461
  return { ...row, attrs };
36349
36462
  });
36350
36463
  for (const p of [...plain, ...qualified]) {
36351
- if (live(p) && !p.attrs["resolvedAt"] && !isConstraintProblem(p)) count++;
36464
+ if (live(p) && !p.attrs["resolvedAt"] && !isConstraintProblem(p)) count2++;
36352
36465
  }
36353
- openProblemsCache.set(store, { at: now, count, ...seq !== void 0 ? { seq } : {} });
36354
- return count;
36466
+ openProblemsCache.set(store, { at: now, count: count2, ...seq !== void 0 ? { seq } : {} });
36467
+ return count2;
36355
36468
  }
36356
36469
  var CONTEXT_CARD_FILE, OPEN_PROBLEMS_TTL_MS, openProblemsCache, OPEN_PROBLEM_SCOPES, OPEN_PROBLEM_ATTRS, HISTORY_QUALITY_READ_KEYS;
36357
36470
  var init_recall_signal = __esm({
@@ -38539,7 +38652,7 @@ function cloudEvidence(raw2) {
38539
38652
  if (!raw2 || typeof raw2 !== "object") return void 0;
38540
38653
  const r = raw2;
38541
38654
  const out2 = {};
38542
- for (const k of ["acceptedCount", "corroborationCount", "failureReportCount", "contradictionPressure", "reinforcementCount"]) {
38655
+ for (const k of ["acceptedCount", "corroborationCount", "failureReportCount", "contradictionPressure", "reinforcementCount", "supersededBy"]) {
38543
38656
  const v = r[k];
38544
38657
  if (typeof v === "number" && Number.isFinite(v) && v > 0) out2[k] = v;
38545
38658
  }
@@ -38984,10 +39097,15 @@ async function rankHits(store, query, hits, opts = {}) {
38984
39097
  const qv = vectors[0];
38985
39098
  const weights = floor != null ? { semanticFloor: floor } : void 0;
38986
39099
  const inputs = hits.map((h, i2) => {
38987
- const local = store?.getNode(h.id)?.attrs;
39100
+ const node2 = store?.getNode(h.id);
39101
+ const local = node2?.attrs;
38988
39102
  const cloud = [h.id, ...h.twins ?? []].map((id) => opts.cloudEvidence?.get(id)).reduce((acc, e) => poolEvidence(acc, e), void 0);
38989
39103
  const cv = vectors[i2 + 1];
38990
- const evidence = poolEvidence(localEvidence(local), cloud);
39104
+ const superseded = store && node2?.label === "Solution" ? supersedersOf(store, h.id).length : 0;
39105
+ const evidence = poolEvidence(
39106
+ poolEvidence(localEvidence(local), superseded > 0 ? { supersededBy: superseded } : void 0),
39107
+ cloud
39108
+ );
38991
39109
  return {
38992
39110
  ...qv && cv ? { semantic: cosine(qv.vector, cv.vector) } : {},
38993
39111
  lexical: termCoverage(terms, texts[i2], weightOf),
@@ -39051,6 +39169,7 @@ var init_one_search = __esm({
39051
39169
  "use strict";
39052
39170
  init_src4();
39053
39171
  init_src3();
39172
+ init_src5();
39054
39173
  REFUTE_PRESSURE = 0.6;
39055
39174
  INHERIT_DEPTH = 3;
39056
39175
  defaultEmbed = async (texts) => texts.map((t) => ({ vector: embed(t), version: EMBEDDING_VERSION }));
@@ -41458,9 +41577,9 @@ async function Module2(moduleArg = {}) {
41458
41577
  }
41459
41578
  __name(getString, "getString");
41460
41579
  function getStringList() {
41461
- var count2 = getLEB();
41580
+ var count22 = getLEB();
41462
41581
  var rtn = [];
41463
- while (count2--) rtn.push(getString());
41582
+ while (count22--) rtn.push(getString());
41464
41583
  return rtn;
41465
41584
  }
41466
41585
  __name(getStringList, "getStringList");
@@ -41509,8 +41628,8 @@ async function Module2(moduleArg = {}) {
41509
41628
  } else if (subsectionType === WASM_DYLINK_NEEDED) {
41510
41629
  customSection.neededDynlibs = getStringList();
41511
41630
  } else if (subsectionType === WASM_DYLINK_EXPORT_INFO) {
41512
- var count = getLEB();
41513
- while (count--) {
41631
+ var count2 = getLEB();
41632
+ while (count2--) {
41514
41633
  var symname = getString();
41515
41634
  var flags2 = getLEB();
41516
41635
  if (flags2 & WASM_SYMBOL_TLS) {
@@ -41518,8 +41637,8 @@ async function Module2(moduleArg = {}) {
41518
41637
  }
41519
41638
  }
41520
41639
  } else if (subsectionType === WASM_DYLINK_IMPORT_INFO) {
41521
- var count = getLEB();
41522
- while (count--) {
41640
+ var count2 = getLEB();
41641
+ while (count2--) {
41523
41642
  var modname = getString();
41524
41643
  var symname = getString();
41525
41644
  var flags2 = getLEB();
@@ -41678,9 +41797,9 @@ async function Module2(moduleArg = {}) {
41678
41797
  }
41679
41798
  return func2;
41680
41799
  }, "getWasmTableEntry");
41681
- var updateTableMap = /* @__PURE__ */ __name((offset, count) => {
41800
+ var updateTableMap = /* @__PURE__ */ __name((offset, count2) => {
41682
41801
  if (functionsInTableMap) {
41683
- for (var i2 = offset; i2 < offset + count; i2++) {
41802
+ for (var i2 = offset; i2 < offset + count2; i2++) {
41684
41803
  var item2 = getWasmTableEntry(i2);
41685
41804
  if (item2) {
41686
41805
  functionsInTableMap.set(item2, i2);
@@ -43107,12 +43226,12 @@ var init_web_tree_sitter = __esm({
43107
43226
  throw new TypeError("Argument must be a Tree");
43108
43227
  }
43109
43228
  C._ts_tree_get_changed_ranges_wasm(this[0], other[0]);
43110
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43229
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43111
43230
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43112
- const result = new Array(count);
43113
- if (count > 0) {
43231
+ const result = new Array(count2);
43232
+ if (count2 > 0) {
43114
43233
  let address = buffer;
43115
- for (let i2 = 0; i2 < count; i2++) {
43234
+ for (let i2 = 0; i2 < count2; i2++) {
43116
43235
  result[i2] = unmarshalRange(address);
43117
43236
  address += SIZE_OF_RANGE;
43118
43237
  }
@@ -43123,12 +43242,12 @@ var init_web_tree_sitter = __esm({
43123
43242
  /** Get the included ranges that were used to parse the syntax tree. */
43124
43243
  getIncludedRanges() {
43125
43244
  C._ts_tree_included_ranges_wasm(this[0]);
43126
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43245
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43127
43246
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43128
- const result = new Array(count);
43129
- if (count > 0) {
43247
+ const result = new Array(count2);
43248
+ if (count2 > 0) {
43130
43249
  let address = buffer;
43131
- for (let i2 = 0; i2 < count; i2++) {
43250
+ for (let i2 = 0; i2 < count2; i2++) {
43132
43251
  result[i2] = unmarshalRange(address);
43133
43252
  address += SIZE_OF_RANGE;
43134
43253
  }
@@ -43653,12 +43772,12 @@ var init_web_tree_sitter = __esm({
43653
43772
  childrenForFieldId(fieldId) {
43654
43773
  marshalNode(this);
43655
43774
  C._ts_node_children_by_field_id_wasm(this.tree[0], fieldId);
43656
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43775
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43657
43776
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43658
- const result = new Array(count);
43659
- if (count > 0) {
43777
+ const result = new Array(count2);
43778
+ if (count2 > 0) {
43660
43779
  let address = buffer;
43661
- for (let i2 = 0; i2 < count; i2++) {
43780
+ for (let i2 = 0; i2 < count2; i2++) {
43662
43781
  result[i2] = unmarshalNode(this.tree, address);
43663
43782
  address += SIZE_OF_NODE;
43664
43783
  }
@@ -43730,12 +43849,12 @@ var init_web_tree_sitter = __esm({
43730
43849
  if (!this._children) {
43731
43850
  marshalNode(this);
43732
43851
  C._ts_node_children_wasm(this.tree[0]);
43733
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43852
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43734
43853
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43735
- this._children = new Array(count);
43736
- if (count > 0) {
43854
+ this._children = new Array(count2);
43855
+ if (count2 > 0) {
43737
43856
  let address = buffer;
43738
- for (let i2 = 0; i2 < count; i2++) {
43857
+ for (let i2 = 0; i2 < count2; i2++) {
43739
43858
  this._children[i2] = unmarshalNode(this.tree, address);
43740
43859
  address += SIZE_OF_NODE;
43741
43860
  }
@@ -43753,12 +43872,12 @@ var init_web_tree_sitter = __esm({
43753
43872
  if (!this._namedChildren) {
43754
43873
  marshalNode(this);
43755
43874
  C._ts_node_named_children_wasm(this.tree[0]);
43756
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43875
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43757
43876
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43758
- this._namedChildren = new Array(count);
43759
- if (count > 0) {
43877
+ this._namedChildren = new Array(count2);
43878
+ if (count2 > 0) {
43760
43879
  let address = buffer;
43761
- for (let i2 = 0; i2 < count; i2++) {
43880
+ for (let i2 = 0; i2 < count2; i2++) {
43762
43881
  this._namedChildren[i2] = unmarshalNode(this.tree, address);
43763
43882
  address += SIZE_OF_NODE;
43764
43883
  }
@@ -44121,12 +44240,12 @@ var init_web_tree_sitter = __esm({
44121
44240
  */
44122
44241
  get supertypes() {
44123
44242
  C._ts_language_supertypes_wasm(this[0]);
44124
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44243
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
44125
44244
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
44126
- const result = new Array(count);
44127
- if (count > 0) {
44245
+ const result = new Array(count2);
44246
+ if (count2 > 0) {
44128
44247
  let address = buffer;
44129
- for (let i2 = 0; i2 < count; i2++) {
44248
+ for (let i2 = 0; i2 < count2; i2++) {
44130
44249
  result[i2] = C.getValue(address, "i16");
44131
44250
  address += SIZE_OF_SHORT;
44132
44251
  }
@@ -44138,12 +44257,12 @@ var init_web_tree_sitter = __esm({
44138
44257
  */
44139
44258
  subtypes(supertype) {
44140
44259
  C._ts_language_subtypes_wasm(this[0], supertype);
44141
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44260
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
44142
44261
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
44143
- const result = new Array(count);
44144
- if (count > 0) {
44262
+ const result = new Array(count2);
44263
+ if (count2 > 0) {
44145
44264
  let address = buffer;
44146
- for (let i2 = 0; i2 < count; i2++) {
44265
+ for (let i2 = 0; i2 < count2; i2++) {
44147
44266
  result[i2] = C.getValue(address, "i16");
44148
44267
  address += SIZE_OF_SHORT;
44149
44268
  }
@@ -44382,12 +44501,12 @@ ${JSON.stringify(symbolNames, null, 2)}`);
44382
44501
  /** Get the ranges of text that the parser will include when parsing. */
44383
44502
  getIncludedRanges() {
44384
44503
  C._ts_parser_included_ranges_wasm(this[0]);
44385
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44504
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
44386
44505
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
44387
- const result = new Array(count);
44388
- if (count > 0) {
44506
+ const result = new Array(count2);
44507
+ if (count2 > 0) {
44389
44508
  let address = buffer;
44390
- for (let i2 = 0; i2 < count; i2++) {
44509
+ for (let i2 = 0; i2 < count2; i2++) {
44391
44510
  result[i2] = unmarshalRange(address);
44392
44511
  address += SIZE_OF_RANGE;
44393
44512
  }
@@ -44777,14 +44896,14 @@ ${JSON.stringify(symbolNames, null, 2)}`);
44777
44896
  matchLimit,
44778
44897
  maxStartDepth
44779
44898
  );
44780
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44899
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
44781
44900
  const startAddress = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
44782
44901
  const didExceedMatchLimit = C.getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, "i32");
44783
44902
  const result = new Array();
44784
44903
  this.exceededMatchLimit = Boolean(didExceedMatchLimit);
44785
44904
  const captures = new Array();
44786
44905
  let address = startAddress;
44787
- for (let i2 = 0; i2 < count; i2++) {
44906
+ for (let i2 = 0; i2 < count2; i2++) {
44788
44907
  const patternIndex = C.getValue(address, "i32");
44789
44908
  address += SIZE_OF_INT;
44790
44909
  const captureCount = C.getValue(address, "i32");
@@ -48023,9 +48142,9 @@ function standingStrandedCount(store) {
48023
48142
  const byFile = { ...last.byFile };
48024
48143
  for (const f of changed) delete byFile[f];
48025
48144
  for (const s of store.strandedSymbolsForFiles(changed)) byFile[s.fileId] = (byFile[s.fileId] ?? 0) + 1;
48026
- const count = Object.values(byFile).reduce((a, b) => a + b, 0);
48027
- store.setMeta?.(STRANDED_KEY, JSON.stringify({ seq, count, byFile }));
48028
- return count;
48145
+ const count2 = Object.values(byFile).reduce((a, b) => a + b, 0);
48146
+ store.setMeta?.(STRANDED_KEY, JSON.stringify({ seq, count: count2, byFile }));
48147
+ return count2;
48029
48148
  } catch {
48030
48149
  return null;
48031
48150
  }
@@ -48254,20 +48373,14 @@ function takeDiscriminatorNudge(path3) {
48254
48373
  shared.close();
48255
48374
  }
48256
48375
  }
48257
- function hitState(n) {
48258
- const reasons = n.attrs["refuteReasons"];
48259
- if (n.attrs["resolutionSuspect"] === true && n.attrs["resolvedAt"] != null) {
48260
- return { state: "regression-suspect", factor: RG_SUSPECT_BOOST };
48261
- }
48262
- if (n.attrs["refutedAt"] != null) {
48263
- return { state: "refuted", ...reasons?.[0] ? { refutedWhy: reasons[0] } : {}, factor: RG_REFUTED_DAMP };
48264
- }
48265
- if (n.attrs["reopenedFrom"] === "regression") {
48266
- return { state: "reopened-regression", factor: RG_SUSPECT_BOOST };
48267
- }
48268
- if (n.attrs["resolvedAt"] != null && n.attrs["resolvedAs"] == null) {
48269
- return { state: "resolved", factor: 1 };
48270
- }
48376
+ function hitState(store, n) {
48377
+ const l = lifecycleOf(store, n);
48378
+ if (l.state === "superseded") return { state: "superseded", supersededBy: l.supersededBy, factor: supersessionFactor(l.supersededBy.length) };
48379
+ if (l.state === "refuted") return { state: "refuted", ...l.refutedWhy ? { refutedWhy: l.refutedWhy } : {}, factor: RG_REFUTED_DAMP };
48380
+ if (l.state === "regression-suspect") return { state: "regression-suspect", factor: RG_SUSPECT_BOOST };
48381
+ if (n.attrs["reopenedFrom"] === "regression") return { state: "reopened-regression", factor: RG_SUSPECT_BOOST };
48382
+ if (l.state === "held") return { state: "held", factor: 1 };
48383
+ if (l.state === "resolved") return { state: "resolved", factor: 1 };
48271
48384
  return { factor: 1 };
48272
48385
  }
48273
48386
  function commentAnchorId(store, commentId) {
@@ -48310,7 +48423,8 @@ function toSearchHit(node2, via, rg) {
48310
48423
  pageRank: node2.pageRank,
48311
48424
  ...via ? { via } : {},
48312
48425
  ...rg.state ? { state: rg.state } : {},
48313
- ...rg.refutedWhy ? { refutedWhy: rg.refutedWhy } : {}
48426
+ ...rg.refutedWhy ? { refutedWhy: rg.refutedWhy } : {},
48427
+ ...rg.supersededBy?.length ? { supersededBy: rg.supersededBy } : {}
48314
48428
  };
48315
48429
  }
48316
48430
  function textMatches(store, query) {
@@ -48372,7 +48486,7 @@ function textMatches(store, query) {
48372
48486
  }
48373
48487
  add(node2, matched, coverageOf(node2.id));
48374
48488
  }
48375
- return [...merged.values()].map((e) => ({ ...e, rg: hitState(e.node) })).sort(
48489
+ return [...merged.values()].map((e) => ({ ...e, rg: hitState(store, e.node) })).sort(
48376
48490
  (a, b) => rankTier(a.node) - rankTier(b.node) || b.matched - a.matched || b.node.pageRank * b.rg.factor - a.node.pageRank * a.rg.factor
48377
48491
  ).map(({ node: node2, via, rg, coverage, matched }) => ({ node: node2, via, rg, coverage, matched }));
48378
48492
  }
@@ -48451,7 +48565,7 @@ function searchGraphWalk(store, query, limit) {
48451
48565
  return ranked.map((r) => {
48452
48566
  const m = byId.get(r.id);
48453
48567
  if (m) return { ...toSearchHit(m.node, m.via, m.rg), score: r.score, matched: true };
48454
- const rg = hitState(r.node);
48568
+ const rg = hitState(store, r.node);
48455
48569
  return {
48456
48570
  ...toSearchHit(r.node, void 0, rg),
48457
48571
  score: r.score,
@@ -48818,6 +48932,7 @@ var init_mcp = __esm({
48818
48932
  init_dual_burst();
48819
48933
  init_twin_index();
48820
48934
  init_src5();
48935
+ init_src3();
48821
48936
  init_src2();
48822
48937
  init_src8();
48823
48938
  init_dual_burst();
@@ -49552,22 +49667,22 @@ var init_mcp = __esm({
49552
49667
  const orderCol = byRank ? "page_rank" : "created_at";
49553
49668
  const sqlSince = since && Number.isFinite(since);
49554
49669
  let nodes;
49555
- let count;
49670
+ let count2;
49556
49671
  if (!like && (!since || sqlSince)) {
49557
49672
  const where = sqlSince ? [{ column: "created_at", gte: since }] : [];
49558
49673
  const q = { labels: [label], where };
49559
- count = store.countNodes(q);
49674
+ count2 = store.countNodes(q);
49560
49675
  nodes = store.selectNodes({ ...q, orderBy: { column: orderCol, desc: true }, limit: sliceEnd(limit) });
49561
49676
  } else {
49562
49677
  nodes = store.selectNodes({ labels: [label] });
49563
49678
  if (like) nodes = nodes.filter((n) => n.description.toLowerCase().includes(like));
49564
49679
  if (since) nodes = nodes.filter((n) => n.createdAt >= since);
49565
49680
  nodes.sort((a, b) => byRank ? b.pageRank - a.pageRank : b.createdAt - a.createdAt);
49566
- count = nodes.length;
49681
+ count2 = nodes.length;
49567
49682
  }
49568
49683
  return {
49569
49684
  label,
49570
- count,
49685
+ count: count2,
49571
49686
  items: nodes.slice(0, limit).map((n) => ({
49572
49687
  id: n.id,
49573
49688
  label: n.label,
@@ -49670,11 +49785,11 @@ var init_mcp = __esm({
49670
49785
  for (const label of labels) {
49671
49786
  const col = isCodeLabel(label) ? "last_updated_at" : "created_at";
49672
49787
  const q = { labels: [label], where: [{ column: col, gte: since }] };
49673
- const count = store.countNodes(q);
49674
- if (count === 0) continue;
49675
- total += count;
49788
+ const count2 = store.countNodes(q);
49789
+ if (count2 === 0) continue;
49790
+ total += count2;
49676
49791
  groups[label] = {
49677
- count,
49792
+ count: count2,
49678
49793
  items: store.selectNodes({
49679
49794
  ...q,
49680
49795
  orderBy: { column: col, desc: true },
@@ -58065,7 +58180,8 @@ __export(webui_exports, {
58065
58180
  findFileByPath: () => findFileByPath,
58066
58181
  hookAudience: () => hookAudience,
58067
58182
  recallForFile: () => recallForFile,
58068
- recallForTool: () => recallForTool
58183
+ recallForTool: () => recallForTool,
58184
+ shownFixes: () => shownFixes
58069
58185
  });
58070
58186
  function accumulateMessageDelta(messageId, index, delta, isFinal, nowMs) {
58071
58187
  return messageAccumulator.accumulate(messageId, index, delta, isFinal, nowMs);
@@ -58530,6 +58646,13 @@ function buildWebUi(deps) {
58530
58646
  }
58531
58647
  if (failed) recall = recallForError(deps.store, stderr || combined);
58532
58648
  }
58649
+ if (event === "PostToolUse" && tool.startsWith("mcp__errata__") && deps.onKnowledgeShown) {
58650
+ try {
58651
+ const shown = shownFixes(input, body2["tool_response"]);
58652
+ if (shown) deps.onKnowledgeShown(String(body2["session_id"] ?? ""), shown);
58653
+ } catch {
58654
+ }
58655
+ }
58533
58656
  if (event === "PostToolUse" && tool && tool !== "Bash" && deps.onToolError) {
58534
58657
  const rawResp = body2["tool_response"];
58535
58658
  const respObj = rawResp && typeof rawResp === "object" ? rawResp : {};
@@ -58975,6 +59098,41 @@ function proposalToIngest(p, profile, daemonVersion) {
58975
59098
  payloadDigest: p.id
58976
59099
  };
58977
59100
  }
59101
+ function shownFixes(input, response) {
59102
+ const query = typeof input["query"] === "string" ? input["query"].trim() : "";
59103
+ if (!query) return null;
59104
+ const texts = [];
59105
+ if (typeof response === "string") texts.push(response);
59106
+ else if (Array.isArray(response)) for (const c of response) {
59107
+ const t = c?.text;
59108
+ if (typeof t === "string") texts.push(t);
59109
+ }
59110
+ else if (response && typeof response === "object") {
59111
+ const content = response.content;
59112
+ if (Array.isArray(content)) for (const c of content) {
59113
+ const t = c?.text;
59114
+ if (typeof t === "string") texts.push(t);
59115
+ }
59116
+ }
59117
+ const fixIds = [];
59118
+ const walk11 = (v, depth) => {
59119
+ if (depth > 6 || !v || typeof v !== "object") return;
59120
+ if (Array.isArray(v)) {
59121
+ for (const x of v) walk11(x, depth + 1);
59122
+ return;
59123
+ }
59124
+ const o = v;
59125
+ if (o["label"] === "Solution" && typeof o["id"] === "string" && !fixIds.includes(o["id"])) fixIds.push(o["id"]);
59126
+ for (const x of Object.values(o)) walk11(x, depth + 1);
59127
+ };
59128
+ for (const t of texts) {
59129
+ try {
59130
+ walk11(JSON.parse(t), 0);
59131
+ } catch {
59132
+ }
59133
+ }
59134
+ return fixIds.length > 0 ? { query, fixIds } : null;
59135
+ }
58978
59136
  var messageAccumulator, GENERIC_ERROR_WORDS, wsPackagesCache, WS_PACKAGES_TTL_MS, loggedToolSessions, SUBAGENT_REFRESH_MIN_MS, WINDOW_RESET_SOURCES, FULL_BLOCK_PREFIX, FOCUS_NOTICE_FIELD, META_LABELS;
58979
59137
  var init_webui = __esm({
58980
59138
  "src/webui.ts"() {
@@ -70196,11 +70354,11 @@ var require_pluralizer = __commonJS({
70196
70354
  this.singular = singular;
70197
70355
  this.plural = plural2;
70198
70356
  }
70199
- pluralize(count) {
70200
- const one = count === 1;
70357
+ pluralize(count2) {
70358
+ const one = count2 === 1;
70201
70359
  const keys = one ? singulars : plurals;
70202
70360
  const noun = one ? this.singular : this.plural;
70203
- return { ...keys, count, noun };
70361
+ return { ...keys, count: count2, noun };
70204
70362
  }
70205
70363
  };
70206
70364
  }
@@ -80517,12 +80675,12 @@ var FSWatcher = class extends EventEmitter {
80517
80675
  let timeoutObject;
80518
80676
  const clear = () => {
80519
80677
  const item2 = action.get(path3);
80520
- const count = item2 ? item2.count : 0;
80678
+ const count2 = item2 ? item2.count : 0;
80521
80679
  action.delete(path3);
80522
80680
  clearTimeout(timeoutObject);
80523
80681
  if (item2)
80524
80682
  clearTimeout(item2.timeoutObject);
80525
- return count;
80683
+ return count2;
80526
80684
  };
80527
80685
  timeoutObject = setTimeout(clear, timeout);
80528
80686
  const thr = { timeoutObject, clear, count: 0 };
@@ -83331,6 +83489,112 @@ function stampWitnessOrigin(items, origin) {
83331
83489
  return items.map((i2) => ({ ...i2, witnessKey: `${i2.witnessKey}:o:${o}` }));
83332
83490
  }
83333
83491
 
83492
+ // src/supersession-asks.ts
83493
+ init_src5();
83494
+ init_src();
83495
+ init_src3();
83496
+ var ASK_PRIORS_MAX = 3;
83497
+ var ASK_SIMILAR_COVERAGE = 0.6;
83498
+ var ASK_TTL_MS = 30 * 6e4;
83499
+ var STRUCTURE = ["SUPERSEDES", "BUILDS_ON", "ALTERNATIVE_TO"];
83500
+ var liveFixesOf = (store, problemId) => store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((s) => !!s && s.label === "Solution" && s.validTo == null && !isEditPlaceholderSolution(s));
83501
+ var termsOf = (text) => [...new Set(text.toLowerCase().split(/[^a-z0-9_.]+/).filter((t) => t.length >= 3))];
83502
+ var MIN_CONTAINED_TERMS = 3;
83503
+ function similarProblems(store, problem) {
83504
+ const terms = termsOf(problem.description);
83505
+ if (terms.length === 0) return [];
83506
+ const hits = store.searchDescriptionTerms(terms, 60).filter((h) => h.node.label === "Problem" && h.node.id !== problem.id);
83507
+ const df = /* @__PURE__ */ new Map();
83508
+ for (const h of hits) for (const t of termsOf(h.node.description)) df.set(t, (df.get(t) ?? 0) + 1);
83509
+ const weightOf = (t) => Math.log(1 + (hits.length + 1) / (1 + (df.get(t) ?? 0)));
83510
+ return hits.filter((h) => {
83511
+ const theirs = termsOf(h.node.description);
83512
+ const ours = terms.length >= MIN_CONTAINED_TERMS ? termCoverage(terms, h.node.description, weightOf) : 0;
83513
+ const contained = theirs.length >= MIN_CONTAINED_TERMS ? termCoverage(theirs, problem.description, weightOf) : 0;
83514
+ return Math.max(ours, contained) >= ASK_SIMILAR_COVERAGE;
83515
+ }).map((h) => h.node.id);
83516
+ }
83517
+ function related(store, a, b) {
83518
+ return store.outEdges(a, [...STRUCTURE]).some((e) => e.to === b) || store.outEdges(b, [...STRUCTURE]).some((e) => e.to === a);
83519
+ }
83520
+ var SHOWN_PER_SESSION = 20;
83521
+ function statesSameSymptom(a, b) {
83522
+ const ta = termsOf(a);
83523
+ const tb = termsOf(b);
83524
+ const pool = [a, b];
83525
+ const df = /* @__PURE__ */ new Map();
83526
+ for (const text of pool) for (const t of termsOf(text)) df.set(t, (df.get(t) ?? 0) + 1);
83527
+ const weightOf = (t) => Math.log(1 + pool.length / (1 + (df.get(t) ?? 0)));
83528
+ const ab = ta.length >= MIN_CONTAINED_TERMS ? termCoverage(ta, b, weightOf) : 0;
83529
+ const ba = tb.length >= MIN_CONTAINED_TERMS ? termCoverage(tb, a, weightOf) : 0;
83530
+ return Math.max(ab, ba) >= ASK_SIMILAR_COVERAGE;
83531
+ }
83532
+ function earlierFixes(store, problemId, fixId, shown = []) {
83533
+ const problem = store.getNode(problemId);
83534
+ const fix = store.getNode(fixId);
83535
+ if (!problem || !fix) return [];
83536
+ const eligible = (s) => !!s && s.id !== fixId && s.label === "Solution" && s.validTo == null && !isEditPlaceholderSolution(s) && !related(store, fixId, s.id) && lifecycleOf(store, s).state !== "superseded";
83537
+ const shownIds = shown.filter((q) => statesSameSymptom(q.query, problem.description)).flatMap((q) => q.fixIds);
83538
+ const problems = /* @__PURE__ */ new Set([problemId]);
83539
+ for (const e of [...store.outEdges(problemId, ["REGRESSION_OF"]), ...store.inEdges(problemId, ["REGRESSION_OF"])]) {
83540
+ problems.add(e.from === problemId ? e.to : e.from);
83541
+ }
83542
+ for (const id of similarProblems(store, problem)) problems.add(id);
83543
+ const siblings = [...problems].flatMap((pid) => liveFixesOf(store, pid).map((s) => s.id));
83544
+ const rivals = [];
83545
+ const restatements = [];
83546
+ for (const id of [...shownIds, ...siblings]) {
83547
+ if (rivals.includes(id) || restatements.includes(id)) continue;
83548
+ const s = store.getNode(id);
83549
+ if (!eligible(s)) continue;
83550
+ (sameFixStatement(s.description, fix.description) ? restatements : rivals).push(id);
83551
+ }
83552
+ return [...rivals, ...restatements].slice(0, ASK_PRIORS_MAX);
83553
+ }
83554
+ var SupersessionAsks = class {
83555
+ bySession = /* @__PURE__ */ new Map();
83556
+ shown = /* @__PURE__ */ new Map();
83557
+ /** An errata tool showed this session these fixes for `query`. */
83558
+ noteShown(sessionId, entry) {
83559
+ if (!sessionId || entry.fixIds.length === 0) return;
83560
+ const list = (this.shown.get(sessionId) ?? []).filter((e) => e.query !== entry.query);
83561
+ list.push(entry);
83562
+ this.shown.set(sessionId, list.slice(-SHOWN_PER_SESSION));
83563
+ }
83564
+ shownTo(sessionId) {
83565
+ return this.shown.get(sessionId) ?? [];
83566
+ }
83567
+ /** Record (or refresh) the ask for a fix the session just recorded. */
83568
+ add(sessionId, fixId, priorIds, now = Date.now()) {
83569
+ if (priorIds.length === 0) return;
83570
+ const asks = (this.bySession.get(sessionId) ?? []).filter((a) => a.fixId !== fixId);
83571
+ asks.push({ fixId, priorIds, askedAt: now });
83572
+ this.bySession.set(sessionId, asks);
83573
+ }
83574
+ forSession(sessionId, now = Date.now()) {
83575
+ return (this.bySession.get(sessionId) ?? []).filter((a) => now - a.askedAt < ASK_TTL_MS);
83576
+ }
83577
+ /** The fix a session's unbound `(supersedes:[h])` answers — the ask that showed `[h]`. */
83578
+ fixAsking(sessionId, priorId, now = Date.now()) {
83579
+ return this.forSession(sessionId, now).find((a) => a.priorIds.includes(priorId))?.fixId;
83580
+ }
83581
+ /**
83582
+ * After a harvest: drop the priors the session judged (any structure tag,
83583
+ * confirm or refute names them), and what has outlived its TTL.
83584
+ */
83585
+ settle(sessionId, judged, now = Date.now()) {
83586
+ const asks = this.bySession.get(sessionId);
83587
+ if (!asks) return;
83588
+ const next = asks.map((a) => ({ ...a, priorIds: a.priorIds.filter((id) => !judged.has(id)) })).filter((a) => a.priorIds.length > 0 && now - a.askedAt < ASK_TTL_MS);
83589
+ if (next.length > 0) this.bySession.set(sessionId, next);
83590
+ else this.bySession.delete(sessionId);
83591
+ }
83592
+ /** A cache-key fingerprint of what this session's block would show. */
83593
+ version(sessionId) {
83594
+ return this.forSession(sessionId).map((a) => `${a.fixId}:${a.priorIds.join(",")}`).join(";");
83595
+ }
83596
+ };
83597
+
83334
83598
  // src/rollup.ts
83335
83599
  function readConversation(transcriptPath, includeThinking = true, maxChars = 6e4) {
83336
83600
  const raw2 = readTail(transcriptPath, 4e6);
@@ -87472,12 +87736,12 @@ function maybeFlushDigests() {
87472
87736
  try {
87473
87737
  if (process.env["ERRATA_NO_NOTIFY"] || !loadConfig().notifications) return;
87474
87738
  const now = Date.now();
87475
- for (const [kind, count] of digestCounts) {
87476
- if (count <= 0) continue;
87739
+ for (const [kind, count2] of digestCounts) {
87740
+ if (count2 <= 0) continue;
87477
87741
  if (now - (digestWindowStart.get(kind) ?? now) < DIGEST_INTERVAL_MS) continue;
87478
87742
  digestWindowStart.set(kind, now);
87479
87743
  digestCounts.set(kind, 0);
87480
- notify("Errata \xB7 daily digest", DIGEST_RENDER[kind]?.(count) ?? `${count} ${kind} today.`);
87744
+ notify("Errata \xB7 daily digest", DIGEST_RENDER[kind]?.(count2) ?? `${count2} ${kind} today.`);
87481
87745
  }
87482
87746
  } catch {
87483
87747
  }
@@ -87578,8 +87842,8 @@ var noteBreakerQuarantine = (path3) => {
87578
87842
  census.breakerQuarantined.push(path3);
87579
87843
  }
87580
87844
  };
87581
- var noteWindowOffender = (path3, count, windowMs) => {
87582
- census.topOffender = { path: path3, count, windowMs, at: Date.now() };
87845
+ var noteWindowOffender = (path3, count2, windowMs) => {
87846
+ census.topOffender = { path: path3, count: count2, windowMs, at: Date.now() };
87583
87847
  };
87584
87848
  function watchCensus() {
87585
87849
  return { ...census };
@@ -87886,7 +88150,7 @@ function createWatchBreaker(deps) {
87886
88150
  }
87887
88151
 
87888
88152
  // src/engine.ts
87889
- var DAEMON_VERSION = true ? "2.0.23-dev.4821" : "2.0.0-alpha.0";
88153
+ var DAEMON_VERSION = true ? "2.0.23-dev.4826" : "2.0.0-alpha.0";
87890
88154
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
87891
88155
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
87892
88156
  var GIT_OP_MUTE_MS = 4e3;
@@ -88328,6 +88592,7 @@ function createWorkspaceEngine(opts) {
88328
88592
  const sessions = createSessionRegistry({ originsPath: join37(paths.configDir, "session-origins.json") });
88329
88593
  const sessionRenders = /* @__PURE__ */ new Map();
88330
88594
  const selfCiteSkipsBySession = /* @__PURE__ */ new Map();
88595
+ const supersessionAsks = new SupersessionAsks();
88331
88596
  const toolRuns = createToolRunState();
88332
88597
  let ctxRefreshTimer = null;
88333
88598
  let contextDirty = false;
@@ -88398,6 +88663,15 @@ function createWorkspaceEngine(opts) {
88398
88663
  }
88399
88664
  return signal;
88400
88665
  };
88666
+ const lifecycleField = (n) => {
88667
+ const note = lifecycleNote(lifecycleOf(store, n));
88668
+ return note ? { lifecycle: note } : {};
88669
+ };
88670
+ const supersessionAsksFor = (sessionId) => supersessionAsks.forSession(sessionId).flatMap((a) => {
88671
+ const fix = store.getNode(a.fixId);
88672
+ const priors = a.priorIds.map((id) => store.getNode(id)).filter((n) => n !== null && n.validTo == null).map((n) => ({ id: n.id, description: n.description, ...lifecycleField(n) }));
88673
+ return fix && priors.length > 0 ? [{ fix: { id: fix.id, description: fix.description }, priors }] : [];
88674
+ });
88401
88675
  const statedIntentFor = (intent) => {
88402
88676
  const collective = intentRemote?.forIntent === intent ? intentRemote : null;
88403
88677
  return {
@@ -88407,7 +88681,8 @@ function createWorkspaceEngine(opts) {
88407
88681
  label: h.node.label,
88408
88682
  description: h.node.description,
88409
88683
  coverage: h.coverage,
88410
- ...isVerdictable(h.node) ? { verdict: closableByCaller(h.node) ? "own" : "foreign" } : {}
88684
+ ...isVerdictable(h.node) ? { verdict: closableByCaller(h.node) ? "own" : "foreign" } : {},
88685
+ ...lifecycleField(h.node)
88411
88686
  })),
88412
88687
  ...collective && collective.hits.length > 0 ? {
88413
88688
  remoteHits: collective.hits.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description }))
@@ -88860,6 +89135,7 @@ function createWorkspaceEngine(opts) {
88860
89135
  const workingFile = workingFiles.get(sessionId);
88861
89136
  const skips = selfCiteSkipsBySession.get(sessionId) ?? 0;
88862
89137
  const key = JSON.stringify([
89138
+ supersessionAsks.version(sessionId),
88863
89139
  subagentBaseVersion,
88864
89140
  lastRemoteAt,
88865
89141
  sessions.version(now),
@@ -88880,6 +89156,9 @@ function createWorkspaceEngine(opts) {
88880
89156
  }
88881
89157
  delete scoped.selfCiteSkips;
88882
89158
  if (skips > 0) scoped.selfCiteSkips = skips;
89159
+ delete scoped.supersessionAsks;
89160
+ const asks = supersessionAsksFor(sessionId);
89161
+ if (asks.length > 0) scoped.supersessionAsks = asks;
88883
89162
  const pendingUpdate = opts.pendingUpdate?.() ?? null;
88884
89163
  const daemonDistress = opts.daemonDistress?.() ?? null;
88885
89164
  const reviewItems = pickReviewItems();
@@ -89010,6 +89289,8 @@ function createWorkspaceEngine(opts) {
89010
89289
  let corroboratedEdges = 0;
89011
89290
  let refutesStamped = 0;
89012
89291
  let confirmsStamped = 0;
89292
+ let supersessionAsked = 0;
89293
+ let structureLinksMinted = 0;
89013
89294
  let recurrencesMarked = 0;
89014
89295
  let reopenedFromRegression = 0;
89015
89296
  let fixHeldConfirmed = 0;
@@ -89130,7 +89411,7 @@ function createWorkspaceEngine(opts) {
89130
89411
  for (const r of parseDesignResolutions(turn.text)) {
89131
89412
  try {
89132
89413
  const retractAs = r.disposition === "false_positive" || r.disposition === "invalid" ? r.disposition : null;
89133
- const closed = retractAs ? r.id ? retractDesignProblemById(store, r.id, retractAs, r.reason, t) : retractDesignProblemByStatement(store, r.problem, retractAs, r.reason, t) : r.id ? resolveDesignProblemById(store, r.id, r.fix, t) : resolveDesignProblemByStatement(store, r.problem, r.fix, t);
89414
+ const closed = retractAs ? r.id ? retractDesignProblemById(store, r.id, retractAs, r.reason, t) : retractDesignProblemByStatement(store, r.problem, retractAs, r.reason, t) : r.id ? resolveDesignProblemById(store, r.id, r.fix, t, sessionId) : resolveDesignProblemByStatement(store, r.problem, r.fix, t, sessionId);
89134
89415
  if (closed) {
89135
89416
  resolved++;
89136
89417
  if (!retractAs) {
@@ -89458,7 +89739,7 @@ function createWorkspaceEngine(opts) {
89458
89739
  }
89459
89740
  continue;
89460
89741
  }
89461
- const closed = resolveDesignProblemById(store, pid, fx.fixNote, t);
89742
+ const closed = resolveDesignProblemById(store, pid, fx.fixNote, t, sessionId);
89462
89743
  if (!closed) {
89463
89744
  const n = store.getNode(pid);
89464
89745
  if (n && n.attrs["resolvedAt"] == null && !closableByCaller(n)) {
@@ -89471,6 +89752,22 @@ function createWorkspaceEngine(opts) {
89471
89752
  );
89472
89753
  }
89473
89754
  }
89755
+ if (fx.fixNote?.trim()) {
89756
+ const fixId = solutionForProblem(store, pid);
89757
+ if (fixId) {
89758
+ try {
89759
+ const priors = earlierFixes(store, pid, fixId, supersessionAsks.shownTo(sessionId));
89760
+ supersessionAsks.add(sessionId, fixId, priors);
89761
+ const fix = priors.length > 0 ? store.getNode(fixId) : null;
89762
+ if (fix) {
89763
+ store.updateNode(fixId, { attrs: { ...fix.attrs, supersessionAskedAt: t }, lastUpdatedAt: t });
89764
+ supersessionAsked++;
89765
+ }
89766
+ } catch (err2) {
89767
+ console.warn("[errata] supersession ask skipped:", err2 instanceof Error ? err2.message : err2);
89768
+ }
89769
+ }
89770
+ }
89474
89771
  if (closed) {
89475
89772
  resolved++;
89476
89773
  const fxAnchor = editedTurnFile ?? turnFile ?? wf;
@@ -89670,8 +89967,9 @@ function createWorkspaceEngine(opts) {
89670
89967
  }
89671
89968
  }
89672
89969
  for (const sl of plan.solutionLinks) {
89673
- const pid = bindPid(sl);
89674
- const solId = pid ? solutionForProblem(store, pid) : void 0;
89970
+ const asked = sl.threadId ? void 0 : sl.targetIds.map((id) => supersessionAsks.fixAsking(sessionId, id)).find(Boolean);
89971
+ const pid = asked ? void 0 : bindPid(sl);
89972
+ const solId = asked ?? (pid ? solutionForProblem(store, pid) : void 0);
89675
89973
  if (!solId) {
89676
89974
  console.warn(`[errata] ${sl.relation} tag dropped: no solution in scope \u2014 state it beside its (fix:\u2026)`);
89677
89975
  continue;
@@ -89679,10 +89977,22 @@ function createWorkspaceEngine(opts) {
89679
89977
  for (const targetId of sl.targetIds) {
89680
89978
  if (targetId === solId) continue;
89681
89979
  const target = store.getNode(targetId);
89682
- if (!target || target.label !== "Solution") continue;
89980
+ if (!target || target.label !== "Solution") {
89981
+ console.warn(`[errata] ${sl.relation} tag dropped: ${targetId.slice(0, 32)} is ${target ? `a ${target.label}` : "not in this store"}, not a fix`);
89982
+ continue;
89983
+ }
89683
89984
  mintCiteEdge(solId, targetId, sl.relation, 0.4, { solutionStructure: true, hypothesis: true });
89985
+ structureLinksMinted++;
89684
89986
  }
89685
89987
  }
89988
+ supersessionAsks.settle(
89989
+ sessionId,
89990
+ /* @__PURE__ */ new Set([
89991
+ ...plan.solutionLinks.flatMap((sl) => sl.targetIds),
89992
+ ...plan.corroborations.map((c) => c.nodeId),
89993
+ ...plan.refutes.map((r) => r.nodeId)
89994
+ ])
89995
+ );
89686
89996
  const citingSession = sessionOriginKey(sessionId);
89687
89997
  const mintedHere = (nodeId) => store.getNode(nodeId)?.attrs["sources"]?.[0] === sessionId;
89688
89998
  const synthetic = sessions.originOf(sessionId) !== void 0;
@@ -89891,6 +90201,8 @@ function createWorkspaceEngine(opts) {
89891
90201
  // the contradict channel; the wire half rides the witness ledger).
89892
90202
  refutesStamped,
89893
90203
  confirmsStamped,
90204
+ supersessionAsked,
90205
+ structureLinksMinted,
89894
90206
  // RG-recognize tier A: resolved problems the door saw recur this pass.
89895
90207
  recurrencesMarked,
89896
90208
  // RG-reopen: closes flipped open on the two-touch evidence bar.
@@ -90282,6 +90594,7 @@ B: ${b}`,
90282
90594
  sessionContext,
90283
90595
  onHook: () => telemetry.count("hooks_fired"),
90284
90596
  onToolsObserved: (sessionId, toolNodeIds) => toolRuns.record(sessionId, toolNodeIds),
90597
+ onKnowledgeShown: (sessionId, shown) => supersessionAsks.noteShown(sessionId, shown),
90285
90598
  onHookEvent,
90286
90599
  onShellEvent,
90287
90600
  onToolError,
@@ -90790,6 +91103,7 @@ async function startDaemon(opts) {
90790
91103
  onHookEvent: engine.webHooks.onHookEvent,
90791
91104
  onShellEvent: engine.webHooks.onShellEvent,
90792
91105
  onToolError: engine.webHooks.onToolError,
91106
+ onKnowledgeShown: engine.webHooks.onKnowledgeShown,
90793
91107
  onDiagnostics: engine.webHooks.onDiagnostics,
90794
91108
  onTurn: engine.webHooks.onTurn,
90795
91109
  onSessionEnd: engine.webHooks.onSessionEnd
@@ -91231,7 +91545,8 @@ function settleEdgeOutcomes(queue, sent, verdicts, now) {
91231
91545
 
91232
91546
  // src/instance-receipts.ts
91233
91547
  import { createHash as createHash18 } from "node:crypto";
91234
- var INSTANCE_SEMANTIC_EDGE_TYPES = ["CAUSED_BY", "SOLVED_BY"];
91548
+ var INSTANCE_SEMANTIC_EDGE_TYPES = ["CAUSED_BY", "SOLVED_BY", "SUPERSEDES", "BUILDS_ON", "ALTERNATIVE_TO"];
91549
+ var INSTANCE_STRUCTURE_EDGE_TYPES = /* @__PURE__ */ new Set(["SUPERSEDES", "BUILDS_ON", "ALTERNATIVE_TO"]);
91235
91550
  var INSTANCE_ANCHOR_EDGE_TYPES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
91236
91551
  function edgeReceiptKind(type) {
91237
91552
  if (INSTANCE_SEMANTIC_EDGE_TYPES.includes(type)) return "semantic";
@@ -91260,7 +91575,7 @@ function instanceEdgeReceipts(sent, received, cloudIds) {
91260
91575
  groups.set(group, expected);
91261
91576
  }
91262
91577
  const complete = new Set([...groups].filter(
91263
- ([, expected]) => [...expected].every(([key, count]) => !rejected.has(key) && (accepted.get(key) ?? 0) >= count)
91578
+ ([, expected]) => [...expected].every(([key, count2]) => !rejected.has(key) && (accepted.get(key) ?? 0) >= count2)
91264
91579
  ).map(([group]) => group));
91265
91580
  return { complete: (source, kind) => complete.has(groupKey(source, kind)) };
91266
91581
  }
@@ -92236,6 +92551,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
92236
92551
  }
92237
92552
  const edges = [];
92238
92553
  const semanticEdgeDigests = {};
92554
+ const pulledStructureTarget = (e) => {
92555
+ if (!INSTANCE_STRUCTURE_EDGE_TYPES.has(e.type)) return void 0;
92556
+ const target = store.getNode(e.to) ?? opts.sharedStore?.getNode(e.to);
92557
+ return target?.label === "Solution" && target.attrs["source"] === "cloud" ? e.to : void 0;
92558
+ };
92239
92559
  for (const [sourceId, wireFrom] of semanticEndpoints) {
92240
92560
  const rawOuts = [
92241
92561
  ...store.outEdges(sourceId, [...INSTANCE_EDGES]),
@@ -92243,7 +92563,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
92243
92563
  ];
92244
92564
  const dedup = /* @__PURE__ */ new Map();
92245
92565
  for (const e of rawOuts) dedup.set(`${e.type}>${e.to}`, e);
92246
- const outs = [...dedup.values()].map((e) => ({ e, wireTo: semanticEndpoints.get(e.to) })).filter((x) => {
92566
+ const outs = [...dedup.values()].map((e) => ({ e, wireTo: semanticEndpoints.get(e.to) ?? pulledStructureTarget(e) })).filter((x) => {
92247
92567
  if (x.wireTo === wireFrom) {
92248
92568
  composition.collapsedEdges++;
92249
92569
  return false;
@@ -92270,7 +92590,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
92270
92590
  const lexicon = opts.lexicon;
92271
92591
  const isKnown = (tok) => lexicon.has(tok);
92272
92592
  const sidecar = {};
92273
- let count = 0;
92593
+ let count2 = 0;
92274
92594
  outer: for (const n of nodes) {
92275
92595
  if (!INSTANCE_LABELS.includes(n.label)) continue;
92276
92596
  for (const tok of extractIdentifierTokens(n.description)) {
@@ -92288,15 +92608,15 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
92288
92608
  composition.sidecarDropReasons[dropBucket] = (composition.sidecarDropReasons[dropBucket] ?? 0) + 1;
92289
92609
  continue;
92290
92610
  }
92291
- if (count >= MAX_SIDECAR_SYMBOLS) {
92611
+ if (count2 >= MAX_SIDECAR_SYMBOLS) {
92292
92612
  composition.sidecarTruncatedAtCap = 1;
92293
92613
  break outer;
92294
92614
  }
92295
92615
  sidecar[tok] = { kind: entry.kind, summary: scrubbed };
92296
- count++;
92616
+ count2++;
92297
92617
  }
92298
92618
  }
92299
- if (count > 0) symbolSummaries = sidecar;
92619
+ if (count2 > 0) symbolSummaries = sidecar;
92300
92620
  }
92301
92621
  edges.push(...anchorEdges);
92302
92622
  if (opts.edgeHolds && Object.keys(opts.edgeHolds).length > 0) {
@@ -95532,9 +95852,9 @@ function collectRepoFacts(root) {
95532
95852
  }
95533
95853
  };
95534
95854
  const roots = git3(["rev-list", "--max-parents=0", "HEAD"]);
95535
- const count = git3(["rev-list", "--count", "HEAD"]);
95855
+ const count2 = git3(["rev-list", "--count", "HEAD"]);
95536
95856
  const rootCommitSha = roots?.split(/\s+/).filter(Boolean).pop();
95537
- const commitCount = count && /^\d+$/.test(count) ? Number(count) : void 0;
95857
+ const commitCount = count2 && /^\d+$/.test(count2) ? Number(count2) : void 0;
95538
95858
  return {
95539
95859
  ...rootCommitSha && /^[0-9a-f]{40,64}$/i.test(rootCommitSha) ? { rootCommitSha } : {},
95540
95860
  ...typeof commitCount === "number" ? { commitCount } : {}
@@ -96532,6 +96852,8 @@ async function startMultiDaemon(opts = {}) {
96532
96852
  // and dropped the record on the floor — toolSessionsTracked read 0 across
96533
96853
  // 936 turns while the log showed records landing (VS-corroboration-rate).
96534
96854
  onToolsObserved: engine.webHooks.onToolsObserved,
96855
+ // Wired on BOTH builders — the onToolsObserved lesson above.
96856
+ onKnowledgeShown: engine.webHooks.onKnowledgeShown,
96535
96857
  onToolError: engine.webHooks.onToolError,
96536
96858
  onDiagnostics: engine.webHooks.onDiagnostics,
96537
96859
  onTurn: engine.webHooks.onTurn,
@@ -98039,18 +98361,18 @@ async function startMultiDaemon(opts = {}) {
98039
98361
  if (!owner) return;
98040
98362
  const fp = refusalFingerprint(reason, owner.n.description);
98041
98363
  const same = instanceReceipt(owner.n, destinationKey)["shipRefusedFingerprint"] === fp;
98042
- const count = same ? Number(instanceReceipt(owner.n, destinationKey)["shipRefusedCount"] ?? 0) + 1 : 1;
98364
+ const count2 = same ? Number(instanceReceipt(owner.n, destinationKey)["shipRefusedCount"] ?? 0) + 1 : 1;
98043
98365
  if (instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0) repeat();
98044
98366
  owner.s.updateNode(id, {
98045
98367
  attrs: updateInstanceReceipt(owner.n, destinationKey, {
98046
98368
  ...instanceReceipt(owner.n, destinationKey),
98047
98369
  ...same && instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0 ? {} : { shipRefusedSinceSeq: owner.s.currentIngestSeq() },
98048
- shipRefusedCount: count,
98370
+ shipRefusedCount: count2,
98049
98371
  shipRefusedReason: reason,
98050
98372
  shipRefusedFingerprint: fp
98051
98373
  }, owner.s === store)
98052
98374
  });
98053
- if (same && count === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
98375
+ if (same && count2 === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
98054
98376
  nowHeld.push({ id, reason });
98055
98377
  }
98056
98378
  };