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

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 +297 -131
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -15388,7 +15388,11 @@ var init_symbol_intent = __esm({
15388
15388
  function isCloudWritableNodeLabel(label) {
15389
15389
  return CLOUD_WRITABLE_NODE_LABEL_SET.has(label);
15390
15390
  }
15391
+ function isQuarantinedExtractionSource(source) {
15392
+ return typeof source === "string" && source.startsWith(QUARANTINE_EXTRACTION_SOURCE_PREFIX);
15393
+ }
15391
15394
  function provenanceBand(source) {
15395
+ if (isQuarantinedExtractionSource(source)) return "seed";
15392
15396
  switch (source) {
15393
15397
  case "agent-observed":
15394
15398
  case "user-edited":
@@ -15436,7 +15440,7 @@ function summarizeIngestResult(r) {
15436
15440
  ...r.patternReconciliation ? { patternReconciliation: r.patternReconciliation } : {}
15437
15441
  };
15438
15442
  }
15439
- var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15443
+ var CLOUD_NODE_LABELS, CLOUD_WRITABLE_NODE_LABELS, CLOUD_WRITABLE_NODE_LABEL_SET, CLOUD_EDGE_TYPES, INGEST_SOURCES, INGEST_EXTRACTION_SOURCES, QUARANTINE_EXTRACTION_SOURCE_PREFIX, MAX_NODES_PER_PAYLOAD, MAX_EDGES_PER_PAYLOAD, CastaliaIngestNodeSchema, RouteContextCountWireSchema, CastaliaIngestEdgeSchema, SymbolSummarySidecarSchema, CastaliaIngestPayloadSchema;
15440
15444
  var init_wire = __esm({
15441
15445
  "../../packages/shared/src/wire.ts"() {
15442
15446
  "use strict";
@@ -15481,6 +15485,7 @@ var init_wire = __esm({
15481
15485
  "cold-start-seed",
15482
15486
  "user-edited"
15483
15487
  ];
15488
+ QUARANTINE_EXTRACTION_SOURCE_PREFIX = "quarantined:";
15484
15489
  MAX_NODES_PER_PAYLOAD = 200;
15485
15490
  MAX_EDGES_PER_PAYLOAD = 500;
15486
15491
  CastaliaIngestNodeSchema = external_exports.object({
@@ -15645,6 +15650,7 @@ __export(src_exports, {
15645
15650
  MAX_SYMBOL_SUMMARY_CHARS: () => MAX_SYMBOL_SUMMARY_CHARS,
15646
15651
  PAGERANK_EXCLUSIONS: () => PAGERANK_EXCLUSIONS,
15647
15652
  PROBLEM_RESOLUTION: () => PROBLEM_RESOLUTION,
15653
+ QUARANTINE_EXTRACTION_SOURCE_PREFIX: () => QUARANTINE_EXTRACTION_SOURCE_PREFIX,
15648
15654
  RESOLUTION_EDGES: () => RESOLUTION_EDGES,
15649
15655
  RouteContextCountWireSchema: () => RouteContextCountWireSchema,
15650
15656
  SEMANTIC_NODE_LABELS: () => SEMANTIC_NODE_LABELS,
@@ -15680,6 +15686,7 @@ __export(src_exports, {
15680
15686
  isCodeLabel: () => isCodeLabel,
15681
15687
  isContextLabel: () => isContextLabel,
15682
15688
  isInferredSource: () => isInferredSource,
15689
+ isQuarantinedExtractionSource: () => isQuarantinedExtractionSource,
15683
15690
  isSeedProvenance: () => isSeedProvenance,
15684
15691
  isSemanticLabel: () => isSemanticLabel,
15685
15692
  isTestRelPath: () => isTestRelPath,
@@ -20362,13 +20369,8 @@ function renderSnapshot(s) {
20362
20369
  if (s.skills.length > 0) {
20363
20370
  lines.push("### Skills available");
20364
20371
  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\`.`
20372
+ `${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
20373
  );
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
20374
  lines.push("");
20373
20375
  }
20374
20376
  lines.push("### Prior knowledge sampled from the shared graph");
@@ -38554,12 +38556,12 @@ var init_report_render = __esm({
38554
38556
 
38555
38557
  // src/cli.ts
38556
38558
  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";
38559
+ import { closeSync as closeSync2, existsSync as existsSync23, openSync as openSync2, readFileSync as readFileSync21, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
38560
+ import { join as join26 } from "node:path";
38559
38561
  import { spawn as spawn3 } from "node:child_process";
38560
38562
 
38561
38563
  // src/daemon.ts
38562
- import { existsSync as existsSync17, writeFileSync as writeFileSync13 } from "node:fs";
38564
+ import { existsSync as existsSync18, writeFileSync as writeFileSync14 } from "node:fs";
38563
38565
 
38564
38566
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
38565
38567
  import { createServer as createServerHTTP } from "http";
@@ -39139,8 +39141,8 @@ init_config();
39139
39141
 
39140
39142
  // src/engine.ts
39141
39143
  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";
39144
+ 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";
39145
+ import { join as join22, relative as relative6, sep as sep4 } from "node:path";
39144
39146
 
39145
39147
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
39146
39148
  import { stat as statcb } from "fs";
@@ -42627,6 +42629,164 @@ async function syncSkills(paths, client, seed, pins = []) {
42627
42629
  return { written: rows.length, pruned, ...staleDaemon ? { staleDaemon } : {} };
42628
42630
  }
42629
42631
 
42632
+ // src/agent-skills.ts
42633
+ import {
42634
+ cpSync,
42635
+ existsSync as existsSync14,
42636
+ lstatSync,
42637
+ mkdirSync as mkdirSync6,
42638
+ readFileSync as readFileSync13,
42639
+ readdirSync as readdirSync7,
42640
+ rmSync as rmSync2,
42641
+ symlinkSync,
42642
+ writeFileSync as writeFileSync11
42643
+ } from "node:fs";
42644
+ import { join as join19 } from "node:path";
42645
+ var SKILL_NS = "errata-";
42646
+ var HARNESS_SKILL_DIRS = [
42647
+ { configDir: ".claude", skillsDir: join19(".claude", "skills") },
42648
+ // Cursor adopted the standard; its exact project dir is still moving — kept
42649
+ // best-effort and gated on `.cursor/` presence so we never create it blind.
42650
+ { configDir: ".cursor", skillsDir: join19(".cursor", "skills") }
42651
+ ];
42652
+ function skillSlug(title, id) {
42653
+ const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
42654
+ return `${SKILL_NS}${base}`.slice(0, 64).replace(/-+$/, "");
42655
+ }
42656
+ function yamlScalar(s) {
42657
+ return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\s+/g, " ").trim()}"`;
42658
+ }
42659
+ function deriveDescription(title, layer, body2) {
42660
+ const firstProse = body2.split(/\r?\n/).map((l) => l.trim()).find((l) => l.length > 0 && !l.startsWith("#") && !l.startsWith("---"));
42661
+ const lead = firstProse && firstProse.length >= 24 ? firstProse : title;
42662
+ const when = ` Apply when working on ${layer === "antipattern" ? "code that risks this pitfall" : "problems in this area"}.`;
42663
+ return `${lead}${lead.endsWith(".") ? "" : "."}${when}`.slice(0, 1024);
42664
+ }
42665
+ function renderSkillMd(name2, description, body2) {
42666
+ return `---
42667
+ name: ${name2}
42668
+ description: ${yamlScalar(description)}
42669
+ ---
42670
+
42671
+ ${body2.trimEnd()}
42672
+ `;
42673
+ }
42674
+ function reconcileNamespaced(dir, keep) {
42675
+ if (!existsSync14(dir)) return 0;
42676
+ let pruned = 0;
42677
+ for (const name2 of readdirSync7(dir)) {
42678
+ if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
42679
+ try {
42680
+ rmSync2(join19(dir, name2), { recursive: true, force: true });
42681
+ pruned++;
42682
+ } catch {
42683
+ }
42684
+ }
42685
+ return pruned;
42686
+ }
42687
+ function linkOrCopy(linkPath, target) {
42688
+ try {
42689
+ if (existsSync14(linkPath) || safeLstat(linkPath)) rmSync2(linkPath, { recursive: true, force: true });
42690
+ } catch {
42691
+ }
42692
+ try {
42693
+ symlinkSync(target, linkPath, "junction");
42694
+ } catch {
42695
+ try {
42696
+ cpSync(target, linkPath, { recursive: true });
42697
+ } catch {
42698
+ }
42699
+ }
42700
+ }
42701
+ function safeLstat(p) {
42702
+ try {
42703
+ lstatSync(p);
42704
+ return true;
42705
+ } catch {
42706
+ return false;
42707
+ }
42708
+ }
42709
+ function emitAndProjectSkills(root, skills) {
42710
+ const agentsSkillsDir = join19(root, ".agents", "skills");
42711
+ mkdirSync6(agentsSkillsDir, { recursive: true });
42712
+ const slugs = [];
42713
+ const keep = /* @__PURE__ */ new Set();
42714
+ let emitted = 0;
42715
+ for (const s of skills) {
42716
+ let body2;
42717
+ try {
42718
+ body2 = readFileSync13(s.bodyPath, "utf8");
42719
+ } catch {
42720
+ continue;
42721
+ }
42722
+ const slug2 = skillSlug(s.title, s.id);
42723
+ if (keep.has(slug2)) continue;
42724
+ keep.add(slug2);
42725
+ slugs.push(slug2);
42726
+ const description = deriveDescription(s.title, s.layer, body2);
42727
+ mkdirSync6(join19(agentsSkillsDir, slug2), { recursive: true });
42728
+ writeFileSync11(
42729
+ join19(agentsSkillsDir, slug2, "SKILL.md"),
42730
+ renderSkillMd(slug2, description, body2),
42731
+ "utf8"
42732
+ );
42733
+ emitted++;
42734
+ }
42735
+ reconcileNamespaced(agentsSkillsDir, keep);
42736
+ let projected = 0;
42737
+ for (const h of HARNESS_SKILL_DIRS) {
42738
+ if (!existsSync14(join19(root, h.configDir))) continue;
42739
+ const dir = join19(root, h.skillsDir);
42740
+ mkdirSync6(dir, { recursive: true });
42741
+ for (const slug2 of slugs) {
42742
+ linkOrCopy(join19(dir, slug2), join19(agentsSkillsDir, slug2));
42743
+ projected++;
42744
+ }
42745
+ reconcileNamespaced(dir, keep);
42746
+ }
42747
+ ensureSkillGitignore(root);
42748
+ return { slugs, emitted, projected };
42749
+ }
42750
+ function emitInputsFromManifest(erretaDir, manifestPath) {
42751
+ if (!existsSync14(manifestPath)) return [];
42752
+ try {
42753
+ const parsed = JSON.parse(readFileSync13(manifestPath, "utf8"));
42754
+ return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
42755
+ id: s.id,
42756
+ title: s.title ?? s.id,
42757
+ layer: s.layer ?? "technique",
42758
+ confidence: s.confidence ?? 0,
42759
+ bodyPath: join19(erretaDir, s.file)
42760
+ }));
42761
+ } catch {
42762
+ return [];
42763
+ }
42764
+ }
42765
+ var GITIGNORE_MARK = "# errata-managed agent skills (daemon-synced; namespaced)";
42766
+ var GITIGNORE_LINES = [
42767
+ GITIGNORE_MARK,
42768
+ ".agents/skills/errata-*/",
42769
+ ".claude/skills/errata-*/",
42770
+ ".cursor/skills/errata-*/"
42771
+ ];
42772
+ function ensureSkillGitignore(root) {
42773
+ const path2 = join19(root, ".gitignore");
42774
+ let current = "";
42775
+ try {
42776
+ current = existsSync14(path2) ? readFileSync13(path2, "utf8") : "";
42777
+ } catch {
42778
+ return;
42779
+ }
42780
+ if (current.includes(GITIGNORE_MARK)) return;
42781
+ const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
42782
+ try {
42783
+ writeFileSync11(path2, `${current}${prefix}
42784
+ ${GITIGNORE_LINES.join("\n")}
42785
+ `, "utf8");
42786
+ } catch {
42787
+ }
42788
+ }
42789
+
42630
42790
  // src/working-file-state.ts
42631
42791
  function createWorkingFileState() {
42632
42792
  const bySession = /* @__PURE__ */ new Map();
@@ -42756,20 +42916,20 @@ var CausalBuffer = class {
42756
42916
  // src/profile.ts
42757
42917
  init_src2();
42758
42918
  init_paths();
42759
- import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
42919
+ import { existsSync as existsSync16, readFileSync as readFileSync15, writeFileSync as writeFileSync12 } from "node:fs";
42760
42920
  import { createHash as createHash12 } from "node:crypto";
42761
- import { join as join20 } from "node:path";
42921
+ import { join as join21 } from "node:path";
42762
42922
 
42763
42923
  // src/git-remote.ts
42764
42924
  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";
42925
+ import { existsSync as existsSync15, readFileSync as readFileSync14, statSync as statSync4 } from "node:fs";
42926
+ import { isAbsolute as isAbsolute3, join as join20, resolve as resolve5 } from "node:path";
42767
42927
  function resolveGitDir(root) {
42768
- const dotGit = join19(root, ".git");
42928
+ const dotGit = join20(root, ".git");
42769
42929
  try {
42770
42930
  const st = statSync4(dotGit);
42771
42931
  if (st.isDirectory()) return dotGit;
42772
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync13(dotGit, "utf8"));
42932
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync14(dotGit, "utf8"));
42773
42933
  if (!m) return null;
42774
42934
  const dir = m[1];
42775
42935
  return isAbsolute3(dir) ? dir : resolve5(root, dir);
@@ -42778,22 +42938,22 @@ function resolveGitDir(root) {
42778
42938
  }
42779
42939
  }
42780
42940
  function gitConfigPath(gitDir) {
42781
- const commondirFile = join19(gitDir, "commondir");
42782
- if (existsSync14(commondirFile)) {
42783
- const common = readFileSync13(commondirFile, "utf8").trim();
42941
+ const commondirFile = join20(gitDir, "commondir");
42942
+ if (existsSync15(commondirFile)) {
42943
+ const common = readFileSync14(commondirFile, "utf8").trim();
42784
42944
  const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
42785
- return join19(commonDir, "config");
42945
+ return join20(commonDir, "config");
42786
42946
  }
42787
- return join19(gitDir, "config");
42947
+ return join20(gitDir, "config");
42788
42948
  }
42789
42949
  function readRemotes(root) {
42790
42950
  const gitDir = resolveGitDir(root);
42791
42951
  if (!gitDir) return [];
42792
42952
  const cfgPath = gitConfigPath(gitDir);
42793
- if (!existsSync14(cfgPath)) return [];
42953
+ if (!existsSync15(cfgPath)) return [];
42794
42954
  let txt;
42795
42955
  try {
42796
- txt = readFileSync13(cfgPath, "utf8");
42956
+ txt = readFileSync14(cfgPath, "utf8");
42797
42957
  } catch {
42798
42958
  return [];
42799
42959
  }
@@ -42825,13 +42985,13 @@ function refreshRepoLocator(root, profile) {
42825
42985
  }
42826
42986
  function loadProfile(root) {
42827
42987
  const p = workspacePaths(root);
42828
- if (!existsSync15(p.workspaceJson)) return null;
42829
- return JSON.parse(readFileSync14(p.workspaceJson, "utf8"));
42988
+ if (!existsSync16(p.workspaceJson)) return null;
42989
+ return JSON.parse(readFileSync15(p.workspaceJson, "utf8"));
42830
42990
  }
42831
42991
  function saveProfile(root, profile) {
42832
42992
  const p = workspacePaths(root);
42833
42993
  ensureDir(p.configDir);
42834
- writeFileSync11(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
42994
+ writeFileSync12(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
42835
42995
  }
42836
42996
  function autodetectProfile(root) {
42837
42997
  const id = workspaceId(root);
@@ -42839,10 +42999,10 @@ function autodetectProfile(root) {
42839
42999
  const p = emptyProfile(id, name2);
42840
43000
  const locator = detectRepoLocator(root);
42841
43001
  if (locator) p.repoLocator = locator;
42842
- const pkgPath = join20(root, "package.json");
42843
- if (existsSync15(pkgPath)) {
43002
+ const pkgPath = join21(root, "package.json");
43003
+ if (existsSync16(pkgPath)) {
42844
43004
  try {
42845
- const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
43005
+ const pkg = JSON.parse(readFileSync15(pkgPath, "utf8"));
42846
43006
  p.languages.push("typescript", "javascript");
42847
43007
  const nodeVer = pkg.engines?.node ?? "node";
42848
43008
  p.stack.push(`node@${nodeVer}`);
@@ -42863,10 +43023,10 @@ function autodetectProfile(root) {
42863
43023
  } catch {
42864
43024
  }
42865
43025
  }
42866
- const pyproject = join20(root, "pyproject.toml");
42867
- if (existsSync15(pyproject)) {
43026
+ const pyproject = join21(root, "pyproject.toml");
43027
+ if (existsSync16(pyproject)) {
42868
43028
  try {
42869
- const txt = readFileSync14(pyproject, "utf8");
43029
+ const txt = readFileSync15(pyproject, "utf8");
42870
43030
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
42871
43031
  p.languages.push("python");
42872
43032
  p.stack.push(`python@${py ?? "3"}`);
@@ -42877,16 +43037,16 @@ function autodetectProfile(root) {
42877
43037
  } catch {
42878
43038
  }
42879
43039
  }
42880
- const reqs = join20(root, "requirements.txt");
42881
- if (existsSync15(reqs)) {
43040
+ const reqs = join21(root, "requirements.txt");
43041
+ if (existsSync16(reqs)) {
42882
43042
  if (!p.languages.includes("python")) p.languages.push("python");
42883
43043
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
42884
43044
  }
42885
- if (existsSync15(join20(root, "go.mod"))) {
43045
+ if (existsSync16(join21(root, "go.mod"))) {
42886
43046
  p.languages.push("go");
42887
43047
  p.stack.push("go");
42888
43048
  }
42889
- if (existsSync15(join20(root, "Cargo.toml"))) {
43049
+ if (existsSync16(join21(root, "Cargo.toml"))) {
42890
43050
  p.languages.push("rust");
42891
43051
  p.stack.push("rust");
42892
43052
  }
@@ -43044,7 +43204,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
43044
43204
  }
43045
43205
 
43046
43206
  // src/engine.ts
43047
- var DAEMON_VERSION = true ? "2.0.0-dev.71" : "2.0.0-alpha.0";
43207
+ var DAEMON_VERSION = true ? "2.0.0-dev.73" : "2.0.0-alpha.0";
43048
43208
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
43049
43209
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
43050
43210
  var GIT_OP_MUTE_MS = 4e3;
@@ -43054,7 +43214,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
43054
43214
  function appendIdentityAudit(path2, record2, line) {
43055
43215
  if (!record2.accepted && record2.score <= 0) return;
43056
43216
  try {
43057
- if (existsSync16(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
43217
+ if (existsSync17(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
43058
43218
  renameSync2(path2, `${path2}.1`);
43059
43219
  }
43060
43220
  appendFileSync2(path2, line);
@@ -43064,14 +43224,14 @@ function appendIdentityAudit(path2, record2, line) {
43064
43224
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
43065
43225
  function loadTurnCursors(path2) {
43066
43226
  try {
43067
- return new Map(Object.entries(JSON.parse(readFileSync15(path2, "utf8"))));
43227
+ return new Map(Object.entries(JSON.parse(readFileSync16(path2, "utf8"))));
43068
43228
  } catch {
43069
43229
  return /* @__PURE__ */ new Map();
43070
43230
  }
43071
43231
  }
43072
43232
  function saveTurnCursors(path2, cursors) {
43073
43233
  try {
43074
- writeFileSync12(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
43234
+ writeFileSync13(path2, JSON.stringify(Object.fromEntries(cursors)), "utf8");
43075
43235
  } catch {
43076
43236
  }
43077
43237
  }
@@ -43093,7 +43253,7 @@ function gitSourceWatchTargets(root) {
43093
43253
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
43094
43254
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
43095
43255
  );
43096
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join21(root, d) + sep4));
43256
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join22(root, d) + sep4));
43097
43257
  } catch {
43098
43258
  }
43099
43259
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -43105,19 +43265,19 @@ function gitSourceWatchTargets(root) {
43105
43265
  if (!f.startsWith(prefix)) continue;
43106
43266
  const rest2 = f.slice(prefix.length);
43107
43267
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
43108
- else targets.add(join21(root, f));
43268
+ else targets.add(join22(root, f));
43109
43269
  }
43110
43270
  for (const c of children) {
43111
- if (IGNORED_PATH.test(join21(root, c) + sep4)) continue;
43271
+ if (IGNORED_PATH.test(join22(root, c) + sep4)) continue;
43112
43272
  if (hasIgnoredChild(c)) addUnder(c);
43113
- else targets.add(join21(root, c));
43273
+ else targets.add(join22(root, c));
43114
43274
  }
43115
43275
  };
43116
43276
  addUnder("");
43117
43277
  if (targets.size > 0) return [...targets];
43118
43278
  } catch {
43119
43279
  }
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)));
43280
+ 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
43281
  }
43122
43282
  function createWorkspaceEngine(opts) {
43123
43283
  const paths = workspacePaths(opts.workspaceRoot);
@@ -43271,7 +43431,7 @@ function createWorkspaceEngine(opts) {
43271
43431
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
43272
43432
  let episodeId2;
43273
43433
  if (srcPaths.length > 0) {
43274
- const abs = srcPaths.map((p) => join21(opts.workspaceRoot, p));
43434
+ const abs = srcPaths.map((p) => join22(opts.workspaceRoot, p));
43275
43435
  try {
43276
43436
  const r = await runReindexPass(
43277
43437
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -43307,8 +43467,8 @@ function createWorkspaceEngine(opts) {
43307
43467
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
43308
43468
  );
43309
43469
  };
43310
- const gitDir = join21(opts.workspaceRoot, ".git");
43311
- if (existsSync16(gitDir)) {
43470
+ const gitDir = join22(opts.workspaceRoot, ".git");
43471
+ if (existsSync17(gitDir)) {
43312
43472
  stopGit = startGitSensor(gitDir, (ev) => {
43313
43473
  void handleGitEvent(ev).catch((err2) => {
43314
43474
  console.warn("[errata] git event handler failed:", err2);
@@ -43376,10 +43536,10 @@ function createWorkspaceEngine(opts) {
43376
43536
  ...pendingUpdate ? { pendingUpdate } : {}
43377
43537
  });
43378
43538
  doneRender?.();
43379
- const target = join21(opts.workspaceRoot, "AGENTS.md");
43539
+ const target = join22(opts.workspaceRoot, "AGENTS.md");
43380
43540
  writeManagedBlock(target, { body: body2 });
43381
43541
  if (elicit) {
43382
- writePrimingHandles(join21(paths.configDir, "priming-handles.json"), [
43542
+ writePrimingHandles(join22(paths.configDir, "priming-handles.json"), [
43383
43543
  ...snapshot.recentProblems.map((r) => r.node),
43384
43544
  // Resolved-band handles: the ✓ problem AND its Solution are citable
43385
43545
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -43549,7 +43709,7 @@ function createWorkspaceEngine(opts) {
43549
43709
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
43550
43710
  });
43551
43711
  };
43552
- const turnCursorPath = join21(paths.configDir, "turn-cursors.json");
43712
+ const turnCursorPath = join22(paths.configDir, "turn-cursors.json");
43553
43713
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
43554
43714
  const sessionLastProblem = /* @__PURE__ */ new Map();
43555
43715
  const sessionThreads = /* @__PURE__ */ new Map();
@@ -43572,7 +43732,7 @@ function createWorkspaceEngine(opts) {
43572
43732
  const t = Date.now();
43573
43733
  let processedTurns = 0;
43574
43734
  const elicit = isEdgeElicitationEnabled();
43575
- const handleMap = elicit ? readPrimingHandles(join21(paths.configDir, "priming-handles.json")) : {};
43735
+ const handleMap = elicit ? readPrimingHandles(join22(paths.configDir, "priming-handles.json")) : {};
43576
43736
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
43577
43737
  const toRel = (abs) => {
43578
43738
  const p = abs.replace(/\\/g, "/");
@@ -44049,7 +44209,13 @@ function createWorkspaceEngine(opts) {
44049
44209
  return typeof cloudId === "string" && cloudId !== p.id ? [p.id, cloudId] : [p.id];
44050
44210
  });
44051
44211
  const pins = profile?.projectId ? await cloud.getSkillPins(profile.projectId).then((r) => r.pins).catch(() => []) : [];
44052
- return syncSkills(paths, cloud, skillSeed, pins);
44212
+ const result = await syncSkills(paths, cloud, skillSeed, pins);
44213
+ try {
44214
+ emitAndProjectSkills(opts.workspaceRoot, emitInputsFromManifest(paths.configDir, paths.skillsManifest));
44215
+ } catch (err2) {
44216
+ console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
44217
+ }
44218
+ return result;
44053
44219
  };
44054
44220
  return {
44055
44221
  profile,
@@ -44231,7 +44397,7 @@ function createWorkspaceEngine(opts) {
44231
44397
  console.log(
44232
44398
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
44233
44399
  );
44234
- const pending = existsSync16(paths.outbox) ? readdirSync7(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
44400
+ const pending = existsSync17(paths.outbox) ? readdirSync8(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
44235
44401
  return { uploaded: 0, failed: 0, remaining: pending };
44236
44402
  }
44237
44403
  try {
@@ -44318,7 +44484,7 @@ async function startDaemon(opts) {
44318
44484
  reviewUrl: () => webUiUrl + "/review"
44319
44485
  });
44320
44486
  const writeLockFile = (url2) => {
44321
- writeFileSync13(
44487
+ writeFileSync14(
44322
44488
  engine.paths.daemonLock,
44323
44489
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
44324
44490
  "utf8"
@@ -44361,7 +44527,7 @@ async function startDaemon(opts) {
44361
44527
  );
44362
44528
  await engine.stop();
44363
44529
  try {
44364
- if (existsSync17(engine.paths.daemonLock)) {
44530
+ if (existsSync18(engine.paths.daemonLock)) {
44365
44531
  }
44366
44532
  } catch {
44367
44533
  }
@@ -44378,16 +44544,16 @@ async function listenServer(fetchFn, port) {
44378
44544
 
44379
44545
  // src/registry.ts
44380
44546
  init_paths();
44381
- import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
44382
- import { join as join22 } from "node:path";
44547
+ import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
44548
+ import { join as join23 } from "node:path";
44383
44549
  function registryPath() {
44384
- return process.env["ERRATA_REGISTRY_PATH"] ?? join22(globalDir(), "workspaces.json");
44550
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join23(globalDir(), "workspaces.json");
44385
44551
  }
44386
44552
  function read() {
44387
44553
  const p = registryPath();
44388
- if (!existsSync18(p)) return { version: 1, workspaces: {} };
44554
+ if (!existsSync19(p)) return { version: 1, workspaces: {} };
44389
44555
  try {
44390
- const parsed = JSON.parse(readFileSync16(p, "utf8"));
44556
+ const parsed = JSON.parse(readFileSync17(p, "utf8"));
44391
44557
  return { version: 1, workspaces: parsed.workspaces ?? {} };
44392
44558
  } catch {
44393
44559
  return { version: 1, workspaces: {} };
@@ -44395,7 +44561,7 @@ function read() {
44395
44561
  }
44396
44562
  function write(reg) {
44397
44563
  ensureDir(globalDir());
44398
- writeFileSync14(registryPath(), JSON.stringify(reg, null, 2), "utf8");
44564
+ writeFileSync15(registryPath(), JSON.stringify(reg, null, 2), "utf8");
44399
44565
  }
44400
44566
  function registerWorkspace(profile, root, now = Date.now()) {
44401
44567
  const reg = read();
@@ -44412,7 +44578,7 @@ function pruneMissingWorkspaces() {
44412
44578
  const reg = read();
44413
44579
  const removed = [];
44414
44580
  for (const [id, entry] of Object.entries(reg.workspaces)) {
44415
- if (!existsSync18(entry.path)) {
44581
+ if (!existsSync19(entry.path)) {
44416
44582
  removed.push(entry);
44417
44583
  delete reg.workspaces[id];
44418
44584
  }
@@ -44421,13 +44587,13 @@ function pruneMissingWorkspaces() {
44421
44587
  return removed;
44422
44588
  }
44423
44589
  function workspaceStatus(entry) {
44424
- const missing = !existsSync18(entry.path);
44590
+ const missing = !existsSync19(entry.path);
44425
44591
  const lockPath = workspacePaths(entry.path).daemonLock;
44426
44592
  let running = false;
44427
44593
  let webUiUrl = null;
44428
- if (existsSync18(lockPath)) {
44594
+ if (existsSync19(lockPath)) {
44429
44595
  try {
44430
- const lock = JSON.parse(readFileSync16(lockPath, "utf8"));
44596
+ const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
44431
44597
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
44432
44598
  running = true;
44433
44599
  webUiUrl = lock.webUiUrl;
@@ -44455,7 +44621,7 @@ function pidAlive(pid) {
44455
44621
  // src/multi.ts
44456
44622
  init_dist();
44457
44623
  init_src4();
44458
- import { readFileSync as readFileSync19, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
44624
+ import { readFileSync as readFileSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync16 } from "node:fs";
44459
44625
 
44460
44626
  // src/principle-sync.ts
44461
44627
  init_src4();
@@ -44482,8 +44648,8 @@ async function syncPrinciples(store, cloud, opts) {
44482
44648
  init_reconcile();
44483
44649
 
44484
44650
  // src/lockfile-auto.ts
44485
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
44486
- import { join as join23 } from "node:path";
44651
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
44652
+ import { join as join24 } from "node:path";
44487
44653
 
44488
44654
  // src/package-index.ts
44489
44655
  init_src();
@@ -44747,11 +44913,11 @@ function runLockfilePass(opts) {
44747
44913
  { file: "package-lock.json", parse: parsePackageLockJson }
44748
44914
  ];
44749
44915
  for (const c of candidates) {
44750
- const p = join23(opts.root, c.file);
44751
- if (!existsSync19(p)) continue;
44916
+ const p = join24(opts.root, c.file);
44917
+ if (!existsSync20(p)) continue;
44752
44918
  let sbom;
44753
44919
  try {
44754
- sbom = c.parse(readFileSync17(p, "utf8"));
44920
+ sbom = c.parse(readFileSync18(p, "utf8"));
44755
44921
  } catch {
44756
44922
  continue;
44757
44923
  }
@@ -45027,7 +45193,7 @@ var ConsolidateWorker = class {
45027
45193
  init_paths();
45028
45194
 
45029
45195
  // src/lock.ts
45030
- import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
45196
+ import { existsSync as existsSync21, readFileSync as readFileSync19 } from "node:fs";
45031
45197
  function isProcessAlive(pid) {
45032
45198
  if (!pid || pid <= 0) return false;
45033
45199
  try {
@@ -45038,9 +45204,9 @@ function isProcessAlive(pid) {
45038
45204
  }
45039
45205
  }
45040
45206
  function readDaemonLock(lockPath) {
45041
- if (!existsSync20(lockPath)) return null;
45207
+ if (!existsSync21(lockPath)) return null;
45042
45208
  try {
45043
- const lock = JSON.parse(readFileSync18(lockPath, "utf8"));
45209
+ const lock = JSON.parse(readFileSync19(lockPath, "utf8"));
45044
45210
  return typeof lock.pid === "number" ? lock : null;
45045
45211
  } catch {
45046
45212
  return null;
@@ -45164,12 +45330,12 @@ async function ensureProjectLink(root, profile, client) {
45164
45330
  }
45165
45331
 
45166
45332
  // src/adopt.ts
45167
- import { existsSync as existsSync21 } from "node:fs";
45168
- import { dirname as dirname8, join as join24 } from "node:path";
45333
+ import { existsSync as existsSync22 } from "node:fs";
45334
+ import { dirname as dirname8, join as join25 } from "node:path";
45169
45335
  function findGitRoot(absPath) {
45170
45336
  let dir = absPath;
45171
45337
  for (let depth = 0; depth < 64; depth++) {
45172
- if (existsSync21(join24(dir, ".git"))) return dir;
45338
+ if (existsSync22(join25(dir, ".git"))) return dir;
45173
45339
  const parent = dirname8(dir);
45174
45340
  if (parent === dir) return null;
45175
45341
  dir = parent;
@@ -45357,7 +45523,7 @@ async function startMultiDaemon(opts = {}) {
45357
45523
  void ambientLinkAll();
45358
45524
  app.route(`/ws/${rec.id}`, rec.webApp);
45359
45525
  try {
45360
- writeFileSync15(
45526
+ writeFileSync16(
45361
45527
  rec.engine.paths.daemonLock,
45362
45528
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${rec.id}`, startedAt: Date.now() }),
45363
45529
  "utf8"
@@ -45543,7 +45709,7 @@ async function startMultiDaemon(opts = {}) {
45543
45709
  baseUrl = `http://127.0.0.1:${port}`;
45544
45710
  try {
45545
45711
  ensureDir(globalDir());
45546
- writeFileSync15(
45712
+ writeFileSync16(
45547
45713
  lockPath,
45548
45714
  JSON.stringify({ pid: process.pid, webUiUrl: baseUrl, startedAt: Date.now() }),
45549
45715
  "utf8"
@@ -45552,7 +45718,7 @@ async function startMultiDaemon(opts = {}) {
45552
45718
  }
45553
45719
  for (const r of records) {
45554
45720
  try {
45555
- writeFileSync15(
45721
+ writeFileSync16(
45556
45722
  r.engine.paths.daemonLock,
45557
45723
  JSON.stringify({ pid: process.pid, webUiUrl: `${baseUrl}/ws/${r.id}`, startedAt: Date.now() }),
45558
45724
  "utf8"
@@ -45906,7 +46072,7 @@ async function startMultiDaemon(opts = {}) {
45906
46072
  },
45907
46073
  async stop() {
45908
46074
  try {
45909
- const cur = readFileSync19(lockPath, "utf8");
46075
+ const cur = readFileSync20(lockPath, "utf8");
45910
46076
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
45911
46077
  } catch {
45912
46078
  }
@@ -46501,21 +46667,21 @@ async function cmdInit() {
46501
46667
  if (!skipHooks) {
46502
46668
  console.log("");
46503
46669
  console.log("installing harness hooks...");
46504
- const { existsSync: existsSync23 } = await import("node:fs");
46505
- const { join: join26 } = await import("node:path");
46670
+ const { existsSync: existsSync24 } = await import("node:fs");
46671
+ const { join: join27 } = await import("node:path");
46506
46672
  try {
46507
46673
  await installClaudeHooks(port);
46508
46674
  } catch (err2) {
46509
46675
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
46510
46676
  }
46511
- if (existsSync23(join26(ROOT, ".cursor"))) {
46677
+ if (existsSync24(join27(ROOT, ".cursor"))) {
46512
46678
  try {
46513
46679
  await installCursorMcpConfig();
46514
46680
  } catch (err2) {
46515
46681
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
46516
46682
  }
46517
46683
  }
46518
- if (existsSync23(join26(ROOT, ".codex"))) {
46684
+ if (existsSync24(join27(ROOT, ".codex"))) {
46519
46685
  try {
46520
46686
  await installCodexHooks(port);
46521
46687
  } catch (err2) {
@@ -46672,8 +46838,8 @@ async function cmdStatus() {
46672
46838
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
46673
46839
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
46674
46840
  }
46675
- console.log(` graph db: ${existsSync22(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46676
- console.log(` event log: ${existsSync22(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46841
+ console.log(` graph db: ${existsSync23(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46842
+ console.log(` event log: ${existsSync23(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46677
46843
  const lockPath = globalDaemonLock();
46678
46844
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
46679
46845
  console.log(
@@ -47125,11 +47291,11 @@ async function cmdUse(args2) {
47125
47291
  }
47126
47292
  async function cmdReview() {
47127
47293
  const paths = workspacePaths(ROOT);
47128
- if (!existsSync22(paths.reviewQueue)) {
47294
+ if (!existsSync23(paths.reviewQueue)) {
47129
47295
  console.log("(review queue empty)");
47130
47296
  return;
47131
47297
  }
47132
- const queue = JSON.parse(readFileSync20(paths.reviewQueue, "utf8"));
47298
+ const queue = JSON.parse(readFileSync21(paths.reviewQueue, "utf8"));
47133
47299
  if (queue.length === 0) {
47134
47300
  console.log("(review queue empty)");
47135
47301
  return;
@@ -47783,7 +47949,7 @@ async function gatherRepo(store, ws) {
47783
47949
  };
47784
47950
  }
47785
47951
  async function gatherReportData(generatedAt) {
47786
- const { existsSync: existsSync23 } = await import("node:fs");
47952
+ const { existsSync: existsSync24 } = await import("node:fs");
47787
47953
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
47788
47954
  const cfg = loadConfig();
47789
47955
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -47791,7 +47957,7 @@ async function gatherReportData(generatedAt) {
47791
47957
  for (const ws of listWorkspaces()) {
47792
47958
  if (ws.missing) continue;
47793
47959
  const dbPath = workspacePaths(ws.path).castalia;
47794
- if (!existsSync23(dbPath)) continue;
47960
+ if (!existsSync24(dbPath)) continue;
47795
47961
  let store = null;
47796
47962
  try {
47797
47963
  store = openGraphStore2({ path: dbPath });
@@ -47822,7 +47988,7 @@ async function gatherReportData(generatedAt) {
47822
47988
  };
47823
47989
  }
47824
47990
  async function cmdReport(args2) {
47825
- const { mkdirSync: mkdirSync6, writeFileSync: writeFileSync16 } = await import("node:fs");
47991
+ const { mkdirSync: mkdirSync7, writeFileSync: writeFileSync17 } = await import("node:fs");
47826
47992
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
47827
47993
  const includeFutureVerbs = args2.includes("--future-verbs");
47828
47994
  const now = /* @__PURE__ */ new Date();
@@ -47833,10 +47999,10 @@ async function cmdReport(args2) {
47833
47999
  process.exit(2);
47834
48000
  }
47835
48001
  const outDir = workspacePaths(ROOT).configDir;
47836
- mkdirSync6(outDir, { recursive: true });
48002
+ mkdirSync7(outDir, { recursive: true });
47837
48003
  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");
48004
+ for (const f of files) writeFileSync17(join26(outDir, f.name), f.html, "utf8");
48005
+ const indexPath = join26(outDir, "report.html");
47840
48006
  console.log(`report \u2192 ${indexPath}`);
47841
48007
  console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
47842
48008
  console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
@@ -47956,15 +48122,15 @@ function hookRelayCommand(port, path2) {
47956
48122
  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
48123
  }
47958
48124
  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");
48125
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48126
+ const { join: join27 } = await import("node:path");
48127
+ const dir = join27(ROOT, ".claude");
48128
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48129
+ const file2 = join27(dir, "settings.json");
47964
48130
  let settings = {};
47965
- if (existsSync23(file2)) {
48131
+ if (existsSync24(file2)) {
47966
48132
  try {
47967
- settings = JSON.parse(readFileSync21(file2, "utf8"));
48133
+ settings = JSON.parse(readFileSync22(file2, "utf8"));
47968
48134
  } catch {
47969
48135
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47970
48136
  process.exit(2);
@@ -48010,10 +48176,10 @@ async function installClaudeHooks(port) {
48010
48176
  dropErrata(list);
48011
48177
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
48012
48178
  }
48013
- writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
48179
+ writeFileSync17(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
48014
48180
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
48015
48181
  await installClaudeMcpConfig();
48016
- const claudeMd = join26(ROOT, "CLAUDE.md");
48182
+ const claudeMd = join27(ROOT, "CLAUDE.md");
48017
48183
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
48018
48184
  if (recall.kind === "collision") {
48019
48185
  console.warn(
@@ -48025,15 +48191,15 @@ async function installClaudeHooks(port) {
48025
48191
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
48026
48192
  }
48027
48193
  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");
48194
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48195
+ const { join: join27, dirname: dirname9 } = await import("node:path");
48196
+ const file2 = join27(ROOT, ".mcp.json");
48031
48197
  const dir = dirname9(file2);
48032
- if (!existsSync23(dir)) mkdirSync6(dir, { recursive: true });
48198
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48033
48199
  let cfg = {};
48034
- if (existsSync23(file2)) {
48200
+ if (existsSync24(file2)) {
48035
48201
  try {
48036
- cfg = JSON.parse(readFileSync21(file2, "utf8"));
48202
+ cfg = JSON.parse(readFileSync22(file2, "utf8"));
48037
48203
  } catch {
48038
48204
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
48039
48205
  process.exit(2);
@@ -48041,21 +48207,21 @@ async function installClaudeMcpConfig() {
48041
48207
  }
48042
48208
  cfg.mcpServers ??= {};
48043
48209
  cfg.mcpServers["errata"] = errataMcpInvocation();
48044
- writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48210
+ writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48045
48211
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
48046
48212
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
48047
48213
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
48048
48214
  }
48049
48215
  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");
48216
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48217
+ const { join: join27 } = await import("node:path");
48218
+ const dir = join27(ROOT, ".cursor");
48219
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48220
+ const file2 = join27(dir, "mcp.json");
48055
48221
  let cfg = {};
48056
- if (existsSync23(file2)) {
48222
+ if (existsSync24(file2)) {
48057
48223
  try {
48058
- cfg = JSON.parse(readFileSync21(file2, "utf8"));
48224
+ cfg = JSON.parse(readFileSync22(file2, "utf8"));
48059
48225
  } catch {
48060
48226
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
48061
48227
  process.exit(2);
@@ -48063,7 +48229,7 @@ async function installCursorMcpConfig() {
48063
48229
  }
48064
48230
  cfg.mcpServers ??= {};
48065
48231
  cfg.mcpServers["errata"] = errataMcpInvocation();
48066
- writeFileSync16(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48232
+ writeFileSync17(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
48067
48233
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
48068
48234
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
48069
48235
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -48071,16 +48237,16 @@ async function installCursorMcpConfig() {
48071
48237
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
48072
48238
  }
48073
48239
  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");
48240
+ const { mkdirSync: mkdirSync7, existsSync: existsSync24, readFileSync: readFileSync22, writeFileSync: writeFileSync17 } = await import("node:fs");
48241
+ const { join: join27 } = await import("node:path");
48242
+ const dir = join27(ROOT, ".codex");
48243
+ if (!existsSync24(dir)) mkdirSync7(dir, { recursive: true });
48244
+ const file2 = join27(dir, "config.toml");
48079
48245
  const BEGIN = `# >>> errata hooks (errata-managed)`;
48080
48246
  const END = `# <<< errata hooks`;
48081
48247
  let existing = "";
48082
- if (existsSync23(file2)) {
48083
- existing = readFileSync21(file2, "utf8");
48248
+ if (existsSync24(file2)) {
48249
+ existing = readFileSync22(file2, "utf8");
48084
48250
  const beginIdx = existing.indexOf(BEGIN);
48085
48251
  const endIdx = existing.indexOf(END);
48086
48252
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -48109,7 +48275,7 @@ ${END}
48109
48275
  const final = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
48110
48276
 
48111
48277
  ${block}` : existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
48112
- writeFileSync16(file2, final, "utf8");
48278
+ writeFileSync17(file2, final, "utf8");
48113
48279
  console.log(`installed Codex hooks \u2192 ${file2}`);
48114
48280
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
48115
48281
  console.log("");
@@ -48372,7 +48538,7 @@ async function cmdDash(args2) {
48372
48538
  await yieldToLoop2();
48373
48539
  try {
48374
48540
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
48375
- const res = bleedRules(join25(r.root, ".claude", "rules"), items);
48541
+ const res = bleedRules(join26(r.root, ".claude", "rules"), items);
48376
48542
  if (res.written || res.pruned) {
48377
48543
  console.log(
48378
48544
  `[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.73",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {