@inerrata-corporation/errata 2.0.2-dev.513 → 2.0.2-dev.530

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
@@ -17314,6 +17314,10 @@ CREATE INDEX IF NOT EXISTS nodes_relpath ON nodes(json_extract(attrs_json, '$.re
17314
17314
  if (!live) return null;
17315
17315
  const version2 = live.version ?? 1;
17316
17316
  const frozenId = `${liveId}@v${version2}`;
17317
+ if (this.getNode(frozenId)) {
17318
+ this.stmts.advanceLive.run({ live_id: liveId, t });
17319
+ return frozenId;
17320
+ }
17317
17321
  this.stmts.freezeCopy.run({ frozen_id: frozenId, live_id: liveId, t });
17318
17322
  this.mergeEdge({
17319
17323
  id: `edge_superseded_${frozenId}`,
@@ -17699,14 +17703,17 @@ function markRevisit(store, node2, reason, ts, answeredWhen) {
17699
17703
  revisit: true,
17700
17704
  revisitReason: reason,
17701
17705
  revisitSinceTs: ts,
17702
- ...answeredWhen ? { revisitAnsweredWhen: answeredWhen } : {}
17706
+ revisitAnsweredWhen: answeredWhen
17703
17707
  },
17704
17708
  lastUpdatedAt: ts
17705
17709
  });
17706
17710
  }
17711
+ function isRevisitCondition(v) {
17712
+ return typeof v === "string" && Object.prototype.hasOwnProperty.call(KNOWN_CONDITIONS, v);
17713
+ }
17707
17714
  function conditionOf(node2) {
17708
17715
  const explicit = node2.attrs["revisitAnsweredWhen"];
17709
- if (explicit === "parentProblemOpen") return explicit;
17716
+ if (isRevisitCondition(explicit)) return explicit;
17710
17717
  if (String(node2.attrs["revisitReason"] ?? "").startsWith(LEGACY_AUTO_CLOSE_ASK)) {
17711
17718
  return "parentProblemOpen";
17712
17719
  }
@@ -17714,23 +17721,32 @@ function conditionOf(node2) {
17714
17721
  }
17715
17722
  function clearAnsweredRevisits(store, ts) {
17716
17723
  const report = { cleared: 0, standing: 0 };
17717
- for (const node2 of store.findNodesByLabel("Solution")) {
17718
- if (node2.attrs["revisit"] !== true) continue;
17719
- if (conditionOf(node2) !== "parentProblemOpen") {
17720
- report.standing++;
17721
- continue;
17722
- }
17723
- const parents = store.inEdges(node2.id, ["SOLVED_BY"]).map((e) => store.getNode(e.from)).filter((n) => n !== null);
17724
- const answered = parents.every((p) => p.attrs["resolvedAt"] == null);
17725
- if (!answered) {
17726
- report.standing++;
17727
- continue;
17724
+ for (const label of SEMANTIC_NODE_LABELS) {
17725
+ for (const node2 of store.findNodesByLabel(label)) {
17726
+ if (node2.attrs["revisit"] !== true) continue;
17727
+ const condition = conditionOf(node2);
17728
+ if (condition === void 0 || !isRevisitAnswered(store, node2, condition)) {
17729
+ report.standing++;
17730
+ continue;
17731
+ }
17732
+ clearRevisit(store, node2.id, ts);
17733
+ report.cleared++;
17728
17734
  }
17729
- clearRevisit(store, node2.id, ts);
17730
- report.cleared++;
17731
17735
  }
17732
17736
  return report;
17733
17737
  }
17738
+ function isRevisitAnswered(store, node2, condition) {
17739
+ switch (condition) {
17740
+ case "parentProblemOpen": {
17741
+ const parents = store.inEdges(node2.id, ["SOLVED_BY"]).map((e) => store.getNode(e.from)).filter((n) => n !== null);
17742
+ return parents.every((p) => p.attrs["resolvedAt"] == null);
17743
+ }
17744
+ case "dependentStale": {
17745
+ const since = Number(node2.attrs["revisitSinceTs"] ?? 0);
17746
+ return since > 0 && node2.lastUpdatedAt > since;
17747
+ }
17748
+ }
17749
+ }
17734
17750
  function clearRevisit(store, nodeId, ts) {
17735
17751
  const n = store.getNode(nodeId);
17736
17752
  if (!n) return;
@@ -17756,7 +17772,7 @@ function cascade(store, seeds, visited, flagged, ts) {
17756
17772
  visited.add(id);
17757
17773
  const node2 = store.getNode(id);
17758
17774
  if (!node2) continue;
17759
- markRevisit(store, node2, reason, ts);
17775
+ markRevisit(store, node2, reason, ts, "dependentStale");
17760
17776
  flagged.push({ id, label: node2.label, description: node2.description, reason });
17761
17777
  for (const e of store.inEdges(id, ["DEPENDS_ON"])) {
17762
17778
  queue.push({
@@ -17803,12 +17819,17 @@ function propagateFactChange(store, opts) {
17803
17819
  cascade(store, seeds, visited, flagged, opts.ts);
17804
17820
  return flagged;
17805
17821
  }
17806
- var LEGACY_AUTO_CLOSE_ASK;
17822
+ var LEGACY_AUTO_CLOSE_ASK, KNOWN_CONDITIONS;
17807
17823
  var init_justification = __esm({
17808
17824
  "../../packages/local-graph/src/justification.ts"() {
17809
17825
  "use strict";
17810
17826
  init_src();
17827
+ init_src2();
17811
17828
  LEGACY_AUTO_CLOSE_ASK = "auto-closed off a pre-provenance anchor";
17829
+ KNOWN_CONDITIONS = {
17830
+ parentProblemOpen: true,
17831
+ dependentStale: true
17832
+ };
17812
17833
  }
17813
17834
  });
17814
17835
 
@@ -18788,7 +18809,8 @@ function isPlaceholderStatement(statement) {
18788
18809
  if (bracketed.length > 0 && bracketedLen >= s.length * 0.6) return true;
18789
18810
  return false;
18790
18811
  }
18791
- function buildNode(id, label, description, ts, attrs) {
18812
+ function buildNode(store, id, label, description, ts, attrs) {
18813
+ const seq = SEMANTIC_NODE_LABELS.includes(label) ? store.nextIngestSeq() : void 0;
18792
18814
  return {
18793
18815
  id,
18794
18816
  label,
@@ -18807,9 +18829,14 @@ function buildNode(id, label, description, ts, attrs) {
18807
18829
  isLandmark: false,
18808
18830
  community: null,
18809
18831
  stability: "unstable",
18832
+ ...seq !== void 0 ? { createdAtSeq: seq, lastReinforcedAtSeq: seq } : {},
18810
18833
  attrs
18811
18834
  };
18812
18835
  }
18836
+ function reinforcedSeqAttrs(store, label) {
18837
+ if (!SEMANTIC_NODE_LABELS.includes(label)) return {};
18838
+ return { lastReinforcedAtSeq: store.nextIngestSeq() };
18839
+ }
18813
18840
  function mergeEdge(store, from, to, type, ts) {
18814
18841
  store.mergeEdge({
18815
18842
  id: `edge_${digest({ from, type, to })}`.slice(0, 24),
@@ -18889,13 +18916,19 @@ function ingestDesignProblem(store, flag, opts) {
18889
18916
  },
18890
18917
  cumulativeHits: (existing.cumulativeHits ?? 0) + 1,
18891
18918
  ...promoted ? { extractionConfidence: 0.65 } : {},
18919
+ // A corroborating re-flag is a REINFORCE: advance the sequence and move
18920
+ // this node's marker with it, which resets its Δseq and makes it read
18921
+ // fresh again. Without this the mint path would advance the ruler while
18922
+ // re-observation never moved along it, so a heavily-reinforced node would
18923
+ // decay exactly as fast as one nobody has mentioned since.
18924
+ ...reinforcedSeqAttrs(store, existing.label),
18892
18925
  lastUpdatedAt: opts.ts
18893
18926
  });
18894
18927
  }
18895
18928
  } else {
18896
18929
  created = true;
18897
18930
  store.mergeNode(
18898
- buildNode(problemId, "Problem", statement, opts.ts, {
18931
+ buildNode(store, problemId, "Problem", statement, opts.ts, {
18899
18932
  source: "convo",
18900
18933
  provisional: true,
18901
18934
  kind: flag.kind ?? "problem",
@@ -18910,7 +18943,7 @@ function ingestDesignProblem(store, flag, opts) {
18910
18943
  if (flag.cause?.trim()) {
18911
18944
  rootCauseId = `dcause_${digest({ problemId, cause: flag.cause })}`.slice(0, 56);
18912
18945
  store.mergeNode(
18913
- buildNode(rootCauseId, "RootCause", flag.cause.trim(), opts.ts, {
18946
+ buildNode(store, rootCauseId, "RootCause", flag.cause.trim(), opts.ts, {
18914
18947
  source: "convo",
18915
18948
  provisional: true
18916
18949
  })
@@ -18921,7 +18954,7 @@ function ingestDesignProblem(store, flag, opts) {
18921
18954
  if (flag.fix?.trim()) {
18922
18955
  solutionId = `dfix_${digest({ problemId, fix: flag.fix })}`.slice(0, 56);
18923
18956
  store.mergeNode(
18924
- buildNode(solutionId, "Solution", flag.fix.trim(), opts.ts, {
18957
+ buildNode(store, solutionId, "Solution", flag.fix.trim(), opts.ts, {
18925
18958
  source: "convo",
18926
18959
  provisional: true,
18927
18960
  rationale: flag.fix.trim()
@@ -18961,6 +18994,8 @@ function mintPatternNode(store, name2, ts) {
18961
18994
  observedCount: (Number(node2.attrs["observedCount"]) || 1) + 1,
18962
18995
  ...aliases.length > 0 ? { aliasTexts: aliases } : {}
18963
18996
  },
18997
+ // Re-observing a Pattern is a REINFORCE on the same ruler as minting one.
18998
+ ...reinforcedSeqAttrs(store, node2.label),
18964
18999
  lastUpdatedAt: ts
18965
19000
  });
18966
19001
  return node2.id;
@@ -18981,7 +19016,7 @@ function mintPatternNode(store, name2, ts) {
18981
19016
  }
18982
19017
  if (best && bestCos >= PATTERN_DEDUP_COSINE) return reinforce(best, display);
18983
19018
  store.mergeNode({
18984
- ...buildNode(id, "Pattern", display, ts, { source: "convo", provisional: true, observedCount: 1 }),
19019
+ ...buildNode(store, id, "Pattern", display, ts, { source: "convo", provisional: true, observedCount: 1 }),
18985
19020
  // Embedded inline (sync hash) so the node participates in the gate
18986
19021
  // immediately — buildNode's empty embedding would leave every new pattern
18987
19022
  // invisible to dedup until the nightly embed pass.
@@ -18997,7 +19032,7 @@ function mintDomainNode(store, name2, ts) {
18997
19032
  const id = `dom_${digest({ domain: display.toLowerCase() })}`.slice(0, 56);
18998
19033
  if (!store.getNode(id)) {
18999
19034
  store.mergeNode(
19000
- buildNode(id, "Domain", display, ts, {
19035
+ buildNode(store, id, "Domain", display, ts, {
19001
19036
  source: "convo",
19002
19037
  provisional: true,
19003
19038
  canonicalId: genericCanonicalId("dom", { type: "Domain", description: display })
@@ -19028,7 +19063,7 @@ function mintCitedPackageNode(store, ref, ts) {
19028
19063
  const purl = `pkg:${eco}/${purlName}`;
19029
19064
  if (!store.getNode(purl)) {
19030
19065
  store.mergeNode(
19031
- buildNode(purl, "Package", name2, ts, {
19066
+ buildNode(store, purl, "Package", name2, ts, {
19032
19067
  purl,
19033
19068
  name: name2,
19034
19069
  ecosystem: eco,
@@ -19048,7 +19083,7 @@ function mintComponentNode(store, name2, ts) {
19048
19083
  const existing = store.getNode(slug2);
19049
19084
  if (!existing) {
19050
19085
  store.mergeNode(
19051
- buildNode(slug2, "Component", display, ts, {
19086
+ buildNode(store, slug2, "Component", display, ts, {
19052
19087
  name: display,
19053
19088
  source: "convo",
19054
19089
  provisional: true,
@@ -19255,7 +19290,7 @@ function closeDesignProblem(store, problemId, fixNote, t) {
19255
19290
  if (fixNote?.trim() && store.outEdges(problemId, ["SOLVED_BY"]).length === 0) {
19256
19291
  const solId = `dfix_${digest({ problemId, fix: fixNote })}`.slice(0, 56);
19257
19292
  store.mergeNode(
19258
- buildNode(solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
19293
+ buildNode(store, solId, "Solution", fixNote.trim(), t, { source: "convo", provisional: false })
19259
19294
  );
19260
19295
  mergeEdge(store, problemId, solId, "SOLVED_BY", t);
19261
19296
  }
@@ -20613,7 +20648,8 @@ var init_src4 = __esm({
20613
20648
  });
20614
20649
 
20615
20650
  // ../../packages/local-graph/src/triage.ts
20616
- function semNode(id, label, description, ts, attrs) {
20651
+ function semNode(store, id, label, description, ts, attrs) {
20652
+ const seq = SEMANTIC_NODE_LABELS.includes(label) ? store.nextIngestSeq() : void 0;
20617
20653
  return {
20618
20654
  id,
20619
20655
  label,
@@ -20631,6 +20667,7 @@ function semNode(id, label, description, ts, attrs) {
20631
20667
  isLandmark: false,
20632
20668
  community: null,
20633
20669
  stability: "unstable",
20670
+ ...seq !== void 0 ? { createdAtSeq: seq, lastReinforcedAtSeq: seq } : {},
20634
20671
  attrs
20635
20672
  };
20636
20673
  }
@@ -20661,7 +20698,7 @@ function recordTriageObservation(l2, obs, ts) {
20661
20698
  const buckets = [...triageContextBuckets(canonicalizeContext(obs.context)), TRIAGE_GLOBAL_BUCKET];
20662
20699
  l2.transaction(() => {
20663
20700
  if (!l2.getNode(presentingId)) {
20664
- l2.mergeNode(semNode(presentingId, "Problem", statement, ts, { scope: {} }));
20701
+ l2.mergeNode(semNode(l2, presentingId, "Problem", statement, ts, { scope: {} }));
20665
20702
  }
20666
20703
  const tri = l2.getNode(triageId);
20667
20704
  const seen = {
@@ -20675,7 +20712,7 @@ function recordTriageObservation(l2, obs, ts) {
20675
20712
  });
20676
20713
  } else {
20677
20714
  l2.mergeNode(
20678
- semNode(triageId, "Triage", `differential for: ${statement}`, ts, {
20715
+ semNode(l2, triageId, "Triage", `differential for: ${statement}`, ts, {
20679
20716
  statement,
20680
20717
  perContextSeen: seen
20681
20718
  })
@@ -20687,7 +20724,7 @@ function recordTriageObservation(l2, obs, ts) {
20687
20724
  }
20688
20725
  if (!l2.getNode(obs.causeId)) {
20689
20726
  l2.mergeNode(
20690
- semNode(obs.causeId, obs.causeLabel ?? "RootCause", obs.causeDescription ?? "(cause)", ts, {
20727
+ semNode(l2, obs.causeId, obs.causeLabel ?? "RootCause", obs.causeDescription ?? "(cause)", ts, {
20691
20728
  scope: {}
20692
20729
  })
20693
20730
  );
@@ -20751,7 +20788,7 @@ function recordCauseChainLink(l2, link, ts, attrs = {}) {
20751
20788
  [link.fromId, link.fromDescription],
20752
20789
  [link.toId, link.toDescription]
20753
20790
  ]) {
20754
- if (!l2.getNode(id)) l2.mergeNode(semNode(id, "RootCause", description, ts, { ...attrs }));
20791
+ if (!l2.getNode(id)) l2.mergeNode(semNode(l2, id, "RootCause", description, ts, { ...attrs }));
20755
20792
  }
20756
20793
  const edgeId2 = `edge_cb_${link.fromId}_${link.toId}`;
20757
20794
  if (!l2.getEdge(edgeId2)) {
@@ -20774,7 +20811,7 @@ function mintWorkspaceCausalFact(ws, fact, ts) {
20774
20811
  ws.transaction(() => {
20775
20812
  if (!ws.getNode(fact.causeId)) {
20776
20813
  ws.mergeNode(
20777
- semNode(fact.causeId, "RootCause", description, ts, {
20814
+ semNode(ws, fact.causeId, "RootCause", description, ts, {
20778
20815
  scope: {},
20779
20816
  ...fact.sessionId ? { sources: [fact.sessionId] } : {}
20780
20817
  })
@@ -21116,7 +21153,7 @@ function harvestTriageFences(l2, text, opts) {
21116
21153
  const fix = f.fix.trim();
21117
21154
  const fixId = `dfix_${digest({ cause: causeId, fix })}`.slice(0, 56);
21118
21155
  if (!l2.getNode(fixId)) {
21119
- l2.mergeNode(semNode(fixId, "Solution", fix, opts.ts, { scope: {} }));
21156
+ l2.mergeNode(semNode(l2, fixId, "Solution", fix, opts.ts, { scope: {} }));
21120
21157
  }
21121
21158
  const solEdgeId = `edge_sol_${causeId}_${fixId}`;
21122
21159
  if (!l2.getEdge(solEdgeId)) {
@@ -21799,6 +21836,169 @@ var init_principle_sync = __esm({
21799
21836
  }
21800
21837
  });
21801
21838
 
21839
+ // ../../packages/local-graph/src/mechanism-liveness.ts
21840
+ function evaluateFed(store, d) {
21841
+ const column = COLUMN_INPUTS[d.fed.attr];
21842
+ const has = (n) => column ? column(n) : n.attrs[d.fed.attr] !== void 0;
21843
+ const nodes = d.fed.labels.flatMap((label) => store.findNodesByLabel(label));
21844
+ let window2 = nodes;
21845
+ if (d.fed.recent !== void 0) {
21846
+ window2 = [...nodes].sort((a, b) => b.createdAt - a.createdAt).slice(0, d.fed.recent);
21847
+ }
21848
+ if (d.fed.sinceFirstStamp) {
21849
+ let anchor = Infinity;
21850
+ for (const n of window2) if (has(n) && n.createdAt < anchor) anchor = n.createdAt;
21851
+ window2 = anchor === Infinity ? [] : window2.filter((n) => n.createdAt >= anchor);
21852
+ }
21853
+ let count = 0;
21854
+ for (const n of window2) if (has(n)) count++;
21855
+ return { count, total: window2.length, fraction: window2.length === 0 ? 0 : count / window2.length };
21856
+ }
21857
+ function evaluateMechanisms(store, invocations = /* @__PURE__ */ new Map(), mechanisms = MECHANISMS) {
21858
+ return mechanisms.map((d) => {
21859
+ const fed = evaluateFed(store, d);
21860
+ const inv = invocations.get(d.pass);
21861
+ const effectCount = inv?.totals[d.effectCounter] ?? 0;
21862
+ const backlog = d.backlogCounter ? inv?.lastTotals?.[d.backlogCounter] : void 0;
21863
+ const backlogWas = d.backlogCounter ? inv?.firstTotals?.[d.backlogCounter] : void 0;
21864
+ const span = inv?.firstTs === void 0 ? 0 : inv.lastTs - inv.firstTs;
21865
+ 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);
21866
+ let verdict;
21867
+ if (!inv || inv.runs === 0) verdict = "never-invoked";
21868
+ else if (fed.fraction < d.fed.minFraction) verdict = "starved";
21869
+ else if (stalled) verdict = "stalled";
21870
+ else if (effectCount === 0) verdict = "no-effect";
21871
+ else verdict = "ok";
21872
+ return {
21873
+ id: d.id,
21874
+ what: d.what,
21875
+ pass: d.pass,
21876
+ fedCount: fed.count,
21877
+ fedTotal: fed.total,
21878
+ fedFraction: fed.fraction,
21879
+ minFraction: d.fed.minFraction,
21880
+ ...inv ? { lastInvokedMs: inv.lastTs } : {},
21881
+ runs: inv?.runs ?? 0,
21882
+ effectCount,
21883
+ ...backlog !== void 0 ? { backlog } : {},
21884
+ ...backlogWas !== void 0 ? { backlogWas } : {},
21885
+ ...inv?.firstTs !== void 0 ? { spanMs: span } : {},
21886
+ verdict,
21887
+ ...d.note ? { note: d.note } : {}
21888
+ };
21889
+ });
21890
+ }
21891
+ function formatMechanismStatus(rows, nowMs) {
21892
+ return rows.map((r) => {
21893
+ const pct = (r.fedFraction * 100).toFixed(r.fedFraction < 0.01 ? 2 : 1);
21894
+ const age = r.lastInvokedMs === void 0 ? "never" : `${Math.max(0, Math.round((nowMs - r.lastInvokedMs) / 6e4))}m ago`;
21895
+ const mark = r.verdict === "ok" ? "ok " : r.verdict === "no-effect" ? "IDLE" : r.verdict === "stalled" ? "STUCK" : "DEAD";
21896
+ const hours = r.spanMs === void 0 ? 0 : Math.floor(r.spanMs / 36e5);
21897
+ const over = hours >= 24 ? `${Math.floor(hours / 24)}d` : `${hours}h`;
21898
+ const trend = r.verdict === "stalled" && r.backlog !== void 0 ? ` \u2014 ${r.backlog} waiting${r.backlogWas !== void 0 ? ` (was ${r.backlogWas})` : ""}, none cleared in ${over}` : "";
21899
+ return `${mark.padEnd(6)}${r.id.padEnd(20)} invoked ${age.padEnd(9)} ` + `fed ${pct}% (${r.fedCount}/${r.fedTotal})`.padEnd(28) + `effect ${r.effectCount}` + trend + (r.verdict !== "ok" && r.note ? ` \u2014 ${r.note}` : "");
21900
+ });
21901
+ }
21902
+ function hasStarvedMechanism(rows) {
21903
+ return rows.some(
21904
+ (r) => r.verdict === "never-invoked" || r.verdict === "starved" || r.verdict === "stalled"
21905
+ );
21906
+ }
21907
+ var STALL_MIN_RUNS, STALL_MIN_SPAN_MS, MECHANISMS, COLUMN_INPUTS;
21908
+ var init_mechanism_liveness = __esm({
21909
+ "../../packages/local-graph/src/mechanism-liveness.ts"() {
21910
+ "use strict";
21911
+ STALL_MIN_RUNS = 3;
21912
+ STALL_MIN_SPAN_MS = 60 * 60 * 1e3;
21913
+ MECHANISMS = [
21914
+ {
21915
+ id: "fix-candidate-ask",
21916
+ what: "asks an agent whether an edit to a problem's anchor fixed it",
21917
+ pass: "semantic-maintenance",
21918
+ // markFixCandidates fails CLOSED on a File anchor with no contentChangedAt —
21919
+ // correct (the alternative manufactured 92 asks out of no-op reindexes) and
21920
+ // exactly why coverage must be watched rather than assumed. Measured over
21921
+ // the recently-TOUCHED files, because the stamp is forward-only: whole-corpus
21922
+ // coverage on this store is ~0.5% and says nothing about whether the
21923
+ // producer works.
21924
+ fed: { labels: ["File"], attr: "contentChangedAt", minFraction: 0.02, recent: 200 },
21925
+ effectCounter: "fixCandidatesSettled",
21926
+ // Standing asks ARE the queue: 94 of them sat forever while the sweep
21927
+ // reported zero every run, and nothing could tell that from a clean backlog.
21928
+ backlogCounter: "fixCandidatesStanding",
21929
+ note: "stamped forward-only; measured over the 200 newest File nodes"
21930
+ },
21931
+ {
21932
+ id: "revisit-sweep",
21933
+ what: "retires a revisit ask once its recorded condition is met",
21934
+ pass: "semantic-maintenance",
21935
+ fed: {
21936
+ labels: ["Solution", "Problem", "RootCause", "Pattern"],
21937
+ attr: "revisitAnsweredWhen",
21938
+ // Only FLAGGED nodes carry it, and flags are rare by design, so the bar is
21939
+ // "the field is written at all" — it was written zero times before this.
21940
+ minFraction: 0
21941
+ },
21942
+ effectCounter: "revisitsCleared",
21943
+ backlogCounter: "revisitsStanding"
21944
+ },
21945
+ {
21946
+ id: "ingest-sequence",
21947
+ what: "orders knowledge arrivals so decay is driven by superseding info, not the clock",
21948
+ // CAPTURE, not semantic-maintenance. The sequence advances where knowledge
21949
+ // ENTERS the graph, and the maintenance pass never mints — so pointing this
21950
+ // at maintenance named a counter that is structurally always zero and the
21951
+ // mechanism read IDLE forever while stamping every new node. A descriptor
21952
+ // that cannot report an effect is the same defect it exists to detect.
21953
+ pass: "capture",
21954
+ fed: {
21955
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
21956
+ attr: "__createdAtSeq",
21957
+ // UNIVERSAL stamp: every semantic node minted after the producer went live
21958
+ // carries a sequence position, so the honest metric is "of the nodes born
21959
+ // since the first stamp, how many are stamped" — an invariant that should
21960
+ // read ~1.0 always. The 173k pre-fix nodes are deliberately never
21961
+ // backfilled (inventing a sequence position would feed the decay math
21962
+ // fabricated evidence it would read as real), and a recent-N window would
21963
+ // have to turn over 50 nodes before it could go green: it read 6% while
21964
+ // the producer was verifiably stamping every new node.
21965
+ minFraction: 0.9,
21966
+ recent: 200,
21967
+ sinceFirstStamp: true
21968
+ },
21969
+ effectCounter: "seqAdvanced",
21970
+ note: "column, not attr; measured over nodes born since the first stamp in the recent window"
21971
+ },
21972
+ {
21973
+ id: "render-ledger",
21974
+ what: "records which priors actually reached the agent, so an answer rate has a denominator",
21975
+ // RENDER, not semantic-maintenance — `shown` only moves during a render, so
21976
+ // attributing it elsewhere named an always-zero counter (same defect as
21977
+ // ingest-sequence's, found alongside it).
21978
+ pass: "render",
21979
+ fed: {
21980
+ labels: ["Problem", "Solution", "RootCause", "Pattern"],
21981
+ attr: "shownCount",
21982
+ minFraction: 5e-3
21983
+ },
21984
+ effectCounter: "shown"
21985
+ },
21986
+ {
21987
+ id: "orphan-reap",
21988
+ what: "closes File nodes whose path the indexer no longer covers",
21989
+ pass: "orphan-reap",
21990
+ // Stranded lineage is the CONDITION this clears, so a rising reading is bad;
21991
+ // it is declared fed-by-liveness so the row exists and the pass is watched.
21992
+ fed: { labels: ["File"], attr: "relPath", minFraction: 0.9 },
21993
+ effectCounter: "reaped"
21994
+ }
21995
+ ];
21996
+ COLUMN_INPUTS = {
21997
+ __createdAtSeq: (n) => n.createdAtSeq !== void 0 && n.createdAtSeq !== null
21998
+ };
21999
+ }
22000
+ });
22001
+
21802
22002
  // ../../packages/local-graph/src/index.ts
21803
22003
  var src_exports2 = {};
21804
22004
  __export(src_exports2, {
@@ -21812,12 +22012,15 @@ __export(src_exports2, {
21812
22012
  JOINT_COMMUNITY_EDGES: () => JOINT_COMMUNITY_EDGES,
21813
22013
  JOINT_COMMUNITY_LABELS: () => JOINT_COMMUNITY_LABELS,
21814
22014
  MAX_ANCHOR_FILES: () => MAX_ANCHOR_FILES,
22015
+ MECHANISMS: () => MECHANISMS,
21815
22016
  MIN_INTENT_TOKENS: () => MIN_INTENT_TOKENS,
21816
22017
  PATTERN_DEDUP_COSINE: () => PATTERN_DEDUP_COSINE,
21817
22018
  PERCOLATING_DRIFT_EDGES: () => PERCOLATING_DRIFT_EDGES,
21818
22019
  PERCOLATING_EDGES: () => PERCOLATING_EDGES,
21819
22020
  PERCOLATING_LABELS: () => PERCOLATING_LABELS,
21820
22021
  SAME_ANCHOR_DEDUP_JACCARD: () => SAME_ANCHOR_DEDUP_JACCARD,
22022
+ STALL_MIN_RUNS: () => STALL_MIN_RUNS,
22023
+ STALL_MIN_SPAN_MS: () => STALL_MIN_SPAN_MS,
21821
22024
  SqliteGraphStore: () => SqliteGraphStore,
21822
22025
  addDependency: () => addDependency,
21823
22026
  aggregateClaimConfidence: () => aggregateClaimConfidence,
@@ -21851,14 +22054,18 @@ __export(src_exports2, {
21851
22054
  detectLocalCommunities: () => detectLocalCommunities,
21852
22055
  edgeConductance: () => edgeConductance,
21853
22056
  evaluateDependency: () => evaluateDependency,
22057
+ evaluateFed: () => evaluateFed,
22058
+ evaluateMechanisms: () => evaluateMechanisms,
21854
22059
  findMintTimeDuplicate: () => findMintTimeDuplicate,
21855
22060
  findOrCreatePackage: () => findOrCreatePackage,
21856
22061
  findPath: () => findPath,
21857
22062
  flattenCloudCounts: () => flattenCloudCounts,
21858
22063
  foldDuplicateProblem: () => foldDuplicateProblem,
22064
+ formatMechanismStatus: () => formatMechanismStatus,
21859
22065
  getClaim: () => getClaim,
21860
22066
  harvestAbstractionFences: () => harvestAbstractionFences,
21861
22067
  harvestTriageFences: () => harvestTriageFences,
22068
+ hasStarvedMechanism: () => hasStarvedMechanism,
21862
22069
  induceAbstractions: () => induceAbstractions,
21863
22070
  induceTriage: () => induceTriage,
21864
22071
  ingestDesignProblem: () => ingestDesignProblem,
@@ -21948,6 +22155,7 @@ var init_src5 = __esm({
21948
22155
  init_problem_package_link();
21949
22156
  init_tools();
21950
22157
  init_principle_sync();
22158
+ init_mechanism_liveness();
21951
22159
  }
21952
22160
  });
21953
22161
 
@@ -28477,7 +28685,7 @@ var init_motifs = __esm({
28477
28685
  });
28478
28686
 
28479
28687
  // ../../packages/generalizer/src/nightly.ts
28480
- function runNightlyPipeline(store) {
28688
+ function runGraphRescore(store) {
28481
28689
  const started2 = Date.now();
28482
28690
  const allowedTypes = new Set(pagerankEdgeTypes());
28483
28691
  const nodeIds = [];
@@ -28560,11 +28768,6 @@ function runNightlyPipeline(store) {
28560
28768
  for (const [id, c] of comm.community) store.updateNode(id, { community: c });
28561
28769
  });
28562
28770
  const motifs = promoteMotifs(store, started2);
28563
- reopenAutoClosedProblems(store, started2);
28564
- const revisits = clearAnsweredRevisits(store, started2);
28565
- const fixCandidates = clearSettledFixCandidates(store, started2);
28566
- const designResolved = markFixCandidates(store, started2);
28567
- const cry = crystallize(store, { ts: started2 });
28568
28771
  return {
28569
28772
  scoredNodes: scored,
28570
28773
  iterations: result.iterations,
@@ -28574,17 +28777,51 @@ function runNightlyPipeline(store) {
28574
28777
  motifsPromoted: motifs.promoted,
28575
28778
  techniques: motifs.techniques,
28576
28779
  antipatterns: motifs.antipatterns,
28577
- skillsInduced: 0,
28578
- // skills are cloud-induced now (see above)
28579
- skillsRefreshed: 0,
28780
+ durationMs: Date.now() - started2
28781
+ };
28782
+ }
28783
+ function runSemanticMaintenance(store) {
28784
+ const started2 = Date.now();
28785
+ reopenAutoClosedProblems(store, started2);
28786
+ const revisits = clearAnsweredRevisits(store, started2);
28787
+ const fixCandidates = clearSettledFixCandidates(store, started2);
28788
+ const designResolved = markFixCandidates(store, started2);
28789
+ const cry = crystallize(store, { ts: started2 });
28790
+ return {
28580
28791
  designResolved,
28581
28792
  revisitsCleared: revisits.cleared,
28793
+ revisitsStanding: revisits.standing,
28582
28794
  fixCandidatesSettled: fixCandidates.answered + fixCandidates.ignored + fixCandidates.unsubstantiated,
28795
+ fixCandidates,
28583
28796
  claimsEvaluated: cry.evaluated,
28584
28797
  claimsDerived: cry.derived.length,
28585
28798
  durationMs: Date.now() - started2
28586
28799
  };
28587
28800
  }
28801
+ function runNightlyPipeline(store) {
28802
+ const started2 = Date.now();
28803
+ const rescore = runGraphRescore(store);
28804
+ const semantic = runSemanticMaintenance(store);
28805
+ return {
28806
+ scoredNodes: rescore.scoredNodes,
28807
+ iterations: rescore.iterations,
28808
+ converged: rescore.converged,
28809
+ landmarks: rescore.landmarks,
28810
+ communities: rescore.communities,
28811
+ motifsPromoted: rescore.motifsPromoted,
28812
+ techniques: rescore.techniques,
28813
+ antipatterns: rescore.antipatterns,
28814
+ skillsInduced: 0,
28815
+ // skills are cloud-induced now (see above)
28816
+ skillsRefreshed: 0,
28817
+ designResolved: semantic.designResolved,
28818
+ revisitsCleared: semantic.revisitsCleared,
28819
+ fixCandidatesSettled: semantic.fixCandidatesSettled,
28820
+ claimsEvaluated: semantic.claimsEvaluated,
28821
+ claimsDerived: semantic.claimsDerived,
28822
+ durationMs: Date.now() - started2
28823
+ };
28824
+ }
28588
28825
  function codeAnchorProjection(store, semanticIds, opts = {}) {
28589
28826
  const anchorToNodes = /* @__PURE__ */ new Map();
28590
28827
  for (const id of semanticIds) {
@@ -28874,7 +29111,9 @@ __export(src_exports4, {
28874
29111
  reconcileDiagnostics: () => reconcileDiagnostics,
28875
29112
  resolveProblem: () => resolveProblem,
28876
29113
  runGeneralizer: () => runGeneralizer,
29114
+ runGraphRescore: () => runGraphRescore,
28877
29115
  runNightlyPipeline: () => runNightlyPipeline,
29116
+ runSemanticMaintenance: () => runSemanticMaintenance,
28878
29117
  scoreCandidate: () => scoreCandidate,
28879
29118
  selectAnchorFrame: () => selectAnchorFrame
28880
29119
  });
@@ -29521,6 +29760,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
29521
29760
  };
29522
29761
  }
29523
29762
  const fileHashes = /* @__PURE__ */ new Map();
29763
+ const contentMovedPaths = /* @__PURE__ */ new Set();
29524
29764
  for (const rel of [...changedRelPaths]) {
29525
29765
  let h;
29526
29766
  try {
@@ -29533,6 +29773,8 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
29533
29773
  if (fnode && fnode.attrs["contentHash"] === h && !fileHasStrandedSymbol(store, fnode.id)) {
29534
29774
  store.updateNode(fnode.id, { lastUpdatedAt: t });
29535
29775
  changedRelPaths.delete(rel);
29776
+ } else if (!fnode || fnode.attrs["contentHash"] !== h) {
29777
+ contentMovedPaths.add(rel);
29536
29778
  }
29537
29779
  }
29538
29780
  if (changedRelPaths.size === 0) {
@@ -29777,12 +30019,11 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
29777
30019
  if (!h) continue;
29778
30020
  const fnode = store.getNode(fileNodeId(workspaceId2, rel));
29779
30021
  if (!fnode) continue;
29780
- const contentMoved = fnode.attrs["contentHash"] !== h;
29781
30022
  store.updateNode(fnode.id, {
29782
30023
  attrs: {
29783
30024
  ...fnode.attrs,
29784
30025
  contentHash: h,
29785
- ...contentMoved ? { contentChangedAt: t } : {}
30026
+ ...contentMovedPaths.has(rel) ? { contentChangedAt: t } : {}
29786
30027
  }
29787
30028
  });
29788
30029
  }
@@ -30355,7 +30596,7 @@ async function scan(root, current, ignores, providers, out2) {
30355
30596
  }
30356
30597
  }
30357
30598
  }
30358
- function gitListFiles(root, ignores, providers) {
30599
+ function gitListRelPaths(root, ignores) {
30359
30600
  let stdout;
30360
30601
  try {
30361
30602
  stdout = execFileSync(
@@ -30378,6 +30619,15 @@ function gitListFiles(root, ignores, providers) {
30378
30619
  if (segs.some((s) => ignores.has(s) || s.startsWith(".") && s.length > 1)) {
30379
30620
  continue;
30380
30621
  }
30622
+ out2.push(rel);
30623
+ }
30624
+ return out2;
30625
+ }
30626
+ function gitListFiles(root, ignores, providers) {
30627
+ const rels = gitListRelPaths(root, ignores);
30628
+ if (rels === null) return null;
30629
+ const out2 = [];
30630
+ for (const rel of rels) {
30381
30631
  const abs = join8(root, rel);
30382
30632
  let size;
30383
30633
  try {
@@ -37717,6 +37967,7 @@ var init_csharp_treesitter = __esm({
37717
37967
  // ../../packages/indexer/src/index.ts
37718
37968
  var src_exports5 = {};
37719
37969
  __export(src_exports5, {
37970
+ DEFAULT_IGNORES: () => DEFAULT_IGNORES,
37720
37971
  DRIFT_FORK_RATIO: () => DRIFT_FORK_RATIO,
37721
37972
  TreeSitterCSharpProvider: () => TreeSitterCSharpProvider,
37722
37973
  TreeSitterCppProvider: () => TreeSitterCppProvider,
@@ -37733,6 +37984,7 @@ __export(src_exports5, {
37733
37984
  findInnermostScope: () => findInnermostScope,
37734
37985
  folderNodeId: () => folderNodeId,
37735
37986
  fromHex: () => fromHex,
37987
+ gitListRelPaths: () => gitListRelPaths,
37736
37988
  hammingDistance: () => hammingDistance,
37737
37989
  hasForkedDrift: () => hasForkedDrift,
37738
37990
  incrementalReindex: () => incrementalReindex,
@@ -37845,6 +38097,8 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
37845
38097
  const fnode = store.getNode(fileNodeId(workspaceId2, rel));
37846
38098
  if (!fnode) {
37847
38099
  stale.push(abs);
38100
+ } else if ((fnode.validTo ?? null) !== null) {
38101
+ stale.push(abs);
37848
38102
  } else if (fnode.lastUpdatedAt < mtimeMs) {
37849
38103
  stale.push(abs);
37850
38104
  } else {
@@ -37880,19 +38134,67 @@ function findStrandedSymbols(store) {
37880
38134
  }
37881
38135
  return stranded;
37882
38136
  }
38137
+ function reapOrphanedFiles(store, rootPath, workspaceId2, ignoreDirs = []) {
38138
+ const ignores = /* @__PURE__ */ new Set([...DEFAULT_IGNORES, ...ignoreDirs]);
38139
+ const listed = gitListRelPaths(rootPath, ignores);
38140
+ if (listed === null) return { reaped: 0, symbolsClosed: 0, skipped: "no-git-listing" };
38141
+ if (listed.length === 0) return { reaped: 0, symbolsClosed: 0, skipped: "empty-listing" };
38142
+ const onDisk = new Set(listed);
38143
+ const live = store.findNodesByLabel("File").filter((f) => f.attrs["workspaceId"] === workspaceId2);
38144
+ const orphans = live.filter((f) => {
38145
+ const rel = f.attrs["relPath"];
38146
+ return typeof rel === "string" && !onDisk.has(rel);
38147
+ });
38148
+ const allowance = Math.max(ORPHAN_REAP_MIN_ALLOWANCE, live.length * ORPHAN_REAP_MAX_FRACTION);
38149
+ if (orphans.length > allowance) {
38150
+ return {
38151
+ reaped: 0,
38152
+ symbolsClosed: 0,
38153
+ skipped: "over-fraction",
38154
+ candidates: orphans.length
38155
+ };
38156
+ }
38157
+ const t = Date.now();
38158
+ let symbolsClosed = 0;
38159
+ store.transaction(() => {
38160
+ for (const f of orphans) {
38161
+ for (const e of store.outEdges(f.id, ["DEFINES", "CONTAINS"])) {
38162
+ store.closeEdge(e.id, t);
38163
+ const sym = store.getNode(e.to);
38164
+ if (sym && (sym.validTo ?? null) === null) {
38165
+ store.closeNode(sym.id, t);
38166
+ symbolsClosed++;
38167
+ }
38168
+ }
38169
+ store.closeNode(f.id, t);
38170
+ }
38171
+ });
38172
+ return { reaped: orphans.length, symbolsClosed };
38173
+ }
37883
38174
  async function reconcileStaleFiles(store, rootPath, workspaceId2) {
37884
38175
  const stale = await findStaleFiles(store, rootPath, workspaceId2);
37885
38176
  if (stale.length === 0) return 0;
37886
38177
  let total = 0;
38178
+ let failedBatches = 0;
37887
38179
  const BATCH = 20;
37888
38180
  for (let i2 = 0; i2 < stale.length; i2 += BATCH) {
37889
- const r = await incrementalReindex(store, rootPath, workspaceId2, stale.slice(i2, i2 + BATCH));
37890
- total += r.filesReindexed;
38181
+ try {
38182
+ const r = await incrementalReindex(store, rootPath, workspaceId2, stale.slice(i2, i2 + BATCH));
38183
+ total += r.filesReindexed;
38184
+ } catch (err2) {
38185
+ failedBatches++;
38186
+ console.warn(
38187
+ `[errata] reconcile: batch ${i2 / BATCH + 1} failed (${stale.slice(i2, i2 + BATCH).length} file(s) skipped): ${err2 instanceof Error ? err2.message : err2}`
38188
+ );
38189
+ }
37891
38190
  if (i2 + BATCH < stale.length) await new Promise((res) => setImmediate(res));
37892
38191
  }
38192
+ if (failedBatches > 0) {
38193
+ console.warn(`[errata] reconcile: ${failedBatches} batch(es) failed; ${total} file(s) reindexed`);
38194
+ }
37893
38195
  return total;
37894
38196
  }
37895
- var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, LIVENESS_CHUNK;
38197
+ var IGNORED, SOURCE_RE, SCAN_YIELD_EVERY, LIVENESS_CHUNK, ORPHAN_REAP_MAX_FRACTION, ORPHAN_REAP_MIN_ALLOWANCE;
37896
38198
  var init_reconcile = __esm({
37897
38199
  "src/reconcile.ts"() {
37898
38200
  "use strict";
@@ -37901,6 +38203,8 @@ var init_reconcile = __esm({
37901
38203
  SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
37902
38204
  SCAN_YIELD_EVERY = 100;
37903
38205
  LIVENESS_CHUNK = 4e3;
38206
+ ORPHAN_REAP_MAX_FRACTION = 0.25;
38207
+ ORPHAN_REAP_MIN_ALLOWANCE = 50;
37904
38208
  }
37905
38209
  });
37906
38210
 
@@ -48064,27 +48368,27 @@ __export(witness_ledger_exports, {
48064
48368
  summarizeWitnessLedger: () => summarizeWitnessLedger,
48065
48369
  witnessLedgerPath: () => witnessLedgerPath
48066
48370
  });
48067
- import { appendFileSync as appendFileSync2, existsSync as existsSync20, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "node:fs";
48068
- import { join as join25 } from "node:path";
48371
+ import { appendFileSync as appendFileSync3, existsSync as existsSync21, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "node:fs";
48372
+ import { join as join26 } from "node:path";
48069
48373
  function witnessLedgerPath(configDir) {
48070
- return join25(configDir, "witness-ledger.jsonl");
48374
+ return join26(configDir, "witness-ledger.jsonl");
48071
48375
  }
48072
48376
  function appendWitnessLedger(configDir, entry) {
48073
48377
  const path2 = witnessLedgerPath(configDir);
48074
48378
  try {
48075
- appendFileSync2(path2, JSON.stringify(entry) + "\n");
48076
- const lines = readFileSync20(path2, "utf8").split("\n").filter(Boolean);
48379
+ appendFileSync3(path2, JSON.stringify(entry) + "\n");
48380
+ const lines = readFileSync21(path2, "utf8").split("\n").filter(Boolean);
48077
48381
  if (lines.length > LEDGER_MAX_LINES) {
48078
- writeFileSync17(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
48382
+ writeFileSync18(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
48079
48383
  }
48080
48384
  } catch {
48081
48385
  }
48082
48386
  }
48083
48387
  function readWitnessLedger(configDir) {
48084
48388
  const path2 = witnessLedgerPath(configDir);
48085
- if (!existsSync20(path2)) return [];
48389
+ if (!existsSync21(path2)) return [];
48086
48390
  try {
48087
- return readFileSync20(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
48391
+ return readFileSync21(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
48088
48392
  } catch {
48089
48393
  return [];
48090
48394
  }
@@ -48510,12 +48814,12 @@ var init_report_render = __esm({
48510
48814
 
48511
48815
  // src/cli.ts
48512
48816
  init_src6();
48513
- import { closeSync as closeSync2, existsSync as existsSync27, openSync as openSync2, readFileSync as readFileSync26, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
48514
- import { join as join30 } from "node:path";
48817
+ import { closeSync as closeSync2, existsSync as existsSync28, openSync as openSync2, readFileSync as readFileSync27, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
48818
+ import { join as join31 } from "node:path";
48515
48819
  import { spawn as spawn3 } from "node:child_process";
48516
48820
 
48517
48821
  // src/daemon.ts
48518
- import { existsSync as existsSync22, writeFileSync as writeFileSync19 } from "node:fs";
48822
+ import { existsSync as existsSync23, writeFileSync as writeFileSync20 } from "node:fs";
48519
48823
 
48520
48824
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
48521
48825
  import { createServer as createServerHTTP } from "http";
@@ -49095,8 +49399,8 @@ init_config();
49095
49399
 
49096
49400
  // src/engine.ts
49097
49401
  import { execFileSync as execFileSync3 } from "node:child_process";
49098
- import { existsSync as existsSync21, statSync as statSync5, appendFileSync as appendFileSync3, readdirSync as readdirSync9, renameSync as renameSync3, readFileSync as readFileSync21, writeFileSync as writeFileSync18 } from "node:fs";
49099
- import { join as join26, relative as relative6, sep as sep4 } from "node:path";
49402
+ import { existsSync as existsSync22, statSync as statSync5, appendFileSync as appendFileSync4, readdirSync as readdirSync9, renameSync as renameSync3, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "node:fs";
49403
+ import { join as join27, relative as relative6, sep as sep4 } from "node:path";
49100
49404
 
49101
49405
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
49102
49406
  import { stat as statcb } from "fs";
@@ -52195,6 +52499,48 @@ function repairInvalidEdges(store, opts) {
52195
52499
  init_symbol_summaries();
52196
52500
  init_reconcile();
52197
52501
 
52502
+ // src/pass-ledger.ts
52503
+ import { appendFileSync as appendFileSync2, existsSync as existsSync15, readFileSync as readFileSync13, writeFileSync as writeFileSync13 } from "node:fs";
52504
+ import { join as join18 } from "node:path";
52505
+ var PER_KIND_MAX = 100;
52506
+ var TRIM_EVERY = 50;
52507
+ var appendsSinceTrim = /* @__PURE__ */ new Map();
52508
+ function passLedgerPath(configDir) {
52509
+ return join18(configDir, "pass-ledger.jsonl");
52510
+ }
52511
+ function appendPassLedger(configDir, kind, durationMs, counts) {
52512
+ const path2 = passLedgerPath(configDir);
52513
+ try {
52514
+ const entry = { ts: Date.now(), kind, durationMs, counts };
52515
+ appendFileSync2(path2, JSON.stringify(entry) + "\n");
52516
+ const n = (appendsSinceTrim.get(path2) ?? 0) + 1;
52517
+ if (n < TRIM_EVERY) {
52518
+ appendsSinceTrim.set(path2, n);
52519
+ return;
52520
+ }
52521
+ appendsSinceTrim.set(path2, 0);
52522
+ const lines = readFileSync13(path2, "utf8").split("\n").filter(Boolean);
52523
+ const keptByKind = /* @__PURE__ */ new Map();
52524
+ const kept = [];
52525
+ for (let i2 = lines.length - 1; i2 >= 0; i2--) {
52526
+ let kind2;
52527
+ try {
52528
+ kind2 = String(JSON.parse(lines[i2]).kind ?? "");
52529
+ } catch {
52530
+ continue;
52531
+ }
52532
+ const n2 = keptByKind.get(kind2) ?? 0;
52533
+ if (n2 >= PER_KIND_MAX) continue;
52534
+ keptByKind.set(kind2, n2 + 1);
52535
+ kept.push(lines[i2]);
52536
+ }
52537
+ if (kept.length < lines.length) {
52538
+ writeFileSync13(path2, kept.reverse().join("\n") + "\n");
52539
+ }
52540
+ } catch {
52541
+ }
52542
+ }
52543
+
52198
52544
  // src/episode.ts
52199
52545
  init_src();
52200
52546
  function deltaIsEmpty(d) {
@@ -52389,11 +52735,11 @@ init_outbox();
52389
52735
  init_src9();
52390
52736
  init_src();
52391
52737
  init_src2();
52392
- import { readFileSync as readFileSync13 } from "node:fs";
52393
- import { join as join18 } from "node:path";
52738
+ import { readFileSync as readFileSync14 } from "node:fs";
52739
+ import { join as join19 } from "node:path";
52394
52740
  function loadClaimIgnorePatterns(workspaceRoot) {
52395
52741
  try {
52396
- return readFileSync13(join18(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
52742
+ return readFileSync14(join19(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
52397
52743
  } catch {
52398
52744
  return [];
52399
52745
  }
@@ -52754,22 +53100,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
52754
53100
  }
52755
53101
 
52756
53102
  // src/git-sensor.ts
52757
- import { existsSync as existsSync15, readFileSync as readFileSync14, watch as fsWatch } from "node:fs";
52758
- import { join as join19 } from "node:path";
53103
+ import { existsSync as existsSync16, readFileSync as readFileSync15, watch as fsWatch } from "node:fs";
53104
+ import { join as join20 } from "node:path";
52759
53105
  function readFirstLine(path2) {
52760
53106
  try {
52761
- return readFileSync14(path2, "utf8").split(/\r?\n/, 1)[0].trim();
53107
+ return readFileSync15(path2, "utf8").split(/\r?\n/, 1)[0].trim();
52762
53108
  } catch {
52763
53109
  return null;
52764
53110
  }
52765
53111
  }
52766
53112
  function readGitRefState(gitDir) {
52767
- const head2 = readFirstLine(join19(gitDir, "HEAD"));
53113
+ const head2 = readFirstLine(join20(gitDir, "HEAD"));
52768
53114
  const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
52769
53115
  const branch = m ? m[1] : null;
52770
53116
  let sha2 = null;
52771
53117
  if (branch) {
52772
- sha2 = readFirstLine(join19(gitDir, "refs", "heads", branch));
53118
+ sha2 = readFirstLine(join20(gitDir, "refs", "heads", branch));
52773
53119
  if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
52774
53120
  } else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
52775
53121
  sha2 = head2;
@@ -52777,13 +53123,13 @@ function readGitRefState(gitDir) {
52777
53123
  return {
52778
53124
  branch,
52779
53125
  sha: sha2,
52780
- mergeHeadExists: existsSync15(join19(gitDir, "MERGE_HEAD")),
52781
- origHeadExists: existsSync15(join19(gitDir, "ORIG_HEAD"))
53126
+ mergeHeadExists: existsSync16(join20(gitDir, "MERGE_HEAD")),
53127
+ origHeadExists: existsSync16(join20(gitDir, "ORIG_HEAD"))
52782
53128
  };
52783
53129
  }
52784
53130
  function shaFromPackedRefs(gitDir, ref) {
52785
53131
  try {
52786
- for (const line of readFileSync14(join19(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
53132
+ for (const line of readFileSync15(join20(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
52787
53133
  const [sha2, name2] = line.split(/\s+/);
52788
53134
  if (name2 === ref && sha2) return sha2;
52789
53135
  }
@@ -52817,7 +53163,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
52817
53163
  const settle = () => {
52818
53164
  if (timer) clearTimeout(timer);
52819
53165
  timer = setTimeout(() => {
52820
- if (existsSync15(join19(gitDir, "index.lock"))) {
53166
+ if (existsSync16(join20(gitDir, "index.lock"))) {
52821
53167
  settle();
52822
53168
  return;
52823
53169
  }
@@ -52828,7 +53174,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
52828
53174
  }, debounceMs);
52829
53175
  };
52830
53176
  for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
52831
- const p = join19(gitDir, sub);
53177
+ const p = join20(gitDir, sub);
52832
53178
  try {
52833
53179
  watchers.push(fsWatch(p, settle));
52834
53180
  } catch {
@@ -53053,21 +53399,21 @@ var TelemetryRecorder = class {
53053
53399
 
53054
53400
  // src/skills.ts
53055
53401
  import {
53056
- existsSync as existsSync16,
53402
+ existsSync as existsSync17,
53057
53403
  mkdirSync as mkdirSync6,
53058
- readFileSync as readFileSync15,
53404
+ readFileSync as readFileSync16,
53059
53405
  readdirSync as readdirSync7,
53060
53406
  unlinkSync as unlinkSync2,
53061
- writeFileSync as writeFileSync13
53407
+ writeFileSync as writeFileSync14
53062
53408
  } from "node:fs";
53063
- import { basename as basename4, join as join20 } from "node:path";
53409
+ import { basename as basename4, join as join21 } from "node:path";
53064
53410
  function skillFileName(id) {
53065
53411
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
53066
53412
  }
53067
53413
  function readSkillManifest(manifestPath) {
53068
- if (!existsSync16(manifestPath)) return [];
53414
+ if (!existsSync17(manifestPath)) return [];
53069
53415
  try {
53070
- const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
53416
+ const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
53071
53417
  return (parsed.skills ?? []).map((s) => ({
53072
53418
  title: s.title ?? "",
53073
53419
  layer: s.layer ?? "technique",
@@ -53091,7 +53437,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53091
53437
  for (const s of res.skills) {
53092
53438
  const fileName = skillFileName(s.id);
53093
53439
  keep.add(fileName);
53094
- writeFileSync13(join20(paths.skillsDir, fileName), s.markdown, "utf8");
53440
+ writeFileSync14(join21(paths.skillsDir, fileName), s.markdown, "utf8");
53095
53441
  rows.push({
53096
53442
  id: s.id,
53097
53443
  title: s.title,
@@ -53104,7 +53450,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53104
53450
  const fileName = skillFileName(p.id);
53105
53451
  if (keep.has(fileName)) continue;
53106
53452
  keep.add(fileName);
53107
- writeFileSync13(join20(paths.skillsDir, fileName), p.markdown, "utf8");
53453
+ writeFileSync14(join21(paths.skillsDir, fileName), p.markdown, "utf8");
53108
53454
  rows.push({
53109
53455
  id: p.id,
53110
53456
  title: p.title,
@@ -53118,13 +53464,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53118
53464
  if (!f.endsWith(".md")) continue;
53119
53465
  if (keep.has(basename4(f))) continue;
53120
53466
  try {
53121
- unlinkSync2(join20(paths.skillsDir, f));
53467
+ unlinkSync2(join21(paths.skillsDir, f));
53122
53468
  pruned++;
53123
53469
  } catch {
53124
53470
  }
53125
53471
  }
53126
53472
  rows.sort((a, b) => a.id.localeCompare(b.id));
53127
- writeFileSync13(
53473
+ writeFileSync14(
53128
53474
  paths.skillsManifest,
53129
53475
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
53130
53476
  "utf8"
@@ -53136,22 +53482,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53136
53482
  init_src2();
53137
53483
  import {
53138
53484
  cpSync,
53139
- existsSync as existsSync17,
53485
+ existsSync as existsSync18,
53140
53486
  lstatSync,
53141
53487
  mkdirSync as mkdirSync7,
53142
- readFileSync as readFileSync16,
53488
+ readFileSync as readFileSync17,
53143
53489
  readdirSync as readdirSync8,
53144
53490
  rmSync as rmSync2,
53145
53491
  symlinkSync,
53146
- writeFileSync as writeFileSync14
53492
+ writeFileSync as writeFileSync15
53147
53493
  } from "node:fs";
53148
- import { join as join21 } from "node:path";
53494
+ import { join as join22 } from "node:path";
53149
53495
  var SKILL_NS = "errata-";
53150
53496
  var HARNESS_SKILL_DIRS = [
53151
- { configDir: ".claude", skillsDir: join21(".claude", "skills") },
53497
+ { configDir: ".claude", skillsDir: join22(".claude", "skills") },
53152
53498
  // Cursor adopted the standard; its exact project dir is still moving — kept
53153
53499
  // best-effort and gated on `.cursor/` presence so we never create it blind.
53154
- { configDir: ".cursor", skillsDir: join21(".cursor", "skills") }
53500
+ { configDir: ".cursor", skillsDir: join22(".cursor", "skills") }
53155
53501
  ];
53156
53502
  function skillSlug(title, id) {
53157
53503
  const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
@@ -53196,12 +53542,12 @@ function skillCiteHandle(s) {
53196
53542
  return priorHandle({ id: s.id, description: s.title });
53197
53543
  }
53198
53544
  function reconcileNamespaced(dir, keep) {
53199
- if (!existsSync17(dir)) return 0;
53545
+ if (!existsSync18(dir)) return 0;
53200
53546
  let pruned = 0;
53201
53547
  for (const name2 of readdirSync8(dir)) {
53202
53548
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
53203
53549
  try {
53204
- rmSync2(join21(dir, name2), { recursive: true, force: true });
53550
+ rmSync2(join22(dir, name2), { recursive: true, force: true });
53205
53551
  pruned++;
53206
53552
  } catch {
53207
53553
  }
@@ -53210,7 +53556,7 @@ function reconcileNamespaced(dir, keep) {
53210
53556
  }
53211
53557
  function linkOrCopy(linkPath, target) {
53212
53558
  try {
53213
- if (existsSync17(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
53559
+ if (existsSync18(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
53214
53560
  } catch {
53215
53561
  }
53216
53562
  try {
@@ -53231,7 +53577,7 @@ function safeLstat(p) {
53231
53577
  }
53232
53578
  }
53233
53579
  function emitAndProjectSkills(root, skills) {
53234
- const agentsSkillsDir = join21(root, ".agents", "skills");
53580
+ const agentsSkillsDir = join22(root, ".agents", "skills");
53235
53581
  mkdirSync7(agentsSkillsDir, { recursive: true });
53236
53582
  const slugs = [];
53237
53583
  const keep = /* @__PURE__ */ new Set();
@@ -53239,7 +53585,7 @@ function emitAndProjectSkills(root, skills) {
53239
53585
  for (const s of skills) {
53240
53586
  let body2;
53241
53587
  try {
53242
- body2 = readFileSync16(s.bodyPath, "utf8");
53588
+ body2 = readFileSync17(s.bodyPath, "utf8");
53243
53589
  } catch {
53244
53590
  continue;
53245
53591
  }
@@ -53248,9 +53594,9 @@ function emitAndProjectSkills(root, skills) {
53248
53594
  keep.add(slug2);
53249
53595
  slugs.push(slug2);
53250
53596
  const description = deriveDescription(s.title, s.layer, body2);
53251
- mkdirSync7(join21(agentsSkillsDir, slug2), { recursive: true });
53252
- writeFileSync14(
53253
- join21(agentsSkillsDir, slug2, "SKILL.md"),
53597
+ mkdirSync7(join22(agentsSkillsDir, slug2), { recursive: true });
53598
+ writeFileSync15(
53599
+ join22(agentsSkillsDir, slug2, "SKILL.md"),
53254
53600
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
53255
53601
  "utf8"
53256
53602
  );
@@ -53259,11 +53605,11 @@ function emitAndProjectSkills(root, skills) {
53259
53605
  reconcileNamespaced(agentsSkillsDir, keep);
53260
53606
  let projected = 0;
53261
53607
  for (const h of HARNESS_SKILL_DIRS) {
53262
- if (!existsSync17(join21(root, h.configDir))) continue;
53263
- const dir = join21(root, h.skillsDir);
53608
+ if (!existsSync18(join22(root, h.configDir))) continue;
53609
+ const dir = join22(root, h.skillsDir);
53264
53610
  mkdirSync7(dir, { recursive: true });
53265
53611
  for (const slug2 of slugs) {
53266
- linkOrCopy(join21(dir, slug2), join21(agentsSkillsDir, slug2));
53612
+ linkOrCopy(join22(dir, slug2), join22(agentsSkillsDir, slug2));
53267
53613
  projected++;
53268
53614
  }
53269
53615
  reconcileNamespaced(dir, keep);
@@ -53272,15 +53618,15 @@ function emitAndProjectSkills(root, skills) {
53272
53618
  return { slugs, emitted, projected };
53273
53619
  }
53274
53620
  function emitInputsFromManifest(erretaDir, manifestPath) {
53275
- if (!existsSync17(manifestPath)) return [];
53621
+ if (!existsSync18(manifestPath)) return [];
53276
53622
  try {
53277
- const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
53623
+ const parsed = JSON.parse(readFileSync17(manifestPath, "utf8"));
53278
53624
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
53279
53625
  id: s.id,
53280
53626
  title: s.title ?? s.id,
53281
53627
  layer: s.layer ?? "technique",
53282
53628
  confidence: s.confidence ?? 0,
53283
- bodyPath: join21(erretaDir, s.file)
53629
+ bodyPath: join22(erretaDir, s.file)
53284
53630
  }));
53285
53631
  } catch {
53286
53632
  return [];
@@ -53294,17 +53640,17 @@ var GITIGNORE_LINES = [
53294
53640
  ".cursor/skills/errata-*/"
53295
53641
  ];
53296
53642
  function ensureSkillGitignore(root) {
53297
- const path2 = join21(root, ".gitignore");
53643
+ const path2 = join22(root, ".gitignore");
53298
53644
  let current = "";
53299
53645
  try {
53300
- current = existsSync17(path2) ? readFileSync16(path2, "utf8") : "";
53646
+ current = existsSync18(path2) ? readFileSync17(path2, "utf8") : "";
53301
53647
  } catch {
53302
53648
  return;
53303
53649
  }
53304
53650
  if (current.includes(GITIGNORE_MARK)) return;
53305
53651
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
53306
53652
  try {
53307
- writeFileSync14(path2, `${current}${prefix}
53653
+ writeFileSync15(path2, `${current}${prefix}
53308
53654
  ${GITIGNORE_LINES.join("\n")}
53309
53655
  `, "utf8");
53310
53656
  } catch {
@@ -53397,20 +53743,20 @@ init_paths();
53397
53743
  // src/profile.ts
53398
53744
  init_src2();
53399
53745
  init_paths();
53400
- import { existsSync as existsSync19, readFileSync as readFileSync18, writeFileSync as writeFileSync15 } from "node:fs";
53746
+ import { existsSync as existsSync20, readFileSync as readFileSync19, writeFileSync as writeFileSync16 } from "node:fs";
53401
53747
  import { createHash as createHash12 } from "node:crypto";
53402
- import { join as join23 } from "node:path";
53748
+ import { join as join24 } from "node:path";
53403
53749
 
53404
53750
  // src/git-remote.ts
53405
53751
  init_src();
53406
- import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync4 } from "node:fs";
53407
- import { isAbsolute as isAbsolute3, join as join22, resolve as resolve5 } from "node:path";
53752
+ import { existsSync as existsSync19, readFileSync as readFileSync18, statSync as statSync4 } from "node:fs";
53753
+ import { isAbsolute as isAbsolute3, join as join23, resolve as resolve5 } from "node:path";
53408
53754
  function resolveGitDir(root) {
53409
- const dotGit = join22(root, ".git");
53755
+ const dotGit = join23(root, ".git");
53410
53756
  try {
53411
53757
  const st = statSync4(dotGit);
53412
53758
  if (st.isDirectory()) return dotGit;
53413
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync17(dotGit, "utf8"));
53759
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync18(dotGit, "utf8"));
53414
53760
  if (!m) return null;
53415
53761
  const dir = m[1];
53416
53762
  return isAbsolute3(dir) ? dir : resolve5(root, dir);
@@ -53419,22 +53765,22 @@ function resolveGitDir(root) {
53419
53765
  }
53420
53766
  }
53421
53767
  function gitConfigPath(gitDir) {
53422
- const commondirFile = join22(gitDir, "commondir");
53423
- if (existsSync18(commondirFile)) {
53424
- const common = readFileSync17(commondirFile, "utf8").trim();
53768
+ const commondirFile = join23(gitDir, "commondir");
53769
+ if (existsSync19(commondirFile)) {
53770
+ const common = readFileSync18(commondirFile, "utf8").trim();
53425
53771
  const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
53426
- return join22(commonDir, "config");
53772
+ return join23(commonDir, "config");
53427
53773
  }
53428
- return join22(gitDir, "config");
53774
+ return join23(gitDir, "config");
53429
53775
  }
53430
53776
  function readRemotes(root) {
53431
53777
  const gitDir = resolveGitDir(root);
53432
53778
  if (!gitDir) return [];
53433
53779
  const cfgPath = gitConfigPath(gitDir);
53434
- if (!existsSync18(cfgPath)) return [];
53780
+ if (!existsSync19(cfgPath)) return [];
53435
53781
  let txt;
53436
53782
  try {
53437
- txt = readFileSync17(cfgPath, "utf8");
53783
+ txt = readFileSync18(cfgPath, "utf8");
53438
53784
  } catch {
53439
53785
  return [];
53440
53786
  }
@@ -53476,13 +53822,13 @@ function refreshRepoLocator(root, profile) {
53476
53822
  }
53477
53823
  function loadProfile(root) {
53478
53824
  const p = workspacePaths(root);
53479
- if (!existsSync19(p.workspaceJson)) return null;
53480
- return JSON.parse(readFileSync18(p.workspaceJson, "utf8"));
53825
+ if (!existsSync20(p.workspaceJson)) return null;
53826
+ return JSON.parse(readFileSync19(p.workspaceJson, "utf8"));
53481
53827
  }
53482
53828
  function saveProfile(root, profile) {
53483
53829
  const p = workspacePaths(root);
53484
53830
  ensureDir(p.configDir);
53485
- writeFileSync15(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
53831
+ writeFileSync16(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
53486
53832
  }
53487
53833
  function autodetectProfile(root) {
53488
53834
  const id = workspaceId(root);
@@ -53490,10 +53836,10 @@ function autodetectProfile(root) {
53490
53836
  const p = emptyProfile(id, name2);
53491
53837
  const locator = detectRepoLocator(root);
53492
53838
  if (locator) p.repoLocator = locator;
53493
- const pkgPath = join23(root, "package.json");
53494
- if (existsSync19(pkgPath)) {
53839
+ const pkgPath = join24(root, "package.json");
53840
+ if (existsSync20(pkgPath)) {
53495
53841
  try {
53496
- const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
53842
+ const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
53497
53843
  p.languages.push("typescript", "javascript");
53498
53844
  const nodeVer = pkg.engines?.node ?? "node";
53499
53845
  p.stack.push(`node@${nodeVer}`);
@@ -53514,10 +53860,10 @@ function autodetectProfile(root) {
53514
53860
  } catch {
53515
53861
  }
53516
53862
  }
53517
- const pyproject = join23(root, "pyproject.toml");
53518
- if (existsSync19(pyproject)) {
53863
+ const pyproject = join24(root, "pyproject.toml");
53864
+ if (existsSync20(pyproject)) {
53519
53865
  try {
53520
- const txt = readFileSync18(pyproject, "utf8");
53866
+ const txt = readFileSync19(pyproject, "utf8");
53521
53867
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
53522
53868
  p.languages.push("python");
53523
53869
  p.stack.push(`python@${py ?? "3"}`);
@@ -53528,16 +53874,16 @@ function autodetectProfile(root) {
53528
53874
  } catch {
53529
53875
  }
53530
53876
  }
53531
- const reqs = join23(root, "requirements.txt");
53532
- if (existsSync19(reqs)) {
53877
+ const reqs = join24(root, "requirements.txt");
53878
+ if (existsSync20(reqs)) {
53533
53879
  if (!p.languages.includes("python")) p.languages.push("python");
53534
53880
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
53535
53881
  }
53536
- if (existsSync19(join23(root, "go.mod"))) {
53882
+ if (existsSync20(join24(root, "go.mod"))) {
53537
53883
  p.languages.push("go");
53538
53884
  p.stack.push("go");
53539
53885
  }
53540
- if (existsSync19(join23(root, "Cargo.toml"))) {
53886
+ if (existsSync20(join24(root, "Cargo.toml"))) {
53541
53887
  p.languages.push("rust");
53542
53888
  p.stack.push("rust");
53543
53889
  }
@@ -53547,17 +53893,17 @@ function autodetectProfile(root) {
53547
53893
  }
53548
53894
 
53549
53895
  // src/witness-queue.ts
53550
- import { readFileSync as readFileSync19, renameSync as renameSync2, writeFileSync as writeFileSync16 } from "node:fs";
53551
- import { dirname as dirname9, join as join24 } from "node:path";
53896
+ import { readFileSync as readFileSync20, renameSync as renameSync2, writeFileSync as writeFileSync17 } from "node:fs";
53897
+ import { dirname as dirname9, join as join25 } from "node:path";
53552
53898
  var WITNESS_QUEUE_CAP = 500;
53553
53899
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
53554
53900
  var WITNESS_MAX_ATTEMPTS = 5;
53555
53901
  function witnessQueuePath(workspaceConfigDir) {
53556
- return join24(workspaceConfigDir, "witness-queue.json");
53902
+ return join25(workspaceConfigDir, "witness-queue.json");
53557
53903
  }
53558
53904
  function loadWitnessQueue(path2) {
53559
53905
  try {
53560
- const raw2 = JSON.parse(readFileSync19(path2, "utf8"));
53906
+ const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
53561
53907
  if (!Array.isArray(raw2)) return [];
53562
53908
  return raw2.filter(
53563
53909
  (w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
@@ -53568,8 +53914,8 @@ function loadWitnessQueue(path2) {
53568
53914
  }
53569
53915
  function saveWitnessQueue(path2, queue) {
53570
53916
  try {
53571
- const tmp = join24(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
53572
- writeFileSync16(tmp, JSON.stringify(queue), "utf8");
53917
+ const tmp = join25(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
53918
+ writeFileSync17(tmp, JSON.stringify(queue), "utf8");
53573
53919
  renameSync2(tmp, path2);
53574
53920
  } catch {
53575
53921
  }
@@ -53860,7 +54206,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53860
54206
  }
53861
54207
 
53862
54208
  // src/engine.ts
53863
- var DAEMON_VERSION = true ? "2.0.2-dev.513" : "2.0.0-alpha.0";
54209
+ var DAEMON_VERSION = true ? "2.0.2-dev.530" : "2.0.0-alpha.0";
53864
54210
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53865
54211
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53866
54212
  var GIT_OP_MUTE_MS = 4e3;
@@ -53870,17 +54216,17 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
53870
54216
  function appendIdentityAudit(path2, record2, line) {
53871
54217
  if (!record2.accepted && record2.score <= 0) return;
53872
54218
  try {
53873
- if (existsSync21(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
54219
+ if (existsSync22(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
53874
54220
  renameSync3(path2, `${path2}.1`);
53875
54221
  }
53876
- appendFileSync3(path2, line);
54222
+ appendFileSync4(path2, line);
53877
54223
  } catch {
53878
54224
  }
53879
54225
  }
53880
54226
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
53881
54227
  function loadTurnCursors(path2) {
53882
54228
  try {
53883
- const raw2 = JSON.parse(readFileSync21(path2, "utf8"));
54229
+ const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
53884
54230
  return new Map(
53885
54231
  Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
53886
54232
  );
@@ -53890,7 +54236,7 @@ function loadTurnCursors(path2) {
53890
54236
  }
53891
54237
  function loadTurnOffsets(path2) {
53892
54238
  try {
53893
- const raw2 = JSON.parse(readFileSync21(path2, "utf8"));
54239
+ const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
53894
54240
  const out2 = /* @__PURE__ */ new Map();
53895
54241
  for (const [k, v] of Object.entries(raw2)) {
53896
54242
  const off = typeof v === "object" && v !== null ? v.offset : void 0;
@@ -53906,7 +54252,7 @@ function saveTurnCursors(path2, cursors, offsets) {
53906
54252
  const merged = {};
53907
54253
  for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
53908
54254
  for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
53909
- writeFileSync18(path2, JSON.stringify(merged), "utf8");
54255
+ writeFileSync19(path2, JSON.stringify(merged), "utf8");
53910
54256
  } catch {
53911
54257
  }
53912
54258
  }
@@ -53928,7 +54274,7 @@ function gitSourceWatchTargets(root) {
53928
54274
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
53929
54275
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
53930
54276
  );
53931
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join26(root, d) + sep4));
54277
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join27(root, d) + sep4));
53932
54278
  } catch {
53933
54279
  }
53934
54280
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -53940,19 +54286,19 @@ function gitSourceWatchTargets(root) {
53940
54286
  if (!f.startsWith(prefix)) continue;
53941
54287
  const rest2 = f.slice(prefix.length);
53942
54288
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
53943
- else targets.add(join26(root, f));
54289
+ else targets.add(join27(root, f));
53944
54290
  }
53945
54291
  for (const c of children) {
53946
- if (IGNORED_PATH.test(join26(root, c) + sep4)) continue;
54292
+ if (IGNORED_PATH.test(join27(root, c) + sep4)) continue;
53947
54293
  if (hasIgnoredChild(c)) addUnder(c);
53948
- else targets.add(join26(root, c));
54294
+ else targets.add(join27(root, c));
53949
54295
  }
53950
54296
  };
53951
54297
  addUnder("");
53952
54298
  if (targets.size > 0) return [...targets];
53953
54299
  } catch {
53954
54300
  }
53955
- return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join26(root, String(e.name)) + sep4)).map((e) => join26(root, String(e.name)));
54301
+ return readdirSync9(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join27(root, String(e.name)) + sep4)).map((e) => join27(root, String(e.name)));
53956
54302
  }
53957
54303
  function createWorkspaceEngine(opts) {
53958
54304
  const paths = workspacePaths(opts.workspaceRoot);
@@ -54110,7 +54456,7 @@ function createWorkspaceEngine(opts) {
54110
54456
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
54111
54457
  let episodeId2;
54112
54458
  if (srcPaths.length > 0) {
54113
- const abs = srcPaths.map((p) => join26(opts.workspaceRoot, p));
54459
+ const abs = srcPaths.map((p) => join27(opts.workspaceRoot, p));
54114
54460
  try {
54115
54461
  const r = await runReindexPass(
54116
54462
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -54146,8 +54492,8 @@ function createWorkspaceEngine(opts) {
54146
54492
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
54147
54493
  );
54148
54494
  };
54149
- const gitDir = join26(opts.workspaceRoot, ".git");
54150
- if (existsSync21(gitDir)) {
54495
+ const gitDir = join27(opts.workspaceRoot, ".git");
54496
+ if (existsSync22(gitDir)) {
54151
54497
  stopGit = startGitSensor(gitDir, (ev) => {
54152
54498
  void handleGitEvent(ev).catch((err2) => {
54153
54499
  console.warn("[errata] git event handler failed:", err2);
@@ -54160,7 +54506,26 @@ function createWorkspaceEngine(opts) {
54160
54506
  if (n > 0) {
54161
54507
  console.log(`[errata] reconcile: re-indexed ${n} stale file(s) on startup`);
54162
54508
  }
54163
- }).catch((err2) => console.warn("[errata] startup reconcile failed:", err2));
54509
+ }).catch((err2) => console.warn("[errata] startup reconcile failed:", err2)).finally(() => {
54510
+ try {
54511
+ const reap = reapOrphanedFiles(store, opts.workspaceRoot, profile.id);
54512
+ appendPassLedger(paths.configDir, "orphan-reap", 0, {
54513
+ reaped: reap.reaped,
54514
+ symbolsClosed: reap.symbolsClosed
54515
+ });
54516
+ if (reap.skipped) {
54517
+ console.warn(
54518
+ `[errata] orphan reap skipped (${reap.skipped}${reap.candidates !== void 0 ? `, ${reap.candidates} candidates` : ""}) \u2014 no File nodes closed`
54519
+ );
54520
+ } else if (reap.reaped > 0) {
54521
+ console.log(
54522
+ `[errata] orphan reap: closed ${reap.reaped} File node(s) no longer indexed (${reap.symbolsClosed} symbol(s) with them)`
54523
+ );
54524
+ }
54525
+ } catch (err2) {
54526
+ console.warn("[errata] orphan reap failed:", err2 instanceof Error ? err2.message : err2);
54527
+ }
54528
+ });
54164
54529
  });
54165
54530
  }
54166
54531
  const workingFiles = createWorkingFileState();
@@ -54252,15 +54617,19 @@ function createWorkspaceEngine(opts) {
54252
54617
  doneRender?.();
54253
54618
  try {
54254
54619
  const seq = store.currentIngestSeq();
54255
- recordRenderLedger(store, ledger, seq, Date.now());
54620
+ const stamped = recordRenderLedger(store, ledger, seq, Date.now());
54621
+ appendPassLedger(paths.configDir, "render", 0, {
54622
+ shown: stamped.shown,
54623
+ evicted: stamped.evicted
54624
+ });
54256
54625
  } catch (err2) {
54257
54626
  console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
54258
54627
  }
54259
54628
  writeContextFile(opts.workspaceRoot, body2);
54260
- const target = join26(opts.workspaceRoot, "AGENTS.md");
54629
+ const target = join27(opts.workspaceRoot, "AGENTS.md");
54261
54630
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
54262
54631
  if (elicit) {
54263
- writePrimingHandles(join26(paths.configDir, "priming-handles.json"), [
54632
+ writePrimingHandles(join27(paths.configDir, "priming-handles.json"), [
54264
54633
  ...snapshot.recentProblems.map((r) => r.node),
54265
54634
  // Resolved-band handles: the ✓ problem AND its Solution are citable
54266
54635
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -54482,7 +54851,7 @@ function createWorkspaceEngine(opts) {
54482
54851
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
54483
54852
  });
54484
54853
  };
54485
- const turnCursorPath = join26(paths.configDir, "turn-cursors.json");
54854
+ const turnCursorPath = join27(paths.configDir, "turn-cursors.json");
54486
54855
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
54487
54856
  const turnOffset = loadTurnOffsets(turnCursorPath);
54488
54857
  const sessionLastProblem = /* @__PURE__ */ new Map();
@@ -54505,8 +54874,9 @@ function createWorkspaceEngine(opts) {
54505
54874
  let linked = 0;
54506
54875
  const t = Date.now();
54507
54876
  let processedTurns = 0;
54877
+ const seqAtStart = store.currentIngestSeq();
54508
54878
  const elicit = isEdgeElicitationEnabled();
54509
- const handleMap = elicit ? readPrimingHandles(join26(paths.configDir, "priming-handles.json")) : {};
54879
+ const handleMap = elicit ? readPrimingHandles(join27(paths.configDir, "priming-handles.json")) : {};
54510
54880
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
54511
54881
  const toRel = (abs) => {
54512
54882
  const p = abs.replace(/\\/g, "/");
@@ -55013,6 +55383,16 @@ function createWorkspaceEngine(opts) {
55013
55383
  if (triaged > 0) {
55014
55384
  console.log(`[errata] triage: ${triaged} wrong-door(s) captured from the conversation`);
55015
55385
  }
55386
+ if (processedTurns > 0) {
55387
+ appendPassLedger(paths.configDir, "capture", Date.now() - t, {
55388
+ turns: processedTurns,
55389
+ minted,
55390
+ resolved,
55391
+ triaged,
55392
+ priorEdges,
55393
+ seqAdvanced: store.currentIngestSeq() - seqAtStart
55394
+ });
55395
+ }
55016
55396
  };
55017
55397
  const harvestTurns = async (sessionId, transcriptPath) => {
55018
55398
  const known = turnOffset.get(sessionId);
@@ -55179,7 +55559,7 @@ function createWorkspaceEngine(opts) {
55179
55559
  try {
55180
55560
  const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
55181
55561
  emitAndProjectSkills(opts.workspaceRoot, inputs);
55182
- writePrimingHandles(join26(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
55562
+ writePrimingHandles(join27(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
55183
55563
  } catch (err2) {
55184
55564
  console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
55185
55565
  }
@@ -55263,6 +55643,26 @@ function createWorkspaceEngine(opts) {
55263
55643
  }
55264
55644
  return report;
55265
55645
  },
55646
+ semanticMaintenance() {
55647
+ const seqBefore = store.currentIngestSeq();
55648
+ const report = runSemanticMaintenance(store);
55649
+ appendPassLedger(paths.configDir, "semantic-maintenance", report.durationMs, {
55650
+ revisitsCleared: report.revisitsCleared,
55651
+ revisitsStanding: report.revisitsStanding,
55652
+ fixCandidatesSettled: report.fixCandidatesSettled,
55653
+ fixCandidatesAnswered: report.fixCandidates.answered,
55654
+ fixCandidatesIgnored: report.fixCandidates.ignored,
55655
+ fixCandidatesUnsubstantiated: report.fixCandidates.unsubstantiated,
55656
+ fixCandidatesStanding: report.fixCandidates.standing,
55657
+ designResolved: report.designResolved,
55658
+ claimsEvaluated: report.claimsEvaluated,
55659
+ seqAdvanced: store.currentIngestSeq() - seqBefore
55660
+ });
55661
+ if (report.revisitsCleared > 0 || report.fixCandidatesSettled > 0 || report.designResolved > 0) {
55662
+ refreshContextNow();
55663
+ }
55664
+ return report;
55665
+ },
55266
55666
  async nightly() {
55267
55667
  const report = (await runNightly()).report;
55268
55668
  const summarizer = opts.intentSummarizer ?? envIntentSummarizer();
@@ -55278,6 +55678,18 @@ function createWorkspaceEngine(opts) {
55278
55678
  console.warn("[errata] symbol summary sweep failed:", err2 instanceof Error ? err2.message : err2);
55279
55679
  }
55280
55680
  }
55681
+ appendPassLedger(paths.configDir, "graph-rescore", report.durationMs, {
55682
+ scoredNodes: report.scoredNodes,
55683
+ landmarks: report.landmarks,
55684
+ communities: report.communities,
55685
+ motifsPromoted: report.motifsPromoted
55686
+ });
55687
+ appendPassLedger(paths.configDir, "semantic-maintenance", report.durationMs, {
55688
+ revisitsCleared: report.revisitsCleared,
55689
+ fixCandidatesSettled: report.fixCandidatesSettled,
55690
+ designResolved: report.designResolved,
55691
+ claimsEvaluated: report.claimsEvaluated
55692
+ });
55281
55693
  return report;
55282
55694
  },
55283
55695
  async embedSettled() {
@@ -55366,7 +55778,7 @@ function createWorkspaceEngine(opts) {
55366
55778
  console.log(
55367
55779
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
55368
55780
  );
55369
- const pending = existsSync21(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
55781
+ const pending = existsSync22(paths.outbox) ? readdirSync9(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
55370
55782
  return { uploaded: 0, failed: 0, remaining: pending };
55371
55783
  }
55372
55784
  try {
@@ -55453,7 +55865,7 @@ async function startDaemon(opts) {
55453
55865
  reviewUrl: () => webUiUrl + "/review"
55454
55866
  });
55455
55867
  const writeLockFile = (url2) => {
55456
- writeFileSync19(
55868
+ writeFileSync20(
55457
55869
  engine.paths.daemonLock,
55458
55870
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
55459
55871
  "utf8"
@@ -55496,7 +55908,7 @@ async function startDaemon(opts) {
55496
55908
  );
55497
55909
  await engine.stop();
55498
55910
  try {
55499
- if (existsSync22(engine.paths.daemonLock)) {
55911
+ if (existsSync23(engine.paths.daemonLock)) {
55500
55912
  }
55501
55913
  } catch {
55502
55914
  }
@@ -55513,16 +55925,16 @@ async function listenServer(fetchFn, port) {
55513
55925
 
55514
55926
  // src/registry.ts
55515
55927
  init_paths();
55516
- import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync20 } from "node:fs";
55517
- import { join as join27 } from "node:path";
55928
+ import { existsSync as existsSync24, readFileSync as readFileSync23, writeFileSync as writeFileSync21 } from "node:fs";
55929
+ import { join as join28 } from "node:path";
55518
55930
  function registryPath() {
55519
- return process.env["ERRATA_REGISTRY_PATH"] ?? join27(globalDir(), "workspaces.json");
55931
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join28(globalDir(), "workspaces.json");
55520
55932
  }
55521
55933
  function read() {
55522
55934
  const p = registryPath();
55523
- if (!existsSync23(p)) return { version: 1, workspaces: {} };
55935
+ if (!existsSync24(p)) return { version: 1, workspaces: {} };
55524
55936
  try {
55525
- const parsed = JSON.parse(readFileSync22(p, "utf8"));
55937
+ const parsed = JSON.parse(readFileSync23(p, "utf8"));
55526
55938
  return { version: 1, workspaces: parsed.workspaces ?? {} };
55527
55939
  } catch {
55528
55940
  return { version: 1, workspaces: {} };
@@ -55530,7 +55942,7 @@ function read() {
55530
55942
  }
55531
55943
  function write(reg) {
55532
55944
  ensureDir(globalDir());
55533
- writeFileSync20(registryPath(), JSON.stringify(reg, null, 2), "utf8");
55945
+ writeFileSync21(registryPath(), JSON.stringify(reg, null, 2), "utf8");
55534
55946
  }
55535
55947
  function registerWorkspace(profile, root, now = Date.now()) {
55536
55948
  const reg = read();
@@ -55547,7 +55959,7 @@ function pruneMissingWorkspaces() {
55547
55959
  const reg = read();
55548
55960
  const removed = [];
55549
55961
  for (const [id, entry] of Object.entries(reg.workspaces)) {
55550
- if (!existsSync23(entry.path)) {
55962
+ if (!existsSync24(entry.path)) {
55551
55963
  removed.push(entry);
55552
55964
  delete reg.workspaces[id];
55553
55965
  }
@@ -55556,13 +55968,13 @@ function pruneMissingWorkspaces() {
55556
55968
  return removed;
55557
55969
  }
55558
55970
  function workspaceStatus(entry) {
55559
- const missing = !existsSync23(entry.path);
55971
+ const missing = !existsSync24(entry.path);
55560
55972
  const lockPath = workspacePaths(entry.path).daemonLock;
55561
55973
  let running = false;
55562
55974
  let webUiUrl = null;
55563
- if (existsSync23(lockPath)) {
55975
+ if (existsSync24(lockPath)) {
55564
55976
  try {
55565
- const lock = JSON.parse(readFileSync22(lockPath, "utf8"));
55977
+ const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
55566
55978
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
55567
55979
  running = true;
55568
55980
  webUiUrl = lock.webUiUrl;
@@ -55590,7 +56002,7 @@ function pidAlive(pid) {
55590
56002
  // src/multi.ts
55591
56003
  init_dist();
55592
56004
  init_src5();
55593
- import { readFileSync as readFileSync25, unlinkSync as unlinkSync3, writeFileSync as writeFileSync21 } from "node:fs";
56005
+ import { readFileSync as readFileSync26, unlinkSync as unlinkSync3, writeFileSync as writeFileSync22 } from "node:fs";
55594
56006
 
55595
56007
  // src/principle-sync.ts
55596
56008
  init_src5();
@@ -55618,8 +56030,8 @@ init_reconcile();
55618
56030
 
55619
56031
  // src/lockfile-auto.ts
55620
56032
  init_src();
55621
- import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
55622
- import { join as join28 } from "node:path";
56033
+ import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
56034
+ import { join as join29 } from "node:path";
55623
56035
 
55624
56036
  // src/package-index.ts
55625
56037
  init_src();
@@ -55768,11 +56180,11 @@ function runLockfilePass(opts) {
55768
56180
  { file: "package-lock.json", parse: parsePackageLockJson }
55769
56181
  ];
55770
56182
  for (const c of candidates) {
55771
- const p = join28(opts.root, c.file);
55772
- if (!existsSync24(p)) continue;
56183
+ const p = join29(opts.root, c.file);
56184
+ if (!existsSync25(p)) continue;
55773
56185
  let sbom;
55774
56186
  try {
55775
- sbom = c.parse(readFileSync23(p, "utf8"));
56187
+ sbom = c.parse(readFileSync24(p, "utf8"));
55776
56188
  } catch {
55777
56189
  continue;
55778
56190
  }
@@ -56220,7 +56632,7 @@ var ConsolidateWorker = class {
56220
56632
  init_paths();
56221
56633
 
56222
56634
  // src/lock.ts
56223
- import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
56635
+ import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
56224
56636
  function isProcessAlive(pid) {
56225
56637
  if (!pid || pid <= 0) return false;
56226
56638
  try {
@@ -56231,9 +56643,9 @@ function isProcessAlive(pid) {
56231
56643
  }
56232
56644
  }
56233
56645
  function readDaemonLock(lockPath) {
56234
- if (!existsSync25(lockPath)) return null;
56646
+ if (!existsSync26(lockPath)) return null;
56235
56647
  try {
56236
- const lock = JSON.parse(readFileSync24(lockPath, "utf8"));
56648
+ const lock = JSON.parse(readFileSync25(lockPath, "utf8"));
56237
56649
  return typeof lock.pid === "number" ? lock : null;
56238
56650
  } catch {
56239
56651
  return null;
@@ -56517,12 +56929,12 @@ async function reanchorProject(opts) {
56517
56929
  }
56518
56930
 
56519
56931
  // src/adopt.ts
56520
- import { existsSync as existsSync26 } from "node:fs";
56521
- import { dirname as dirname10, join as join29 } from "node:path";
56932
+ import { existsSync as existsSync27 } from "node:fs";
56933
+ import { dirname as dirname10, join as join30 } from "node:path";
56522
56934
  function findGitRoot(absPath) {
56523
56935
  let dir = absPath;
56524
56936
  for (let depth = 0; depth < 64; depth++) {
56525
- if (existsSync26(join29(dir, ".git"))) return dir;
56937
+ if (existsSync27(join30(dir, ".git"))) return dir;
56526
56938
  const parent = dirname10(dir);
56527
56939
  if (parent === dir) return null;
56528
56940
  dir = parent;
@@ -56771,7 +57183,7 @@ async function startMultiDaemon(opts = {}) {
56771
57183
  void ambientLinkAll();
56772
57184
  app.route(`/ws/${rec.id}`, rec.webApp);
56773
57185
  try {
56774
- writeFileSync21(
57186
+ writeFileSync22(
56775
57187
  rec.engine.paths.daemonLock,
56776
57188
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
56777
57189
  "utf8"
@@ -56960,7 +57372,7 @@ async function startMultiDaemon(opts = {}) {
56960
57372
  baseUrl = `http://127.0.0.1:${port}`;
56961
57373
  try {
56962
57374
  ensureDir(globalDir());
56963
- writeFileSync21(
57375
+ writeFileSync22(
56964
57376
  lockPath,
56965
57377
  JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
56966
57378
  "utf8"
@@ -56969,7 +57381,7 @@ async function startMultiDaemon(opts = {}) {
56969
57381
  }
56970
57382
  for (const r of records) {
56971
57383
  try {
56972
- writeFileSync21(
57384
+ writeFileSync22(
56973
57385
  r.engine.paths.daemonLock,
56974
57386
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
56975
57387
  "utf8"
@@ -57096,6 +57508,22 @@ async function startMultiDaemon(opts = {}) {
57096
57508
  }
57097
57509
  return out2;
57098
57510
  },
57511
+ semanticMaintenanceAll() {
57512
+ const out2 = /* @__PURE__ */ new Map();
57513
+ for (const r of records) {
57514
+ const done = markPass(`semantic:${r.entry.name}`);
57515
+ try {
57516
+ out2.set(r.id, r.engine.semanticMaintenance());
57517
+ } catch (err2) {
57518
+ console.warn(
57519
+ `[errata] semantic maintenance failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`
57520
+ );
57521
+ } finally {
57522
+ done();
57523
+ }
57524
+ }
57525
+ return out2;
57526
+ },
57099
57527
  async nightlyAll() {
57100
57528
  const out2 = /* @__PURE__ */ new Map();
57101
57529
  for (const r of records) {
@@ -57501,7 +57929,7 @@ async function startMultiDaemon(opts = {}) {
57501
57929
  },
57502
57930
  async stop() {
57503
57931
  try {
57504
- const cur = readFileSync25(lockPath, "utf8");
57932
+ const cur = readFileSync26(lockPath, "utf8");
57505
57933
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
57506
57934
  } catch {
57507
57935
  }
@@ -58518,21 +58946,21 @@ async function cmdInit() {
58518
58946
  if (!skipHooks) {
58519
58947
  console.log("");
58520
58948
  console.log("installing harness hooks...");
58521
- const { existsSync: existsSync28 } = await import("node:fs");
58522
- const { join: join31 } = await import("node:path");
58949
+ const { existsSync: existsSync29 } = await import("node:fs");
58950
+ const { join: join32 } = await import("node:path");
58523
58951
  try {
58524
58952
  await installClaudeHooks(port);
58525
58953
  } catch (err2) {
58526
58954
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
58527
58955
  }
58528
- if (existsSync28(join31(ROOT, ".cursor"))) {
58956
+ if (existsSync29(join32(ROOT, ".cursor"))) {
58529
58957
  try {
58530
58958
  await installCursorMcpConfig();
58531
58959
  } catch (err2) {
58532
58960
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
58533
58961
  }
58534
58962
  }
58535
- if (existsSync28(join31(ROOT, ".codex"))) {
58963
+ if (existsSync29(join32(ROOT, ".codex"))) {
58536
58964
  try {
58537
58965
  await installCodexHooks(port);
58538
58966
  } catch (err2) {
@@ -58689,9 +59117,9 @@ async function cmdStatus() {
58689
59117
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
58690
59118
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
58691
59119
  }
58692
- console.log(` graph db: ${existsSync27(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
58693
- console.log(` event log: ${existsSync27(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
58694
- if (existsSync27(paths.castalia)) {
59120
+ console.log(` graph db: ${existsSync28(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
59121
+ console.log(` event log: ${existsSync28(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
59122
+ if (existsSync28(paths.castalia)) {
58695
59123
  try {
58696
59124
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
58697
59125
  const store = openGraphStore2({ path: paths.castalia });
@@ -59372,11 +59800,11 @@ function cmdInstallationProfile(args2) {
59372
59800
  }
59373
59801
  async function cmdReview() {
59374
59802
  const paths = workspacePaths(ROOT);
59375
- if (!existsSync27(paths.reviewQueue)) {
59803
+ if (!existsSync28(paths.reviewQueue)) {
59376
59804
  console.log("(review queue empty)");
59377
59805
  return;
59378
59806
  }
59379
- const queue = JSON.parse(readFileSync26(paths.reviewQueue, "utf8"));
59807
+ const queue = JSON.parse(readFileSync27(paths.reviewQueue, "utf8"));
59380
59808
  if (queue.length === 0) {
59381
59809
  console.log("(review queue empty)");
59382
59810
  return;
@@ -60047,7 +60475,7 @@ async function gatherRepo(store, ws) {
60047
60475
  };
60048
60476
  }
60049
60477
  async function gatherReportData(generatedAt) {
60050
- const { existsSync: existsSync28 } = await import("node:fs");
60478
+ const { existsSync: existsSync29 } = await import("node:fs");
60051
60479
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
60052
60480
  const cfg = loadConfig();
60053
60481
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -60055,7 +60483,7 @@ async function gatherReportData(generatedAt) {
60055
60483
  for (const ws of listWorkspaces()) {
60056
60484
  if (ws.missing) continue;
60057
60485
  const dbPath = workspacePaths(ws.path).castalia;
60058
- if (!existsSync28(dbPath)) continue;
60486
+ if (!existsSync29(dbPath)) continue;
60059
60487
  let store = null;
60060
60488
  try {
60061
60489
  store = openGraphStore2({ path: dbPath });
@@ -60086,7 +60514,7 @@ async function gatherReportData(generatedAt) {
60086
60514
  };
60087
60515
  }
60088
60516
  async function cmdReport(args2) {
60089
- const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync22 } = await import("node:fs");
60517
+ const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync23 } = await import("node:fs");
60090
60518
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
60091
60519
  const includeFutureVerbs = args2.includes("--future-verbs");
60092
60520
  const now = /* @__PURE__ */ new Date();
@@ -60099,8 +60527,8 @@ async function cmdReport(args2) {
60099
60527
  const outDir = workspacePaths(ROOT).configDir;
60100
60528
  mkdirSync8(outDir, { recursive: true });
60101
60529
  const files = renderReport2(data, { includeFutureVerbs });
60102
- for (const f of files) writeFileSync22(join30(outDir, f.name), f.html, "utf8");
60103
- const indexPath = join30(outDir, "report.html");
60530
+ for (const f of files) writeFileSync23(join31(outDir, f.name), f.html, "utf8");
60531
+ const indexPath = join31(outDir, "report.html");
60104
60532
  console.log(`report \u2192 ${indexPath}`);
60105
60533
  console.log(
60106
60534
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -60218,15 +60646,15 @@ function hookRelayCommand(port, path2) {
60218
60646
  return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
60219
60647
  }
60220
60648
  async function installClaudeHooks(port) {
60221
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60222
- const { join: join31 } = await import("node:path");
60223
- const dir = join31(ROOT, ".claude");
60224
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60225
- const file2 = join31(dir, "settings.json");
60649
+ const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
60650
+ const { join: join32 } = await import("node:path");
60651
+ const dir = join32(ROOT, ".claude");
60652
+ if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
60653
+ const file2 = join32(dir, "settings.json");
60226
60654
  let settings = {};
60227
- if (existsSync28(file2)) {
60655
+ if (existsSync29(file2)) {
60228
60656
  try {
60229
- settings = JSON.parse(readFileSync27(file2, "utf8"));
60657
+ settings = JSON.parse(readFileSync28(file2, "utf8"));
60230
60658
  } catch {
60231
60659
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
60232
60660
  process.exit(2);
@@ -60272,10 +60700,10 @@ async function installClaudeHooks(port) {
60272
60700
  dropErrata(list);
60273
60701
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
60274
60702
  }
60275
- writeFileSync22(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
60703
+ writeFileSync23(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
60276
60704
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
60277
60705
  await installClaudeMcpConfig();
60278
- const claudeMd = join31(ROOT, "CLAUDE.md");
60706
+ const claudeMd = join32(ROOT, "CLAUDE.md");
60279
60707
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
60280
60708
  if (recall.kind === "collision") {
60281
60709
  console.warn(
@@ -60287,15 +60715,15 @@ async function installClaudeHooks(port) {
60287
60715
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
60288
60716
  }
60289
60717
  async function installClaudeMcpConfig() {
60290
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60291
- const { join: join31, dirname: dirname11 } = await import("node:path");
60292
- const file2 = join31(ROOT, ".mcp.json");
60718
+ const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
60719
+ const { join: join32, dirname: dirname11 } = await import("node:path");
60720
+ const file2 = join32(ROOT, ".mcp.json");
60293
60721
  const dir = dirname11(file2);
60294
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60722
+ if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
60295
60723
  let cfg = {};
60296
- if (existsSync28(file2)) {
60724
+ if (existsSync29(file2)) {
60297
60725
  try {
60298
- cfg = JSON.parse(readFileSync27(file2, "utf8"));
60726
+ cfg = JSON.parse(readFileSync28(file2, "utf8"));
60299
60727
  } catch {
60300
60728
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
60301
60729
  process.exit(2);
@@ -60303,21 +60731,21 @@ async function installClaudeMcpConfig() {
60303
60731
  }
60304
60732
  cfg.mcpServers ??= {};
60305
60733
  cfg.mcpServers["errata"] = errataMcpInvocation();
60306
- writeFileSync22(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60734
+ writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60307
60735
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
60308
60736
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
60309
60737
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
60310
60738
  }
60311
60739
  async function installCursorMcpConfig() {
60312
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60313
- const { join: join31 } = await import("node:path");
60314
- const dir = join31(ROOT, ".cursor");
60315
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60316
- const file2 = join31(dir, "mcp.json");
60740
+ const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
60741
+ const { join: join32 } = await import("node:path");
60742
+ const dir = join32(ROOT, ".cursor");
60743
+ if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
60744
+ const file2 = join32(dir, "mcp.json");
60317
60745
  let cfg = {};
60318
- if (existsSync28(file2)) {
60746
+ if (existsSync29(file2)) {
60319
60747
  try {
60320
- cfg = JSON.parse(readFileSync27(file2, "utf8"));
60748
+ cfg = JSON.parse(readFileSync28(file2, "utf8"));
60321
60749
  } catch {
60322
60750
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
60323
60751
  process.exit(2);
@@ -60325,7 +60753,7 @@ async function installCursorMcpConfig() {
60325
60753
  }
60326
60754
  cfg.mcpServers ??= {};
60327
60755
  cfg.mcpServers["errata"] = errataMcpInvocation();
60328
- writeFileSync22(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60756
+ writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60329
60757
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
60330
60758
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
60331
60759
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -60333,16 +60761,16 @@ async function installCursorMcpConfig() {
60333
60761
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
60334
60762
  }
60335
60763
  async function installCodexHooks(port) {
60336
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60337
- const { join: join31 } = await import("node:path");
60338
- const dir = join31(ROOT, ".codex");
60339
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60340
- const file2 = join31(dir, "config.toml");
60764
+ const { mkdirSync: mkdirSync8, existsSync: existsSync29, readFileSync: readFileSync28, writeFileSync: writeFileSync23 } = await import("node:fs");
60765
+ const { join: join32 } = await import("node:path");
60766
+ const dir = join32(ROOT, ".codex");
60767
+ if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
60768
+ const file2 = join32(dir, "config.toml");
60341
60769
  const BEGIN = `# >>> errata hooks (errata-managed)`;
60342
60770
  const END = `# <<< errata hooks`;
60343
60771
  let existing = "";
60344
- if (existsSync28(file2)) {
60345
- existing = readFileSync27(file2, "utf8");
60772
+ if (existsSync29(file2)) {
60773
+ existing = readFileSync28(file2, "utf8");
60346
60774
  const beginIdx = existing.indexOf(BEGIN);
60347
60775
  const endIdx = existing.indexOf(END);
60348
60776
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -60371,7 +60799,7 @@ ${END}
60371
60799
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
60372
60800
 
60373
60801
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
60374
- writeFileSync22(file2, final, "utf8");
60802
+ writeFileSync23(file2, final, "utf8");
60375
60803
  console.log(`installed Codex hooks \u2192 ${file2}`);
60376
60804
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
60377
60805
  console.log("");
@@ -60564,16 +60992,38 @@ async function cmdDash(args2) {
60564
60992
  }).catch(() => {
60565
60993
  });
60566
60994
  };
60995
+ const runSemanticPass = (reason) => {
60996
+ try {
60997
+ const reports = handle2.semanticMaintenanceAll();
60998
+ let cleared = 0;
60999
+ let settled = 0;
61000
+ let raised = 0;
61001
+ for (const r of reports.values()) {
61002
+ cleared += r.revisitsCleared;
61003
+ settled += r.fixCandidatesSettled;
61004
+ raised += r.designResolved;
61005
+ }
61006
+ if (cleared > 0 || settled > 0 || raised > 0) {
61007
+ console.log(
61008
+ `[semantic:${reason}] asks settled ${settled}, revisits cleared ${cleared}, questions raised ${raised}`
61009
+ );
61010
+ }
61011
+ } catch (err2) {
61012
+ console.warn(`[semantic] pass failed: ${err2 instanceof Error ? err2.message : err2}`);
61013
+ }
61014
+ };
60567
61015
  const scheduleQuiescenceFlush = () => {
60568
61016
  if (quiesceTimer) clearTimeout(quiesceTimer);
60569
61017
  quiesceTimer = setTimeout(() => {
60570
61018
  quiesceTimer = null;
60571
61019
  runBoundaryFlush("quiescent");
61020
+ runSemanticPass("quiescent");
60572
61021
  triggerConsolidation(false);
60573
61022
  }, QUIESCENCE_MS);
60574
61023
  };
60575
61024
  handle2.onSessionBoundary(() => {
60576
61025
  runBoundaryFlush("session-end");
61026
+ runSemanticPass("session-end");
60577
61027
  triggerConsolidation(true);
60578
61028
  });
60579
61029
  let ticking = false;
@@ -60685,7 +61135,7 @@ async function cmdDash(args2) {
60685
61135
  await yieldToLoop2();
60686
61136
  try {
60687
61137
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
60688
- const res = bleedRules(join30(r.root, ".claude", "rules"), items);
61138
+ const res = bleedRules(join31(r.root, ".claude", "rules"), items);
60689
61139
  if (res.written || res.pruned) {
60690
61140
  console.log(
60691
61141
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
@@ -60787,7 +61237,10 @@ async function cmdDash(args2) {
60787
61237
  }
60788
61238
  };
60789
61239
  triggerConsolidation = (force) => void maybeConsolidate(force);
60790
- const nightlyInterval = setInterval(() => triggerConsolidation(false), NIGHTLY_INTERVAL_MS);
61240
+ const nightlyInterval = setInterval(() => {
61241
+ runSemanticPass("periodic");
61242
+ triggerConsolidation(false);
61243
+ }, NIGHTLY_INTERVAL_MS);
60791
61244
  const shutdown = async (signal) => {
60792
61245
  console.log(`
60793
61246
  shutting down\u2026 (${signal})`);