@inerrata-corporation/errata 2.0.0-dev.71 → 2.0.0-dev.72

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.
Files changed (2) hide show
  1. package/errata.mjs +289 -130
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -20362,13 +20362,8 @@ function renderSnapshot(s) {
20362
20362
  if (s.skills.length > 0) {
20363
20363
  lines.push("### Skills available");
20364
20364
  lines.push(
20365
- `${s.skills.length} induced skill${s.skills.length === 1 ? "" : "s"} for this workspace. Read the body before applying; full manifest at \`.errata/skills.json\`.`
20365
+ `${s.skills.length} induced skill${s.skills.length === 1 ? "" : "s"} for this workspace, installed as \`SKILL.md\` under \`.agents/skills/\` (and your harness's skills dir) \u2014 invoke natively. No auto-discovery (e.g. Aider)? \`/read-only\` the relevant \`.agents/skills/errata-*/SKILL.md\`.`
20366
20366
  );
20367
- for (const sk of [...s.skills].sort((a, b) => b.confidence - a.confidence).slice(0, 10)) {
20368
- lines.push(
20369
- `- **${sk.title}** (${sk.layer}, ${(sk.confidence * 100).toFixed(0)}%) \u2192 \`.errata/${sk.file}\``
20370
- );
20371
- }
20372
20367
  lines.push("");
20373
20368
  }
20374
20369
  lines.push("### Prior knowledge sampled from the shared graph");
@@ -38554,12 +38549,12 @@ var init_report_render = __esm({
38554
38549
 
38555
38550
  // src/cli.ts
38556
38551
  init_src5();
38557
- import { closeSync as closeSync2, existsSync as existsSync22, openSync as openSync2, readFileSync as readFileSync20, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
38558
- import { join as join25 } from "node:path";
38552
+ import { closeSync as closeSync2, existsSync as existsSync23, openSync as openSync2, readFileSync as readFileSync21, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
38553
+ import { join as join26 } from "node:path";
38559
38554
  import { spawn as spawn3 } from "node:child_process";
38560
38555
 
38561
38556
  // src/daemon.ts
38562
- import { existsSync as existsSync17, writeFileSync as writeFileSync13 } from "node:fs";
38557
+ import { existsSync as existsSync18, writeFileSync as writeFileSync14 } from "node:fs";
38563
38558
 
38564
38559
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
38565
38560
  import { createServer as createServerHTTP } from "http";
@@ -39139,8 +39134,8 @@ init_config();
39139
39134
 
39140
39135
  // src/engine.ts
39141
39136
  import { execFileSync as execFileSync3 } from "node:child_process";
39142
- import { existsSync as existsSync16, statSync as statSync5, appendFileSync as appendFileSync2, readdirSync as readdirSync7, renameSync as renameSync2, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
39143
- import { join as join21, relative as relative6, sep as sep4 } from "node:path";
39137
+ 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";
39138
+ import { join as join22, relative as relative6, sep as sep4 } from "node:path";
39144
39139
 
39145
39140
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
39146
39141
  import { stat as statcb } from "fs";
@@ -42627,6 +42622,164 @@ async function syncSkills(paths, client, seed, pins = []) {
42627
42622
  return { written: rows.length, pruned, ...staleDaemon ? { staleDaemon } : {} };
42628
42623
  }
42629
42624
 
42625
+ // src/agent-skills.ts
42626
+ import {
42627
+ cpSync,
42628
+ existsSync as existsSync14,
42629
+ lstatSync,
42630
+ mkdirSync as mkdirSync6,
42631
+ readFileSync as readFileSync13,
42632
+ readdirSync as readdirSync7,
42633
+ rmSync as rmSync2,
42634
+ symlinkSync,
42635
+ writeFileSync as writeFileSync11
42636
+ } from "node:fs";
42637
+ import { join as join19 } from "node:path";
42638
+ var SKILL_NS = "errata-";
42639
+ var HARNESS_SKILL_DIRS = [
42640
+ { configDir: ".claude", skillsDir: join19(".claude", "skills") },
42641
+ // Cursor adopted the standard; its exact project dir is still moving — kept
42642
+ // best-effort and gated on `.cursor/` presence so we never create it blind.
42643
+ { configDir: ".cursor", skillsDir: join19(".cursor", "skills") }
42644
+ ];
42645
+ function skillSlug(title, id) {
42646
+ const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
42647
+ return `${SKILL_NS}${base}`.slice(0, 64).replace(/-+$/, "");
42648
+ }
42649
+ function yamlScalar(s) {
42650
+ return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\s+/g, " ").trim()}"`;
42651
+ }
42652
+ function deriveDescription(title, layer, body2) {
42653
+ const firstProse = body2.split(/\r?\n/).map((l) => l.trim()).find((l) => l.length > 0 && !l.startsWith("#") && !l.startsWith("---"));
42654
+ const lead = firstProse && firstProse.length >= 24 ? firstProse : title;
42655
+ const when = ` Apply when working on ${layer === "antipattern" ? "code that risks this pitfall" : "problems in this area"}.`;
42656
+ return `${lead}${lead.endsWith(".") ? "" : "."}${when}`.slice(0, 1024);
42657
+ }
42658
+ function renderSkillMd(name2, description, body2) {
42659
+ return `---
42660
+ name: ${name2}
42661
+ description: ${yamlScalar(description)}
42662
+ ---
42663
+
42664
+ ${body2.trimEnd()}
42665
+ `;
42666
+ }
42667
+ function reconcileNamespaced(dir, keep) {
42668
+ if (!existsSync14(dir)) return 0;
42669
+ let pruned = 0;
42670
+ for (const name2 of readdirSync7(dir)) {
42671
+ if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
42672
+ try {
42673
+ rmSync2(join19(dir, name2), { recursive: true, force: true });
42674
+ pruned++;
42675
+ } catch {
42676
+ }
42677
+ }
42678
+ return pruned;
42679
+ }
42680
+ function linkOrCopy(linkPath, target) {
42681
+ try {
42682
+ if (existsSync14(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
42683
+ } catch {
42684
+ }
42685
+ try {
42686
+ symlinkSync(target, linkPath, "junction");
42687
+ } catch {
42688
+ try {
42689
+ cpSync(target, linkPath, { recursive: true });
42690
+ } catch {
42691
+ }
42692
+ }
42693
+ }
42694
+ function safeLstat(p) {
42695
+ try {
42696
+ lstatSync(p);
42697
+ return true;
42698
+ } catch {
42699
+ return false;
42700
+ }
42701
+ }
42702
+ function emitAndProjectSkills(root, skills) {
42703
+ const agentsSkillsDir = join19(root, ".agents", "skills");
42704
+ mkdirSync6(agentsSkillsDir, { recursive: true });
42705
+ const slugs = [];
42706
+ const keep = /* @__PURE__ */ new Set();
42707
+ let emitted = 0;
42708
+ for (const s of skills) {
42709
+ let body2;
42710
+ try {
42711
+ body2 = readFileSync13(s.bodyPath, "utf8");
42712
+ } catch {
42713
+ continue;
42714
+ }
42715
+ const slug2 = skillSlug(s.title, s.id);
42716
+ if (keep.has(slug2)) continue;
42717
+ keep.add(slug2);
42718
+ slugs.push(slug2);
42719
+ const description = deriveDescription(s.title, s.layer, body2);
42720
+ mkdirSync6(join19(agentsSkillsDir, slug2), { recursive: true });
42721
+ writeFileSync11(
42722
+ join19(agentsSkillsDir, slug2, "SKILL.md"),
42723
+ renderSkillMd(slug2, description, body2),
42724
+ "utf8"
42725
+ );
42726
+ emitted++;
42727
+ }
42728
+ reconcileNamespaced(agentsSkillsDir, keep);
42729
+ let projected = 0;
42730
+ for (const h of HARNESS_SKILL_DIRS) {
42731
+ if (!existsSync14(join19(root, h.configDir))) continue;
42732
+ const dir = join19(root, h.skillsDir);
42733
+ mkdirSync6(dir, { recursive: true });
42734
+ for (const slug2 of slugs) {
42735
+ linkOrCopy(join19(dir, slug2), join19(agentsSkillsDir, slug2));
42736
+ projected++;
42737
+ }
42738
+ reconcileNamespaced(dir, keep);
42739
+ }
42740
+ ensureSkillGitignore(root);
42741
+ return { slugs, emitted, projected };
42742
+ }
42743
+ function emitInputsFromManifest(erretaDir, manifestPath) {
42744
+ if (!existsSync14(manifestPath)) return [];
42745
+ try {
42746
+ const parsed = JSON.parse(readFileSync13(manifestPath, "utf8"));
42747
+ return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
42748
+ id: s.id,
42749
+ title: s.title ?? s.id,
42750
+ layer: s.layer ?? "technique",
42751
+ confidence: s.confidence ?? 0,
42752
+ bodyPath: join19(erretaDir, s.file)
42753
+ }));
42754
+ } catch {
42755
+ return [];
42756
+ }
42757
+ }
42758
+ var GITIGNORE_MARK = "# errata-managed agent skills (daemon-synced; namespaced)";
42759
+ var GITIGNORE_LINES = [
42760
+ GITIGNORE_MARK,
42761
+ ".agents/skills/errata-*/",
42762
+ ".claude/skills/errata-*/",
42763
+ ".cursor/skills/errata-*/"
42764
+ ];
42765
+ function ensureSkillGitignore(root) {
42766
+ const path2 = join19(root, ".gitignore");
42767
+ let current = "";
42768
+ try {
42769
+ current = existsSync14(path2) ? readFileSync13(path2, "utf8") : "";
42770
+ } catch {
42771
+ return;
42772
+ }
42773
+ if (current.includes(GITIGNORE_MARK)) return;
42774
+ const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
42775
+ try {
42776
+ writeFileSync11(path2, `${current}${prefix}
42777
+ ${GITIGNORE_LINES.join("\n")}
42778
+ `, "utf8");
42779
+ } catch {
42780
+ }
42781
+ }
42782
+
42630
42783
  // src/working-file-state.ts
42631
42784
  function createWorkingFileState() {
42632
42785
  const bySession = /* @__PURE__ */ new Map();
@@ -42756,20 +42909,20 @@ var CausalBuffer = class {
42756
42909
  // src/profile.ts
42757
42910
  init_src2();
42758
42911
  init_paths();
42759
- import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
42912
+ import { existsSync as existsSync16, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
42760
42913
  import { createHash as createHash12 } from "node:crypto";
42761
- import { join as join20 } from "node:path";
42914
+ import { join as join21 } from "node:path";
42762
42915
 
42763
42916
  // src/git-remote.ts
42764
42917
  init_src();
42765
- import { existsSync as existsSync14, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
42766
- import { isAbsolute as isAbsolute3, join as join19, resolve as resolve5 } from "node:path";
42918
+ import { existsSync as existsSync15, readFileSync as readFileSync14, statSync as statSync4 } from "node:fs";
42919
+ import { isAbsolute as isAbsolute3, join as join20, resolve as resolve5 } from "node:path";
42767
42920
  function resolveGitDir(root) {
42768
- const dotGit = join19(root, ".git");
42921
+ const dotGit = join20(root, ".git");
42769
42922
  try {
42770
42923
  const st = statSync4(dotGit);
42771
42924
  if (st.isDirectory()) return dotGit;
42772
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync13(dotGit, "utf8"));
42925
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync14(dotGit, "utf8"));
42773
42926
  if (!m) return null;
42774
42927
  const dir = m[1];
42775
42928
  return isAbsolute3(dir) ? dir : resolve5(root, dir);
@@ -42778,22 +42931,22 @@ function resolveGitDir(root) {
42778
42931
  }
42779
42932
  }
42780
42933
  function gitConfigPath(gitDir) {
42781
- const commondirFile = join19(gitDir, "commondir");
42782
- if (existsSync14(commondirFile)) {
42783
- const common = readFileSync13(commondirFile, "utf8").trim();
42934
+ const commondirFile = join20(gitDir, "commondir");
42935
+ if (existsSync15(commondirFile)) {
42936
+ const common = readFileSync14(commondirFile, "utf8").trim();
42784
42937
  const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
42785
- return join19(commonDir, "config");
42938
+ return join20(commonDir, "config");
42786
42939
  }
42787
- return join19(gitDir, "config");
42940
+ return join20(gitDir, "config");
42788
42941
  }
42789
42942
  function readRemotes(root) {
42790
42943
  const gitDir = resolveGitDir(root);
42791
42944
  if (!gitDir) return [];
42792
42945
  const cfgPath = gitConfigPath(gitDir);
42793
- if (!existsSync14(cfgPath)) return [];
42946
+ if (!existsSync15(cfgPath)) return [];
42794
42947
  let txt;
42795
42948
  try {
42796
- txt = readFileSync13(cfgPath, "utf8");
42949
+ txt = readFileSync14(cfgPath, "utf8");
42797
42950
  } catch {
42798
42951
  return [];
42799
42952
  }
@@ -42825,13 +42978,13 @@ function refreshRepoLocator(root, profile) {
42825
42978
  }
42826
42979
  function loadProfile(root) {
42827
42980
  const p = workspacePaths(root);
42828
- if (!existsSync15(p.workspaceJson)) return null;
42829
- return JSON.parse(readFileSync14(p.workspaceJson, "utf8"));
42981
+ if (!existsSync16(p.workspaceJson)) return null;
42982
+ return JSON.parse(readFileSync15(p.workspaceJson, "utf8"));
42830
42983
  }
42831
42984
  function saveProfile(root, profile) {
42832
42985
  const p = workspacePaths(root);
42833
42986
  ensureDir(p.configDir);
42834
- writeFileSync11(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
42987
+ writeFileSync12(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
42835
42988
  }
42836
42989
  function autodetectProfile(root) {
42837
42990
  const id = workspaceId(root);
@@ -42839,10 +42992,10 @@ function autodetectProfile(root) {
42839
42992
  const p = emptyProfile(id, name2);
42840
42993
  const locator = detectRepoLocator(root);
42841
42994
  if (locator) p.repoLocator = locator;
42842
- const pkgPath = join20(root, "package.json");
42843
- if (existsSync15(pkgPath)) {
42995
+ const pkgPath = join21(root, "package.json");
42996
+ if (existsSync16(pkgPath)) {
42844
42997
  try {
42845
- const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
42998
+ const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
42846
42999
  p.languages.push("typescript", "javascript");
42847
43000
  const nodeVer = pkg.engines?.node ?? "node";
42848
43001
  p.stack.push(`node@${nodeVer}`);
@@ -42863,10 +43016,10 @@ function autodetectProfile(root) {
42863
43016
  } catch {
42864
43017
  }
42865
43018
  }
42866
- const pyproject = join20(root, "pyproject.toml");
42867
- if (existsSync15(pyproject)) {
43019
+ const pyproject = join21(root, "pyproject.toml");
43020
+ if (existsSync16(pyproject)) {
42868
43021
  try {
42869
- const txt = readFileSync14(pyproject, "utf8");
43022
+ const txt = readFileSync15(pyproject, "utf8");
42870
43023
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
42871
43024
  p.languages.push("python");
42872
43025
  p.stack.push(`python@${py ?? "3"}`);
@@ -42877,16 +43030,16 @@ function autodetectProfile(root) {
42877
43030
  } catch {
42878
43031
  }
42879
43032
  }
42880
- const reqs = join20(root, "requirements.txt");
42881
- if (existsSync15(reqs)) {
43033
+ const reqs = join21(root, "requirements.txt");
43034
+ if (existsSync16(reqs)) {
42882
43035
  if (!p.languages.includes("python")) p.languages.push("python");
42883
43036
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
42884
43037
  }
42885
- if (existsSync15(join20(root, "go.mod"))) {
43038
+ if (existsSync16(join21(root, "go.mod"))) {
42886
43039
  p.languages.push("go");
42887
43040
  p.stack.push("go");
42888
43041
  }
42889
- if (existsSync15(join20(root, "Cargo.toml"))) {
43042
+ if (existsSync16(join21(root, "Cargo.toml"))) {
42890
43043
  p.languages.push("rust");
42891
43044
  p.stack.push("rust");
42892
43045
  }
@@ -43044,7 +43197,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
43044
43197
  }
43045
43198
 
43046
43199
  // src/engine.ts
43047
- var DAEMON_VERSION = true ? "2.0.0-dev.71" : "2.0.0-alpha.0";
43200
+ var DAEMON_VERSION = true ? "2.0.0-dev.72" : "2.0.0-alpha.0";
43048
43201
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
43049
43202
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
43050
43203
  var GIT_OP_MUTE_MS = 4e3;
@@ -43054,7 +43207,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
43054
43207
  function appendIdentityAudit(path2, record2, line) {
43055
43208
  if (!record2.accepted && record2.score <= 0) return;
43056
43209
  try {
43057
- if (existsSync16(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
43210
+ if (existsSync17(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
43058
43211
  renameSync2(path2, `${path2}.1`);
43059
43212
  }
43060
43213
  appendFileSync2(path2, line);
@@ -43064,14 +43217,14 @@ function appendIdentityAudit(path2, record2, line) {
43064
43217
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
43065
43218
  function loadTurnCursors(path2) {
43066
43219
  try {
43067
- return new Map(Object.entries(JSON.parse(readFileSync15(path2, "utf8"))));
43220
+ return new Map(Object.entries(JSON.parse(readFileSync16(path2, "utf8"))));
43068
43221
  } catch {
43069
43222
  return /* @__PURE__ */ new Map();
43070
43223
  }
43071
43224
  }
43072
43225
  function saveTurnCursors(path2, cursors) {
43073
43226
  try {
43074
- writeFileSync12(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
43227
+ writeFileSync13(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
43075
43228
  } catch {
43076
43229
  }
43077
43230
  }
@@ -43093,7 +43246,7 @@ function gitSourceWatchTargets(root) {
43093
43246
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
43094
43247
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
43095
43248
  );
43096
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join21(root, d) + sep4));
43249
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join22(root, d) + sep4));
43097
43250
  } catch {
43098
43251
  }
43099
43252
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -43105,19 +43258,19 @@ function gitSourceWatchTargets(root) {
43105
43258
  if (!f.startsWith(prefix)) continue;
43106
43259
  const rest2 = f.slice(prefix.length);
43107
43260
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
43108
- else targets.add(join21(root, f));
43261
+ else targets.add(join22(root, f));
43109
43262
  }
43110
43263
  for (const c of children) {
43111
- if (IGNORED_PATH.test(join21(root, c) + sep4)) continue;
43264
+ if (IGNORED_PATH.test(join22(root, c) + sep4)) continue;
43112
43265
  if (hasIgnoredChild(c)) addUnder(c);
43113
- else targets.add(join21(root, c));
43266
+ else targets.add(join22(root, c));
43114
43267
  }
43115
43268
  };
43116
43269
  addUnder("");
43117
43270
  if (targets.size > 0) return [...targets];
43118
43271
  } catch {
43119
43272
  }
43120
- return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join21(root, String(e.name)) + sep4)).map((e) => join21(root, String(e.name)));
43273
+ return readdirSync8(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join22(root, String(e.name)) + sep4)).map((e) => join22(root, String(e.name)));
43121
43274
  }
43122
43275
  function createWorkspaceEngine(opts) {
43123
43276
  const paths = workspacePaths(opts.workspaceRoot);
@@ -43271,7 +43424,7 @@ function createWorkspaceEngine(opts) {
43271
43424
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
43272
43425
  let episodeId2;
43273
43426
  if (srcPaths.length > 0) {
43274
- const abs = srcPaths.map((p) => join21(opts.workspaceRoot, p));
43427
+ const abs = srcPaths.map((p) => join22(opts.workspaceRoot, p));
43275
43428
  try {
43276
43429
  const r = await runReindexPass(
43277
43430
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -43307,8 +43460,8 @@ function createWorkspaceEngine(opts) {
43307
43460
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
43308
43461
  );
43309
43462
  };
43310
- const gitDir = join21(opts.workspaceRoot, ".git");
43311
- if (existsSync16(gitDir)) {
43463
+ const gitDir = join22(opts.workspaceRoot, ".git");
43464
+ if (existsSync17(gitDir)) {
43312
43465
  stopGit = startGitSensor(gitDir, (ev) => {
43313
43466
  void handleGitEvent(ev).catch((err2) => {
43314
43467
  console.warn("[errata] git event handler failed:", err2);
@@ -43376,10 +43529,10 @@ function createWorkspaceEngine(opts) {
43376
43529
  ...pendingUpdate ? { pendingUpdate } : {}
43377
43530
  });
43378
43531
  doneRender?.();
43379
- const target = join21(opts.workspaceRoot, "AGENTS.md");
43532
+ const target = join22(opts.workspaceRoot, "AGENTS.md");
43380
43533
  writeManagedBlock(target, { body: body2 });
43381
43534
  if (elicit) {
43382
- writePrimingHandles(join21(paths.configDir, "priming-handles.json"), [
43535
+ writePrimingHandles(join22(paths.configDir, "priming-handles.json"), [
43383
43536
  ...snapshot.recentProblems.map((r) => r.node),
43384
43537
  // Resolved-band handles: the ✓ problem AND its Solution are citable
43385
43538
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -43549,7 +43702,7 @@ function createWorkspaceEngine(opts) {
43549
43702
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
43550
43703
  });
43551
43704
  };
43552
- const turnCursorPath = join21(paths.configDir, "turn-cursors.json");
43705
+ const turnCursorPath = join22(paths.configDir, "turn-cursors.json");
43553
43706
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
43554
43707
  const sessionLastProblem = /* @__PURE__ */ new Map();
43555
43708
  const sessionThreads = /* @__PURE__ */ new Map();
@@ -43572,7 +43725,7 @@ function createWorkspaceEngine(opts) {
43572
43725
  const t = Date.now();
43573
43726
  let processedTurns = 0;
43574
43727
  const elicit = isEdgeElicitationEnabled();
43575
- const handleMap = elicit ? readPrimingHandles(join21(paths.configDir, "priming-handles.json")) : {};
43728
+ const handleMap = elicit ? readPrimingHandles(join22(paths.configDir, "priming-handles.json")) : {};
43576
43729
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
43577
43730
  const toRel = (abs) => {
43578
43731
  const p = abs.replace(/\\/g, "/");
@@ -44049,7 +44202,13 @@ function createWorkspaceEngine(opts) {
44049
44202
  return typeof cloudId === "string" && cloudId !== p.id ? [p.id, cloudId] : [p.id];
44050
44203
  });
44051
44204
  const pins = profile?.projectId ? await cloud.getSkillPins(profile.projectId).then((r) => r.pins).catch(() => []) : [];
44052
- return syncSkills(paths, cloud, skillSeed, pins);
44205
+ const result = await syncSkills(paths, cloud, skillSeed, pins);
44206
+ try {
44207
+ emitAndProjectSkills(opts.workspaceRoot, emitInputsFromManifest(paths.configDir, paths.skillsManifest));
44208
+ } catch (err2) {
44209
+ console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
44210
+ }
44211
+ return result;
44053
44212
  };
44054
44213
  return {
44055
44214
  profile,
@@ -44231,7 +44390,7 @@ function createWorkspaceEngine(opts) {
44231
44390
  console.log(
44232
44391
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
44233
44392
  );
44234
- const pending = existsSync16(paths.outbox) ? readdirSync7(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
44393
+ const pending = existsSync17(paths.outbox) ? readdirSync8(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
44235
44394
  return { uploaded: 0, failed: 0, remaining: pending };
44236
44395
  }
44237
44396
  try {
@@ -44318,7 +44477,7 @@ async function startDaemon(opts) {
44318
44477
  reviewUrl: () => webUiUrl + "/review"
44319
44478
  });
44320
44479
  const writeLockFile = (url2) => {
44321
- writeFileSync13(
44480
+ writeFileSync14(
44322
44481
  engine.paths.daemonLock,
44323
44482
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
44324
44483
  "utf8"
@@ -44361,7 +44520,7 @@ async function startDaemon(opts) {
44361
44520
  );
44362
44521
  await engine.stop();
44363
44522
  try {
44364
- if (existsSync17(engine.paths.daemonLock)) {
44523
+ if (existsSync18(engine.paths.daemonLock)) {
44365
44524
  }
44366
44525
  } catch {
44367
44526
  }
@@ -44378,16 +44537,16 @@ async function listenServer(fetchFn, port) {
44378
44537
 
44379
44538
  // src/registry.ts
44380
44539
  init_paths();
44381
- import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
44382
- import { join as join22 } from "node:path";
44540
+ import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
44541
+ import { join as join23 } from "node:path";
44383
44542
  function registryPath() {
44384
- return process.env["ERRATA_REGISTRY_PATH"] ?? join22(globalDir(), "workspaces.json");
44543
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join23(globalDir(), "workspaces.json");
44385
44544
  }
44386
44545
  function read() {
44387
44546
  const p = registryPath();
44388
- if (!existsSync18(p)) return { version: 1, workspaces: {} };
44547
+ if (!existsSync19(p)) return { version: 1, workspaces: {} };
44389
44548
  try {
44390
- const parsed = JSON.parse(readFileSync16(p, "utf8"));
44549
+ const parsed = JSON.parse(readFileSync17(p, "utf8"));
44391
44550
  return { version: 1, workspaces: parsed.workspaces ?? {} };
44392
44551
  } catch {
44393
44552
  return { version: 1, workspaces: {} };
@@ -44395,7 +44554,7 @@ function read() {
44395
44554
  }
44396
44555
  function write(reg) {
44397
44556
  ensureDir(globalDir());
44398
- writeFileSync14(registryPath(), JSON.stringify(reg, null, 2), "utf8");
44557
+ writeFileSync15(registryPath(), JSON.stringify(reg, null, 2), "utf8");
44399
44558
  }
44400
44559
  function registerWorkspace(profile, root, now = Date.now()) {
44401
44560
  const reg = read();
@@ -44412,7 +44571,7 @@ function pruneMissingWorkspaces() {
44412
44571
  const reg = read();
44413
44572
  const removed = [];
44414
44573
  for (const [id, entry] of Object.entries(reg.workspaces)) {
44415
- if (!existsSync18(entry.path)) {
44574
+ if (!existsSync19(entry.path)) {
44416
44575
  removed.push(entry);
44417
44576
  delete reg.workspaces[id];
44418
44577
  }
@@ -44421,13 +44580,13 @@ function pruneMissingWorkspaces() {
44421
44580
  return removed;
44422
44581
  }
44423
44582
  function workspaceStatus(entry) {
44424
- const missing = !existsSync18(entry.path);
44583
+ const missing = !existsSync19(entry.path);
44425
44584
  const lockPath = workspacePaths(entry.path).daemonLock;
44426
44585
  let running = false;
44427
44586
  let webUiUrl = null;
44428
- if (existsSync18(lockPath)) {
44587
+ if (existsSync19(lockPath)) {
44429
44588
  try {
44430
- const lock = JSON.parse(readFileSync16(lockPath, "utf8"));
44589
+ const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
44431
44590
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
44432
44591
  running = true;
44433
44592
  webUiUrl = lock.webUiUrl;
@@ -44455,7 +44614,7 @@ function pidAlive(pid) {
44455
44614
  // src/multi.ts
44456
44615
  init_dist();
44457
44616
  init_src4();
44458
- import { readFileSync as readFileSync19, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
44617
+ import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync16 } from "node:fs";
44459
44618
 
44460
44619
  // src/principle-sync.ts
44461
44620
  init_src4();
@@ -44482,8 +44641,8 @@ async function syncPrinciples(store, cloud, opts) {
44482
44641
  init_reconcile();
44483
44642
 
44484
44643
  // src/lockfile-auto.ts
44485
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
44486
- import { join as join23 } from "node:path";
44644
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
44645
+ import { join as join24 } from "node:path";
44487
44646
 
44488
44647
  // src/package-index.ts
44489
44648
  init_src();
@@ -44747,11 +44906,11 @@ function runLockfilePass(opts) {
44747
44906
  { file: "package-lock.json", parse: parsePackageLockJson }
44748
44907
  ];
44749
44908
  for (const c of candidates) {
44750
- const p = join23(opts.root, c.file);
44751
- if (!existsSync19(p)) continue;
44909
+ const p = join24(opts.root, c.file);
44910
+ if (!existsSync20(p)) continue;
44752
44911
  let sbom;
44753
44912
  try {
44754
- sbom = c.parse(readFileSync17(p, "utf8"));
44913
+ sbom = c.parse(readFileSync18(p, "utf8"));
44755
44914
  } catch {
44756
44915
  continue;
44757
44916
  }
@@ -45027,7 +45186,7 @@ var ConsolidateWorker = class {
45027
45186
  init_paths();
45028
45187
 
45029
45188
  // src/lock.ts
45030
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
45189
+ import { existsSync as existsSync21, readFileSync as readFileSync19 } from "node:fs";
45031
45190
  function isProcessAlive(pid) {
45032
45191
  if (!pid || pid <= 0) return false;
45033
45192
  try {
@@ -45038,9 +45197,9 @@ function isProcessAlive(pid) {
45038
45197
  }
45039
45198
  }
45040
45199
  function readDaemonLock(lockPath) {
45041
- if (!existsSync20(lockPath)) return null;
45200
+ if (!existsSync21(lockPath)) return null;
45042
45201
  try {
45043
- const lock = JSON.parse(readFileSync18(lockPath, "utf8"));
45202
+ const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
45044
45203
  return typeof lock.pid === "number" ? lock : null;
45045
45204
  } catch {
45046
45205
  return null;
@@ -45164,12 +45323,12 @@ async function ensureProjectLink(root, profile, client) {
45164
45323
  }
45165
45324
 
45166
45325
  // src/adopt.ts
45167
- import { existsSync as existsSync21 } from "node:fs";
45168
- import { dirname as dirname8, join as join24 } from "node:path";
45326
+ import { existsSync as existsSync22 } from "node:fs";
45327
+ import { dirname as dirname8, join as join25 } from "node:path";
45169
45328
  function findGitRoot(absPath) {
45170
45329
  let dir = absPath;
45171
45330
  for (let depth = 0; depth < 64; depth++) {
45172
- if (existsSync21(join24(dir, ".git"))) return dir;
45331
+ if (existsSync22(join25(dir, ".git"))) return dir;
45173
45332
  const parent = dirname8(dir);
45174
45333
  if (parent === dir) return null;
45175
45334
  dir = parent;
@@ -45357,7 +45516,7 @@ async function startMultiDaemon(opts = {}) {
45357
45516
  void ambientLinkAll();
45358
45517
  app.route(`/ws/${rec.id}`, rec.webApp);
45359
45518
  try {
45360
- writeFileSync15(
45519
+ writeFileSync16(
45361
45520
  rec.engine.paths.daemonLock,
45362
45521
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
45363
45522
  "utf8"
@@ -45543,7 +45702,7 @@ async function startMultiDaemon(opts = {}) {
45543
45702
  baseUrl = `http://127.0.0.1:${port}`;
45544
45703
  try {
45545
45704
  ensureDir(globalDir());
45546
- writeFileSync15(
45705
+ writeFileSync16(
45547
45706
  lockPath,
45548
45707
  JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
45549
45708
  "utf8"
@@ -45552,7 +45711,7 @@ async function startMultiDaemon(opts = {}) {
45552
45711
  }
45553
45712
  for (const r of records) {
45554
45713
  try {
45555
- writeFileSync15(
45714
+ writeFileSync16(
45556
45715
  r.engine.paths.daemonLock,
45557
45716
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
45558
45717
  "utf8"
@@ -45906,7 +46065,7 @@ async function startMultiDaemon(opts = {}) {
45906
46065
  },
45907
46066
  async stop() {
45908
46067
  try {
45909
- const cur = readFileSync19(lockPath, "utf8");
46068
+ const cur = readFileSync20(lockPath, "utf8");
45910
46069
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
45911
46070
  } catch {
45912
46071
  }
@@ -46501,21 +46660,21 @@ async function cmdInit() {
46501
46660
  if (!skipHooks) {
46502
46661
  console.log("");
46503
46662
  console.log("installing harness hooks...");
46504
- const { existsSync: existsSync23 } = await import("node:fs");
46505
- const { join: join26 } = await import("node:path");
46663
+ const { existsSync: existsSync24 } = await import("node:fs");
46664
+ const { join: join27 } = await import("node:path");
46506
46665
  try {
46507
46666
  await installClaudeHooks(port);
46508
46667
  } catch (err2) {
46509
46668
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
46510
46669
  }
46511
- if (existsSync23(join26(ROOT, ".cursor"))) {
46670
+ if (existsSync24(join27(ROOT, ".cursor"))) {
46512
46671
  try {
46513
46672
  await installCursorMcpConfig();
46514
46673
  } catch (err2) {
46515
46674
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
46516
46675
  }
46517
46676
  }
46518
- if (existsSync23(join26(ROOT, ".codex"))) {
46677
+ if (existsSync24(join27(ROOT, ".codex"))) {
46519
46678
  try {
46520
46679
  await installCodexHooks(port);
46521
46680
  } catch (err2) {
@@ -46672,8 +46831,8 @@ async function cmdStatus() {
46672
46831
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
46673
46832
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
46674
46833
  }
46675
- console.log(` graph db: ${existsSync22(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46676
- console.log(` event log: ${existsSync22(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46834
+ console.log(` graph db: ${existsSync23(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46835
+ console.log(` event log: ${existsSync23(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46677
46836
  const lockPath = globalDaemonLock();
46678
46837
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
46679
46838
  console.log(
@@ -47125,11 +47284,11 @@ async function cmdUse(args2) {
47125
47284
  }
47126
47285
  async function cmdReview() {
47127
47286
  const paths = workspacePaths(ROOT);
47128
- if (!existsSync22(paths.reviewQueue)) {
47287
+ if (!existsSync23(paths.reviewQueue)) {
47129
47288
  console.log("(review queue empty)");
47130
47289
  return;
47131
47290
  }
47132
- const queue = JSON.parse(readFileSync20(paths.reviewQueue, "utf8"));
47291
+ const queue = JSON.parse(readFileSync21(paths.reviewQueue, "utf8"));
47133
47292
  if (queue.length === 0) {
47134
47293
  console.log("(review queue empty)");
47135
47294
  return;
@@ -47783,7 +47942,7 @@ async function gatherRepo(store, ws) {
47783
47942
  };
47784
47943
  }
47785
47944
  async function gatherReportData(generatedAt) {
47786
- const { existsSync: existsSync23 } = await import("node:fs");
47945
+ const { existsSync: existsSync24 } = await import("node:fs");
47787
47946
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
47788
47947
  const cfg = loadConfig();
47789
47948
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -47791,7 +47950,7 @@ async function gatherReportData(generatedAt) {
47791
47950
  for (const ws of listWorkspaces()) {
47792
47951
  if (ws.missing) continue;
47793
47952
  const dbPath = workspacePaths(ws.path).castalia;
47794
- if (!existsSync23(dbPath)) continue;
47953
+ if (!existsSync24(dbPath)) continue;
47795
47954
  let store = null;
47796
47955
  try {
47797
47956
  store = openGraphStore2({ path: dbPath });
@@ -47822,7 +47981,7 @@ async function gatherReportData(generatedAt) {
47822
47981
  };
47823
47982
  }
47824
47983
  async function cmdReport(args2) {
47825
- const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync16 } = await import("node:fs");
47984
+ const { mkdirSync: mkdirSync7, writeFileSync: writeFileSync17 } = await import("node:fs");
47826
47985
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
47827
47986
  const includeFutureVerbs = args2.includes("--future-verbs");
47828
47987
  const now = /* @__PURE__ */ new Date();
@@ -47833,10 +47992,10 @@ async function cmdReport(args2) {
47833
47992
  process.exit(2);
47834
47993
  }
47835
47994
  const outDir = workspacePaths(ROOT).configDir;
47836
- mkdirSync6(outDir, { recursive: true });
47995
+ mkdirSync7(outDir, { recursive: true });
47837
47996
  const files = renderReport2(data, { includeFutureVerbs });
47838
- for (const f of files) writeFileSync16(join25(outDir, f.name), f.html, "utf8");
47839
- const indexPath = join25(outDir, "report.html");
47997
+ for (const f of files) writeFileSync17(join26(outDir, f.name), f.html, "utf8");
47998
+ const indexPath = join26(outDir, "report.html");
47840
47999
  console.log(`report \u2192 ${indexPath}`);
47841
48000
  console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
47842
48001
  console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
@@ -47956,15 +48115,15 @@ function hookRelayCommand(port, path2) {
47956
48115
  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 '{}'`;
47957
48116
  }
47958
48117
  async function installClaudeHooks(port) {
47959
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
47960
- const { join: join26 } = await import("node:path");
47961
- const dir = join26(ROOT, ".claude");
47962
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
47963
- const file2 = join26(dir, "settings.json");
48118
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48119
+ const { join: join27 } = await import("node:path");
48120
+ const dir = join27(ROOT, ".claude");
48121
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48122
+ const file2 = join27(dir, "settings.json");
47964
48123
  let settings = {};
47965
- if (existsSync23(file2)) {
48124
+ if (existsSync24(file2)) {
47966
48125
  try {
47967
- settings = JSON.parse(readFileSync21(file2, "utf8"));
48126
+ settings = JSON.parse(readFileSync22(file2, "utf8"));
47968
48127
  } catch {
47969
48128
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47970
48129
  process.exit(2);
@@ -48010,10 +48169,10 @@ async function installClaudeHooks(port) {
48010
48169
  dropErrata(list);
48011
48170
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
48012
48171
  }
48013
- writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
48172
+ writeFileSync17(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
48014
48173
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
48015
48174
  await installClaudeMcpConfig();
48016
- const claudeMd = join26(ROOT, "CLAUDE.md");
48175
+ const claudeMd = join27(ROOT, "CLAUDE.md");
48017
48176
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
48018
48177
  if (recall.kind === "collision") {
48019
48178
  console.warn(
@@ -48025,15 +48184,15 @@ async function installClaudeHooks(port) {
48025
48184
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
48026
48185
  }
48027
48186
  async function installClaudeMcpConfig() {
48028
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
48029
- const { join: join26, dirname: dirname9 } = await import("node:path");
48030
- const file2 = join26(ROOT, ".mcp.json");
48187
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48188
+ const { join: join27, dirname: dirname9 } = await import("node:path");
48189
+ const file2 = join27(ROOT, ".mcp.json");
48031
48190
  const dir = dirname9(file2);
48032
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48191
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48033
48192
  let cfg = {};
48034
- if (existsSync23(file2)) {
48193
+ if (existsSync24(file2)) {
48035
48194
  try {
48036
- cfg = JSON.parse(readFileSync21(file2, "utf8"));
48195
+ cfg = JSON.parse(readFileSync22(file2, "utf8"));
48037
48196
  } catch {
48038
48197
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
48039
48198
  process.exit(2);
@@ -48041,21 +48200,21 @@ async function installClaudeMcpConfig() {
48041
48200
  }
48042
48201
  cfg.mcpServers ??= {};
48043
48202
  cfg.mcpServers["errata"] = errataMcpInvocation();
48044
- writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48203
+ writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48045
48204
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
48046
48205
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
48047
48206
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
48048
48207
  }
48049
48208
  async function installCursorMcpConfig() {
48050
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
48051
- const { join: join26 } = await import("node:path");
48052
- const dir = join26(ROOT, ".cursor");
48053
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48054
- const file2 = join26(dir, "mcp.json");
48209
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48210
+ const { join: join27 } = await import("node:path");
48211
+ const dir = join27(ROOT, ".cursor");
48212
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48213
+ const file2 = join27(dir, "mcp.json");
48055
48214
  let cfg = {};
48056
- if (existsSync23(file2)) {
48215
+ if (existsSync24(file2)) {
48057
48216
  try {
48058
- cfg = JSON.parse(readFileSync21(file2, "utf8"));
48217
+ cfg = JSON.parse(readFileSync22(file2, "utf8"));
48059
48218
  } catch {
48060
48219
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
48061
48220
  process.exit(2);
@@ -48063,7 +48222,7 @@ async function installCursorMcpConfig() {
48063
48222
  }
48064
48223
  cfg.mcpServers ??= {};
48065
48224
  cfg.mcpServers["errata"] = errataMcpInvocation();
48066
- writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48225
+ writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48067
48226
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
48068
48227
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
48069
48228
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -48071,16 +48230,16 @@ async function installCursorMcpConfig() {
48071
48230
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
48072
48231
  }
48073
48232
  async function installCodexHooks(port) {
48074
- const { mkdirSync: mkdirSync6, existsSync: existsSync23, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
48075
- const { join: join26 } = await import("node:path");
48076
- const dir = join26(ROOT, ".codex");
48077
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48078
- const file2 = join26(dir, "config.toml");
48233
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48234
+ const { join: join27 } = await import("node:path");
48235
+ const dir = join27(ROOT, ".codex");
48236
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48237
+ const file2 = join27(dir, "config.toml");
48079
48238
  const BEGIN = `# >>> errata hooks (errata-managed)`;
48080
48239
  const END = `# <<< errata hooks`;
48081
48240
  let existing = "";
48082
- if (existsSync23(file2)) {
48083
- existing = readFileSync21(file2, "utf8");
48241
+ if (existsSync24(file2)) {
48242
+ existing = readFileSync22(file2, "utf8");
48084
48243
  const beginIdx = existing.indexOf(BEGIN);
48085
48244
  const endIdx = existing.indexOf(END);
48086
48245
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -48109,7 +48268,7 @@ ${END}
48109
48268
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
48110
48269
 
48111
48270
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
48112
- writeFileSync16(file2, final, "utf8");
48271
+ writeFileSync17(file2, final, "utf8");
48113
48272
  console.log(`installed Codex hooks \u2192 ${file2}`);
48114
48273
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
48115
48274
  console.log("");
@@ -48372,7 +48531,7 @@ async function cmdDash(args2) {
48372
48531
  await yieldToLoop2();
48373
48532
  try {
48374
48533
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
48375
- const res = bleedRules(join25(r.root, ".claude", "rules"), items);
48534
+ const res = bleedRules(join26(r.root, ".claude", "rules"), items);
48376
48535
  if (res.written || res.pruned) {
48377
48536
  console.log(
48378
48537
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-dev.71",
3
+ "version": "2.0.0-dev.72",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {