@inerrata-corporation/errata 2.0.23-dev.4803 → 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);
@@ -18334,7 +18334,25 @@ var TAG_CANONICAL_ID_PREFIXES, TAG_HANDLE_SOURCE, TAG_THREAD_SOURCE, TAG_PLACEHO
18334
18334
  var init_tag_grammar = __esm({
18335
18335
  "../../packages/local-shared/src/tag-grammar.ts"() {
18336
18336
  "use strict";
18337
- TAG_CANONICAL_ID_PREFIXES = ["pat", "sol", "drc", "dcause", "dfix", "dprob", "dvuln", "prob", "claim", "err"];
18337
+ TAG_CANONICAL_ID_PREFIXES = [
18338
+ "motif_community_projn",
18339
+ "motif_community_orgn",
18340
+ "motif",
18341
+ "projn",
18342
+ "orgn",
18343
+ "dtri",
18344
+ "dom",
18345
+ "pat",
18346
+ "sol",
18347
+ "drc",
18348
+ "dcause",
18349
+ "dfix",
18350
+ "dprob",
18351
+ "dvuln",
18352
+ "prob",
18353
+ "claim",
18354
+ "err"
18355
+ ];
18338
18356
  TAG_HANDLE_SOURCE = String.raw`\[([a-z0-9][\w-]{0,80})\]|((?:${TAG_CANONICAL_ID_PREFIXES.join("|")})_[0-9a-f]{6,})`;
18339
18357
  TAG_THREAD_SOURCE = String.raw`#([a-z][\w-]{0,63})`;
18340
18358
  TAG_PLACEHOLDER_HANDLES = /* @__PURE__ */ new Set([
@@ -19571,7 +19589,7 @@ var init_lineage_integrity = __esm({
19571
19589
  });
19572
19590
 
19573
19591
  // ../../packages/math/src/constants.ts
19574
- var SURPRISE_MOMENTUM, SURPRISE_LEARNING_RATE, SURPRISE_LEARNING_RATE_SCALING, TIER_HALFLIFE_MULTIPLIER, HIT_RATE_SCALING_ALPHA, BASE_HALF_LIFE_SEQ, MOMENTUM_GATE_FLOOR, SURPRISE_RECENCY_LAMBDA_SEQ, NEMORI_SOFT_WRITE_MIN_COSINE, NEMORI_SOFT_WRITE_MAX_COSINE, NEMORI_DEDUP_COSINE, NEMORI_SOFT_ALPHA_MIN, NEMORI_SOFT_ALPHA_MAX, NEMORI_HIGH_SURPRISE_THRESHOLD, NEMORI_PREDICTION_FLOOR, REVIEW_SURPRISE_THRESHOLD, REVIEW_HITS_THRESHOLD;
19592
+ var SURPRISE_MOMENTUM, SURPRISE_LEARNING_RATE, SURPRISE_LEARNING_RATE_SCALING, TIER_HALFLIFE_MULTIPLIER, HIT_RATE_SCALING_ALPHA, BASE_HALF_LIFE_SEQ, MOMENTUM_GATE_FLOOR, EVIDENCE_HALFLIFE_SEQ, EVIDENCE_ACCEPTED_HALFLIFE_MULT, EVIDENCE_DECAY_FLOOR, CORROBORATION_WEIGHT, SURPRISE_RECENCY_LAMBDA_SEQ, NEMORI_SOFT_WRITE_MIN_COSINE, NEMORI_SOFT_WRITE_MAX_COSINE, NEMORI_DEDUP_COSINE, NEMORI_SOFT_ALPHA_MIN, NEMORI_SOFT_ALPHA_MAX, NEMORI_HIGH_SURPRISE_THRESHOLD, NEMORI_PREDICTION_FLOOR, REVIEW_SURPRISE_THRESHOLD, REVIEW_HITS_THRESHOLD;
19575
19593
  var init_constants = __esm({
19576
19594
  "../../packages/math/src/constants.ts"() {
19577
19595
  "use strict";
@@ -19586,6 +19604,10 @@ var init_constants = __esm({
19586
19604
  HIT_RATE_SCALING_ALPHA = 0.5;
19587
19605
  BASE_HALF_LIFE_SEQ = 500;
19588
19606
  MOMENTUM_GATE_FLOOR = 0.5;
19607
+ EVIDENCE_HALFLIFE_SEQ = 500;
19608
+ EVIDENCE_ACCEPTED_HALFLIFE_MULT = 1.5;
19609
+ EVIDENCE_DECAY_FLOOR = 0.3;
19610
+ CORROBORATION_WEIGHT = 0.3;
19589
19611
  SURPRISE_RECENCY_LAMBDA_SEQ = 36e-4;
19590
19612
  NEMORI_SOFT_WRITE_MIN_COSINE = 0.8;
19591
19613
  NEMORI_SOFT_WRITE_MAX_COSINE = 0.88;
@@ -19686,9 +19708,23 @@ var init_momentum = __esm({
19686
19708
  });
19687
19709
 
19688
19710
  // ../../packages/math/src/persistence.ts
19711
+ function reinforcementFactor(count2) {
19712
+ const n = Math.max(0, count2 ?? 0);
19713
+ return 1 + REINFORCEMENT_ALPHA * Math.tanh(n / REINFORCEMENT_K);
19714
+ }
19715
+ function contradictionFactor(pressure) {
19716
+ const p = Math.max(0, pressure ?? 0);
19717
+ return 1 - CONTRADICTION_MAX_DAMPENER * Math.tanh(p / CONTRADICTION_K);
19718
+ }
19719
+ var REINFORCEMENT_ALPHA, REINFORCEMENT_K, SUPERSESSION_DAMPENER, CONTRADICTION_MAX_DAMPENER, CONTRADICTION_K;
19689
19720
  var init_persistence = __esm({
19690
19721
  "../../packages/math/src/persistence.ts"() {
19691
19722
  "use strict";
19723
+ REINFORCEMENT_ALPHA = 0.3;
19724
+ REINFORCEMENT_K = 20;
19725
+ SUPERSESSION_DAMPENER = 0.7;
19726
+ CONTRADICTION_MAX_DAMPENER = 0.25;
19727
+ CONTRADICTION_K = 10;
19692
19728
  }
19693
19729
  });
19694
19730
 
@@ -19731,6 +19767,45 @@ var init_decay = __esm({
19731
19767
  });
19732
19768
 
19733
19769
  // ../../packages/math/src/uncertainty.ts
19770
+ function evidenceDecaySeq(referenceSeq, currentIngestSeq, opts) {
19771
+ if (referenceSeq == null || currentIngestSeq == null) return 1;
19772
+ const delta = Math.max(0, currentIngestSeq - referenceSeq);
19773
+ const halfLife = EVIDENCE_HALFLIFE_SEQ * (opts?.isAccepted ? EVIDENCE_ACCEPTED_HALFLIFE_MULT : 1);
19774
+ const raw2 = Math.pow(0.5, delta / halfLife);
19775
+ return Math.max(EVIDENCE_DECAY_FLOOR, Math.min(1, raw2));
19776
+ }
19777
+ function computeNodeUncertainty(node2, currentIngestSeq) {
19778
+ const referenceSeq = node2.lastValidatedAtSeq ?? node2.createdAtSeq;
19779
+ const decay = evidenceDecaySeq(referenceSeq, currentIngestSeq, {
19780
+ isAccepted: node2.validated === true
19781
+ });
19782
+ const acceptedCount = Math.max(0, node2.acceptedCount ?? 0);
19783
+ const corroborationCount = Math.max(0, node2.corroborationCount ?? 0);
19784
+ const failureReportCount = Math.max(0, node2.failureReportCount ?? 0);
19785
+ const decayedValidations = (acceptedCount + CORROBORATION_WEIGHT * corroborationCount) * decay;
19786
+ const decayedFailures = failureReportCount * decay;
19787
+ const alpha = 1 + decayedValidations;
19788
+ const beta = 1 + decayedFailures;
19789
+ const rawUncertainty = beta / (alpha + beta);
19790
+ const uncertainty = Number.isFinite(rawUncertainty) ? rawUncertainty : 0.5;
19791
+ const rawVariance = alpha * beta / ((alpha + beta) ** 2 * (alpha + beta + 1));
19792
+ const variance = Number.isFinite(rawVariance) ? rawVariance : 0;
19793
+ return {
19794
+ nodeId: node2.id,
19795
+ uncertainty: Math.max(0, Math.min(1, uncertainty)),
19796
+ alpha,
19797
+ beta,
19798
+ variance,
19799
+ components: {
19800
+ decayedValidations,
19801
+ decayedFailures,
19802
+ priorStrength: alpha + beta
19803
+ }
19804
+ };
19805
+ }
19806
+ function uncertaintyAdjustedScore(originalScore, uncertainty) {
19807
+ return originalScore * (1.25 - 0.5 * uncertainty);
19808
+ }
19734
19809
  var init_uncertainty = __esm({
19735
19810
  "../../packages/math/src/uncertainty.ts"() {
19736
19811
  "use strict";
@@ -20453,6 +20528,82 @@ var init_pagerank_local = __esm({
20453
20528
  }
20454
20529
  });
20455
20530
 
20531
+ // ../../packages/math/src/rank-knowledge.ts
20532
+ function rankKnowledge(input, weights) {
20533
+ const w = { ...DEFAULT_RANK_KNOWLEDGE_WEIGHTS, ...weights };
20534
+ const semantic = input.semantic == null || !Number.isFinite(input.semantic) ? null : clamp012((input.semantic - w.semanticFloor) / (1 - w.semanticFloor));
20535
+ const lexical = clamp012(input.lexical);
20536
+ const own = semantic == null ? lexical : 1 - (1 - semantic) * (1 - lexical);
20537
+ const relevance = Math.max(own, clamp012(input.inherited ?? 0));
20538
+ const hop = Math.max(w.hopFloor, 1 - w.hopPenalty * Math.max(0, input.hops ?? 0));
20539
+ const e = input.evidence ?? {};
20540
+ const persistence = reinforcementFactor(e.reinforcementCount) * contradictionFactor(e.contradictionPressure) * supersessionFactor(e.supersededBy);
20541
+ const { uncertainty } = computeNodeUncertainty({
20542
+ id: "",
20543
+ acceptedCount: e.acceptedCount ?? 0,
20544
+ corroborationCount: e.corroborationCount ?? 0,
20545
+ failureReportCount: e.failureReportCount ?? 0
20546
+ });
20547
+ const reliability = uncertaintyAdjustedScore(1, uncertainty);
20548
+ return {
20549
+ score: relevance * hop * persistence * reliability,
20550
+ components: { relevance, semantic, lexical, hop, persistence, reliability, uncertainty }
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
+ }
20557
+ function termCoverage(terms, text, weightOf) {
20558
+ if (terms.length === 0) return 0;
20559
+ const hay = text.toLowerCase();
20560
+ let total = 0;
20561
+ let held = 0;
20562
+ for (const t of terms) {
20563
+ const wt = Math.max(0, weightOf(t));
20564
+ total += wt;
20565
+ if (hay.includes(t.toLowerCase())) held += wt;
20566
+ }
20567
+ return total > 0 ? held / total : 0;
20568
+ }
20569
+ function poolEvidence(a, b) {
20570
+ if (!a) return b;
20571
+ if (!b) return a;
20572
+ const keys = ["acceptedCount", "corroborationCount", "failureReportCount", "contradictionPressure", "reinforcementCount", "supersededBy"];
20573
+ const out2 = {};
20574
+ for (const k of keys) out2[k] = Math.max(a[k] ?? 0, b[k] ?? 0);
20575
+ return out2;
20576
+ }
20577
+ var DEFAULT_RANK_KNOWLEDGE_WEIGHTS, clamp012;
20578
+ var init_rank_knowledge = __esm({
20579
+ "../../packages/math/src/rank-knowledge.ts"() {
20580
+ "use strict";
20581
+ init_persistence();
20582
+ init_uncertainty();
20583
+ DEFAULT_RANK_KNOWLEDGE_WEIGHTS = {
20584
+ semanticFloor: 0.5,
20585
+ hopPenalty: 0.15,
20586
+ hopFloor: 0.3
20587
+ };
20588
+ clamp012 = (x) => x < 0 ? 0 : x > 1 ? 1 : x;
20589
+ }
20590
+ });
20591
+
20592
+ // ../../packages/math/src/reader-evidence.ts
20593
+ var FIELD_CODES, FIELDS;
20594
+ var init_reader_evidence = __esm({
20595
+ "../../packages/math/src/reader-evidence.ts"() {
20596
+ "use strict";
20597
+ FIELD_CODES = {
20598
+ a: "acceptedCount",
20599
+ c: "corroborationCount",
20600
+ f: "failureReportCount",
20601
+ p: "contradictionPressure"
20602
+ };
20603
+ FIELDS = Object.values(FIELD_CODES);
20604
+ }
20605
+ });
20606
+
20456
20607
  // ../../packages/math/src/index.ts
20457
20608
  var init_src3 = __esm({
20458
20609
  "../../packages/math/src/index.ts"() {
@@ -20480,6 +20631,8 @@ var init_src3 = __esm({
20480
20631
  init_motif_gate();
20481
20632
  init_bko();
20482
20633
  init_pagerank_local();
20634
+ init_rank_knowledge();
20635
+ init_reader_evidence();
20483
20636
  }
20484
20637
  });
20485
20638
 
@@ -21883,11 +22036,11 @@ CREATE INDEX IF NOT EXISTS nodes_revisit_true ON nodes(valid_from) WHERE json_ty
21883
22036
  * kept with the change-feed reading of the rows it counts — triggers bump it on
21884
22037
  * every write from any connection, so a hit is exact, not a TTL guess. */
21885
22038
  counts = /* @__PURE__ */ new Map();
21886
- countAt(key, scopes, count) {
22039
+ countAt(key, scopes, count2) {
21887
22040
  const seq = readChangeSeq(this.db, scopes);
21888
22041
  const hit = this.counts.get(key);
21889
22042
  if (hit && hit.seq === seq) return hit.n;
21890
- const n = count();
22043
+ const n = count2();
21891
22044
  this.counts.set(key, { seq, n });
21892
22045
  return n;
21893
22046
  }
@@ -24318,7 +24471,7 @@ function recordVulnerabilityCause(store, findingId, causes, ts) {
24318
24471
  const finding = store.getNode(findingId);
24319
24472
  if (finding?.label !== "Vulnerability") return 0;
24320
24473
  let from = findingId;
24321
- let count = 0;
24474
+ let count2 = 0;
24322
24475
  for (const description of causes) {
24323
24476
  if (isPlaceholderStatement(description)) continue;
24324
24477
  const id = genericCanonicalId("dcause", { findingId, description: description.trim() });
@@ -24330,9 +24483,9 @@ function recordVulnerabilityCause(store, findingId, causes, ts) {
24330
24483
  }));
24331
24484
  mergeEdge(store, from, id, "CAUSED_BY", ts);
24332
24485
  from = id;
24333
- count++;
24486
+ count2++;
24334
24487
  }
24335
- return count;
24488
+ return count2;
24336
24489
  }
24337
24490
  function canonicalizePatternText(name2) {
24338
24491
  const stripped = name2.replace(/^\s*pattern(?:\s*[×x]\s*\d+)?\s*(?:\(exemplar\))?\s*[:—–-]\s*/i, "").replace(/\s+/g, " ").trim();
@@ -24648,6 +24801,15 @@ function isFragmentFixNote(note) {
24648
24801
  function isAutoMinted(n) {
24649
24802
  return isEditPlaceholderSolution(n);
24650
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
+ }
24651
24813
  function solutionTextKey(text) {
24652
24814
  return text.trim().replace(/\s+/g, " ").toLowerCase();
24653
24815
  }
@@ -24674,7 +24836,7 @@ function priorsForFile(store, relPath) {
24674
24836
  const constraints = [];
24675
24837
  const resolvedProblems = [];
24676
24838
  const seenProblem = /* @__PURE__ */ new Set();
24677
- const related = /* @__PURE__ */ new Map();
24839
+ const related2 = /* @__PURE__ */ new Map();
24678
24840
  const anchorEdges = [
24679
24841
  ...store.inEdges(file2.id, ["ANCHORED_AT"]),
24680
24842
  ...store.outEdges(file2.id, ["DEFINES"]).flatMap((d) => store.inEdges(d.to, ["ANCHORED_AT"]))
@@ -24691,14 +24853,14 @@ function priorsForFile(store, relPath) {
24691
24853
  resolvedProblems.push(n);
24692
24854
  }
24693
24855
  } else if (CITABLE_PRIOR_LABELS.has(n.label) && !isAutoMinted(n)) {
24694
- related.set(n.id, n);
24856
+ related2.set(n.id, n);
24695
24857
  }
24696
24858
  }
24697
24859
  const solutionsByProblem = /* @__PURE__ */ new Map();
24698
24860
  for (const p of [...openProblems, ...constraints, ...resolvedProblems]) {
24699
24861
  for (const e of store.outEdges(p.id, ["SOLVED_BY", "CAUSED_BY", "INSTANCE_OF"])) {
24700
24862
  const n = store.getNode(e.to);
24701
- 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);
24702
24864
  if (n && n.label === "Solution" && e.type === "SOLVED_BY" && !isAutoMinted(n)) {
24703
24865
  const list = solutionsByProblem.get(p.id) ?? [];
24704
24866
  if (!list.some((s) => s.id === n.id)) list.push(n);
@@ -24706,7 +24868,7 @@ function priorsForFile(store, relPath) {
24706
24868
  }
24707
24869
  }
24708
24870
  }
24709
- 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)
24710
24872
  return null;
24711
24873
  const recentFirst = (a, b) => (b.lastUpdatedAt ?? 0) - (a.lastUpdatedAt ?? 0);
24712
24874
  openProblems.sort(recentFirst);
@@ -24719,7 +24881,7 @@ function priorsForFile(store, relPath) {
24719
24881
  openProblems,
24720
24882
  constraints,
24721
24883
  resolvedProblems,
24722
- related: [...related.values()],
24884
+ related: [...related2.values()],
24723
24885
  solutionsByProblem
24724
24886
  };
24725
24887
  }
@@ -24747,8 +24909,13 @@ function anchorNodeToDiff(store, nodeId, expectLabel, changedPaths, workspaceId2
24747
24909
  return n;
24748
24910
  }
24749
24911
  function solutionForProblem(store, problemId) {
24750
- const e = store.outEdges(problemId, ["SOLVED_BY"])[0];
24751
- 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;
24752
24919
  }
24753
24920
  function anchorProblemToWorkingFile(store, problemId, relPath, workspaceId2, ts, provenance = "edited", opts = {}) {
24754
24921
  const p = store.getNode(problemId);
@@ -24932,9 +25099,9 @@ function upgradeAnchorHints(store, workspaceId2, ts) {
24932
25099
  }
24933
25100
  return { upgraded, standing, unresolvable, blocked };
24934
25101
  }
24935
- function resolveDesignProblemByStatement(store, statement, fixNote, t) {
25102
+ function resolveDesignProblemByStatement(store, statement, fixNote, t, session) {
24936
25103
  const problemId = identityId({ kind: "DesignProblem", statement });
24937
- return closeDesignProblem(store, problemId, fixNote, t);
25104
+ return closeDesignProblem(store, problemId, fixNote, t, session);
24938
25105
  }
24939
25106
  function closableByCaller(node2) {
24940
25107
  if (node2.attrs["source"] !== "cloud") return true;
@@ -24944,17 +25111,19 @@ function closableByCaller(node2) {
24944
25111
  function isVerdictable(node2) {
24945
25112
  return node2.label === "Problem" && node2.attrs["resolvedAt"] == null && (node2.validTo ?? null) === null && !isConstraintProblem(node2) && node2.attrs["kind"] !== "todo";
24946
25113
  }
24947
- function resolveDesignProblemById(store, id, fixNote, t) {
24948
- return closeDesignProblem(store, id.trim(), fixNote, t);
25114
+ function resolveDesignProblemById(store, id, fixNote, t, session) {
25115
+ return closeDesignProblem(store, id.trim(), fixNote, t, session);
24949
25116
  }
24950
- function closeDesignProblem(store, problemId, fixNote, t) {
25117
+ function closeDesignProblem(store, problemId, fixNote, t, session) {
24951
25118
  const p = store.getNode(problemId);
24952
25119
  if (!p || p.label !== "Problem" && p.label !== "Vulnerability") return false;
24953
25120
  if (!closableByCaller(p)) return false;
24954
25121
  if (p.attrs["resolvedAs"]) return false;
24955
25122
  if (fixNote?.trim() && !isFragmentFixNote(fixNote)) {
24956
25123
  const sols = store.outEdges(problemId, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => n !== null);
24957
- 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) {
24958
25127
  const reuse = p.label === "Vulnerability" ? null : findReusableSolution(store, fixNote);
24959
25128
  if (reuse) {
24960
25129
  mergeEdge(store, problemId, reuse.id, "SOLVED_BY", t);
@@ -24964,7 +25133,9 @@ function closeDesignProblem(store, problemId, fixNote, t) {
24964
25133
  buildNode(store, solId, "Solution", fixNote.trim(), t, {
24965
25134
  source: "convo",
24966
25135
  provisional: false,
24967
- ...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] } : {}
24968
25139
  })
24969
25140
  );
24970
25141
  mergeEdge(store, problemId, solId, "SOLVED_BY", t);
@@ -25271,7 +25442,7 @@ function exposureOutcomeAttrs(node2, exposure, at) {
25271
25442
  lastOutcomeAt: typeof prev === "number" ? Math.max(prev, at.ts) : at.ts
25272
25443
  };
25273
25444
  }
25274
- 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;
25275
25446
  var init_design_problem = __esm({
25276
25447
  "../../packages/local-graph/src/design-problem.ts"() {
25277
25448
  "use strict";
@@ -25337,6 +25508,7 @@ var init_design_problem = __esm({
25337
25508
  "Technique",
25338
25509
  "AntiPattern"
25339
25510
  ]);
25511
+ SAME_FIX_JACCARD = 0.5;
25340
25512
  MAX_ANCHOR_FILES = 5;
25341
25513
  ENCLOSING_SYMBOL_KINDS = /* @__PURE__ */ new Set([
25342
25514
  "Function",
@@ -25359,6 +25531,58 @@ var init_design_problem = __esm({
25359
25531
  }
25360
25532
  });
25361
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
+
25362
25586
  // ../../packages/local-graph/src/intent.ts
25363
25587
  function parseIntentFences(text) {
25364
25588
  const out2 = [];
@@ -27346,24 +27570,24 @@ function evaluateFed(store, d, stamps) {
27346
27570
  if (d.fedIncoming && incomingRows) {
27347
27571
  const targets = new Set(store.liveEdgeTargets(d.fedIncoming.edgeTypes));
27348
27572
  const rows = d.fedIncoming.cloudOnly ? incomingRows.filter((r) => r.cloud) : incomingRows;
27349
- const count2 = rows.filter((r) => targets.has(r.id)).length;
27350
- 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 };
27351
27575
  }
27352
27576
  if (d.fedIncoming) {
27353
- const { count: count2, total } = store.incomingEdgeCoverage?.(
27577
+ const { count: count3, total } = store.incomingEdgeCoverage?.(
27354
27578
  d.fedIncoming.label,
27355
27579
  d.fedIncoming.edgeTypes,
27356
27580
  d.fedIncoming.cloudOnly
27357
27581
  ) ?? { count: 0, total: 0 };
27358
- return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
27582
+ return { count: count3, total, fraction: total === 0 ? 0 : count3 / total };
27359
27583
  }
27360
27584
  if (d.fedEdges) {
27361
- const { count: count2, total } = store.recentEdgeAttrCoverage(
27585
+ const { count: count3, total } = store.recentEdgeAttrCoverage(
27362
27586
  d.fedEdges.marker,
27363
27587
  d.fedEdges.attr,
27364
27588
  d.fedEdges.recent
27365
27589
  );
27366
- return { count: count2, total, fraction: total === 0 ? 0 : count2 / total };
27590
+ return { count: count3, total, fraction: total === 0 ? 0 : count3 / total };
27367
27591
  }
27368
27592
  if (!d.fed) return { count: 0, total: 0, fraction: 0 };
27369
27593
  const column2 = COLUMN_INPUTS[d.fed.attr];
@@ -27381,13 +27605,13 @@ function evaluateFed(store, d, stamps) {
27381
27605
  for (const n of window2) if (has(n) && n.createdAt < anchor) anchor = n.createdAt;
27382
27606
  window2 = anchor === Infinity ? [] : window2.filter((n) => n.createdAt >= anchor);
27383
27607
  }
27384
- let count = 0;
27385
- for (const n of window2) if (has(n)) count++;
27386
- 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 };
27387
27611
  }
27388
27612
  function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mechanisms = MECHANISMS) {
27389
27613
  const counts = /* @__PURE__ */ new Map();
27390
- const count = (label) => {
27614
+ const count2 = (label) => {
27391
27615
  if (!counts.has(label)) counts.set(label, store.countNodesByLabel(label));
27392
27616
  return counts.get(label);
27393
27617
  };
@@ -27411,8 +27635,8 @@ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mech
27411
27635
  const span = inv?.firstTs === void 0 ? 0 : inv.lastTs - inv.firstTs;
27412
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);
27413
27637
  let verdict;
27414
- const hasInput = fed.total > 0 || Boolean(d.fed?.sinceFirstStamp && d.fed.labels.some((label) => count(label) > 0));
27415
- 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;
27416
27640
  if (d.configCounter && inv?.lastTotals?.[d.configCounter] === 0) verdict = "unconfigured";
27417
27641
  else if ((backlog ?? 0) === 0 && (!hasInput && !d.inputOptional || missingRequiredNodes)) verdict = "no-input";
27418
27642
  else if (!inv || inv.runs === 0) verdict = "never-invoked";
@@ -27483,6 +27707,37 @@ var init_mechanism_liveness = __esm({
27483
27707
  effectCounter: "refutesStamped",
27484
27708
  note: "RG-mark; reason text is local-only (wire ships nodeId+witnessKey)"
27485
27709
  },
27710
+ {
27711
+ id: "confirm-local-stamp",
27712
+ what: "stamps a harvested confirm / leaned-on witness onto the LOCAL node (confirmedAt/confirmations)",
27713
+ pass: "capture",
27714
+ // The consumer is errata.search's one formula (apps/daemon one-search.ts
27715
+ // localEvidence → packages/math rankKnowledge reliability). Self-gated and
27716
+ // synthetic-gated at harvest, so a quiet counter can also mean every cite
27717
+ // was the session's own — the written-at-all bar, like refutedAt.
27718
+ fed: {
27719
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
27720
+ attr: "confirmedAt",
27721
+ minFraction: 0
27722
+ },
27723
+ effectCounter: "confirmsStamped",
27724
+ note: "consumed by one-search rankKnowledge; transport to cloud corroborationCount unchanged"
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
+ },
27486
27741
  {
27487
27742
  id: "regression-recognize",
27488
27743
  what: "marks a resolved problem as resolutionSuspect when it recurs at the door",
@@ -27916,6 +28171,8 @@ __export(src_exports2, {
27916
28171
  isUnfilledPlaceholder: () => isUnfilledPlaceholder,
27917
28172
  isVerdictable: () => isVerdictable,
27918
28173
  learnedConductance: () => learnedConductance,
28174
+ lifecycleNote: () => lifecycleNote,
28175
+ lifecycleOf: () => lifecycleOf,
27919
28176
  linkProblemToLanguages: () => linkProblemToLanguages,
27920
28177
  linkProblemToPackages: () => linkProblemToPackages,
27921
28178
  linkProblemToSymbols: () => linkProblemToSymbols,
@@ -27978,12 +28235,14 @@ __export(src_exports2, {
27978
28235
  retractDesignProblemByStatement: () => retractDesignProblemByStatement,
27979
28236
  revisitContradictedPrinciples: () => revisitContradictedPrinciples,
27980
28237
  revisitStaleRoutes: () => revisitStaleRoutes,
28238
+ sameFixStatement: () => sameFixStatement,
27981
28239
  searchByIntent: () => searchByIntent,
27982
28240
  solutionForProblem: () => solutionForProblem,
27983
28241
  splittingAxis: () => splittingAxis,
27984
28242
  stampObservedOs: () => stampObservedOs,
27985
28243
  statementIdentityKey: () => statementIdentityKey,
27986
28244
  staticConductance: () => staticConductance,
28245
+ supersedersOf: () => supersedersOf,
27987
28246
  symbolCandidatesInText: () => symbolCandidatesInText,
27988
28247
  symbolIndexForText: () => symbolIndexForText,
27989
28248
  toolNodeId: () => toolNodeId,
@@ -28009,6 +28268,7 @@ var init_src5 = __esm({
28009
28268
  init_crystallize();
28010
28269
  init_aggregate();
28011
28270
  init_design_problem();
28271
+ init_lifecycle();
28012
28272
  init_intent();
28013
28273
  init_anchor_backfill();
28014
28274
  init_percolate();
@@ -28456,6 +28716,22 @@ function renderSnapshot(s) {
28456
28716
  );
28457
28717
  lines.push("");
28458
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
+ }
28459
28735
  lines.push("### Recently observed problems in this workspace");
28460
28736
  if (s.recentProblems.length === 0 && s.recentResolved.length === 0 && s.recentConstraints.length === 0 && s.regressions.length === 0) {
28461
28737
  lines.push("- _none yet \u2014 errata is still building its model_");
@@ -28578,7 +28854,7 @@ function renderSnapshot(s) {
28578
28854
  lines.push("");
28579
28855
  lines.push("_Priors that speak to it \u2014 cite one with its `[handle]` if you lean on it:_");
28580
28856
  for (const h of si.hits) {
28581
- lines.push(`- **${h.description}** \u2014 \`${h.id}\``);
28857
+ lines.push(`- **${h.description}** \u2014 \`${h.id}\`${h.lifecycle ? ` _(${h.lifecycle})_` : ""}`);
28582
28858
  if (h.verdict === "own") {
28583
28859
  lines.push(
28584
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"
@@ -28758,6 +29034,7 @@ function isolateSnapshot(s) {
28758
29034
  workingFile: _workingFile,
28759
29035
  statedIntent: _statedIntent,
28760
29036
  selfCiteSkips: _selfCiteSkips,
29037
+ supersessionAsks: _supersessionAsks,
28761
29038
  pendingUpdate: _pendingUpdate,
28762
29039
  daemonDistress: _daemonDistress,
28763
29040
  reviewItems: _reviewItems,
@@ -29315,14 +29592,14 @@ function sidecarForNodes(sidecar, nodes) {
29315
29592
  const present = /* @__PURE__ */ new Set();
29316
29593
  for (const n of nodes) for (const tok of extractIdentifierTokens(n.description)) present.add(tok);
29317
29594
  const filtered = {};
29318
- let count = 0;
29595
+ let count2 = 0;
29319
29596
  for (const [symbol2, entry] of Object.entries(sidecar)) {
29320
29597
  if (present.has(symbol2)) {
29321
29598
  filtered[symbol2] = entry;
29322
- count++;
29599
+ count2++;
29323
29600
  }
29324
29601
  }
29325
- return count > 0 ? filtered : void 0;
29602
+ return count2 > 0 ? filtered : void 0;
29326
29603
  }
29327
29604
  function wireVia(value) {
29328
29605
  if (!value || typeof value !== "object" || Array.isArray(value)) return null;
@@ -29386,7 +29663,7 @@ function toWirePayload(batch, runId) {
29386
29663
  toCanonicalId: e.to,
29387
29664
  type: e.type,
29388
29665
  attrs: {
29389
- ...typeof e.confidence === "number" ? { confidence: clamp012(e.confidence) } : {},
29666
+ ...typeof e.confidence === "number" ? { confidence: clamp013(e.confidence) } : {},
29390
29667
  ...perContext ? { perContext } : {},
29391
29668
  ...triageDiscriminatorAttrs(e.type, e.attrs),
29392
29669
  // PJ-anchor-version: the two opaque version stamps ride on anchors only.
@@ -29414,7 +29691,7 @@ function toWirePayload(batch, runId) {
29414
29691
  ...symbolSummaries ? { symbolSummaries } : {}
29415
29692
  };
29416
29693
  }
29417
- function clamp012(x) {
29694
+ function clamp013(x) {
29418
29695
  return Math.max(0, Math.min(1, x));
29419
29696
  }
29420
29697
  function compactAttrs(input) {
@@ -29430,7 +29707,7 @@ function textOrThrow(value, field) {
29430
29707
  return text;
29431
29708
  }
29432
29709
  function optionalEdgeAttrs(confidence) {
29433
- return typeof confidence === "number" ? { confidence: clamp012(confidence) } : void 0;
29710
+ return typeof confidence === "number" ? { confidence: clamp013(confidence) } : void 0;
29434
29711
  }
29435
29712
  function makeEdge(fromCanonicalId, type, toCanonicalId, confidence) {
29436
29713
  const attrs = optionalEdgeAttrs(confidence);
@@ -30087,7 +30364,7 @@ var init_client = __esm({
30087
30364
  id: n.canonicalId,
30088
30365
  label: n.label,
30089
30366
  description: n.description,
30090
- extractionConfidence: typeof n.attrs["score"] === "number" ? clamp012(n.attrs["score"]) : 0.5,
30367
+ extractionConfidence: typeof n.attrs["score"] === "number" ? clamp013(n.attrs["score"]) : 0.5,
30091
30368
  extractionSource: INGEST_EXTRACTION_SOURCES.includes(n.attrs["extractionSource"]) ? n.attrs["extractionSource"] : "cold-start-seed",
30092
30369
  embedding: [],
30093
30370
  cumulativeSurprise: 0,
@@ -30107,7 +30384,7 @@ var init_client = __esm({
30107
30384
  from: e.fromCanonicalId,
30108
30385
  to: e.toCanonicalId,
30109
30386
  type: e.type,
30110
- confidence: typeof e.attrs["confidence"] === "number" ? clamp012(e.attrs["confidence"]) : 0.5,
30387
+ confidence: typeof e.attrs["confidence"] === "number" ? clamp013(e.attrs["confidence"]) : 0.5,
30111
30388
  extractionSource: "agent-observed",
30112
30389
  createdAt: now,
30113
30390
  lastSeenAt: now,
@@ -36137,9 +36414,9 @@ function contextCard(store, snapshot) {
36137
36414
  for (const r of snapshot.recentProblems) add(r.node);
36138
36415
  for (const n of snapshot.remote ?? []) add(n);
36139
36416
  for (const m of snapshot.motifs) add(m);
36140
- const count = plural(delivered.length, "prior");
36417
+ const count2 = plural(delivered.length, "prior");
36141
36418
  const intent = snapshot.statedIntent?.text;
36142
- 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);
36143
36420
  }
36144
36421
  function writeContextCard(root, hash2, card) {
36145
36422
  writeFileSync6(join8(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({
@@ -36162,7 +36439,7 @@ function openProblemCount(store, now = Date.now()) {
36162
36439
  const hit = openProblemsCache.get(store);
36163
36440
  const seq = store.changeSeq?.(OPEN_PROBLEM_SCOPES);
36164
36441
  if (hit && (seq !== void 0 ? hit.seq === seq : now - hit.at < OPEN_PROBLEMS_TTL_MS)) return hit.count;
36165
- let count = 0;
36442
+ let count2 = 0;
36166
36443
  const labels = ["Problem", "Vulnerability"];
36167
36444
  const plain = store.selectNodes({
36168
36445
  labels,
@@ -36184,10 +36461,10 @@ function openProblemCount(store, now = Date.now()) {
36184
36461
  return { ...row, attrs };
36185
36462
  });
36186
36463
  for (const p of [...plain, ...qualified]) {
36187
- if (live(p) && !p.attrs["resolvedAt"] && !isConstraintProblem(p)) count++;
36464
+ if (live(p) && !p.attrs["resolvedAt"] && !isConstraintProblem(p)) count2++;
36188
36465
  }
36189
- openProblemsCache.set(store, { at: now, count, ...seq !== void 0 ? { seq } : {} });
36190
- return count;
36466
+ openProblemsCache.set(store, { at: now, count: count2, ...seq !== void 0 ? { seq } : {} });
36467
+ return count2;
36191
36468
  }
36192
36469
  var CONTEXT_CARD_FILE, OPEN_PROBLEMS_TTL_MS, openProblemsCache, OPEN_PROBLEM_SCOPES, OPEN_PROBLEM_ATTRS, HISTORY_QUALITY_READ_KEYS;
36193
36470
  var init_recall_signal = __esm({
@@ -38371,6 +38648,16 @@ function dedupCloudHits(hits) {
38371
38648
  }
38372
38649
  return [...byId.values()];
38373
38650
  }
38651
+ function cloudEvidence(raw2) {
38652
+ if (!raw2 || typeof raw2 !== "object") return void 0;
38653
+ const r = raw2;
38654
+ const out2 = {};
38655
+ for (const k of ["acceptedCount", "corroborationCount", "failureReportCount", "contradictionPressure", "reinforcementCount", "supersededBy"]) {
38656
+ const v = r[k];
38657
+ if (typeof v === "number" && Number.isFinite(v) && v > 0) out2[k] = v;
38658
+ }
38659
+ return Object.keys(out2).length ? out2 : void 0;
38660
+ }
38374
38661
  function searchResultToCloudHits(result) {
38375
38662
  const n = result.nodes.length;
38376
38663
  const scores = result.nodes.map((nd) => typeof nd.attrs?.["score"] === "number" ? nd.attrs["score"] : NaN);
@@ -38382,11 +38669,13 @@ function searchResultToCloudHits(result) {
38382
38669
  const communityId = node2.attrs?.["community"];
38383
38670
  const communityLabel = node2.attrs?.["communityLabel"];
38384
38671
  const via = result.via?.[node2.id];
38672
+ const evidence = cloudEvidence(node2.attrs?.["evidence"]);
38385
38673
  return {
38386
38674
  id: node2.id,
38387
38675
  label: node2.label,
38388
38676
  description: node2.description,
38389
38677
  cloudScore,
38678
+ ...evidence ? { evidence } : {},
38390
38679
  ...typeof usage === "number" ? { usageCount: usage } : {},
38391
38680
  ...typeof communityId === "number" ? { community: { id: communityId, label: typeof communityLabel === "string" ? communityLabel : null } } : {},
38392
38681
  ...via ? { via } : {}
@@ -38551,7 +38840,8 @@ async function dualAugment(opts) {
38551
38840
  status: "merged",
38552
38841
  merged,
38553
38842
  seedProvenance,
38554
- seedUsageCount
38843
+ seedUsageCount,
38844
+ cloudEvidence: new Map(deduped.flatMap((h) => h.evidence ? [[h.id, h.evidence]] : []))
38555
38845
  };
38556
38846
  }
38557
38847
  function federationHint(status) {
@@ -38762,6 +39052,130 @@ var init_dual_augment = __esm({
38762
39052
  }
38763
39053
  });
38764
39054
 
39055
+ // src/one-search.ts
39056
+ function localEvidence(attrs) {
39057
+ if (!attrs) return void 0;
39058
+ const n = (k) => {
39059
+ const v = Number(attrs[k]);
39060
+ return Number.isFinite(v) && v > 0 ? v : 0;
39061
+ };
39062
+ const refutations = n("refutations");
39063
+ const evidence = {
39064
+ // Verdict witnesses (prior-tags.ts): `(confirm:)` → confirmations, `(refute:)` → refutations.
39065
+ corroborationCount: n("confirmations"),
39066
+ failureReportCount: refutations,
39067
+ contradictionPressure: refutations * REFUTE_PRESSURE,
39068
+ // Re-observation of the same problem is reinforcement (§5.2), not validation:
39069
+ // `corroborations` here counts the problem being raised again.
39070
+ reinforcementCount: Math.max(n("corroborations"), n("observedCount") - 1)
39071
+ };
39072
+ return Object.values(evidence).some((v) => (v ?? 0) > 0) ? evidence : void 0;
39073
+ }
39074
+ async function rankHits(store, query, hits, opts = {}) {
39075
+ const terms = query.trim().split(/\s+/).filter((t) => t.length >= 2);
39076
+ const texts = hits.map((h) => [h.name ?? h.description ?? "", h.viaText ?? ""].join(" ").trim());
39077
+ const lowered = terms.map((t) => t.toLowerCase());
39078
+ const df = /* @__PURE__ */ new Map();
39079
+ for (const text of texts) {
39080
+ const hay = text.toLowerCase();
39081
+ for (const t of lowered) if (hay.includes(t)) df.set(t, (df.get(t) ?? 0) + 1);
39082
+ }
39083
+ const weightOf = (t) => Math.log(1 + hits.length / (1 + (df.get(t.toLowerCase()) ?? 0)));
39084
+ let vectors = [];
39085
+ let floor;
39086
+ try {
39087
+ const out2 = await (opts.embed ?? defaultEmbed)([query, ...texts]);
39088
+ const q = out2[0];
39089
+ if (q) {
39090
+ floor = semanticFloorFor(q.version);
39091
+ vectors = out2.slice(1).map((v) => v && v.version === q.version ? v : null);
39092
+ vectors.unshift(q);
39093
+ }
39094
+ } catch {
39095
+ vectors = [];
39096
+ }
39097
+ const qv = vectors[0];
39098
+ const weights = floor != null ? { semanticFloor: floor } : void 0;
39099
+ const inputs = hits.map((h, i2) => {
39100
+ const node2 = store?.getNode(h.id);
39101
+ const local = node2?.attrs;
39102
+ const cloud = [h.id, ...h.twins ?? []].map((id) => opts.cloudEvidence?.get(id)).reduce((acc, e) => poolEvidence(acc, e), void 0);
39103
+ const cv = vectors[i2 + 1];
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
+ );
39109
+ return {
39110
+ ...qv && cv ? { semantic: cosine(qv.vector, cv.vector) } : {},
39111
+ lexical: termCoverage(terms, texts[i2], weightOf),
39112
+ hops: h.hops ?? 0,
39113
+ ...evidence ? { evidence } : {}
39114
+ };
39115
+ });
39116
+ const indexOf = /* @__PURE__ */ new Map();
39117
+ hits.forEach((h, i2) => {
39118
+ for (const id of [h.id, ...h.twins ?? []]) if (!indexOf.has(id)) indexOf.set(id, i2);
39119
+ });
39120
+ const own = inputs.map((inp) => rankKnowledge(inp, weights).components.relevance);
39121
+ const best = [...own];
39122
+ for (let step = 0; step < INHERIT_DEPTH; step++) {
39123
+ hits.forEach((h, i2) => {
39124
+ const p = h.parentId != null ? indexOf.get(h.parentId) : void 0;
39125
+ if (p != null && p !== i2 && best[p] > best[i2]) best[i2] = best[p];
39126
+ });
39127
+ }
39128
+ const ranked = hits.map((h, i2) => {
39129
+ const r = rankKnowledge({ ...inputs[i2], ...best[i2] > own[i2] ? { inherited: best[i2] } : {} }, weights);
39130
+ return { hit: h, i: i2, r };
39131
+ });
39132
+ ranked.sort((a, b) => b.r.score - a.r.score || a.i - b.i);
39133
+ return ranked.map(({ hit, r }) => ({ ...hit, score: r.score, rank: r.components }));
39134
+ }
39135
+ function interleaveLanes(ranked, isKnowledge, limit) {
39136
+ const lanes = [ranked.filter((r) => isKnowledge(r.label)), ranked.filter((r) => !isKnowledge(r.label))];
39137
+ const out2 = [];
39138
+ for (let i2 = 0; out2.length < limit && i2 < ranked.length; i2++) {
39139
+ const round2 = lanes.flatMap((lane) => lane[i2] ? [lane[i2]] : []).sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
39140
+ for (const hit of round2) if (out2.length < limit) out2.push(hit);
39141
+ }
39142
+ return out2;
39143
+ }
39144
+ function seedQuery(text) {
39145
+ return text.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[^A-Za-z0-9]+/g, " ").trim();
39146
+ }
39147
+ async function rankDualNodes(store, query, nodes, cloudEvidence2) {
39148
+ const withParents = nodes.map((n) => {
39149
+ const parent = n.via?.parentId;
39150
+ return parent ? { ...n, parentId: parent } : n;
39151
+ });
39152
+ const ranked = await rankHits(store, query, withParents, cloudEvidence2 ? { cloudEvidence: cloudEvidence2 } : {});
39153
+ return ranked.map(({ rank, score: score2, ...n }) => ({ ...n, score: score2, why: rankWhy(rank) }));
39154
+ }
39155
+ async function rankSimilarLocal(store, seedText, hits) {
39156
+ const ranked = await rankHits(store, seedQuery(seedText), hits.map((h) => ({ ...h, hops: 0 })));
39157
+ return ranked.map(({ rank, score: score2, hops: _hops, ...h }) => ({ ...h, score: score2, why: rankWhy(rank) }));
39158
+ }
39159
+ function withCite(records, isKnowledge) {
39160
+ return records.map((r) => isKnowledge(String(r["label"])) ? { ...r, cite: String(r["id"]) } : r);
39161
+ }
39162
+ function rankWhy(c) {
39163
+ const r = (x) => Math.round(x * 1e3) / 1e3;
39164
+ return { relevance: r(c.relevance), reliability: r(c.reliability), persistence: r(c.persistence) };
39165
+ }
39166
+ var REFUTE_PRESSURE, INHERIT_DEPTH, defaultEmbed;
39167
+ var init_one_search = __esm({
39168
+ "src/one-search.ts"() {
39169
+ "use strict";
39170
+ init_src4();
39171
+ init_src3();
39172
+ init_src5();
39173
+ REFUTE_PRESSURE = 0.6;
39174
+ INHERIT_DEPTH = 3;
39175
+ defaultEmbed = async (texts) => texts.map((t) => ({ vector: embed(t), version: EMBEDDING_VERSION }));
39176
+ }
39177
+ });
39178
+
38765
39179
  // src/daemon-generalize-client.ts
38766
39180
  function daemonLoopbackUrl(lockPath = globalDaemonLock()) {
38767
39181
  const url2 = readDaemonLock(lockPath)?.webUiUrl;
@@ -41163,9 +41577,9 @@ async function Module2(moduleArg = {}) {
41163
41577
  }
41164
41578
  __name(getString, "getString");
41165
41579
  function getStringList() {
41166
- var count2 = getLEB();
41580
+ var count22 = getLEB();
41167
41581
  var rtn = [];
41168
- while (count2--) rtn.push(getString());
41582
+ while (count22--) rtn.push(getString());
41169
41583
  return rtn;
41170
41584
  }
41171
41585
  __name(getStringList, "getStringList");
@@ -41214,8 +41628,8 @@ async function Module2(moduleArg = {}) {
41214
41628
  } else if (subsectionType === WASM_DYLINK_NEEDED) {
41215
41629
  customSection.neededDynlibs = getStringList();
41216
41630
  } else if (subsectionType === WASM_DYLINK_EXPORT_INFO) {
41217
- var count = getLEB();
41218
- while (count--) {
41631
+ var count2 = getLEB();
41632
+ while (count2--) {
41219
41633
  var symname = getString();
41220
41634
  var flags2 = getLEB();
41221
41635
  if (flags2 & WASM_SYMBOL_TLS) {
@@ -41223,8 +41637,8 @@ async function Module2(moduleArg = {}) {
41223
41637
  }
41224
41638
  }
41225
41639
  } else if (subsectionType === WASM_DYLINK_IMPORT_INFO) {
41226
- var count = getLEB();
41227
- while (count--) {
41640
+ var count2 = getLEB();
41641
+ while (count2--) {
41228
41642
  var modname = getString();
41229
41643
  var symname = getString();
41230
41644
  var flags2 = getLEB();
@@ -41383,9 +41797,9 @@ async function Module2(moduleArg = {}) {
41383
41797
  }
41384
41798
  return func2;
41385
41799
  }, "getWasmTableEntry");
41386
- var updateTableMap = /* @__PURE__ */ __name((offset, count) => {
41800
+ var updateTableMap = /* @__PURE__ */ __name((offset, count2) => {
41387
41801
  if (functionsInTableMap) {
41388
- for (var i2 = offset; i2 < offset + count; i2++) {
41802
+ for (var i2 = offset; i2 < offset + count2; i2++) {
41389
41803
  var item2 = getWasmTableEntry(i2);
41390
41804
  if (item2) {
41391
41805
  functionsInTableMap.set(item2, i2);
@@ -42812,12 +43226,12 @@ var init_web_tree_sitter = __esm({
42812
43226
  throw new TypeError("Argument must be a Tree");
42813
43227
  }
42814
43228
  C._ts_tree_get_changed_ranges_wasm(this[0], other[0]);
42815
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43229
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
42816
43230
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
42817
- const result = new Array(count);
42818
- if (count > 0) {
43231
+ const result = new Array(count2);
43232
+ if (count2 > 0) {
42819
43233
  let address = buffer;
42820
- for (let i2 = 0; i2 < count; i2++) {
43234
+ for (let i2 = 0; i2 < count2; i2++) {
42821
43235
  result[i2] = unmarshalRange(address);
42822
43236
  address += SIZE_OF_RANGE;
42823
43237
  }
@@ -42828,12 +43242,12 @@ var init_web_tree_sitter = __esm({
42828
43242
  /** Get the included ranges that were used to parse the syntax tree. */
42829
43243
  getIncludedRanges() {
42830
43244
  C._ts_tree_included_ranges_wasm(this[0]);
42831
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43245
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
42832
43246
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
42833
- const result = new Array(count);
42834
- if (count > 0) {
43247
+ const result = new Array(count2);
43248
+ if (count2 > 0) {
42835
43249
  let address = buffer;
42836
- for (let i2 = 0; i2 < count; i2++) {
43250
+ for (let i2 = 0; i2 < count2; i2++) {
42837
43251
  result[i2] = unmarshalRange(address);
42838
43252
  address += SIZE_OF_RANGE;
42839
43253
  }
@@ -43358,12 +43772,12 @@ var init_web_tree_sitter = __esm({
43358
43772
  childrenForFieldId(fieldId) {
43359
43773
  marshalNode(this);
43360
43774
  C._ts_node_children_by_field_id_wasm(this.tree[0], fieldId);
43361
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43775
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43362
43776
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43363
- const result = new Array(count);
43364
- if (count > 0) {
43777
+ const result = new Array(count2);
43778
+ if (count2 > 0) {
43365
43779
  let address = buffer;
43366
- for (let i2 = 0; i2 < count; i2++) {
43780
+ for (let i2 = 0; i2 < count2; i2++) {
43367
43781
  result[i2] = unmarshalNode(this.tree, address);
43368
43782
  address += SIZE_OF_NODE;
43369
43783
  }
@@ -43435,12 +43849,12 @@ var init_web_tree_sitter = __esm({
43435
43849
  if (!this._children) {
43436
43850
  marshalNode(this);
43437
43851
  C._ts_node_children_wasm(this.tree[0]);
43438
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43852
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43439
43853
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43440
- this._children = new Array(count);
43441
- if (count > 0) {
43854
+ this._children = new Array(count2);
43855
+ if (count2 > 0) {
43442
43856
  let address = buffer;
43443
- for (let i2 = 0; i2 < count; i2++) {
43857
+ for (let i2 = 0; i2 < count2; i2++) {
43444
43858
  this._children[i2] = unmarshalNode(this.tree, address);
43445
43859
  address += SIZE_OF_NODE;
43446
43860
  }
@@ -43458,12 +43872,12 @@ var init_web_tree_sitter = __esm({
43458
43872
  if (!this._namedChildren) {
43459
43873
  marshalNode(this);
43460
43874
  C._ts_node_named_children_wasm(this.tree[0]);
43461
- const count = C.getValue(TRANSFER_BUFFER, "i32");
43875
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43462
43876
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43463
- this._namedChildren = new Array(count);
43464
- if (count > 0) {
43877
+ this._namedChildren = new Array(count2);
43878
+ if (count2 > 0) {
43465
43879
  let address = buffer;
43466
- for (let i2 = 0; i2 < count; i2++) {
43880
+ for (let i2 = 0; i2 < count2; i2++) {
43467
43881
  this._namedChildren[i2] = unmarshalNode(this.tree, address);
43468
43882
  address += SIZE_OF_NODE;
43469
43883
  }
@@ -43826,12 +44240,12 @@ var init_web_tree_sitter = __esm({
43826
44240
  */
43827
44241
  get supertypes() {
43828
44242
  C._ts_language_supertypes_wasm(this[0]);
43829
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44243
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43830
44244
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43831
- const result = new Array(count);
43832
- if (count > 0) {
44245
+ const result = new Array(count2);
44246
+ if (count2 > 0) {
43833
44247
  let address = buffer;
43834
- for (let i2 = 0; i2 < count; i2++) {
44248
+ for (let i2 = 0; i2 < count2; i2++) {
43835
44249
  result[i2] = C.getValue(address, "i16");
43836
44250
  address += SIZE_OF_SHORT;
43837
44251
  }
@@ -43843,12 +44257,12 @@ var init_web_tree_sitter = __esm({
43843
44257
  */
43844
44258
  subtypes(supertype) {
43845
44259
  C._ts_language_subtypes_wasm(this[0], supertype);
43846
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44260
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
43847
44261
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
43848
- const result = new Array(count);
43849
- if (count > 0) {
44262
+ const result = new Array(count2);
44263
+ if (count2 > 0) {
43850
44264
  let address = buffer;
43851
- for (let i2 = 0; i2 < count; i2++) {
44265
+ for (let i2 = 0; i2 < count2; i2++) {
43852
44266
  result[i2] = C.getValue(address, "i16");
43853
44267
  address += SIZE_OF_SHORT;
43854
44268
  }
@@ -44087,12 +44501,12 @@ ${JSON.stringify(symbolNames, null, 2)}`);
44087
44501
  /** Get the ranges of text that the parser will include when parsing. */
44088
44502
  getIncludedRanges() {
44089
44503
  C._ts_parser_included_ranges_wasm(this[0]);
44090
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44504
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
44091
44505
  const buffer = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
44092
- const result = new Array(count);
44093
- if (count > 0) {
44506
+ const result = new Array(count2);
44507
+ if (count2 > 0) {
44094
44508
  let address = buffer;
44095
- for (let i2 = 0; i2 < count; i2++) {
44509
+ for (let i2 = 0; i2 < count2; i2++) {
44096
44510
  result[i2] = unmarshalRange(address);
44097
44511
  address += SIZE_OF_RANGE;
44098
44512
  }
@@ -44482,14 +44896,14 @@ ${JSON.stringify(symbolNames, null, 2)}`);
44482
44896
  matchLimit,
44483
44897
  maxStartDepth
44484
44898
  );
44485
- const count = C.getValue(TRANSFER_BUFFER, "i32");
44899
+ const count2 = C.getValue(TRANSFER_BUFFER, "i32");
44486
44900
  const startAddress = C.getValue(TRANSFER_BUFFER + SIZE_OF_INT, "i32");
44487
44901
  const didExceedMatchLimit = C.getValue(TRANSFER_BUFFER + 2 * SIZE_OF_INT, "i32");
44488
44902
  const result = new Array();
44489
44903
  this.exceededMatchLimit = Boolean(didExceedMatchLimit);
44490
44904
  const captures = new Array();
44491
44905
  let address = startAddress;
44492
- for (let i2 = 0; i2 < count; i2++) {
44906
+ for (let i2 = 0; i2 < count2; i2++) {
44493
44907
  const patternIndex = C.getValue(address, "i32");
44494
44908
  address += SIZE_OF_INT;
44495
44909
  const captureCount = C.getValue(address, "i32");
@@ -47728,9 +48142,9 @@ function standingStrandedCount(store) {
47728
48142
  const byFile = { ...last.byFile };
47729
48143
  for (const f of changed) delete byFile[f];
47730
48144
  for (const s of store.strandedSymbolsForFiles(changed)) byFile[s.fileId] = (byFile[s.fileId] ?? 0) + 1;
47731
- const count = Object.values(byFile).reduce((a, b) => a + b, 0);
47732
- store.setMeta?.(STRANDED_KEY, JSON.stringify({ seq, count, byFile }));
47733
- 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;
47734
48148
  } catch {
47735
48149
  return null;
47736
48150
  }
@@ -47959,20 +48373,14 @@ function takeDiscriminatorNudge(path3) {
47959
48373
  shared.close();
47960
48374
  }
47961
48375
  }
47962
- function hitState(n) {
47963
- const reasons = n.attrs["refuteReasons"];
47964
- if (n.attrs["resolutionSuspect"] === true && n.attrs["resolvedAt"] != null) {
47965
- return { state: "regression-suspect", factor: RG_SUSPECT_BOOST };
47966
- }
47967
- if (n.attrs["refutedAt"] != null) {
47968
- return { state: "refuted", ...reasons?.[0] ? { refutedWhy: reasons[0] } : {}, factor: RG_REFUTED_DAMP };
47969
- }
47970
- if (n.attrs["reopenedFrom"] === "regression") {
47971
- return { state: "reopened-regression", factor: RG_SUSPECT_BOOST };
47972
- }
47973
- if (n.attrs["resolvedAt"] != null && n.attrs["resolvedAs"] == null) {
47974
- return { state: "resolved", factor: 1 };
47975
- }
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 };
47976
48384
  return { factor: 1 };
47977
48385
  }
47978
48386
  function commentAnchorId(store, commentId) {
@@ -48015,7 +48423,8 @@ function toSearchHit(node2, via, rg) {
48015
48423
  pageRank: node2.pageRank,
48016
48424
  ...via ? { via } : {},
48017
48425
  ...rg.state ? { state: rg.state } : {},
48018
- ...rg.refutedWhy ? { refutedWhy: rg.refutedWhy } : {}
48426
+ ...rg.refutedWhy ? { refutedWhy: rg.refutedWhy } : {},
48427
+ ...rg.supersededBy?.length ? { supersededBy: rg.supersededBy } : {}
48019
48428
  };
48020
48429
  }
48021
48430
  function textMatches(store, query) {
@@ -48077,7 +48486,7 @@ function textMatches(store, query) {
48077
48486
  }
48078
48487
  add(node2, matched, coverageOf(node2.id));
48079
48488
  }
48080
- return [...merged.values()].map((e) => ({ ...e, rg: hitState(e.node) })).sort(
48489
+ return [...merged.values()].map((e) => ({ ...e, rg: hitState(store, e.node) })).sort(
48081
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
48082
48491
  ).map(({ node: node2, via, rg, coverage, matched }) => ({ node: node2, via, rg, coverage, matched }));
48083
48492
  }
@@ -48156,7 +48565,7 @@ function searchGraphWalk(store, query, limit) {
48156
48565
  return ranked.map((r) => {
48157
48566
  const m = byId.get(r.id);
48158
48567
  if (m) return { ...toSearchHit(m.node, m.via, m.rg), score: r.score, matched: true };
48159
- const rg = hitState(r.node);
48568
+ const rg = hitState(store, r.node);
48160
48569
  return {
48161
48570
  ...toSearchHit(r.node, void 0, rg),
48162
48571
  score: r.score,
@@ -48519,9 +48928,11 @@ var init_mcp = __esm({
48519
48928
  init_identity2();
48520
48929
  init_registry();
48521
48930
  init_dual_augment();
48931
+ init_one_search();
48522
48932
  init_dual_burst();
48523
48933
  init_twin_index();
48524
48934
  init_src5();
48935
+ init_src3();
48525
48936
  init_src2();
48526
48937
  init_src8();
48527
48938
  init_dual_burst();
@@ -48586,7 +48997,7 @@ var init_mcp = __esm({
48586
48997
  },
48587
48998
  {
48588
48999
  name: "errata.search",
48589
- description: "Find a symbol, string, comment, or the knowledge around them, as a GRAPH search. The query's words pick entry points \u2014 a symbol an identifier names, knowledge carrying the query's words (a literal phrase counts most), the strongest code matches \u2014 and one walk from all of them ranks what sits at their centre, so a Problem anchored on the function you named surfaces without repeating your words. Knowledge and code alternate down the list. Each hit carries `matched` (true = the text matched; false = the walk reached it, with `reachedVia` {edgeType, from}), `score`, and `links` \u2014 its edges to the OTHER hits in this answer, so a Problem \u2014CAUSED_BY\u2192 RootCause or a fix \u2014ANCHORED_AT\u2192 the function reads as a chain. Word order and punctuation don't matter. A comment that documents a symbol resolves to that SYMBOL (the comment rides along as `via` \u2014 it's the why, not the destination); test scaffolding and floating comments sort below production code. When the collective is reachable, results BLEND cross-project knowledge, each tagged `provenance` (local | collective | corroborated) with `usageCount`.",
49000
+ description: "Find a symbol, string, comment, or the knowledge around them, as a GRAPH search. The query's words pick entry points \u2014 a symbol an identifier names, knowledge carrying the query's words (a literal phrase counts most), the strongest code matches \u2014 and one walk from all of them ranks what sits at their centre, so a Problem anchored on the function you named surfaces without repeating your words. Knowledge and code alternate down the list. Each hit carries `matched` (true = the text matched; false = the walk reached it, with `reachedVia` {edgeType, from}), `score`, and `links` \u2014 its edges to the OTHER hits in this answer, so a Problem \u2014CAUSED_BY\u2192 RootCause or a fix \u2014ANCHORED_AT\u2192 the function reads as a chain. Word order and punctuation don't matter. A comment that documents a symbol resolves to that SYMBOL (the comment rides along as `via` \u2014 it's the why, not the destination); test scaffolding and floating comments sort below production code. When the collective is reachable, results BLEND cross-project knowledge, each tagged `provenance` (local | collective | corroborated) with `usageCount`. Local and Network hits are ranked by one formula \u2014 relevance \xD7 evidence \u2014 and each knowledge hit's `why` shows its relevance and reliability. Judge a hit you relied on or ruled out by its `cite`: (confirm:<cite>) or (refute:<cite> why).",
48590
49001
  inputSchema: {
48591
49002
  type: "object",
48592
49003
  properties: {
@@ -48598,12 +49009,20 @@ var init_mcp = __esm({
48598
49009
  handler: async (args2, store, ctx) => {
48599
49010
  const query = String(args2["query"] ?? "");
48600
49011
  const limit = Math.max(1, Math.min(100, Number(args2["limit"] ?? 20)));
48601
- const hits = withLinks(
48602
- store,
48603
- searchWalkEnabled() ? searchGraphWalk(store, query, limit) : searchGraph(store, query, limit).map((h) => ({ ...h, score: h.pageRank, matched: true }))
48604
- );
49012
+ const pool = searchWalkEnabled() ? searchGraphWalk(store, query, limit * 2) : searchGraph(store, query, limit * 2).map((h) => ({ ...h, score: h.pageRank, matched: true }));
49013
+ const viaText = new Map(pool.flatMap((h) => h.via?.text ? [[h.id, h.via.text]] : []));
49014
+ const parentOf = new Map(pool.flatMap((h) => {
49015
+ const from = h.reachedVia?.from;
49016
+ return from ? [[h.id, from]] : [];
49017
+ }));
49018
+ const isKnowledge = (label) => KNOWLEDGE_LABELS.has(label);
49019
+ const rankLocal = async () => interleaveLanes(
49020
+ await rankHits(store, query, pool.map((h) => ({ ...h, name: h.description, ...h.via?.text ? { viaText: h.via.text } : {}, ...parentOf.has(h.id) ? { parentId: parentOf.get(h.id) } : {}, hops: h.matched ? 0 : 1 }))),
49021
+ isKnowledge,
49022
+ limit
49023
+ ).map(({ rank, ...h }) => ({ ...h, why: rankWhy(rank), ...isKnowledge(h.label) ? { cite: h.id } : {} }));
48605
49024
  if (ctx.cloud && query.trim()) {
48606
- const localHits = hits.map((h) => ({
49025
+ const localHits = pool.map((h) => ({
48607
49026
  id: h.id,
48608
49027
  node: { label: h.label, description: h.description },
48609
49028
  score: h.score,
@@ -48615,30 +49034,45 @@ var init_mcp = __esm({
48615
49034
  ...ctx.generalizeSoft ? { generalizeSoft: ctx.generalizeSoft } : {},
48616
49035
  localHits,
48617
49036
  queryText: query,
48618
- limit,
48619
- fuse: "rank"
49037
+ limit
48620
49038
  });
48621
49039
  if (dual.status === "merged") {
49040
+ const ranked = await rankHits(
49041
+ store,
49042
+ query,
49043
+ dual.merged.nodes.map((n) => ({
49044
+ ...n,
49045
+ ...viaText.has(n.id) ? { viaText: viaText.get(n.id) } : {},
49046
+ ...parentOf.get(n.id) ?? n.via?.parentId ? { parentId: parentOf.get(n.id) ?? n.via?.parentId } : {},
49047
+ // A Network entry matched the query; a node it reached by walking carries `via`.
49048
+ hops: n.provenance === "collective" ? n.via ? 1 : 0 : n.hops
49049
+ })),
49050
+ { cloudEvidence: dual.cloudEvidence }
49051
+ );
49052
+ const chosen = interleaveLanes(ranked, isKnowledge, limit);
49053
+ const why = new Map(chosen.map((n) => [n.id, rankWhy(n.rank)]));
49054
+ const formatted = formatDualNodes({ ...dual.merged, nodes: chosen.map(({ rank: _rank, viaText: _via, ...n }) => n) });
48622
49055
  return {
48623
49056
  query,
48624
49057
  collectiveReachable: true,
48625
49058
  collectiveStatus: "merged",
48626
- count: dual.merged.nodes.length,
49059
+ count: formatted.length,
48627
49060
  corroborated: dual.merged.corroboratedCount,
48628
49061
  collective: dual.merged.collectiveCount,
48629
- results: withLinks(store, formatDualNodes(dual.merged))
49062
+ results: withLinks(store, withCite(formatted.map((r) => ({ ...r, why: why.get(String(r["id"])) })), isKnowledge))
48630
49063
  };
48631
49064
  }
49065
+ const local = withLinks(store, await rankLocal());
48632
49066
  return {
48633
49067
  query,
48634
49068
  collectiveReachable: dual.status === "empty",
48635
49069
  collectiveStatus: dual.status,
48636
49070
  ...federationHint(dual.status) ? { collectiveHint: federationHint(dual.status) } : {},
48637
- count: hits.length,
48638
- results: hits
49071
+ count: local.length,
49072
+ results: local
48639
49073
  };
48640
49074
  }
48641
- return hits;
49075
+ return withLinks(store, await rankLocal());
48642
49076
  }
48643
49077
  },
48644
49078
  {
@@ -48816,6 +49250,8 @@ var init_mcp = __esm({
48816
49250
  limit: args2["limit"] != null ? Number(args2["limit"]) : 20
48817
49251
  });
48818
49252
  if (dual.status === "merged") {
49253
+ const nodes = await rankDualNodes(store, seedQuery(seedNode?.description ?? id), dual.merged.nodes, dual.cloudEvidence);
49254
+ const why = new Map(nodes.map((n) => [n.id, n.why]));
48819
49255
  return {
48820
49256
  seed: id,
48821
49257
  ...seedTwinFields(args2, seedNode),
@@ -48823,14 +49259,17 @@ var init_mcp = __esm({
48823
49259
  ...dual.seedUsageCount != null ? { seedUsageCount: dual.seedUsageCount } : {},
48824
49260
  collectiveReachable: true,
48825
49261
  collectiveStatus: "merged",
48826
- count: dual.merged.nodes.length,
49262
+ count: nodes.length,
48827
49263
  corroborated: dual.merged.corroboratedCount,
48828
49264
  collective: dual.merged.collectiveCount,
48829
- results: formatDualNodes(dual.merged)
49265
+ results: withCite(formatDualNodes({ ...dual.merged, nodes }).map((r) => ({ ...r, why: why.get(String(r["id"])) })), (l) => KNOWLEDGE_LABELS.has(l))
48830
49266
  };
48831
49267
  }
48832
49268
  collectiveStatus = dual.status;
48833
49269
  }
49270
+ const localOnly = mergeDualBurst(localHits, [], { twins: storeTwinIndex(store, []), seedId: id });
49271
+ const localNodes = await rankDualNodes(store, seedQuery(seedNode?.description ?? id), localOnly.nodes);
49272
+ const localWhy = new Map(localNodes.map((n) => [n.id, n.why]));
48834
49273
  return {
48835
49274
  seed: id,
48836
49275
  ...seedTwinFields(args2, seedNode),
@@ -48838,12 +49277,8 @@ var init_mcp = __esm({
48838
49277
  collectiveReachable: collectiveStatus === "empty",
48839
49278
  collectiveStatus,
48840
49279
  ...federationHint(collectiveStatus) ? { collectiveHint: federationHint(collectiveStatus) } : {},
48841
- // Same twin fold as the merged path: a hydrated in-store copy of a hit
48842
- // (or of the seed) is not a second entity.
48843
- ...(() => {
48844
- const localOnly = mergeDualBurst(localHits, [], { twins: storeTwinIndex(store, []), seedId: id });
48845
- return { count: localOnly.nodes.length, results: formatDualNodes(localOnly) };
48846
- })()
49280
+ count: localNodes.length,
49281
+ results: withCite(formatDualNodes({ ...localOnly, nodes: localNodes }).map((r) => ({ ...r, why: localWhy.get(String(r["id"])) })), (l) => KNOWLEDGE_LABELS.has(l))
48847
49282
  };
48848
49283
  }
48849
49284
  },
@@ -49232,22 +49667,22 @@ var init_mcp = __esm({
49232
49667
  const orderCol = byRank ? "page_rank" : "created_at";
49233
49668
  const sqlSince = since && Number.isFinite(since);
49234
49669
  let nodes;
49235
- let count;
49670
+ let count2;
49236
49671
  if (!like && (!since || sqlSince)) {
49237
49672
  const where = sqlSince ? [{ column: "created_at", gte: since }] : [];
49238
49673
  const q = { labels: [label], where };
49239
- count = store.countNodes(q);
49674
+ count2 = store.countNodes(q);
49240
49675
  nodes = store.selectNodes({ ...q, orderBy: { column: orderCol, desc: true }, limit: sliceEnd(limit) });
49241
49676
  } else {
49242
49677
  nodes = store.selectNodes({ labels: [label] });
49243
49678
  if (like) nodes = nodes.filter((n) => n.description.toLowerCase().includes(like));
49244
49679
  if (since) nodes = nodes.filter((n) => n.createdAt >= since);
49245
49680
  nodes.sort((a, b) => byRank ? b.pageRank - a.pageRank : b.createdAt - a.createdAt);
49246
- count = nodes.length;
49681
+ count2 = nodes.length;
49247
49682
  }
49248
49683
  return {
49249
49684
  label,
49250
- count,
49685
+ count: count2,
49251
49686
  items: nodes.slice(0, limit).map((n) => ({
49252
49687
  id: n.id,
49253
49688
  label: n.label,
@@ -49350,11 +49785,11 @@ var init_mcp = __esm({
49350
49785
  for (const label of labels) {
49351
49786
  const col = isCodeLabel(label) ? "last_updated_at" : "created_at";
49352
49787
  const q = { labels: [label], where: [{ column: col, gte: since }] };
49353
- const count = store.countNodes(q);
49354
- if (count === 0) continue;
49355
- total += count;
49788
+ const count2 = store.countNodes(q);
49789
+ if (count2 === 0) continue;
49790
+ total += count2;
49356
49791
  groups[label] = {
49357
- count,
49792
+ count: count2,
49358
49793
  items: store.selectNodes({
49359
49794
  ...q,
49360
49795
  orderBy: { column: col, desc: true },
@@ -49436,24 +49871,27 @@ var init_mcp = __esm({
49436
49871
  limit
49437
49872
  });
49438
49873
  if (dual.status === "merged") {
49874
+ const nodes = (await rankDualNodes(store, seedQuery(node2.description), dual.merged.nodes, dual.cloudEvidence)).slice(0, limit);
49875
+ const why = new Map(nodes.map((n) => [n.id, n.why]));
49439
49876
  return {
49440
49877
  seedId: id,
49441
49878
  collectiveReachable: true,
49442
49879
  collectiveStatus: "merged",
49443
- count: dual.merged.nodes.length,
49880
+ count: nodes.length,
49444
49881
  corroborated: dual.merged.corroboratedCount,
49445
49882
  collective: dual.merged.collectiveCount,
49446
- results: formatDualNodes(dual.merged)
49883
+ results: withCite(formatDualNodes({ ...dual.merged, nodes }).map((r) => ({ ...r, why: why.get(String(r["id"])) })), (l) => KNOWLEDGE_LABELS.has(l))
49447
49884
  };
49448
49885
  }
49449
49886
  return {
49450
49887
  ...local,
49888
+ hits: await rankSimilarLocal(store, node2.description, local.hits ?? []),
49451
49889
  collectiveReachable: dual.status === "empty",
49452
49890
  collectiveStatus: dual.status,
49453
49891
  ...federationHint(dual.status) ? { collectiveHint: federationHint(dual.status) } : {}
49454
49892
  };
49455
49893
  }
49456
- return local;
49894
+ return { ...local, hits: await rankSimilarLocal(store, node2.description, local.hits ?? []) };
49457
49895
  }
49458
49896
  },
49459
49897
  {
@@ -57742,7 +58180,8 @@ __export(webui_exports, {
57742
58180
  findFileByPath: () => findFileByPath,
57743
58181
  hookAudience: () => hookAudience,
57744
58182
  recallForFile: () => recallForFile,
57745
- recallForTool: () => recallForTool
58183
+ recallForTool: () => recallForTool,
58184
+ shownFixes: () => shownFixes
57746
58185
  });
57747
58186
  function accumulateMessageDelta(messageId, index, delta, isFinal, nowMs) {
57748
58187
  return messageAccumulator.accumulate(messageId, index, delta, isFinal, nowMs);
@@ -58207,6 +58646,13 @@ function buildWebUi(deps) {
58207
58646
  }
58208
58647
  if (failed) recall = recallForError(deps.store, stderr || combined);
58209
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
+ }
58210
58656
  if (event === "PostToolUse" && tool && tool !== "Bash" && deps.onToolError) {
58211
58657
  const rawResp = body2["tool_response"];
58212
58658
  const respObj = rawResp && typeof rawResp === "object" ? rawResp : {};
@@ -58652,6 +59098,41 @@ function proposalToIngest(p, profile, daemonVersion) {
58652
59098
  payloadDigest: p.id
58653
59099
  };
58654
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
+ }
58655
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;
58656
59137
  var init_webui = __esm({
58657
59138
  "src/webui.ts"() {
@@ -69873,11 +70354,11 @@ var require_pluralizer = __commonJS({
69873
70354
  this.singular = singular;
69874
70355
  this.plural = plural2;
69875
70356
  }
69876
- pluralize(count) {
69877
- const one = count === 1;
70357
+ pluralize(count2) {
70358
+ const one = count2 === 1;
69878
70359
  const keys = one ? singulars : plurals;
69879
70360
  const noun = one ? this.singular : this.plural;
69880
- return { ...keys, count, noun };
70361
+ return { ...keys, count: count2, noun };
69881
70362
  }
69882
70363
  };
69883
70364
  }
@@ -80194,12 +80675,12 @@ var FSWatcher = class extends EventEmitter {
80194
80675
  let timeoutObject;
80195
80676
  const clear = () => {
80196
80677
  const item2 = action.get(path3);
80197
- const count = item2 ? item2.count : 0;
80678
+ const count2 = item2 ? item2.count : 0;
80198
80679
  action.delete(path3);
80199
80680
  clearTimeout(timeoutObject);
80200
80681
  if (item2)
80201
80682
  clearTimeout(item2.timeoutObject);
80202
- return count;
80683
+ return count2;
80203
80684
  };
80204
80685
  timeoutObject = setTimeout(clear, timeout);
80205
80686
  const thr = { timeoutObject, clear, count: 0 };
@@ -81771,7 +82252,10 @@ var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
81771
82252
  var HANDLE_RE2 = new RegExp(TAG_HANDLE_SOURCE, "gi");
81772
82253
  var PLACEHOLDER_HANDLES = TAG_PLACEHOLDER_HANDLES;
81773
82254
  var isPlaceholderHandle = (h) => PLACEHOLDER_HANDLES.has(h.toLowerCase());
81774
- var FLAG_BODY_HANDLE_RE = /^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:pat|sol|drc|dcause|dfix|dprob|dvuln|prob|claim|err)_[0-9a-f]{6,})$/i;
82255
+ var FLAG_BODY_HANDLE_RE = new RegExp(
82256
+ String.raw`^(?:[a-z0-9]+(?:-[a-z0-9]+){2,}-(?=[0-9a-f]{0,3}\d)[0-9a-f]{4}|(?:${TAG_CANONICAL_ID_PREFIXES.join("|")})_[0-9a-f]{6,})$`,
82257
+ "i"
82258
+ );
81775
82259
  var FIX_PREFIX = /^\s*fix:(?:#([a-z][\w-]{0,63}))?\s*/i;
81776
82260
  var CAUSE_PREFIX = /^\s*cause:(?:#([a-z][\w-]{0,63}))?\s*/i;
81777
82261
  var NEST2_UNIT = String.raw`(?:[^()\n]|\((?:[^()\n]|\([^()\n]*\))*\))`;
@@ -82541,6 +83025,32 @@ function applyLocalRefutations(store, refutes, ts) {
82541
83025
  }
82542
83026
  return out2;
82543
83027
  }
83028
+ function applyLocalConfirmations(store, confirms, ts) {
83029
+ const out2 = { stamped: 0, duplicate: 0, unknownNode: 0 };
83030
+ for (const c of confirms) {
83031
+ const node2 = store.getNode(c.nodeId);
83032
+ if (!node2) {
83033
+ out2.unknownNode++;
83034
+ continue;
83035
+ }
83036
+ const keys = node2.attrs["confirmWitnessKeys"] ?? [];
83037
+ if (keys.includes(c.witnessKey)) {
83038
+ out2.duplicate++;
83039
+ continue;
83040
+ }
83041
+ store.updateNode(c.nodeId, {
83042
+ attrs: {
83043
+ ...node2.attrs,
83044
+ confirmedAt: ts,
83045
+ confirmations: (Number(node2.attrs["confirmations"]) || 0) + 1,
83046
+ confirmWitnessKeys: [...keys, c.witnessKey].slice(-REFUTE_WITNESS_KEYS_CAP)
83047
+ },
83048
+ lastUpdatedAt: ts
83049
+ });
83050
+ out2.stamped++;
83051
+ }
83052
+ return out2;
83053
+ }
82544
83054
  var PRIOR_TAG_INSTRUCTION = buildAgentInstruction();
82545
83055
  function isEdgeElicitationEnabled() {
82546
83056
  return (process.env["EDGE_ELICITATION_ENABLED"] ?? "true").toLowerCase() !== "false";
@@ -82576,8 +83086,15 @@ function readPrimingHandles(path3) {
82576
83086
  return {};
82577
83087
  }
82578
83088
  }
83089
+ var BARE_KNOWLEDGE_ID_RE = new RegExp(
83090
+ String.raw`^(?:${TAG_CANONICAL_ID_PREFIXES.filter((p) => p !== "dom").join("|")})_[0-9a-f]{6,}$`,
83091
+ "i"
83092
+ );
83093
+ function isCloudBornKnowledgeId(store, id) {
83094
+ return !store.getNode(id) && BARE_KNOWLEDGE_ID_RE.test(id);
83095
+ }
82579
83096
  function resolveHandle(store, handle2, handleMap) {
82580
- return handleMap[handle2]?.id ?? (store.getNode(handle2) ? handle2 : void 0);
83097
+ return handleMap[handle2]?.id ?? (store.getNode(handle2) || BARE_KNOWLEDGE_ID_RE.test(handle2) ? handle2 : void 0);
82581
83098
  }
82582
83099
  var CITE_ANCHOR_LABELS = /* @__PURE__ */ new Set(["Problem", "Solution", "RootCause", "Pattern", "Claim", "Technique", "AntiPattern"]);
82583
83100
  var CITE_ANCHOR_PROMOTE_SESSIONS = 2;
@@ -82897,7 +83414,7 @@ function harvestInlineTags(store, text, opts) {
82897
83414
  const targetId = resolveCited(tag.kind, tag.handle);
82898
83415
  const target = targetId ? store.getNode(targetId) : null;
82899
83416
  const citedLabel = target?.label ?? opts.handleMap[tag.handle]?.label;
82900
- if (targetId && citedLabel && CORROBORATABLE_LABELS.has(citedLabel)) {
83417
+ if (targetId && (citedLabel ? CORROBORATABLE_LABELS.has(citedLabel) : isCloudBornKnowledgeId(store, targetId))) {
82901
83418
  if (tag.kind === "confirm") {
82902
83419
  const witnessKey = `corrob:${targetId}:confirm:${digest({ h: tag.handle })}`.slice(0, 72);
82903
83420
  if (!plan.corroborations.some((c) => c.witnessKey === witnessKey)) {
@@ -82917,7 +83434,7 @@ function harvestInlineTags(store, text, opts) {
82917
83434
  const targetId = resolveCited("prior", tag.handle);
82918
83435
  const target = targetId ? store.getNode(targetId) : null;
82919
83436
  const citedLabel = target?.label ?? opts.handleMap[tag.handle]?.label;
82920
- if (targetId && citedLabel && CORROBORATABLE_LABELS.has(citedLabel)) {
83437
+ if (targetId && (citedLabel ? CORROBORATABLE_LABELS.has(citedLabel) : isCloudBornKnowledgeId(store, targetId))) {
82921
83438
  const witnessKey = `corrob:${targetId}:lean:${digest({ h: tag.handle })}`.slice(0, 72);
82922
83439
  if (!plan.corroborations.some((c) => c.witnessKey === witnessKey)) {
82923
83440
  const exposure = typeof store.currentIngestSeq === "function" ? priorExposure(store, targetId, { seq: store.currentIngestSeq(), ts: opts.ts }) : "unshown";
@@ -82972,6 +83489,112 @@ function stampWitnessOrigin(items, origin) {
82972
83489
  return items.map((i2) => ({ ...i2, witnessKey: `${i2.witnessKey}:o:${o}` }));
82973
83490
  }
82974
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
+
82975
83598
  // src/rollup.ts
82976
83599
  function readConversation(transcriptPath, includeThinking = true, maxChars = 6e4) {
82977
83600
  const raw2 = readTail(transcriptPath, 4e6);
@@ -87113,12 +87736,12 @@ function maybeFlushDigests() {
87113
87736
  try {
87114
87737
  if (process.env["ERRATA_NO_NOTIFY"] || !loadConfig().notifications) return;
87115
87738
  const now = Date.now();
87116
- for (const [kind, count] of digestCounts) {
87117
- if (count <= 0) continue;
87739
+ for (const [kind, count2] of digestCounts) {
87740
+ if (count2 <= 0) continue;
87118
87741
  if (now - (digestWindowStart.get(kind) ?? now) < DIGEST_INTERVAL_MS) continue;
87119
87742
  digestWindowStart.set(kind, now);
87120
87743
  digestCounts.set(kind, 0);
87121
- 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.`);
87122
87745
  }
87123
87746
  } catch {
87124
87747
  }
@@ -87219,8 +87842,8 @@ var noteBreakerQuarantine = (path3) => {
87219
87842
  census.breakerQuarantined.push(path3);
87220
87843
  }
87221
87844
  };
87222
- var noteWindowOffender = (path3, count, windowMs) => {
87223
- 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() };
87224
87847
  };
87225
87848
  function watchCensus() {
87226
87849
  return { ...census };
@@ -87527,7 +88150,7 @@ function createWatchBreaker(deps) {
87527
88150
  }
87528
88151
 
87529
88152
  // src/engine.ts
87530
- var DAEMON_VERSION = true ? "2.0.23-dev.4803" : "2.0.0-alpha.0";
88153
+ var DAEMON_VERSION = true ? "2.0.23-dev.4826" : "2.0.0-alpha.0";
87531
88154
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
87532
88155
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
87533
88156
  var GIT_OP_MUTE_MS = 4e3;
@@ -87969,6 +88592,7 @@ function createWorkspaceEngine(opts) {
87969
88592
  const sessions = createSessionRegistry({ originsPath: join37(paths.configDir, "session-origins.json") });
87970
88593
  const sessionRenders = /* @__PURE__ */ new Map();
87971
88594
  const selfCiteSkipsBySession = /* @__PURE__ */ new Map();
88595
+ const supersessionAsks = new SupersessionAsks();
87972
88596
  const toolRuns = createToolRunState();
87973
88597
  let ctxRefreshTimer = null;
87974
88598
  let contextDirty = false;
@@ -88039,6 +88663,15 @@ function createWorkspaceEngine(opts) {
88039
88663
  }
88040
88664
  return signal;
88041
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
+ });
88042
88675
  const statedIntentFor = (intent) => {
88043
88676
  const collective = intentRemote?.forIntent === intent ? intentRemote : null;
88044
88677
  return {
@@ -88048,7 +88681,8 @@ function createWorkspaceEngine(opts) {
88048
88681
  label: h.node.label,
88049
88682
  description: h.node.description,
88050
88683
  coverage: h.coverage,
88051
- ...isVerdictable(h.node) ? { verdict: closableByCaller(h.node) ? "own" : "foreign" } : {}
88684
+ ...isVerdictable(h.node) ? { verdict: closableByCaller(h.node) ? "own" : "foreign" } : {},
88685
+ ...lifecycleField(h.node)
88052
88686
  })),
88053
88687
  ...collective && collective.hits.length > 0 ? {
88054
88688
  remoteHits: collective.hits.slice(0, 4).map((n) => ({ id: n.id, label: n.label, description: n.description }))
@@ -88501,6 +89135,7 @@ function createWorkspaceEngine(opts) {
88501
89135
  const workingFile = workingFiles.get(sessionId);
88502
89136
  const skips = selfCiteSkipsBySession.get(sessionId) ?? 0;
88503
89137
  const key = JSON.stringify([
89138
+ supersessionAsks.version(sessionId),
88504
89139
  subagentBaseVersion,
88505
89140
  lastRemoteAt,
88506
89141
  sessions.version(now),
@@ -88521,6 +89156,9 @@ function createWorkspaceEngine(opts) {
88521
89156
  }
88522
89157
  delete scoped.selfCiteSkips;
88523
89158
  if (skips > 0) scoped.selfCiteSkips = skips;
89159
+ delete scoped.supersessionAsks;
89160
+ const asks = supersessionAsksFor(sessionId);
89161
+ if (asks.length > 0) scoped.supersessionAsks = asks;
88524
89162
  const pendingUpdate = opts.pendingUpdate?.() ?? null;
88525
89163
  const daemonDistress = opts.daemonDistress?.() ?? null;
88526
89164
  const reviewItems = pickReviewItems();
@@ -88650,6 +89288,9 @@ function createWorkspaceEngine(opts) {
88650
89288
  let exposureRecent = 0;
88651
89289
  let corroboratedEdges = 0;
88652
89290
  let refutesStamped = 0;
89291
+ let confirmsStamped = 0;
89292
+ let supersessionAsked = 0;
89293
+ let structureLinksMinted = 0;
88653
89294
  let recurrencesMarked = 0;
88654
89295
  let reopenedFromRegression = 0;
88655
89296
  let fixHeldConfirmed = 0;
@@ -88770,7 +89411,7 @@ function createWorkspaceEngine(opts) {
88770
89411
  for (const r of parseDesignResolutions(turn.text)) {
88771
89412
  try {
88772
89413
  const retractAs = r.disposition === "false_positive" || r.disposition === "invalid" ? r.disposition : null;
88773
- 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);
88774
89415
  if (closed) {
88775
89416
  resolved++;
88776
89417
  if (!retractAs) {
@@ -88838,6 +89479,14 @@ function createWorkspaceEngine(opts) {
88838
89479
  citeAnchorsPromoted += plan.citeAnchorsPromoted;
88839
89480
  const refuteResult = applyLocalRefutations(store, plan.refutes, t);
88840
89481
  refutesStamped += refuteResult.stamped;
89482
+ if (sessions.originOf(sessionId) === void 0) {
89483
+ const confirmResult = applyLocalConfirmations(
89484
+ store,
89485
+ plan.corroborations.filter((c) => store.getNode(c.nodeId)?.attrs["sources"]?.[0] !== sessionId),
89486
+ t
89487
+ );
89488
+ confirmsStamped += confirmResult.stamped;
89489
+ }
88841
89490
  for (const c of plan.corroborations) {
88842
89491
  const node2 = store.getNode(c.nodeId);
88843
89492
  if (node2?.label !== "Solution") continue;
@@ -89090,7 +89739,7 @@ function createWorkspaceEngine(opts) {
89090
89739
  }
89091
89740
  continue;
89092
89741
  }
89093
- const closed = resolveDesignProblemById(store, pid, fx.fixNote, t);
89742
+ const closed = resolveDesignProblemById(store, pid, fx.fixNote, t, sessionId);
89094
89743
  if (!closed) {
89095
89744
  const n = store.getNode(pid);
89096
89745
  if (n && n.attrs["resolvedAt"] == null && !closableByCaller(n)) {
@@ -89103,6 +89752,22 @@ function createWorkspaceEngine(opts) {
89103
89752
  );
89104
89753
  }
89105
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
+ }
89106
89771
  if (closed) {
89107
89772
  resolved++;
89108
89773
  const fxAnchor = editedTurnFile ?? turnFile ?? wf;
@@ -89302,8 +89967,9 @@ function createWorkspaceEngine(opts) {
89302
89967
  }
89303
89968
  }
89304
89969
  for (const sl of plan.solutionLinks) {
89305
- const pid = bindPid(sl);
89306
- 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);
89307
89973
  if (!solId) {
89308
89974
  console.warn(`[errata] ${sl.relation} tag dropped: no solution in scope \u2014 state it beside its (fix:\u2026)`);
89309
89975
  continue;
@@ -89311,10 +89977,22 @@ function createWorkspaceEngine(opts) {
89311
89977
  for (const targetId of sl.targetIds) {
89312
89978
  if (targetId === solId) continue;
89313
89979
  const target = store.getNode(targetId);
89314
- 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
+ }
89315
89984
  mintCiteEdge(solId, targetId, sl.relation, 0.4, { solutionStructure: true, hypothesis: true });
89985
+ structureLinksMinted++;
89316
89986
  }
89317
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
+ );
89318
89996
  const citingSession = sessionOriginKey(sessionId);
89319
89997
  const mintedHere = (nodeId) => store.getNode(nodeId)?.attrs["sources"]?.[0] === sessionId;
89320
89998
  const synthetic = sessions.originOf(sessionId) !== void 0;
@@ -89522,6 +90200,9 @@ function createWorkspaceEngine(opts) {
89522
90200
  // RG-mark: refute witnesses stamped onto local nodes (the local half of
89523
90201
  // the contradict channel; the wire half rides the witness ledger).
89524
90202
  refutesStamped,
90203
+ confirmsStamped,
90204
+ supersessionAsked,
90205
+ structureLinksMinted,
89525
90206
  // RG-recognize tier A: resolved problems the door saw recur this pass.
89526
90207
  recurrencesMarked,
89527
90208
  // RG-reopen: closes flipped open on the two-touch evidence bar.
@@ -89913,6 +90594,7 @@ B: ${b}`,
89913
90594
  sessionContext,
89914
90595
  onHook: () => telemetry.count("hooks_fired"),
89915
90596
  onToolsObserved: (sessionId, toolNodeIds) => toolRuns.record(sessionId, toolNodeIds),
90597
+ onKnowledgeShown: (sessionId, shown) => supersessionAsks.noteShown(sessionId, shown),
89916
90598
  onHookEvent,
89917
90599
  onShellEvent,
89918
90600
  onToolError,
@@ -90421,6 +91103,7 @@ async function startDaemon(opts) {
90421
91103
  onHookEvent: engine.webHooks.onHookEvent,
90422
91104
  onShellEvent: engine.webHooks.onShellEvent,
90423
91105
  onToolError: engine.webHooks.onToolError,
91106
+ onKnowledgeShown: engine.webHooks.onKnowledgeShown,
90424
91107
  onDiagnostics: engine.webHooks.onDiagnostics,
90425
91108
  onTurn: engine.webHooks.onTurn,
90426
91109
  onSessionEnd: engine.webHooks.onSessionEnd
@@ -90862,7 +91545,8 @@ function settleEdgeOutcomes(queue, sent, verdicts, now) {
90862
91545
 
90863
91546
  // src/instance-receipts.ts
90864
91547
  import { createHash as createHash18 } from "node:crypto";
90865
- 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"]);
90866
91550
  var INSTANCE_ANCHOR_EDGE_TYPES = ["OCCURS_IN", "DEPENDS_ON", "PERTAIN_TO", "CONCERNS"];
90867
91551
  function edgeReceiptKind(type) {
90868
91552
  if (INSTANCE_SEMANTIC_EDGE_TYPES.includes(type)) return "semantic";
@@ -90891,7 +91575,7 @@ function instanceEdgeReceipts(sent, received, cloudIds) {
90891
91575
  groups.set(group, expected);
90892
91576
  }
90893
91577
  const complete = new Set([...groups].filter(
90894
- ([, 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)
90895
91579
  ).map(([group]) => group));
90896
91580
  return { complete: (source, kind) => complete.has(groupKey(source, kind)) };
90897
91581
  }
@@ -90912,7 +91596,7 @@ function instanceCloudWithdrawal(n, destination, getMeta) {
90912
91596
  return held;
90913
91597
  }
90914
91598
  }
90915
- var FIELDS = ["cloudWithdrawn", "withdrawnAtCorrectionSeq", "contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
91599
+ var FIELDS2 = ["cloudWithdrawn", "withdrawnAtCorrectionSeq", "contributedAtSeq", "cloudNodeId", "anchorsContributedDigest", "projectAnchorsContributedDigest", "semanticEdgesContributedDigest", "shipRefusedSinceSeq", "shipRefusedCount", "shipRefusedReason", "shipRefusedFingerprint"];
90916
91600
  function instanceDestinationKey(input) {
90917
91601
  return createHash18("sha256").update(JSON.stringify([
90918
91602
  input.workspace,
@@ -90934,7 +91618,7 @@ function instanceReceipt(n, destination) {
90934
91618
  function updateInstanceReceipt(n, destination, patch, mirrorLegacy) {
90935
91619
  const receipt = { ...instanceReceipt(n, destination), ...patch };
90936
91620
  const attrs = { ...n.attrs, instanceReceipts: { ...receiptMap(n.attrs), [destination]: receipt } };
90937
- if (mirrorLegacy) for (const field of FIELDS) {
91621
+ if (mirrorLegacy) for (const field of FIELDS2) {
90938
91622
  if (field in receipt) attrs[field] = receipt[field];
90939
91623
  else delete attrs[field];
90940
91624
  }
@@ -91867,6 +92551,11 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
91867
92551
  }
91868
92552
  const edges = [];
91869
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
+ };
91870
92559
  for (const [sourceId, wireFrom] of semanticEndpoints) {
91871
92560
  const rawOuts = [
91872
92561
  ...store.outEdges(sourceId, [...INSTANCE_EDGES]),
@@ -91874,7 +92563,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
91874
92563
  ];
91875
92564
  const dedup = /* @__PURE__ */ new Map();
91876
92565
  for (const e of rawOuts) dedup.set(`${e.type}>${e.to}`, e);
91877
- 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) => {
91878
92567
  if (x.wireTo === wireFrom) {
91879
92568
  composition.collapsedEdges++;
91880
92569
  return false;
@@ -91901,7 +92590,7 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
91901
92590
  const lexicon = opts.lexicon;
91902
92591
  const isKnown = (tok) => lexicon.has(tok);
91903
92592
  const sidecar = {};
91904
- let count = 0;
92593
+ let count2 = 0;
91905
92594
  outer: for (const n of nodes) {
91906
92595
  if (!INSTANCE_LABELS.includes(n.label)) continue;
91907
92596
  for (const tok of extractIdentifierTokens(n.description)) {
@@ -91919,15 +92608,15 @@ function buildInstanceIngest(store, profile, daemonVersion, ignorePatterns = [],
91919
92608
  composition.sidecarDropReasons[dropBucket] = (composition.sidecarDropReasons[dropBucket] ?? 0) + 1;
91920
92609
  continue;
91921
92610
  }
91922
- if (count >= MAX_SIDECAR_SYMBOLS) {
92611
+ if (count2 >= MAX_SIDECAR_SYMBOLS) {
91923
92612
  composition.sidecarTruncatedAtCap = 1;
91924
92613
  break outer;
91925
92614
  }
91926
92615
  sidecar[tok] = { kind: entry.kind, summary: scrubbed };
91927
- count++;
92616
+ count2++;
91928
92617
  }
91929
92618
  }
91930
- if (count > 0) symbolSummaries = sidecar;
92619
+ if (count2 > 0) symbolSummaries = sidecar;
91931
92620
  }
91932
92621
  edges.push(...anchorEdges);
91933
92622
  if (opts.edgeHolds && Object.keys(opts.edgeHolds).length > 0) {
@@ -95163,9 +95852,9 @@ function collectRepoFacts(root) {
95163
95852
  }
95164
95853
  };
95165
95854
  const roots = git3(["rev-list", "--max-parents=0", "HEAD"]);
95166
- const count = git3(["rev-list", "--count", "HEAD"]);
95855
+ const count2 = git3(["rev-list", "--count", "HEAD"]);
95167
95856
  const rootCommitSha = roots?.split(/\s+/).filter(Boolean).pop();
95168
- const commitCount = count && /^\d+$/.test(count) ? Number(count) : void 0;
95857
+ const commitCount = count2 && /^\d+$/.test(count2) ? Number(count2) : void 0;
95169
95858
  return {
95170
95859
  ...rootCommitSha && /^[0-9a-f]{40,64}$/i.test(rootCommitSha) ? { rootCommitSha } : {},
95171
95860
  ...typeof commitCount === "number" ? { commitCount } : {}
@@ -96163,6 +96852,8 @@ async function startMultiDaemon(opts = {}) {
96163
96852
  // and dropped the record on the floor — toolSessionsTracked read 0 across
96164
96853
  // 936 turns while the log showed records landing (VS-corroboration-rate).
96165
96854
  onToolsObserved: engine.webHooks.onToolsObserved,
96855
+ // Wired on BOTH builders — the onToolsObserved lesson above.
96856
+ onKnowledgeShown: engine.webHooks.onKnowledgeShown,
96166
96857
  onToolError: engine.webHooks.onToolError,
96167
96858
  onDiagnostics: engine.webHooks.onDiagnostics,
96168
96859
  onTurn: engine.webHooks.onTurn,
@@ -97670,18 +98361,18 @@ async function startMultiDaemon(opts = {}) {
97670
98361
  if (!owner) return;
97671
98362
  const fp = refusalFingerprint(reason, owner.n.description);
97672
98363
  const same = instanceReceipt(owner.n, destinationKey)["shipRefusedFingerprint"] === fp;
97673
- 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;
97674
98365
  if (instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0) repeat();
97675
98366
  owner.s.updateNode(id, {
97676
98367
  attrs: updateInstanceReceipt(owner.n, destinationKey, {
97677
98368
  ...instanceReceipt(owner.n, destinationKey),
97678
98369
  ...same && instanceReceipt(owner.n, destinationKey)["shipRefusedSinceSeq"] !== void 0 ? {} : { shipRefusedSinceSeq: owner.s.currentIngestSeq() },
97679
- shipRefusedCount: count,
98370
+ shipRefusedCount: count2,
97680
98371
  shipRefusedReason: reason,
97681
98372
  shipRefusedFingerprint: fp
97682
98373
  }, owner.s === store)
97683
98374
  });
97684
- if (same && count === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
98375
+ if (same && count2 === SHIP_TERMINAL_REFUSALS && !isRetryableRefusal(reason)) {
97685
98376
  nowHeld.push({ id, reason });
97686
98377
  }
97687
98378
  };