@inerrata-corporation/errata 2.0.0-dev.88 → 2.0.0-dev.90

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
@@ -919,6 +919,20 @@ function normalizeToolName(raw2) {
919
919
  function operatingSystemCanonicalId(name2) {
920
920
  return genericCanonicalId("OperatingSystem", { name: name2.trim().toLowerCase() });
921
921
  }
922
+ function osNameForPlatform(platform) {
923
+ switch (platform) {
924
+ case "win32":
925
+ return OS_NAME.windows;
926
+ case "darwin":
927
+ return OS_NAME.macos;
928
+ case "linux":
929
+ return OS_NAME.linux;
930
+ case "android":
931
+ return OS_NAME.android;
932
+ default:
933
+ return null;
934
+ }
935
+ }
922
936
  function packageCanonicalId(p) {
923
937
  const eco = p.ecosystem.toLowerCase();
924
938
  const name2 = eco === "npm" ? p.name.toLowerCase() : p.name;
@@ -939,7 +953,7 @@ function parsePackageRef(ref) {
939
953
  const slug2 = (version2 ? `${name2}@${version2}` : name2).toLowerCase();
940
954
  return { name: name2, version: version2, slug: slug2 };
941
955
  }
942
- var DESIGN_PROBLEM_PREFIX, DESIGN_PROBLEM_ID_LENGTH, DIAGNOSTIC_PROBLEM_PREFIX, DIAGNOSTIC_HASH_LENGTH, TRIAGE_PREFIX, TRIAGE_ID_LENGTH, SAFE_TOOL_NAME;
956
+ var DESIGN_PROBLEM_PREFIX, DESIGN_PROBLEM_ID_LENGTH, DIAGNOSTIC_PROBLEM_PREFIX, DIAGNOSTIC_HASH_LENGTH, TRIAGE_PREFIX, TRIAGE_ID_LENGTH, SAFE_TOOL_NAME, OS_NAME;
943
957
  var init_identity = __esm({
944
958
  "../../packages/shared/src/identity.ts"() {
945
959
  "use strict";
@@ -953,6 +967,12 @@ var init_identity = __esm({
953
967
  TRIAGE_PREFIX = "dtri_";
954
968
  TRIAGE_ID_LENGTH = 56;
955
969
  SAFE_TOOL_NAME = /^[a-z0-9][a-z0-9._+-]{0,63}$/;
970
+ OS_NAME = {
971
+ windows: "Windows",
972
+ macos: "macOS",
973
+ linux: "Linux",
974
+ android: "Android"
975
+ };
956
976
  }
957
977
  });
958
978
 
@@ -15894,6 +15914,7 @@ __export(src_exports, {
15894
15914
  MAX_NODES_PER_PAYLOAD: () => MAX_NODES_PER_PAYLOAD,
15895
15915
  MAX_SIDECAR_SYMBOLS: () => MAX_SIDECAR_SYMBOLS,
15896
15916
  MAX_SYMBOL_SUMMARY_CHARS: () => MAX_SYMBOL_SUMMARY_CHARS,
15917
+ OS_NAME: () => OS_NAME,
15897
15918
  PAGERANK_EXCLUSIONS: () => PAGERANK_EXCLUSIONS,
15898
15919
  PROBLEM_RESOLUTION: () => PROBLEM_RESOLUTION,
15899
15920
  PROJECT_ONLY_EDGE_TYPES: () => PROJECT_ONLY_EDGE_TYPES,
@@ -15951,6 +15972,7 @@ __export(src_exports, {
15951
15972
  normalizeToolName: () => normalizeToolName,
15952
15973
  npmPurl: () => npmPurl,
15953
15974
  operatingSystemCanonicalId: () => operatingSystemCanonicalId,
15975
+ osNameForPlatform: () => osNameForPlatform,
15954
15976
  packageCanonicalId: () => packageCanonicalId,
15955
15977
  pagerankEdgeTypes: () => pagerankEdgeTypes,
15956
15978
  parsePackageLockJson: () => parsePackageLockJson,
@@ -16002,7 +16024,7 @@ function writeManagedBlock(filePath, opts) {
16002
16024
  const newBody = opts.body.trim();
16003
16025
  const newHash = blockHash(newBody);
16004
16026
  const generated = opts.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
16005
- const startMarker = `<!-- ERRATA:START version=2 generated=${generated} hash=${newHash} -->`;
16027
+ const startMarker = opts.stable ? `<!-- ERRATA:START version=2 hash=${newHash} -->` : `<!-- ERRATA:START version=2 generated=${generated} hash=${newHash} -->`;
16006
16028
  const endMarker = `<!-- ERRATA:END -->`;
16007
16029
  const blockText = `${startMarker}
16008
16030
 
@@ -16031,6 +16053,9 @@ ${blockText}`, "utf8");
16031
16053
  if (expectedHash && expectedHash !== actualHash && !opts.force) {
16032
16054
  return { kind: "collision", expectedHash, actualHash };
16033
16055
  }
16056
+ if (opts.stable && existingBody === newBody && startM[0] === startMarker) {
16057
+ return { kind: "written", previousHash: actualHash, newHash };
16058
+ }
16034
16059
  const before = current.slice(0, startM.index);
16035
16060
  const after = current.slice(endM.index + endM[0].length).replace(/^\s*/, "");
16036
16061
  const written = after ? `${before}${blockText.trim()}
@@ -16040,21 +16065,6 @@ ${after}` : `${before}${blockText.trim()}
16040
16065
  writeFileSync(filePath, written, "utf8");
16041
16066
  return { kind: "written", previousHash: expectedHash ?? null, newHash };
16042
16067
  }
16043
- function readManagedBlock(filePath) {
16044
- if (!existsSync(filePath)) return null;
16045
- const current = readFileSync(filePath, "utf8");
16046
- const startM = current.match(START_RE);
16047
- const endM = current.match(END_RE);
16048
- if (!startM || !endM || startM.index === void 0 || endM.index === void 0) {
16049
- return null;
16050
- }
16051
- return current.slice(startM.index + startM[0].length, endM.index).trim();
16052
- }
16053
- function readManagedBlockWithHash(filePath) {
16054
- const body2 = readManagedBlock(filePath);
16055
- if (body2 === null) return null;
16056
- return { body: body2, hash: sha256(body2).slice(0, 16) };
16057
- }
16058
16068
  var START_RE, END_RE, blockHash;
16059
16069
  var init_agents_md = __esm({
16060
16070
  "../../packages/context-writer/src/agents-md.ts"() {
@@ -16066,9 +16076,57 @@ var init_agents_md = __esm({
16066
16076
  }
16067
16077
  });
16068
16078
 
16069
- // ../../packages/context-writer/src/redirectors.ts
16070
- import { existsSync as existsSync2, mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
16079
+ // ../../packages/context-writer/src/context-file.ts
16080
+ import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
16071
16081
  import { dirname, join } from "node:path";
16082
+ function contextFilePath(root) {
16083
+ return join(root, ".errata", "context.md");
16084
+ }
16085
+ function writeContextFile(root, body2) {
16086
+ const path2 = contextFilePath(root);
16087
+ mkdirSync(dirname(path2), { recursive: true });
16088
+ const text = `${body2.trim()}
16089
+ `;
16090
+ writeFileSync2(path2, text, "utf8");
16091
+ return contextHash(text);
16092
+ }
16093
+ function contextHash(body2) {
16094
+ return sha256(body2.replace(/\r\n?/g, "\n").trim()).slice(0, 16);
16095
+ }
16096
+ function readContextFileWithHash(root) {
16097
+ const path2 = contextFilePath(root);
16098
+ if (!existsSync2(path2)) return null;
16099
+ try {
16100
+ const raw2 = readFileSync2(path2, "utf8");
16101
+ const body2 = raw2.trim();
16102
+ if (!body2) return null;
16103
+ return { body: body2, hash: contextHash(raw2) };
16104
+ } catch {
16105
+ return null;
16106
+ }
16107
+ }
16108
+ var AGENTS_POINTER_BODY;
16109
+ var init_context_file = __esm({
16110
+ "../../packages/context-writer/src/context-file.ts"() {
16111
+ "use strict";
16112
+ init_src();
16113
+ AGENTS_POINTER_BODY = [
16114
+ "## Errata context",
16115
+ "",
16116
+ "Live agent context for this checkout \u2014 priors, open problems, the capture",
16117
+ "protocol \u2014 is maintained by the errata daemon at `.errata/context.md`.",
16118
+ "",
16119
+ "It is gitignored ON PURPOSE: it is this machine's runtime state, not repo",
16120
+ "content. Committing it would prime your teammates with your graph.",
16121
+ "",
16122
+ "@.errata/context.md"
16123
+ ].join("\n");
16124
+ }
16125
+ });
16126
+
16127
+ // ../../packages/context-writer/src/redirectors.ts
16128
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
16129
+ import { dirname as dirname2, join as join2 } from "node:path";
16072
16130
  function defaultRedirectors() {
16073
16131
  return [
16074
16132
  {
@@ -16100,13 +16158,13 @@ function installRedirectors(workspaceRoot, redirectors = defaultRedirectors()) {
16100
16158
  const written = [];
16101
16159
  const skipped = [];
16102
16160
  for (const r of redirectors) {
16103
- const abs = join(workspaceRoot, r.relPath);
16104
- if (existsSync2(abs)) {
16161
+ const abs = join2(workspaceRoot, r.relPath);
16162
+ if (existsSync3(abs)) {
16105
16163
  skipped.push(r.relPath);
16106
16164
  continue;
16107
16165
  }
16108
- mkdirSync(dirname(abs), { recursive: true });
16109
- writeFileSync2(abs, r.content, "utf8");
16166
+ mkdirSync2(dirname2(abs), { recursive: true });
16167
+ writeFileSync3(abs, r.content, "utf8");
16110
16168
  written.push(r.relPath);
16111
16169
  }
16112
16170
  return { written, skipped };
@@ -20352,6 +20410,100 @@ var init_problem_dedup = __esm({
20352
20410
  }
20353
20411
  });
20354
20412
 
20413
+ // ../../packages/local-graph/src/tools.ts
20414
+ function toolNodeId(name2) {
20415
+ return `tool:${name2}`;
20416
+ }
20417
+ function osNodeId(name2) {
20418
+ return `os:${name2.toLowerCase()}`;
20419
+ }
20420
+ function resolveOsNode(store, osName, ts) {
20421
+ const id = osNodeId(osName);
20422
+ const existing = store.getNode(id);
20423
+ if (existing) return existing;
20424
+ const node2 = {
20425
+ id,
20426
+ label: "OperatingSystem",
20427
+ description: osName,
20428
+ extractionConfidence: 1,
20429
+ extractionSource: "daemon-extracted",
20430
+ embedding: [],
20431
+ cumulativeSurprise: 0,
20432
+ peakSurprise: 0,
20433
+ cumulativeHits: 0,
20434
+ lastUpdatedAt: ts,
20435
+ createdAt: ts,
20436
+ memoryTier: "short-term",
20437
+ pageRank: 0,
20438
+ isLandmark: false,
20439
+ community: null,
20440
+ stability: "stable",
20441
+ attrs: { name: osName, canonicalId: operatingSystemCanonicalId(osName), public: true }
20442
+ };
20443
+ store.mergeNode(node2);
20444
+ return node2;
20445
+ }
20446
+ function stampObservedOs(store, nodeId, osName, ts) {
20447
+ if (!osName || !store.getNode(nodeId)) return false;
20448
+ const os2 = resolveOsNode(store, osName, ts);
20449
+ const already = store.outEdges(nodeId, ["OCCURS_ON"]).some((e) => e.to === os2.id);
20450
+ if (already) return true;
20451
+ store.mergeEdge({
20452
+ id: `edge_${digest({ from: nodeId, type: "OCCURS_ON", to: os2.id })}`.slice(0, 24),
20453
+ from: nodeId,
20454
+ to: os2.id,
20455
+ type: "OCCURS_ON",
20456
+ confidence: 1,
20457
+ // observed, not inferred — we ran on this platform
20458
+ extractionSource: "daemon-extracted",
20459
+ createdAt: ts,
20460
+ lastSeenAt: ts,
20461
+ navSuccesses: 0,
20462
+ navFailures: 0,
20463
+ attrs: { observed: true }
20464
+ });
20465
+ return true;
20466
+ }
20467
+ function rankToolsForHandles(store, limit = 5) {
20468
+ const scored = store.findNodesByLabel("Tool").map((node2) => ({
20469
+ node: node2,
20470
+ concerns: store.inEdges(node2.id, ["CONCERNS"]).length,
20471
+ hits: node2.cumulativeHits ?? 0
20472
+ }));
20473
+ scored.sort((a, b) => b.concerns - a.concerns || b.hits - a.hits);
20474
+ return scored.slice(0, Math.max(0, limit)).map((s) => s.node);
20475
+ }
20476
+ function toolPriorsFor(store, toolName, ctx, limit = 4) {
20477
+ const tool = store.getNode(toolNodeId(toolName));
20478
+ if (!tool) return [];
20479
+ const pkgs = ctx.workspacePackageIds ?? /* @__PURE__ */ new Set();
20480
+ const fits = [];
20481
+ for (const e of store.inEdges(tool.id, ["CONCERNS"])) {
20482
+ const node2 = store.getNode(e.from);
20483
+ if (!node2) continue;
20484
+ if (node2.attrs["resolvedAs"] === "false_positive") continue;
20485
+ const observedOn = store.outEdges(node2.id, ["OCCURS_ON"]).map((oe) => store.getNode(oe.to)?.description).filter((d) => !!d);
20486
+ const osMismatch = observedOn.length > 0 && !!ctx.os && !observedOn.includes(ctx.os);
20487
+ const deps = store.outEdges(node2.id, ["DEPENDS_ON"]).map((de) => de.to);
20488
+ const stackHits = [];
20489
+ const stackMisses = [];
20490
+ for (const d of deps) {
20491
+ const name2 = String(store.getNode(d)?.attrs["name"] ?? d);
20492
+ (pkgs.has(d) ? stackHits : stackMisses).push(name2);
20493
+ }
20494
+ fits.push({ node: node2, observedOn, osMismatch, stackHits, stackMisses });
20495
+ }
20496
+ const rank = (f) => (f.osMismatch ? 0 : 2) + (f.stackHits.length > 0 ? 1 : 0);
20497
+ fits.sort((a, b) => rank(b) - rank(a) || (b.node.cumulativeHits ?? 0) - (a.node.cumulativeHits ?? 0));
20498
+ return fits.slice(0, Math.max(0, limit));
20499
+ }
20500
+ var init_tools = __esm({
20501
+ "../../packages/local-graph/src/tools.ts"() {
20502
+ "use strict";
20503
+ init_src();
20504
+ }
20505
+ });
20506
+
20355
20507
  // ../../packages/local-graph/src/principle-sync.ts
20356
20508
  function asStrings(v) {
20357
20509
  return Array.isArray(v) ? v : [];
@@ -20514,6 +20666,7 @@ __export(src_exports2, {
20514
20666
  mergeDuplicateProblems: () => mergeDuplicateProblems,
20515
20667
  mintPatternNode: () => mintPatternNode,
20516
20668
  openGraphStore: () => openGraphStore,
20669
+ osNodeId: () => osNodeId,
20517
20670
  parseAbstractionFences: () => parseAbstractionFences,
20518
20671
  parseSemver: () => parseSemver,
20519
20672
  parseTriageFences: () => parseTriageFences,
@@ -20522,6 +20675,7 @@ __export(src_exports2, {
20522
20675
  priorsForFile: () => priorsForFile,
20523
20676
  propagateFactChange: () => propagateFactChange,
20524
20677
  propagateVersionChange: () => propagateVersionChange,
20678
+ rankToolsForHandles: () => rankToolsForHandles,
20525
20679
  recordAnchorHint: () => recordAnchorHint,
20526
20680
  recordClaim: () => recordClaim,
20527
20681
  recordMisreadPrior: () => recordMisreadPrior,
@@ -20531,13 +20685,17 @@ __export(src_exports2, {
20531
20685
  resolveDesignProblemById: () => resolveDesignProblemById,
20532
20686
  resolveDesignProblemByStatement: () => resolveDesignProblemByStatement,
20533
20687
  resolveDesignProblems: () => resolveDesignProblems,
20688
+ resolveOsNode: () => resolveOsNode,
20534
20689
  retractDesignProblemById: () => retractDesignProblemById,
20535
20690
  retractDesignProblemByStatement: () => retractDesignProblemByStatement,
20536
20691
  revisitContradictedPrinciples: () => revisitContradictedPrinciples,
20537
20692
  revisitStaleRoutes: () => revisitStaleRoutes,
20538
20693
  solutionForProblem: () => solutionForProblem,
20539
20694
  splittingAxis: () => splittingAxis,
20695
+ stampObservedOs: () => stampObservedOs,
20540
20696
  staticConductance: () => staticConductance,
20697
+ toolNodeId: () => toolNodeId,
20698
+ toolPriorsFor: () => toolPriorsFor,
20541
20699
  triageOf: () => triageOf,
20542
20700
  walk: () => walk
20543
20701
  });
@@ -20560,6 +20718,7 @@ var init_src4 = __esm({
20560
20718
  init_triage2();
20561
20719
  init_problem_dedup();
20562
20720
  init_problem_package_link();
20721
+ init_tools();
20563
20722
  init_principle_sync();
20564
20723
  }
20565
20724
  });
@@ -20628,7 +20787,7 @@ function buildSnapshot(opts) {
20628
20787
  };
20629
20788
  const langNodes = opts.store.findNodesByLabel("Language");
20630
20789
  const pkgNodes = opts.store.findNodesByLabel("Package");
20631
- const toolNodes = opts.store.findNodesByLabel("Tool").sort((a, b) => (b.cumulativeHits ?? 0) - (a.cumulativeHits ?? 0)).slice(0, 5);
20790
+ const toolNodes = rankToolsForHandles(opts.store, 5);
20632
20791
  const profileContext = {
20633
20792
  languages: opts.profile.languages.map((name2) => ({ name: name2, node: matchNode(langNodes, name2) })),
20634
20793
  packages: opts.profile.stack.map((name2) => ({ name: name2, node: matchNode(pkgNodes, pkgBase(name2)) })),
@@ -20995,8 +21154,8 @@ var init_bleed_memory = __esm({
20995
21154
  });
20996
21155
 
20997
21156
  // ../../packages/context-writer/src/bleed-rules.ts
20998
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync, readFileSync as readFileSync2, rmSync, writeFileSync as writeFileSync3 } from "node:fs";
20999
- import { join as join2 } from "node:path";
21157
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync4 } from "node:fs";
21158
+ import { join as join3 } from "node:path";
21000
21159
  function formatRuleFile(item) {
21001
21160
  const frontmatter = item.paths && item.paths.length > 0 ? `---
21002
21161
  paths:
@@ -21009,21 +21168,21 @@ ${item.body.trim()}
21009
21168
  `;
21010
21169
  }
21011
21170
  function bleedRules(rulesDir, items) {
21012
- if (!existsSync3(rulesDir)) mkdirSync2(rulesDir, { recursive: true });
21171
+ if (!existsSync4(rulesDir)) mkdirSync3(rulesDir, { recursive: true });
21013
21172
  const wanted = new Map(items.map((i2) => [fileFor(i2.slug), i2]));
21014
21173
  let written = 0;
21015
21174
  let created = 0;
21016
21175
  for (const [file2, item] of wanted) {
21017
- const path2 = join2(rulesDir, file2);
21018
- if (!existsSync3(path2)) created++;
21019
- writeFileSync3(path2, formatRuleFile(item), "utf8");
21176
+ const path2 = join3(rulesDir, file2);
21177
+ if (!existsSync4(path2)) created++;
21178
+ writeFileSync4(path2, formatRuleFile(item), "utf8");
21020
21179
  written++;
21021
21180
  }
21022
21181
  let pruned = 0;
21023
21182
  for (const f of readdirSync(rulesDir)) {
21024
21183
  if (!f.startsWith(PREFIX) || !f.endsWith(".md") || wanted.has(f)) continue;
21025
- if (readFileSync2(join2(rulesDir, f), "utf8").includes(MARKER)) {
21026
- rmSync(join2(rulesDir, f));
21184
+ if (readFileSync3(join3(rulesDir, f), "utf8").includes(MARKER)) {
21185
+ rmSync(join3(rulesDir, f));
21027
21186
  pruned++;
21028
21187
  }
21029
21188
  }
@@ -21110,6 +21269,7 @@ var init_src5 = __esm({
21110
21269
  "../../packages/context-writer/src/index.ts"() {
21111
21270
  "use strict";
21112
21271
  init_agents_md();
21272
+ init_context_file();
21113
21273
  init_redirectors();
21114
21274
  init_render();
21115
21275
  init_bleed_memory();
@@ -22027,34 +22187,34 @@ __export(paths_exports, {
22027
22187
  workspaceDir: () => workspaceDir,
22028
22188
  workspacePaths: () => workspacePaths
22029
22189
  });
22030
- import { mkdirSync as mkdirSync3 } from "node:fs";
22031
- import { dirname as dirname2, join as join3 } from "node:path";
22190
+ import { mkdirSync as mkdirSync4 } from "node:fs";
22191
+ import { dirname as dirname3, join as join4 } from "node:path";
22032
22192
  function globalDir() {
22033
22193
  const p = envPaths("errata", { suffix: "" });
22034
22194
  return p.config;
22035
22195
  }
22036
22196
  function globalConfigPath() {
22037
- return process.env["ERRATA_CONFIG_PATH"] ?? join3(globalDir(), "config.json");
22197
+ return process.env["ERRATA_CONFIG_PATH"] ?? join4(globalDir(), "config.json");
22038
22198
  }
22039
22199
  function daemonLogPath() {
22040
- mkdirSync3(globalDir(), { recursive: true });
22041
- return join3(globalDir(), "daemon.log");
22200
+ mkdirSync4(globalDir(), { recursive: true });
22201
+ return join4(globalDir(), "daemon.log");
22042
22202
  }
22043
22203
  function globalDaemonLock() {
22044
- return process.env["ERRATA_DAEMON_LOCK"] ?? join3(globalDir(), "daemon.lock");
22204
+ return process.env["ERRATA_DAEMON_LOCK"] ?? join4(globalDir(), "daemon.lock");
22045
22205
  }
22046
22206
  function sharedStorePath() {
22047
- return process.env["ERRATA_SHARED_DB"] ?? join3(globalDir(), "shared", "graph.db");
22207
+ return process.env["ERRATA_SHARED_DB"] ?? join4(globalDir(), "shared", "graph.db");
22048
22208
  }
22049
22209
  function workspaceDir(workspaceRoot) {
22050
- return join3(workspaceRoot, ".errata");
22210
+ return join4(workspaceRoot, ".errata");
22051
22211
  }
22052
22212
  function ensureDir(p) {
22053
- mkdirSync3(p, { recursive: true });
22213
+ mkdirSync4(p, { recursive: true });
22054
22214
  return p;
22055
22215
  }
22056
22216
  function ensureParent(p) {
22057
- mkdirSync3(dirname2(p), { recursive: true });
22217
+ mkdirSync4(dirname3(p), { recursive: true });
22058
22218
  return p;
22059
22219
  }
22060
22220
  function workspacePaths(root) {
@@ -22062,15 +22222,15 @@ function workspacePaths(root) {
22062
22222
  return {
22063
22223
  root,
22064
22224
  configDir: dir,
22065
- workspaceJson: join3(dir, "workspace.json"),
22066
- eventLog: join3(dir, "eventlog.sqlite"),
22067
- castalia: join3(dir, "castalia.db"),
22068
- reviewQueue: join3(dir, "review-queue.json"),
22069
- outbox: join3(dir, "outbox"),
22070
- daemonLock: join3(dir, "daemon.lock"),
22071
- identityAudit: join3(dir, "identity-audit.log"),
22072
- skillsDir: join3(dir, "skills"),
22073
- skillsManifest: join3(dir, "skills.json")
22225
+ workspaceJson: join4(dir, "workspace.json"),
22226
+ eventLog: join4(dir, "eventlog.sqlite"),
22227
+ castalia: join4(dir, "castalia.db"),
22228
+ reviewQueue: join4(dir, "review-queue.json"),
22229
+ outbox: join4(dir, "outbox"),
22230
+ daemonLock: join4(dir, "daemon.lock"),
22231
+ identityAudit: join4(dir, "identity-audit.log"),
22232
+ skillsDir: join4(dir, "skills"),
22233
+ skillsManifest: join4(dir, "skills.json")
22074
22234
  };
22075
22235
  }
22076
22236
  var init_paths = __esm({
@@ -22081,7 +22241,7 @@ var init_paths = __esm({
22081
22241
  });
22082
22242
 
22083
22243
  // src/config.ts
22084
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
22244
+ import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "node:fs";
22085
22245
  import { randomUUID as randomUUID2 } from "node:crypto";
22086
22246
  function defaultConfig() {
22087
22247
  return {
@@ -22107,13 +22267,13 @@ function defaultConfig() {
22107
22267
  }
22108
22268
  function loadConfig() {
22109
22269
  const p = globalConfigPath();
22110
- if (!existsSync4(p)) {
22270
+ if (!existsSync5(p)) {
22111
22271
  ensureDir(globalDir());
22112
22272
  const cfg = defaultConfig();
22113
22273
  saveConfig({ ...cfg, cloudUrl: DEFAULT_CLOUD_URL });
22114
22274
  return cfg;
22115
22275
  }
22116
- const raw2 = readFileSync3(p, "utf8").replace(/^\uFEFF/, "");
22276
+ const raw2 = readFileSync4(p, "utf8").replace(/^\uFEFF/, "");
22117
22277
  const parsed = JSON.parse(raw2);
22118
22278
  const base = defaultConfig();
22119
22279
  const envCloudUrl = process.env["ERRATA_CLOUD_URL"];
@@ -22134,7 +22294,7 @@ function loadConfig() {
22134
22294
  }
22135
22295
  function saveConfig(cfg) {
22136
22296
  ensureDir(globalDir());
22137
- writeFileSync4(globalConfigPath(), JSON.stringify(cfg, null, 2), { encoding: "utf8", mode: 384 });
22297
+ writeFileSync5(globalConfigPath(), JSON.stringify(cfg, null, 2), { encoding: "utf8", mode: 384 });
22138
22298
  }
22139
22299
  function machineId() {
22140
22300
  const fromEnv = process.env["ERRATA_MACHINE_ID"];
@@ -24766,17 +24926,17 @@ var init_agent_signals = __esm({
24766
24926
  });
24767
24927
 
24768
24928
  // src/review.ts
24769
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "node:fs";
24929
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
24770
24930
  function loadReviewQueue(paths) {
24771
- if (!existsSync5(paths.reviewQueue)) return [];
24931
+ if (!existsSync6(paths.reviewQueue)) return [];
24772
24932
  try {
24773
- return JSON.parse(readFileSync4(paths.reviewQueue, "utf8"));
24933
+ return JSON.parse(readFileSync5(paths.reviewQueue, "utf8"));
24774
24934
  } catch {
24775
24935
  return [];
24776
24936
  }
24777
24937
  }
24778
24938
  function saveReviewQueue(paths, queue) {
24779
- writeFileSync5(paths.reviewQueue, JSON.stringify(queue, null, 2), "utf8");
24939
+ writeFileSync6(paths.reviewQueue, JSON.stringify(queue, null, 2), "utf8");
24780
24940
  }
24781
24941
  function addProposal(paths, store, node2, reason, surprise) {
24782
24942
  const queue = loadReviewQueue(paths);
@@ -25374,9 +25534,9 @@ var init_dual_augment = __esm({
25374
25534
  });
25375
25535
 
25376
25536
  // ../../packages/embedding/src/model.ts
25377
- import { mkdirSync as mkdirSync4, existsSync as existsSync6 } from "node:fs";
25537
+ import { mkdirSync as mkdirSync5, existsSync as existsSync7 } from "node:fs";
25378
25538
  import { homedir as homedir2 } from "node:os";
25379
- import { dirname as dirname3, join as join4 } from "node:path";
25539
+ import { dirname as dirname4, join as join5 } from "node:path";
25380
25540
  import { createRequire } from "node:module";
25381
25541
  function semanticFloorFor(version2) {
25382
25542
  if (version2 === EMBEDDING_VERSION || version2 === MODEL_EMBEDDING_VERSION) return 0.25;
@@ -25391,7 +25551,7 @@ function noteHashFallback() {
25391
25551
  );
25392
25552
  }
25393
25553
  function getCacheDir() {
25394
- return process.env["ERRATA_MODEL_CACHE"] ?? join4(homedir2(), ".errata", "models");
25554
+ return process.env["ERRATA_MODEL_CACHE"] ?? join5(homedir2(), ".errata", "models");
25395
25555
  }
25396
25556
  async function loadTransformers() {
25397
25557
  try {
@@ -25400,9 +25560,9 @@ async function loadTransformers() {
25400
25560
  void err2;
25401
25561
  }
25402
25562
  try {
25403
- const seaResourceBase = join4(
25563
+ const seaResourceBase = join5(
25404
25564
  // execPath dir is where errata.exe lives; resources/ rides alongside.
25405
- dirname3(process.execPath),
25565
+ dirname4(process.execPath),
25406
25566
  "resources",
25407
25567
  "_resolve.js"
25408
25568
  );
@@ -25415,7 +25575,7 @@ async function loadTransformers() {
25415
25575
  }
25416
25576
  async function loadPipeline() {
25417
25577
  const cacheDir = getCacheDir();
25418
- if (!existsSync6(cacheDir)) mkdirSync4(cacheDir, { recursive: true });
25578
+ if (!existsSync7(cacheDir)) mkdirSync5(cacheDir, { recursive: true });
25419
25579
  try {
25420
25580
  const tx = await loadTransformers();
25421
25581
  if (!tx) {
@@ -25705,7 +25865,7 @@ var init_diagnostic_matcher = __esm({
25705
25865
  });
25706
25866
 
25707
25867
  // ../../packages/generalizer/src/generalizer.ts
25708
- import { isAbsolute, join as join5, relative } from "node:path";
25868
+ import { isAbsolute, join as join6, relative } from "node:path";
25709
25869
  async function runGeneralizer(opts) {
25710
25870
  const report = {
25711
25871
  eventsProcessed: 0,
@@ -25813,7 +25973,7 @@ function extractDiagnostics(ev) {
25813
25973
  function diagRelPath(file2, cwd, workspaceRoot) {
25814
25974
  const norm = (p) => p.replace(/\\/g, "/");
25815
25975
  if (!workspaceRoot) return norm(file2);
25816
- const abs = isAbsolute(file2) ? file2 : join5(cwd ?? workspaceRoot, file2);
25976
+ const abs = isAbsolute(file2) ? file2 : join6(cwd ?? workspaceRoot, file2);
25817
25977
  return norm(relative(workspaceRoot, abs));
25818
25978
  }
25819
25979
  function extractErrorSignature(ev) {
@@ -27185,16 +27345,16 @@ var init_src10 = __esm({
27185
27345
  });
27186
27346
 
27187
27347
  // src/symbol-summaries.ts
27188
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
27189
- import { join as join6 } from "node:path";
27348
+ import { existsSync as existsSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "node:fs";
27349
+ import { join as join7 } from "node:path";
27190
27350
  function symbolSummariesPath(configDir) {
27191
- return join6(configDir, "symbol-summaries.json");
27351
+ return join7(configDir, "symbol-summaries.json");
27192
27352
  }
27193
27353
  function loadSymbolSummaryCache(configDir) {
27194
27354
  const p = symbolSummariesPath(configDir);
27195
- if (existsSync7(p)) {
27355
+ if (existsSync8(p)) {
27196
27356
  try {
27197
- const raw2 = JSON.parse(readFileSync5(p, "utf8"));
27357
+ const raw2 = JSON.parse(readFileSync6(p, "utf8"));
27198
27358
  if (raw2 && raw2.version === 1 && raw2.entries && typeof raw2.entries === "object") {
27199
27359
  return { version: 1, entries: raw2.entries };
27200
27360
  }
@@ -27204,7 +27364,7 @@ function loadSymbolSummaryCache(configDir) {
27204
27364
  return { version: 1, entries: {} };
27205
27365
  }
27206
27366
  function saveSymbolSummaryCache(configDir, cache) {
27207
- writeFileSync6(symbolSummariesPath(configDir), JSON.stringify(cache, null, 2), "utf8");
27367
+ writeFileSync7(symbolSummariesPath(configDir), JSON.stringify(cache, null, 2), "utf8");
27208
27368
  }
27209
27369
  function summariesByBodyHash(cache) {
27210
27370
  const m = /* @__PURE__ */ new Map();
@@ -27278,7 +27438,7 @@ function readSnippet(workspaceRoot, attrs) {
27278
27438
  return void 0;
27279
27439
  }
27280
27440
  try {
27281
- const buf = readFileSync5(join6(workspaceRoot, ...relPath.split("/")));
27441
+ const buf = readFileSync6(join7(workspaceRoot, ...relPath.split("/")));
27282
27442
  const slice = buf.subarray(Math.max(0, startByte), Math.min(buf.length, endByte));
27283
27443
  const text = slice.toString("utf8");
27284
27444
  return text.length > MAX_SNIPPET_CHARS ? text.slice(0, MAX_SNIPPET_CHARS) : text;
@@ -27578,9 +27738,9 @@ var init_identity2 = __esm({
27578
27738
  });
27579
27739
 
27580
27740
  // ../../packages/indexer/src/pipeline.ts
27581
- import { appendFileSync, readFileSync as readFileSync6, statSync } from "node:fs";
27741
+ import { appendFileSync, readFileSync as readFileSync7, statSync } from "node:fs";
27582
27742
  import { readdir } from "node:fs/promises";
27583
- import { extname, join as join7, relative as relative2, sep } from "node:path";
27743
+ import { extname, join as join8, relative as relative2, sep } from "node:path";
27584
27744
  import { createHash as createHash3 } from "node:crypto";
27585
27745
  import { execFileSync } from "node:child_process";
27586
27746
  function nowTs() {
@@ -27713,7 +27873,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
27713
27873
  for (const rel of [...changedRelPaths]) {
27714
27874
  let h;
27715
27875
  try {
27716
- h = createHash3("sha256").update(readFileSync6(join7(rootPath, rel))).digest("hex");
27876
+ h = createHash3("sha256").update(readFileSync7(join8(rootPath, rel))).digest("hex");
27717
27877
  } catch {
27718
27878
  continue;
27719
27879
  }
@@ -27760,13 +27920,13 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
27760
27920
  let parsedFiles = 0;
27761
27921
  for (const rel of changedRelPaths) {
27762
27922
  if (parsedFiles++ > 0) await new Promise((r2) => setImmediate(r2));
27763
- const abs = join7(rootPath, ...rel.split("/"));
27923
+ const abs = join8(rootPath, ...rel.split("/"));
27764
27924
  const ext = extname(abs).toLowerCase();
27765
27925
  const provider = providers.find((p) => p.fileExtensions.includes(ext));
27766
27926
  if (!provider) continue;
27767
27927
  let symbols;
27768
27928
  try {
27769
- symbols = provider.extractSymbols(readFileSync6(abs, "utf8"), abs);
27929
+ symbols = provider.extractSymbols(readFileSync7(abs, "utf8"), abs);
27770
27930
  } catch {
27771
27931
  continue;
27772
27932
  }
@@ -28072,7 +28232,7 @@ async function runIndexer(store, opts) {
28072
28232
  report.filesSkipped++;
28073
28233
  continue;
28074
28234
  }
28075
- source = readFileSync6(f.absPath, "utf8");
28235
+ source = readFileSync7(f.absPath, "utf8");
28076
28236
  } catch {
28077
28237
  report.filesSkipped++;
28078
28238
  continue;
@@ -28130,7 +28290,7 @@ async function runIndexer(store, opts) {
28130
28290
  const depth = fileNode.relPath.split("/").length;
28131
28291
  if (depth !== 3) continue;
28132
28292
  try {
28133
- const pkg = JSON.parse(readFileSync6(fileNode.absPath, "utf8"));
28293
+ const pkg = JSON.parse(readFileSync7(fileNode.absPath, "utf8"));
28134
28294
  if (!pkg.name) continue;
28135
28295
  const pkgDir = fileNode.relPath.replace(/\/package\.json$/, "");
28136
28296
  const candidates = [
@@ -28512,7 +28672,7 @@ async function scan(root, current, ignores, providers, out2) {
28512
28672
  for (const ent of entries) {
28513
28673
  if (ignores.has(ent.name)) continue;
28514
28674
  if (ent.name.startsWith(".") && ent.name !== ".") continue;
28515
- const abs = join7(current, ent.name);
28675
+ const abs = join8(current, ent.name);
28516
28676
  if (ent.isDirectory()) {
28517
28677
  await scan(root, abs, ignores, providers, out2);
28518
28678
  } else if (ent.isFile()) {
@@ -28558,7 +28718,7 @@ function gitListFiles(root, ignores, providers) {
28558
28718
  if (segs.some((s) => ignores.has(s) || s.startsWith(".") && s.length > 1)) {
28559
28719
  continue;
28560
28720
  }
28561
- const abs = join7(root, rel);
28721
+ const abs = join8(root, rel);
28562
28722
  let size;
28563
28723
  try {
28564
28724
  size = statSync(abs).size;
@@ -28581,7 +28741,7 @@ function upsertFile(store, id, f, workspaceId2) {
28581
28741
  const now = nowTs();
28582
28742
  let contentHash;
28583
28743
  try {
28584
- contentHash = createHash3("sha256").update(readFileSync6(f.absPath)).digest("hex");
28744
+ contentHash = createHash3("sha256").update(readFileSync7(f.absPath)).digest("hex");
28585
28745
  } catch {
28586
28746
  }
28587
28747
  const node2 = {
@@ -32944,42 +33104,42 @@ ${JSON.stringify(symbolNames, null, 2)}`);
32944
33104
 
32945
33105
  // ../../packages/indexer/src/languages/tree-sitter-loader.ts
32946
33106
  import { fileURLToPath } from "node:url";
32947
- import { dirname as dirname4, join as join8 } from "node:path";
32948
- import { existsSync as existsSync8, readdirSync as readdirSync2 } from "node:fs";
33107
+ import { dirname as dirname5, join as join9 } from "node:path";
33108
+ import { existsSync as existsSync9, readdirSync as readdirSync2 } from "node:fs";
32949
33109
  import { createRequire as createRequire2 } from "node:module";
32950
33110
  function entryDir() {
32951
33111
  try {
32952
33112
  const url2 = import.meta?.url;
32953
33113
  if (typeof url2 === "string" && url2.length > 0) {
32954
- return dirname4(fileURLToPath(url2));
33114
+ return dirname5(fileURLToPath(url2));
32955
33115
  }
32956
33116
  } catch {
32957
33117
  }
32958
- return dirname4(process.execPath);
33118
+ return dirname5(process.execPath);
32959
33119
  }
32960
33120
  function findWasmDir() {
32961
33121
  const here = entryDir();
32962
- const seaWasm = join8(here, "resources", "wasm");
32963
- if (existsSync8(join8(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
33122
+ const seaWasm = join9(here, "resources", "wasm");
33123
+ if (existsSync9(join9(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
32964
33124
  let dir = here;
32965
33125
  for (let i2 = 0; i2 < 6; i2++) {
32966
- const flat = join8(
33126
+ const flat = join9(
32967
33127
  dir,
32968
33128
  "node_modules",
32969
33129
  "@vscode",
32970
33130
  "tree-sitter-wasm",
32971
33131
  "wasm"
32972
33132
  );
32973
- if (existsSync8(join8(flat, "tree-sitter-typescript.wasm"))) return flat;
32974
- dir = dirname4(dir);
33133
+ if (existsSync9(join9(flat, "tree-sitter-typescript.wasm"))) return flat;
33134
+ dir = dirname5(dir);
32975
33135
  }
32976
33136
  let root = here;
32977
33137
  for (let i2 = 0; i2 < 6; i2++) {
32978
- const pnpmDir = join8(root, "node_modules", ".pnpm");
32979
- if (existsSync8(pnpmDir)) {
33138
+ const pnpmDir = join9(root, "node_modules", ".pnpm");
33139
+ if (existsSync9(pnpmDir)) {
32980
33140
  for (const entry of readdirSync2(pnpmDir)) {
32981
33141
  if (entry.startsWith("@vscode+tree-sitter-wasm@")) {
32982
- const candidate = join8(
33142
+ const candidate = join9(
32983
33143
  pnpmDir,
32984
33144
  entry,
32985
33145
  "node_modules",
@@ -32987,13 +33147,13 @@ function findWasmDir() {
32987
33147
  "tree-sitter-wasm",
32988
33148
  "wasm"
32989
33149
  );
32990
- if (existsSync8(join8(candidate, "tree-sitter-typescript.wasm"))) {
33150
+ if (existsSync9(join9(candidate, "tree-sitter-typescript.wasm"))) {
32991
33151
  return candidate;
32992
33152
  }
32993
33153
  }
32994
33154
  }
32995
33155
  }
32996
- root = dirname4(root);
33156
+ root = dirname5(root);
32997
33157
  }
32998
33158
  throw new Error(
32999
33159
  "@vscode/tree-sitter-wasm grammar files not found \u2014 is the package installed?"
@@ -33001,33 +33161,33 @@ function findWasmDir() {
33001
33161
  }
33002
33162
  function findRuntimeDir() {
33003
33163
  const here = entryDir();
33004
- const seaRuntime = join8(here, "resources", "wasm");
33005
- if (existsSync8(join8(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
33164
+ const seaRuntime = join9(here, "resources", "wasm");
33165
+ if (existsSync9(join9(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
33006
33166
  let dir = here;
33007
33167
  for (let i2 = 0; i2 < 6; i2++) {
33008
- const flat = join8(dir, "node_modules", "web-tree-sitter");
33009
- if (existsSync8(join8(flat, "web-tree-sitter.wasm"))) return flat;
33010
- dir = dirname4(dir);
33168
+ const flat = join9(dir, "node_modules", "web-tree-sitter");
33169
+ if (existsSync9(join9(flat, "web-tree-sitter.wasm"))) return flat;
33170
+ dir = dirname5(dir);
33011
33171
  }
33012
33172
  let root = here;
33013
33173
  for (let i2 = 0; i2 < 6; i2++) {
33014
- const pnpmDir = join8(root, "node_modules", ".pnpm");
33015
- if (existsSync8(pnpmDir)) {
33174
+ const pnpmDir = join9(root, "node_modules", ".pnpm");
33175
+ if (existsSync9(pnpmDir)) {
33016
33176
  for (const entry of readdirSync2(pnpmDir)) {
33017
33177
  if (entry.startsWith("web-tree-sitter@")) {
33018
- const candidate = join8(
33178
+ const candidate = join9(
33019
33179
  pnpmDir,
33020
33180
  entry,
33021
33181
  "node_modules",
33022
33182
  "web-tree-sitter"
33023
33183
  );
33024
- if (existsSync8(join8(candidate, "web-tree-sitter.wasm"))) {
33184
+ if (existsSync9(join9(candidate, "web-tree-sitter.wasm"))) {
33025
33185
  return candidate;
33026
33186
  }
33027
33187
  }
33028
33188
  }
33029
33189
  }
33030
- root = dirname4(root);
33190
+ root = dirname5(root);
33031
33191
  }
33032
33192
  throw new Error("web-tree-sitter runtime WASM not found");
33033
33193
  }
@@ -33038,7 +33198,7 @@ async function loadWebTreeSitter() {
33038
33198
  void err2;
33039
33199
  }
33040
33200
  const here = entryDir();
33041
- const seaResourceBase = join8(here, "resources", "_resolve.js");
33201
+ const seaResourceBase = join9(here, "resources", "_resolve.js");
33042
33202
  const resourceRequire = createRequire2(seaResourceBase);
33043
33203
  return resourceRequire("web-tree-sitter");
33044
33204
  }
@@ -33053,9 +33213,9 @@ async function ensureTreeSitterReady() {
33053
33213
  await Parser2.init({
33054
33214
  locateFile: (name2) => {
33055
33215
  if (name2 === "tree-sitter.wasm" || name2 === "web-tree-sitter.wasm") {
33056
- return join8(runtime, name2);
33216
+ return join9(runtime, name2);
33057
33217
  }
33058
- return join8(grammars, name2);
33218
+ return join9(grammars, name2);
33059
33219
  }
33060
33220
  });
33061
33221
  })();
@@ -33067,7 +33227,7 @@ async function loadGrammar(name2) {
33067
33227
  if (cached2) return cached2;
33068
33228
  if (!languageClass) throw new Error("tree-sitter not initialized");
33069
33229
  const grammars = findWasmDir();
33070
- const lang = await languageClass.load(join8(grammars, `${name2}.wasm`));
33230
+ const lang = await languageClass.load(join9(grammars, `${name2}.wasm`));
33071
33231
  grammarCache.set(name2, lang);
33072
33232
  return lang;
33073
33233
  }
@@ -35969,7 +36129,7 @@ var init_src11 = __esm({
35969
36129
  // src/reconcile.ts
35970
36130
  import { execFileSync as execFileSync2 } from "node:child_process";
35971
36131
  import { readdirSync as readdirSync3, statSync as statSync2 } from "node:fs";
35972
- import { join as join9, relative as relative3, sep as sep2 } from "node:path";
36132
+ import { join as join10, relative as relative3, sep as sep2 } from "node:path";
35973
36133
  function gitSourceFiles(root) {
35974
36134
  let stdout;
35975
36135
  try {
@@ -35984,7 +36144,7 @@ function gitSourceFiles(root) {
35984
36144
  const out2 = [];
35985
36145
  for (const rel of stdout.split("\0")) {
35986
36146
  if (!rel || !SOURCE_RE.test(rel)) continue;
35987
- const abs = join9(root, rel);
36147
+ const abs = join10(root, rel);
35988
36148
  if (IGNORED.test(abs)) continue;
35989
36149
  out2.push(abs);
35990
36150
  }
@@ -35999,7 +36159,7 @@ function* walkSource(dir) {
35999
36159
  }
36000
36160
  for (const e of entries) {
36001
36161
  const name2 = String(e.name);
36002
- const full = join9(dir, name2);
36162
+ const full = join10(dir, name2);
36003
36163
  if (IGNORED.test(full)) continue;
36004
36164
  if (e.isDirectory()) yield* walkSource(full);
36005
36165
  else if (SOURCE_RE.test(name2)) yield full;
@@ -36077,7 +36237,7 @@ __export(mcp_exports, {
36077
36237
  runTool: () => runTool,
36078
36238
  searchGraph: () => searchGraph
36079
36239
  });
36080
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
36240
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
36081
36241
  import { resolve } from "node:path";
36082
36242
  function collectEnrichmentPulls(store, opts = {}) {
36083
36243
  const pending = store.findNodesByLabel("Solution").filter((s) => s.attrs["enrichmentPending"] === true).filter((s) => !opts.onlyUnsurfaced || s.attrs["enrichmentSurfaced"] !== true);
@@ -36190,10 +36350,10 @@ function showNode(store, node2, maxLines) {
36190
36350
  if (!relPath) return { found: false, reason: "no file owner for node" };
36191
36351
  const workspaceRoot = process.cwd();
36192
36352
  const absPath = resolve(workspaceRoot, relPath);
36193
- if (!existsSync9(absPath)) {
36353
+ if (!existsSync10(absPath)) {
36194
36354
  return { found: false, reason: `file not found on disk: ${absPath}` };
36195
36355
  }
36196
- const source = readFileSync7(absPath, "utf8");
36356
+ const source = readFileSync8(absPath, "utf8");
36197
36357
  const attrs = node2.attrs;
36198
36358
  let startByte = attrs["bodyStartByte"] ?? attrs["startByte"];
36199
36359
  let endByte = attrs["bodyEndByte"] ?? attrs["endByte"];
@@ -37426,7 +37586,7 @@ var init_mcp = __esm({
37426
37586
  inputSchema: { type: "object", properties: {} },
37427
37587
  handler: () => {
37428
37588
  const path2 = sharedStorePath();
37429
- if (!existsSync9(path2)) return { count: 0, pending: [] };
37589
+ if (!existsSync10(path2)) return { count: 0, pending: [] };
37430
37590
  const shared = openGraphStore({ path: path2 });
37431
37591
  try {
37432
37592
  const pending = pendingAbstractions(shared);
@@ -37457,7 +37617,7 @@ var init_mcp = __esm({
37457
37617
  },
37458
37618
  handler: (args2) => {
37459
37619
  const path2 = sharedStorePath();
37460
- if (!existsSync9(path2)) return { count: 0, routes: [] };
37620
+ if (!existsSync10(path2)) return { count: 0, routes: [] };
37461
37621
  const shared = openGraphStore({ path: path2 });
37462
37622
  try {
37463
37623
  const result = triageOf(shared, {
@@ -37842,8 +38002,8 @@ __export(vfile_exports, {
37842
38002
  resolvePath: () => resolvePath,
37843
38003
  segmentsOf: () => segmentsOf
37844
38004
  });
37845
- import { writeFileSync as writeFileSync7 } from "node:fs";
37846
- import { join as join10, resolve as resolve2, sep as sep3 } from "node:path";
38005
+ import { writeFileSync as writeFileSync8 } from "node:fs";
38006
+ import { join as join11, resolve as resolve2, sep as sep3 } from "node:path";
37847
38007
  function segmentsOf(rawPath) {
37848
38008
  let p = rawPath.replace(/\\/g, "/");
37849
38009
  p = p.replace(/^.*\.errata\/g\//, "").replace(/^\/?g\//, "").replace(/^\/+/, "");
@@ -37917,14 +38077,14 @@ async function renderVFile(rawPath, store, ctx = {}) {
37917
38077
  }
37918
38078
  async function materializeVFile(rawPath, workspaceRoot, store, ctx = {}) {
37919
38079
  const segs = segmentsOf(rawPath);
37920
- const gRoot = join10(workspaceRoot, ".errata", "g");
38080
+ const gRoot = join11(workspaceRoot, ".errata", "g");
37921
38081
  const abs = resolve2(gRoot, ...segs.length ? segs : ["index"]);
37922
38082
  if (abs !== gRoot && !abs.startsWith(gRoot + sep3)) {
37923
38083
  throw new Error(`refusing to materialize outside .errata/g: ${rawPath}`);
37924
38084
  }
37925
38085
  const text = await renderVFile(rawPath, store, ctx);
37926
38086
  ensureParent(abs);
37927
- writeFileSync7(abs, text, "utf8");
38087
+ writeFileSync8(abs, text, "utf8");
37928
38088
  return abs;
37929
38089
  }
37930
38090
  async function materializeOverview(workspaceRoot, store, ctx = {}) {
@@ -45185,8 +45345,8 @@ var init_tldr_tools_generated = __esm({
45185
45345
  });
45186
45346
 
45187
45347
  // src/tool-index.ts
45188
- function toolNodeId(name2) {
45189
- return `tool:${name2}`;
45348
+ function currentOsName() {
45349
+ return osNameForPlatform(process.platform);
45190
45350
  }
45191
45351
  function extractExecutables(command) {
45192
45352
  const out2 = [];
@@ -45211,8 +45371,10 @@ function extractExecutables(command) {
45211
45371
  }
45212
45372
  function observeCommandTools(store, command, ts) {
45213
45373
  const result = { minted: [], reinforced: [] };
45374
+ const osName = currentOsName();
45214
45375
  for (const name2 of extractExecutables(command)) {
45215
45376
  if (!PUBLIC_TOOLS.has(name2)) continue;
45377
+ if (PLUMBING.has(name2)) continue;
45216
45378
  const id = toolNodeId(name2);
45217
45379
  const existing = store.getNode(id);
45218
45380
  if (existing) {
@@ -45245,17 +45407,60 @@ function observeCommandTools(store, command, ts) {
45245
45407
  attrs: { name: name2, canonicalId: toolCanonicalId(name2), public: true }
45246
45408
  });
45247
45409
  result.minted.push(name2);
45410
+ if (osName) {
45411
+ const os2 = resolveOsNode(store, osName, ts);
45412
+ store.mergeEdge({
45413
+ id: `edge_${digest({ from: id, type: "RUNS_ON", to: os2.id })}`.slice(0, 24),
45414
+ from: id,
45415
+ to: os2.id,
45416
+ type: "RUNS_ON",
45417
+ confidence: 1,
45418
+ // observed
45419
+ extractionSource: "daemon-extracted",
45420
+ createdAt: ts,
45421
+ lastSeenAt: ts,
45422
+ navSuccesses: 0,
45423
+ navFailures: 0,
45424
+ attrs: { observed: true }
45425
+ });
45426
+ }
45248
45427
  }
45249
45428
  }
45250
45429
  return result;
45251
45430
  }
45252
- var PUBLIC_TOOLS, PASSTHROUGH, SEGMENT_SPLIT;
45431
+ var PUBLIC_TOOLS, PLUMBING, PASSTHROUGH, SEGMENT_SPLIT;
45253
45432
  var init_tool_index = __esm({
45254
45433
  "src/tool-index.ts"() {
45255
45434
  "use strict";
45256
45435
  init_src();
45436
+ init_src();
45437
+ init_src4();
45257
45438
  init_tldr_tools_generated();
45258
45439
  PUBLIC_TOOLS = new Set(TLDR_TOOL_NAMES);
45440
+ PLUMBING = /* @__PURE__ */ new Set([
45441
+ "cd",
45442
+ "pwd",
45443
+ "ls",
45444
+ "dir",
45445
+ "echo",
45446
+ "clear",
45447
+ "cls",
45448
+ "exit",
45449
+ "true",
45450
+ "false",
45451
+ "which",
45452
+ "where",
45453
+ "alias",
45454
+ "unalias",
45455
+ "history",
45456
+ "set",
45457
+ "unset",
45458
+ "export",
45459
+ "source",
45460
+ "sleep",
45461
+ "time",
45462
+ "type"
45463
+ ]);
45259
45464
  PASSTHROUGH = /* @__PURE__ */ new Set(["sudo", "npx", "pnpx", "bunx", "uvx", "time", "nohup", "xargs", "watch"]);
45260
45465
  SEGMENT_SPLIT = /\|\|?|&&|;|\r?\n/;
45261
45466
  }
@@ -45263,25 +45468,25 @@ var init_tool_index = __esm({
45263
45468
 
45264
45469
  // src/outbox.ts
45265
45470
  import {
45266
- existsSync as existsSync10,
45471
+ existsSync as existsSync11,
45267
45472
  readdirSync as readdirSync4,
45268
- readFileSync as readFileSync8,
45473
+ readFileSync as readFileSync9,
45269
45474
  renameSync,
45270
45475
  unlinkSync,
45271
- writeFileSync as writeFileSync8
45476
+ writeFileSync as writeFileSync9
45272
45477
  } from "node:fs";
45273
- import { join as join11 } from "node:path";
45478
+ import { join as join12 } from "node:path";
45274
45479
  import { createHash as createHash11 } from "node:crypto";
45275
45480
  function enqueueOutbox(paths, payload) {
45276
45481
  ensureDir(paths.outbox);
45277
45482
  const id = createHash11("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
45278
- const file2 = join11(paths.outbox, `${Date.now()}-${id}.json`);
45279
- writeFileSync8(file2, JSON.stringify(payload, null, 2), "utf8");
45483
+ const file2 = join12(paths.outbox, `${Date.now()}-${id}.json`);
45484
+ writeFileSync9(file2, JSON.stringify(payload, null, 2), "utf8");
45280
45485
  return file2;
45281
45486
  }
45282
45487
  async function flushOutbox(paths, client, store) {
45283
45488
  ensureDir(paths.outbox);
45284
- const entries = existsSync10(paths.outbox) ? readdirSync4(paths.outbox) : [];
45489
+ const entries = existsSync11(paths.outbox) ? readdirSync4(paths.outbox) : [];
45285
45490
  let uploaded = 0;
45286
45491
  let failed = 0;
45287
45492
  const quarantine = (abs, reason) => {
@@ -45292,10 +45497,10 @@ async function flushOutbox(paths, client, store) {
45292
45497
  }
45293
45498
  };
45294
45499
  for (const f of entries.filter((e) => e.endsWith(".json")).sort()) {
45295
- const abs = join11(paths.outbox, f);
45500
+ const abs = join12(paths.outbox, f);
45296
45501
  let payload;
45297
45502
  try {
45298
- payload = JSON.parse(readFileSync8(abs, "utf8"));
45503
+ payload = JSON.parse(readFileSync9(abs, "utf8"));
45299
45504
  } catch {
45300
45505
  failed++;
45301
45506
  quarantine(abs, "unparseable JSON");
@@ -45340,7 +45545,7 @@ async function flushOutbox(paths, client, store) {
45340
45545
  }
45341
45546
  }
45342
45547
  }
45343
- const remainingFiles = existsSync10(paths.outbox) ? readdirSync4(paths.outbox).filter((e) => e.endsWith(".json")) : [];
45548
+ const remainingFiles = existsSync11(paths.outbox) ? readdirSync4(paths.outbox).filter((e) => e.endsWith(".json")) : [];
45344
45549
  return { uploaded, failed, remaining: remainingFiles.length };
45345
45550
  }
45346
45551
  var init_outbox = __esm({
@@ -45357,9 +45562,9 @@ __export(webui_exports, {
45357
45562
  decideContextInject: () => decideContextInject,
45358
45563
  fileUriToFsPath: () => fileUriToFsPath,
45359
45564
  findFileByPath: () => findFileByPath,
45360
- recallForFile: () => recallForFile
45565
+ recallForFile: () => recallForFile,
45566
+ recallForTool: () => recallForTool
45361
45567
  });
45362
- import { join as join12 } from "node:path";
45363
45568
  function fileUriToFsPath(raw2) {
45364
45569
  let p = raw2.replace(/^file:\/\//, "").replace(/\\/g, "/");
45365
45570
  if (/^\/[A-Za-z]:/.test(p)) p = p.slice(1);
@@ -45410,6 +45615,35 @@ function recallForFile(store, relPath) {
45410
45615
  ${lines.join("\n")}
45411
45616
  ` + buildFileRecallInstruction();
45412
45617
  }
45618
+ function workspacePackageIds(store) {
45619
+ const hit = wsPackagesCache.get(store);
45620
+ const now = Date.now();
45621
+ if (hit && now - hit.at < WS_PACKAGES_TTL_MS) return hit.ids;
45622
+ const ids = new Set(store.findNodesByLabel("Package").map((n) => n.id));
45623
+ wsPackagesCache.set(store, { at: now, ids });
45624
+ return ids;
45625
+ }
45626
+ function recallForTool(store, command, ctx) {
45627
+ const lines = [];
45628
+ const seen = /* @__PURE__ */ new Set();
45629
+ for (const name2 of extractExecutables(command)) {
45630
+ if (seen.has(name2)) continue;
45631
+ seen.add(name2);
45632
+ for (const fit of toolPriorsFor(store, name2, ctx, 3)) {
45633
+ const where = fit.osMismatch ? ` \`[${fit.observedOn.join("/")}]\`` : "";
45634
+ const stack = fit.stackHits.length > 0 ? ` \`[${fit.stackHits.join(", ")}]\`` : "";
45635
+ lines.push(
45636
+ `- \`${name2}\`${where}${stack} ${recallLine(
45637
+ fit.node,
45638
+ fit.node.label === "Problem" ? `${TAG_EXAMPLE.fix(fit.node.id)} if you resolved it \xB7 ${TAG_EXAMPLE.prior(fit.node.id)} to cite` : `cite with ${TAG_EXAMPLE.prior(fit.node.id)}`
45639
+ ).slice(2)}`
45640
+ );
45641
+ }
45642
+ }
45643
+ if (lines.length === 0) return null;
45644
+ return `errata \u2014 ${lines.length} prior(s) about the tool(s) you're about to run (a \`[platform]\` tag means it was seen on a DIFFERENT OS than this one \u2014 judge it):
45645
+ ${lines.join("\n")}`;
45646
+ }
45413
45647
  function decideContextInject(args2) {
45414
45648
  const { event, source, sessionId, block, lastInjectedHash } = args2;
45415
45649
  if (!block) return null;
@@ -45581,6 +45815,15 @@ function buildWebUi(deps) {
45581
45815
  }
45582
45816
  return c.json({ ok: true, materialized });
45583
45817
  }
45818
+ if (tool === "Bash" && typeof input["command"] === "string") {
45819
+ try {
45820
+ recallCtx = recallForTool(deps.store, input["command"], {
45821
+ os: currentOsName(),
45822
+ workspacePackageIds: workspacePackageIds(deps.store)
45823
+ });
45824
+ } catch {
45825
+ }
45826
+ }
45584
45827
  }
45585
45828
  const filePath = extractWorkingFile(tool, input);
45586
45829
  let rel = null;
@@ -45672,6 +45915,11 @@ function buildWebUi(deps) {
45672
45915
  }
45673
45916
  return c.body(null, 204);
45674
45917
  }
45918
+ if (event === "PreToolUse" && recallCtx) {
45919
+ return c.json({
45920
+ hookSpecificOutput: { hookEventName: "PreToolUse", additionalContext: recallCtx }
45921
+ });
45922
+ }
45675
45923
  return c.json({ ok: true, event, tool, recognizedFile: filePath ?? null });
45676
45924
  });
45677
45925
  app.post("/api/turn", async (c) => {
@@ -45728,7 +45976,7 @@ function buildWebUi(deps) {
45728
45976
  } catch {
45729
45977
  return c.json({});
45730
45978
  }
45731
- const block = readManagedBlockWithHash(join12(deps.paths.root, "AGENTS.md"));
45979
+ const block = readContextFileWithHash(deps.paths.root);
45732
45980
  const decision = decideContextInject({
45733
45981
  event: String(body2["hook_event_name"] ?? "UserPromptSubmit"),
45734
45982
  source: String(body2["source"] ?? ""),
@@ -45918,7 +46166,7 @@ function proposalToIngest(p, profile, daemonVersion) {
45918
46166
  payloadDigest: p.id
45919
46167
  };
45920
46168
  }
45921
- var META_LABELS;
46169
+ var wsPackagesCache, WS_PACKAGES_TTL_MS, META_LABELS;
45922
46170
  var init_webui = __esm({
45923
46171
  "src/webui.ts"() {
45924
46172
  "use strict";
@@ -45930,6 +46178,8 @@ var init_webui = __esm({
45930
46178
  init_vfile();
45931
46179
  init_tool_index();
45932
46180
  init_outbox();
46181
+ wsPackagesCache = /* @__PURE__ */ new WeakMap();
46182
+ WS_PACKAGES_TTL_MS = 6e4;
45933
46183
  META_LABELS = /* @__PURE__ */ new Set([
45934
46184
  "Pattern",
45935
46185
  "Technique",
@@ -46331,12 +46581,12 @@ var init_report_render = __esm({
46331
46581
 
46332
46582
  // src/cli.ts
46333
46583
  init_src5();
46334
- import { closeSync as closeSync2, existsSync as existsSync23, openSync as openSync2, readFileSync as readFileSync21, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
46584
+ import { closeSync as closeSync2, existsSync as existsSync24, openSync as openSync2, readFileSync as readFileSync22, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
46335
46585
  import { join as join26 } from "node:path";
46336
46586
  import { spawn as spawn3 } from "node:child_process";
46337
46587
 
46338
46588
  // src/daemon.ts
46339
- import { existsSync as existsSync18, writeFileSync as writeFileSync14 } from "node:fs";
46589
+ import { existsSync as existsSync19, writeFileSync as writeFileSync15 } from "node:fs";
46340
46590
 
46341
46591
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
46342
46592
  import { createServer as createServerHTTP } from "http";
@@ -46916,7 +47166,7 @@ init_config();
46916
47166
 
46917
47167
  // src/engine.ts
46918
47168
  import { execFileSync as execFileSync3 } from "node:child_process";
46919
- import { existsSync as existsSync17, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync8, renameSync as renameSync2, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "node:fs";
47169
+ import { existsSync as existsSync18, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync8, renameSync as renameSync2, readFileSync as readFileSync17, writeFileSync as writeFileSync14 } from "node:fs";
46920
47170
  import { join as join22, relative as relative6, sep as sep4 } from "node:path";
46921
47171
 
46922
47172
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
@@ -47648,9 +47898,9 @@ var NodeFsHandler = class {
47648
47898
  if (this.fsw.closed) {
47649
47899
  return;
47650
47900
  }
47651
- const dirname9 = sysPath.dirname(file2);
47901
+ const dirname10 = sysPath.dirname(file2);
47652
47902
  const basename5 = sysPath.basename(file2);
47653
- const parent = this.fsw._getWatchedDir(dirname9);
47903
+ const parent = this.fsw._getWatchedDir(dirname10);
47654
47904
  let prevStats = stats;
47655
47905
  if (parent.has(basename5))
47656
47906
  return;
@@ -47677,7 +47927,7 @@ var NodeFsHandler = class {
47677
47927
  prevStats = newStats2;
47678
47928
  }
47679
47929
  } catch (error48) {
47680
- this.fsw._remove(dirname9, basename5);
47930
+ this.fsw._remove(dirname10, basename5);
47681
47931
  }
47682
47932
  } else if (parent.has(basename5)) {
47683
47933
  const at = newStats.atimeMs;
@@ -48779,8 +49029,8 @@ init_src10();
48779
49029
  init_review2();
48780
49030
 
48781
49031
  // src/turn.ts
48782
- import { closeSync, existsSync as existsSync11, fstatSync, openSync, readdirSync as readdirSync5, readSync, statSync as statSync3 } from "node:fs";
48783
- import { basename as basename3, dirname as dirname7, join as join15 } from "node:path";
49032
+ import { closeSync, existsSync as existsSync12, fstatSync, openSync, readdirSync as readdirSync5, readSync, statSync as statSync3 } from "node:fs";
49033
+ import { basename as basename3, dirname as dirname8, join as join15 } from "node:path";
48784
49034
  import { homedir as homedir3 } from "node:os";
48785
49035
  function readTail(path2, maxBytes) {
48786
49036
  let fd;
@@ -48923,7 +49173,7 @@ function claudeProjectDir(cwd, home = homedir3()) {
48923
49173
  }
48924
49174
  function recentTranscripts(cwd, opts = {}) {
48925
49175
  const dir = claudeProjectDir(cwd, opts.home ?? homedir3());
48926
- if (!existsSync11(dir)) return [];
49176
+ if (!existsSync12(dir)) return [];
48927
49177
  let names;
48928
49178
  try {
48929
49179
  names = readdirSync5(dir);
@@ -48949,8 +49199,8 @@ function recentTranscripts(cwd, opts = {}) {
48949
49199
  }
48950
49200
  function subagentTranscripts(mainTranscriptPath, sessionId) {
48951
49201
  if (!mainTranscriptPath || !sessionId) return [];
48952
- const dir = join15(dirname7(mainTranscriptPath), sessionId, "subagents");
48953
- if (!existsSync11(dir)) return [];
49202
+ const dir = join15(dirname8(mainTranscriptPath), sessionId, "subagents");
49203
+ if (!existsSync12(dir)) return [];
48954
49204
  let names;
48955
49205
  try {
48956
49206
  names = readdirSync5(dir);
@@ -48977,7 +49227,9 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
48977
49227
  init_src();
48978
49228
  init_src2();
48979
49229
  init_agent_signals();
48980
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "node:fs";
49230
+ init_tool_index();
49231
+ init_src4();
49232
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync10 } from "node:fs";
48981
49233
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
48982
49234
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
48983
49235
  var HANDLE_RE = /\[([a-z0-9][\w-]{0,40})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
@@ -49265,13 +49517,13 @@ function writePrimingHandles(path2, nodes, now = Date.now()) {
49265
49517
  entries.sort((a, b) => (b[1].seenAt ?? 0) - (a[1].seenAt ?? 0));
49266
49518
  entries.length = HANDLE_MAP_MAX;
49267
49519
  }
49268
- writeFileSync9(path2, JSON.stringify(Object.fromEntries(entries)));
49520
+ writeFileSync10(path2, JSON.stringify(Object.fromEntries(entries)));
49269
49521
  } catch {
49270
49522
  }
49271
49523
  }
49272
49524
  function readPrimingHandles(path2) {
49273
49525
  try {
49274
- return JSON.parse(readFileSync9(path2, "utf8"));
49526
+ return JSON.parse(readFileSync10(path2, "utf8"));
49275
49527
  } catch {
49276
49528
  return {};
49277
49529
  }
@@ -49304,6 +49556,7 @@ function mintPriorEdge(store, source, target, sentence, touched, ts) {
49304
49556
  navFailures: 0,
49305
49557
  attrs: { provisional: true, priorTag: true, primingProvenance: true, corroborated }
49306
49558
  });
49559
+ if (type === "CONCERNS") stampObservedOs(store, source.id, currentOsName(), ts);
49307
49560
  return true;
49308
49561
  }
49309
49562
  function harvestInlineTags(store, text, opts) {
@@ -49754,11 +50007,11 @@ init_outbox();
49754
50007
  init_src8();
49755
50008
  init_src();
49756
50009
  init_src2();
49757
- import { readFileSync as readFileSync10 } from "node:fs";
50010
+ import { readFileSync as readFileSync11 } from "node:fs";
49758
50011
  import { join as join16 } from "node:path";
49759
50012
  function loadClaimIgnorePatterns(workspaceRoot) {
49760
50013
  try {
49761
- return readFileSync10(join16(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
50014
+ return readFileSync11(join16(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
49762
50015
  } catch {
49763
50016
  return [];
49764
50017
  }
@@ -50062,11 +50315,11 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
50062
50315
  }
50063
50316
 
50064
50317
  // src/git-sensor.ts
50065
- import { existsSync as existsSync12, readFileSync as readFileSync11, watch as fsWatch } from "node:fs";
50318
+ import { existsSync as existsSync13, readFileSync as readFileSync12, watch as fsWatch } from "node:fs";
50066
50319
  import { join as join17 } from "node:path";
50067
50320
  function readFirstLine(path2) {
50068
50321
  try {
50069
- return readFileSync11(path2, "utf8").split(/\r?\n/, 1)[0].trim();
50322
+ return readFileSync12(path2, "utf8").split(/\r?\n/, 1)[0].trim();
50070
50323
  } catch {
50071
50324
  return null;
50072
50325
  }
@@ -50085,13 +50338,13 @@ function readGitRefState(gitDir) {
50085
50338
  return {
50086
50339
  branch,
50087
50340
  sha: sha2,
50088
- mergeHeadExists: existsSync12(join17(gitDir, "MERGE_HEAD")),
50089
- origHeadExists: existsSync12(join17(gitDir, "ORIG_HEAD"))
50341
+ mergeHeadExists: existsSync13(join17(gitDir, "MERGE_HEAD")),
50342
+ origHeadExists: existsSync13(join17(gitDir, "ORIG_HEAD"))
50090
50343
  };
50091
50344
  }
50092
50345
  function shaFromPackedRefs(gitDir, ref) {
50093
50346
  try {
50094
- for (const line of readFileSync11(join17(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
50347
+ for (const line of readFileSync12(join17(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
50095
50348
  const [sha2, name2] = line.split(/\s+/);
50096
50349
  if (name2 === ref && sha2) return sha2;
50097
50350
  }
@@ -50125,7 +50378,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
50125
50378
  const settle = () => {
50126
50379
  if (timer) clearTimeout(timer);
50127
50380
  timer = setTimeout(() => {
50128
- if (existsSync12(join17(gitDir, "index.lock"))) {
50381
+ if (existsSync13(join17(gitDir, "index.lock"))) {
50129
50382
  settle();
50130
50383
  return;
50131
50384
  }
@@ -50361,21 +50614,21 @@ var TelemetryRecorder = class {
50361
50614
 
50362
50615
  // src/skills.ts
50363
50616
  import {
50364
- existsSync as existsSync13,
50365
- mkdirSync as mkdirSync5,
50366
- readFileSync as readFileSync12,
50617
+ existsSync as existsSync14,
50618
+ mkdirSync as mkdirSync6,
50619
+ readFileSync as readFileSync13,
50367
50620
  readdirSync as readdirSync6,
50368
50621
  unlinkSync as unlinkSync2,
50369
- writeFileSync as writeFileSync10
50622
+ writeFileSync as writeFileSync11
50370
50623
  } from "node:fs";
50371
50624
  import { basename as basename4, join as join18 } from "node:path";
50372
50625
  function skillFileName(id) {
50373
50626
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
50374
50627
  }
50375
50628
  function readSkillManifest(manifestPath) {
50376
- if (!existsSync13(manifestPath)) return [];
50629
+ if (!existsSync14(manifestPath)) return [];
50377
50630
  try {
50378
- const parsed = JSON.parse(readFileSync12(manifestPath, "utf8"));
50631
+ const parsed = JSON.parse(readFileSync13(manifestPath, "utf8"));
50379
50632
  return (parsed.skills ?? []).map((s) => ({
50380
50633
  title: s.title ?? "",
50381
50634
  layer: s.layer ?? "technique",
@@ -50389,7 +50642,7 @@ function readSkillManifest(manifestPath) {
50389
50642
  async function syncSkills(paths, client, seed, pins = []) {
50390
50643
  const res = await client.getSkills(void 0, seed);
50391
50644
  const staleDaemon = res.staleDaemon && res.latestDaemonVersion ? { latest: res.latestDaemonVersion } : void 0;
50392
- mkdirSync5(paths.skillsDir, { recursive: true });
50645
+ mkdirSync6(paths.skillsDir, { recursive: true });
50393
50646
  if (res.skills.length === 0 && pins.length === 0) {
50394
50647
  const existing = readdirSync6(paths.skillsDir).filter((f) => f.endsWith(".md"));
50395
50648
  if (existing.length > 0) return { written: 0, pruned: 0, ...staleDaemon ? { staleDaemon } : {} };
@@ -50399,7 +50652,7 @@ async function syncSkills(paths, client, seed, pins = []) {
50399
50652
  for (const s of res.skills) {
50400
50653
  const fileName = skillFileName(s.id);
50401
50654
  keep.add(fileName);
50402
- writeFileSync10(join18(paths.skillsDir, fileName), s.markdown, "utf8");
50655
+ writeFileSync11(join18(paths.skillsDir, fileName), s.markdown, "utf8");
50403
50656
  rows.push({
50404
50657
  id: s.id,
50405
50658
  title: s.title,
@@ -50412,7 +50665,7 @@ async function syncSkills(paths, client, seed, pins = []) {
50412
50665
  const fileName = skillFileName(p.id);
50413
50666
  if (keep.has(fileName)) continue;
50414
50667
  keep.add(fileName);
50415
- writeFileSync10(join18(paths.skillsDir, fileName), p.markdown, "utf8");
50668
+ writeFileSync11(join18(paths.skillsDir, fileName), p.markdown, "utf8");
50416
50669
  rows.push({
50417
50670
  id: p.id,
50418
50671
  title: p.title,
@@ -50432,7 +50685,7 @@ async function syncSkills(paths, client, seed, pins = []) {
50432
50685
  }
50433
50686
  }
50434
50687
  rows.sort((a, b) => a.id.localeCompare(b.id));
50435
- writeFileSync10(
50688
+ writeFileSync11(
50436
50689
  paths.skillsManifest,
50437
50690
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
50438
50691
  "utf8"
@@ -50443,14 +50696,14 @@ async function syncSkills(paths, client, seed, pins = []) {
50443
50696
  // src/agent-skills.ts
50444
50697
  import {
50445
50698
  cpSync,
50446
- existsSync as existsSync14,
50699
+ existsSync as existsSync15,
50447
50700
  lstatSync,
50448
- mkdirSync as mkdirSync6,
50449
- readFileSync as readFileSync13,
50701
+ mkdirSync as mkdirSync7,
50702
+ readFileSync as readFileSync14,
50450
50703
  readdirSync as readdirSync7,
50451
50704
  rmSync as rmSync2,
50452
50705
  symlinkSync,
50453
- writeFileSync as writeFileSync11
50706
+ writeFileSync as writeFileSync12
50454
50707
  } from "node:fs";
50455
50708
  import { join as join19 } from "node:path";
50456
50709
  var SKILL_NS = "errata-";
@@ -50483,7 +50736,7 @@ ${body2.trimEnd()}
50483
50736
  `;
50484
50737
  }
50485
50738
  function reconcileNamespaced(dir, keep) {
50486
- if (!existsSync14(dir)) return 0;
50739
+ if (!existsSync15(dir)) return 0;
50487
50740
  let pruned = 0;
50488
50741
  for (const name2 of readdirSync7(dir)) {
50489
50742
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
@@ -50497,7 +50750,7 @@ function reconcileNamespaced(dir, keep) {
50497
50750
  }
50498
50751
  function linkOrCopy(linkPath, target) {
50499
50752
  try {
50500
- if (existsSync14(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
50753
+ if (existsSync15(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
50501
50754
  } catch {
50502
50755
  }
50503
50756
  try {
@@ -50519,14 +50772,14 @@ function safeLstat(p) {
50519
50772
  }
50520
50773
  function emitAndProjectSkills(root, skills) {
50521
50774
  const agentsSkillsDir = join19(root, ".agents", "skills");
50522
- mkdirSync6(agentsSkillsDir, { recursive: true });
50775
+ mkdirSync7(agentsSkillsDir, { recursive: true });
50523
50776
  const slugs = [];
50524
50777
  const keep = /* @__PURE__ */ new Set();
50525
50778
  let emitted = 0;
50526
50779
  for (const s of skills) {
50527
50780
  let body2;
50528
50781
  try {
50529
- body2 = readFileSync13(s.bodyPath, "utf8");
50782
+ body2 = readFileSync14(s.bodyPath, "utf8");
50530
50783
  } catch {
50531
50784
  continue;
50532
50785
  }
@@ -50535,8 +50788,8 @@ function emitAndProjectSkills(root, skills) {
50535
50788
  keep.add(slug2);
50536
50789
  slugs.push(slug2);
50537
50790
  const description = deriveDescription(s.title, s.layer, body2);
50538
- mkdirSync6(join19(agentsSkillsDir, slug2), { recursive: true });
50539
- writeFileSync11(
50791
+ mkdirSync7(join19(agentsSkillsDir, slug2), { recursive: true });
50792
+ writeFileSync12(
50540
50793
  join19(agentsSkillsDir, slug2, "SKILL.md"),
50541
50794
  renderSkillMd(slug2, description, body2),
50542
50795
  "utf8"
@@ -50546,9 +50799,9 @@ function emitAndProjectSkills(root, skills) {
50546
50799
  reconcileNamespaced(agentsSkillsDir, keep);
50547
50800
  let projected = 0;
50548
50801
  for (const h of HARNESS_SKILL_DIRS) {
50549
- if (!existsSync14(join19(root, h.configDir))) continue;
50802
+ if (!existsSync15(join19(root, h.configDir))) continue;
50550
50803
  const dir = join19(root, h.skillsDir);
50551
- mkdirSync6(dir, { recursive: true });
50804
+ mkdirSync7(dir, { recursive: true });
50552
50805
  for (const slug2 of slugs) {
50553
50806
  linkOrCopy(join19(dir, slug2), join19(agentsSkillsDir, slug2));
50554
50807
  projected++;
@@ -50559,9 +50812,9 @@ function emitAndProjectSkills(root, skills) {
50559
50812
  return { slugs, emitted, projected };
50560
50813
  }
50561
50814
  function emitInputsFromManifest(erretaDir, manifestPath) {
50562
- if (!existsSync14(manifestPath)) return [];
50815
+ if (!existsSync15(manifestPath)) return [];
50563
50816
  try {
50564
- const parsed = JSON.parse(readFileSync13(manifestPath, "utf8"));
50817
+ const parsed = JSON.parse(readFileSync14(manifestPath, "utf8"));
50565
50818
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
50566
50819
  id: s.id,
50567
50820
  title: s.title ?? s.id,
@@ -50584,14 +50837,14 @@ function ensureSkillGitignore(root) {
50584
50837
  const path2 = join19(root, ".gitignore");
50585
50838
  let current = "";
50586
50839
  try {
50587
- current = existsSync14(path2) ? readFileSync13(path2, "utf8") : "";
50840
+ current = existsSync15(path2) ? readFileSync14(path2, "utf8") : "";
50588
50841
  } catch {
50589
50842
  return;
50590
50843
  }
50591
50844
  if (current.includes(GITIGNORE_MARK)) return;
50592
50845
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
50593
50846
  try {
50594
- writeFileSync11(path2, `${current}${prefix}
50847
+ writeFileSync12(path2, `${current}${prefix}
50595
50848
  ${GITIGNORE_LINES.join("\n")}
50596
50849
  `, "utf8");
50597
50850
  } catch {
@@ -50727,20 +50980,20 @@ var CausalBuffer = class {
50727
50980
  // src/profile.ts
50728
50981
  init_src2();
50729
50982
  init_paths();
50730
- import { existsSync as existsSync16, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
50983
+ import { existsSync as existsSync17, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "node:fs";
50731
50984
  import { createHash as createHash12 } from "node:crypto";
50732
50985
  import { join as join21 } from "node:path";
50733
50986
 
50734
50987
  // src/git-remote.ts
50735
50988
  init_src();
50736
- import { existsSync as existsSync15, readFileSync as readFileSync14, statSync as statSync4 } from "node:fs";
50989
+ import { existsSync as existsSync16, readFileSync as readFileSync15, statSync as statSync4 } from "node:fs";
50737
50990
  import { isAbsolute as isAbsolute3, join as join20, resolve as resolve5 } from "node:path";
50738
50991
  function resolveGitDir(root) {
50739
50992
  const dotGit = join20(root, ".git");
50740
50993
  try {
50741
50994
  const st = statSync4(dotGit);
50742
50995
  if (st.isDirectory()) return dotGit;
50743
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync14(dotGit, "utf8"));
50996
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync15(dotGit, "utf8"));
50744
50997
  if (!m) return null;
50745
50998
  const dir = m[1];
50746
50999
  return isAbsolute3(dir) ? dir : resolve5(root, dir);
@@ -50750,8 +51003,8 @@ function resolveGitDir(root) {
50750
51003
  }
50751
51004
  function gitConfigPath(gitDir) {
50752
51005
  const commondirFile = join20(gitDir, "commondir");
50753
- if (existsSync15(commondirFile)) {
50754
- const common = readFileSync14(commondirFile, "utf8").trim();
51006
+ if (existsSync16(commondirFile)) {
51007
+ const common = readFileSync15(commondirFile, "utf8").trim();
50755
51008
  const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
50756
51009
  return join20(commonDir, "config");
50757
51010
  }
@@ -50761,10 +51014,10 @@ function readRemotes(root) {
50761
51014
  const gitDir = resolveGitDir(root);
50762
51015
  if (!gitDir) return [];
50763
51016
  const cfgPath = gitConfigPath(gitDir);
50764
- if (!existsSync15(cfgPath)) return [];
51017
+ if (!existsSync16(cfgPath)) return [];
50765
51018
  let txt;
50766
51019
  try {
50767
- txt = readFileSync14(cfgPath, "utf8");
51020
+ txt = readFileSync15(cfgPath, "utf8");
50768
51021
  } catch {
50769
51022
  return [];
50770
51023
  }
@@ -50796,13 +51049,13 @@ function refreshRepoLocator(root, profile) {
50796
51049
  }
50797
51050
  function loadProfile(root) {
50798
51051
  const p = workspacePaths(root);
50799
- if (!existsSync16(p.workspaceJson)) return null;
50800
- return JSON.parse(readFileSync15(p.workspaceJson, "utf8"));
51052
+ if (!existsSync17(p.workspaceJson)) return null;
51053
+ return JSON.parse(readFileSync16(p.workspaceJson, "utf8"));
50801
51054
  }
50802
51055
  function saveProfile(root, profile) {
50803
51056
  const p = workspacePaths(root);
50804
51057
  ensureDir(p.configDir);
50805
- writeFileSync12(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
51058
+ writeFileSync13(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
50806
51059
  }
50807
51060
  function autodetectProfile(root) {
50808
51061
  const id = workspaceId(root);
@@ -50811,9 +51064,9 @@ function autodetectProfile(root) {
50811
51064
  const locator = detectRepoLocator(root);
50812
51065
  if (locator) p.repoLocator = locator;
50813
51066
  const pkgPath = join21(root, "package.json");
50814
- if (existsSync16(pkgPath)) {
51067
+ if (existsSync17(pkgPath)) {
50815
51068
  try {
50816
- const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
51069
+ const pkg = JSON.parse(readFileSync16(pkgPath, "utf8"));
50817
51070
  p.languages.push("typescript", "javascript");
50818
51071
  const nodeVer = pkg.engines?.node ?? "node";
50819
51072
  p.stack.push(`node@${nodeVer}`);
@@ -50835,9 +51088,9 @@ function autodetectProfile(root) {
50835
51088
  }
50836
51089
  }
50837
51090
  const pyproject = join21(root, "pyproject.toml");
50838
- if (existsSync16(pyproject)) {
51091
+ if (existsSync17(pyproject)) {
50839
51092
  try {
50840
- const txt = readFileSync15(pyproject, "utf8");
51093
+ const txt = readFileSync16(pyproject, "utf8");
50841
51094
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
50842
51095
  p.languages.push("python");
50843
51096
  p.stack.push(`python@${py ?? "3"}`);
@@ -50849,15 +51102,15 @@ function autodetectProfile(root) {
50849
51102
  }
50850
51103
  }
50851
51104
  const reqs = join21(root, "requirements.txt");
50852
- if (existsSync16(reqs)) {
51105
+ if (existsSync17(reqs)) {
50853
51106
  if (!p.languages.includes("python")) p.languages.push("python");
50854
51107
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
50855
51108
  }
50856
- if (existsSync16(join21(root, "go.mod"))) {
51109
+ if (existsSync17(join21(root, "go.mod"))) {
50857
51110
  p.languages.push("go");
50858
51111
  p.stack.push("go");
50859
51112
  }
50860
- if (existsSync16(join21(root, "Cargo.toml"))) {
51113
+ if (existsSync17(join21(root, "Cargo.toml"))) {
50861
51114
  p.languages.push("rust");
50862
51115
  p.stack.push("rust");
50863
51116
  }
@@ -51015,7 +51268,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
51015
51268
  }
51016
51269
 
51017
51270
  // src/engine.ts
51018
- var DAEMON_VERSION = true ? "2.0.0-dev.88" : "2.0.0-alpha.0";
51271
+ var DAEMON_VERSION = true ? "2.0.0-dev.90" : "2.0.0-alpha.0";
51019
51272
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
51020
51273
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
51021
51274
  var GIT_OP_MUTE_MS = 4e3;
@@ -51025,7 +51278,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
51025
51278
  function appendIdentityAudit(path2, record2, line) {
51026
51279
  if (!record2.accepted && record2.score <= 0) return;
51027
51280
  try {
51028
- if (existsSync17(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
51281
+ if (existsSync18(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
51029
51282
  renameSync2(path2, `${path2}.1`);
51030
51283
  }
51031
51284
  appendFileSync2(path2, line);
@@ -51035,14 +51288,14 @@ function appendIdentityAudit(path2, record2, line) {
51035
51288
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
51036
51289
  function loadTurnCursors(path2) {
51037
51290
  try {
51038
- return new Map(Object.entries(JSON.parse(readFileSync16(path2, "utf8"))));
51291
+ return new Map(Object.entries(JSON.parse(readFileSync17(path2, "utf8"))));
51039
51292
  } catch {
51040
51293
  return /* @__PURE__ */ new Map();
51041
51294
  }
51042
51295
  }
51043
51296
  function saveTurnCursors(path2, cursors) {
51044
51297
  try {
51045
- writeFileSync13(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
51298
+ writeFileSync14(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
51046
51299
  } catch {
51047
51300
  }
51048
51301
  }
@@ -51279,7 +51532,7 @@ function createWorkspaceEngine(opts) {
51279
51532
  );
51280
51533
  };
51281
51534
  const gitDir = join22(opts.workspaceRoot, ".git");
51282
- if (existsSync17(gitDir)) {
51535
+ if (existsSync18(gitDir)) {
51283
51536
  stopGit = startGitSensor(gitDir, (ev) => {
51284
51537
  void handleGitEvent(ev).catch((err2) => {
51285
51538
  console.warn("[errata] git event handler failed:", err2);
@@ -51347,8 +51600,9 @@ function createWorkspaceEngine(opts) {
51347
51600
  ...pendingUpdate ? { pendingUpdate } : {}
51348
51601
  });
51349
51602
  doneRender?.();
51603
+ writeContextFile(opts.workspaceRoot, body2);
51350
51604
  const target = join22(opts.workspaceRoot, "AGENTS.md");
51351
- writeManagedBlock(target, { body: body2 });
51605
+ writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
51352
51606
  if (elicit) {
51353
51607
  writePrimingHandles(join22(paths.configDir, "priming-handles.json"), [
51354
51608
  ...snapshot.recentProblems.map((r) => r.node),
@@ -52242,7 +52496,7 @@ function createWorkspaceEngine(opts) {
52242
52496
  console.log(
52243
52497
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
52244
52498
  );
52245
- const pending = existsSync17(paths.outbox) ? readdirSync8(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
52499
+ const pending = existsSync18(paths.outbox) ? readdirSync8(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
52246
52500
  return { uploaded: 0, failed: 0, remaining: pending };
52247
52501
  }
52248
52502
  try {
@@ -52329,7 +52583,7 @@ async function startDaemon(opts) {
52329
52583
  reviewUrl: () => webUiUrl + "/review"
52330
52584
  });
52331
52585
  const writeLockFile = (url2) => {
52332
- writeFileSync14(
52586
+ writeFileSync15(
52333
52587
  engine.paths.daemonLock,
52334
52588
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
52335
52589
  "utf8"
@@ -52372,7 +52626,7 @@ async function startDaemon(opts) {
52372
52626
  );
52373
52627
  await engine.stop();
52374
52628
  try {
52375
- if (existsSync18(engine.paths.daemonLock)) {
52629
+ if (existsSync19(engine.paths.daemonLock)) {
52376
52630
  }
52377
52631
  } catch {
52378
52632
  }
@@ -52389,16 +52643,16 @@ async function listenServer(fetchFn, port) {
52389
52643
 
52390
52644
  // src/registry.ts
52391
52645
  init_paths();
52392
- import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
52646
+ import { existsSync as existsSync20, readFileSync as readFileSync18, writeFileSync as writeFileSync16 } from "node:fs";
52393
52647
  import { join as join23 } from "node:path";
52394
52648
  function registryPath() {
52395
52649
  return process.env["ERRATA_REGISTRY_PATH"] ?? join23(globalDir(), "workspaces.json");
52396
52650
  }
52397
52651
  function read() {
52398
52652
  const p = registryPath();
52399
- if (!existsSync19(p)) return { version: 1, workspaces: {} };
52653
+ if (!existsSync20(p)) return { version: 1, workspaces: {} };
52400
52654
  try {
52401
- const parsed = JSON.parse(readFileSync17(p, "utf8"));
52655
+ const parsed = JSON.parse(readFileSync18(p, "utf8"));
52402
52656
  return { version: 1, workspaces: parsed.workspaces ?? {} };
52403
52657
  } catch {
52404
52658
  return { version: 1, workspaces: {} };
@@ -52406,7 +52660,7 @@ function read() {
52406
52660
  }
52407
52661
  function write(reg) {
52408
52662
  ensureDir(globalDir());
52409
- writeFileSync15(registryPath(), JSON.stringify(reg, null, 2), "utf8");
52663
+ writeFileSync16(registryPath(), JSON.stringify(reg, null, 2), "utf8");
52410
52664
  }
52411
52665
  function registerWorkspace(profile, root, now = Date.now()) {
52412
52666
  const reg = read();
@@ -52423,7 +52677,7 @@ function pruneMissingWorkspaces() {
52423
52677
  const reg = read();
52424
52678
  const removed = [];
52425
52679
  for (const [id, entry] of Object.entries(reg.workspaces)) {
52426
- if (!existsSync19(entry.path)) {
52680
+ if (!existsSync20(entry.path)) {
52427
52681
  removed.push(entry);
52428
52682
  delete reg.workspaces[id];
52429
52683
  }
@@ -52432,13 +52686,13 @@ function pruneMissingWorkspaces() {
52432
52686
  return removed;
52433
52687
  }
52434
52688
  function workspaceStatus(entry) {
52435
- const missing = !existsSync19(entry.path);
52689
+ const missing = !existsSync20(entry.path);
52436
52690
  const lockPath = workspacePaths(entry.path).daemonLock;
52437
52691
  let running = false;
52438
52692
  let webUiUrl = null;
52439
- if (existsSync19(lockPath)) {
52693
+ if (existsSync20(lockPath)) {
52440
52694
  try {
52441
- const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
52695
+ const lock = JSON.parse(readFileSync18(lockPath, "utf8"));
52442
52696
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
52443
52697
  running = true;
52444
52698
  webUiUrl = lock.webUiUrl;
@@ -52466,7 +52720,7 @@ function pidAlive(pid) {
52466
52720
  // src/multi.ts
52467
52721
  init_dist();
52468
52722
  init_src4();
52469
- import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync16 } from "node:fs";
52723
+ import { readFileSync as readFileSync21, unlinkSync as unlinkSync3, writeFileSync as writeFileSync17 } from "node:fs";
52470
52724
 
52471
52725
  // src/principle-sync.ts
52472
52726
  init_src4();
@@ -52494,7 +52748,7 @@ init_reconcile();
52494
52748
 
52495
52749
  // src/lockfile-auto.ts
52496
52750
  init_src();
52497
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
52751
+ import { existsSync as existsSync21, readFileSync as readFileSync19 } from "node:fs";
52498
52752
  import { join as join24 } from "node:path";
52499
52753
 
52500
52754
  // src/package-index.ts
@@ -52630,10 +52884,10 @@ function runLockfilePass(opts) {
52630
52884
  ];
52631
52885
  for (const c of candidates) {
52632
52886
  const p = join24(opts.root, c.file);
52633
- if (!existsSync20(p)) continue;
52887
+ if (!existsSync21(p)) continue;
52634
52888
  let sbom;
52635
52889
  try {
52636
- sbom = c.parse(readFileSync18(p, "utf8"));
52890
+ sbom = c.parse(readFileSync19(p, "utf8"));
52637
52891
  } catch {
52638
52892
  continue;
52639
52893
  }
@@ -52954,7 +53208,7 @@ var ConsolidateWorker = class {
52954
53208
  init_paths();
52955
53209
 
52956
53210
  // src/lock.ts
52957
- import { existsSync as existsSync21, readFileSync as readFileSync19 } from "node:fs";
53211
+ import { existsSync as existsSync22, readFileSync as readFileSync20 } from "node:fs";
52958
53212
  function isProcessAlive(pid) {
52959
53213
  if (!pid || pid <= 0) return false;
52960
53214
  try {
@@ -52965,9 +53219,9 @@ function isProcessAlive(pid) {
52965
53219
  }
52966
53220
  }
52967
53221
  function readDaemonLock(lockPath) {
52968
- if (!existsSync21(lockPath)) return null;
53222
+ if (!existsSync22(lockPath)) return null;
52969
53223
  try {
52970
- const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
53224
+ const lock = JSON.parse(readFileSync20(lockPath, "utf8"));
52971
53225
  return typeof lock.pid === "number" ? lock : null;
52972
53226
  } catch {
52973
53227
  return null;
@@ -53209,13 +53463,13 @@ async function reanchorProject(opts) {
53209
53463
  }
53210
53464
 
53211
53465
  // src/adopt.ts
53212
- import { existsSync as existsSync22 } from "node:fs";
53213
- import { dirname as dirname8, join as join25 } from "node:path";
53466
+ import { existsSync as existsSync23 } from "node:fs";
53467
+ import { dirname as dirname9, join as join25 } from "node:path";
53214
53468
  function findGitRoot(absPath) {
53215
53469
  let dir = absPath;
53216
53470
  for (let depth = 0; depth < 64; depth++) {
53217
- if (existsSync22(join25(dir, ".git"))) return dir;
53218
- const parent = dirname8(dir);
53471
+ if (existsSync23(join25(dir, ".git"))) return dir;
53472
+ const parent = dirname9(dir);
53219
53473
  if (parent === dir) return null;
53220
53474
  dir = parent;
53221
53475
  }
@@ -53410,7 +53664,7 @@ async function startMultiDaemon(opts = {}) {
53410
53664
  void ambientLinkAll();
53411
53665
  app.route(`/ws/${rec.id}`, rec.webApp);
53412
53666
  try {
53413
- writeFileSync16(
53667
+ writeFileSync17(
53414
53668
  rec.engine.paths.daemonLock,
53415
53669
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
53416
53670
  "utf8"
@@ -53596,7 +53850,7 @@ async function startMultiDaemon(opts = {}) {
53596
53850
  baseUrl = `http://127.0.0.1:${port}`;
53597
53851
  try {
53598
53852
  ensureDir(globalDir());
53599
- writeFileSync16(
53853
+ writeFileSync17(
53600
53854
  lockPath,
53601
53855
  JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
53602
53856
  "utf8"
@@ -53605,7 +53859,7 @@ async function startMultiDaemon(opts = {}) {
53605
53859
  }
53606
53860
  for (const r of records) {
53607
53861
  try {
53608
- writeFileSync16(
53862
+ writeFileSync17(
53609
53863
  r.engine.paths.daemonLock,
53610
53864
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
53611
53865
  "utf8"
@@ -54004,7 +54258,7 @@ async function startMultiDaemon(opts = {}) {
54004
54258
  },
54005
54259
  async stop() {
54006
54260
  try {
54007
- const cur = readFileSync20(lockPath, "utf8");
54261
+ const cur = readFileSync21(lockPath, "utf8");
54008
54262
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
54009
54263
  } catch {
54010
54264
  }
@@ -54599,21 +54853,21 @@ async function cmdInit() {
54599
54853
  if (!skipHooks) {
54600
54854
  console.log("");
54601
54855
  console.log("installing harness hooks...");
54602
- const { existsSync: existsSync24 } = await import("node:fs");
54856
+ const { existsSync: existsSync25 } = await import("node:fs");
54603
54857
  const { join: join27 } = await import("node:path");
54604
54858
  try {
54605
54859
  await installClaudeHooks(port);
54606
54860
  } catch (err2) {
54607
54861
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
54608
54862
  }
54609
- if (existsSync24(join27(ROOT, ".cursor"))) {
54863
+ if (existsSync25(join27(ROOT, ".cursor"))) {
54610
54864
  try {
54611
54865
  await installCursorMcpConfig();
54612
54866
  } catch (err2) {
54613
54867
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
54614
54868
  }
54615
54869
  }
54616
- if (existsSync24(join27(ROOT, ".codex"))) {
54870
+ if (existsSync25(join27(ROOT, ".codex"))) {
54617
54871
  try {
54618
54872
  await installCodexHooks(port);
54619
54873
  } catch (err2) {
@@ -54770,8 +55024,8 @@ async function cmdStatus() {
54770
55024
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
54771
55025
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
54772
55026
  }
54773
- console.log(` graph db: ${existsSync23(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
54774
- console.log(` event log: ${existsSync23(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
55027
+ console.log(` graph db: ${existsSync24(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
55028
+ console.log(` event log: ${existsSync24(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
54775
55029
  const lockPath = globalDaemonLock();
54776
55030
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
54777
55031
  console.log(
@@ -55223,11 +55477,11 @@ async function cmdUse(args2) {
55223
55477
  }
55224
55478
  async function cmdReview() {
55225
55479
  const paths = workspacePaths(ROOT);
55226
- if (!existsSync23(paths.reviewQueue)) {
55480
+ if (!existsSync24(paths.reviewQueue)) {
55227
55481
  console.log("(review queue empty)");
55228
55482
  return;
55229
55483
  }
55230
- const queue = JSON.parse(readFileSync21(paths.reviewQueue, "utf8"));
55484
+ const queue = JSON.parse(readFileSync22(paths.reviewQueue, "utf8"));
55231
55485
  if (queue.length === 0) {
55232
55486
  console.log("(review queue empty)");
55233
55487
  return;
@@ -55881,7 +56135,7 @@ async function gatherRepo(store, ws) {
55881
56135
  };
55882
56136
  }
55883
56137
  async function gatherReportData(generatedAt) {
55884
- const { existsSync: existsSync24 } = await import("node:fs");
56138
+ const { existsSync: existsSync25 } = await import("node:fs");
55885
56139
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
55886
56140
  const cfg = loadConfig();
55887
56141
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -55889,7 +56143,7 @@ async function gatherReportData(generatedAt) {
55889
56143
  for (const ws of listWorkspaces()) {
55890
56144
  if (ws.missing) continue;
55891
56145
  const dbPath = workspacePaths(ws.path).castalia;
55892
- if (!existsSync24(dbPath)) continue;
56146
+ if (!existsSync25(dbPath)) continue;
55893
56147
  let store = null;
55894
56148
  try {
55895
56149
  store = openGraphStore2({ path: dbPath });
@@ -55920,7 +56174,7 @@ async function gatherReportData(generatedAt) {
55920
56174
  };
55921
56175
  }
55922
56176
  async function cmdReport(args2) {
55923
- const { mkdirSync: mkdirSync7, writeFileSync: writeFileSync17 } = await import("node:fs");
56177
+ const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync18 } = await import("node:fs");
55924
56178
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
55925
56179
  const includeFutureVerbs = args2.includes("--future-verbs");
55926
56180
  const now = /* @__PURE__ */ new Date();
@@ -55931,9 +56185,9 @@ async function cmdReport(args2) {
55931
56185
  process.exit(2);
55932
56186
  }
55933
56187
  const outDir = workspacePaths(ROOT).configDir;
55934
- mkdirSync7(outDir, { recursive: true });
56188
+ mkdirSync8(outDir, { recursive: true });
55935
56189
  const files = renderReport2(data, { includeFutureVerbs });
55936
- for (const f of files) writeFileSync17(join26(outDir, f.name), f.html, "utf8");
56190
+ for (const f of files) writeFileSync18(join26(outDir, f.name), f.html, "utf8");
55937
56191
  const indexPath = join26(outDir, "report.html");
55938
56192
  console.log(`report \u2192 ${indexPath}`);
55939
56193
  console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
@@ -56054,15 +56308,15 @@ function hookRelayCommand(port, path2) {
56054
56308
  return process.platform === "win32" ? `cmd //c "curl -s --connect-timeout 1 --max-time 2 -X POST -H \\"Content-Type: application/json\\" --data-binary @- ${url2} 2>NUL || echo {}"` : `curl -s --connect-timeout 1 --max-time 2 -X POST -H 'Content-Type: application/json' --data-binary @- ${url2} 2>/dev/null || echo '{}'`;
56055
56309
  }
56056
56310
  async function installClaudeHooks(port) {
56057
- const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
56311
+ const { mkdirSync: mkdirSync8, existsSync: existsSync25, readFileSync: readFileSync23, writeFileSync: writeFileSync18 } = await import("node:fs");
56058
56312
  const { join: join27 } = await import("node:path");
56059
56313
  const dir = join27(ROOT, ".claude");
56060
- if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
56314
+ if (!existsSync25(dir)) mkdirSync8(dir, { recursive: true });
56061
56315
  const file2 = join27(dir, "settings.json");
56062
56316
  let settings = {};
56063
- if (existsSync24(file2)) {
56317
+ if (existsSync25(file2)) {
56064
56318
  try {
56065
- settings = JSON.parse(readFileSync22(file2, "utf8"));
56319
+ settings = JSON.parse(readFileSync23(file2, "utf8"));
56066
56320
  } catch {
56067
56321
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
56068
56322
  process.exit(2);
@@ -56070,7 +56324,7 @@ async function installClaudeHooks(port) {
56070
56324
  }
56071
56325
  const matcher = "Read|Edit|Write|Grep|Glob|NotebookEdit|Bash";
56072
56326
  const postMatcher = `${matcher}|ToolSearch|mcp__errata__.*`;
56073
- const preCmd = `${hookCurlCommand(port)} ${ERRATA_TAG}`;
56327
+ const preCmd = `${hookRelayCommand(port, "/api/hook")} ${ERRATA_TAG}`;
56074
56328
  const postCmd = `${hookRelayCommand(port, "/api/hook")} ${ERRATA_TAG}`;
56075
56329
  settings.hooks ??= {};
56076
56330
  const dropErrata = (list) => {
@@ -56108,7 +56362,7 @@ async function installClaudeHooks(port) {
56108
56362
  dropErrata(list);
56109
56363
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
56110
56364
  }
56111
- writeFileSync17(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
56365
+ writeFileSync18(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
56112
56366
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
56113
56367
  await installClaudeMcpConfig();
56114
56368
  const claudeMd = join27(ROOT, "CLAUDE.md");
@@ -56123,15 +56377,15 @@ async function installClaudeHooks(port) {
56123
56377
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
56124
56378
  }
56125
56379
  async function installClaudeMcpConfig() {
56126
- const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
56127
- const { join: join27, dirname: dirname9 } = await import("node:path");
56380
+ const { mkdirSync: mkdirSync8, existsSync: existsSync25, readFileSync: readFileSync23, writeFileSync: writeFileSync18 } = await import("node:fs");
56381
+ const { join: join27, dirname: dirname10 } = await import("node:path");
56128
56382
  const file2 = join27(ROOT, ".mcp.json");
56129
- const dir = dirname9(file2);
56130
- if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
56383
+ const dir = dirname10(file2);
56384
+ if (!existsSync25(dir)) mkdirSync8(dir, { recursive: true });
56131
56385
  let cfg = {};
56132
- if (existsSync24(file2)) {
56386
+ if (existsSync25(file2)) {
56133
56387
  try {
56134
- cfg = JSON.parse(readFileSync22(file2, "utf8"));
56388
+ cfg = JSON.parse(readFileSync23(file2, "utf8"));
56135
56389
  } catch {
56136
56390
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
56137
56391
  process.exit(2);
@@ -56139,21 +56393,21 @@ async function installClaudeMcpConfig() {
56139
56393
  }
56140
56394
  cfg.mcpServers ??= {};
56141
56395
  cfg.mcpServers["errata"] = errataMcpInvocation();
56142
- writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
56396
+ writeFileSync18(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
56143
56397
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
56144
56398
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
56145
56399
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
56146
56400
  }
56147
56401
  async function installCursorMcpConfig() {
56148
- const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
56402
+ const { mkdirSync: mkdirSync8, existsSync: existsSync25, readFileSync: readFileSync23, writeFileSync: writeFileSync18 } = await import("node:fs");
56149
56403
  const { join: join27 } = await import("node:path");
56150
56404
  const dir = join27(ROOT, ".cursor");
56151
- if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
56405
+ if (!existsSync25(dir)) mkdirSync8(dir, { recursive: true });
56152
56406
  const file2 = join27(dir, "mcp.json");
56153
56407
  let cfg = {};
56154
- if (existsSync24(file2)) {
56408
+ if (existsSync25(file2)) {
56155
56409
  try {
56156
- cfg = JSON.parse(readFileSync22(file2, "utf8"));
56410
+ cfg = JSON.parse(readFileSync23(file2, "utf8"));
56157
56411
  } catch {
56158
56412
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
56159
56413
  process.exit(2);
@@ -56161,7 +56415,7 @@ async function installCursorMcpConfig() {
56161
56415
  }
56162
56416
  cfg.mcpServers ??= {};
56163
56417
  cfg.mcpServers["errata"] = errataMcpInvocation();
56164
- writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
56418
+ writeFileSync18(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
56165
56419
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
56166
56420
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
56167
56421
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -56169,16 +56423,16 @@ async function installCursorMcpConfig() {
56169
56423
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
56170
56424
  }
56171
56425
  async function installCodexHooks(port) {
56172
- const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
56426
+ const { mkdirSync: mkdirSync8, existsSync: existsSync25, readFileSync: readFileSync23, writeFileSync: writeFileSync18 } = await import("node:fs");
56173
56427
  const { join: join27 } = await import("node:path");
56174
56428
  const dir = join27(ROOT, ".codex");
56175
- if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
56429
+ if (!existsSync25(dir)) mkdirSync8(dir, { recursive: true });
56176
56430
  const file2 = join27(dir, "config.toml");
56177
56431
  const BEGIN = `# >>> errata hooks (errata-managed)`;
56178
56432
  const END = `# <<< errata hooks`;
56179
56433
  let existing = "";
56180
- if (existsSync24(file2)) {
56181
- existing = readFileSync22(file2, "utf8");
56434
+ if (existsSync25(file2)) {
56435
+ existing = readFileSync23(file2, "utf8");
56182
56436
  const beginIdx = existing.indexOf(BEGIN);
56183
56437
  const endIdx = existing.indexOf(END);
56184
56438
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -56207,7 +56461,7 @@ ${END}
56207
56461
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
56208
56462
 
56209
56463
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
56210
- writeFileSync17(file2, final, "utf8");
56464
+ writeFileSync18(file2, final, "utf8");
56211
56465
  console.log(`installed Codex hooks \u2192 ${file2}`);
56212
56466
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
56213
56467
  console.log("");