@inerrata-corporation/errata 2.0.2-dev.517 → 2.0.2-dev.532

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 && n.validTo == 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
  });
@@ -30357,7 +30596,7 @@ async function scan(root, current, ignores, providers, out2) {
30357
30596
  }
30358
30597
  }
30359
30598
  }
30360
- function gitListFiles(root, ignores, providers) {
30599
+ function gitListRelPaths(root, ignores) {
30361
30600
  let stdout;
30362
30601
  try {
30363
30602
  stdout = execFileSync(
@@ -30380,6 +30619,15 @@ function gitListFiles(root, ignores, providers) {
30380
30619
  if (segs.some((s) => ignores.has(s) || s.startsWith(".") && s.length > 1)) {
30381
30620
  continue;
30382
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) {
30383
30631
  const abs = join8(root, rel);
30384
30632
  let size;
30385
30633
  try {
@@ -37719,6 +37967,7 @@ var init_csharp_treesitter = __esm({
37719
37967
  // ../../packages/indexer/src/index.ts
37720
37968
  var src_exports5 = {};
37721
37969
  __export(src_exports5, {
37970
+ DEFAULT_IGNORES: () => DEFAULT_IGNORES,
37722
37971
  DRIFT_FORK_RATIO: () => DRIFT_FORK_RATIO,
37723
37972
  TreeSitterCSharpProvider: () => TreeSitterCSharpProvider,
37724
37973
  TreeSitterCppProvider: () => TreeSitterCppProvider,
@@ -37735,6 +37984,7 @@ __export(src_exports5, {
37735
37984
  findInnermostScope: () => findInnermostScope,
37736
37985
  folderNodeId: () => folderNodeId,
37737
37986
  fromHex: () => fromHex,
37987
+ gitListRelPaths: () => gitListRelPaths,
37738
37988
  hammingDistance: () => hammingDistance,
37739
37989
  hasForkedDrift: () => hasForkedDrift,
37740
37990
  incrementalReindex: () => incrementalReindex,
@@ -37847,6 +38097,8 @@ async function findStaleFiles(store, rootPath, workspaceId2) {
37847
38097
  const fnode = store.getNode(fileNodeId(workspaceId2, rel));
37848
38098
  if (!fnode) {
37849
38099
  stale.push(abs);
38100
+ } else if ((fnode.validTo ?? null) !== null) {
38101
+ stale.push(abs);
37850
38102
  } else if (fnode.lastUpdatedAt < mtimeMs) {
37851
38103
  stale.push(abs);
37852
38104
  } else {
@@ -37882,19 +38134,67 @@ function findStrandedSymbols(store) {
37882
38134
  }
37883
38135
  return stranded;
37884
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
+ }
37885
38174
  async function reconcileStaleFiles(store, rootPath, workspaceId2) {
37886
38175
  const stale = await findStaleFiles(store, rootPath, workspaceId2);
37887
38176
  if (stale.length === 0) return 0;
37888
38177
  let total = 0;
38178
+ let failedBatches = 0;
37889
38179
  const BATCH = 20;
37890
38180
  for (let i2 = 0; i2 < stale.length; i2 += BATCH) {
37891
- const r = await incrementalReindex(store, rootPath, workspaceId2, stale.slice(i2, i2 + BATCH));
37892
- 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
+ }
37893
38190
  if (i2 + BATCH < stale.length) await new Promise((res) => setImmediate(res));
37894
38191
  }
38192
+ if (failedBatches > 0) {
38193
+ console.warn(`[errata] reconcile: ${failedBatches} batch(es) failed; ${total} file(s) reindexed`);
38194
+ }
37895
38195
  return total;
37896
38196
  }
37897
- 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;
37898
38198
  var init_reconcile = __esm({
37899
38199
  "src/reconcile.ts"() {
37900
38200
  "use strict";
@@ -37903,6 +38203,8 @@ var init_reconcile = __esm({
37903
38203
  SOURCE_RE = /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i;
37904
38204
  SCAN_YIELD_EVERY = 100;
37905
38205
  LIVENESS_CHUNK = 4e3;
38206
+ ORPHAN_REAP_MAX_FRACTION = 0.25;
38207
+ ORPHAN_REAP_MIN_ALLOWANCE = 50;
37906
38208
  }
37907
38209
  });
37908
38210
 
@@ -48066,27 +48368,27 @@ __export(witness_ledger_exports, {
48066
48368
  summarizeWitnessLedger: () => summarizeWitnessLedger,
48067
48369
  witnessLedgerPath: () => witnessLedgerPath
48068
48370
  });
48069
- import { appendFileSync as appendFileSync2, existsSync as existsSync20, readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "node:fs";
48070
- 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";
48071
48373
  function witnessLedgerPath(configDir) {
48072
- return join25(configDir, "witness-ledger.jsonl");
48374
+ return join26(configDir, "witness-ledger.jsonl");
48073
48375
  }
48074
48376
  function appendWitnessLedger(configDir, entry) {
48075
48377
  const path2 = witnessLedgerPath(configDir);
48076
48378
  try {
48077
- appendFileSync2(path2, JSON.stringify(entry) + "\n");
48078
- 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);
48079
48381
  if (lines.length > LEDGER_MAX_LINES) {
48080
- 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");
48081
48383
  }
48082
48384
  } catch {
48083
48385
  }
48084
48386
  }
48085
48387
  function readWitnessLedger(configDir) {
48086
48388
  const path2 = witnessLedgerPath(configDir);
48087
- if (!existsSync20(path2)) return [];
48389
+ if (!existsSync21(path2)) return [];
48088
48390
  try {
48089
- 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");
48090
48392
  } catch {
48091
48393
  return [];
48092
48394
  }
@@ -48512,12 +48814,12 @@ var init_report_render = __esm({
48512
48814
 
48513
48815
  // src/cli.ts
48514
48816
  init_src6();
48515
- import { closeSync as closeSync2, existsSync as existsSync27, openSync as openSync2, readFileSync as readFileSync26, renameSync as renameSync4, statSync as statSync6 } from "node:fs";
48516
- 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";
48517
48819
  import { spawn as spawn3 } from "node:child_process";
48518
48820
 
48519
48821
  // src/daemon.ts
48520
- import { existsSync as existsSync22, writeFileSync as writeFileSync19 } from "node:fs";
48822
+ import { existsSync as existsSync23, writeFileSync as writeFileSync20 } from "node:fs";
48521
48823
 
48522
48824
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
48523
48825
  import { createServer as createServerHTTP } from "http";
@@ -49097,8 +49399,8 @@ init_config();
49097
49399
 
49098
49400
  // src/engine.ts
49099
49401
  import { execFileSync as execFileSync3 } from "node:child_process";
49100
- 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";
49101
- 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";
49102
49404
 
49103
49405
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
49104
49406
  import { stat as statcb } from "fs";
@@ -52197,6 +52499,48 @@ function repairInvalidEdges(store, opts) {
52197
52499
  init_symbol_summaries();
52198
52500
  init_reconcile();
52199
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
+
52200
52544
  // src/episode.ts
52201
52545
  init_src();
52202
52546
  function deltaIsEmpty(d) {
@@ -52391,11 +52735,11 @@ init_outbox();
52391
52735
  init_src9();
52392
52736
  init_src();
52393
52737
  init_src2();
52394
- import { readFileSync as readFileSync13 } from "node:fs";
52395
- import { join as join18 } from "node:path";
52738
+ import { readFileSync as readFileSync14 } from "node:fs";
52739
+ import { join as join19 } from "node:path";
52396
52740
  function loadClaimIgnorePatterns(workspaceRoot) {
52397
52741
  try {
52398
- 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());
52399
52743
  } catch {
52400
52744
  return [];
52401
52745
  }
@@ -52756,22 +53100,22 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
52756
53100
  }
52757
53101
 
52758
53102
  // src/git-sensor.ts
52759
- import { existsSync as existsSync15, readFileSync as readFileSync14, watch as fsWatch } from "node:fs";
52760
- 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";
52761
53105
  function readFirstLine(path2) {
52762
53106
  try {
52763
- return readFileSync14(path2, "utf8").split(/\r?\n/, 1)[0].trim();
53107
+ return readFileSync15(path2, "utf8").split(/\r?\n/, 1)[0].trim();
52764
53108
  } catch {
52765
53109
  return null;
52766
53110
  }
52767
53111
  }
52768
53112
  function readGitRefState(gitDir) {
52769
- const head2 = readFirstLine(join19(gitDir, "HEAD"));
53113
+ const head2 = readFirstLine(join20(gitDir, "HEAD"));
52770
53114
  const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
52771
53115
  const branch = m ? m[1] : null;
52772
53116
  let sha2 = null;
52773
53117
  if (branch) {
52774
- sha2 = readFirstLine(join19(gitDir, "refs", "heads", branch));
53118
+ sha2 = readFirstLine(join20(gitDir, "refs", "heads", branch));
52775
53119
  if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
52776
53120
  } else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
52777
53121
  sha2 = head2;
@@ -52779,13 +53123,13 @@ function readGitRefState(gitDir) {
52779
53123
  return {
52780
53124
  branch,
52781
53125
  sha: sha2,
52782
- mergeHeadExists: existsSync15(join19(gitDir, "MERGE_HEAD")),
52783
- origHeadExists: existsSync15(join19(gitDir, "ORIG_HEAD"))
53126
+ mergeHeadExists: existsSync16(join20(gitDir, "MERGE_HEAD")),
53127
+ origHeadExists: existsSync16(join20(gitDir, "ORIG_HEAD"))
52784
53128
  };
52785
53129
  }
52786
53130
  function shaFromPackedRefs(gitDir, ref) {
52787
53131
  try {
52788
- 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/)) {
52789
53133
  const [sha2, name2] = line.split(/\s+/);
52790
53134
  if (name2 === ref && sha2) return sha2;
52791
53135
  }
@@ -52819,7 +53163,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
52819
53163
  const settle = () => {
52820
53164
  if (timer) clearTimeout(timer);
52821
53165
  timer = setTimeout(() => {
52822
- if (existsSync15(join19(gitDir, "index.lock"))) {
53166
+ if (existsSync16(join20(gitDir, "index.lock"))) {
52823
53167
  settle();
52824
53168
  return;
52825
53169
  }
@@ -52830,7 +53174,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
52830
53174
  }, debounceMs);
52831
53175
  };
52832
53176
  for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
52833
- const p = join19(gitDir, sub);
53177
+ const p = join20(gitDir, sub);
52834
53178
  try {
52835
53179
  watchers.push(fsWatch(p, settle));
52836
53180
  } catch {
@@ -53055,21 +53399,21 @@ var TelemetryRecorder = class {
53055
53399
 
53056
53400
  // src/skills.ts
53057
53401
  import {
53058
- existsSync as existsSync16,
53402
+ existsSync as existsSync17,
53059
53403
  mkdirSync as mkdirSync6,
53060
- readFileSync as readFileSync15,
53404
+ readFileSync as readFileSync16,
53061
53405
  readdirSync as readdirSync7,
53062
53406
  unlinkSync as unlinkSync2,
53063
- writeFileSync as writeFileSync13
53407
+ writeFileSync as writeFileSync14
53064
53408
  } from "node:fs";
53065
- import { basename as basename4, join as join20 } from "node:path";
53409
+ import { basename as basename4, join as join21 } from "node:path";
53066
53410
  function skillFileName(id) {
53067
53411
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
53068
53412
  }
53069
53413
  function readSkillManifest(manifestPath) {
53070
- if (!existsSync16(manifestPath)) return [];
53414
+ if (!existsSync17(manifestPath)) return [];
53071
53415
  try {
53072
- const parsed = JSON.parse(readFileSync15(manifestPath, "utf8"));
53416
+ const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
53073
53417
  return (parsed.skills ?? []).map((s) => ({
53074
53418
  title: s.title ?? "",
53075
53419
  layer: s.layer ?? "technique",
@@ -53093,7 +53437,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53093
53437
  for (const s of res.skills) {
53094
53438
  const fileName = skillFileName(s.id);
53095
53439
  keep.add(fileName);
53096
- writeFileSync13(join20(paths.skillsDir, fileName), s.markdown, "utf8");
53440
+ writeFileSync14(join21(paths.skillsDir, fileName), s.markdown, "utf8");
53097
53441
  rows.push({
53098
53442
  id: s.id,
53099
53443
  title: s.title,
@@ -53106,7 +53450,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53106
53450
  const fileName = skillFileName(p.id);
53107
53451
  if (keep.has(fileName)) continue;
53108
53452
  keep.add(fileName);
53109
- writeFileSync13(join20(paths.skillsDir, fileName), p.markdown, "utf8");
53453
+ writeFileSync14(join21(paths.skillsDir, fileName), p.markdown, "utf8");
53110
53454
  rows.push({
53111
53455
  id: p.id,
53112
53456
  title: p.title,
@@ -53120,13 +53464,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53120
53464
  if (!f.endsWith(".md")) continue;
53121
53465
  if (keep.has(basename4(f))) continue;
53122
53466
  try {
53123
- unlinkSync2(join20(paths.skillsDir, f));
53467
+ unlinkSync2(join21(paths.skillsDir, f));
53124
53468
  pruned++;
53125
53469
  } catch {
53126
53470
  }
53127
53471
  }
53128
53472
  rows.sort((a, b) => a.id.localeCompare(b.id));
53129
- writeFileSync13(
53473
+ writeFileSync14(
53130
53474
  paths.skillsManifest,
53131
53475
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
53132
53476
  "utf8"
@@ -53138,22 +53482,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
53138
53482
  init_src2();
53139
53483
  import {
53140
53484
  cpSync,
53141
- existsSync as existsSync17,
53485
+ existsSync as existsSync18,
53142
53486
  lstatSync,
53143
53487
  mkdirSync as mkdirSync7,
53144
- readFileSync as readFileSync16,
53488
+ readFileSync as readFileSync17,
53145
53489
  readdirSync as readdirSync8,
53146
53490
  rmSync as rmSync2,
53147
53491
  symlinkSync,
53148
- writeFileSync as writeFileSync14
53492
+ writeFileSync as writeFileSync15
53149
53493
  } from "node:fs";
53150
- import { join as join21 } from "node:path";
53494
+ import { join as join22 } from "node:path";
53151
53495
  var SKILL_NS = "errata-";
53152
53496
  var HARNESS_SKILL_DIRS = [
53153
- { configDir: ".claude", skillsDir: join21(".claude", "skills") },
53497
+ { configDir: ".claude", skillsDir: join22(".claude", "skills") },
53154
53498
  // Cursor adopted the standard; its exact project dir is still moving — kept
53155
53499
  // best-effort and gated on `.cursor/` presence so we never create it blind.
53156
- { configDir: ".cursor", skillsDir: join21(".cursor", "skills") }
53500
+ { configDir: ".cursor", skillsDir: join22(".cursor", "skills") }
53157
53501
  ];
53158
53502
  function skillSlug(title, id) {
53159
53503
  const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
@@ -53198,12 +53542,12 @@ function skillCiteHandle(s) {
53198
53542
  return priorHandle({ id: s.id, description: s.title });
53199
53543
  }
53200
53544
  function reconcileNamespaced(dir, keep) {
53201
- if (!existsSync17(dir)) return 0;
53545
+ if (!existsSync18(dir)) return 0;
53202
53546
  let pruned = 0;
53203
53547
  for (const name2 of readdirSync8(dir)) {
53204
53548
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
53205
53549
  try {
53206
- rmSync2(join21(dir, name2), { recursive: true, force: true });
53550
+ rmSync2(join22(dir, name2), { recursive: true, force: true });
53207
53551
  pruned++;
53208
53552
  } catch {
53209
53553
  }
@@ -53212,7 +53556,7 @@ function reconcileNamespaced(dir, keep) {
53212
53556
  }
53213
53557
  function linkOrCopy(linkPath, target) {
53214
53558
  try {
53215
- if (existsSync17(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
53559
+ if (existsSync18(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
53216
53560
  } catch {
53217
53561
  }
53218
53562
  try {
@@ -53233,7 +53577,7 @@ function safeLstat(p) {
53233
53577
  }
53234
53578
  }
53235
53579
  function emitAndProjectSkills(root, skills) {
53236
- const agentsSkillsDir = join21(root, ".agents", "skills");
53580
+ const agentsSkillsDir = join22(root, ".agents", "skills");
53237
53581
  mkdirSync7(agentsSkillsDir, { recursive: true });
53238
53582
  const slugs = [];
53239
53583
  const keep = /* @__PURE__ */ new Set();
@@ -53241,7 +53585,7 @@ function emitAndProjectSkills(root, skills) {
53241
53585
  for (const s of skills) {
53242
53586
  let body2;
53243
53587
  try {
53244
- body2 = readFileSync16(s.bodyPath, "utf8");
53588
+ body2 = readFileSync17(s.bodyPath, "utf8");
53245
53589
  } catch {
53246
53590
  continue;
53247
53591
  }
@@ -53250,9 +53594,9 @@ function emitAndProjectSkills(root, skills) {
53250
53594
  keep.add(slug2);
53251
53595
  slugs.push(slug2);
53252
53596
  const description = deriveDescription(s.title, s.layer, body2);
53253
- mkdirSync7(join21(agentsSkillsDir, slug2), { recursive: true });
53254
- writeFileSync14(
53255
- join21(agentsSkillsDir, slug2, "SKILL.md"),
53597
+ mkdirSync7(join22(agentsSkillsDir, slug2), { recursive: true });
53598
+ writeFileSync15(
53599
+ join22(agentsSkillsDir, slug2, "SKILL.md"),
53256
53600
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
53257
53601
  "utf8"
53258
53602
  );
@@ -53261,11 +53605,11 @@ function emitAndProjectSkills(root, skills) {
53261
53605
  reconcileNamespaced(agentsSkillsDir, keep);
53262
53606
  let projected = 0;
53263
53607
  for (const h of HARNESS_SKILL_DIRS) {
53264
- if (!existsSync17(join21(root, h.configDir))) continue;
53265
- const dir = join21(root, h.skillsDir);
53608
+ if (!existsSync18(join22(root, h.configDir))) continue;
53609
+ const dir = join22(root, h.skillsDir);
53266
53610
  mkdirSync7(dir, { recursive: true });
53267
53611
  for (const slug2 of slugs) {
53268
- linkOrCopy(join21(dir, slug2), join21(agentsSkillsDir, slug2));
53612
+ linkOrCopy(join22(dir, slug2), join22(agentsSkillsDir, slug2));
53269
53613
  projected++;
53270
53614
  }
53271
53615
  reconcileNamespaced(dir, keep);
@@ -53274,15 +53618,15 @@ function emitAndProjectSkills(root, skills) {
53274
53618
  return { slugs, emitted, projected };
53275
53619
  }
53276
53620
  function emitInputsFromManifest(erretaDir, manifestPath) {
53277
- if (!existsSync17(manifestPath)) return [];
53621
+ if (!existsSync18(manifestPath)) return [];
53278
53622
  try {
53279
- const parsed = JSON.parse(readFileSync16(manifestPath, "utf8"));
53623
+ const parsed = JSON.parse(readFileSync17(manifestPath, "utf8"));
53280
53624
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
53281
53625
  id: s.id,
53282
53626
  title: s.title ?? s.id,
53283
53627
  layer: s.layer ?? "technique",
53284
53628
  confidence: s.confidence ?? 0,
53285
- bodyPath: join21(erretaDir, s.file)
53629
+ bodyPath: join22(erretaDir, s.file)
53286
53630
  }));
53287
53631
  } catch {
53288
53632
  return [];
@@ -53296,17 +53640,17 @@ var GITIGNORE_LINES = [
53296
53640
  ".cursor/skills/errata-*/"
53297
53641
  ];
53298
53642
  function ensureSkillGitignore(root) {
53299
- const path2 = join21(root, ".gitignore");
53643
+ const path2 = join22(root, ".gitignore");
53300
53644
  let current = "";
53301
53645
  try {
53302
- current = existsSync17(path2) ? readFileSync16(path2, "utf8") : "";
53646
+ current = existsSync18(path2) ? readFileSync17(path2, "utf8") : "";
53303
53647
  } catch {
53304
53648
  return;
53305
53649
  }
53306
53650
  if (current.includes(GITIGNORE_MARK)) return;
53307
53651
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
53308
53652
  try {
53309
- writeFileSync14(path2, `${current}${prefix}
53653
+ writeFileSync15(path2, `${current}${prefix}
53310
53654
  ${GITIGNORE_LINES.join("\n")}
53311
53655
  `, "utf8");
53312
53656
  } catch {
@@ -53399,20 +53743,20 @@ init_paths();
53399
53743
  // src/profile.ts
53400
53744
  init_src2();
53401
53745
  init_paths();
53402
- 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";
53403
53747
  import { createHash as createHash12 } from "node:crypto";
53404
- import { join as join23 } from "node:path";
53748
+ import { join as join24 } from "node:path";
53405
53749
 
53406
53750
  // src/git-remote.ts
53407
53751
  init_src();
53408
- import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync4 } from "node:fs";
53409
- 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";
53410
53754
  function resolveGitDir(root) {
53411
- const dotGit = join22(root, ".git");
53755
+ const dotGit = join23(root, ".git");
53412
53756
  try {
53413
53757
  const st = statSync4(dotGit);
53414
53758
  if (st.isDirectory()) return dotGit;
53415
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync17(dotGit, "utf8"));
53759
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync18(dotGit, "utf8"));
53416
53760
  if (!m) return null;
53417
53761
  const dir = m[1];
53418
53762
  return isAbsolute3(dir) ? dir : resolve5(root, dir);
@@ -53421,22 +53765,22 @@ function resolveGitDir(root) {
53421
53765
  }
53422
53766
  }
53423
53767
  function gitConfigPath(gitDir) {
53424
- const commondirFile = join22(gitDir, "commondir");
53425
- if (existsSync18(commondirFile)) {
53426
- const common = readFileSync17(commondirFile, "utf8").trim();
53768
+ const commondirFile = join23(gitDir, "commondir");
53769
+ if (existsSync19(commondirFile)) {
53770
+ const common = readFileSync18(commondirFile, "utf8").trim();
53427
53771
  const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
53428
- return join22(commonDir, "config");
53772
+ return join23(commonDir, "config");
53429
53773
  }
53430
- return join22(gitDir, "config");
53774
+ return join23(gitDir, "config");
53431
53775
  }
53432
53776
  function readRemotes(root) {
53433
53777
  const gitDir = resolveGitDir(root);
53434
53778
  if (!gitDir) return [];
53435
53779
  const cfgPath = gitConfigPath(gitDir);
53436
- if (!existsSync18(cfgPath)) return [];
53780
+ if (!existsSync19(cfgPath)) return [];
53437
53781
  let txt;
53438
53782
  try {
53439
- txt = readFileSync17(cfgPath, "utf8");
53783
+ txt = readFileSync18(cfgPath, "utf8");
53440
53784
  } catch {
53441
53785
  return [];
53442
53786
  }
@@ -53478,13 +53822,13 @@ function refreshRepoLocator(root, profile) {
53478
53822
  }
53479
53823
  function loadProfile(root) {
53480
53824
  const p = workspacePaths(root);
53481
- if (!existsSync19(p.workspaceJson)) return null;
53482
- return JSON.parse(readFileSync18(p.workspaceJson, "utf8"));
53825
+ if (!existsSync20(p.workspaceJson)) return null;
53826
+ return JSON.parse(readFileSync19(p.workspaceJson, "utf8"));
53483
53827
  }
53484
53828
  function saveProfile(root, profile) {
53485
53829
  const p = workspacePaths(root);
53486
53830
  ensureDir(p.configDir);
53487
- writeFileSync15(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
53831
+ writeFileSync16(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
53488
53832
  }
53489
53833
  function autodetectProfile(root) {
53490
53834
  const id = workspaceId(root);
@@ -53492,10 +53836,10 @@ function autodetectProfile(root) {
53492
53836
  const p = emptyProfile(id, name2);
53493
53837
  const locator = detectRepoLocator(root);
53494
53838
  if (locator) p.repoLocator = locator;
53495
- const pkgPath = join23(root, "package.json");
53496
- if (existsSync19(pkgPath)) {
53839
+ const pkgPath = join24(root, "package.json");
53840
+ if (existsSync20(pkgPath)) {
53497
53841
  try {
53498
- const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
53842
+ const pkg = JSON.parse(readFileSync19(pkgPath, "utf8"));
53499
53843
  p.languages.push("typescript", "javascript");
53500
53844
  const nodeVer = pkg.engines?.node ?? "node";
53501
53845
  p.stack.push(`node@${nodeVer}`);
@@ -53516,10 +53860,10 @@ function autodetectProfile(root) {
53516
53860
  } catch {
53517
53861
  }
53518
53862
  }
53519
- const pyproject = join23(root, "pyproject.toml");
53520
- if (existsSync19(pyproject)) {
53863
+ const pyproject = join24(root, "pyproject.toml");
53864
+ if (existsSync20(pyproject)) {
53521
53865
  try {
53522
- const txt = readFileSync18(pyproject, "utf8");
53866
+ const txt = readFileSync19(pyproject, "utf8");
53523
53867
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
53524
53868
  p.languages.push("python");
53525
53869
  p.stack.push(`python@${py ?? "3"}`);
@@ -53530,16 +53874,16 @@ function autodetectProfile(root) {
53530
53874
  } catch {
53531
53875
  }
53532
53876
  }
53533
- const reqs = join23(root, "requirements.txt");
53534
- if (existsSync19(reqs)) {
53877
+ const reqs = join24(root, "requirements.txt");
53878
+ if (existsSync20(reqs)) {
53535
53879
  if (!p.languages.includes("python")) p.languages.push("python");
53536
53880
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
53537
53881
  }
53538
- if (existsSync19(join23(root, "go.mod"))) {
53882
+ if (existsSync20(join24(root, "go.mod"))) {
53539
53883
  p.languages.push("go");
53540
53884
  p.stack.push("go");
53541
53885
  }
53542
- if (existsSync19(join23(root, "Cargo.toml"))) {
53886
+ if (existsSync20(join24(root, "Cargo.toml"))) {
53543
53887
  p.languages.push("rust");
53544
53888
  p.stack.push("rust");
53545
53889
  }
@@ -53549,17 +53893,17 @@ function autodetectProfile(root) {
53549
53893
  }
53550
53894
 
53551
53895
  // src/witness-queue.ts
53552
- import { readFileSync as readFileSync19, renameSync as renameSync2, writeFileSync as writeFileSync16 } from "node:fs";
53553
- 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";
53554
53898
  var WITNESS_QUEUE_CAP = 500;
53555
53899
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
53556
53900
  var WITNESS_MAX_ATTEMPTS = 5;
53557
53901
  function witnessQueuePath(workspaceConfigDir) {
53558
- return join24(workspaceConfigDir, "witness-queue.json");
53902
+ return join25(workspaceConfigDir, "witness-queue.json");
53559
53903
  }
53560
53904
  function loadWitnessQueue(path2) {
53561
53905
  try {
53562
- const raw2 = JSON.parse(readFileSync19(path2, "utf8"));
53906
+ const raw2 = JSON.parse(readFileSync20(path2, "utf8"));
53563
53907
  if (!Array.isArray(raw2)) return [];
53564
53908
  return raw2.filter(
53565
53909
  (w) => !!w && typeof w === "object" && typeof w.nodeId === "string" && typeof w.witnessKey === "string"
@@ -53570,8 +53914,8 @@ function loadWitnessQueue(path2) {
53570
53914
  }
53571
53915
  function saveWitnessQueue(path2, queue) {
53572
53916
  try {
53573
- const tmp = join24(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
53574
- writeFileSync16(tmp, JSON.stringify(queue), "utf8");
53917
+ const tmp = join25(dirname9(path2), `.${Date.now()}.witness-queue.tmp`);
53918
+ writeFileSync17(tmp, JSON.stringify(queue), "utf8");
53575
53919
  renameSync2(tmp, path2);
53576
53920
  } catch {
53577
53921
  }
@@ -53862,7 +54206,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
53862
54206
  }
53863
54207
 
53864
54208
  // src/engine.ts
53865
- var DAEMON_VERSION = true ? "2.0.2-dev.517" : "2.0.0-alpha.0";
54209
+ var DAEMON_VERSION = true ? "2.0.2-dev.532" : "2.0.0-alpha.0";
53866
54210
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
53867
54211
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
53868
54212
  var GIT_OP_MUTE_MS = 4e3;
@@ -53872,17 +54216,17 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
53872
54216
  function appendIdentityAudit(path2, record2, line) {
53873
54217
  if (!record2.accepted && record2.score <= 0) return;
53874
54218
  try {
53875
- if (existsSync21(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
54219
+ if (existsSync22(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
53876
54220
  renameSync3(path2, `${path2}.1`);
53877
54221
  }
53878
- appendFileSync3(path2, line);
54222
+ appendFileSync4(path2, line);
53879
54223
  } catch {
53880
54224
  }
53881
54225
  }
53882
54226
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
53883
54227
  function loadTurnCursors(path2) {
53884
54228
  try {
53885
- const raw2 = JSON.parse(readFileSync21(path2, "utf8"));
54229
+ const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
53886
54230
  return new Map(
53887
54231
  Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
53888
54232
  );
@@ -53892,7 +54236,7 @@ function loadTurnCursors(path2) {
53892
54236
  }
53893
54237
  function loadTurnOffsets(path2) {
53894
54238
  try {
53895
- const raw2 = JSON.parse(readFileSync21(path2, "utf8"));
54239
+ const raw2 = JSON.parse(readFileSync22(path2, "utf8"));
53896
54240
  const out2 = /* @__PURE__ */ new Map();
53897
54241
  for (const [k, v] of Object.entries(raw2)) {
53898
54242
  const off = typeof v === "object" && v !== null ? v.offset : void 0;
@@ -53908,7 +54252,7 @@ function saveTurnCursors(path2, cursors, offsets) {
53908
54252
  const merged = {};
53909
54253
  for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
53910
54254
  for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
53911
- writeFileSync18(path2, JSON.stringify(merged), "utf8");
54255
+ writeFileSync19(path2, JSON.stringify(merged), "utf8");
53912
54256
  } catch {
53913
54257
  }
53914
54258
  }
@@ -53930,7 +54274,7 @@ function gitSourceWatchTargets(root) {
53930
54274
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
53931
54275
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
53932
54276
  );
53933
- 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));
53934
54278
  } catch {
53935
54279
  }
53936
54280
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -53942,19 +54286,19 @@ function gitSourceWatchTargets(root) {
53942
54286
  if (!f.startsWith(prefix)) continue;
53943
54287
  const rest2 = f.slice(prefix.length);
53944
54288
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
53945
- else targets.add(join26(root, f));
54289
+ else targets.add(join27(root, f));
53946
54290
  }
53947
54291
  for (const c of children) {
53948
- if (IGNORED_PATH.test(join26(root, c) + sep4)) continue;
54292
+ if (IGNORED_PATH.test(join27(root, c) + sep4)) continue;
53949
54293
  if (hasIgnoredChild(c)) addUnder(c);
53950
- else targets.add(join26(root, c));
54294
+ else targets.add(join27(root, c));
53951
54295
  }
53952
54296
  };
53953
54297
  addUnder("");
53954
54298
  if (targets.size > 0) return [...targets];
53955
54299
  } catch {
53956
54300
  }
53957
- 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)));
53958
54302
  }
53959
54303
  function createWorkspaceEngine(opts) {
53960
54304
  const paths = workspacePaths(opts.workspaceRoot);
@@ -54112,7 +54456,7 @@ function createWorkspaceEngine(opts) {
54112
54456
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
54113
54457
  let episodeId2;
54114
54458
  if (srcPaths.length > 0) {
54115
- const abs = srcPaths.map((p) => join26(opts.workspaceRoot, p));
54459
+ const abs = srcPaths.map((p) => join27(opts.workspaceRoot, p));
54116
54460
  try {
54117
54461
  const r = await runReindexPass(
54118
54462
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -54148,8 +54492,8 @@ function createWorkspaceEngine(opts) {
54148
54492
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
54149
54493
  );
54150
54494
  };
54151
- const gitDir = join26(opts.workspaceRoot, ".git");
54152
- if (existsSync21(gitDir)) {
54495
+ const gitDir = join27(opts.workspaceRoot, ".git");
54496
+ if (existsSync22(gitDir)) {
54153
54497
  stopGit = startGitSensor(gitDir, (ev) => {
54154
54498
  void handleGitEvent(ev).catch((err2) => {
54155
54499
  console.warn("[errata] git event handler failed:", err2);
@@ -54162,7 +54506,26 @@ function createWorkspaceEngine(opts) {
54162
54506
  if (n > 0) {
54163
54507
  console.log(`[errata] reconcile: re-indexed ${n} stale file(s) on startup`);
54164
54508
  }
54165
- }).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
+ });
54166
54529
  });
54167
54530
  }
54168
54531
  const workingFiles = createWorkingFileState();
@@ -54254,15 +54617,19 @@ function createWorkspaceEngine(opts) {
54254
54617
  doneRender?.();
54255
54618
  try {
54256
54619
  const seq = store.currentIngestSeq();
54257
- 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
+ });
54258
54625
  } catch (err2) {
54259
54626
  console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
54260
54627
  }
54261
54628
  writeContextFile(opts.workspaceRoot, body2);
54262
- const target = join26(opts.workspaceRoot, "AGENTS.md");
54629
+ const target = join27(opts.workspaceRoot, "AGENTS.md");
54263
54630
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
54264
54631
  if (elicit) {
54265
- writePrimingHandles(join26(paths.configDir, "priming-handles.json"), [
54632
+ writePrimingHandles(join27(paths.configDir, "priming-handles.json"), [
54266
54633
  ...snapshot.recentProblems.map((r) => r.node),
54267
54634
  // Resolved-band handles: the ✓ problem AND its Solution are citable
54268
54635
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -54484,7 +54851,7 @@ function createWorkspaceEngine(opts) {
54484
54851
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
54485
54852
  });
54486
54853
  };
54487
- const turnCursorPath = join26(paths.configDir, "turn-cursors.json");
54854
+ const turnCursorPath = join27(paths.configDir, "turn-cursors.json");
54488
54855
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
54489
54856
  const turnOffset = loadTurnOffsets(turnCursorPath);
54490
54857
  const sessionLastProblem = /* @__PURE__ */ new Map();
@@ -54507,8 +54874,9 @@ function createWorkspaceEngine(opts) {
54507
54874
  let linked = 0;
54508
54875
  const t = Date.now();
54509
54876
  let processedTurns = 0;
54877
+ const seqAtStart = store.currentIngestSeq();
54510
54878
  const elicit = isEdgeElicitationEnabled();
54511
- const handleMap = elicit ? readPrimingHandles(join26(paths.configDir, "priming-handles.json")) : {};
54879
+ const handleMap = elicit ? readPrimingHandles(join27(paths.configDir, "priming-handles.json")) : {};
54512
54880
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
54513
54881
  const toRel = (abs) => {
54514
54882
  const p = abs.replace(/\\/g, "/");
@@ -55015,6 +55383,16 @@ function createWorkspaceEngine(opts) {
55015
55383
  if (triaged > 0) {
55016
55384
  console.log(`[errata] triage: ${triaged} wrong-door(s) captured from the conversation`);
55017
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
+ }
55018
55396
  };
55019
55397
  const harvestTurns = async (sessionId, transcriptPath) => {
55020
55398
  const known = turnOffset.get(sessionId);
@@ -55181,7 +55559,7 @@ function createWorkspaceEngine(opts) {
55181
55559
  try {
55182
55560
  const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
55183
55561
  emitAndProjectSkills(opts.workspaceRoot, inputs);
55184
- writePrimingHandles(join26(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
55562
+ writePrimingHandles(join27(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
55185
55563
  } catch (err2) {
55186
55564
  console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
55187
55565
  }
@@ -55265,6 +55643,26 @@ function createWorkspaceEngine(opts) {
55265
55643
  }
55266
55644
  return report;
55267
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
+ },
55268
55666
  async nightly() {
55269
55667
  const report = (await runNightly()).report;
55270
55668
  const summarizer = opts.intentSummarizer ?? envIntentSummarizer();
@@ -55280,6 +55678,18 @@ function createWorkspaceEngine(opts) {
55280
55678
  console.warn("[errata] symbol summary sweep failed:", err2 instanceof Error ? err2.message : err2);
55281
55679
  }
55282
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
+ });
55283
55693
  return report;
55284
55694
  },
55285
55695
  async embedSettled() {
@@ -55368,7 +55778,7 @@ function createWorkspaceEngine(opts) {
55368
55778
  console.log(
55369
55779
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
55370
55780
  );
55371
- 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;
55372
55782
  return { uploaded: 0, failed: 0, remaining: pending };
55373
55783
  }
55374
55784
  try {
@@ -55455,7 +55865,7 @@ async function startDaemon(opts) {
55455
55865
  reviewUrl: () => webUiUrl + "/review"
55456
55866
  });
55457
55867
  const writeLockFile = (url2) => {
55458
- writeFileSync19(
55868
+ writeFileSync20(
55459
55869
  engine.paths.daemonLock,
55460
55870
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
55461
55871
  "utf8"
@@ -55498,7 +55908,7 @@ async function startDaemon(opts) {
55498
55908
  );
55499
55909
  await engine.stop();
55500
55910
  try {
55501
- if (existsSync22(engine.paths.daemonLock)) {
55911
+ if (existsSync23(engine.paths.daemonLock)) {
55502
55912
  }
55503
55913
  } catch {
55504
55914
  }
@@ -55515,16 +55925,16 @@ async function listenServer(fetchFn, port) {
55515
55925
 
55516
55926
  // src/registry.ts
55517
55927
  init_paths();
55518
- import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync20 } from "node:fs";
55519
- 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";
55520
55930
  function registryPath() {
55521
- return process.env["ERRATA_REGISTRY_PATH"] ?? join27(globalDir(), "workspaces.json");
55931
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join28(globalDir(), "workspaces.json");
55522
55932
  }
55523
55933
  function read() {
55524
55934
  const p = registryPath();
55525
- if (!existsSync23(p)) return { version: 1, workspaces: {} };
55935
+ if (!existsSync24(p)) return { version: 1, workspaces: {} };
55526
55936
  try {
55527
- const parsed = JSON.parse(readFileSync22(p, "utf8"));
55937
+ const parsed = JSON.parse(readFileSync23(p, "utf8"));
55528
55938
  return { version: 1, workspaces: parsed.workspaces ?? {} };
55529
55939
  } catch {
55530
55940
  return { version: 1, workspaces: {} };
@@ -55532,7 +55942,7 @@ function read() {
55532
55942
  }
55533
55943
  function write(reg) {
55534
55944
  ensureDir(globalDir());
55535
- writeFileSync20(registryPath(), JSON.stringify(reg, null, 2), "utf8");
55945
+ writeFileSync21(registryPath(), JSON.stringify(reg, null, 2), "utf8");
55536
55946
  }
55537
55947
  function registerWorkspace(profile, root, now = Date.now()) {
55538
55948
  const reg = read();
@@ -55549,7 +55959,7 @@ function pruneMissingWorkspaces() {
55549
55959
  const reg = read();
55550
55960
  const removed = [];
55551
55961
  for (const [id, entry] of Object.entries(reg.workspaces)) {
55552
- if (!existsSync23(entry.path)) {
55962
+ if (!existsSync24(entry.path)) {
55553
55963
  removed.push(entry);
55554
55964
  delete reg.workspaces[id];
55555
55965
  }
@@ -55558,13 +55968,13 @@ function pruneMissingWorkspaces() {
55558
55968
  return removed;
55559
55969
  }
55560
55970
  function workspaceStatus(entry) {
55561
- const missing = !existsSync23(entry.path);
55971
+ const missing = !existsSync24(entry.path);
55562
55972
  const lockPath = workspacePaths(entry.path).daemonLock;
55563
55973
  let running = false;
55564
55974
  let webUiUrl = null;
55565
- if (existsSync23(lockPath)) {
55975
+ if (existsSync24(lockPath)) {
55566
55976
  try {
55567
- const lock = JSON.parse(readFileSync22(lockPath, "utf8"));
55977
+ const lock = JSON.parse(readFileSync23(lockPath, "utf8"));
55568
55978
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
55569
55979
  running = true;
55570
55980
  webUiUrl = lock.webUiUrl;
@@ -55592,7 +56002,7 @@ function pidAlive(pid) {
55592
56002
  // src/multi.ts
55593
56003
  init_dist();
55594
56004
  init_src5();
55595
- 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";
55596
56006
 
55597
56007
  // src/principle-sync.ts
55598
56008
  init_src5();
@@ -55620,8 +56030,8 @@ init_reconcile();
55620
56030
 
55621
56031
  // src/lockfile-auto.ts
55622
56032
  init_src();
55623
- import { existsSync as existsSync24, readFileSync as readFileSync23 } from "node:fs";
55624
- 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";
55625
56035
 
55626
56036
  // src/package-index.ts
55627
56037
  init_src();
@@ -55770,11 +56180,11 @@ function runLockfilePass(opts) {
55770
56180
  { file: "package-lock.json", parse: parsePackageLockJson }
55771
56181
  ];
55772
56182
  for (const c of candidates) {
55773
- const p = join28(opts.root, c.file);
55774
- if (!existsSync24(p)) continue;
56183
+ const p = join29(opts.root, c.file);
56184
+ if (!existsSync25(p)) continue;
55775
56185
  let sbom;
55776
56186
  try {
55777
- sbom = c.parse(readFileSync23(p, "utf8"));
56187
+ sbom = c.parse(readFileSync24(p, "utf8"));
55778
56188
  } catch {
55779
56189
  continue;
55780
56190
  }
@@ -56222,7 +56632,7 @@ var ConsolidateWorker = class {
56222
56632
  init_paths();
56223
56633
 
56224
56634
  // src/lock.ts
56225
- import { existsSync as existsSync25, readFileSync as readFileSync24 } from "node:fs";
56635
+ import { existsSync as existsSync26, readFileSync as readFileSync25 } from "node:fs";
56226
56636
  function isProcessAlive(pid) {
56227
56637
  if (!pid || pid <= 0) return false;
56228
56638
  try {
@@ -56233,9 +56643,9 @@ function isProcessAlive(pid) {
56233
56643
  }
56234
56644
  }
56235
56645
  function readDaemonLock(lockPath) {
56236
- if (!existsSync25(lockPath)) return null;
56646
+ if (!existsSync26(lockPath)) return null;
56237
56647
  try {
56238
- const lock = JSON.parse(readFileSync24(lockPath, "utf8"));
56648
+ const lock = JSON.parse(readFileSync25(lockPath, "utf8"));
56239
56649
  return typeof lock.pid === "number" ? lock : null;
56240
56650
  } catch {
56241
56651
  return null;
@@ -56519,12 +56929,12 @@ async function reanchorProject(opts) {
56519
56929
  }
56520
56930
 
56521
56931
  // src/adopt.ts
56522
- import { existsSync as existsSync26 } from "node:fs";
56523
- 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";
56524
56934
  function findGitRoot(absPath) {
56525
56935
  let dir = absPath;
56526
56936
  for (let depth = 0; depth < 64; depth++) {
56527
- if (existsSync26(join29(dir, ".git"))) return dir;
56937
+ if (existsSync27(join30(dir, ".git"))) return dir;
56528
56938
  const parent = dirname10(dir);
56529
56939
  if (parent === dir) return null;
56530
56940
  dir = parent;
@@ -56773,7 +57183,7 @@ async function startMultiDaemon(opts = {}) {
56773
57183
  void ambientLinkAll();
56774
57184
  app.route(`/ws/${rec.id}`, rec.webApp);
56775
57185
  try {
56776
- writeFileSync21(
57186
+ writeFileSync22(
56777
57187
  rec.engine.paths.daemonLock,
56778
57188
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
56779
57189
  "utf8"
@@ -56962,7 +57372,7 @@ async function startMultiDaemon(opts = {}) {
56962
57372
  baseUrl = `http://127.0.0.1:${port}`;
56963
57373
  try {
56964
57374
  ensureDir(globalDir());
56965
- writeFileSync21(
57375
+ writeFileSync22(
56966
57376
  lockPath,
56967
57377
  JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
56968
57378
  "utf8"
@@ -56971,7 +57381,7 @@ async function startMultiDaemon(opts = {}) {
56971
57381
  }
56972
57382
  for (const r of records) {
56973
57383
  try {
56974
- writeFileSync21(
57384
+ writeFileSync22(
56975
57385
  r.engine.paths.daemonLock,
56976
57386
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
56977
57387
  "utf8"
@@ -57098,6 +57508,22 @@ async function startMultiDaemon(opts = {}) {
57098
57508
  }
57099
57509
  return out2;
57100
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
+ },
57101
57527
  async nightlyAll() {
57102
57528
  const out2 = /* @__PURE__ */ new Map();
57103
57529
  for (const r of records) {
@@ -57503,7 +57929,7 @@ async function startMultiDaemon(opts = {}) {
57503
57929
  },
57504
57930
  async stop() {
57505
57931
  try {
57506
- const cur = readFileSync25(lockPath, "utf8");
57932
+ const cur = readFileSync26(lockPath, "utf8");
57507
57933
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
57508
57934
  } catch {
57509
57935
  }
@@ -58520,21 +58946,21 @@ async function cmdInit() {
58520
58946
  if (!skipHooks) {
58521
58947
  console.log("");
58522
58948
  console.log("installing harness hooks...");
58523
- const { existsSync: existsSync28 } = await import("node:fs");
58524
- const { join: join31 } = await import("node:path");
58949
+ const { existsSync: existsSync29 } = await import("node:fs");
58950
+ const { join: join32 } = await import("node:path");
58525
58951
  try {
58526
58952
  await installClaudeHooks(port);
58527
58953
  } catch (err2) {
58528
58954
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
58529
58955
  }
58530
- if (existsSync28(join31(ROOT, ".cursor"))) {
58956
+ if (existsSync29(join32(ROOT, ".cursor"))) {
58531
58957
  try {
58532
58958
  await installCursorMcpConfig();
58533
58959
  } catch (err2) {
58534
58960
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
58535
58961
  }
58536
58962
  }
58537
- if (existsSync28(join31(ROOT, ".codex"))) {
58963
+ if (existsSync29(join32(ROOT, ".codex"))) {
58538
58964
  try {
58539
58965
  await installCodexHooks(port);
58540
58966
  } catch (err2) {
@@ -58691,9 +59117,9 @@ async function cmdStatus() {
58691
59117
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
58692
59118
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
58693
59119
  }
58694
- console.log(` graph db: ${existsSync27(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
58695
- console.log(` event log: ${existsSync27(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
58696
- 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)) {
58697
59123
  try {
58698
59124
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
58699
59125
  const store = openGraphStore2({ path: paths.castalia });
@@ -59374,11 +59800,11 @@ function cmdInstallationProfile(args2) {
59374
59800
  }
59375
59801
  async function cmdReview() {
59376
59802
  const paths = workspacePaths(ROOT);
59377
- if (!existsSync27(paths.reviewQueue)) {
59803
+ if (!existsSync28(paths.reviewQueue)) {
59378
59804
  console.log("(review queue empty)");
59379
59805
  return;
59380
59806
  }
59381
- const queue = JSON.parse(readFileSync26(paths.reviewQueue, "utf8"));
59807
+ const queue = JSON.parse(readFileSync27(paths.reviewQueue, "utf8"));
59382
59808
  if (queue.length === 0) {
59383
59809
  console.log("(review queue empty)");
59384
59810
  return;
@@ -60049,7 +60475,7 @@ async function gatherRepo(store, ws) {
60049
60475
  };
60050
60476
  }
60051
60477
  async function gatherReportData(generatedAt) {
60052
- const { existsSync: existsSync28 } = await import("node:fs");
60478
+ const { existsSync: existsSync29 } = await import("node:fs");
60053
60479
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
60054
60480
  const cfg = loadConfig();
60055
60481
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -60057,7 +60483,7 @@ async function gatherReportData(generatedAt) {
60057
60483
  for (const ws of listWorkspaces()) {
60058
60484
  if (ws.missing) continue;
60059
60485
  const dbPath = workspacePaths(ws.path).castalia;
60060
- if (!existsSync28(dbPath)) continue;
60486
+ if (!existsSync29(dbPath)) continue;
60061
60487
  let store = null;
60062
60488
  try {
60063
60489
  store = openGraphStore2({ path: dbPath });
@@ -60088,7 +60514,7 @@ async function gatherReportData(generatedAt) {
60088
60514
  };
60089
60515
  }
60090
60516
  async function cmdReport(args2) {
60091
- const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync22 } = await import("node:fs");
60517
+ const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync23 } = await import("node:fs");
60092
60518
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
60093
60519
  const includeFutureVerbs = args2.includes("--future-verbs");
60094
60520
  const now = /* @__PURE__ */ new Date();
@@ -60101,8 +60527,8 @@ async function cmdReport(args2) {
60101
60527
  const outDir = workspacePaths(ROOT).configDir;
60102
60528
  mkdirSync8(outDir, { recursive: true });
60103
60529
  const files = renderReport2(data, { includeFutureVerbs });
60104
- for (const f of files) writeFileSync22(join30(outDir, f.name), f.html, "utf8");
60105
- 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");
60106
60532
  console.log(`report \u2192 ${indexPath}`);
60107
60533
  console.log(
60108
60534
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -60220,15 +60646,15 @@ function hookRelayCommand(port, path2) {
60220
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 '{}'`;
60221
60647
  }
60222
60648
  async function installClaudeHooks(port) {
60223
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60224
- const { join: join31 } = await import("node:path");
60225
- const dir = join31(ROOT, ".claude");
60226
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60227
- 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");
60228
60654
  let settings = {};
60229
- if (existsSync28(file2)) {
60655
+ if (existsSync29(file2)) {
60230
60656
  try {
60231
- settings = JSON.parse(readFileSync27(file2, "utf8"));
60657
+ settings = JSON.parse(readFileSync28(file2, "utf8"));
60232
60658
  } catch {
60233
60659
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
60234
60660
  process.exit(2);
@@ -60274,10 +60700,10 @@ async function installClaudeHooks(port) {
60274
60700
  dropErrata(list);
60275
60701
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
60276
60702
  }
60277
- writeFileSync22(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
60703
+ writeFileSync23(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
60278
60704
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
60279
60705
  await installClaudeMcpConfig();
60280
- const claudeMd = join31(ROOT, "CLAUDE.md");
60706
+ const claudeMd = join32(ROOT, "CLAUDE.md");
60281
60707
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
60282
60708
  if (recall.kind === "collision") {
60283
60709
  console.warn(
@@ -60289,15 +60715,15 @@ async function installClaudeHooks(port) {
60289
60715
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
60290
60716
  }
60291
60717
  async function installClaudeMcpConfig() {
60292
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60293
- const { join: join31, dirname: dirname11 } = await import("node:path");
60294
- 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");
60295
60721
  const dir = dirname11(file2);
60296
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60722
+ if (!existsSync29(dir)) mkdirSync8(dir, { recursive: true });
60297
60723
  let cfg = {};
60298
- if (existsSync28(file2)) {
60724
+ if (existsSync29(file2)) {
60299
60725
  try {
60300
- cfg = JSON.parse(readFileSync27(file2, "utf8"));
60726
+ cfg = JSON.parse(readFileSync28(file2, "utf8"));
60301
60727
  } catch {
60302
60728
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
60303
60729
  process.exit(2);
@@ -60305,21 +60731,21 @@ async function installClaudeMcpConfig() {
60305
60731
  }
60306
60732
  cfg.mcpServers ??= {};
60307
60733
  cfg.mcpServers["errata"] = errataMcpInvocation();
60308
- writeFileSync22(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60734
+ writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60309
60735
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
60310
60736
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
60311
60737
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
60312
60738
  }
60313
60739
  async function installCursorMcpConfig() {
60314
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60315
- const { join: join31 } = await import("node:path");
60316
- const dir = join31(ROOT, ".cursor");
60317
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60318
- 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");
60319
60745
  let cfg = {};
60320
- if (existsSync28(file2)) {
60746
+ if (existsSync29(file2)) {
60321
60747
  try {
60322
- cfg = JSON.parse(readFileSync27(file2, "utf8"));
60748
+ cfg = JSON.parse(readFileSync28(file2, "utf8"));
60323
60749
  } catch {
60324
60750
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
60325
60751
  process.exit(2);
@@ -60327,7 +60753,7 @@ async function installCursorMcpConfig() {
60327
60753
  }
60328
60754
  cfg.mcpServers ??= {};
60329
60755
  cfg.mcpServers["errata"] = errataMcpInvocation();
60330
- writeFileSync22(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60756
+ writeFileSync23(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
60331
60757
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
60332
60758
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
60333
60759
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -60335,16 +60761,16 @@ async function installCursorMcpConfig() {
60335
60761
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
60336
60762
  }
60337
60763
  async function installCodexHooks(port) {
60338
- const { mkdirSync: mkdirSync8, existsSync: existsSync28, readFileSync: readFileSync27, writeFileSync: writeFileSync22 } = await import("node:fs");
60339
- const { join: join31 } = await import("node:path");
60340
- const dir = join31(ROOT, ".codex");
60341
- if (!existsSync28(dir)) mkdirSync8(dir, { recursive: true });
60342
- 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");
60343
60769
  const BEGIN = `# >>> errata hooks (errata-managed)`;
60344
60770
  const END = `# <<< errata hooks`;
60345
60771
  let existing = "";
60346
- if (existsSync28(file2)) {
60347
- existing = readFileSync27(file2, "utf8");
60772
+ if (existsSync29(file2)) {
60773
+ existing = readFileSync28(file2, "utf8");
60348
60774
  const beginIdx = existing.indexOf(BEGIN);
60349
60775
  const endIdx = existing.indexOf(END);
60350
60776
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -60373,7 +60799,7 @@ ${END}
60373
60799
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
60374
60800
 
60375
60801
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
60376
- writeFileSync22(file2, final, "utf8");
60802
+ writeFileSync23(file2, final, "utf8");
60377
60803
  console.log(`installed Codex hooks \u2192 ${file2}`);
60378
60804
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
60379
60805
  console.log("");
@@ -60566,16 +60992,38 @@ async function cmdDash(args2) {
60566
60992
  }).catch(() => {
60567
60993
  });
60568
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
+ };
60569
61015
  const scheduleQuiescenceFlush = () => {
60570
61016
  if (quiesceTimer) clearTimeout(quiesceTimer);
60571
61017
  quiesceTimer = setTimeout(() => {
60572
61018
  quiesceTimer = null;
60573
61019
  runBoundaryFlush("quiescent");
61020
+ runSemanticPass("quiescent");
60574
61021
  triggerConsolidation(false);
60575
61022
  }, QUIESCENCE_MS);
60576
61023
  };
60577
61024
  handle2.onSessionBoundary(() => {
60578
61025
  runBoundaryFlush("session-end");
61026
+ runSemanticPass("session-end");
60579
61027
  triggerConsolidation(true);
60580
61028
  });
60581
61029
  let ticking = false;
@@ -60687,7 +61135,7 @@ async function cmdDash(args2) {
60687
61135
  await yieldToLoop2();
60688
61136
  try {
60689
61137
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
60690
- const res = bleedRules(join30(r.root, ".claude", "rules"), items);
61138
+ const res = bleedRules(join31(r.root, ".claude", "rules"), items);
60691
61139
  if (res.written || res.pruned) {
60692
61140
  console.log(
60693
61141
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
@@ -60789,7 +61237,10 @@ async function cmdDash(args2) {
60789
61237
  }
60790
61238
  };
60791
61239
  triggerConsolidation = (force) => void maybeConsolidate(force);
60792
- const nightlyInterval = setInterval(() => triggerConsolidation(false), NIGHTLY_INTERVAL_MS);
61240
+ const nightlyInterval = setInterval(() => {
61241
+ runSemanticPass("periodic");
61242
+ triggerConsolidation(false);
61243
+ }, NIGHTLY_INTERVAL_MS);
60793
61244
  const shutdown = async (signal) => {
60794
61245
  console.log(`
60795
61246
  shutting down\u2026 (${signal})`);