@inerrata-corporation/errata 2.0.2-dev.437 → 2.0.2-dev.476

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.
@@ -16684,6 +16684,13 @@ init_src2();
16684
16684
  // ../../packages/local-graph/src/problem-package-link.ts
16685
16685
  init_src();
16686
16686
 
16687
+ // ../../packages/local-graph/src/problem-dedup.ts
16688
+ init_src();
16689
+ init_src();
16690
+
16691
+ // ../../packages/local-graph/src/intent.ts
16692
+ init_src();
16693
+
16687
16694
  // ../../packages/local-graph/src/anchor-backfill.ts
16688
16695
  init_src();
16689
16696
  init_src2();
@@ -17421,10 +17428,6 @@ function revisitContradictedPrinciples(l2, ts) {
17421
17428
  // ../../packages/local-graph/src/community.ts
17422
17429
  init_src2();
17423
17430
 
17424
- // ../../packages/local-graph/src/problem-dedup.ts
17425
- init_src();
17426
- init_src();
17427
-
17428
17431
  // ../../packages/local-graph/src/tools.ts
17429
17432
  init_src();
17430
17433
 
package/errata.mjs CHANGED
@@ -18562,6 +18562,132 @@ var init_problem_package_link = __esm({
18562
18562
  }
18563
18563
  });
18564
18564
 
