@inerrata-corporation/errata 2.0.14-dev.3165 → 2.0.14-dev.3236

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
@@ -17278,6 +17278,18 @@ var init_triage_canon = __esm({
17278
17278
  }
17279
17279
  });
17280
17280
 
17281
+ // ../../packages/shared/src/project-wire-attrs.ts
17282
+ function projectWireAttrs(obj) {
17283
+ return Object.fromEntries(Object.entries(obj).filter(
17284
+ ([key]) => !/^(?:orgId|teamId|groupId|projectId|aliasTexts|aliasCanonicalIds|mergedFrom.*|.*WitnessKeys|.*Sessions|authoringSession.*|contributor.*|witnessKeys.*)$/.test(key)
17285
+ ));
17286
+ }
17287
+ var init_project_wire_attrs = __esm({
17288
+ "../../packages/shared/src/project-wire-attrs.ts"() {
17289
+ "use strict";
17290
+ }
17291
+ });
17292
+
17281
17293
  // ../../packages/shared/src/index.ts
17282
17294
  var src_exports = {};
17283
17295
  __export(src_exports, {
@@ -17437,6 +17449,7 @@ __export(src_exports, {
17437
17449
  problemIdFromError: () => problemIdFromError,
17438
17450
  projectSaltedNodeId: () => projectSaltedNodeId,
17439
17451
  projectSymbolId: () => projectSymbolId,
17452
+ projectWireAttrs: () => projectWireAttrs,
17440
17453
  provenanceBand: () => provenanceBand,
17441
17454
  resolveCanonical: () => resolveCanonical,
17442
17455
  resolveCanonicalId: () => resolveCanonicalId,
@@ -17491,6 +17504,7 @@ var init_src = __esm({
17491
17504
  init_taxonomy();
17492
17505
  init_triage_canon();
17493
17506
  init_history_text();
17507
+ init_project_wire_attrs();
17494
17508
  }
17495
17509
  });
17496
17510
 
@@ -17918,9 +17932,10 @@ var init_src2 = __esm({
17918
17932
 
17919
17933
  // ../../packages/local-graph/src/history-cache-floor.ts
17920
17934
  function installHistoryCacheFloor(db) {
17921
- const key = "history-cache-withdrawal-floor-2";
17935
+ const key = "history-cache-withdrawal-floor-3";
17922
17936
  if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get(key)) return;
17923
17937
  db.transaction(() => {
17938
+ db.exec("DROP TRIGGER IF EXISTS history_cache_nodes_insert; DROP TRIGGER IF EXISTS history_cache_nodes_update;");
17924
17939
  if (db.prepare("SELECT value FROM store_meta WHERE key = ?").get("history-cache-withdrawal-floor-1")) {
17925
17940
  db.exec("DROP INDEX IF EXISTS nodes_cloud_id");
17926
17941
  }
@@ -17938,9 +17953,10 @@ function installHistoryCacheFloor(db) {
17938
17953
  `);
17939
17954
  const lookup = (field) => `(SELECT ${field} FROM history_cache_withdrawals w WHERE w.id = nodes.id)`;
17940
17955
  const privacy = `coalesce(${lookup("privacy")}, 0)`;
17941
- const description = `CASE WHEN ${privacy} THEN 'History source withdrawn.' ELSE description END`;
17956
+ const source = `coalesce(json_extract(attrs_json, '$.extractionSource'), extraction_source)`;
17957
+ const description = `CASE WHEN ${privacy} THEN CASE WHEN ${source} = 'history-mined' THEN 'History source withdrawn.' ELSE 'Cloud source withdrawn.' END ELSE description END`;
17942
17958
  const attrs = `CASE WHEN ${privacy} THEN json_object(
17943
- 'source', 'cloud', 'cloudNodeId', ${lookup("cloud_id")}, 'extractionSource', 'history-mined',
17959
+ 'source', 'cloud', 'cloudNodeId', ${lookup("cloud_id")}, 'extractionSource', ${source},
17944
17960
  'historyQuality', json_object('sourceSupport', 'quarantined', 'applicability', 'unknown'),
17945
17961
  'historyCorrectionSeq', ${lookup("seq")})
17946
17962
  ELSE json_set(json_remove(attrs_json, '$.embeddingVersion'),
@@ -17953,11 +17969,22 @@ function installHistoryCacheFloor(db) {
17953
17969
  OR EXISTS(SELECT 1 FROM history_cache_withdrawals w WHERE w.id = nodes.id))
17954
17970
  AND (embedding_blob IS NOT NULL OR embedding_json <> '[]' OR is_landmark <> 0
17955
17971
  OR description <> ${description} OR attrs_json <> ${attrs});`;
17972
+ const internal = `key IN ('orgId','teamId','groupId','projectId','aliasTexts','aliasCanonicalIds')
17973
+ OR key GLOB 'mergedFrom*' OR key GLOB '*WitnessKeys' OR key GLOB '*Sessions'
17974
+ OR key GLOB 'authoringSession*' OR key GLOB 'contributor*' OR key GLOB 'witnessKeys*'`;
17975
+ const stripMetadata = (scope) => `UPDATE nodes SET attrs_json=(
17976
+ SELECT json_group_object(key, CASE WHEN type IN ('array','object') THEN json(value)
17977
+ WHEN type IN ('true','false') THEN json(type) ELSE value END)
17978
+ FROM json_each(nodes.attrs_json) WHERE NOT (${internal}))
17979
+ WHERE (${scope}) AND json_extract(attrs_json,'$.source')='cloud'
17980
+ AND EXISTS(SELECT 1 FROM store_meta m WHERE m.key='history-correction:' || coalesce(json_extract(nodes.attrs_json,'$.cloudNodeId'),nodes.id) AND json_valid(m.value))
17981
+ AND EXISTS(SELECT 1 FROM json_each(nodes.attrs_json) WHERE ${internal});`;
17956
17982
  for (const operation of ["INSERT", "UPDATE"]) {
17957
17983
  db.exec(`CREATE TRIGGER IF NOT EXISTS history_cache_nodes_${operation.toLowerCase()}
17958
- AFTER ${operation} ON nodes BEGIN ${repair("id = NEW.id")} END;`);
17984
+ AFTER ${operation} ON nodes BEGIN ${repair("id = NEW.id")} ${stripMetadata("id = NEW.id")} END;`);
17959
17985
  }
17960
17986
  db.exec(repair("json_extract(attrs_json, '$.source') = 'cloud' OR json_extract(attrs_json, '$.historyQuality.sourceSupport') IN ('quarantined','contradicted')"));
17987
+ db.exec(stripMetadata("1=1"));
17961
17988
  db.prepare("INSERT INTO store_meta(key,value) VALUES (?,?)").run(key, "installed");
17962
17989
  });
17963
17990
  }
@@ -22609,14 +22636,14 @@ function localMoving(nodeIds, g) {
22609
22636
  return community;
22610
22637
  }
22611
22638
  function refineConnectivity(community, g) {
22612
- const members2 = /* @__PURE__ */ new Map();
22639
+ const members = /* @__PURE__ */ new Map();
22613
22640
  for (const [id, c] of community) {
22614
- const l = members2.get(c) ?? [];
22641
+ const l = members.get(c) ?? [];
22615
22642
  l.push(id);
22616
- members2.set(c, l);
22643
+ members.set(c, l);
22617
22644
  }
22618
22645
  const refined = /* @__PURE__ */ new Map();
22619
- for (const [, group] of members2) {
22646
+ for (const [, group] of members) {
22620
22647
  const inGroup = new Set(group);
22621
22648
  const seen = /* @__PURE__ */ new Set();
22622
22649
  for (const start2 of [...group].sort()) {
@@ -23535,7 +23562,7 @@ function sharedScope(l2, memberIds) {
23535
23562
  const versionRange = shared("versionRange");
23536
23563
  return { ...lang ? { lang } : {}, ...versionRange ? { versionRange } : {} };
23537
23564
  }
23538
- function buildCandidate(id, ts, members2, contexts, originMachine, scope) {
23565
+ function buildCandidate(id, ts, members, contexts, originMachine, scope) {
23539
23566
  return {
23540
23567
  id,
23541
23568
  label: "Claim",
@@ -23561,7 +23588,7 @@ function buildCandidate(id, ts, members2, contexts, originMachine, scope) {
23561
23588
  pendingDistillation: true,
23562
23589
  // membership is the unit of truth — the harness validates its fence against
23563
23590
  // this set (P3 / C3) and may only phrase, never alter, it.
23564
- members: members2,
23591
+ members,
23565
23592
  memberContexts: contexts,
23566
23593
  distinctContexts: contexts.length,
23567
23594
  // standard Claim envelope so it crystallizes/syncs unchanged once distilled
@@ -23633,14 +23660,14 @@ function induceAbstractions(l2, opts) {
23633
23660
  }
23634
23661
  const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
23635
23662
  report.communities = comm.count;
23636
- const members2 = /* @__PURE__ */ new Map();
23663
+ const members = /* @__PURE__ */ new Map();
23637
23664
  for (const [id, c] of comm.community) {
23638
- const l = members2.get(c) ?? [];
23665
+ const l = members.get(c) ?? [];
23639
23666
  l.push(id);
23640
- members2.set(c, l);
23667
+ members.set(c, l);
23641
23668
  }
23642
23669
  l2.transaction(() => {
23643
- for (const mem of members2.values()) {
23670
+ for (const mem of members.values()) {
23644
23671
  if (opts.touched && !mem.some((id) => opts.touched.has(id))) continue;
23645
23672
  if (mem.length < K) {
23646
23673
  report.skippedSmall++;
@@ -23682,14 +23709,14 @@ function pendingAbstractions(l2) {
23682
23709
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
23683
23710
  if (n.attrs["provisional"] !== true) continue;
23684
23711
  const memberIds = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
23685
- const members2 = memberIds.map((id) => {
23712
+ const members = memberIds.map((id) => {
23686
23713
  const m = l2.getNode(id);
23687
23714
  return m ? { id: m.id, label: m.label, description: m.description } : { id, label: "?", description: "(member missing)" };
23688
23715
  });
23689
23716
  out2.push({
23690
23717
  candidate: n.id,
23691
23718
  distinctContexts: Number(n.attrs["distinctContexts"] ?? 0),
23692
- members: members2
23719
+ members
23693
23720
  });
23694
23721
  }
23695
23722
  return out2;
@@ -23719,10 +23746,10 @@ function applyAbstractionFence(l2, fence, ts) {
23719
23746
  if (node2.attrs["provisional"] !== true) {
23720
23747
  return { applied: false, principleId: fence.candidate, reason: "candidate already distilled" };
23721
23748
  }
23722
- const members2 = Array.isArray(node2.attrs["members"]) ? node2.attrs["members"] : [];
23723
- const want = new Set(members2);
23749
+ const members = Array.isArray(node2.attrs["members"]) ? node2.attrs["members"] : [];
23750
+ const want = new Set(members);
23724
23751
  const got = new Set(fence.covers);
23725
- const missing = members2.filter((id) => !got.has(id));
23752
+ const missing = members.filter((id) => !got.has(id));
23726
23753
  const invented = fence.covers.filter((id) => !want.has(id));
23727
23754
  if (missing.length > 0 || invented.length > 0) {
23728
23755
  return {
@@ -23753,10 +23780,10 @@ function revisitContradictedPrinciples(l2, ts) {
23753
23780
  for (const n of l2.findNodesByLabel("Claim")) {
23754
23781
  if (Number(n.attrs["abstractionLevel"] ?? ABSTRACTION_LEVEL.CONCRETE) < ABSTRACTION_LEVEL.PRINCIPLE) continue;
23755
23782
  if (n.attrs["revisit"] === true) continue;
23756
- const members2 = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
23757
- const memberSet = new Set(members2);
23783
+ const members = Array.isArray(n.attrs["members"]) ? n.attrs["members"] : [];
23784
+ const memberSet = new Set(members);
23758
23785
  let reason = "";
23759
- for (const id of members2) {
23786
+ for (const id of members) {
23760
23787
  const m = l2.getNode(id);
23761
23788
  if (!m) {
23762
23789
  reason = `member ${id} was removed`;
@@ -23847,14 +23874,14 @@ function detectLocalCommunities(store, opts = {}) {
23847
23874
  }
23848
23875
  }
23849
23876
  const comm = detectCommunitiesLeiden({ nodeIds: [...ids], adj }, { protect });
23850
- const members2 = /* @__PURE__ */ new Map();
23877
+ const members = /* @__PURE__ */ new Map();
23851
23878
  for (const [id, c] of comm.community) {
23852
- const l = members2.get(c) ?? [];
23879
+ const l = members.get(c) ?? [];
23853
23880
  l.push(id);
23854
- members2.set(c, l);
23881
+ members.set(c, l);
23855
23882
  }
23856
23883
  store.transaction(() => {
23857
- for (const [cid, mem] of members2) {
23884
+ for (const [cid, mem] of members) {
23858
23885
  const qualifies = mem.length >= minSize;
23859
23886
  let hasLocal = false;
23860
23887
  let hasCloud = false;
@@ -30877,8 +30904,8 @@ var init_generalizer = __esm({
30877
30904
  function layerOf(kind) {
30878
30905
  return kind === "Technique" ? "technique" : kind === "AntiPattern" ? "antipattern" : "pattern";
30879
30906
  }
30880
- function motifTitle(members2, layer, instanceCount) {
30881
- const top = [...members2].sort(
30907
+ function motifTitle(members, layer, instanceCount) {
30908
+ const top = [...members].sort(
30882
30909
  (a, b) => b.extractionConfidence - a.extractionConfidence
30883
30910
  )[0];
30884
30911
  return `${layer} \xD7${instanceCount} (exemplar): ${top?.description ?? "recurring problem cluster"}`;
@@ -30907,17 +30934,17 @@ function promoteMotifs(store, t) {
30907
30934
  let techniques = 0;
30908
30935
  let antipatterns = 0;
30909
30936
  store.transaction(() => {
30910
- for (const [cid, members2] of byCommunity) {
30911
- const instances = members2.filter((m) => m.label === "Problem");
30912
- const instanceCount = instances.length || members2.length;
30937
+ for (const [cid, members] of byCommunity) {
30938
+ const instances = members.filter((m) => m.label === "Problem");
30939
+ const instanceCount = instances.length || members.length;
30913
30940
  const motifId = `motif_${cid}`;
30914
30941
  const existing = store.getNode(motifId);
30915
30942
  const d = motifDecision({
30916
- instances: members2.map((m) => ({
30943
+ instances: members.map((m) => ({
30917
30944
  confidence: m.extractionConfidence,
30918
30945
  failed: false
30919
30946
  })),
30920
- memberCount: members2.length,
30947
+ memberCount: members.length,
30921
30948
  instanceCount,
30922
30949
  priorSurvivedRuns: existing?.attrs["survivedRuns"] ?? 0
30923
30950
  });
@@ -30929,7 +30956,7 @@ function promoteMotifs(store, t) {
30929
30956
  label: kind,
30930
30957
  // Refresh the deterministic title every run (exemplar/count/kind drift),
30931
30958
  // but never clobber a distilled one — a distillation pass owns it then.
30932
- description: existing?.attrs["titleDistilled"] === true ? existing.description : motifTitle(members2, layerOf(kind), instanceCount),
30959
+ description: existing?.attrs["titleDistilled"] === true ? existing.description : motifTitle(members, layerOf(kind), instanceCount),
30933
30960
  extractionConfidence: d.motifConfidence,
30934
30961
  extractionSource: "bko-inferred",
30935
30962
  embedding: existing?.embedding ?? [],
@@ -30948,7 +30975,7 @@ function promoteMotifs(store, t) {
30948
30975
  communityId: cid,
30949
30976
  survivedRuns: d.survivedRuns,
30950
30977
  motifConfidence: d.motifConfidence,
30951
- memberCount: members2.length,
30978
+ memberCount: members.length,
30952
30979
  instanceCount,
30953
30980
  promoted: d.promoted
30954
30981
  }
@@ -31969,47 +31996,43 @@ var init_recall_card = __esm({
31969
31996
  });
31970
31997
 
31971
31998
  // src/recall-signal.ts
31999
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
32000
+ import { join as join7 } from "node:path";
31972
32001
  function live(n) {
31973
32002
  return n != null && n.validTo == null && historyReadPolicy(n, { mode: "passive" }).allow;
31974
32003
  }
31975
32004
  function isPlaceholderFix(n) {
31976
32005
  return n.label === "Solution" && (n.description ?? "").startsWith(AUTO_MINT_PREFIX);
31977
32006
  }
31978
- function causalChains(store, problems, scoreOf) {
31979
- const best = (ids) => ids.sort((a, b) => scoreOf(b.id) - scoreOf(a.id))[0];
32007
+ function causalChains(store, problems) {
32008
+ const newest = (nodes) => nodes.sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt)[0];
31980
32009
  const chains = [];
31981
32010
  for (const problem of problems) {
31982
- const causes = store.outEdges(problem.id, ["CAUSED_BY"]).map((e) => store.getNode(e.to)).filter((n) => live(n) && n.label === "RootCause");
31983
- const fixes = store.outEdges(problem.id, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => live(n) && n.label === "Solution" && !isPlaceholderFix(n));
31984
- const cause = best(causes);
31985
- const fix = best(fixes);
32011
+ const cause = newest(
32012
+ store.outEdges(problem.id, ["CAUSED_BY"]).map((e) => store.getNode(e.to)).filter((n) => live(n) && n.label === "RootCause")
32013
+ );
32014
+ const fix = newest(
32015
+ store.outEdges(problem.id, ["SOLVED_BY"]).map((e) => store.getNode(e.to)).filter((n) => live(n) && n.label === "Solution" && !isPlaceholderFix(n))
32016
+ );
31986
32017
  if (cause || fix) chains.push({ problem, ...cause ? { cause } : {}, ...fix ? { fix } : {} });
31987
32018
  }
31988
32019
  return chains;
31989
32020
  }
31990
- function members(c) {
31991
- return [c.problem, c.cause, c.fix].filter((n) => n != null);
31992
- }
31993
- function pickChain(chains, scoreOf) {
31994
- const mean = (c) => {
31995
- const m = members(c);
31996
- return m.reduce((s, n) => s + scoreOf(n.id), 0) / m.length;
31997
- };
31998
- return chains.filter((c) => scoreOf(c.problem.id) > 0).sort((a, b) => members(b).length - members(a).length || mean(b) - mean(a))[0];
31999
- }
32000
32021
  function item(n) {
32001
32022
  return { label: n.label, text: n.description ?? "" };
32002
32023
  }
32003
- function signalCard(headline, ranked, chains, chainScores = /* @__PURE__ */ new Map()) {
32004
- if (ranked.length === 0 && chains.length === 0) return null;
32005
- const score2 = new Map([...chainScores, ...ranked.map((r) => [r.id, r.score])]);
32006
- const scoreOf = (id) => score2.get(id) ?? 0;
32007
- const chain2 = pickChain(chains, scoreOf);
32008
- const inChain = new Set(chain2 ? members(chain2).map((n) => n.id) : []);
32009
- const single = ranked.find((r) => r.score > 0 && !inChain.has(r.id))?.node;
32024
+ function deliveredPrior(n) {
32025
+ return { id: n.id, label: n.label, text: n.description ?? "" };
32026
+ }
32027
+ function deliveredCard(store, headline, delivered) {
32028
+ if (delivered.length === 0) return null;
32029
+ const problems = delivered.filter((d) => d.label === "Problem").map((d) => store.getNode(d.id)).filter((n) => live(n));
32030
+ const chain2 = causalChains(store, problems)[0];
32031
+ const inChain = new Set(chain2 ? [chain2.problem.id, chain2.cause?.id, chain2.fix?.id] : []);
32032
+ const single = delivered.find((d) => !inChain.has(d.id));
32010
32033
  return {
32011
32034
  headline,
32012
- items: ranked.map((r) => item(r.node)),
32035
+ items: delivered.map((d) => ({ label: d.label, text: d.text })),
32013
32036
  ...chain2 ? {
32014
32037
  chain: {
32015
32038
  problem: item(chain2.problem),
@@ -32017,19 +32040,43 @@ function signalCard(headline, ranked, chains, chainScores = /* @__PURE__ */ new
32017
32040
  ...chain2.fix ? { fix: item(chain2.fix) } : {}
32018
32041
  }
32019
32042
  } : {},
32020
- ...single ? { single: item(single) } : {}
32043
+ ...single ? { single: { label: single.label, text: single.text } } : {}
32021
32044
  };
32022
32045
  }
32023
- function promptPool(store, limit = 150) {
32024
- const problems = [...openProblems(store)].sort((a, b) => b.lastUpdatedAt - a.lastUpdatedAt).slice(0, limit);
32025
- const ids = new Set(problems.map((p) => p.id));
32026
- for (const p of problems) {
32027
- for (const e of store.outEdges(p.id, ["CAUSED_BY", "SOLVED_BY"])) {
32028
- const n = store.getNode(e.to);
32029
- if (live(n) && !isPlaceholderFix(n)) ids.add(n.id);
32030
- }
32046
+ function clipIntent(text, width = 48) {
32047
+ const flat = text.replace(/\s+/g, " ").trim();
32048
+ return flat.length > width ? `${flat.slice(0, width - 1)}\u2026` : flat;
32049
+ }
32050
+ function contextCard(store, snapshot) {
32051
+ const seen = /* @__PURE__ */ new Set();
32052
+ const delivered = [];
32053
+ const add = (n) => {
32054
+ if (!n.id || seen.has(n.id)) return;
32055
+ seen.add(n.id);
32056
+ delivered.push(deliveredPrior(n));
32057
+ };
32058
+ for (const h of snapshot.statedIntent?.hits ?? []) add(h);
32059
+ for (const h of snapshot.statedIntent?.remoteHits ?? []) add(h);
32060
+ for (const p of snapshot.workingFile?.priors?.openProblems ?? []) add({ ...p, label: "Problem" });
32061
+ for (const r of snapshot.recentProblems) add(r.node);
32062
+ for (const n of snapshot.remote ?? []) add(n);
32063
+ for (const m of snapshot.motifs) add(m);
32064
+ const count = plural(delivered.length, "prior");
32065
+ const intent = snapshot.statedIntent?.text;
32066
+ return deliveredCard(store, intent ? `${count} for \u201C${clipIntent(intent)}\u201D` : `${count} in context`, delivered);
32067
+ }
32068
+ function writeContextCard(root, hash2, card) {
32069
+ writeFileSync6(join7(root, ".errata", CONTEXT_CARD_FILE), JSON.stringify({ hash: hash2, card }));
32070
+ }
32071
+ function readContextCard(root, hash2) {
32072
+ const path2 = join7(root, ".errata", CONTEXT_CARD_FILE);
32073
+ if (!existsSync7(path2)) return null;
32074
+ try {
32075
+ const saved = JSON.parse(readFileSync5(path2, "utf8"));
32076
+ return saved.hash === hash2 ? saved.card ?? null : null;
32077
+ } catch {
32078
+ return null;
32031
32079
  }
32032
- return { problems, ids: [...ids] };
32033
32080
  }
32034
32081
  function openProblems(store, now = Date.now()) {
32035
32082
  const hit = openProblemsCache.get(store);
@@ -32038,60 +32085,34 @@ function openProblems(store, now = Date.now()) {
32038
32085
  openProblemsCache.set(store, { at: now, nodes });
32039
32086
  return nodes;
32040
32087
  }
32041
- async function promptRecallCard(store, prompt) {
32042
- const { problems, ids } = promptPool(store);
32043
- if (ids.length === 0) return null;
32044
- const ranked = await rankForText(store, prompt.slice(0, 2e3), ids);
32045
- const matched = promptMatches(ranked);
32046
- if (matched.length === 0) return null;
32047
- const score2 = new Map(ranked.map((r) => [r.id, r.score]));
32048
- const matchedIds = new Set(matched.map((r) => r.id));
32049
- const chains = causalChains(store, problems.filter((p) => matchedIds.has(p.id)), (id) => score2.get(id) ?? 0);
32050
- const verb = matched.length === 1 ? "matches" : "match";
32051
- const card = signalCard(`${plural(matched.length, "prior")} ${verb} this prompt`, matched, chains, score2);
32052
- return card && { ...card, moreWhere: "matching" };
32053
- }
32054
- function promptMatches(ranked, sigmas = 3.5) {
32055
- const sims = ranked.map((r) => r.components.semantic ?? 0);
32056
- if (sims.length < 3) return [...ranked];
32057
- const median = (xs) => {
32058
- const s = [...xs].sort((a, b) => a - b);
32059
- const m = s.length >> 1;
32060
- return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
32061
- };
32062
- const center = median(sims);
32063
- const sigma = 1.4826 * median(sims.map((x) => Math.abs(x - center)));
32064
- if (sigma === 0) return [];
32065
- return ranked.map((r, i2) => ({ r, sim: sims[i2] })).filter((x) => x.sim >= center + sigmas * sigma).sort((a, b) => b.sim - a.sim || b.r.score - a.r.score).map((x) => x.r);
32066
- }
32067
32088
  function openProblemCount(store) {
32068
32089
  return openProblems(store).length;
32069
32090
  }
32070
- var OPEN_PROBLEMS_TTL_MS, openProblemsCache;
32091
+ var CONTEXT_CARD_FILE, OPEN_PROBLEMS_TTL_MS, openProblemsCache;
32071
32092
  var init_recall_signal = __esm({
32072
32093
  "src/recall-signal.ts"() {
32073
32094
  "use strict";
32074
32095
  init_src5();
32075
32096
  init_src();
32076
- init_src8();
32077
32097
  init_recall_card();
32098
+ CONTEXT_CARD_FILE = "context-card.json";
32078
32099
  OPEN_PROBLEMS_TTL_MS = 6e4;
32079
32100
  openProblemsCache = /* @__PURE__ */ new WeakMap();
32080
32101
  }
32081
32102
  });
32082
32103
 
32083
32104
  // src/review.ts
32084
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
32105
+ import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
32085
32106
  function loadReviewQueue(paths) {
32086
- if (!existsSync7(paths.reviewQueue)) return [];
32107
+ if (!existsSync8(paths.reviewQueue)) return [];
32087
32108
  try {
32088
- return JSON.parse(readFileSync5(paths.reviewQueue, "utf8"));
32109
+ return JSON.parse(readFileSync6(paths.reviewQueue, "utf8"));
32089
32110
  } catch {
32090
32111
  return [];
32091
32112
  }
32092
32113
  }
32093
32114
  function saveReviewQueue(paths, queue) {
32094
- writeFileSync6(paths.reviewQueue, JSON.stringify(queue, null, 2), "utf8");
32115
+ writeFileSync7(paths.reviewQueue, JSON.stringify(queue, null, 2), "utf8");
32095
32116
  }
32096
32117
  function addProposal(paths, store, node2, reason, surprise) {
32097
32118
  const queue = loadReviewQueue(paths);
@@ -32161,14 +32182,14 @@ var init_consent = __esm({
32161
32182
  });
32162
32183
 
32163
32184
  // src/git-remote.ts
32164
- import { existsSync as existsSync8, readFileSync as readFileSync6, statSync } from "node:fs";
32165
- import { isAbsolute as isAbsolute2, join as join7, resolve } from "node:path";
32185
+ import { existsSync as existsSync9, readFileSync as readFileSync7, statSync } from "node:fs";
32186
+ import { isAbsolute as isAbsolute2, join as join8, resolve } from "node:path";
32166
32187
  function resolveGitDir(root) {
32167
- const dotGit = join7(root, ".git");
32188
+ const dotGit = join8(root, ".git");
32168
32189
  try {
32169
32190
  const st = statSync(dotGit);
32170
32191
  if (st.isDirectory()) return dotGit;
32171
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync6(dotGit, "utf8"));
32192
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync7(dotGit, "utf8"));
32172
32193
  if (!m) return null;
32173
32194
  const dir = m[1];
32174
32195
  return isAbsolute2(dir) ? dir : resolve(root, dir);
@@ -32177,22 +32198,22 @@ function resolveGitDir(root) {
32177
32198
  }
32178
32199
  }
32179
32200
  function gitConfigPath(gitDir) {
32180
- const commondirFile = join7(gitDir, "commondir");
32181
- if (existsSync8(commondirFile)) {
32182
- const common = readFileSync6(commondirFile, "utf8").trim();
32201
+ const commondirFile = join8(gitDir, "commondir");
32202
+ if (existsSync9(commondirFile)) {
32203
+ const common = readFileSync7(commondirFile, "utf8").trim();
32183
32204
  const commonDir = isAbsolute2(common) ? common : resolve(gitDir, common);
32184
- return join7(commonDir, "config");
32205
+ return join8(commonDir, "config");
32185
32206
  }
32186
- return join7(gitDir, "config");
32207
+ return join8(gitDir, "config");
32187
32208
  }
32188
32209
  function readRemotes(root) {
32189
32210
  const gitDir = resolveGitDir(root);
32190
32211
  if (!gitDir) return [];
32191
32212
  const cfgPath = gitConfigPath(gitDir);
32192
- if (!existsSync8(cfgPath)) return [];
32213
+ if (!existsSync9(cfgPath)) return [];
32193
32214
  let txt;
32194
32215
  try {
32195
- txt = readFileSync6(cfgPath, "utf8");
32216
+ txt = readFileSync7(cfgPath, "utf8");
32196
32217
  } catch {
32197
32218
  return [];
32198
32219
  }
@@ -32218,9 +32239,9 @@ var init_git_remote = __esm({
32218
32239
  });
32219
32240
 
32220
32241
  // src/profile.ts
32221
- import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
32242
+ import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync8 } from "node:fs";
32222
32243
  import { createHash as createHash5 } from "node:crypto";
32223
- import { join as join8 } from "node:path";
32244
+ import { join as join9 } from "node:path";
32224
32245
  function workspaceId(root) {
32225
32246
  return "wp_" + createHash5("sha256").update(root).digest("hex").slice(0, 12);
32226
32247
  }
@@ -32243,13 +32264,13 @@ function refreshRepoLocator(root, profile) {
32243
32264
  }
32244
32265
  function loadProfile(root) {
32245
32266
  const p = workspacePaths(root);
32246
- if (!existsSync9(p.workspaceJson)) return null;
32247
- return JSON.parse(readFileSync7(p.workspaceJson, "utf8"));
32267
+ if (!existsSync10(p.workspaceJson)) return null;
32268
+ return JSON.parse(readFileSync8(p.workspaceJson, "utf8"));
32248
32269
  }
32249
32270
  function saveProfile(root, profile) {
32250
32271
  const p = workspacePaths(root);
32251
32272
  ensureDir(p.configDir);
32252
- writeFileSync7(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
32273
+ writeFileSync8(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
32253
32274
  }
32254
32275
  function autodetectProfile(root) {
32255
32276
  const id = workspaceId(root);
@@ -32257,13 +32278,13 @@ function autodetectProfile(root) {
32257
32278
  const p = emptyProfile(id, name2);
32258
32279
  const locator = detectRepoLocator(root);
32259
32280
  if (locator) p.repoLocator = locator;
32260
- const pkgPath = join8(root, "package.json");
32261
- if (existsSync9(pkgPath)) {
32281
+ const pkgPath = join9(root, "package.json");
32282
+ if (existsSync10(pkgPath)) {
32262
32283
  try {
32263
- const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
32284
+ const pkg = JSON.parse(readFileSync8(pkgPath, "utf8"));
32264
32285
  const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
32265
32286
  p.languages.push("javascript");
32266
- if (existsSync9(join8(root, "tsconfig.json")) || deps["typescript"]) {
32287
+ if (existsSync10(join9(root, "tsconfig.json")) || deps["typescript"]) {
32267
32288
  p.languages.push("typescript");
32268
32289
  }
32269
32290
  const nodeVer = pkg.engines?.node?.trim();
@@ -32284,10 +32305,10 @@ function autodetectProfile(root) {
32284
32305
  } catch {
32285
32306
  }
32286
32307
  }
32287
- const pyproject = join8(root, "pyproject.toml");
32288
- if (existsSync9(pyproject)) {
32308
+ const pyproject = join9(root, "pyproject.toml");
32309
+ if (existsSync10(pyproject)) {
32289
32310
  try {
32290
- const txt = readFileSync7(pyproject, "utf8");
32311
+ const txt = readFileSync8(pyproject, "utf8");
32291
32312
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
32292
32313
  p.languages.push("python");
32293
32314
  p.stack.push(`python@${py ?? "3"}`);
@@ -32298,16 +32319,16 @@ function autodetectProfile(root) {
32298
32319
  } catch {
32299
32320
  }
32300
32321
  }
32301
- const reqs = join8(root, "requirements.txt");
32302
- if (existsSync9(reqs)) {
32322
+ const reqs = join9(root, "requirements.txt");
32323
+ if (existsSync10(reqs)) {
32303
32324
  if (!p.languages.includes("python")) p.languages.push("python");
32304
32325
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
32305
32326
  }
32306
- if (existsSync9(join8(root, "go.mod"))) {
32327
+ if (existsSync10(join9(root, "go.mod"))) {
32307
32328
  p.languages.push("go");
32308
32329
  p.stack.push("go");
32309
32330
  }
32310
- if (existsSync9(join8(root, "Cargo.toml"))) {
32331
+ if (existsSync10(join9(root, "Cargo.toml"))) {
32311
32332
  p.languages.push("rust");
32312
32333
  p.stack.push("rust");
32313
32334
  }
@@ -32412,12 +32433,12 @@ var init_identity2 = __esm({
32412
32433
  });
32413
32434
 
32414
32435
  // src/checkout-root.ts
32415
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
32416
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join9, resolve as resolve2 } from "node:path";
32436
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "node:fs";
32437
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute3, join as join10, resolve as resolve2 } from "node:path";
32417
32438
  function nearestGitRoot(dir) {
32418
32439
  let cur = resolve2(dir);
32419
32440
  for (; ; ) {
32420
- if (existsSync10(join9(cur, ".git"))) return cur;
32441
+ if (existsSync11(join10(cur, ".git"))) return cur;
32421
32442
  const parent = dirname6(cur);
32422
32443
  if (parent === cur) return null;
32423
32444
  cur = parent;
@@ -32425,19 +32446,19 @@ function nearestGitRoot(dir) {
32425
32446
  }
32426
32447
  function mainCheckoutOfWorktree(root) {
32427
32448
  const gitDir = resolveGitDir(root);
32428
- if (!gitDir || gitDir === join9(root, ".git")) return null;
32429
- const commondirFile = join9(gitDir, "commondir");
32430
- if (!existsSync10(commondirFile)) return null;
32449
+ if (!gitDir || gitDir === join10(root, ".git")) return null;
32450
+ const commondirFile = join10(gitDir, "commondir");
32451
+ if (!existsSync11(commondirFile)) return null;
32431
32452
  let common;
32432
32453
  try {
32433
- common = readFileSync8(commondirFile, "utf8").trim();
32454
+ common = readFileSync9(commondirFile, "utf8").trim();
32434
32455
  } catch {
32435
32456
  return null;
32436
32457
  }
32437
32458
  const commonDir = resolve2(isAbsolute3(common) ? common : resolve2(gitDir, common));
32438
32459
  if (basename2(commonDir) !== ".git") return null;
32439
32460
  const main2 = dirname6(commonDir);
32440
- return existsSync10(join9(main2, ".git")) ? main2 : null;
32461
+ return existsSync11(join10(main2, ".git")) ? main2 : null;
32441
32462
  }
32442
32463
  function checkoutRootOf(cwd) {
32443
32464
  const root = nearestGitRoot(cwd);
@@ -32455,16 +32476,16 @@ var init_checkout_root = __esm({
32455
32476
  });
32456
32477
 
32457
32478
  // src/registry.ts
32458
- import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "node:fs";
32459
- import { join as join10 } from "node:path";
32479
+ import { existsSync as existsSync12, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "node:fs";
32480
+ import { join as join11 } from "node:path";
32460
32481
  function registryPath() {
32461
- return process.env["ERRATA_REGISTRY_PATH"] ?? join10(globalDir(), "workspaces.json");
32482
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join11(globalDir(), "workspaces.json");
32462
32483
  }
32463
32484
  function read() {
32464
32485
  const p = registryPath();
32465
- if (!existsSync11(p)) return { version: 1, workspaces: {} };
32486
+ if (!existsSync12(p)) return { version: 1, workspaces: {} };
32466
32487
  try {
32467
- const parsed = JSON.parse(readFileSync9(p, "utf8"));
32488
+ const parsed = JSON.parse(readFileSync10(p, "utf8"));
32468
32489
  return { version: 1, workspaces: parsed.workspaces ?? {} };
32469
32490
  } catch {
32470
32491
  return { version: 1, workspaces: {} };
@@ -32472,9 +32493,9 @@ function read() {
32472
32493
  }
32473
32494
  function registryCorrupt() {
32474
32495
  const p = registryPath();
32475
- if (!existsSync11(p)) return false;
32496
+ if (!existsSync12(p)) return false;
32476
32497
  try {
32477
- JSON.parse(readFileSync9(p, "utf8"));
32498
+ JSON.parse(readFileSync10(p, "utf8"));
32478
32499
  return false;
32479
32500
  } catch {
32480
32501
  return true;
@@ -32482,7 +32503,7 @@ function registryCorrupt() {
32482
32503
  }
32483
32504
  function write(reg) {
32484
32505
  ensureDir(globalDir());
32485
- writeFileSync8(registryPath(), JSON.stringify(reg, null, 2), "utf8");
32506
+ writeFileSync9(registryPath(), JSON.stringify(reg, null, 2), "utf8");
32486
32507
  }
32487
32508
  function registerWorkspace(profile, root, now = Date.now()) {
32488
32509
  if (isLinkedWorktree(root)) return;
@@ -32527,7 +32548,7 @@ function pruneMissingWorkspaces() {
32527
32548
  const reg = read();
32528
32549
  const removed = [];
32529
32550
  for (const [id, entry] of Object.entries(reg.workspaces)) {
32530
- if (!existsSync11(entry.path)) {
32551
+ if (!existsSync12(entry.path)) {
32531
32552
  removed.push(entry);
32532
32553
  delete reg.workspaces[id];
32533
32554
  }
@@ -32536,13 +32557,13 @@ function pruneMissingWorkspaces() {
32536
32557
  return removed;
32537
32558
  }
32538
32559
  function workspaceStatus(entry) {
32539
- const missing = !existsSync11(entry.path);
32560
+ const missing = !existsSync12(entry.path);
32540
32561
  const lockPath = workspacePaths(entry.path).daemonLock;
32541
32562
  let running = false;
32542
32563
  let webUiUrl = null;
32543
- if (existsSync11(lockPath)) {
32564
+ if (existsSync12(lockPath)) {
32544
32565
  try {
32545
- const lock = JSON.parse(readFileSync9(lockPath, "utf8"));
32566
+ const lock = JSON.parse(readFileSync10(lockPath, "utf8"));
32546
32567
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
32547
32568
  running = true;
32548
32569
  webUiUrl = lock.webUiUrl;
@@ -33867,22 +33888,22 @@ var init_dual_augment = __esm({
33867
33888
 
33868
33889
  // ../../packages/indexer/src/parse-cache.ts
33869
33890
  import { createHash as createHash6 } from "node:crypto";
33870
- import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync10, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync9 } from "node:fs";
33891
+ import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync10 } from "node:fs";
33871
33892
  import { homedir as homedir3 } from "node:os";
33872
- import { join as join11 } from "node:path";
33893
+ import { join as join12 } from "node:path";
33873
33894
  function parseCacheDir() {
33874
- return process.env["ERRATA_PARSE_CACHE"] ?? join11(homedir3(), ".errata", "parse-cache");
33895
+ return process.env["ERRATA_PARSE_CACHE"] ?? join12(homedir3(), ".errata", "parse-cache");
33875
33896
  }
33876
33897
  function parseCacheKey(source, providerId) {
33877
33898
  return createHash6("sha256").update(`${PARSE_CACHE_VERSION}:${providerId}:${source}`).digest("hex");
33878
33899
  }
33879
33900
  function entryPath(dir, key) {
33880
- return join11(dir, key.slice(0, 2), `${key.slice(2)}.json`);
33901
+ return join12(dir, key.slice(0, 2), `${key.slice(2)}.json`);
33881
33902
  }
33882
33903
  function readParseCache(dir, key) {
33883
33904
  const file2 = entryPath(dir, key);
33884
33905
  try {
33885
- const raw2 = readFileSync10(file2, "utf8");
33906
+ const raw2 = readFileSync11(file2, "utf8");
33886
33907
  const parsed = JSON.parse(raw2);
33887
33908
  if (parsed.v !== PARSE_CACHE_VERSION || !Array.isArray(parsed.symbols)) return null;
33888
33909
  return { symbols: parsed.symbols, reExports: parsed.reExports ?? [] };
@@ -33901,8 +33922,8 @@ function writeParseCache(dir, key, providerId, value) {
33901
33922
  const body2 = JSON.stringify(envelope);
33902
33923
  if (body2.length > MAX_ENTRY_BYTES) return;
33903
33924
  const file2 = entryPath(dir, key);
33904
- mkdirSync6(join11(dir, key.slice(0, 2)), { recursive: true });
33905
- writeFileSync9(file2, body2);
33925
+ mkdirSync6(join12(dir, key.slice(0, 2)), { recursive: true });
33926
+ writeFileSync10(file2, body2);
33906
33927
  } catch {
33907
33928
  }
33908
33929
  }
@@ -33911,9 +33932,9 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
33911
33932
  sweptThisProcess = true;
33912
33933
  let removed = 0;
33913
33934
  try {
33914
- if (!existsSync12(dir)) return 0;
33935
+ if (!existsSync13(dir)) return 0;
33915
33936
  for (const bucket of readdirSync2(dir)) {
33916
- const bucketDir = join11(dir, bucket);
33937
+ const bucketDir = join12(dir, bucket);
33917
33938
  let names;
33918
33939
  try {
33919
33940
  names = readdirSync2(bucketDir);
@@ -33921,7 +33942,7 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
33921
33942
  continue;
33922
33943
  }
33923
33944
  for (const name2 of names) {
33924
- const file2 = join11(bucketDir, name2);
33945
+ const file2 = join12(bucketDir, name2);
33925
33946
  try {
33926
33947
  if (now - statSync2(file2).mtimeMs > ENTRY_TTL_MS) {
33927
33948
  rmSync2(file2, { force: true });
@@ -34169,9 +34190,9 @@ var init_identity3 = __esm({
34169
34190
  });
34170
34191
 
34171
34192
  // ../../packages/indexer/src/pipeline.ts
34172
- import { appendFileSync, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
34193
+ import { appendFileSync, readFileSync as readFileSync12, statSync as statSync3 } from "node:fs";
34173
34194
  import { readdir } from "node:fs/promises";
34174
- import { extname, join as join12, relative as relative2, sep } from "node:path";
34195
+ import { extname, join as join13, relative as relative2, sep } from "node:path";
34175
34196
  import { createHash as createHash7 } from "node:crypto";
34176
34197
  import { execFileSync } from "node:child_process";
34177
34198
  function nowTs() {
@@ -34309,7 +34330,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
34309
34330
  for (const rel of [...changedRelPaths]) {
34310
34331
  let h;
34311
34332
  try {
34312
- h = createHash7("sha256").update(readFileSync11(join12(rootPath, rel))).digest("hex");
34333
+ h = createHash7("sha256").update(readFileSync12(join13(rootPath, rel))).digest("hex");
34313
34334
  } catch {
34314
34335
  continue;
34315
34336
  }
@@ -34358,13 +34379,13 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
34358
34379
  let parsedFiles = 0;
34359
34380
  for (const rel of changedRelPaths) {
34360
34381
  if (parsedFiles++ > 0) await new Promise((r2) => setImmediate(r2));
34361
- const abs = join12(rootPath, ...rel.split("/"));
34382
+ const abs = join13(rootPath, ...rel.split("/"));
34362
34383
  const ext = extname(abs).toLowerCase();
34363
34384
  const provider = providers.find((p) => p.fileExtensions.includes(ext));
34364
34385
  if (!provider) continue;
34365
34386
  let symbols;
34366
34387
  try {
34367
- symbols = provider.extractSymbols(readFileSync11(abs, "utf8"), abs);
34388
+ symbols = provider.extractSymbols(readFileSync12(abs, "utf8"), abs);
34368
34389
  } catch {
34369
34390
  continue;
34370
34391
  }
@@ -34684,7 +34705,7 @@ async function runIndexer(store, opts) {
34684
34705
  report.filesSkipped++;
34685
34706
  continue;
34686
34707
  }
34687
- source = readFileSync11(f.absPath, "utf8");
34708
+ source = readFileSync12(f.absPath, "utf8");
34688
34709
  } catch {
34689
34710
  report.filesSkipped++;
34690
34711
  continue;
@@ -34756,7 +34777,7 @@ async function runIndexer(store, opts) {
34756
34777
  const depth = fileNode.relPath.split("/").length;
34757
34778
  if (depth !== 3) continue;
34758
34779
  try {
34759
- const pkg = JSON.parse(readFileSync11(fileNode.absPath, "utf8"));
34780
+ const pkg = JSON.parse(readFileSync12(fileNode.absPath, "utf8"));
34760
34781
  if (!pkg.name) continue;
34761
34782
  const pkgDir = fileNode.relPath.replace(/\/package\.json$/, "");
34762
34783
  const candidates = [
@@ -35144,7 +35165,7 @@ async function scan(root, current, ignores, providers, out2) {
35144
35165
  for (const ent of entries) {
35145
35166
  if (ignores.has(ent.name)) continue;
35146
35167
  if (ent.name.startsWith(".") && ent.name !== ".") continue;
35147
- const abs = join12(current, ent.name);
35168
+ const abs = join13(current, ent.name);
35148
35169
  if (ent.isDirectory()) {
35149
35170
  await scan(root, abs, ignores, providers, out2);
35150
35171
  } else if (ent.isFile()) {
@@ -35203,7 +35224,7 @@ function gitListFiles(root, ignores, providers) {
35203
35224
  if (rels === null) return null;
35204
35225
  const out2 = [];
35205
35226
  for (const rel of rels) {
35206
- const abs = join12(root, rel);
35227
+ const abs = join13(root, rel);
35207
35228
  let size;
35208
35229
  let mtimeMs;
35209
35230
  try {
@@ -35232,7 +35253,7 @@ function upsertFile(store, id, f, workspaceId2, skip) {
35232
35253
  if (existing && fileUnchanged(existing.attrs, f, skip)) return;
35233
35254
  let contentHash;
35234
35255
  try {
35235
- contentHash = createHash7("sha256").update(readFileSync11(f.absPath)).digest("hex");
35256
+ contentHash = createHash7("sha256").update(readFileSync12(f.absPath)).digest("hex");
35236
35257
  } catch {
35237
35258
  }
35238
35259
  const carried = { ...existing?.attrs ?? {} };
@@ -39615,8 +39636,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
39615
39636
 
39616
39637
  // ../../packages/indexer/src/languages/tree-sitter-loader.ts
39617
39638
  import { fileURLToPath } from "node:url";
39618
- import { dirname as dirname7, join as join13 } from "node:path";
39619
- import { existsSync as existsSync13, readdirSync as readdirSync3 } from "node:fs";
39639
+ import { dirname as dirname7, join as join14 } from "node:path";
39640
+ import { existsSync as existsSync14, readdirSync as readdirSync3 } from "node:fs";
39620
39641
  import { createRequire as createRequire2 } from "node:module";
39621
39642
  function entryDir() {
39622
39643
  try {
@@ -39630,27 +39651,27 @@ function entryDir() {
39630
39651
  }
39631
39652
  function findWasmDir() {
39632
39653
  const here = entryDir();
39633
- const seaWasm = join13(here, "resources", "wasm");
39634
- if (existsSync13(join13(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
39654
+ const seaWasm = join14(here, "resources", "wasm");
39655
+ if (existsSync14(join14(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
39635
39656
  let dir = here;
39636
39657
  for (let i2 = 0; i2 < 6; i2++) {
39637
- const flat = join13(
39658
+ const flat = join14(
39638
39659
  dir,
39639
39660
  "node_modules",
39640
39661
  "@vscode",
39641
39662
  "tree-sitter-wasm",
39642
39663
  "wasm"
39643
39664
  );
39644
- if (existsSync13(join13(flat, "tree-sitter-typescript.wasm"))) return flat;
39665
+ if (existsSync14(join14(flat, "tree-sitter-typescript.wasm"))) return flat;
39645
39666
  dir = dirname7(dir);
39646
39667
  }
39647
39668
  let root = here;
39648
39669
  for (let i2 = 0; i2 < 6; i2++) {
39649
- const pnpmDir = join13(root, "node_modules", ".pnpm");
39650
- if (existsSync13(pnpmDir)) {
39670
+ const pnpmDir = join14(root, "node_modules", ".pnpm");
39671
+ if (existsSync14(pnpmDir)) {
39651
39672
  for (const entry of readdirSync3(pnpmDir)) {
39652
39673
  if (entry.startsWith("@vscode+tree-sitter-wasm@")) {
39653
- const candidate = join13(
39674
+ const candidate = join14(
39654
39675
  pnpmDir,
39655
39676
  entry,
39656
39677
  "node_modules",
@@ -39658,7 +39679,7 @@ function findWasmDir() {
39658
39679
  "tree-sitter-wasm",
39659
39680
  "wasm"
39660
39681
  );
39661
- if (existsSync13(join13(candidate, "tree-sitter-typescript.wasm"))) {
39682
+ if (existsSync14(join14(candidate, "tree-sitter-typescript.wasm"))) {
39662
39683
  return candidate;
39663
39684
  }
39664
39685
  }
@@ -39672,27 +39693,27 @@ function findWasmDir() {
39672
39693
  }
39673
39694
  function findRuntimeDir() {
39674
39695
  const here = entryDir();
39675
- const seaRuntime = join13(here, "resources", "wasm");
39676
- if (existsSync13(join13(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
39696
+ const seaRuntime = join14(here, "resources", "wasm");
39697
+ if (existsSync14(join14(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
39677
39698
  let dir = here;
39678
39699
  for (let i2 = 0; i2 < 6; i2++) {
39679
- const flat = join13(dir, "node_modules", "web-tree-sitter");
39680
- if (existsSync13(join13(flat, "web-tree-sitter.wasm"))) return flat;
39700
+ const flat = join14(dir, "node_modules", "web-tree-sitter");
39701
+ if (existsSync14(join14(flat, "web-tree-sitter.wasm"))) return flat;
39681
39702
  dir = dirname7(dir);
39682
39703
  }
39683
39704
  let root = here;
39684
39705
  for (let i2 = 0; i2 < 6; i2++) {
39685
- const pnpmDir = join13(root, "node_modules", ".pnpm");
39686
- if (existsSync13(pnpmDir)) {
39706
+ const pnpmDir = join14(root, "node_modules", ".pnpm");
39707
+ if (existsSync14(pnpmDir)) {
39687
39708
  for (const entry of readdirSync3(pnpmDir)) {
39688
39709
  if (entry.startsWith("web-tree-sitter@")) {
39689
- const candidate = join13(
39710
+ const candidate = join14(
39690
39711
  pnpmDir,
39691
39712
  entry,
39692
39713
  "node_modules",
39693
39714
  "web-tree-sitter"
39694
39715
  );
39695
- if (existsSync13(join13(candidate, "web-tree-sitter.wasm"))) {
39716
+ if (existsSync14(join14(candidate, "web-tree-sitter.wasm"))) {
39696
39717
  return candidate;
39697
39718
  }
39698
39719
  }
@@ -39709,7 +39730,7 @@ async function loadWebTreeSitter() {
39709
39730
  void err2;
39710
39731
  }
39711
39732
  const here = entryDir();
39712
- const seaResourceBase = join13(here, "resources", "_resolve.js");
39733
+ const seaResourceBase = join14(here, "resources", "_resolve.js");
39713
39734
  const resourceRequire = createRequire2(seaResourceBase);
39714
39735
  return resourceRequire("web-tree-sitter");
39715
39736
  }
@@ -39724,9 +39745,9 @@ async function ensureTreeSitterReady() {
39724
39745
  await Parser2.init({
39725
39746
  locateFile: (name2) => {
39726
39747
  if (name2 === "tree-sitter.wasm" || name2 === "web-tree-sitter.wasm") {
39727
- return join13(runtime, name2);
39748
+ return join14(runtime, name2);
39728
39749
  }
39729
- return join13(grammars, name2);
39750
+ return join14(grammars, name2);
39730
39751
  }
39731
39752
  });
39732
39753
  })();
@@ -39738,7 +39759,7 @@ async function loadGrammar(name2) {
39738
39759
  if (cached2) return cached2;
39739
39760
  if (!languageClass) throw new Error("tree-sitter not initialized");
39740
39761
  const grammars = findWasmDir();
39741
- const lang = await languageClass.load(join13(grammars, `${name2}.wasm`));
39762
+ const lang = await languageClass.load(join14(grammars, `${name2}.wasm`));
39742
39763
  grammarCache.set(name2, lang);
39743
39764
  return lang;
39744
39765
  }
@@ -42643,7 +42664,7 @@ var init_src11 = __esm({
42643
42664
  // src/reconcile.ts
42644
42665
  import { execFileSync as execFileSync2 } from "node:child_process";
42645
42666
  import { readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
42646
- import { join as join14, relative as relative3, sep as sep2 } from "node:path";
42667
+ import { join as join15, relative as relative3, sep as sep2 } from "node:path";
42647
42668
  function indexerWouldScan(rel) {
42648
42669
  for (const seg of rel.split(/[\\/]/)) {
42649
42670
  if (seg.length === 0) continue;
@@ -42666,7 +42687,7 @@ function gitSourceFiles(root) {
42666
42687
  const out2 = [];
42667
42688
  for (const rel of stdout.split("\0")) {
42668
42689
  if (!rel || !SOURCE_RE.test(rel) || !indexerWouldScan(rel)) continue;
42669
- const abs = join14(root, rel);
42690
+ const abs = join15(root, rel);
42670
42691
  if (IGNORED.test(abs)) continue;
42671
42692
  out2.push(abs);
42672
42693
  }
@@ -42681,7 +42702,7 @@ function* walkSource(dir) {
42681
42702
  }
42682
42703
  for (const e of entries) {
42683
42704
  const name2 = String(e.name);
42684
- const full = join14(dir, name2);
42705
+ const full = join15(dir, name2);
42685
42706
  if (IGNORED.test(full)) continue;
42686
42707
  if (!indexerWouldScan(name2)) continue;
42687
42708
  if (e.isDirectory()) yield* walkSource(full);
@@ -42831,7 +42852,7 @@ __export(mcp_exports, {
42831
42852
  runTool: () => runTool,
42832
42853
  searchGraph: () => searchGraph
42833
42854
  });
42834
- import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
42855
+ import { existsSync as existsSync15, readFileSync as readFileSync13 } from "node:fs";
42835
42856
  import { resolve as resolve3 } from "node:path";
42836
42857
  function collectEnrichmentPulls(store, opts = {}) {
42837
42858
  const pending = store.findNodesByLabel("Solution").filter((s) => s.attrs["enrichmentPending"] === true).filter((s) => !opts.onlyUnsurfaced || s.attrs["enrichmentSurfaced"] !== true);
@@ -42868,7 +42889,7 @@ function takeEnrichmentNudge(store) {
42868
42889
  ` + items;
42869
42890
  }
42870
42891
  function takeDiscriminatorNudge(path2) {
42871
- if (!path2 || !existsSync14(path2)) return null;
42892
+ if (!path2 || !existsSync15(path2)) return null;
42872
42893
  let shared;
42873
42894
  try {
42874
42895
  shared = openGraphStore({ path: path2 });
@@ -42999,10 +43020,10 @@ function showNode(store, node2, maxLines) {
42999
43020
  if (!relPath) return { found: false, reason: "no file owner for node" };
43000
43021
  const workspaceRoot = process.cwd();
43001
43022
  const absPath = resolve3(workspaceRoot, relPath);
43002
- if (!existsSync14(absPath)) {
43023
+ if (!existsSync15(absPath)) {
43003
43024
  return { found: false, reason: `file not found on disk: ${absPath}` };
43004
43025
  }
43005
- const source = readFileSync12(absPath, "utf8");
43026
+ const source = readFileSync13(absPath, "utf8");
43006
43027
  const attrs = node2.attrs;
43007
43028
  let startByte = attrs["bodyStartByte"] ?? attrs["startByte"];
43008
43029
  let endByte = attrs["bodyEndByte"] ?? attrs["endByte"];
@@ -43759,7 +43780,7 @@ var init_mcp = __esm({
43759
43780
  const local = causalChain(store, { seedId: id, direction: "both", maxHops, limit });
43760
43781
  try {
43761
43782
  const path2 = sharedStorePath();
43762
- if (!existsSync14(path2)) return { found: true, ...local };
43783
+ if (!existsSync15(path2)) return { found: true, ...local };
43763
43784
  const shared = openGraphStore({ path: path2 });
43764
43785
  try {
43765
43786
  if (!shared.getNode(id)) return { found: true, ...local };
@@ -44360,7 +44381,7 @@ var init_mcp = __esm({
44360
44381
  inputSchema: { type: "object", properties: {} },
44361
44382
  handler: () => {
44362
44383
  const path2 = sharedStorePath();
44363
- if (!existsSync14(path2)) return { count: 0, pending: [] };
44384
+ if (!existsSync15(path2)) return { count: 0, pending: [] };
44364
44385
  const shared = openGraphStore({ path: path2 });
44365
44386
  try {
44366
44387
  const pending = pendingAbstractions(shared);
@@ -44388,7 +44409,7 @@ var init_mcp = __esm({
44388
44409
  },
44389
44410
  handler: (args2) => {
44390
44411
  const path2 = sharedStorePath();
44391
- if (!existsSync14(path2)) return { count: 0, pending: [] };
44412
+ if (!existsSync15(path2)) return { count: 0, pending: [] };
44392
44413
  const shared = openGraphStore({ path: path2 });
44393
44414
  try {
44394
44415
  const pending = pendingDiscriminators(shared, {
@@ -44432,7 +44453,7 @@ var init_mcp = __esm({
44432
44453
  },
44433
44454
  handler: (args2) => {
44434
44455
  const path2 = sharedStorePath();
44435
- if (!existsSync14(path2)) return { count: 0, routes: [] };
44456
+ if (!existsSync15(path2)) return { count: 0, routes: [] };
44436
44457
  const shared = openGraphStore({ path: path2 });
44437
44458
  try {
44438
44459
  const result = triageOf(shared, {
@@ -44817,8 +44838,8 @@ __export(vfile_exports, {
44817
44838
  resolvePath: () => resolvePath,
44818
44839
  segmentsOf: () => segmentsOf
44819
44840
  });
44820
- import { writeFileSync as writeFileSync10 } from "node:fs";
44821
- import { join as join15, resolve as resolve4, sep as sep3 } from "node:path";
44841
+ import { writeFileSync as writeFileSync11 } from "node:fs";
44842
+ import { join as join16, resolve as resolve4, sep as sep3 } from "node:path";
44822
44843
  function segmentsOf(rawPath) {
44823
44844
  let p = rawPath.replace(/\\/g, "/");
44824
44845
  p = p.replace(/^.*\.errata\/g\//, "").replace(/^\/?g\//, "").replace(/^\/+/, "");
@@ -44892,14 +44913,14 @@ async function renderVFile(rawPath, store, ctx = {}) {
44892
44913
  }
44893
44914
  async function materializeVFile(rawPath, workspaceRoot, store, ctx = {}) {
44894
44915
  const segs = segmentsOf(rawPath);
44895
- const gRoot = join15(workspaceRoot, ".errata", "g");
44916
+ const gRoot = join16(workspaceRoot, ".errata", "g");
44896
44917
  const abs = resolve4(gRoot, ...segs.length ? segs : ["index"]);
44897
44918
  if (abs !== gRoot && !abs.startsWith(gRoot + sep3)) {
44898
44919
  throw new Error(`refusing to materialize outside .errata/g: ${rawPath}`);
44899
44920
  }
44900
44921
  const text = await renderVFile(rawPath, store, ctx);
44901
44922
  ensureParent(abs);
44902
- writeFileSync10(abs, text, "utf8");
44923
+ writeFileSync11(abs, text, "utf8");
44903
44924
  return abs;
44904
44925
  }
44905
44926
  async function materializeOverview(workspaceRoot, store, ctx = {}) {
@@ -52319,25 +52340,25 @@ var init_tool_index = __esm({
52319
52340
 
52320
52341
  // src/outbox.ts
52321
52342
  import {
52322
- existsSync as existsSync15,
52343
+ existsSync as existsSync16,
52323
52344
  readdirSync as readdirSync5,
52324
- readFileSync as readFileSync13,
52345
+ readFileSync as readFileSync14,
52325
52346
  renameSync,
52326
52347
  unlinkSync,
52327
- writeFileSync as writeFileSync11
52348
+ writeFileSync as writeFileSync12
52328
52349
  } from "node:fs";
52329
- import { join as join16 } from "node:path";
52350
+ import { join as join17 } from "node:path";
52330
52351
  import { createHash as createHash15 } from "node:crypto";
52331
52352
  function enqueueOutbox(paths, payload) {
52332
52353
  ensureDir(paths.outbox);
52333
52354
  const id = createHash15("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
52334
- const file2 = join16(paths.outbox, `${Date.now()}-${id}.json`);
52335
- writeFileSync11(file2, JSON.stringify(payload, null, 2), "utf8");
52355
+ const file2 = join17(paths.outbox, `${Date.now()}-${id}.json`);
52356
+ writeFileSync12(file2, JSON.stringify(payload, null, 2), "utf8");
52336
52357
  return file2;
52337
52358
  }
52338
52359
  async function flushOutbox(paths, client, store) {
52339
52360
  ensureDir(paths.outbox);
52340
- const entries = existsSync15(paths.outbox) ? readdirSync5(paths.outbox) : [];
52361
+ const entries = existsSync16(paths.outbox) ? readdirSync5(paths.outbox) : [];
52341
52362
  let uploaded = 0;
52342
52363
  let failed = 0;
52343
52364
  const quarantine = (abs, reason) => {
@@ -52348,10 +52369,10 @@ async function flushOutbox(paths, client, store) {
52348
52369
  }
52349
52370
  };
52350
52371
  for (const f of entries.filter((e) => e.endsWith(".json")).sort()) {
52351
- const abs = join16(paths.outbox, f);
52372
+ const abs = join17(paths.outbox, f);
52352
52373
  let payload;
52353
52374
  try {
52354
- payload = JSON.parse(readFileSync13(abs, "utf8"));
52375
+ payload = JSON.parse(readFileSync14(abs, "utf8"));
52355
52376
  } catch {
52356
52377
  failed++;
52357
52378
  quarantine(abs, "unparseable JSON");
@@ -52396,7 +52417,7 @@ async function flushOutbox(paths, client, store) {
52396
52417
  }
52397
52418
  }
52398
52419
  }
52399
- const remainingFiles = existsSync15(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
52420
+ const remainingFiles = existsSync16(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
52400
52421
  return { uploaded, failed, remaining: remainingFiles.length };
52401
52422
  }
52402
52423
  var init_outbox = __esm({
@@ -52535,31 +52556,26 @@ function fileRecall(store, relPath) {
52535
52556
  priors.constraints.sort(byRank);
52536
52557
  priors.related.sort(byRank);
52537
52558
  const lines = [];
52538
- for (const p of priors.openProblems.slice(0, 3)) {
52559
+ const shownProblems = priors.openProblems.slice(0, 3);
52560
+ const shownConstraints = priors.constraints.slice(0, 2);
52561
+ const shownRelated = priors.related.slice(0, 4);
52562
+ for (const p of shownProblems) {
52539
52563
  const hasCause = store.outEdges(p.id, ["CAUSED_BY"]).some((e) => store.getNode(e.to)?.label === "RootCause");
52540
52564
  const causeCue = hasCause ? "" : ` \xB7 ${TAG_EXAMPLE.triageMint()} to diagnose its cause`;
52541
52565
  lines.push(
52542
52566
  recallLine(p, `${TAG_EXAMPLE.fix(p.id)} if you resolved it \xB7 ${TAG_EXAMPLE.prior(p.id)} to cite${causeCue}`)
52543
52567
  );
52544
52568
  }
52545
- for (const c of priors.constraints.slice(0, 2)) {
52569
+ for (const c of shownConstraints) {
52546
52570
  lines.push(recallLine(c, `design tension \u2014 hold it, don't "fix" it \xB7 ${TAG_EXAMPLE.prior(c.id)} to cite`));
52547
52571
  }
52548
- for (const n of priors.related.slice(0, 4)) {
52572
+ for (const n of shownRelated) {
52549
52573
  lines.push(recallLine(n, `cite with ${TAG_EXAMPLE.prior(n.id)}`));
52550
52574
  }
52551
52575
  const total = pool.length;
52552
- const headline = `${plural(total, "prior")} on ${relPath.split("/").slice(-2).join("/")}`;
52553
- const chainProblems = [...priors.openProblems, ...priors.resolvedProblems];
52554
- const scoreOf = new Map(ranked.map((r) => [r.id, r.score]));
52555
- const missing = /* @__PURE__ */ new Set();
52556
- for (const p of chainProblems) {
52557
- if (!scoreOf.has(p.id)) missing.add(p.id);
52558
- for (const e of store.outEdges(p.id, ["CAUSED_BY", "SOLVED_BY"])) if (!scoreOf.has(e.to)) missing.add(e.to);
52559
- }
52560
- for (const r of rankByRelevance(store, priors.file.id, [...missing])) scoreOf.set(r.id, r.score);
52561
- const chains = causalChains(store, chainProblems, (id) => scoreOf.get(id) ?? 0);
52562
- const card = signalCard(headline, ranked, chains, scoreOf) ?? { headline, items: [] };
52576
+ const shown = [...shownProblems, ...shownConstraints, ...shownRelated].map(deliveredPrior);
52577
+ const headline = `${plural(shown.length, "prior")} on ${relPath.split("/").slice(-2).join("/")}`;
52578
+ const card = deliveredCard(store, headline, shown) ?? { headline, items: [] };
52563
52579
  return {
52564
52580
  context: `errata \u2014 ${total} prior(s) recorded on this file (act only if relevant):
52565
52581
  ${lines.join("\n")}
@@ -52948,30 +52964,28 @@ function buildWebUi(deps) {
52948
52964
  return c.json({});
52949
52965
  }
52950
52966
  const sid = String(body2["session_id"] ?? "");
52951
- const prompt = typeof body2["prompt"] === "string" ? body2["prompt"] : "";
52952
52967
  const hookEvent = String(body2["hook_event_name"] ?? "UserPromptSubmit");
52953
- if (sid && recallCardEnabled() && (hookEvent === "UserPromptSubmit" || hookEvent === "SessionStart")) {
52954
- const since = Date.now();
52968
+ const atPrompt = hookEvent === "UserPromptSubmit" || hookEvent === "SessionStart";
52969
+ if (sid && recallCardEnabled() && atPrompt) {
52955
52970
  setImmediate(() => {
52956
52971
  try {
52957
52972
  rememberOpenCount(sid, openProblemCount(deps.store));
52958
52973
  } catch {
52959
52974
  }
52960
- if (!prompt.trim()) return;
52961
- promptRecallCard(deps.store, prompt).then((card) => {
52962
- if (card) rememberCard(sid, card, Date.now(), since);
52963
- }).catch(() => {
52964
- });
52965
52975
  });
52966
52976
  }
52967
52977
  const block = readContextFileWithHash(deps.paths.root);
52968
52978
  const decision = decideContextInject({
52969
- event: String(body2["hook_event_name"] ?? "UserPromptSubmit"),
52979
+ event: hookEvent,
52970
52980
  source: String(body2["source"] ?? ""),
52971
- sessionId: String(body2["session_id"] ?? ""),
52981
+ sessionId: sid,
52972
52982
  block,
52973
52983
  lastInjectedHash
52974
52984
  });
52985
+ if (sid && block && recallCardEnabled() && (decision || atPrompt)) {
52986
+ const card = readContextCard(deps.paths.root, block.hash);
52987
+ if (card) rememberCard(sid, card);
52988
+ }
52975
52989
  if (!decision) return c.json({});
52976
52990
  return c.json({
52977
52991
  hookSpecificOutput: {
@@ -72011,27 +72025,27 @@ __export(witness_ledger_exports, {
72011
72025
  summarizeWitnessLedger: () => summarizeWitnessLedger,
72012
72026
  witnessLedgerPath: () => witnessLedgerPath
72013
72027
  });
72014
- import { appendFileSync as appendFileSync3, existsSync as existsSync24, readFileSync as readFileSync26, writeFileSync as writeFileSync19 } from "node:fs";
72015
- import { join as join32 } from "node:path";
72028
+ import { appendFileSync as appendFileSync3, existsSync as existsSync25, readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "node:fs";
72029
+ import { join as join33 } from "node:path";
72016
72030
  function witnessLedgerPath(configDir) {
72017
- return join32(configDir, "witness-ledger.jsonl");
72031
+ return join33(configDir, "witness-ledger.jsonl");
72018
72032
  }
72019
72033
  function appendWitnessLedger(configDir, entry) {
72020
72034
  const path2 = witnessLedgerPath(configDir);
72021
72035
  try {
72022
72036
  appendFileSync3(path2, JSON.stringify(entry) + "\n");
72023
- const lines = readFileSync26(path2, "utf8").split("\n").filter(Boolean);
72037
+ const lines = readFileSync27(path2, "utf8").split("\n").filter(Boolean);
72024
72038
  if (lines.length > LEDGER_MAX_LINES) {
72025
- writeFileSync19(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
72039
+ writeFileSync20(path2, lines.slice(-Math.floor(LEDGER_MAX_LINES / 2)).join("\n") + "\n");
72026
72040
  }
72027
72041
  } catch {
72028
72042
  }
72029
72043
  }
72030
72044
  function readWitnessLedger(configDir) {
72031
72045
  const path2 = witnessLedgerPath(configDir);
72032
- if (!existsSync24(path2)) return [];
72046
+ if (!existsSync25(path2)) return [];
72033
72047
  try {
72034
- return readFileSync26(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
72048
+ return readFileSync27(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter((e) => typeof e.ts === "number" && typeof e.channel === "string");
72035
72049
  } catch {
72036
72050
  return [];
72037
72051
  }
@@ -72470,12 +72484,12 @@ var init_report_render = __esm({
72470
72484
 
72471
72485
  // src/cli.ts
72472
72486
  init_src6();
72473
- import { closeSync as closeSync2, existsSync as existsSync35, openSync as openSync2, readFileSync as readFileSync36, renameSync as renameSync4, statSync as statSync10 } from "node:fs";
72474
- import { join as join43, resolve as pathResolve2 } from "node:path";
72487
+ import { closeSync as closeSync2, existsSync as existsSync36, openSync as openSync2, readFileSync as readFileSync37, renameSync as renameSync4, statSync as statSync10 } from "node:fs";
72488
+ import { join as join44, resolve as pathResolve2 } from "node:path";
72475
72489
  import { spawn as spawn5 } from "node:child_process";
72476
72490
 
72477
72491
  // src/daemon.ts
72478
- import { existsSync as existsSync26, writeFileSync as writeFileSync22 } from "node:fs";
72492
+ import { existsSync as existsSync27, writeFileSync as writeFileSync23 } from "node:fs";
72479
72493
 
72480
72494
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
72481
72495
  import { createServer as createServerHTTP } from "http";
@@ -73055,13 +73069,13 @@ init_config();
73055
73069
 
73056
73070
  // src/engine.ts
73057
73071
  import { execFileSync as execFileSync4 } from "node:child_process";
73058
- import { existsSync as existsSync25, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "node:fs";
73059
- import { basename as basename7, join as join34, relative as relative6, sep as sep4 } from "node:path";
73072
+ import { existsSync as existsSync26, statSync as statSync8, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync29, writeFileSync as writeFileSync22 } from "node:fs";
73073
+ import { basename as basename7, join as join35, relative as relative6, sep as sep4 } from "node:path";
73060
73074
 
73061
73075
  // src/source-watcher.ts
73062
73076
  import { EventEmitter as EventEmitter2 } from "node:events";
73063
73077
  import { statSync as statSync5, watch as watch2 } from "node:fs";
73064
- import { join as join19 } from "node:path";
73078
+ import { join as join20 } from "node:path";
73065
73079
 
73066
73080
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
73067
73081
  import { stat as statcb } from "fs";
@@ -74794,7 +74808,7 @@ var NativeSourceWatcher = class extends EventEmitter2 {
74794
74808
  }
74795
74809
  try {
74796
74810
  const h = watch2(target, { recursive: isDir, persistent: true }, (event, name2) => {
74797
- const path2 = isDir ? name2 ? join19(target, name2.toString()) : null : target;
74811
+ const path2 = isDir ? name2 ? join20(target, name2.toString()) : null : target;
74798
74812
  if (!path2) return;
74799
74813
  this.emit("raw", event, path2, { watchedPath: target });
74800
74814
  if (!this.ignored(path2)) this.schedule(path2, event === "rename");
@@ -75094,13 +75108,14 @@ async function chat(req) {
75094
75108
  // src/engine.ts
75095
75109
  init_src11();
75096
75110
  init_src6();
75111
+ init_recall_signal();
75097
75112
  init_src8();
75098
75113
  init_review2();
75099
75114
 
75100
75115
  // src/turn.ts
75101
75116
  init_checkout_root();
75102
- import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
75103
- import { basename as basename5, delimiter, dirname as dirname10, join as join20, normalize as normalize3 } from "node:path";
75117
+ import { closeSync, existsSync as existsSync17, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync6 } from "node:fs";
75118
+ import { basename as basename5, delimiter, dirname as dirname10, join as join21, normalize as normalize3 } from "node:path";
75104
75119
  import { homedir as homedir4 } from "node:os";
75105
75120
  import { createHash as createHash16 } from "node:crypto";
75106
75121
  function completeJsonlPrefix(buf) {
@@ -75488,11 +75503,11 @@ function turnsSince(turns, mark) {
75488
75503
  return at >= 0 ? turns.slice(at + 1) : turns;
75489
75504
  }
75490
75505
  function claudeProjectDir(cwd, home = homedir4()) {
75491
- return join20(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
75506
+ return join21(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
75492
75507
  }
75493
75508
  function recentTranscripts(cwd, opts = {}) {
75494
75509
  const dir = claudeProjectDir(cwd, opts.home ?? homedir4());
75495
- if (!existsSync16(dir)) return [];
75510
+ if (!existsSync17(dir)) return [];
75496
75511
  let names;
75497
75512
  try {
75498
75513
  names = readdirSync6(dir);
@@ -75503,7 +75518,7 @@ function recentTranscripts(cwd, opts = {}) {
75503
75518
  const refs = [];
75504
75519
  for (const name2 of names) {
75505
75520
  if (!name2.endsWith(".jsonl")) continue;
75506
- const path2 = join20(dir, name2);
75521
+ const path2 = join21(dir, name2);
75507
75522
  let mtimeMs;
75508
75523
  try {
75509
75524
  mtimeMs = statSync6(path2).mtimeMs;
@@ -75518,8 +75533,8 @@ function recentTranscripts(cwd, opts = {}) {
75518
75533
  }
75519
75534
  function subagentTranscripts(mainTranscriptPath, sessionId) {
75520
75535
  if (!mainTranscriptPath || !sessionId) return [];
75521
- const dir = join20(dirname10(mainTranscriptPath), sessionId, "subagents");
75522
- if (!existsSync16(dir)) return [];
75536
+ const dir = join21(dirname10(mainTranscriptPath), sessionId, "subagents");
75537
+ if (!existsSync17(dir)) return [];
75523
75538
  let names;
75524
75539
  try {
75525
75540
  names = readdirSync6(dir);
@@ -75529,7 +75544,7 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
75529
75544
  const refs = [];
75530
75545
  for (const name2 of names) {
75531
75546
  if (!name2.endsWith(".jsonl")) continue;
75532
- const path2 = join20(dir, name2);
75547
+ const path2 = join21(dir, name2);
75533
75548
  let mtimeMs;
75534
75549
  try {
75535
75550
  mtimeMs = statSync6(path2).mtimeMs;
@@ -75548,8 +75563,8 @@ function splitPathList(value, sep5 = delimiter) {
75548
75563
  function codexSessionRoots(env2 = process.env, home = homedir4()) {
75549
75564
  const roots = /* @__PURE__ */ new Set();
75550
75565
  for (const d of splitPathList(env2["ERRATA_CODEX_SESSIONS_DIRS"])) roots.add(d);
75551
- if (env2["CODEX_HOME"]) roots.add(join20(env2["CODEX_HOME"], "sessions"));
75552
- roots.add(join20(home, ".codex", "sessions"));
75566
+ if (env2["CODEX_HOME"]) roots.add(join21(env2["CODEX_HOME"], "sessions"));
75567
+ roots.add(join21(home, ".codex", "sessions"));
75553
75568
  return [...roots];
75554
75569
  }
75555
75570
  function readCodexRolloutIdentity(path2) {
@@ -75603,7 +75618,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
75603
75618
  const owner = checkoutRootOf(cwd);
75604
75619
  const owners = /* @__PURE__ */ new Map();
75605
75620
  for (const root of codexSessionRoots(opts.env, opts.home)) {
75606
- if (!existsSync16(root)) {
75621
+ if (!existsSync17(root)) {
75607
75622
  codexRolloutActivity.delete(root);
75608
75623
  continue;
75609
75624
  }
@@ -75621,7 +75636,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
75621
75636
  continue;
75622
75637
  }
75623
75638
  for (const name2 of names) {
75624
- const full = join20(dir, name2);
75639
+ const full = join21(dir, name2);
75625
75640
  let st;
75626
75641
  try {
75627
75642
  st = statSync6(full);
@@ -75663,8 +75678,8 @@ function codexRolloutsForCwd(cwd, opts = {}) {
75663
75678
  function geminiSessionRoots(env2 = process.env, home = homedir4()) {
75664
75679
  const roots = /* @__PURE__ */ new Set();
75665
75680
  for (const d of splitPathList(env2["ERRATA_GEMINI_SESSIONS_DIRS"])) roots.add(d);
75666
- if (env2["GEMINI_CLI_HOME"]) roots.add(join20(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
75667
- roots.add(join20(home, ".gemini", "tmp"));
75681
+ if (env2["GEMINI_CLI_HOME"]) roots.add(join21(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
75682
+ roots.add(join21(home, ".gemini", "tmp"));
75668
75683
  return [...roots];
75669
75684
  }
75670
75685
  function geminiProjectHash(cwd) {
@@ -75704,7 +75719,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
75704
75719
  const hashes = geminiHashesFor(cwd);
75705
75720
  const out2 = [];
75706
75721
  for (const root of geminiSessionRoots(opts.env, opts.home)) {
75707
- if (!existsSync16(root)) continue;
75722
+ if (!existsSync17(root)) continue;
75708
75723
  let slugs;
75709
75724
  try {
75710
75725
  slugs = readdirSync6(root);
@@ -75712,7 +75727,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
75712
75727
  continue;
75713
75728
  }
75714
75729
  for (const slug2 of slugs) {
75715
- const chats = join20(root, slug2, "chats");
75730
+ const chats = join21(root, slug2, "chats");
75716
75731
  let names;
75717
75732
  try {
75718
75733
  names = readdirSync6(chats);
@@ -75721,7 +75736,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
75721
75736
  }
75722
75737
  for (const name2 of names) {
75723
75738
  if (!name2.startsWith("session-") || !name2.endsWith(".jsonl")) continue;
75724
- const full = join20(chats, name2);
75739
+ const full = join21(chats, name2);
75725
75740
  let st;
75726
75741
  try {
75727
75742
  st = statSync6(full);
@@ -75741,8 +75756,8 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
75741
75756
  function opencodeSessionRoots(env2 = process.env, home = homedir4()) {
75742
75757
  const roots = /* @__PURE__ */ new Set();
75743
75758
  for (const d of splitPathList(env2["ERRATA_OPENCODE_SESSIONS_DIRS"])) roots.add(d);
75744
- if (env2["XDG_DATA_HOME"]) roots.add(join20(env2["XDG_DATA_HOME"], "opencode", "errata"));
75745
- roots.add(join20(home, ".local", "share", "opencode", "errata"));
75759
+ if (env2["XDG_DATA_HOME"]) roots.add(join21(env2["XDG_DATA_HOME"], "opencode", "errata"));
75760
+ roots.add(join21(home, ".local", "share", "opencode", "errata"));
75746
75761
  return [...roots];
75747
75762
  }
75748
75763
  function readOpencodeTranscriptDirectory(path2) {
@@ -75775,7 +75790,7 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
75775
75790
  }
75776
75791
  const out2 = [];
75777
75792
  for (const root of opencodeSessionRoots(opts.env, opts.home)) {
75778
- if (!existsSync16(root)) continue;
75793
+ if (!existsSync17(root)) continue;
75779
75794
  let names;
75780
75795
  try {
75781
75796
  names = readdirSync6(root);
@@ -75784,7 +75799,7 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
75784
75799
  }
75785
75800
  for (const name2 of names) {
75786
75801
  if (!name2.endsWith(".jsonl")) continue;
75787
- const full = join20(root, name2);
75802
+ const full = join21(root, name2);
75788
75803
  let st;
75789
75804
  try {
75790
75805
  st = statSync6(full);
@@ -75807,7 +75822,7 @@ init_src2();
75807
75822
  init_agent_signals();
75808
75823
  init_tool_index();
75809
75824
  init_src5();
75810
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "node:fs";
75825
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "node:fs";
75811
75826
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
75812
75827
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
75813
75828
  var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
@@ -76496,13 +76511,13 @@ function writePrimingHandles(path2, nodes, now = Date.now()) {
76496
76511
  entries.sort((a, b) => (b[1].seenAt ?? 0) - (a[1].seenAt ?? 0));
76497
76512
  entries.length = HANDLE_MAP_MAX;
76498
76513
  }
76499
- writeFileSync12(path2, JSON.stringify(Object.fromEntries(entries)));
76514
+ writeFileSync13(path2, JSON.stringify(Object.fromEntries(entries)));
76500
76515
  } catch {
76501
76516
  }
76502
76517
  }
76503
76518
  function readPrimingHandles(path2) {
76504
76519
  try {
76505
- return JSON.parse(readFileSync14(path2, "utf8"));
76520
+ return JSON.parse(readFileSync15(path2, "utf8"));
76506
76521
  } catch {
76507
76522
  return {};
76508
76523
  }
@@ -76977,8 +76992,8 @@ ${conversation}` }]
76977
76992
  // src/constraint-backfill.ts
76978
76993
  init_src5();
76979
76994
  init_src2();
76980
- import { existsSync as existsSync17, readFileSync as readFileSync15, readdirSync as readdirSync7, writeFileSync as writeFileSync13 } from "node:fs";
76981
- import { join as join21 } from "node:path";
76995
+ import { existsSync as existsSync18, readFileSync as readFileSync16, readdirSync as readdirSync7, writeFileSync as writeFileSync14 } from "node:fs";
76996
+ import { join as join22 } from "node:path";
76982
76997
  import { homedir as homedir5 } from "node:os";
76983
76998
  var BACKFILL_VERSION = 1;
76984
76999
  var EMPTY = {
@@ -76992,13 +77007,13 @@ var EMPTY = {
76992
77007
  recoverable: 0
76993
77008
  };
76994
77009
  function markerPath(configDir) {
76995
- return join21(configDir, "constraint-backfill.json");
77010
+ return join22(configDir, "constraint-backfill.json");
76996
77011
  }
76997
77012
  function alreadyDone(configDir) {
76998
77013
  const p = markerPath(configDir);
76999
- if (!existsSync17(p)) return false;
77014
+ if (!existsSync18(p)) return false;
77000
77015
  try {
77001
- const raw2 = JSON.parse(readFileSync15(p, "utf8"));
77016
+ const raw2 = JSON.parse(readFileSync16(p, "utf8"));
77002
77017
  return raw2?.version === BACKFILL_VERSION;
77003
77018
  } catch {
77004
77019
  return false;
@@ -77008,7 +77023,7 @@ function replay(root) {
77008
77023
  const statements = /* @__PURE__ */ new Set();
77009
77024
  const citedByFix = /* @__PURE__ */ new Set();
77010
77025
  const dir = claudeProjectDir(root, homedir5());
77011
- if (!existsSync17(dir)) return { statements, citedByFix };
77026
+ if (!existsSync18(dir)) return { statements, citedByFix };
77012
77027
  let names;
77013
77028
  try {
77014
77029
  names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
@@ -77018,7 +77033,7 @@ function replay(root) {
77018
77033
  for (const f of names) {
77019
77034
  let lines;
77020
77035
  try {
77021
- lines = readFileSync15(join21(dir, f), "utf8").split("\n");
77036
+ lines = readFileSync16(join22(dir, f), "utf8").split("\n");
77022
77037
  } catch {
77023
77038
  continue;
77024
77039
  }
@@ -77132,7 +77147,7 @@ function backfillConstraintKind(store, opts) {
77132
77147
  }
77133
77148
  });
77134
77149
  try {
77135
- writeFileSync13(
77150
+ writeFileSync14(
77136
77151
  markerPath(opts.configDir),
77137
77152
  JSON.stringify({ version: BACKFILL_VERSION, at: opts.now, ...report, cloudTwins: report.cloudTwins.length }, null, 2),
77138
77153
  "utf8"
@@ -77145,8 +77160,8 @@ function backfillConstraintKind(store, opts) {
77145
77160
  // src/edge-repair.ts
77146
77161
  init_src();
77147
77162
  init_src5();
77148
- import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
77149
- import { join as join22 } from "node:path";
77163
+ import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
77164
+ import { join as join23 } from "node:path";
77150
77165
  function citeEdgeId(from, type, to) {
77151
77166
  return `edge_${digest({ from, type, to })}`.slice(0, 24);
77152
77167
  }
@@ -77161,13 +77176,13 @@ var EMPTY2 = {
77161
77176
  byType: {}
77162
77177
  };
77163
77178
  function markerPath2(configDir) {
77164
- return join22(configDir, "edge-repair.json");
77179
+ return join23(configDir, "edge-repair.json");
77165
77180
  }
77166
77181
  function alreadyDone2(configDir) {
77167
77182
  const p = markerPath2(configDir);
77168
- if (!existsSync18(p)) return false;
77183
+ if (!existsSync19(p)) return false;
77169
77184
  try {
77170
- return JSON.parse(readFileSync16(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
77185
+ return JSON.parse(readFileSync17(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
77171
77186
  } catch {
77172
77187
  return false;
77173
77188
  }
@@ -77216,7 +77231,7 @@ function repairInvalidEdges(store, opts) {
77216
77231
  });
77217
77232
  store.pruneEdgeRejections(opts.now - REJECTION_RETENTION_MS);
77218
77233
  try {
77219
- writeFileSync14(
77234
+ writeFileSync15(
77220
77235
  markerPath2(opts.configDir),
77221
77236
  JSON.stringify({ version: EDGE_REPAIR_VERSION, at: opts.now, ...report }, null, 2),
77222
77237
  "utf8"
@@ -77230,8 +77245,8 @@ function repairInvalidEdges(store, opts) {
77230
77245
  init_reconcile();
77231
77246
 
77232
77247
  // src/pass-ledger.ts
77233
- import { appendFileSync as appendFileSync2, existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
77234
- import { join as join23 } from "node:path";
77248
+ import { appendFileSync as appendFileSync2, existsSync as existsSync20, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "node:fs";
77249
+ import { join as join24 } from "node:path";
77235
77250
 
77236
77251
  // src/isolate-census.ts
77237
77252
  var live2 = 0;
@@ -77254,7 +77269,7 @@ var PER_KIND_MAX = 100;
77254
77269
  var TRIM_EVERY = 50;
77255
77270
  var appendsSinceTrim = /* @__PURE__ */ new Map();
77256
77271
  function passLedgerPath(configDir) {
77257
- return join23(configDir, "pass-ledger.jsonl");
77272
+ return join24(configDir, "pass-ledger.jsonl");
77258
77273
  }
77259
77274
  function appendPassLedger(configDir, kind, durationMs, counts) {
77260
77275
  const path2 = passLedgerPath(configDir);
@@ -77283,7 +77298,7 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
77283
77298
  return;
77284
77299
  }
77285
77300
  appendsSinceTrim.set(path2, 0);
77286
- const lines = readFileSync17(path2, "utf8").split("\n").filter(Boolean);
77301
+ const lines = readFileSync18(path2, "utf8").split("\n").filter(Boolean);
77287
77302
  const keptByKind = /* @__PURE__ */ new Map();
77288
77303
  const kept = [];
77289
77304
  for (let i2 = lines.length - 1; i2 >= 0; i2--) {
@@ -77299,16 +77314,16 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
77299
77314
  kept.push(lines[i2]);
77300
77315
  }
77301
77316
  if (kept.length < lines.length) {
77302
- writeFileSync15(path2, kept.reverse().join("\n") + "\n");
77317
+ writeFileSync16(path2, kept.reverse().join("\n") + "\n");
77303
77318
  }
77304
77319
  } catch {
77305
77320
  }
77306
77321
  }
77307
77322
  function readPassLedger(configDir) {
77308
77323
  const path2 = passLedgerPath(configDir);
77309
- if (!existsSync19(path2)) return [];
77324
+ if (!existsSync20(path2)) return [];
77310
77325
  try {
77311
- return readFileSync17(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
77326
+ return readFileSync18(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
77312
77327
  (e) => typeof e?.ts === "number" && typeof e?.kind === "string" && typeof e?.durationMs === "number"
77313
77328
  ).map((e) => ({ ...e, counts: e.counts ?? {} }));
77314
77329
  } catch {
@@ -77680,11 +77695,11 @@ init_outbox();
77680
77695
  init_src10();
77681
77696
  init_src();
77682
77697
  init_src2();
77683
- import { readFileSync as readFileSync18 } from "node:fs";
77684
- import { join as join24 } from "node:path";
77698
+ import { readFileSync as readFileSync19 } from "node:fs";
77699
+ import { join as join25 } from "node:path";
77685
77700
  function loadClaimIgnorePatterns(workspaceRoot) {
77686
77701
  try {
77687
- return readFileSync18(join24(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
77702
+ return readFileSync19(join25(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
77688
77703
  } catch {
77689
77704
  return [];
77690
77705
  }
@@ -78062,9 +78077,9 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
78062
78077
  // src/retrieval-stack.ts
78063
78078
  init_src();
78064
78079
  import { execFileSync as execFileSync3 } from "node:child_process";
78065
- import { existsSync as existsSync20, readFileSync as readFileSync19, statSync as statSync7 } from "node:fs";
78080
+ import { existsSync as existsSync21, readFileSync as readFileSync20, statSync as statSync7 } from "node:fs";
78066
78081
  import { homedir as homedir6 } from "node:os";
78067
- import { join as join25 } from "node:path";
78082
+ import { join as join26 } from "node:path";
78068
78083
  var RETRIEVAL_STACK_CAP = 24;
78069
78084
  var MANIFEST_SCAN_CAP = 400;
78070
78085
  var RUNTIME_TOKENS = /* @__PURE__ */ new Set([
@@ -78354,51 +78369,51 @@ function mavenGroupIsSelfDisclosing(name2, selfTokens) {
78354
78369
  function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
78355
78370
  const read2 = (p) => {
78356
78371
  try {
78357
- return readFileSync19(p, "utf8");
78372
+ return readFileSync20(p, "utf8");
78358
78373
  } catch {
78359
78374
  return null;
78360
78375
  }
78361
78376
  };
78362
78377
  const texts = (...paths) => paths.map(read2).filter((t) => t !== null);
78363
78378
  const home = homedir6();
78364
- const npm = parseNpmrcPolicy(texts(join25(root, ".npmrc"), join25(home, ".npmrc")));
78379
+ const npm = parseNpmrcPolicy(texts(join26(root, ".npmrc"), join26(home, ".npmrc")));
78365
78380
  const blocked = /* @__PURE__ */ new Set();
78366
78381
  if (!npm.defaultPublic) blocked.add("npm");
78367
78382
  if (pypiIndexIsPrivate(
78368
78383
  texts(
78369
- join25(root, "pip.conf"),
78370
- join25(root, "pip.ini"),
78371
- join25(root, "pyproject.toml"),
78372
- join25(root, "requirements.txt"),
78373
- join25(home, ".pip", "pip.conf"),
78374
- join25(home, ".config", "pip", "pip.conf"),
78375
- join25(env2["APPDATA"] ?? home, "pip", "pip.ini")
78384
+ join26(root, "pip.conf"),
78385
+ join26(root, "pip.ini"),
78386
+ join26(root, "pyproject.toml"),
78387
+ join26(root, "requirements.txt"),
78388
+ join26(home, ".pip", "pip.conf"),
78389
+ join26(home, ".config", "pip", "pip.conf"),
78390
+ join26(env2["APPDATA"] ?? home, "pip", "pip.ini")
78376
78391
  )
78377
78392
  )) {
78378
78393
  blocked.add("pypi");
78379
78394
  }
78380
78395
  if (cargoRegistryIsPrivate(
78381
78396
  texts(
78382
- join25(root, ".cargo", "config.toml"),
78383
- join25(root, ".cargo", "config"),
78384
- join25(home, ".cargo", "config.toml"),
78385
- join25(home, ".cargo", "config")
78397
+ join26(root, ".cargo", "config.toml"),
78398
+ join26(root, ".cargo", "config"),
78399
+ join26(home, ".cargo", "config.toml"),
78400
+ join26(home, ".cargo", "config")
78386
78401
  )
78387
78402
  )) {
78388
78403
  blocked.add("cargo");
78389
78404
  }
78390
78405
  if (nugetSourcesArePrivate(
78391
78406
  texts(
78392
- join25(root, "NuGet.config"),
78393
- join25(root, "nuget.config"),
78394
- join25(root, "NuGet.Config"),
78395
- join25(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
78396
- join25(home, ".nuget", "NuGet", "NuGet.Config")
78407
+ join26(root, "NuGet.config"),
78408
+ join26(root, "nuget.config"),
78409
+ join26(root, "NuGet.Config"),
78410
+ join26(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
78411
+ join26(home, ".nuget", "NuGet", "NuGet.Config")
78397
78412
  )
78398
78413
  )) {
78399
78414
  blocked.add("nuget");
78400
78415
  }
78401
- const goEnvFile = env2["GOENV"] ?? join25(env2["APPDATA"] ?? join25(home, ".config"), "go", "env");
78416
+ const goEnvFile = env2["GOENV"] ?? join26(env2["APPDATA"] ?? join26(home, ".config"), "go", "env");
78402
78417
  const goEnvText = read2(goEnvFile) ?? "";
78403
78418
  const fromFile = ["GOPRIVATE", "GONOSUMDB", "GONOSUMCHECK"].map(
78404
78419
  (k) => new RegExp(`^${k}=(.*)$`, "m").exec(goEnvText)?.[1]
@@ -78409,10 +78424,10 @@ function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
78409
78424
  env2["GONOSUMCHECK"],
78410
78425
  ...fromFile
78411
78426
  ]);
78412
- const gemfiles = texts(join25(root, "Gemfile"));
78427
+ const gemfiles = texts(join26(root, "Gemfile"));
78413
78428
  if (gemSourceIsPrivate(gemfiles)) blocked.add("gem");
78414
78429
  if (mavenReposArePrivate(
78415
- texts(join25(root, "pom.xml"), join25(home, ".m2", "settings.xml"))
78430
+ texts(join26(root, "pom.xml"), join26(home, ".m2", "settings.xml"))
78416
78431
  )) {
78417
78432
  blocked.add("maven");
78418
78433
  }
@@ -78579,8 +78594,8 @@ function readDirectDependencies(root) {
78579
78594
  const familiesSeen = /* @__PURE__ */ new Set();
78580
78595
  for (const c of LOCKFILES) {
78581
78596
  if (familiesSeen.has(c.family)) continue;
78582
- const p = join25(root, c.file);
78583
- if (!existsSync20(p)) continue;
78597
+ const p = join26(root, c.file);
78598
+ if (!existsSync21(p)) continue;
78584
78599
  try {
78585
78600
  const s = statSync7(p);
78586
78601
  stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
@@ -78600,7 +78615,7 @@ function readDirectDependencies(root) {
78600
78615
  const direct = [];
78601
78616
  for (const { c, path: path2 } of found) {
78602
78617
  try {
78603
- direct.push(...c.parse(readFileSync19(path2, "utf8")).direct ?? []);
78618
+ direct.push(...c.parse(readFileSync20(path2, "utf8")).direct ?? []);
78604
78619
  } catch {
78605
78620
  }
78606
78621
  }
@@ -78643,14 +78658,14 @@ function manifestPaths(root) {
78643
78658
  "project.godot"
78644
78659
  ];
78645
78660
  return {
78646
- paths: ROOT_MANIFESTS.filter((f) => existsSync20(join25(root, f))),
78661
+ paths: ROOT_MANIFESTS.filter((f) => existsSync21(join26(root, f))),
78647
78662
  tracked: false,
78648
78663
  truncated: false
78649
78664
  };
78650
78665
  }
78651
78666
  var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
78652
78667
  function rootDeclaresWorkspace(root, texts) {
78653
- if (WORKSPACE_MARKERS.some((f) => existsSync20(join25(root, f)))) return true;
78668
+ if (WORKSPACE_MARKERS.some((f) => existsSync21(join26(root, f)))) return true;
78654
78669
  return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
78655
78670
  }
78656
78671
  var EMPTY_SCAN = { deps: [], self: [], complete: true };
@@ -78664,11 +78679,11 @@ function scanManifests(root) {
78664
78679
  const texts = /* @__PURE__ */ new Map();
78665
78680
  const stamps = [];
78666
78681
  for (const rel of paths) {
78667
- const abs = join25(root, rel);
78682
+ const abs = join26(root, rel);
78668
78683
  try {
78669
78684
  const s = statSync7(abs);
78670
78685
  stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
78671
- texts.set(rel, readFileSync19(abs, "utf8"));
78686
+ texts.set(rel, readFileSync20(abs, "utf8"));
78672
78687
  } catch {
78673
78688
  }
78674
78689
  }
@@ -78697,22 +78712,22 @@ function readManifestDependencies(root) {
78697
78712
  }
78698
78713
 
78699
78714
  // src/git-sensor.ts
78700
- import { existsSync as existsSync21, readFileSync as readFileSync20, watch as fsWatch } from "node:fs";
78701
- import { join as join26 } from "node:path";
78715
+ import { existsSync as existsSync22, readFileSync as readFileSync21, watch as fsWatch } from "node:fs";
78716
+ import { join as join27 } from "node:path";
78702
78717
  function readFirstLine(path2) {
78703
78718
  try {
78704
- return readFileSync20(path2, "utf8").split(/\r?\n/, 1)[0].trim();
78719
+ return readFileSync21(path2, "utf8").split(/\r?\n/, 1)[0].trim();
78705
78720
  } catch {
78706
78721
  return null;
78707
78722
  }
78708
78723
  }
78709
78724
  function readGitRefState(gitDir) {
78710
- const head2 = readFirstLine(join26(gitDir, "HEAD"));
78725
+ const head2 = readFirstLine(join27(gitDir, "HEAD"));
78711
78726
  const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
78712
78727
  const branch = m ? m[1] : null;
78713
78728
  let sha2 = null;
78714
78729
  if (branch) {
78715
- sha2 = readFirstLine(join26(gitDir, "refs", "heads", branch));
78730
+ sha2 = readFirstLine(join27(gitDir, "refs", "heads", branch));
78716
78731
  if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
78717
78732
  } else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
78718
78733
  sha2 = head2;
@@ -78720,13 +78735,13 @@ function readGitRefState(gitDir) {
78720
78735
  return {
78721
78736
  branch,
78722
78737
  sha: sha2,
78723
- mergeHeadExists: existsSync21(join26(gitDir, "MERGE_HEAD")),
78724
- origHeadExists: existsSync21(join26(gitDir, "ORIG_HEAD"))
78738
+ mergeHeadExists: existsSync22(join27(gitDir, "MERGE_HEAD")),
78739
+ origHeadExists: existsSync22(join27(gitDir, "ORIG_HEAD"))
78725
78740
  };
78726
78741
  }
78727
78742
  function shaFromPackedRefs(gitDir, ref) {
78728
78743
  try {
78729
- for (const line of readFileSync20(join26(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
78744
+ for (const line of readFileSync21(join27(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
78730
78745
  const [sha2, name2] = line.split(/\s+/);
78731
78746
  if (name2 === ref && sha2) return sha2;
78732
78747
  }
@@ -78760,7 +78775,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
78760
78775
  const settle = () => {
78761
78776
  if (timer) clearTimeout(timer);
78762
78777
  timer = setTimeout(() => {
78763
- if (existsSync21(join26(gitDir, "index.lock"))) {
78778
+ if (existsSync22(join27(gitDir, "index.lock"))) {
78764
78779
  settle();
78765
78780
  return;
78766
78781
  }
@@ -78771,7 +78786,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
78771
78786
  }, debounceMs);
78772
78787
  };
78773
78788
  for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
78774
- const p = join26(gitDir, sub);
78789
+ const p = join27(gitDir, sub);
78775
78790
  try {
78776
78791
  watchers.push(fsWatch(p, settle));
78777
78792
  } catch {
@@ -78995,8 +79010,8 @@ var TelemetryRecorder = class {
78995
79010
  };
78996
79011
 
78997
79012
  // src/file-activity.ts
78998
- import { readFileSync as readFileSync22 } from "node:fs";
78999
- import { join as join28 } from "node:path";
79013
+ import { readFileSync as readFileSync23 } from "node:fs";
79014
+ import { join as join29 } from "node:path";
79000
79015
  import { createHash as createHash17 } from "node:crypto";
79001
79016
 
79002
79017
  // ../../packages/privacy/src/patterns/credentials.ts
@@ -79748,8 +79763,8 @@ init_git_remote();
79748
79763
  // src/history-bundle.ts
79749
79764
  init_src();
79750
79765
  import { execFile as execFile2 } from "node:child_process";
79751
- import { readFileSync as readFileSync21 } from "node:fs";
79752
- import { join as join27 } from "node:path";
79766
+ import { readFileSync as readFileSync22 } from "node:fs";
79767
+ import { join as join28 } from "node:path";
79753
79768
  var DEFAULT_MAX_TOKENS = 6e3;
79754
79769
  var FILE_LIST_CAP = 60;
79755
79770
  var DIFF_FILE_CAP = 40;
@@ -79784,7 +79799,7 @@ function pathAllowedByFloor(path2) {
79784
79799
  function loadRepoIgnore(root, extraPatterns = []) {
79785
79800
  let source = "";
79786
79801
  try {
79787
- source = readFileSync21(join27(root, ".errataignore"), "utf8");
79802
+ source = readFileSync22(join28(root, ".errataignore"), "utf8");
79788
79803
  } catch {
79789
79804
  source = "";
79790
79805
  }
@@ -80077,7 +80092,7 @@ function readActivityBranch(root) {
80077
80092
  try {
80078
80093
  const gitDir = resolveGitDir(root);
80079
80094
  if (!gitDir) return null;
80080
- const head2 = readFileSync22(join28(gitDir, "HEAD"), "utf8").trim();
80095
+ const head2 = readFileSync23(join29(gitDir, "HEAD"), "utf8").trim();
80081
80096
  const branch = head2.startsWith("ref: refs/heads/") ? head2.slice(16) : /^[a-f0-9]{40,64}$/i.test(head2) ? "HEAD" : null;
80082
80097
  return branch && branch.length <= 256 && !/[\x00-\x1f\x7f]/.test(branch) ? branch : null;
80083
80098
  } catch {
@@ -80234,21 +80249,21 @@ var FileActivityReporter = class {
80234
80249
 
80235
80250
  // src/skills.ts
80236
80251
  import {
80237
- existsSync as existsSync22,
80252
+ existsSync as existsSync23,
80238
80253
  mkdirSync as mkdirSync7,
80239
- readFileSync as readFileSync23,
80254
+ readFileSync as readFileSync24,
80240
80255
  readdirSync as readdirSync8,
80241
80256
  unlinkSync as unlinkSync2,
80242
- writeFileSync as writeFileSync16
80257
+ writeFileSync as writeFileSync17
80243
80258
  } from "node:fs";
80244
- import { basename as basename6, join as join29 } from "node:path";
80259
+ import { basename as basename6, join as join30 } from "node:path";
80245
80260
  function skillFileName(id) {
80246
80261
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
80247
80262
  }
80248
80263
  function readSkillManifest(manifestPath) {
80249
- if (!existsSync22(manifestPath)) return [];
80264
+ if (!existsSync23(manifestPath)) return [];
80250
80265
  try {
80251
- const parsed = JSON.parse(readFileSync23(manifestPath, "utf8"));
80266
+ const parsed = JSON.parse(readFileSync24(manifestPath, "utf8"));
80252
80267
  return (parsed.skills ?? []).map((s) => ({
80253
80268
  title: s.title ?? "",
80254
80269
  layer: s.layer ?? "technique",
@@ -80272,7 +80287,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80272
80287
  for (const s of res.skills) {
80273
80288
  const fileName = skillFileName(s.id);
80274
80289
  keep.add(fileName);
80275
- writeFileSync16(join29(paths.skillsDir, fileName), s.markdown, "utf8");
80290
+ writeFileSync17(join30(paths.skillsDir, fileName), s.markdown, "utf8");
80276
80291
  rows.push({
80277
80292
  id: s.id,
80278
80293
  title: s.title,
@@ -80285,7 +80300,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80285
80300
  const fileName = skillFileName(p.id);
80286
80301
  if (keep.has(fileName)) continue;
80287
80302
  keep.add(fileName);
80288
- writeFileSync16(join29(paths.skillsDir, fileName), p.markdown, "utf8");
80303
+ writeFileSync17(join30(paths.skillsDir, fileName), p.markdown, "utf8");
80289
80304
  rows.push({
80290
80305
  id: p.id,
80291
80306
  title: p.title,
@@ -80299,13 +80314,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80299
80314
  if (!f.endsWith(".md")) continue;
80300
80315
  if (keep.has(basename6(f))) continue;
80301
80316
  try {
80302
- unlinkSync2(join29(paths.skillsDir, f));
80317
+ unlinkSync2(join30(paths.skillsDir, f));
80303
80318
  pruned++;
80304
80319
  } catch {
80305
80320
  }
80306
80321
  }
80307
80322
  rows.sort((a, b) => a.id.localeCompare(b.id));
80308
- writeFileSync16(
80323
+ writeFileSync17(
80309
80324
  paths.skillsManifest,
80310
80325
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
80311
80326
  "utf8"
@@ -80317,22 +80332,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
80317
80332
  init_src2();
80318
80333
  import {
80319
80334
  cpSync,
80320
- existsSync as existsSync23,
80335
+ existsSync as existsSync24,
80321
80336
  lstatSync,
80322
80337
  mkdirSync as mkdirSync8,
80323
- readFileSync as readFileSync24,
80338
+ readFileSync as readFileSync25,
80324
80339
  readdirSync as readdirSync9,
80325
80340
  rmSync as rmSync3,
80326
80341
  symlinkSync,
80327
- writeFileSync as writeFileSync17
80342
+ writeFileSync as writeFileSync18
80328
80343
  } from "node:fs";
80329
- import { join as join30 } from "node:path";
80344
+ import { join as join31 } from "node:path";
80330
80345
  var SKILL_NS = "errata-";
80331
80346
  var HARNESS_SKILL_DIRS = [
80332
- { configDir: ".claude", skillsDir: join30(".claude", "skills") },
80347
+ { configDir: ".claude", skillsDir: join31(".claude", "skills") },
80333
80348
  // Cursor adopted the standard; its exact project dir is still moving — kept
80334
80349
  // best-effort and gated on `.cursor/` presence so we never create it blind.
80335
- { configDir: ".cursor", skillsDir: join30(".cursor", "skills") }
80350
+ { configDir: ".cursor", skillsDir: join31(".cursor", "skills") }
80336
80351
  ];
80337
80352
  function skillSlug(title, id) {
80338
80353
  const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
@@ -80377,12 +80392,12 @@ function skillCiteHandle(s) {
80377
80392
  return priorHandle({ id: s.id, description: s.title });
80378
80393
  }
80379
80394
  function reconcileNamespaced(dir, keep) {
80380
- if (!existsSync23(dir)) return 0;
80395
+ if (!existsSync24(dir)) return 0;
80381
80396
  let pruned = 0;
80382
80397
  for (const name2 of readdirSync9(dir)) {
80383
80398
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
80384
80399
  try {
80385
- rmSync3(join30(dir, name2), { recursive: true, force: true });
80400
+ rmSync3(join31(dir, name2), { recursive: true, force: true });
80386
80401
  pruned++;
80387
80402
  } catch {
80388
80403
  }
@@ -80391,7 +80406,7 @@ function reconcileNamespaced(dir, keep) {
80391
80406
  }
80392
80407
  function linkOrCopy(linkPath, target) {
80393
80408
  try {
80394
- if (existsSync23(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
80409
+ if (existsSync24(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
80395
80410
  } catch {
80396
80411
  }
80397
80412
  try {
@@ -80412,7 +80427,7 @@ function safeLstat(p) {
80412
80427
  }
80413
80428
  }
80414
80429
  function emitAndProjectSkills(root, skills) {
80415
- const agentsSkillsDir = join30(root, ".agents", "skills");
80430
+ const agentsSkillsDir = join31(root, ".agents", "skills");
80416
80431
  mkdirSync8(agentsSkillsDir, { recursive: true });
80417
80432
  const slugs = [];
80418
80433
  const keep = /* @__PURE__ */ new Set();
@@ -80420,7 +80435,7 @@ function emitAndProjectSkills(root, skills) {
80420
80435
  for (const s of skills) {
80421
80436
  let body2;
80422
80437
  try {
80423
- body2 = readFileSync24(s.bodyPath, "utf8");
80438
+ body2 = readFileSync25(s.bodyPath, "utf8");
80424
80439
  } catch {
80425
80440
  continue;
80426
80441
  }
@@ -80429,9 +80444,9 @@ function emitAndProjectSkills(root, skills) {
80429
80444
  keep.add(slug2);
80430
80445
  slugs.push(slug2);
80431
80446
  const description = deriveDescription(s.title, s.layer, body2);
80432
- mkdirSync8(join30(agentsSkillsDir, slug2), { recursive: true });
80433
- writeFileSync17(
80434
- join30(agentsSkillsDir, slug2, "SKILL.md"),
80447
+ mkdirSync8(join31(agentsSkillsDir, slug2), { recursive: true });
80448
+ writeFileSync18(
80449
+ join31(agentsSkillsDir, slug2, "SKILL.md"),
80435
80450
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
80436
80451
  "utf8"
80437
80452
  );
@@ -80440,11 +80455,11 @@ function emitAndProjectSkills(root, skills) {
80440
80455
  reconcileNamespaced(agentsSkillsDir, keep);
80441
80456
  let projected = 0;
80442
80457
  for (const h of HARNESS_SKILL_DIRS) {
80443
- if (!existsSync23(join30(root, h.configDir))) continue;
80444
- const dir = join30(root, h.skillsDir);
80458
+ if (!existsSync24(join31(root, h.configDir))) continue;
80459
+ const dir = join31(root, h.skillsDir);
80445
80460
  mkdirSync8(dir, { recursive: true });
80446
80461
  for (const slug2 of slugs) {
80447
- linkOrCopy(join30(dir, slug2), join30(agentsSkillsDir, slug2));
80462
+ linkOrCopy(join31(dir, slug2), join31(agentsSkillsDir, slug2));
80448
80463
  projected++;
80449
80464
  }
80450
80465
  reconcileNamespaced(dir, keep);
@@ -80453,15 +80468,15 @@ function emitAndProjectSkills(root, skills) {
80453
80468
  return { slugs, emitted, projected };
80454
80469
  }
80455
80470
  function emitInputsFromManifest(erretaDir, manifestPath) {
80456
- if (!existsSync23(manifestPath)) return [];
80471
+ if (!existsSync24(manifestPath)) return [];
80457
80472
  try {
80458
- const parsed = JSON.parse(readFileSync24(manifestPath, "utf8"));
80473
+ const parsed = JSON.parse(readFileSync25(manifestPath, "utf8"));
80459
80474
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
80460
80475
  id: s.id,
80461
80476
  title: s.title ?? s.id,
80462
80477
  layer: s.layer ?? "technique",
80463
80478
  confidence: s.confidence ?? 0,
80464
- bodyPath: join30(erretaDir, s.file)
80479
+ bodyPath: join31(erretaDir, s.file)
80465
80480
  }));
80466
80481
  } catch {
80467
80482
  return [];
@@ -80475,17 +80490,17 @@ var GITIGNORE_LINES = [
80475
80490
  ".cursor/skills/errata-*/"
80476
80491
  ];
80477
80492
  function ensureSkillGitignore(root) {
80478
- const path2 = join30(root, ".gitignore");
80493
+ const path2 = join31(root, ".gitignore");
80479
80494
  let current = "";
80480
80495
  try {
80481
- current = existsSync23(path2) ? readFileSync24(path2, "utf8") : "";
80496
+ current = existsSync24(path2) ? readFileSync25(path2, "utf8") : "";
80482
80497
  } catch {
80483
80498
  return;
80484
80499
  }
80485
80500
  if (current.includes(GITIGNORE_MARK)) return;
80486
80501
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
80487
80502
  try {
80488
- writeFileSync17(path2, `${current}${prefix}
80503
+ writeFileSync18(path2, `${current}${prefix}
80489
80504
  ${GITIGNORE_LINES.join("\n")}
80490
80505
  `, "utf8");
80491
80506
  } catch {
@@ -80581,18 +80596,18 @@ init_paths();
80581
80596
  init_profile2();
80582
80597
 
80583
80598
  // src/witness-queue.ts
80584
- import { readFileSync as readFileSync25, renameSync as renameSync2, writeFileSync as writeFileSync18 } from "node:fs";
80585
- import { dirname as dirname11, join as join31 } from "node:path";
80599
+ import { readFileSync as readFileSync26, renameSync as renameSync2, writeFileSync as writeFileSync19 } from "node:fs";
80600
+ import { dirname as dirname11, join as join32 } from "node:path";
80586
80601
  var WITNESS_QUEUE_CAP = 500;
80587
80602
  var WITNESS_TTL_MS = 14 * 24 * 60 * 60 * 1e3;
80588
80603
  var WITNESS_MAX_ATTEMPTS = 5;
80589
80604
  function witnessQueuePath(workspaceConfigDir) {
80590
- return join31(workspaceConfigDir, "witness-queue.json");
80605
+ return join32(workspaceConfigDir, "witness-queue.json");
80591
80606
  }
80592
80607
  function loadWitnessQueueWithLosses(path2) {
80593
80608
  let raw2;
80594
80609
  try {
80595
- raw2 = JSON.parse(readFileSync25(path2, "utf8"));
80610
+ raw2 = JSON.parse(readFileSync26(path2, "utf8"));
80596
80611
  } catch (err2) {
80597
80612
  const absent = err2?.code === "ENOENT";
80598
80613
  return { queue: [], fileUnreadable: !absent, malformedEntries: 0 };
@@ -80605,8 +80620,8 @@ function loadWitnessQueueWithLosses(path2) {
80605
80620
  }
80606
80621
  function saveWitnessQueue(path2, queue) {
80607
80622
  try {
80608
- const tmp = join31(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
80609
- writeFileSync18(tmp, JSON.stringify(queue), "utf8");
80623
+ const tmp = join32(dirname11(path2), `.${Date.now()}.witness-queue.tmp`);
80624
+ writeFileSync19(tmp, JSON.stringify(queue), "utf8");
80610
80625
  renameSync2(tmp, path2);
80611
80626
  } catch {
80612
80627
  }
@@ -80913,8 +80928,8 @@ function maybeFlushDigests() {
80913
80928
 
80914
80929
  // src/liveness-watch.ts
80915
80930
  init_src5();
80916
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync20 } from "node:fs";
80917
- import { join as join33 } from "node:path";
80931
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync21 } from "node:fs";
80932
+ import { join as join34 } from "node:path";
80918
80933
 
80919
80934
  // src/loop-lag.ts
80920
80935
  var HEARTBEAT_MS = 500;
@@ -81045,11 +81060,11 @@ function watchCensusLine(c = watchCensus(), now = Date.now()) {
81045
81060
  var LIVENESS_WATCH_INTERVAL_MS = 60 * 60 * 1e3;
81046
81061
  var ALARM_RENOTIFY_MS = 24 * 60 * 60 * 1e3;
81047
81062
  function alarmStatePath(configDir) {
81048
- return join33(configDir, "liveness-alarms.json");
81063
+ return join34(configDir, "liveness-alarms.json");
81049
81064
  }
81050
81065
  function loadAlarmState(configDir) {
81051
81066
  try {
81052
- const raw2 = JSON.parse(readFileSync27(alarmStatePath(configDir), "utf8"));
81067
+ const raw2 = JSON.parse(readFileSync28(alarmStatePath(configDir), "utf8"));
81053
81068
  return new Map(Object.entries(raw2).filter((e) => typeof e[1] === "number"));
81054
81069
  } catch {
81055
81070
  return /* @__PURE__ */ new Map();
@@ -81057,7 +81072,7 @@ function loadAlarmState(configDir) {
81057
81072
  }
81058
81073
  function saveAlarmState(configDir, state) {
81059
81074
  try {
81060
- writeFileSync20(alarmStatePath(configDir), JSON.stringify(Object.fromEntries(state)));
81075
+ writeFileSync21(alarmStatePath(configDir), JSON.stringify(Object.fromEntries(state)));
81061
81076
  } catch {
81062
81077
  }
81063
81078
  }
@@ -81226,7 +81241,7 @@ function createWatchBreaker(deps) {
81226
81241
  }
81227
81242
 
81228
81243
  // src/engine.ts
81229
- var DAEMON_VERSION = true ? "2.0.14-dev.3165" : "2.0.0-alpha.0";
81244
+ var DAEMON_VERSION = true ? "2.0.14-dev.3236" : "2.0.0-alpha.0";
81230
81245
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
81231
81246
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
81232
81247
  var GIT_OP_MUTE_MS = 4e3;
@@ -81238,7 +81253,7 @@ var CODEX_SWEEP_LOOKBACK_MS = 10 * 6e4;
81238
81253
  function appendIdentityAudit(path2, record2, line) {
81239
81254
  if (!record2.accepted && record2.score <= 0) return;
81240
81255
  try {
81241
- if (existsSync25(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
81256
+ if (existsSync26(path2) && statSync8(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
81242
81257
  renameSync3(path2, `${path2}.1`);
81243
81258
  }
81244
81259
  appendFileSync4(path2, line);
@@ -81248,7 +81263,7 @@ function appendIdentityAudit(path2, record2, line) {
81248
81263
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
81249
81264
  function loadTurnCursors(path2) {
81250
81265
  try {
81251
- const raw2 = JSON.parse(readFileSync28(path2, "utf8"));
81266
+ const raw2 = JSON.parse(readFileSync29(path2, "utf8"));
81252
81267
  return new Map(
81253
81268
  Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
81254
81269
  );
@@ -81258,7 +81273,7 @@ function loadTurnCursors(path2) {
81258
81273
  }
81259
81274
  function loadTurnOffsets(path2) {
81260
81275
  try {
81261
- const raw2 = JSON.parse(readFileSync28(path2, "utf8"));
81276
+ const raw2 = JSON.parse(readFileSync29(path2, "utf8"));
81262
81277
  const out2 = /* @__PURE__ */ new Map();
81263
81278
  for (const [k, v] of Object.entries(raw2)) {
81264
81279
  const off = typeof v === "object" && v !== null ? v.offset : void 0;
@@ -81274,7 +81289,7 @@ function saveTurnCursors(path2, cursors, offsets) {
81274
81289
  const merged = {};
81275
81290
  for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
81276
81291
  for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
81277
- writeFileSync21(path2, JSON.stringify(merged), "utf8");
81292
+ writeFileSync22(path2, JSON.stringify(merged), "utf8");
81278
81293
  } catch {
81279
81294
  }
81280
81295
  }
@@ -81296,7 +81311,7 @@ function gitSourceWatchTargets(root) {
81296
81311
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
81297
81312
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
81298
81313
  );
81299
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join34(root, d) + sep4));
81314
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join35(root, d) + sep4));
81300
81315
  } catch {
81301
81316
  }
81302
81317
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -81308,19 +81323,19 @@ function gitSourceWatchTargets(root) {
81308
81323
  if (!f.startsWith(prefix)) continue;
81309
81324
  const rest2 = f.slice(prefix.length);
81310
81325
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
81311
- else targets.add(join34(root, f));
81326
+ else targets.add(join35(root, f));
81312
81327
  }
81313
81328
  for (const c of children) {
81314
- if (IGNORED_PATH.test(join34(root, c) + sep4)) continue;
81329
+ if (IGNORED_PATH.test(join35(root, c) + sep4)) continue;
81315
81330
  if (hasIgnoredChild(c)) addUnder(c);
81316
- else targets.add(join34(root, c));
81331
+ else targets.add(join35(root, c));
81317
81332
  }
81318
81333
  };
81319
81334
  addUnder("");
81320
81335
  if (targets.size > 0) return [...targets];
81321
81336
  } catch {
81322
81337
  }
81323
- return readdirSync10(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join34(root, String(e.name)) + sep4)).map((e) => join34(root, String(e.name)));
81338
+ return readdirSync10(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join35(root, String(e.name)) + sep4)).map((e) => join35(root, String(e.name)));
81324
81339
  }
81325
81340
  function createWorkspaceEngine(opts) {
81326
81341
  const paths = workspacePaths(opts.workspaceRoot);
@@ -81526,7 +81541,7 @@ function createWorkspaceEngine(opts) {
81526
81541
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
81527
81542
  let episodeId2;
81528
81543
  if (srcPaths.length > 0) {
81529
- const abs = srcPaths.map((p) => join34(opts.workspaceRoot, p));
81544
+ const abs = srcPaths.map((p) => join35(opts.workspaceRoot, p));
81530
81545
  try {
81531
81546
  const r = await runReindexPass(
81532
81547
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -81562,8 +81577,8 @@ function createWorkspaceEngine(opts) {
81562
81577
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
81563
81578
  );
81564
81579
  };
81565
- const gitDir = join34(opts.workspaceRoot, ".git");
81566
- if (existsSync25(gitDir)) {
81580
+ const gitDir = join35(opts.workspaceRoot, ".git");
81581
+ if (existsSync26(gitDir)) {
81567
81582
  stopGit = startGitSensor(gitDir, (ev) => {
81568
81583
  void handleGitEvent(ev).catch((err2) => {
81569
81584
  console.warn("[errata] git event handler failed:", err2);
@@ -81682,7 +81697,7 @@ function createWorkspaceEngine(opts) {
81682
81697
  const elicit = isEdgeElicitationEnabled();
81683
81698
  const snapOpts = {
81684
81699
  profile,
81685
- atCommit: readGitRefState(join34(opts.workspaceRoot, ".git")).sha ?? void 0,
81700
+ atCommit: readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0,
81686
81701
  reviewCount: pendingCount(paths),
81687
81702
  reviewUiUrl: opts.reviewUrl(),
81688
81703
  workingFile: workingFiles.mostRecent() ?? void 0,
@@ -81696,7 +81711,7 @@ function createWorkspaceEngine(opts) {
81696
81711
  );
81697
81712
  return null;
81698
81713
  }) : null;
81699
- if (snapOpts.atCommit !== (readGitRefState(join34(opts.workspaceRoot, ".git")).sha ?? void 0)) {
81714
+ if (snapOpts.atCommit !== (readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0)) {
81700
81715
  contextDirty = true;
81701
81716
  return;
81702
81717
  }
@@ -81749,10 +81764,16 @@ function createWorkspaceEngine(opts) {
81749
81764
  console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
81750
81765
  }
81751
81766
  writeContextFile(opts.workspaceRoot, body2);
81752
- const target = join34(opts.workspaceRoot, "AGENTS.md");
81767
+ try {
81768
+ const written = readContextFileWithHash(opts.workspaceRoot);
81769
+ if (written) writeContextCard(opts.workspaceRoot, written.hash, contextCard(store, snapshot));
81770
+ } catch (err2) {
81771
+ console.warn("[errata] context card failed:", err2.message?.slice(0, 120));
81772
+ }
81773
+ const target = join35(opts.workspaceRoot, "AGENTS.md");
81753
81774
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
81754
81775
  if (elicit) {
81755
- writePrimingHandles(join34(paths.configDir, "priming-handles.json"), [
81776
+ writePrimingHandles(join35(paths.configDir, "priming-handles.json"), [
81756
81777
  ...snapshot.recentProblems.map((r) => r.node),
81757
81778
  // Resolved-band handles: the ✓ problem AND its Solution are citable
81758
81779
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -82094,7 +82115,7 @@ function createWorkspaceEngine(opts) {
82094
82115
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
82095
82116
  });
82096
82117
  };
82097
- const turnCursorPath = join34(paths.configDir, "turn-cursors.json");
82118
+ const turnCursorPath = join35(paths.configDir, "turn-cursors.json");
82098
82119
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
82099
82120
  const turnOffset = loadTurnOffsets(turnCursorPath);
82100
82121
  const readLosses = { parseFailures: 0, ioFailures: 0, bytesUnreachable: 0, sliceGuardHits: 0 };
@@ -82152,7 +82173,7 @@ function createWorkspaceEngine(opts) {
82152
82173
  let processedTurns = 0;
82153
82174
  const seqAtStart = store.currentIngestSeq();
82154
82175
  const elicit = isEdgeElicitationEnabled();
82155
- const handleMap = elicit ? readPrimingHandles(join34(paths.configDir, "priming-handles.json")) : {};
82176
+ const handleMap = elicit ? readPrimingHandles(join35(paths.configDir, "priming-handles.json")) : {};
82156
82177
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
82157
82178
  const toRel = (abs) => {
82158
82179
  const p = abs.replace(/\\/g, "/");
@@ -82449,10 +82470,10 @@ function createWorkspaceEngine(opts) {
82449
82470
  let enclosing = {};
82450
82471
  if (p.location?.line !== void 0) {
82451
82472
  try {
82452
- const headSha = readGitRefState(join34(opts.workspaceRoot, ".git")).sha ?? void 0;
82473
+ const headSha = readGitRefState(join35(opts.workspaceRoot, ".git")).sha ?? void 0;
82453
82474
  enclosing = {
82454
82475
  line: p.location.line,
82455
- fileText: readFileSync28(join34(opts.workspaceRoot, anchorPath), "utf8"),
82476
+ fileText: readFileSync29(join35(opts.workspaceRoot, anchorPath), "utf8"),
82456
82477
  ...headSha ? { headSha } : {}
82457
82478
  };
82458
82479
  } catch {
@@ -83251,7 +83272,7 @@ B: ${b}`,
83251
83272
  try {
83252
83273
  const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
83253
83274
  emitAndProjectSkills(opts.workspaceRoot, inputs);
83254
- writePrimingHandles(join34(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
83275
+ writePrimingHandles(join35(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
83255
83276
  } catch (err2) {
83256
83277
  console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
83257
83278
  }
@@ -83558,7 +83579,7 @@ B: ${b}`,
83558
83579
  console.log(
83559
83580
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
83560
83581
  );
83561
- const pending = existsSync25(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
83582
+ const pending = existsSync26(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
83562
83583
  return { uploaded: 0, failed: 0, remaining: pending };
83563
83584
  }
83564
83585
  const onDisk = loadProfile(opts.workspaceRoot);
@@ -83566,7 +83587,7 @@ B: ${b}`,
83566
83587
  console.log(
83567
83588
  "[errata] sync held \u2014 this repo is already on errata in another workspace; run `errata link` to join it or create your own project"
83568
83589
  );
83569
- const pending = existsSync25(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
83590
+ const pending = existsSync26(paths.outbox) ? readdirSync10(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
83570
83591
  return { uploaded: 0, failed: 0, remaining: pending };
83571
83592
  }
83572
83593
  try {
@@ -83659,7 +83680,7 @@ async function startDaemon(opts) {
83659
83680
  reviewUrl: () => webUiUrl + "/review"
83660
83681
  });
83661
83682
  const writeLockFile = (url2) => {
83662
- writeFileSync22(
83683
+ writeFileSync23(
83663
83684
  engine.paths.daemonLock,
83664
83685
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
83665
83686
  "utf8"
@@ -83702,7 +83723,7 @@ async function startDaemon(opts) {
83702
83723
  );
83703
83724
  await engine.stop();
83704
83725
  try {
83705
- if (existsSync26(engine.paths.daemonLock)) {
83726
+ if (existsSync27(engine.paths.daemonLock)) {
83706
83727
  }
83707
83728
  } catch {
83708
83729
  }
@@ -83903,7 +83924,7 @@ function instanceReceiptSequence(n) {
83903
83924
  // src/multi.ts
83904
83925
  init_dist();
83905
83926
  init_src5();
83906
- import { existsSync as existsSync32, readFileSync as readFileSync33, unlinkSync as unlinkSync3, writeFileSync as writeFileSync24 } from "node:fs";
83927
+ import { existsSync as existsSync33, readFileSync as readFileSync34, unlinkSync as unlinkSync3, writeFileSync as writeFileSync25 } from "node:fs";
83907
83928
  import { resolve as pathResolve } from "node:path";
83908
83929
 
83909
83930
  // src/principle-sync.ts
@@ -83932,8 +83953,8 @@ init_reconcile();
83932
83953
 
83933
83954
  // src/lockfile-auto.ts
83934
83955
  init_src();
83935
- import { existsSync as existsSync27, readFileSync as readFileSync29 } from "node:fs";
83936
- import { join as join35 } from "node:path";
83956
+ import { existsSync as existsSync28, readFileSync as readFileSync30 } from "node:fs";
83957
+ import { join as join36 } from "node:path";
83937
83958
 
83938
83959
  // src/package-index.ts
83939
83960
  init_src();
@@ -84082,11 +84103,11 @@ function runLockfilePass(opts) {
84082
84103
  { file: "package-lock.json", parse: parsePackageLockJson }
84083
84104
  ];
84084
84105
  for (const c of candidates) {
84085
- const p = join35(opts.root, c.file);
84086
- if (!existsSync27(p)) continue;
84106
+ const p = join36(opts.root, c.file);
84107
+ if (!existsSync28(p)) continue;
84087
84108
  let sbom;
84088
84109
  try {
84089
- sbom = c.parse(readFileSync29(p, "utf8"));
84110
+ sbom = c.parse(readFileSync30(p, "utf8"));
84090
84111
  } catch {
84091
84112
  continue;
84092
84113
  }
@@ -84146,8 +84167,8 @@ function noveltyAgainst(node2, neighbors, opts = {}) {
84146
84167
  init_profile2();
84147
84168
 
84148
84169
  // src/public-symbols.ts
84149
- import { readFileSync as readFileSync30, readdirSync as readdirSync11, existsSync as existsSync28 } from "node:fs";
84150
- import { join as join36 } from "node:path";
84170
+ import { readFileSync as readFileSync31, readdirSync as readdirSync11, existsSync as existsSync29 } from "node:fs";
84171
+ import { join as join37 } from "node:path";
84151
84172
  var HEAD_BYTES = 8 * 1024;
84152
84173
  var INDEX_TTL_MS = 10 * 60 * 1e3;
84153
84174
  var MIN_SYMBOL_LEN = 4;
@@ -84180,20 +84201,20 @@ function bindingNames(clause) {
84180
84201
  function internalPackageNames(workspaceRoot) {
84181
84202
  const names = /* @__PURE__ */ new Set();
84182
84203
  const tryRead = (dir) => {
84183
- const pj = join36(dir, "package.json");
84184
- if (!existsSync28(pj)) return;
84204
+ const pj = join37(dir, "package.json");
84205
+ if (!existsSync29(pj)) return;
84185
84206
  try {
84186
- const name2 = JSON.parse(readFileSync30(pj, "utf8")).name;
84207
+ const name2 = JSON.parse(readFileSync31(pj, "utf8")).name;
84187
84208
  if (typeof name2 === "string" && name2.length > 0) names.add(name2);
84188
84209
  } catch {
84189
84210
  }
84190
84211
  };
84191
84212
  tryRead(workspaceRoot);
84192
84213
  for (const group of ["packages", "apps"]) {
84193
- const groupDir = join36(workspaceRoot, group);
84194
- if (!existsSync28(groupDir)) continue;
84214
+ const groupDir = join37(workspaceRoot, group);
84215
+ if (!existsSync29(groupDir)) continue;
84195
84216
  try {
84196
- for (const entry of readdirSync11(groupDir)) tryRead(join36(groupDir, entry));
84217
+ for (const entry of readdirSync11(groupDir)) tryRead(join37(groupDir, entry));
84197
84218
  } catch {
84198
84219
  }
84199
84220
  }
@@ -84212,7 +84233,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
84212
84233
  }
84213
84234
  const readHead = deps.readHead ?? ((absPath) => {
84214
84235
  try {
84215
- return readFileSync30(absPath, "utf8").slice(0, HEAD_BYTES);
84236
+ return readFileSync31(absPath, "utf8").slice(0, HEAD_BYTES);
84216
84237
  } catch {
84217
84238
  return "";
84218
84239
  }
@@ -84232,7 +84253,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
84232
84253
  }
84233
84254
  const symbols = /* @__PURE__ */ new Set();
84234
84255
  for (const rel of files) {
84235
- const head2 = readHead(join36(workspaceRoot, rel));
84256
+ const head2 = readHead(join37(workspaceRoot, rel));
84236
84257
  if (!head2) continue;
84237
84258
  for (const re of [NAMED_IMPORT_RE, REQUIRE_RE]) {
84238
84259
  re.lastIndex = 0;
@@ -85031,7 +85052,7 @@ function cloudTargetDrift(daemon, shell2) {
85031
85052
  }
85032
85053
 
85033
85054
  // src/lock.ts
85034
- import { existsSync as existsSync29, readFileSync as readFileSync31 } from "node:fs";
85055
+ import { existsSync as existsSync30, readFileSync as readFileSync32 } from "node:fs";
85035
85056
  function daemonLockPayload(lock) {
85036
85057
  return JSON.stringify({
85037
85058
  pid: lock.pid,
@@ -85069,9 +85090,9 @@ function isProcessAlive(pid) {
85069
85090
  }
85070
85091
  }
85071
85092
  function readDaemonLock(lockPath) {
85072
- if (!existsSync29(lockPath)) return null;
85093
+ if (!existsSync30(lockPath)) return null;
85073
85094
  try {
85074
- const lock = JSON.parse(readFileSync31(lockPath, "utf8"));
85095
+ const lock = JSON.parse(readFileSync32(lockPath, "utf8"));
85075
85096
  return typeof lock.pid === "number" ? lock : null;
85076
85097
  } catch {
85077
85098
  return null;
@@ -85267,6 +85288,7 @@ init_src11();
85267
85288
  init_profile2();
85268
85289
 
85269
85290
  // src/history-corrections.ts
85291
+ init_src();
85270
85292
  init_profile2();
85271
85293
  function applyHistoryCorrections(store, page) {
85272
85294
  let changed = 0;
@@ -85281,15 +85303,16 @@ function applyHistoryCorrections(store, page) {
85281
85303
  for (const node2 of copies) {
85282
85304
  if (node2.attrs["source"] !== "cloud" || node2.attrs["cloudNodeId"] && node2.attrs["cloudNodeId"] !== correction.nodeId || Number(node2.attrs["historyCorrectionSeq"] ?? 0) >= correction.seq) continue;
85283
85305
  const quality = { sourceSupport: correction.sourceSupport ?? (privacy ? "quarantined" : "unreviewed"), applicability: "unknown" };
85306
+ const historical = node2.extractionSource === "history-mined" || node2.attrs["extractionSource"] === "history-mined";
85284
85307
  store.mergeNode({
85285
85308
  ...node2,
85286
85309
  lastUpdatedAt: Date.now(),
85287
- ...privacy ? { description: "History source withdrawn.", embedding: [], isLandmark: false } : {},
85310
+ ...privacy ? { description: historical ? "History source withdrawn." : "Cloud source withdrawn.", embedding: [], isLandmark: false } : {},
85288
85311
  attrs: {
85289
- ...privacy ? {} : node2.attrs,
85312
+ ...privacy ? {} : projectWireAttrs(node2.attrs),
85290
85313
  source: "cloud",
85291
85314
  cloudNodeId: correction.nodeId,
85292
- extractionSource: "history-mined",
85315
+ extractionSource: node2.extractionSource,
85293
85316
  historyQuality: quality,
85294
85317
  historyCorrectionSeq: correction.seq
85295
85318
  }
@@ -85783,8 +85806,8 @@ async function syncHistoryRevisionPage(opts) {
85783
85806
  init_src7();
85784
85807
  init_src();
85785
85808
  import { execFile as execFile5 } from "node:child_process";
85786
- import { readFileSync as readFileSync32 } from "node:fs";
85787
- import { join as join37 } from "node:path";
85809
+ import { readFileSync as readFileSync33 } from "node:fs";
85810
+ import { join as join38 } from "node:path";
85788
85811
  import { promisify as promisify3 } from "node:util";
85789
85812
 
85790
85813
  // src/history-walk.ts
@@ -86107,8 +86130,8 @@ function narrative(unit, group) {
86107
86130
  }
86108
86131
  function narrativeSources(unit, group) {
86109
86132
  if (!group || group.length === 0) return [{ commitSha: unit.sha, text: message(unit).trim() }].filter((s) => s.text.length > 0);
86110
- const members2 = group.filter((g) => g.groupSha === (unit.groupSha ?? unit.sha)).sort((a, b) => a.subIndex - b.subIndex);
86111
- const source = members2.length > 0 ? members2 : [...group].sort((a, b) => a.subIndex - b.subIndex);
86133
+ const members = group.filter((g) => g.groupSha === (unit.groupSha ?? unit.sha)).sort((a, b) => a.subIndex - b.subIndex);
86134
+ const source = members.length > 0 ? members : [...group].sort((a, b) => a.subIndex - b.subIndex);
86112
86135
  return source.map((member) => ({ commitSha: member.sha, text: message(member).trim() })).filter((s) => s.text.length > 0);
86113
86136
  }
86114
86137
 
@@ -86331,7 +86354,7 @@ async function defaultGit(root, args2) {
86331
86354
  function readIgnoreLines(root, profile) {
86332
86355
  let lines = [];
86333
86356
  try {
86334
- lines = readFileSync32(join37(root, ".errataignore"), "utf8").split("\n");
86357
+ lines = readFileSync33(join38(root, ".errataignore"), "utf8").split("\n");
86335
86358
  } catch {
86336
86359
  }
86337
86360
  return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -86761,8 +86784,8 @@ async function startHistoryStage(root, input, client, walk11 = {}) {
86761
86784
  init_cloud_auth();
86762
86785
  import { createHash as createHash19 } from "node:crypto";
86763
86786
  import { execFileSync as execFileSync5 } from "node:child_process";
86764
- import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
86765
- import { join as join38 } from "node:path";
86787
+ import { existsSync as existsSync31, writeFileSync as writeFileSync24 } from "node:fs";
86788
+ import { join as join39 } from "node:path";
86766
86789
 
86767
86790
  // src/device-poll.ts
86768
86791
  var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
@@ -87220,9 +87243,9 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
87220
87243
  delete nextProfile.projectLinkHold;
87221
87244
  let wroteIgnore = false;
87222
87245
  if (decision.writeIgnoreStarter !== false) {
87223
- const target = join38(root, ".errataignore");
87224
- if (!existsSync30(target)) {
87225
- writeFileSync23(target, IGNORE_STARTER, "utf8");
87246
+ const target = join39(root, ".errataignore");
87247
+ if (!existsSync31(target)) {
87248
+ writeFileSync24(target, IGNORE_STARTER, "utf8");
87226
87249
  wroteIgnore = true;
87227
87250
  }
87228
87251
  }
@@ -87235,12 +87258,12 @@ init_registry();
87235
87258
 
87236
87259
  // src/adopt.ts
87237
87260
  init_git_remote();
87238
- import { existsSync as existsSync31 } from "node:fs";
87239
- import { dirname as dirname12, join as join39 } from "node:path";
87261
+ import { existsSync as existsSync32 } from "node:fs";
87262
+ import { dirname as dirname12, join as join40 } from "node:path";
87240
87263
  function findGitRoot(absPath) {
87241
87264
  let dir = absPath;
87242
87265
  for (let depth = 0; depth < 64; depth++) {
87243
- if (existsSync31(join39(dir, ".git"))) return dir;
87266
+ if (existsSync32(join40(dir, ".git"))) return dir;
87244
87267
  const parent = dirname12(dir);
87245
87268
  if (parent === dir) return null;
87246
87269
  dir = parent;
@@ -87933,7 +87956,7 @@ async function startMultiDaemon(opts = {}) {
87933
87956
  records.push(rec);
87934
87957
  void ambientLinkAll();
87935
87958
  try {
87936
- writeFileSync24(
87959
+ writeFileSync25(
87937
87960
  rec.engine.paths.daemonLock,
87938
87961
  daemonLockPayload({
87939
87962
  pid: process.pid,
@@ -88219,7 +88242,7 @@ async function startMultiDaemon(opts = {}) {
88219
88242
  lastActiveAt = Math.max(lastActiveAt, rec.engine.lastActivityAt());
88220
88243
  } catch {
88221
88244
  }
88222
- const reason = retireDecision({ exists: existsSync32(rec.root), lastActiveAt, now });
88245
+ const reason = retireDecision({ exists: existsSync33(rec.root), lastActiveAt, now });
88223
88246
  if (reason) void retireWorkspace(rec, reason);
88224
88247
  }
88225
88248
  };
@@ -88290,7 +88313,7 @@ async function startMultiDaemon(opts = {}) {
88290
88313
  baseUrl = `http://127.0.0.1:${port}`;
88291
88314
  try {
88292
88315
  ensureDir(globalDir());
88293
- writeFileSync24(
88316
+ writeFileSync25(
88294
88317
  lockPath,
88295
88318
  daemonLockPayload({ pid: process.pid, webUiUrl: baseUrl, processStartedAt: PROCESS_STARTED_AT, entry: SELF_ENTRY, version: DAEMON_VERSION }),
88296
88319
  "utf8"
@@ -88299,7 +88322,7 @@ async function startMultiDaemon(opts = {}) {
88299
88322
  }
88300
88323
  for (const r of records) {
88301
88324
  try {
88302
- writeFileSync24(
88325
+ writeFileSync25(
88303
88326
  r.engine.paths.daemonLock,
88304
88327
  daemonLockPayload({
88305
88328
  pid: process.pid,
@@ -89271,7 +89294,7 @@ async function startMultiDaemon(opts = {}) {
89271
89294
  clearInterval(anchorPull);
89272
89295
  clearTimeout(codexWakeBoot);
89273
89296
  try {
89274
- const cur = readFileSync33(lockPath, "utf8");
89297
+ const cur = readFileSync34(lockPath, "utf8");
89275
89298
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
89276
89299
  } catch {
89277
89300
  }
@@ -89694,7 +89717,7 @@ import { spawnSync } from "node:child_process";
89694
89717
 
89695
89718
  // src/codex-runtime.ts
89696
89719
  import { readdirSync as readdirSync12, statSync as statSync9 } from "node:fs";
89697
- import { join as join40 } from "node:path";
89720
+ import { join as join41 } from "node:path";
89698
89721
  function resolveCodexExecutable(options = {}) {
89699
89722
  const platform = options.platform ?? process.platform;
89700
89723
  const env2 = options.env ?? process.env;
@@ -89709,13 +89732,13 @@ function resolveCodexExecutable(options = {}) {
89709
89732
  };
89710
89733
  for (const dir of (env2["PATH"] ?? env2["Path"] ?? "").split(";")) {
89711
89734
  if (!dir.trim()) continue;
89712
- const path2 = join40(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
89735
+ const path2 = join41(dir.trim().replace(/^"|"$/g, ""), "codex.exe");
89713
89736
  if (fileTime(path2) !== null) return path2;
89714
89737
  }
89715
89738
  if (!env2["LOCALAPPDATA"]) return "codex";
89716
- const root = join40(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
89739
+ const root = join41(env2["LOCALAPPDATA"], "OpenAI", "Codex", "bin");
89717
89740
  try {
89718
- const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join40(root, entry.name, "codex.exe")).map((path2) => ({ path: path2, mtime: fileTime(path2) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
89741
+ const candidates = readdirSync12(root, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join41(root, entry.name, "codex.exe")).map((path2) => ({ path: path2, mtime: fileTime(path2) })).filter((candidate) => candidate.mtime !== null).sort((a, b) => b.mtime - a.mtime || a.path.localeCompare(b.path));
89719
89742
  return candidates[0]?.path ?? "codex";
89720
89743
  } catch {
89721
89744
  return "codex";
@@ -89834,9 +89857,9 @@ import { spawn as spawn4 } from "node:child_process";
89834
89857
  import { createInterface } from "node:readline";
89835
89858
 
89836
89859
  // src/codex-hooks.ts
89837
- import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync34, writeFileSync as writeFileSync25 } from "node:fs";
89860
+ import { existsSync as existsSync34, mkdirSync as mkdirSync9, readFileSync as readFileSync35, writeFileSync as writeFileSync26 } from "node:fs";
89838
89861
  import { homedir as homedir7 } from "node:os";
89839
- import { join as join41 } from "node:path";
89862
+ import { join as join42 } from "node:path";
89840
89863
 
89841
89864
  // src/hook-commands.ts
89842
89865
  function hookCurlCommand(port, path2 = "/api/hook") {
@@ -89915,8 +89938,8 @@ try {
89915
89938
 
89916
89939
  // src/codex-hooks.ts
89917
89940
  var CODEX_HOOK_REVIEW_HELP = "Codex desktop: Settings > Hooks, select this project, expand each event and Trust the Errata hook. CLI users can use /hooks.";
89918
- function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join41(homedir7(), ".codex")) {
89919
- return existsSync33(join41(root, ".codex")) || existsSync33(codexHome);
89941
+ function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join42(homedir7(), ".codex")) {
89942
+ return existsSync34(join42(root, ".codex")) || existsSync34(codexHome);
89920
89943
  }
89921
89944
  function replaceCodexHooks(existing, block) {
89922
89945
  const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
@@ -89932,14 +89955,14 @@ function replaceCodexHooks(existing, block) {
89932
89955
  return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
89933
89956
  }
89934
89957
  function writeCodexHooks(root, port, nodePath = process.execPath) {
89935
- const dir = join41(root, ".codex");
89936
- const file2 = join41(dir, "config.toml");
89937
- const relay = join41(dir, "hooks", "errata-relay.mjs");
89958
+ const dir = join42(root, ".codex");
89959
+ const file2 = join42(dir, "config.toml");
89960
+ const relay = join42(dir, "hooks", "errata-relay.mjs");
89938
89961
  const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
89939
- const final = replaceCodexHooks(existsSync33(file2) ? readFileSync34(file2, "utf8") : "", block);
89940
- mkdirSync9(join41(dir, "hooks"), { recursive: true });
89941
- writeFileSync25(relay, CODEX_RELAY_SOURCE, "utf8");
89942
- writeFileSync25(file2, final, "utf8");
89962
+ const final = replaceCodexHooks(existsSync34(file2) ? readFileSync35(file2, "utf8") : "", block);
89963
+ mkdirSync9(join42(dir, "hooks"), { recursive: true });
89964
+ writeFileSync26(relay, CODEX_RELAY_SOURCE, "utf8");
89965
+ writeFileSync26(file2, final, "utf8");
89943
89966
  return file2;
89944
89967
  }
89945
89968
 
@@ -90106,9 +90129,9 @@ function consolidationGapMs(lastPassMs, policy) {
90106
90129
  }
90107
90130
 
90108
90131
  // src/claude-statusline.ts
90109
- import { existsSync as existsSync34, mkdirSync as mkdirSync10, readFileSync as readFileSync35, writeFileSync as writeFileSync26 } from "node:fs";
90132
+ import { existsSync as existsSync35, mkdirSync as mkdirSync10, readFileSync as readFileSync36, writeFileSync as writeFileSync27 } from "node:fs";
90110
90133
  import { homedir as homedir8 } from "node:os";
90111
- import { dirname as dirname13, join as join42 } from "node:path";
90134
+ import { dirname as dirname13, join as join43 } from "node:path";
90112
90135
  var STATUSLINE_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata init / install-hooks claude
90113
90136
  import { readFileSync } from 'node:fs';
90114
90137
 
@@ -90141,8 +90164,8 @@ function removeProjectStatusLine(settings) {
90141
90164
  return true;
90142
90165
  }
90143
90166
  function userClaudeSettingsPath() {
90144
- const base = process.env["CLAUDE_CONFIG_DIR"] ?? join42(homedir8(), ".claude");
90145
- return join42(base, "settings.json");
90167
+ const base = process.env["CLAUDE_CONFIG_DIR"] ?? join43(homedir8(), ".claude");
90168
+ return join43(base, "settings.json");
90146
90169
  }
90147
90170
  function ensureUserStatusLine(opts) {
90148
90171
  const env2 = opts.env ?? process.env;
@@ -90150,9 +90173,9 @@ function ensureUserStatusLine(opts) {
90150
90173
  if (off === "0" || off === "off" || off === "false" || off === "no") return "disabled";
90151
90174
  const settingsPath = opts.userSettingsPath ?? userClaudeSettingsPath();
90152
90175
  let settings = {};
90153
- if (existsSync34(settingsPath)) {
90176
+ if (existsSync35(settingsPath)) {
90154
90177
  try {
90155
- const parsed = JSON.parse(readFileSync35(settingsPath, "utf8"));
90178
+ const parsed = JSON.parse(readFileSync36(settingsPath, "utf8"));
90156
90179
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return "unreadable";
90157
90180
  settings = parsed;
90158
90181
  } catch {
@@ -90160,16 +90183,16 @@ function ensureUserStatusLine(opts) {
90160
90183
  }
90161
90184
  }
90162
90185
  if (settings["statusLine"] !== void 0 && !isErrataStatusLine(settings["statusLine"])) return "kept-own";
90163
- const relay = join42(opts.relayDir, STATUSLINE_RELAY_FILE);
90186
+ const relay = join43(opts.relayDir, STATUSLINE_RELAY_FILE);
90164
90187
  mkdirSync10(opts.relayDir, { recursive: true });
90165
- if (!existsSync34(relay) || readFileSync35(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
90166
- writeFileSync26(relay, STATUSLINE_RELAY_SOURCE, "utf8");
90188
+ if (!existsSync35(relay) || readFileSync36(relay, "utf8") !== STATUSLINE_RELAY_SOURCE) {
90189
+ writeFileSync27(relay, STATUSLINE_RELAY_SOURCE, "utf8");
90167
90190
  }
90168
90191
  const next = buildStatusLine(opts.port, opts.nodePath ?? process.execPath, relay);
90169
90192
  if (JSON.stringify(settings["statusLine"]) === JSON.stringify(next)) return "unchanged";
90170
90193
  settings["statusLine"] = next;
90171
90194
  mkdirSync10(dirname13(settingsPath), { recursive: true });
90172
- writeFileSync26(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
90195
+ writeFileSync27(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
90173
90196
  return "installed";
90174
90197
  }
90175
90198
  function describeStatusLineOutcome(outcome) {
@@ -90592,14 +90615,14 @@ async function cmdInit() {
90592
90615
  if (!skipHooks) {
90593
90616
  console.log("");
90594
90617
  console.log("installing harness hooks...");
90595
- const { existsSync: existsSync36 } = await import("node:fs");
90596
- const { join: join44 } = await import("node:path");
90618
+ const { existsSync: existsSync37 } = await import("node:fs");
90619
+ const { join: join45 } = await import("node:path");
90597
90620
  try {
90598
90621
  await installClaudeHooks(port);
90599
90622
  } catch (err2) {
90600
90623
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
90601
90624
  }
90602
- if (existsSync36(join44(ROOT, ".cursor"))) {
90625
+ if (existsSync37(join45(ROOT, ".cursor"))) {
90603
90626
  try {
90604
90627
  await installCursorMcpConfig();
90605
90628
  } catch (err2) {
@@ -90789,9 +90812,9 @@ async function cmdStatus() {
90789
90812
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
90790
90813
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
90791
90814
  }
90792
- console.log(` graph db: ${existsSync35(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
90793
- console.log(` event log: ${existsSync35(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
90794
- if (existsSync35(paths.castalia)) {
90815
+ console.log(` graph db: ${existsSync36(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
90816
+ console.log(` event log: ${existsSync36(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
90817
+ if (existsSync36(paths.castalia)) {
90795
90818
  try {
90796
90819
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
90797
90820
  const store = openGraphStore2({ path: paths.castalia });
@@ -91759,11 +91782,11 @@ async function cmdInstallationProfile(args2) {
91759
91782
  }
91760
91783
  async function cmdReview() {
91761
91784
  const paths = workspacePaths(ROOT);
91762
- if (!existsSync35(paths.reviewQueue)) {
91785
+ if (!existsSync36(paths.reviewQueue)) {
91763
91786
  console.log("(review queue empty)");
91764
91787
  return;
91765
91788
  }
91766
- const queue = JSON.parse(readFileSync36(paths.reviewQueue, "utf8"));
91789
+ const queue = JSON.parse(readFileSync37(paths.reviewQueue, "utf8"));
91767
91790
  if (queue.length === 0) {
91768
91791
  console.log("(review queue empty)");
91769
91792
  return;
@@ -92434,7 +92457,7 @@ async function gatherRepo(store, ws) {
92434
92457
  };
92435
92458
  }
92436
92459
  async function gatherReportData(generatedAt) {
92437
- const { existsSync: existsSync36 } = await import("node:fs");
92460
+ const { existsSync: existsSync37 } = await import("node:fs");
92438
92461
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src5(), src_exports2));
92439
92462
  const cfg = loadConfig();
92440
92463
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -92442,7 +92465,7 @@ async function gatherReportData(generatedAt) {
92442
92465
  for (const ws of listWorkspaces()) {
92443
92466
  if (ws.missing) continue;
92444
92467
  const dbPath = workspacePaths(ws.path).castalia;
92445
- if (!existsSync36(dbPath)) continue;
92468
+ if (!existsSync37(dbPath)) continue;
92446
92469
  let store = null;
92447
92470
  try {
92448
92471
  store = openGraphStore2({ path: dbPath });
@@ -92473,7 +92496,7 @@ async function gatherReportData(generatedAt) {
92473
92496
  };
92474
92497
  }
92475
92498
  async function cmdReport(args2) {
92476
- const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync27 } = await import("node:fs");
92499
+ const { mkdirSync: mkdirSync11, writeFileSync: writeFileSync28 } = await import("node:fs");
92477
92500
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
92478
92501
  const includeFutureVerbs = args2.includes("--future-verbs");
92479
92502
  const now = /* @__PURE__ */ new Date();
@@ -92486,8 +92509,8 @@ async function cmdReport(args2) {
92486
92509
  const outDir = workspacePaths(ROOT).configDir;
92487
92510
  mkdirSync11(outDir, { recursive: true });
92488
92511
  const files = renderReport2(data, { includeFutureVerbs });
92489
- for (const f of files) writeFileSync27(join43(outDir, f.name), f.html, "utf8");
92490
- const indexPath = join43(outDir, "report.html");
92512
+ for (const f of files) writeFileSync28(join44(outDir, f.name), f.html, "utf8");
92513
+ const indexPath = join44(outDir, "report.html");
92491
92514
  console.log(`report \u2192 ${indexPath}`);
92492
92515
  console.log(
92493
92516
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -92607,24 +92630,24 @@ async function cmdInstallHooks(args2) {
92607
92630
  }
92608
92631
  }
92609
92632
  async function installOpencodePlugin(port) {
92610
- const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
92611
- const { join: join44 } = await import("node:path");
92612
- const dir = join44(ROOT, ".opencode", "plugin");
92613
- if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
92614
- const file2 = join44(dir, "inerrata.js");
92615
- if (existsSync36(file2)) {
92616
- const head2 = readFileSync37(file2, "utf8").split("\n")[0] ?? "";
92633
+ const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync38, writeFileSync: writeFileSync28 } = await import("node:fs");
92634
+ const { join: join45 } = await import("node:path");
92635
+ const dir = join45(ROOT, ".opencode", "plugin");
92636
+ if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
92637
+ const file2 = join45(dir, "inerrata.js");
92638
+ if (existsSync37(file2)) {
92639
+ const head2 = readFileSync38(file2, "utf8").split("\n")[0] ?? "";
92617
92640
  if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
92618
92641
  console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
92619
92642
  process.exit(2);
92620
92643
  }
92621
92644
  }
92622
- writeFileSync27(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
92623
- const cfgFile = join44(ROOT, "opencode.json");
92645
+ writeFileSync28(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
92646
+ const cfgFile = join45(ROOT, "opencode.json");
92624
92647
  let cfg = { $schema: "https://opencode.ai/config.json" };
92625
- if (existsSync36(cfgFile)) {
92648
+ if (existsSync37(cfgFile)) {
92626
92649
  try {
92627
- cfg = JSON.parse(readFileSync37(cfgFile, "utf8"));
92650
+ cfg = JSON.parse(readFileSync38(cfgFile, "utf8"));
92628
92651
  } catch {
92629
92652
  console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
92630
92653
  process.exit(2);
@@ -92635,7 +92658,7 @@ async function installOpencodePlugin(port) {
92635
92658
  if (!hadErrata) {
92636
92659
  const inv = errataMcpInvocation();
92637
92660
  cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
92638
- writeFileSync27(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
92661
+ writeFileSync28(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
92639
92662
  }
92640
92663
  console.log(`installed OpenCode plugin \u2192 ${file2}`);
92641
92664
  if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
@@ -92662,15 +92685,15 @@ function ensureStatusLine(port) {
92662
92685
  }
92663
92686
  }
92664
92687
  async function installClaudeHooks(port) {
92665
- const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
92666
- const { join: join44 } = await import("node:path");
92667
- const dir = join44(ROOT, ".claude");
92668
- if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
92669
- const file2 = join44(dir, "settings.json");
92688
+ const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync38, writeFileSync: writeFileSync28 } = await import("node:fs");
92689
+ const { join: join45 } = await import("node:path");
92690
+ const dir = join45(ROOT, ".claude");
92691
+ if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
92692
+ const file2 = join45(dir, "settings.json");
92670
92693
  let settings = {};
92671
- if (existsSync36(file2)) {
92694
+ if (existsSync37(file2)) {
92672
92695
  try {
92673
- settings = JSON.parse(readFileSync37(file2, "utf8"));
92696
+ settings = JSON.parse(readFileSync38(file2, "utf8"));
92674
92697
  } catch {
92675
92698
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
92676
92699
  process.exit(2);
@@ -92718,11 +92741,11 @@ async function installClaudeHooks(port) {
92718
92741
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
92719
92742
  }
92720
92743
  removeProjectStatusLine(settings);
92721
- writeFileSync27(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
92744
+ writeFileSync28(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
92722
92745
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
92723
92746
  console.log(` ${ensureStatusLine(port)}`);
92724
92747
  await installClaudeMcpConfig();
92725
- const claudeMd = join44(ROOT, "CLAUDE.md");
92748
+ const claudeMd = join45(ROOT, "CLAUDE.md");
92726
92749
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
92727
92750
  if (recall.kind === "collision") {
92728
92751
  console.warn(
@@ -92734,15 +92757,15 @@ async function installClaudeHooks(port) {
92734
92757
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
92735
92758
  }
92736
92759
  async function installClaudeMcpConfig() {
92737
- const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
92738
- const { join: join44, dirname: dirname14 } = await import("node:path");
92739
- const file2 = join44(ROOT, ".mcp.json");
92760
+ const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync38, writeFileSync: writeFileSync28 } = await import("node:fs");
92761
+ const { join: join45, dirname: dirname14 } = await import("node:path");
92762
+ const file2 = join45(ROOT, ".mcp.json");
92740
92763
  const dir = dirname14(file2);
92741
- if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
92764
+ if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
92742
92765
  let cfg = {};
92743
- if (existsSync36(file2)) {
92766
+ if (existsSync37(file2)) {
92744
92767
  try {
92745
- cfg = JSON.parse(readFileSync37(file2, "utf8"));
92768
+ cfg = JSON.parse(readFileSync38(file2, "utf8"));
92746
92769
  } catch {
92747
92770
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
92748
92771
  process.exit(2);
@@ -92750,21 +92773,21 @@ async function installClaudeMcpConfig() {
92750
92773
  }
92751
92774
  cfg.mcpServers ??= {};
92752
92775
  cfg.mcpServers["errata"] = errataMcpInvocation();
92753
- writeFileSync27(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
92776
+ writeFileSync28(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
92754
92777
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
92755
92778
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
92756
92779
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
92757
92780
  }
92758
92781
  async function installCursorMcpConfig() {
92759
- const { mkdirSync: mkdirSync11, existsSync: existsSync36, readFileSync: readFileSync37, writeFileSync: writeFileSync27 } = await import("node:fs");
92760
- const { join: join44 } = await import("node:path");
92761
- const dir = join44(ROOT, ".cursor");
92762
- if (!existsSync36(dir)) mkdirSync11(dir, { recursive: true });
92763
- const file2 = join44(dir, "mcp.json");
92782
+ const { mkdirSync: mkdirSync11, existsSync: existsSync37, readFileSync: readFileSync38, writeFileSync: writeFileSync28 } = await import("node:fs");
92783
+ const { join: join45 } = await import("node:path");
92784
+ const dir = join45(ROOT, ".cursor");
92785
+ if (!existsSync37(dir)) mkdirSync11(dir, { recursive: true });
92786
+ const file2 = join45(dir, "mcp.json");
92764
92787
  let cfg = {};
92765
- if (existsSync36(file2)) {
92788
+ if (existsSync37(file2)) {
92766
92789
  try {
92767
- cfg = JSON.parse(readFileSync37(file2, "utf8"));
92790
+ cfg = JSON.parse(readFileSync38(file2, "utf8"));
92768
92791
  } catch {
92769
92792
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
92770
92793
  process.exit(2);
@@ -92772,7 +92795,7 @@ async function installCursorMcpConfig() {
92772
92795
  }
92773
92796
  cfg.mcpServers ??= {};
92774
92797
  cfg.mcpServers["errata"] = errataMcpInvocation();
92775
- writeFileSync27(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
92798
+ writeFileSync28(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
92776
92799
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
92777
92800
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
92778
92801
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -92783,7 +92806,7 @@ async function installCodexHooks(port) {
92783
92806
  const gitRoot = nearestGitRoot(process.cwd());
92784
92807
  const hookRoot = gitRoot && mainCheckoutOfWorktree(gitRoot) ? gitRoot : ROOT;
92785
92808
  const file2 = writeCodexHooks(hookRoot, port);
92786
- const instructions = writeManagedBlock(join43(hookRoot, "AGENTS.md"), {
92809
+ const instructions = writeManagedBlock(join44(hookRoot, "AGENTS.md"), {
92787
92810
  body: AGENTS_POINTER_BODY,
92788
92811
  stable: true
92789
92812
  });
@@ -93187,9 +93210,9 @@ async function cmdDash(args2) {
93187
93210
  await yieldToLoop2();
93188
93211
  try {
93189
93212
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile, {
93190
- atCommit: readGitRefState(join43(r.root, ".git")).sha ?? void 0
93213
+ atCommit: readGitRefState(join44(r.root, ".git")).sha ?? void 0
93191
93214
  });
93192
- const res = bleedRules(join43(r.root, ".claude", "rules"), items);
93215
+ const res = bleedRules(join44(r.root, ".claude", "rules"), items);
93193
93216
  if (res.written || res.pruned) {
93194
93217
  console.log(
93195
93218
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")