18565
+ // ../../packages/local-graph/src/problem-dedup.ts
18566
+ function corroborations(n) {
18567
+ return Number(n.attrs["corroborations"] ?? 0);
18568
+ }
18569
+ function overlap(a, b) {
18570
+ if (a.size === 0 || b.size === 0) return 0;
18571
+ let inter = 0;
18572
+ for (const x of a) if (b.has(x)) inter++;
18573
+ return inter / Math.min(a.size, b.size);
18574
+ }
18575
+ function mergeDuplicateProblems(store, opts) {
18576
+ const minOverlap = opts.minOverlap ?? 0.85;
18577
+ const minTokens = opts.minTokens ?? 4;
18578
+ const report = { clusters: 0, merged: 0 };
18579
+ const open2 = store.findNodesByLabel("Problem").filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0);
18580
+ const tokens = /* @__PURE__ */ new Map();
18581
+ for (const p of open2) tokens.set(p.id, new Set(conceptTokens(p.description)));
18582
+ const consumed = /* @__PURE__ */ new Set();
18583
+ store.transaction(() => {
18584
+ for (let i2 = 0; i2 < open2.length; i2++) {
18585
+ const a = open2[i2];
18586
+ if (consumed.has(a.id)) continue;
18587
+ const cluster = [a];
18588
+ const ta = tokens.get(a.id);
18589
+ for (let j = i2 + 1; j < open2.length; j++) {
18590
+ const b = open2[j];
18591
+ if (consumed.has(b.id)) continue;
18592
+ const tb = tokens.get(b.id);
18593
+ if (Math.min(ta.size, tb.size) < minTokens) continue;
18594
+ if (isConstraintProblem(a) !== isConstraintProblem(b)) continue;
18595
+ if (overlap(ta, tb) >= minOverlap) {
18596
+ cluster.push(b);
18597
+ consumed.add(b.id);
18598
+ }
18599
+ }
18600
+ if (cluster.length < 2) continue;
18601
+ report.clusters++;
18602
+ cluster.sort((x, y) => corroborations(y) - corroborations(x) || x.createdAt - y.createdAt);
18603
+ const survivor = cluster[0];
18604
+ for (const dup of cluster.slice(1)) {
18605
+ foldDuplicateProblem(store, dup, survivor, opts.ts);
18606
+ report.merged++;
18607
+ }
18608
+ }
18609
+ });
18610
+ return report;
18611
+ }
18612
+ function foldDuplicateProblem(store, dup, survivor, ts) {
18613
+ const surv = store.getNode(survivor.id);
18614
+ if (!surv) return;
18615
+ const sources = new Set(surv.attrs["sources"] ?? []);
18616
+ for (const s of dup.attrs["sources"] ?? []) sources.add(s);
18617
+ store.updateNode(survivor.id, {
18618
+ attrs: {
18619
+ ...surv.attrs,
18620
+ sources: [...sources],
18621
+ corroborations: corroborations(surv) + corroborations(dup) + 1
18622
+ },
18623
+ cumulativeHits: (surv.cumulativeHits ?? 0) + (dup.cumulativeHits ?? 0),
18624
+ lastUpdatedAt: ts
18625
+ });
18626
+ for (const e of store.outEdges(dup.id, REDIRECT_EDGES)) {
18627
+ if (e.to === survivor.id) continue;
18628
+ const id = `edge_${digest({ from: survivor.id, type: e.type, to: e.to })}`.slice(0, 24);
18629
+ if (store.getEdge(id)) continue;
18630
+ const redirected = {
18631
+ ...e,
18632
+ id,
18633
+ from: survivor.id,
18634
+ createdAt: ts,
18635
+ lastSeenAt: ts
18636
+ };
18637
+ store.mergeEdge(redirected);
18638
+ }
18639
+ store.updateNode(dup.id, {
18640
+ attrs: { ...dup.attrs, mergedInto: survivor.id, resolvedAs: "duplicate", resolvedAt: ts },
18641
+ lastUpdatedAt: ts
18642
+ });
18643
+ store.closeNode(dup.id, ts);
18644
+ }
18645
+ function statementIdentityKey(statement) {
18646
+ return statement.toLowerCase().replace(/[`"'“”‘’*_]/g, "").replace(/[—–]/g, "-").replace(/\s+/g, " ").trim().replace(/[.,;:!?]+$/, "");
18647
+ }
18648
+ function findMintTimeDuplicate(store, statement, kind, opts) {
18649
+ const minOverlap = opts?.minOverlap ?? 0.85;
18650
+ const minTokens = opts?.minTokens ?? 4;
18651
+ const incomingIsConstraint = kind === "constraint";
18652
+ const open2 = store.findNodesByLabel("Problem").filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0);
18653
+ if (open2.length === 0) return null;
18654
+ const key = statementIdentityKey(statement);
18655
+ for (const p of open2) {
18656
+ if (isConstraintProblem(p) !== incomingIsConstraint) continue;
18657
+ if (statementIdentityKey(p.description) === key) return p.id;
18658
+ }
18659
+ const ta = new Set(conceptTokens(statement));
18660
+ if (ta.size < minTokens) return null;
18661
+ let best = null;
18662
+ for (const p of open2) {
18663
+ if (isConstraintProblem(p) !== incomingIsConstraint) continue;
18664
+ const tb = new Set(conceptTokens(p.description));
18665
+ if (Math.min(ta.size, tb.size) < minTokens) continue;
18666
+ const score2 = overlap(ta, tb);
18667
+ if (score2 >= minOverlap && (best === null || score2 > best.score)) {
18668
+ best = { id: p.id, score: score2 };
18669
+ }
18670
+ }
18671
+ return best?.id ?? null;
18672
+ }
18673
+ var REDIRECT_EDGES;
18674
+ var init_problem_dedup = __esm({
18675
+ "../../packages/local-graph/src/problem-dedup.ts"() {
18676
+ "use strict";
18677
+ init_src();
18678
+ init_src();
18679
+ init_design_problem();
18680
+ REDIRECT_EDGES = [
18681
+ "CAUSED_BY",
18682
+ "SOLVED_BY",
18683
+ "FIXED_BY",
18684
+ "ANCHORED_AT",
18685
+ "MANIFESTED_IN",
18686
+ "EVIDENCED_BY"
18687
+ ];
18688
+ }
18689
+ });
18690
+
18565
18691
  // ../../packages/local-graph/src/design-problem.ts
18566
18692
  function isConstraintProblem(node2) {
18567
18693
  return node2.attrs["kind"] === "constraint";
@@ -18644,7 +18770,9 @@ function ingestDesignProblem(store, flag, opts) {
18644
18770
  rejected: true
18645
18771
  };
18646
18772
  }
18647
- const problemId = identityId({ kind: "DesignProblem", statement });
18773
+ const rawId = identityId({ kind: "DesignProblem", statement });
18774
+ const dupId = store.getNode(rawId) ? null : findMintTimeDuplicate(store, statement, flag.kind);
18775
+ const problemId = dupId ?? rawId;
18648
18776
  const existing = store.getNode(problemId);
18649
18777
  let created = false;
18650
18778
  let corroborated = false;
@@ -18659,7 +18787,18 @@ function ingestDesignProblem(store, flag, opts) {
18659
18787
  ...existing.attrs,
18660
18788
  sources: [...sources, opts.source],
18661
18789
  corroborations: corroborations2,
18662
- ...promoted ? { provisional: false } : {}
18790
+ ...promoted ? { provisional: false } : {},
18791
+ // Keep the variant wording when a restatement resolved here rather
18792
+ // than minting — audit trail, and input for a future judge tier.
18793
+ ...dupId && statement !== existing.description ? {
18794
+ statementAliases: [
18795
+ ...(existing.attrs["statementAliases"] ?? []).slice(
18796
+ 0,
18797
+ STATEMENT_ALIAS_CAP - 1
18798
+ ),
18799
+ statement
18800
+ ]
18801
+ } : {}
18663
18802
  },
18664
18803
  cumulativeHits: (existing.cumulativeHits ?? 0) + 1,
18665
18804
  ...promoted ? { extractionConfidence: 0.65 } : {},
@@ -19133,7 +19272,32 @@ function markFixCandidates(store, t) {
19133
19272
  }
19134
19273
  return resolved;
19135
19274
  }
19136
- var DESIGN_PROMOTE_AT, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, AUTO_MINT_PREFIX;
19275
+ function recordRenderLedger(store, ledger, seq, ts) {
19276
+ const bump = (ids, field) => {
19277
+ let n = 0;
19278
+ for (const id of new Set(ids.map((i2) => i2.id))) {
19279
+ const node2 = store.getNode(id);
19280
+ if (!node2) continue;
19281
+ const attrs = { ...node2.attrs };
19282
+ attrs[field] = (attrs[field] ?? 0) + 1;
19283
+ if (field === "shownCount") {
19284
+ attrs["lastShownAtSeq"] = seq;
19285
+ if (attrs["firstShownAtSeq"] === void 0) attrs["firstShownAtSeq"] = seq;
19286
+ }
19287
+ store.updateNode(id, { attrs, lastUpdatedAt: node2.lastUpdatedAt });
19288
+ n++;
19289
+ }
19290
+ return n;
19291
+ };
19292
+ let shown = 0;
19293
+ let evicted = 0;
19294
+ store.transaction(() => {
19295
+ shown = bump(ledger.shown, "shownCount");
19296
+ evicted = bump(ledger.evicted, "evictedCount");
19297
+ });
19298
+ return { shown, evicted };
19299
+ }
19300
+ var DESIGN_PROMOTE_AT, STATEMENT_ALIAS_CAP, PATTERN_DEDUP_COSINE, PATTERN_ALIAS_CAP, DEDUP_STOPWORDS, SAME_ANCHOR_DEDUP_JACCARD, CITABLE_PRIOR_LABELS, MAX_ANCHOR_FILES, AUTO_MINT_PREFIX;
19137
19301
  var init_design_problem = __esm({
19138
19302
  "../../packages/local-graph/src/design-problem.ts"() {
19139
19303
  "use strict";
@@ -19142,7 +19306,9 @@ var init_design_problem = __esm({
19142
19306
  init_src3();
19143
19307
  init_src2();
19144
19308
  init_problem_package_link();
19309
+ init_problem_dedup();
19145
19310
  DESIGN_PROMOTE_AT = 1;
19311
+ STATEMENT_ALIAS_CAP = 5;
19146
19312
  PATTERN_DEDUP_COSINE = 0.85;
19147
19313
  PATTERN_ALIAS_CAP = 5;
19148
19314
  DEDUP_STOPWORDS = /* @__PURE__ */ new Set([
@@ -19181,6 +19347,61 @@ var init_design_problem = __esm({
19181
19347
  }
19182
19348
  });
19183
19349
 
19350
+ // ../../packages/local-graph/src/intent.ts
19351
+ function parseIntentFences(text) {
19352
+ const out2 = [];
19353
+ const block = /```errata-intent[^\n]*\n([\s\S]*?)```/g;
19354
+ let m;
19355
+ while ((m = block.exec(text)) !== null) {
19356
+ const lines = m[1].split(/\r?\n/);
19357
+ const parts2 = [];
19358
+ for (const line of lines) {
19359
+ const kv = /^\s*intent\s*:\s*(.+?)\s*$/i.exec(line);
19360
+ if (kv) parts2.push(kv[1].trim());
19361
+ else if (parts2.length > 0 && line.trim()) parts2.push(line.trim());
19362
+ }
19363
+ const intent = parts2.join(" ").trim();
19364
+ if (intent) out2.push({ intent });
19365
+ }
19366
+ return out2;
19367
+ }
19368
+ function searchByIntent(store, intent, opts) {
19369
+ const limit = opts?.limit ?? 5;
19370
+ const minCoverage = opts?.minCoverage ?? 0.25;
19371
+ const want = new Set(conceptTokens(intent));
19372
+ if (want.size < MIN_INTENT_TOKENS) return [];
19373
+ const hits = [];
19374
+ for (const label of RECALLABLE) {
19375
+ for (const node2 of store.findNodesByLabel(label)) {
19376
+ if (node2.attrs["mergedInto"] !== void 0) continue;
19377
+ if (label === "Problem" && node2.attrs["resolvedAt"] != null && !isConstraintProblem(node2)) {
19378
+ continue;
19379
+ }
19380
+ const bag = conceptTokens(node2.description ?? "");
19381
+ if (bag.length === 0) continue;
19382
+ const matched = bag.filter((t) => want.has(t));
19383
+ if (matched.length === 0) continue;
19384
+ const coverage = matched.length / want.size;
19385
+ if (coverage < minCoverage) continue;
19386
+ hits.push({ node: node2, coverage, matched });
19387
+ }
19388
+ }
19389
+ hits.sort(
19390
+ (a, b) => b.coverage - a.coverage || (a.node.description?.length ?? 0) - (b.node.description?.length ?? 0)
19391
+ );
19392
+ return hits.slice(0, limit);
19393
+ }
19394
+ var RECALLABLE, MIN_INTENT_TOKENS;
19395
+ var init_intent = __esm({
19396
+ "../../packages/local-graph/src/intent.ts"() {
19397
+ "use strict";
19398
+ init_src();
19399
+ init_design_problem();
19400
+ RECALLABLE = ["Problem", "Solution", "RootCause", "Pattern"];
19401
+ MIN_INTENT_TOKENS = 2;
19402
+ }
19403
+ });
19404
+
19184
19405
  // ../../packages/local-graph/src/anchor-backfill.ts
19185
19406
  function isLegacyAnchor(attrs) {
19186
19407
  return attrs?.["captureTime"] === true && attrs["anchorProvenance"] === void 0;
@@ -21222,104 +21443,6 @@ var init_community2 = __esm({
21222
21443
  }
21223
21444
  });
21224
21445
 
21225
- // ../../packages/local-graph/src/problem-dedup.ts
21226
- function corroborations(n) {
21227
- return Number(n.attrs["corroborations"] ?? 0);
21228
- }
21229
- function overlap(a, b) {
21230
- if (a.size === 0 || b.size === 0) return 0;
21231
- let inter = 0;
21232
- for (const x of a) if (b.has(x)) inter++;
21233
- return inter / Math.min(a.size, b.size);
21234
- }
21235
- function mergeDuplicateProblems(store, opts) {
21236
- const minOverlap = opts.minOverlap ?? 0.85;
21237
- const minTokens = opts.minTokens ?? 4;
21238
- const report = { clusters: 0, merged: 0 };
21239
- const open2 = store.findNodesByLabel("Problem").filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0);
21240
- const tokens = /* @__PURE__ */ new Map();
21241
- for (const p of open2) tokens.set(p.id, new Set(conceptTokens(p.description)));
21242
- const consumed = /* @__PURE__ */ new Set();
21243
- store.transaction(() => {
21244
- for (let i2 = 0; i2 < open2.length; i2++) {
21245
- const a = open2[i2];
21246
- if (consumed.has(a.id)) continue;
21247
- const cluster = [a];
21248
- const ta = tokens.get(a.id);
21249
- for (let j = i2 + 1; j < open2.length; j++) {
21250
- const b = open2[j];
21251
- if (consumed.has(b.id)) continue;
21252
- const tb = tokens.get(b.id);
21253
- if (Math.min(ta.size, tb.size) < minTokens) continue;
21254
- if (isConstraintProblem(a) !== isConstraintProblem(b)) continue;
21255
- if (overlap(ta, tb) >= minOverlap) {
21256
- cluster.push(b);
21257
- consumed.add(b.id);
21258
- }
21259
- }
21260
- if (cluster.length < 2) continue;
21261
- report.clusters++;
21262
- cluster.sort((x, y) => corroborations(y) - corroborations(x) || x.createdAt - y.createdAt);
21263
- const survivor = cluster[0];
21264
- for (const dup of cluster.slice(1)) {
21265
- foldDuplicateProblem(store, dup, survivor, opts.ts);
21266
- report.merged++;
21267
- }
21268
- }
21269
- });
21270
- return report;
21271
- }
21272
- function foldDuplicateProblem(store, dup, survivor, ts) {
21273
- const surv = store.getNode(survivor.id);
21274
- if (!surv) return;
21275
- const sources = new Set(surv.attrs["sources"] ?? []);
21276
- for (const s of dup.attrs["sources"] ?? []) sources.add(s);
21277
- store.updateNode(survivor.id, {
21278
- attrs: {
21279
- ...surv.attrs,
21280
- sources: [...sources],
21281
- corroborations: corroborations(surv) + corroborations(dup) + 1
21282
- },
21283
- cumulativeHits: (surv.cumulativeHits ?? 0) + (dup.cumulativeHits ?? 0),
21284
- lastUpdatedAt: ts
21285
- });
21286
- for (const e of store.outEdges(dup.id, REDIRECT_EDGES)) {
21287
- if (e.to === survivor.id) continue;
21288
- const id = `edge_${digest({ from: survivor.id, type: e.type, to: e.to })}`.slice(0, 24);
21289
- if (store.getEdge(id)) continue;
21290
- const redirected = {
21291
- ...e,
21292
- id,
21293
- from: survivor.id,
21294
- createdAt: ts,
21295
- lastSeenAt: ts
21296
- };
21297
- store.mergeEdge(redirected);
21298
- }
21299
- store.updateNode(dup.id, {
21300
- attrs: { ...dup.attrs, mergedInto: survivor.id, resolvedAs: "duplicate", resolvedAt: ts },
21301
- lastUpdatedAt: ts
21302
- });
21303
- store.closeNode(dup.id, ts);
21304
- }
21305
- var REDIRECT_EDGES;
21306
- var init_problem_dedup = __esm({
21307
- "../../packages/local-graph/src/problem-dedup.ts"() {
21308
- "use strict";
21309
- init_src();
21310
- init_src();
21311
- init_design_problem();
21312
- REDIRECT_EDGES = [
21313
- "CAUSED_BY",
21314
- "SOLVED_BY",
21315
- "FIXED_BY",
21316
- "ANCHORED_AT",
21317
- "MANIFESTED_IN",
21318
- "EVIDENCED_BY"
21319
- ];
21320
- }
21321
- });
21322
-
21323
21446
  // ../../packages/local-graph/src/tools.ts
21324
21447
  function toolNodeId(name2) {
21325
21448
  return `tool:${name2}`;
@@ -21523,6 +21646,7 @@ __export(src_exports2, {
21523
21646
  JOINT_COMMUNITY_EDGES: () => JOINT_COMMUNITY_EDGES,
21524
21647
  JOINT_COMMUNITY_LABELS: () => JOINT_COMMUNITY_LABELS,
21525
21648
  MAX_ANCHOR_FILES: () => MAX_ANCHOR_FILES,
21649
+ MIN_INTENT_TOKENS: () => MIN_INTENT_TOKENS,
21526
21650
  PATTERN_DEDUP_COSINE: () => PATTERN_DEDUP_COSINE,
21527
21651
  PERCOLATING_DRIFT_EDGES: () => PERCOLATING_DRIFT_EDGES,
21528
21652
  PERCOLATING_EDGES: () => PERCOLATING_EDGES,
@@ -21559,6 +21683,7 @@ __export(src_exports2, {
21559
21683
  detectLocalCommunities: () => detectLocalCommunities,
21560
21684
  edgeConductance: () => edgeConductance,
21561
21685
  evaluateDependency: () => evaluateDependency,
21686
+ findMintTimeDuplicate: () => findMintTimeDuplicate,
21562
21687
  findOrCreatePackage: () => findOrCreatePackage,
21563
21688
  findPath: () => findPath,
21564
21689
  flattenCloudCounts: () => flattenCloudCounts,
@@ -21594,6 +21719,7 @@ __export(src_exports2, {
21594
21719
  openGraphStore: () => openGraphStore,
21595
21720
  osNodeId: () => osNodeId,
21596
21721
  parseAbstractionFences: () => parseAbstractionFences,
21722
+ parseIntentFences: () => parseIntentFences,
21597
21723
  parseSemver: () => parseSemver,
21598
21724
  parseTriageFences: () => parseTriageFences,
21599
21725
  pendingAbstractions: () => pendingAbstractions,
@@ -21608,6 +21734,7 @@ __export(src_exports2, {
21608
21734
  recordCauseChainLink: () => recordCauseChainLink,
21609
21735
  recordClaim: () => recordClaim,
21610
21736
  recordMisreadPrior: () => recordMisreadPrior,
21737
+ recordRenderLedger: () => recordRenderLedger,
21611
21738
  recordTriageObservation: () => recordTriageObservation,
21612
21739
  reinforceSameAnchorProblem: () => reinforceSameAnchorProblem,
21613
21740
  relateClaims: () => relateClaims,
@@ -21620,9 +21747,11 @@ __export(src_exports2, {
21620
21747
  retractDesignProblemByStatement: () => retractDesignProblemByStatement,
21621
21748
  revisitContradictedPrinciples: () => revisitContradictedPrinciples,
21622
21749
  revisitStaleRoutes: () => revisitStaleRoutes,
21750
+ searchByIntent: () => searchByIntent,
21623
21751
  solutionForProblem: () => solutionForProblem,
21624
21752
  splittingAxis: () => splittingAxis,
21625
21753
  stampObservedOs: () => stampObservedOs,
21754
+ statementIdentityKey: () => statementIdentityKey,
21626
21755
  staticConductance: () => staticConductance,
21627
21756
  toolNodeId: () => toolNodeId,
21628
21757
  toolPriorsFor: () => toolPriorsFor,
@@ -21641,6 +21770,7 @@ var init_src5 = __esm({
21641
21770
  init_crystallize();
21642
21771
  init_aggregate();
21643
21772
  init_design_problem();
21773
+ init_intent();
21644
21774
  init_anchor_backfill();
21645
21775
  init_percolate();
21646
21776
  init_abstraction();
@@ -22138,14 +22268,42 @@ function assembleAgentContext(opts) {
22138
22268
  }
22139
22269
  snapshot.skills = [...snapshot.skills].sort((a, b) => b.confidence - a.confidence);
22140
22270
  const maxChars = opts.maxChars ?? DEFAULT_AGENT_CONTEXT_BUDGET;
22271
+ const candidates = snapshotImpressions(snapshot);
22141
22272
  const dropped = budgetSnapshot(snapshot, maxChars);
22273
+ const ledger = diffRenderLedger(candidates, snapshotImpressions(snapshot));
22142
22274
  let body2 = renderSnapshot(snapshot);
22143
22275
  if (dropped > 0) {
22144
22276
  body2 += `
22145
22277
 
22146
22278
  _${dropped} lower-priority item${dropped === 1 ? "" : "s"} omitted to fit the passive-context budget \u2014 the full graph is in the errata dashboard._`;
22147
22279
  }
22148
- return { body: body2, snapshot, dropped };
22280
+ return { body: body2, snapshot, dropped, ledger };
22281
+ }
22282
+ function snapshotImpressions(s) {
22283
+ const out2 = [];
22284
+ const push = (band, ids) => {
22285
+ for (const id of ids) if (id) out2.push({ id, band });
22286
+ };
22287
+ push("recentProblems", s.recentProblems.map((p) => p.node.id));
22288
+ push("recentResolved", s.recentResolved.map((r) => r.node.id));
22289
+ push("recentConstraints", s.recentConstraints.map((c) => c.id));
22290
+ push("motifs", s.motifs.map((m) => m.id));
22291
+ push("remote", (s.remote ?? []).map((r) => r.id));
22292
+ push("needsRevisit", s.needsRevisit.map((r) => r.id));
22293
+ push(
22294
+ "reviewItems",
22295
+ (s.reviewItems ?? []).map((r) => r.kind === "abstraction" ? r.candidate : r.route)
22296
+ );
22297
+ push("workingFile", s.workingFile?.priors?.openProblems.map((p) => p.id) ?? []);
22298
+ return out2;
22299
+ }
22300
+ function diffRenderLedger(before, after) {
22301
+ const key = (i2) => `${i2.band}\0${i2.id}`;
22302
+ const survived = new Set(after.map(key));
22303
+ const shown = [];
22304
+ const evicted = [];
22305
+ for (const i2 of before) (survived.has(key(i2)) ? shown : evicted).push(i2);
22306
+ return { shown, evicted };
22149
22307
  }
22150
22308
  var RECALL_FIRST_HEADER, RECALL_FIRST_BODY, RECALL_FIRST_BLOCK, SEARCH_IMPERATIVE_HEADER, SEARCH_IMPERATIVE_BODY, EVICTION_ORDER, MOTIF_FLOOR, REMOTE_FLOOR, PROBLEM_FLOOR, REVIEW_ITEM_FLOOR, DEFAULT_AGENT_CONTEXT_BUDGET;
22151
22309
  var init_render = __esm({
@@ -22159,7 +22317,7 @@ var init_render = __esm({
22159
22317
 
22160
22318
  ${RECALL_FIRST_BODY}`;
22161
22319
  SEARCH_IMPERATIVE_HEADER = "### \u{1F50E} PRIORS ARE SEEDS \u2014 a sample, not the whole graph";
22162
- SEARCH_IMPERATIVE_BODY = "Everything below is a budgeted, top-of-head slice of a much larger graph. Any prior id below is a live burst seed: `errata.burst` it (or read `.errata/g/burst/<id>`) to pull its wider neighborhood \u2014 causes, fixes, siblings. When a prior is adjacent-but-not-quite, or none fit, that gap is exactly when to search deeper before solving cold: a stuck search is itself a signal that routes help to you.";
22320
+ SEARCH_IMPERATIVE_BODY = "Everything below is a budgeted slice of a much larger graph, not all errata knows. Starting a piece of work? Say what it is \u2014 we search on it between your tool calls and put what we find here:\n```errata-intent\nintent: <the work in hand, in your words>\n```\nNarration, not a detour: no tool call, no plan change. It is the one signal we cannot derive from your edits \u2014 everything else here is guessed from the files you touched.";
22163
22321
  EVICTION_ORDER = [
22164
22322
  "skills",
22165
22323
  // Review items beyond the floor drop immediately after skills — one naming
@@ -26177,7 +26335,7 @@ function buildAgentInstruction(opts = {}) {
26177
26335
  const ref = opts.referent ?? "its-handle";
26178
26336
  const token = (s) => s === "problem" ? TAG_EXAMPLE.problem() : s === "constraint" ? TAG_EXAMPLE.constraint() : s === "attempt" ? TAG_EXAMPLE.tried() : s === "domain" ? TAG_EXAMPLE.domain() : s === "link" ? TAG_EXAMPLE.pattern() : TAG_EXAMPLE[s](ref);
26179
26337
  const head2 = `We tag the priors we show you with a short handle like [${opts.handleExample ?? "chokidar-glob"}]. Tags are the ONLY signal recorded \u2014 anything you state but don't tag is silently lost. Weave each tag inline in your prose as you state it (no fences or backticks, no extra calls); tag everything, we filter downstream:`;
26180
- const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 RESTATE every tag in your turn-final message; the final message is what reliably survives.";
26338
+ const tail = "Mid-turn text (between tool calls) can be dropped by the harness \u2014 RESTATE every tag in your turn-final message; the final message is what reliably survives \u2014 EXCEPT one already shown above with an id: that is captured, so cite `[its-handle]` rather than retyping it (drift mints a duplicate).";
26181
26339
  return [
26182
26340
  head2,
26183
26341
  ...signals.map(
@@ -53453,7 +53611,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53453
53611
  }
53454
53612
 
53455
53613
  // src/engine.ts
53456
- var DAEMON_VERSION = true ? "2.0.2-dev.437" : "2.0.0-alpha.0";
53614
+ var DAEMON_VERSION = true ? "2.0.2-dev.476" : "2.0.0-alpha.0";
53457
53615
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53458
53616
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53459
53617
  var GIT_OP_MUTE_MS = 4e3;
@@ -53824,7 +53982,7 @@ function createWorkspaceEngine(opts) {
53824
53982
  const doneRender = prebuilt ? null : markPass(`context-render-inline:${profile.name}`);
53825
53983
  const pendingUpdate = opts.pendingUpdate?.() ?? null;
53826
53984
  const reviewItems = pickReviewItems();
53827
- const { body: body2, snapshot } = assembleAgentContext({
53985
+ const { body: body2, snapshot, ledger } = assembleAgentContext({
53828
53986
  store,
53829
53987
  ...snapOpts,
53830
53988
  remote: remotePriors,
@@ -53834,6 +53992,12 @@ function createWorkspaceEngine(opts) {
53834
53992
  ...reviewItems.length ? { reviewItems } : {}
53835
53993
  });
53836
53994
  doneRender?.();
53995
+ try {
53996
+ const seq = store.currentIngestSeq();
53997
+ recordRenderLedger(store, ledger, seq, Date.now());
53998
+ } catch (err2) {
53999
+ console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
54000
+ }
53837
54001
  writeContextFile(opts.workspaceRoot, body2);
53838
54002
  const target = join26(opts.workspaceRoot, "AGENTS.md");
53839
54003
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.2-dev.437",
3
+ "version": "2.0.2-dev.476",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -25316,6 +25316,97 @@ function backfillProblemContext(store2, ts) {
25316
25316
  return report;
25317
25317
  }
25318
25318
 
25319
+ // ../../packages/local-graph/src/problem-dedup.ts
25320
+ init_src();
25321
+ init_src();
25322
+ var REDIRECT_EDGES = [
25323
+ "CAUSED_BY",
25324
+ "SOLVED_BY",
25325
+ "FIXED_BY",
25326
+ "ANCHORED_AT",
25327
+ "MANIFESTED_IN",
25328
+ "EVIDENCED_BY"
25329
+ ];
25330
+ function corroborations(n) {
25331
+ return Number(n.attrs["corroborations"] ?? 0);
25332
+ }
25333
+ function overlap(a, b) {
25334
+ if (a.size === 0 || b.size === 0) return 0;
25335
+ let inter = 0;
25336
+ for (const x of a) if (b.has(x)) inter++;
25337
+ return inter / Math.min(a.size, b.size);
25338
+ }
25339
+ function mergeDuplicateProblems(store2, opts) {
25340
+ const minOverlap = opts.minOverlap ?? 0.85;
25341
+ const minTokens = opts.minTokens ?? 4;
25342
+ const report = { clusters: 0, merged: 0 };
25343
+ const open = store2.findNodesByLabel("Problem").filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0);
25344
+ const tokens = /* @__PURE__ */ new Map();
25345
+ for (const p of open) tokens.set(p.id, new Set(conceptTokens(p.description)));
25346
+ const consumed = /* @__PURE__ */ new Set();
25347
+ store2.transaction(() => {
25348
+ for (let i2 = 0; i2 < open.length; i2++) {
25349
+ const a = open[i2];
25350
+ if (consumed.has(a.id)) continue;
25351
+ const cluster = [a];
25352
+ const ta = tokens.get(a.id);
25353
+ for (let j = i2 + 1; j < open.length; j++) {
25354
+ const b = open[j];
25355
+ if (consumed.has(b.id)) continue;
25356
+ const tb = tokens.get(b.id);
25357
+ if (Math.min(ta.size, tb.size) < minTokens) continue;
25358
+ if (isConstraintProblem(a) !== isConstraintProblem(b)) continue;
25359
+ if (overlap(ta, tb) >= minOverlap) {
25360
+ cluster.push(b);
25361
+ consumed.add(b.id);
25362
+ }
25363
+ }
25364
+ if (cluster.length < 2) continue;
25365
+ report.clusters++;
25366
+ cluster.sort((x, y) => corroborations(y) - corroborations(x) || x.createdAt - y.createdAt);
25367
+ const survivor = cluster[0];
25368
+ for (const dup of cluster.slice(1)) {
25369
+ foldDuplicateProblem(store2, dup, survivor, opts.ts);
25370
+ report.merged++;
25371
+ }
25372
+ }
25373
+ });
25374
+ return report;
25375
+ }
25376
+ function foldDuplicateProblem(store2, dup, survivor, ts) {
25377
+ const surv = store2.getNode(survivor.id);
25378
+ if (!surv) return;
25379
+ const sources = new Set(surv.attrs["sources"] ?? []);
25380
+ for (const s of dup.attrs["sources"] ?? []) sources.add(s);
25381
+ store2.updateNode(survivor.id, {
25382
+ attrs: {
25383
+ ...surv.attrs,
25384
+ sources: [...sources],
25385
+ corroborations: corroborations(surv) + corroborations(dup) + 1
25386
+ },
25387
+ cumulativeHits: (surv.cumulativeHits ?? 0) + (dup.cumulativeHits ?? 0),
25388
+ lastUpdatedAt: ts
25389
+ });
25390
+ for (const e of store2.outEdges(dup.id, REDIRECT_EDGES)) {
25391
+ if (e.to === survivor.id) continue;
25392
+ const id = `edge_${digest({ from: survivor.id, type: e.type, to: e.to })}`.slice(0, 24);
25393
+ if (store2.getEdge(id)) continue;
25394
+ const redirected = {
25395
+ ...e,
25396
+ id,
25397
+ from: survivor.id,
25398
+ createdAt: ts,
25399
+ lastSeenAt: ts
25400
+ };
25401
+ store2.mergeEdge(redirected);
25402
+ }
25403
+ store2.updateNode(dup.id, {
25404
+ attrs: { ...dup.attrs, mergedInto: survivor.id, resolvedAs: "duplicate", resolvedAt: ts },
25405
+ lastUpdatedAt: ts
25406
+ });
25407
+ store2.closeNode(dup.id, ts);
25408
+ }
25409
+
25319
25410
  // ../../packages/local-graph/src/design-problem.ts
25320
25411
  function isConstraintProblem(node) {
25321
25412
  return node.attrs["kind"] === "constraint";
@@ -25464,6 +25555,9 @@ function markFixCandidates(store2, t) {
25464
25555
  return resolved;
25465
25556
  }
25466
25557
 
25558
+ // ../../packages/local-graph/src/intent.ts
25559
+ init_src();
25560
+
25467
25561
  // ../../packages/local-graph/src/anchor-backfill.ts
25468
25562
  init_src();
25469
25563
  init_src2();
@@ -25952,97 +26046,6 @@ var DRIFT_VALUES = new Set(Object.values(DRIFT_KIND));
25952
26046
  // ../../packages/local-graph/src/community.ts
25953
26047
  init_src2();
25954
26048
 
25955
- // ../../packages/local-graph/src/problem-dedup.ts
25956
- init_src();
25957
- init_src();
25958
- var REDIRECT_EDGES = [
25959
- "CAUSED_BY",
25960
- "SOLVED_BY",
25961
- "FIXED_BY",
25962
- "ANCHORED_AT",
25963
- "MANIFESTED_IN",
25964
- "EVIDENCED_BY"
25965
- ];
25966
- function corroborations(n) {
25967
- return Number(n.attrs["corroborations"] ?? 0);
25968
- }
25969
- function overlap(a, b) {
25970
- if (a.size === 0 || b.size === 0) return 0;
25971
- let inter = 0;
25972
- for (const x of a) if (b.has(x)) inter++;
25973
- return inter / Math.min(a.size, b.size);
25974
- }
25975
- function mergeDuplicateProblems(store2, opts) {
25976
- const minOverlap = opts.minOverlap ?? 0.85;
25977
- const minTokens = opts.minTokens ?? 4;
25978
- const report = { clusters: 0, merged: 0 };
25979
- const open = store2.findNodesByLabel("Problem").filter((p) => p.attrs["resolvedAt"] == null && p.attrs["mergedInto"] === void 0);
25980
- const tokens = /* @__PURE__ */ new Map();
25981
- for (const p of open) tokens.set(p.id, new Set(conceptTokens(p.description)));
25982
- const consumed = /* @__PURE__ */ new Set();
25983
- store2.transaction(() => {
25984
- for (let i2 = 0; i2 < open.length; i2++) {
25985
- const a = open[i2];
25986
- if (consumed.has(a.id)) continue;
25987
- const cluster = [a];
25988
- const ta = tokens.get(a.id);
25989
- for (let j = i2 + 1; j < open.length; j++) {
25990
- const b = open[j];
25991
- if (consumed.has(b.id)) continue;
25992
- const tb = tokens.get(b.id);
25993
- if (Math.min(ta.size, tb.size) < minTokens) continue;
25994
- if (isConstraintProblem(a) !== isConstraintProblem(b)) continue;
25995
- if (overlap(ta, tb) >= minOverlap) {
25996
- cluster.push(b);
25997
- consumed.add(b.id);
25998
- }
25999
- }
26000
- if (cluster.length < 2) continue;
26001
- report.clusters++;
26002
- cluster.sort((x, y) => corroborations(y) - corroborations(x) || x.createdAt - y.createdAt);
26003
- const survivor = cluster[0];
26004
- for (const dup of cluster.slice(1)) {
26005
- foldDuplicateProblem(store2, dup, survivor, opts.ts);
26006
- report.merged++;
26007
- }
26008
- }
26009
- });
26010
- return report;
26011
- }
26012
- function foldDuplicateProblem(store2, dup, survivor, ts) {
26013
- const surv = store2.getNode(survivor.id);
26014
- if (!surv) return;
26015
- const sources = new Set(surv.attrs["sources"] ?? []);
26016
- for (const s of dup.attrs["sources"] ?? []) sources.add(s);
26017
- store2.updateNode(survivor.id, {
26018
- attrs: {
26019
- ...surv.attrs,
26020
- sources: [...sources],
26021
- corroborations: corroborations(surv) + corroborations(dup) + 1
26022
- },
26023
- cumulativeHits: (surv.cumulativeHits ?? 0) + (dup.cumulativeHits ?? 0),
26024
- lastUpdatedAt: ts
26025
- });
26026
- for (const e of store2.outEdges(dup.id, REDIRECT_EDGES)) {
26027
- if (e.to === survivor.id) continue;
26028
- const id = `edge_${digest({ from: survivor.id, type: e.type, to: e.to })}`.slice(0, 24);
26029
- if (store2.getEdge(id)) continue;
26030
- const redirected = {
26031
- ...e,
26032
- id,
26033
- from: survivor.id,
26034
- createdAt: ts,
26035
- lastSeenAt: ts
26036
- };
26037
- store2.mergeEdge(redirected);
26038
- }
26039
- store2.updateNode(dup.id, {
26040
- attrs: { ...dup.attrs, mergedInto: survivor.id, resolvedAs: "duplicate", resolvedAt: ts },
26041
- lastUpdatedAt: ts
26042
- });
26043
- store2.closeNode(dup.id, ts);
26044
- }
26045
-
26046
26049
  // ../../packages/local-graph/src/tools.ts
26047
26050
  init_src();
26048
26051
  function rankToolsForHandles(store2, limit = 5) {