@inerrata-corporation/errata 2.0.0-dev.43 → 2.0.0-dev.44

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.
@@ -15178,6 +15178,13 @@ var init_wire = __esm({
15178
15178
  }
15179
15179
  });
15180
15180
 
15181
+ // ../../packages/shared/src/repo-locator.ts
15182
+ var init_repo_locator = __esm({
15183
+ "../../packages/shared/src/repo-locator.ts"() {
15184
+ "use strict";
15185
+ }
15186
+ });
15187
+
15181
15188
  // ../../packages/shared/src/nlp/canonicalize.ts
15182
15189
  var init_canonicalize = __esm({
15183
15190
  "../../packages/shared/src/nlp/canonicalize.ts"() {
@@ -15212,6 +15219,7 @@ var init_src = __esm({
15212
15219
  init_wire();
15213
15220
  init_edge_rules();
15214
15221
  init_symbol_intent();
15222
+ init_repo_locator();
15215
15223
  init_hash();
15216
15224
  init_error_signature();
15217
15225
  init_canonicalize();
package/errata.mjs CHANGED
@@ -15481,6 +15481,42 @@ var init_wire = __esm({
15481
15481
  }
15482
15482
  });
15483
15483
 
15484
+ // ../../packages/shared/src/repo-locator.ts
15485
+ function normalizeRepoLocator(remoteUrl) {
15486
+ const raw2 = remoteUrl.trim();
15487
+ if (!raw2) return null;
15488
+ let host;
15489
+ let path2;
15490
+ const schemeMatch = /^(?:git\+)?([a-z][a-z0-9+.-]*):\/\//i.exec(raw2);
15491
+ if (schemeMatch) {
15492
+ const scheme = schemeMatch[1].toLowerCase();
15493
+ if (scheme === "file") return null;
15494
+ let u;
15495
+ try {
15496
+ u = new URL(raw2.replace(/^git\+/i, ""));
15497
+ } catch {
15498
+ return null;
15499
+ }
15500
+ host = u.hostname.toLowerCase() + (u.port ? `:${u.port}` : "");
15501
+ path2 = u.pathname;
15502
+ } else {
15503
+ const scp = SCP_LIKE.exec(raw2);
15504
+ if (!scp) return null;
15505
+ host = scp[2].toLowerCase();
15506
+ path2 = scp[3];
15507
+ }
15508
+ path2 = path2.replace(/^\/+/, "").replace(/\/+$/, "").replace(/\.git$/i, "");
15509
+ if (!host || !path2) return null;
15510
+ return `${host}/${path2}`;
15511
+ }
15512
+ var SCP_LIKE;
15513
+ var init_repo_locator = __esm({
15514
+ "../../packages/shared/src/repo-locator.ts"() {
15515
+ "use strict";
15516
+ SCP_LIKE = /^(?:([^@/]+)@)?([^:/@]+\.[^:/@]+):(.+)$/;
15517
+ }
15518
+ });
15519
+
15484
15520
  // ../../packages/shared/src/nlp/canonicalize.ts
15485
15521
  function canonicalize(value) {
15486
15522
  return value.normalize("NFC").trim().toLowerCase().replace(/\s+/g, " ");
@@ -15587,6 +15623,7 @@ __export(src_exports, {
15587
15623
  languageCanonicalId: () => languageCanonicalId,
15588
15624
  normalizeExtractionSource: () => normalizeExtractionSource,
15589
15625
  normalizePredicate: () => normalizePredicate,
15626
+ normalizeRepoLocator: () => normalizeRepoLocator,
15590
15627
  packageCanonicalId: () => packageCanonicalId,
15591
15628
  pagerankEdgeTypes: () => pagerankEdgeTypes,
15592
15629
  parsePackageRef: () => parsePackageRef,
@@ -15612,6 +15649,7 @@ var init_src = __esm({
15612
15649
  init_wire();
15613
15650
  init_edge_rules();
15614
15651
  init_symbol_intent();
15652
+ init_repo_locator();
15615
15653
  init_hash();
15616
15654
  init_error_signature();
15617
15655
  init_canonicalize();
@@ -28352,13 +28390,13 @@ async function Module2(moduleArg = {}) {
28352
28390
  }
28353
28391
  readAsync = /* @__PURE__ */ __name(async (url2) => {
28354
28392
  if (isFileURI(url2)) {
28355
- return new Promise((resolve5, reject) => {
28393
+ return new Promise((resolve6, reject) => {
28356
28394
  var xhr = new XMLHttpRequest();
28357
28395
  xhr.open("GET", url2, true);
28358
28396
  xhr.responseType = "arraybuffer";
28359
28397
  xhr.onload = () => {
28360
28398
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
28361
- resolve5(xhr.response);
28399
+ resolve6(xhr.response);
28362
28400
  return;
28363
28401
  }
28364
28402
  reject(xhr.status);
@@ -28554,9 +28592,9 @@ async function Module2(moduleArg = {}) {
28554
28592
  __name(receiveInstantiationResult, "receiveInstantiationResult");
28555
28593
  var info2 = getWasmImports();
28556
28594
  if (Module["instantiateWasm"]) {
28557
- return new Promise((resolve5, reject) => {
28595
+ return new Promise((resolve6, reject) => {
28558
28596
  Module["instantiateWasm"](info2, (mod, inst) => {
28559
- resolve5(receiveInstance(mod, inst));
28597
+ resolve6(receiveInstance(mod, inst));
28560
28598
  });
28561
28599
  });
28562
28600
  }
@@ -29887,8 +29925,8 @@ async function Module2(moduleArg = {}) {
29887
29925
  if (runtimeInitialized) {
29888
29926
  moduleRtn = Module;
29889
29927
  } else {
29890
- moduleRtn = new Promise((resolve5, reject) => {
29891
- readyPromiseResolve = resolve5;
29928
+ moduleRtn = new Promise((resolve6, reject) => {
29929
+ readyPromiseResolve = resolve6;
29892
29930
  readyPromiseReject = reject;
29893
29931
  });
29894
29932
  }
@@ -38216,12 +38254,12 @@ var init_report_render = __esm({
38216
38254
 
38217
38255
  // src/cli.ts
38218
38256
  init_src5();
38219
- import { closeSync as closeSync2, existsSync as existsSync20, openSync as openSync2, readFileSync as readFileSync19, renameSync as renameSync3, statSync as statSync5 } from "node:fs";
38220
- import { join as join23 } from "node:path";
38257
+ import { closeSync as closeSync2, existsSync as existsSync21, openSync as openSync2, readFileSync as readFileSync20, renameSync as renameSync3, statSync as statSync6 } from "node:fs";
38258
+ import { join as join24 } from "node:path";
38221
38259
  import { spawn as spawn3 } from "node:child_process";
38222
38260
 
38223
38261
  // src/daemon.ts
38224
- import { existsSync as existsSync16, writeFileSync as writeFileSync13 } from "node:fs";
38262
+ import { existsSync as existsSync17, writeFileSync as writeFileSync13 } from "node:fs";
38225
38263
 
38226
38264
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
38227
38265
  import { createServer as createServerHTTP } from "http";
@@ -38651,7 +38689,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
38651
38689
  });
38652
38690
  if (!chunk) {
38653
38691
  if (i2 === 1) {
38654
- await new Promise((resolve5) => setTimeout(resolve5));
38692
+ await new Promise((resolve6) => setTimeout(resolve6));
38655
38693
  maxReadCount = 3;
38656
38694
  continue;
38657
38695
  }
@@ -38801,8 +38839,8 @@ init_config();
38801
38839
 
38802
38840
  // src/engine.ts
38803
38841
  import { execFileSync as execFileSync3 } from "node:child_process";
38804
- import { existsSync as existsSync15, statSync as statSync4, appendFileSync as appendFileSync2, readdirSync as readdirSync7, renameSync as renameSync2, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "node:fs";
38805
- import { join as join20, relative as relative6, sep as sep4 } from "node:path";
38842
+ 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";
38843
+ import { join as join21, relative as relative6, sep as sep4 } from "node:path";
38806
38844
 
38807
38845
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
38808
38846
  import { stat as statcb } from "fs";
@@ -39658,7 +39696,7 @@ var NodeFsHandler = class {
39658
39696
  this._addToNodeFs(path2, initialAdd, wh, depth + 1);
39659
39697
  }
39660
39698
  }).on(EV.ERROR, this._boundHandleError);
39661
- return new Promise((resolve5, reject) => {
39699
+ return new Promise((resolve6, reject) => {
39662
39700
  if (!stream)
39663
39701
  return reject();
39664
39702
  stream.once(STR_END, () => {
@@ -39667,7 +39705,7 @@ var NodeFsHandler = class {
39667
39705
  return;
39668
39706
  }
39669
39707
  const wasThrottled = throttler ? throttler.clear() : false;
39670
- resolve5(void 0);
39708
+ resolve6(void 0);
39671
39709
  previous.getChildren().filter((item) => {
39672
39710
  return item !== directory && !current.has(item);
39673
39711
  }).forEach((item) => {
@@ -41481,8 +41519,8 @@ var PassWorker = class {
41481
41519
  this.ensureWorker();
41482
41520
  const id = this.nextId++;
41483
41521
  return this.ready.then(
41484
- () => new Promise((resolve5, reject) => {
41485
- this.pending.set(id, { resolve: resolve5, reject });
41522
+ () => new Promise((resolve6, reject) => {
41523
+ this.pending.set(id, { resolve: resolve6, reject });
41486
41524
  this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
41487
41525
  })
41488
41526
  );
@@ -41492,12 +41530,12 @@ var PassWorker = class {
41492
41530
  const workerUrl = new URL("./pass-worker.mjs", import.meta.url);
41493
41531
  const worker = new Worker(workerUrl, { workerData: this.init, execArgv: process.execArgv });
41494
41532
  this.worker = worker;
41495
- this.ready = new Promise((resolve5, reject) => {
41533
+ this.ready = new Promise((resolve6, reject) => {
41496
41534
  const onReady = (m) => {
41497
41535
  if (m?.ready) {
41498
41536
  worker.off("message", onReady);
41499
41537
  worker.off("error", onErr);
41500
- resolve5();
41538
+ resolve6();
41501
41539
  }
41502
41540
  };
41503
41541
  const onErr = (err2) => reject(err2);
@@ -41939,7 +41977,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
41939
41977
  // src/git-delta.ts
41940
41978
  import { execFile } from "node:child_process";
41941
41979
  function git(repoDir, args2) {
41942
- return new Promise((resolve5, reject) => {
41980
+ return new Promise((resolve6, reject) => {
41943
41981
  execFile(
41944
41982
  "git",
41945
41983
  ["-C", repoDir, ...args2],
@@ -41950,7 +41988,7 @@ function git(repoDir, args2) {
41950
41988
  // git-sensor runs on every commit/checkout.
41951
41989
  windowsHide: true
41952
41990
  },
41953
- (err2, stdout) => err2 ? reject(err2) : resolve5(stdout)
41991
+ (err2, stdout) => err2 ? reject(err2) : resolve6(stdout)
41954
41992
  );
41955
41993
  });
41956
41994
  }
@@ -42338,16 +42376,77 @@ var CausalBuffer = class {
42338
42376
  // src/profile.ts
42339
42377
  init_src2();
42340
42378
  init_paths();
42341
- import { existsSync as existsSync14, readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "node:fs";
42379
+ import { existsSync as existsSync15, readFileSync as readFileSync14, writeFileSync as writeFileSync11 } from "node:fs";
42342
42380
  import { createHash as createHash12 } from "node:crypto";
42343
- import { join as join19 } from "node:path";
42381
+ import { join as join20 } from "node:path";
42382
+
42383
+ // src/git-remote.ts
42384
+ init_src();
42385
+ import { existsSync as existsSync14, readFileSync as readFileSync13, statSync as statSync4 } from "node:fs";
42386
+ import { isAbsolute as isAbsolute3, join as join19, resolve as resolve5 } from "node:path";
42387
+ function resolveGitDir(root) {
42388
+ const dotGit = join19(root, ".git");
42389
+ try {
42390
+ const st = statSync4(dotGit);
42391
+ if (st.isDirectory()) return dotGit;
42392
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync13(dotGit, "utf8"));
42393
+ if (!m) return null;
42394
+ const dir = m[1];
42395
+ return isAbsolute3(dir) ? dir : resolve5(root, dir);
42396
+ } catch {
42397
+ return null;
42398
+ }
42399
+ }
42400
+ function gitConfigPath(gitDir) {
42401
+ const commondirFile = join19(gitDir, "commondir");
42402
+ if (existsSync14(commondirFile)) {
42403
+ const common = readFileSync13(commondirFile, "utf8").trim();
42404
+ const commonDir = isAbsolute3(common) ? common : resolve5(gitDir, common);
42405
+ return join19(commonDir, "config");
42406
+ }
42407
+ return join19(gitDir, "config");
42408
+ }
42409
+ function readRemotes(root) {
42410
+ const gitDir = resolveGitDir(root);
42411
+ if (!gitDir) return [];
42412
+ const cfgPath = gitConfigPath(gitDir);
42413
+ if (!existsSync14(cfgPath)) return [];
42414
+ let txt;
42415
+ try {
42416
+ txt = readFileSync13(cfgPath, "utf8");
42417
+ } catch {
42418
+ return [];
42419
+ }
42420
+ const out2 = [];
42421
+ const sectionRe = /^\s*\[remote "([^"]+)"\]\s*$([\s\S]*?)(?=^\s*\[|\s*$(?![\s\S]))/gm;
42422
+ for (const m of txt.matchAll(sectionRe)) {
42423
+ const url2 = /^\s*url\s*=\s*(.+?)\s*$/m.exec(m[2])?.[1];
42424
+ if (url2) out2.push({ name: m[1], url: url2 });
42425
+ }
42426
+ return out2;
42427
+ }
42428
+ function detectRepoLocator(root) {
42429
+ const remotes = readRemotes(root);
42430
+ if (remotes.length === 0) return null;
42431
+ const pick2 = remotes.find((r) => r.name === "origin") ?? (remotes.length === 1 ? remotes[0] : null);
42432
+ return pick2 ? normalizeRepoLocator(pick2.url) : null;
42433
+ }
42434
+
42435
+ // src/profile.ts
42344
42436
  function workspaceId(root) {
42345
42437
  return "wp_" + createHash12("sha256").update(root).digest("hex").slice(0, 12);
42346
42438
  }
42439
+ function refreshRepoLocator(root, profile) {
42440
+ const detected = detectRepoLocator(root);
42441
+ if (!detected || detected === profile.repoLocator) return false;
42442
+ profile.repoLocator = detected;
42443
+ saveProfile(root, profile);
42444
+ return true;
42445
+ }
42347
42446
  function loadProfile(root) {
42348
42447
  const p = workspacePaths(root);
42349
- if (!existsSync14(p.workspaceJson)) return null;
42350
- return JSON.parse(readFileSync13(p.workspaceJson, "utf8"));
42448
+ if (!existsSync15(p.workspaceJson)) return null;
42449
+ return JSON.parse(readFileSync14(p.workspaceJson, "utf8"));
42351
42450
  }
42352
42451
  function saveProfile(root, profile) {
42353
42452
  const p = workspacePaths(root);
@@ -42358,10 +42457,12 @@ function autodetectProfile(root) {
42358
42457
  const id = workspaceId(root);
42359
42458
  const name2 = root.split(/[\\/]/).filter(Boolean).pop() ?? "workspace";
42360
42459
  const p = emptyProfile(id, name2);
42361
- const pkgPath = join19(root, "package.json");
42362
- if (existsSync14(pkgPath)) {
42460
+ const locator = detectRepoLocator(root);
42461
+ if (locator) p.repoLocator = locator;
42462
+ const pkgPath = join20(root, "package.json");
42463
+ if (existsSync15(pkgPath)) {
42363
42464
  try {
42364
- const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
42465
+ const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
42365
42466
  p.languages.push("typescript", "javascript");
42366
42467
  const nodeVer = pkg.engines?.node ?? "node";
42367
42468
  p.stack.push(`node@${nodeVer}`);
@@ -42382,10 +42483,10 @@ function autodetectProfile(root) {
42382
42483
  } catch {
42383
42484
  }
42384
42485
  }
42385
- const pyproject = join19(root, "pyproject.toml");
42386
- if (existsSync14(pyproject)) {
42486
+ const pyproject = join20(root, "pyproject.toml");
42487
+ if (existsSync15(pyproject)) {
42387
42488
  try {
42388
- const txt = readFileSync13(pyproject, "utf8");
42489
+ const txt = readFileSync14(pyproject, "utf8");
42389
42490
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
42390
42491
  p.languages.push("python");
42391
42492
  p.stack.push(`python@${py ?? "3"}`);
@@ -42396,16 +42497,16 @@ function autodetectProfile(root) {
42396
42497
  } catch {
42397
42498
  }
42398
42499
  }
42399
- const reqs = join19(root, "requirements.txt");
42400
- if (existsSync14(reqs)) {
42500
+ const reqs = join20(root, "requirements.txt");
42501
+ if (existsSync15(reqs)) {
42401
42502
  if (!p.languages.includes("python")) p.languages.push("python");
42402
42503
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
42403
42504
  }
42404
- if (existsSync14(join19(root, "go.mod"))) {
42505
+ if (existsSync15(join20(root, "go.mod"))) {
42405
42506
  p.languages.push("go");
42406
42507
  p.stack.push("go");
42407
42508
  }
42408
- if (existsSync14(join19(root, "Cargo.toml"))) {
42509
+ if (existsSync15(join20(root, "Cargo.toml"))) {
42409
42510
  p.languages.push("rust");
42410
42511
  p.stack.push("rust");
42411
42512
  }
@@ -42563,7 +42664,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
42563
42664
  }
42564
42665
 
42565
42666
  // src/engine.ts
42566
- var DAEMON_VERSION = true ? "2.0.0-dev.43" : "2.0.0-alpha.0";
42667
+ var DAEMON_VERSION = true ? "2.0.0-dev.44" : "2.0.0-alpha.0";
42567
42668
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
42568
42669
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
42569
42670
  var GIT_OP_MUTE_MS = 4e3;
@@ -42573,7 +42674,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
42573
42674
  function appendIdentityAudit(path2, record2, line) {
42574
42675
  if (!record2.accepted && record2.score <= 0) return;
42575
42676
  try {
42576
- if (existsSync15(path2) && statSync4(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
42677
+ if (existsSync16(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
42577
42678
  renameSync2(path2, `${path2}.1`);
42578
42679
  }
42579
42680
  appendFileSync2(path2, line);
@@ -42583,7 +42684,7 @@ function appendIdentityAudit(path2, record2, line) {
42583
42684
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
42584
42685
  function loadTurnCursors(path2) {
42585
42686
  try {
42586
- return new Map(Object.entries(JSON.parse(readFileSync14(path2, "utf8"))));
42687
+ return new Map(Object.entries(JSON.parse(readFileSync15(path2, "utf8"))));
42587
42688
  } catch {
42588
42689
  return /* @__PURE__ */ new Map();
42589
42690
  }
@@ -42612,7 +42713,7 @@ function gitSourceWatchTargets(root) {
42612
42713
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
42613
42714
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
42614
42715
  );
42615
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join20(root, d) + sep4));
42716
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join21(root, d) + sep4));
42616
42717
  } catch {
42617
42718
  }
42618
42719
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -42624,19 +42725,19 @@ function gitSourceWatchTargets(root) {
42624
42725
  if (!f.startsWith(prefix)) continue;
42625
42726
  const rest2 = f.slice(prefix.length);
42626
42727
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
42627
- else targets.add(join20(root, f));
42728
+ else targets.add(join21(root, f));
42628
42729
  }
42629
42730
  for (const c of children) {
42630
- if (IGNORED_PATH.test(join20(root, c) + sep4)) continue;
42731
+ if (IGNORED_PATH.test(join21(root, c) + sep4)) continue;
42631
42732
  if (hasIgnoredChild(c)) addUnder(c);
42632
- else targets.add(join20(root, c));
42733
+ else targets.add(join21(root, c));
42633
42734
  }
42634
42735
  };
42635
42736
  addUnder("");
42636
42737
  if (targets.size > 0) return [...targets];
42637
42738
  } catch {
42638
42739
  }
42639
- return readdirSync7(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join20(root, String(e.name)) + sep4)).map((e) => join20(root, String(e.name)));
42740
+ 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)));
42640
42741
  }
42641
42742
  function createWorkspaceEngine(opts) {
42642
42743
  const paths = workspacePaths(opts.workspaceRoot);
@@ -42647,6 +42748,8 @@ function createWorkspaceEngine(opts) {
42647
42748
  if (!profile) {
42648
42749
  profile = autodetectProfile(opts.workspaceRoot);
42649
42750
  saveProfile(opts.workspaceRoot, profile);
42751
+ } else {
42752
+ refreshRepoLocator(opts.workspaceRoot, profile);
42650
42753
  }
42651
42754
  const store = openGraphStore({ path: paths.castalia });
42652
42755
  const log = openEventLog({ path: paths.eventLog });
@@ -42675,7 +42778,7 @@ function createWorkspaceEngine(opts) {
42675
42778
  if (IGNORED_PATH.test(path2) || IGNORED_NOISE.test(path2)) return;
42676
42779
  let size = 0;
42677
42780
  try {
42678
- size = statSync4(path2).size;
42781
+ size = statSync5(path2).size;
42679
42782
  } catch {
42680
42783
  }
42681
42784
  const base = { ts: Date.now(), kind, workspaceId: profile.id, path: path2, size };
@@ -42788,7 +42891,7 @@ function createWorkspaceEngine(opts) {
42788
42891
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
42789
42892
  let episodeId2;
42790
42893
  if (srcPaths.length > 0) {
42791
- const abs = srcPaths.map((p) => join20(opts.workspaceRoot, p));
42894
+ const abs = srcPaths.map((p) => join21(opts.workspaceRoot, p));
42792
42895
  try {
42793
42896
  const r = await runReindexPass(
42794
42897
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -42819,8 +42922,8 @@ function createWorkspaceEngine(opts) {
42819
42922
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
42820
42923
  );
42821
42924
  };
42822
- const gitDir = join20(opts.workspaceRoot, ".git");
42823
- if (existsSync15(gitDir)) {
42925
+ const gitDir = join21(opts.workspaceRoot, ".git");
42926
+ if (existsSync16(gitDir)) {
42824
42927
  stopGit = startGitSensor(gitDir, (ev) => {
42825
42928
  void handleGitEvent(ev);
42826
42929
  });
@@ -42886,10 +42989,10 @@ function createWorkspaceEngine(opts) {
42886
42989
  ...pendingUpdate ? { pendingUpdate } : {}
42887
42990
  });
42888
42991
  doneRender?.();
42889
- const target = join20(opts.workspaceRoot, "AGENTS.md");
42992
+ const target = join21(opts.workspaceRoot, "AGENTS.md");
42890
42993
  writeManagedBlock(target, { body: body2 });
42891
42994
  if (elicit) {
42892
- writePrimingHandles(join20(paths.configDir, "priming-handles.json"), [
42995
+ writePrimingHandles(join21(paths.configDir, "priming-handles.json"), [
42893
42996
  ...snapshot.recentProblems.map((r) => r.node),
42894
42997
  // Resolved-band handles: the ✓ problem AND its Solution are citable
42895
42998
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -43059,7 +43162,7 @@ function createWorkspaceEngine(opts) {
43059
43162
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
43060
43163
  });
43061
43164
  };
43062
- const turnCursorPath = join20(paths.configDir, "turn-cursors.json");
43165
+ const turnCursorPath = join21(paths.configDir, "turn-cursors.json");
43063
43166
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
43064
43167
  const sessionLastProblem = /* @__PURE__ */ new Map();
43065
43168
  const sessionThreads = /* @__PURE__ */ new Map();
@@ -43082,7 +43185,7 @@ function createWorkspaceEngine(opts) {
43082
43185
  const t = Date.now();
43083
43186
  let processedTurns = 0;
43084
43187
  const elicit = isEdgeElicitationEnabled();
43085
- const handleMap = elicit ? readPrimingHandles(join20(paths.configDir, "priming-handles.json")) : {};
43188
+ const handleMap = elicit ? readPrimingHandles(join21(paths.configDir, "priming-handles.json")) : {};
43086
43189
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
43087
43190
  const toRel = (abs) => {
43088
43191
  const p = abs.replace(/\\/g, "/");
@@ -43711,7 +43814,7 @@ function createWorkspaceEngine(opts) {
43711
43814
  console.log(
43712
43815
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
43713
43816
  );
43714
- const pending = existsSync15(paths.outbox) ? readdirSync7(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
43817
+ const pending = existsSync16(paths.outbox) ? readdirSync7(paths.outbox).filter((f) => f.endsWith(".json")).length : 0;
43715
43818
  return { uploaded: 0, failed: 0, remaining: pending };
43716
43819
  }
43717
43820
  try {
@@ -43841,7 +43944,7 @@ async function startDaemon(opts) {
43841
43944
  );
43842
43945
  await engine.stop();
43843
43946
  try {
43844
- if (existsSync16(engine.paths.daemonLock)) {
43947
+ if (existsSync17(engine.paths.daemonLock)) {
43845
43948
  }
43846
43949
  } catch {
43847
43950
  }
@@ -43849,25 +43952,25 @@ async function startDaemon(opts) {
43849
43952
  };
43850
43953
  }
43851
43954
  async function listenServer(fetchFn, port) {
43852
- return new Promise((resolve5) => {
43955
+ return new Promise((resolve6) => {
43853
43956
  const server = serve({ fetch: fetchFn, hostname: "127.0.0.1", port }, (info2) => {
43854
- resolve5({ server, port: info2.port });
43957
+ resolve6({ server, port: info2.port });
43855
43958
  });
43856
43959
  });
43857
43960
  }
43858
43961
 
43859
43962
  // src/registry.ts
43860
43963
  init_paths();
43861
- import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "node:fs";
43862
- import { join as join21 } from "node:path";
43964
+ import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
43965
+ import { join as join22 } from "node:path";
43863
43966
  function registryPath() {
43864
- return process.env["ERRATA_REGISTRY_PATH"] ?? join21(globalDir(), "workspaces.json");
43967
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join22(globalDir(), "workspaces.json");
43865
43968
  }
43866
43969
  function read() {
43867
43970
  const p = registryPath();
43868
- if (!existsSync17(p)) return { version: 1, workspaces: {} };
43971
+ if (!existsSync18(p)) return { version: 1, workspaces: {} };
43869
43972
  try {
43870
- const parsed = JSON.parse(readFileSync15(p, "utf8"));
43973
+ const parsed = JSON.parse(readFileSync16(p, "utf8"));
43871
43974
  return { version: 1, workspaces: parsed.workspaces ?? {} };
43872
43975
  } catch {
43873
43976
  return { version: 1, workspaces: {} };
@@ -43892,7 +43995,7 @@ function pruneMissingWorkspaces() {
43892
43995
  const reg = read();
43893
43996
  const removed = [];
43894
43997
  for (const [id, entry] of Object.entries(reg.workspaces)) {
43895
- if (!existsSync17(entry.path)) {
43998
+ if (!existsSync18(entry.path)) {
43896
43999
  removed.push(entry);
43897
44000
  delete reg.workspaces[id];
43898
44001
  }
@@ -43901,13 +44004,13 @@ function pruneMissingWorkspaces() {
43901
44004
  return removed;
43902
44005
  }
43903
44006
  function workspaceStatus(entry) {
43904
- const missing = !existsSync17(entry.path);
44007
+ const missing = !existsSync18(entry.path);
43905
44008
  const lockPath = workspacePaths(entry.path).daemonLock;
43906
44009
  let running = false;
43907
44010
  let webUiUrl = null;
43908
- if (existsSync17(lockPath)) {
44011
+ if (existsSync18(lockPath)) {
43909
44012
  try {
43910
- const lock = JSON.parse(readFileSync15(lockPath, "utf8"));
44013
+ const lock = JSON.parse(readFileSync16(lockPath, "utf8"));
43911
44014
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
43912
44015
  running = true;
43913
44016
  webUiUrl = lock.webUiUrl;
@@ -43935,7 +44038,7 @@ function pidAlive(pid) {
43935
44038
  // src/multi.ts
43936
44039
  init_dist();
43937
44040
  init_src4();
43938
- import { readFileSync as readFileSync18, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
44041
+ import { readFileSync as readFileSync19, unlinkSync as unlinkSync3, writeFileSync as writeFileSync15 } from "node:fs";
43939
44042
 
43940
44043
  // src/principle-sync.ts
43941
44044
  init_src4();
@@ -43962,8 +44065,8 @@ async function syncPrinciples(store, cloud, opts) {
43962
44065
  init_reconcile();
43963
44066
 
43964
44067
  // src/lockfile-auto.ts
43965
- import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
43966
- import { join as join22 } from "node:path";
44068
+ import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
44069
+ import { join as join23 } from "node:path";
43967
44070
 
43968
44071
  // src/package-index.ts
43969
44072
  init_src();
@@ -44227,11 +44330,11 @@ function runLockfilePass(opts) {
44227
44330
  { file: "package-lock.json", parse: parsePackageLockJson }
44228
44331
  ];
44229
44332
  for (const c of candidates) {
44230
- const p = join22(opts.root, c.file);
44231
- if (!existsSync18(p)) continue;
44333
+ const p = join23(opts.root, c.file);
44334
+ if (!existsSync19(p)) continue;
44232
44335
  let sbom;
44233
44336
  try {
44234
- sbom = c.parse(readFileSync16(p, "utf8"));
44337
+ sbom = c.parse(readFileSync17(p, "utf8"));
44235
44338
  } catch {
44236
44339
  continue;
44237
44340
  }
@@ -44449,8 +44552,8 @@ var ConsolidateWorker = class {
44449
44552
  this.ensureWorker();
44450
44553
  const id = this.nextId++;
44451
44554
  return this.ready.then(
44452
- () => new Promise((resolve5, reject) => {
44453
- this.pending.set(id, { resolve: resolve5, reject });
44555
+ () => new Promise((resolve6, reject) => {
44556
+ this.pending.set(id, { resolve: resolve6, reject });
44454
44557
  this.worker.postMessage({ ...req, id });
44455
44558
  })
44456
44559
  );
@@ -44460,12 +44563,12 @@ var ConsolidateWorker = class {
44460
44563
  const workerUrl = new URL("./consolidate-worker.mjs", import.meta.url);
44461
44564
  const worker = new Worker2(workerUrl, { workerData: {}, execArgv: process.execArgv });
44462
44565
  this.worker = worker;
44463
- this.ready = new Promise((resolve5, reject) => {
44566
+ this.ready = new Promise((resolve6, reject) => {
44464
44567
  const onReady = (m) => {
44465
44568
  if (m?.ready) {
44466
44569
  worker.off("message", onReady);
44467
44570
  worker.off("error", onErr);
44468
- resolve5();
44571
+ resolve6();
44469
44572
  }
44470
44573
  };
44471
44574
  const onErr = (err2) => {
@@ -44507,7 +44610,7 @@ var ConsolidateWorker = class {
44507
44610
  init_paths();
44508
44611
 
44509
44612
  // src/lock.ts
44510
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
44613
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
44511
44614
  function isProcessAlive(pid) {
44512
44615
  if (!pid || pid <= 0) return false;
44513
44616
  try {
@@ -44518,9 +44621,9 @@ function isProcessAlive(pid) {
44518
44621
  }
44519
44622
  }
44520
44623
  function readDaemonLock(lockPath) {
44521
- if (!existsSync19(lockPath)) return null;
44624
+ if (!existsSync20(lockPath)) return null;
44522
44625
  try {
44523
- const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
44626
+ const lock = JSON.parse(readFileSync18(lockPath, "utf8"));
44524
44627
  return typeof lock.pid === "number" ? lock : null;
44525
44628
  } catch {
44526
44629
  return null;
@@ -44606,13 +44709,13 @@ function startUpdatePoller(opts) {
44606
44709
  };
44607
44710
  }
44608
44711
  function runNpmInstall(channel) {
44609
- return new Promise((resolve5) => {
44712
+ return new Promise((resolve6) => {
44610
44713
  const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
44611
44714
  stdio: "inherit",
44612
44715
  shell: true
44613
44716
  });
44614
- child.on("close", (code) => resolve5(code ?? 1));
44615
- child.on("error", () => resolve5(1));
44717
+ child.on("close", (code) => resolve6(code ?? 1));
44718
+ child.on("error", () => resolve6(1));
44616
44719
  });
44617
44720
  }
44618
44721
 
@@ -44975,7 +45078,7 @@ async function startMultiDaemon(opts = {}) {
44975
45078
  const packageAutoAll = async () => {
44976
45079
  const out2 = /* @__PURE__ */ new Map();
44977
45080
  for (const r of records) {
44978
- await new Promise((resolve5) => setImmediate(resolve5));
45081
+ await new Promise((resolve6) => setImmediate(resolve6));
44979
45082
  const done = markPass(`package-index:${r.entry.name}`);
44980
45083
  try {
44981
45084
  out2.set(
@@ -45045,7 +45148,10 @@ async function startMultiDaemon(opts = {}) {
45045
45148
  ts,
45046
45149
  workspaces: fileBacked.map((r) => ({
45047
45150
  recordId: r.id,
45048
- workspaceId: r.engine.profile.id,
45151
+ // Repo-keyed when linked: two checkouts of one repo are ONE
45152
+ // project in observedInProjects, not two independent
45153
+ // observations (PJ-local — the Q9 independence gate).
45154
+ workspaceId: r.engine.profile.repoLocator ?? r.engine.profile.id,
45049
45155
  castaliaPath: r.engine.paths.castalia
45050
45156
  }))
45051
45157
  });
@@ -45059,7 +45165,13 @@ async function startMultiDaemon(opts = {}) {
45059
45165
  for (const r of inlineRecords) {
45060
45166
  const done = markPass(`percolate-inline:${r.entry.name}`);
45061
45167
  try {
45062
- out2.set(r.id, percolate(r.engine.store, sharedStore, { workspaceId: r.engine.profile.id, ts }));
45168
+ out2.set(
45169
+ r.id,
45170
+ percolate(r.engine.store, sharedStore, {
45171
+ workspaceId: r.engine.profile.repoLocator ?? r.engine.profile.id,
45172
+ ts
45173
+ })
45174
+ );
45063
45175
  } catch (err2) {
45064
45176
  console.warn(
45065
45177
  `[errata] percolate failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`
@@ -45263,7 +45375,7 @@ async function startMultiDaemon(opts = {}) {
45263
45375
  },
45264
45376
  async stop() {
45265
45377
  try {
45266
- const cur = readFileSync18(lockPath, "utf8");
45378
+ const cur = readFileSync19(lockPath, "utf8");
45267
45379
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
45268
45380
  } catch {
45269
45381
  }
@@ -45461,7 +45573,7 @@ async function loginOAuthLoopback(opts) {
45461
45573
  const state = randomState();
45462
45574
  const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
45463
45575
  const { code, redirectUri, clientId } = await new Promise(
45464
- (resolve5, reject) => {
45576
+ (resolve6, reject) => {
45465
45577
  const server = createServer((req, res) => {
45466
45578
  const u = new URL(req.url ?? "/", "http://127.0.0.1");
45467
45579
  if (u.pathname !== "/callback") {
@@ -45484,7 +45596,7 @@ async function loginOAuthLoopback(opts) {
45484
45596
  res.writeHead(200, { "content-type": "text/html" });
45485
45597
  res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
45486
45598
  server.close();
45487
- resolve5({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
45599
+ resolve6({ code: code2, redirectUri: `http://127.0.0.1:${port}/callback`, clientId: activeClientId });
45488
45600
  });
45489
45601
  let activeClientId = oauthClientId();
45490
45602
  server.on("error", reject);
@@ -45824,27 +45936,28 @@ async function cmdInit() {
45824
45936
  console.log(`initialized errata workspace:`);
45825
45937
  console.log(` id: ${profile.id}`);
45826
45938
  console.log(` name: ${profile.name}`);
45939
+ console.log(` repo: ${profile.repoLocator ?? "(no git remote detected)"}`);
45827
45940
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
45828
45941
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
45829
45942
  }
45830
45943
  if (!skipHooks) {
45831
45944
  console.log("");
45832
45945
  console.log("installing harness hooks...");
45833
- const { existsSync: existsSync21 } = await import("node:fs");
45834
- const { join: join24 } = await import("node:path");
45946
+ const { existsSync: existsSync22 } = await import("node:fs");
45947
+ const { join: join25 } = await import("node:path");
45835
45948
  try {
45836
45949
  await installClaudeHooks(port);
45837
45950
  } catch (err2) {
45838
45951
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
45839
45952
  }
45840
- if (existsSync21(join24(ROOT, ".cursor"))) {
45953
+ if (existsSync22(join25(ROOT, ".cursor"))) {
45841
45954
  try {
45842
45955
  await installCursorMcpConfig();
45843
45956
  } catch (err2) {
45844
45957
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
45845
45958
  }
45846
45959
  }
45847
- if (existsSync21(join24(ROOT, ".codex"))) {
45960
+ if (existsSync22(join25(ROOT, ".codex"))) {
45848
45961
  try {
45849
45962
  await installCodexHooks(port);
45850
45963
  } catch (err2) {
@@ -45958,11 +46071,12 @@ async function cmdStatus() {
45958
46071
  console.log(` version: ${DAEMON_VERSION} (update channel: ${cfg.updateChannel})`);
45959
46072
  console.log(` workspace: ${profile ? `${profile.name} (${profile.id})` : "(not initialized)"}`);
45960
46073
  if (profile) {
46074
+ console.log(` repo: ${profile.repoLocator ?? "(no git remote \u2014 unlinked)"}`);
45961
46075
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
45962
46076
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
45963
46077
  }
45964
- console.log(` graph db: ${existsSync20(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
45965
- console.log(` event log: ${existsSync20(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
46078
+ console.log(` graph db: ${existsSync21(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
46079
+ console.log(` event log: ${existsSync21(paths.eventLog) ? "yes" : "no"} (${paths.eventLog})`);
45966
46080
  const lockPath = globalDaemonLock();
45967
46081
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
45968
46082
  console.log(
@@ -46280,11 +46394,11 @@ async function cmdUse(args2) {
46280
46394
  }
46281
46395
  async function cmdReview() {
46282
46396
  const paths = workspacePaths(ROOT);
46283
- if (!existsSync20(paths.reviewQueue)) {
46397
+ if (!existsSync21(paths.reviewQueue)) {
46284
46398
  console.log("(review queue empty)");
46285
46399
  return;
46286
46400
  }
46287
- const queue = JSON.parse(readFileSync19(paths.reviewQueue, "utf8"));
46401
+ const queue = JSON.parse(readFileSync20(paths.reviewQueue, "utf8"));
46288
46402
  if (queue.length === 0) {
46289
46403
  console.log("(review queue empty)");
46290
46404
  return;
@@ -46914,7 +47028,7 @@ async function gatherRepo(store, ws) {
46914
47028
  };
46915
47029
  }
46916
47030
  async function gatherReportData(generatedAt) {
46917
- const { existsSync: existsSync21 } = await import("node:fs");
47031
+ const { existsSync: existsSync22 } = await import("node:fs");
46918
47032
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
46919
47033
  const cfg = loadConfig();
46920
47034
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -46922,7 +47036,7 @@ async function gatherReportData(generatedAt) {
46922
47036
  for (const ws of listWorkspaces()) {
46923
47037
  if (ws.missing) continue;
46924
47038
  const dbPath = workspacePaths(ws.path).castalia;
46925
- if (!existsSync21(dbPath)) continue;
47039
+ if (!existsSync22(dbPath)) continue;
46926
47040
  let store = null;
46927
47041
  try {
46928
47042
  store = openGraphStore2({ path: dbPath });
@@ -46966,8 +47080,8 @@ async function cmdReport(args2) {
46966
47080
  const outDir = workspacePaths(ROOT).configDir;
46967
47081
  mkdirSync6(outDir, { recursive: true });
46968
47082
  const files = renderReport2(data, { includeFutureVerbs });
46969
- for (const f of files) writeFileSync16(join23(outDir, f.name), f.html, "utf8");
46970
- const indexPath = join23(outDir, "report.html");
47083
+ for (const f of files) writeFileSync16(join24(outDir, f.name), f.html, "utf8");
47084
+ const indexPath = join24(outDir, "report.html");
46971
47085
  console.log(`report \u2192 ${indexPath}`);
46972
47086
  console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
46973
47087
  console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
@@ -47019,7 +47133,7 @@ function spawnDaemonDetached() {
47019
47133
  try {
47020
47134
  const logPath = daemonLogPath();
47021
47135
  try {
47022
- if (statSync5(logPath).size > 5 * 1024 * 1024) renameSync3(logPath, `${logPath}.1`);
47136
+ if (statSync6(logPath).size > 5 * 1024 * 1024) renameSync3(logPath, `${logPath}.1`);
47023
47137
  } catch {
47024
47138
  }
47025
47139
  out2 = openSync2(logPath, "a");
@@ -47087,15 +47201,15 @@ function hookRelayCommand(port, path2) {
47087
47201
  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 '{}'`;
47088
47202
  }
47089
47203
  async function installClaudeHooks(port) {
47090
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47091
- const { join: join24 } = await import("node:path");
47092
- const dir = join24(ROOT, ".claude");
47093
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47094
- const file2 = join24(dir, "settings.json");
47204
+ const { mkdirSync: mkdirSync6, existsSync: existsSync22, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
47205
+ const { join: join25 } = await import("node:path");
47206
+ const dir = join25(ROOT, ".claude");
47207
+ if (!existsSync22(dir)) mkdirSync6(dir, { recursive: true });
47208
+ const file2 = join25(dir, "settings.json");
47095
47209
  let settings = {};
47096
- if (existsSync21(file2)) {
47210
+ if (existsSync22(file2)) {
47097
47211
  try {
47098
- settings = JSON.parse(readFileSync20(file2, "utf8"));
47212
+ settings = JSON.parse(readFileSync21(file2, "utf8"));
47099
47213
  } catch {
47100
47214
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47101
47215
  process.exit(2);
@@ -47144,7 +47258,7 @@ async function installClaudeHooks(port) {
47144
47258
  writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
47145
47259
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
47146
47260
  await installClaudeMcpConfig();
47147
- const claudeMd = join24(ROOT, "CLAUDE.md");
47261
+ const claudeMd = join25(ROOT, "CLAUDE.md");
47148
47262
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
47149
47263
  if (recall.kind === "collision") {
47150
47264
  console.warn(
@@ -47156,15 +47270,15 @@ async function installClaudeHooks(port) {
47156
47270
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
47157
47271
  }
47158
47272
  async function installClaudeMcpConfig() {
47159
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47160
- const { join: join24, dirname: dirname8 } = await import("node:path");
47161
- const file2 = join24(ROOT, ".mcp.json");
47273
+ const { mkdirSync: mkdirSync6, existsSync: existsSync22, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
47274
+ const { join: join25, dirname: dirname8 } = await import("node:path");
47275
+ const file2 = join25(ROOT, ".mcp.json");
47162
47276
  const dir = dirname8(file2);
47163
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47277
+ if (!existsSync22(dir)) mkdirSync6(dir, { recursive: true });
47164
47278
  let cfg = {};
47165
- if (existsSync21(file2)) {
47279
+ if (existsSync22(file2)) {
47166
47280
  try {
47167
- cfg = JSON.parse(readFileSync20(file2, "utf8"));
47281
+ cfg = JSON.parse(readFileSync21(file2, "utf8"));
47168
47282
  } catch {
47169
47283
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47170
47284
  process.exit(2);
@@ -47178,15 +47292,15 @@ async function installClaudeMcpConfig() {
47178
47292
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
47179
47293
  }
47180
47294
  async function installCursorMcpConfig() {
47181
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47182
- const { join: join24 } = await import("node:path");
47183
- const dir = join24(ROOT, ".cursor");
47184
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47185
- const file2 = join24(dir, "mcp.json");
47295
+ const { mkdirSync: mkdirSync6, existsSync: existsSync22, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
47296
+ const { join: join25 } = await import("node:path");
47297
+ const dir = join25(ROOT, ".cursor");
47298
+ if (!existsSync22(dir)) mkdirSync6(dir, { recursive: true });
47299
+ const file2 = join25(dir, "mcp.json");
47186
47300
  let cfg = {};
47187
- if (existsSync21(file2)) {
47301
+ if (existsSync22(file2)) {
47188
47302
  try {
47189
- cfg = JSON.parse(readFileSync20(file2, "utf8"));
47303
+ cfg = JSON.parse(readFileSync21(file2, "utf8"));
47190
47304
  } catch {
47191
47305
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47192
47306
  process.exit(2);
@@ -47202,16 +47316,16 @@ async function installCursorMcpConfig() {
47202
47316
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
47203
47317
  }
47204
47318
  async function installCodexHooks(port) {
47205
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47206
- const { join: join24 } = await import("node:path");
47207
- const dir = join24(ROOT, ".codex");
47208
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47209
- const file2 = join24(dir, "config.toml");
47319
+ const { mkdirSync: mkdirSync6, existsSync: existsSync22, readFileSync: readFileSync21, writeFileSync: writeFileSync16 } = await import("node:fs");
47320
+ const { join: join25 } = await import("node:path");
47321
+ const dir = join25(ROOT, ".codex");
47322
+ if (!existsSync22(dir)) mkdirSync6(dir, { recursive: true });
47323
+ const file2 = join25(dir, "config.toml");
47210
47324
  const BEGIN = `# >>> errata hooks (errata-managed)`;
47211
47325
  const END = `# <<< errata hooks`;
47212
47326
  let existing = "";
47213
- if (existsSync21(file2)) {
47214
- existing = readFileSync20(file2, "utf8");
47327
+ if (existsSync22(file2)) {
47328
+ existing = readFileSync21(file2, "utf8");
47215
47329
  const beginIdx = existing.indexOf(BEGIN);
47216
47330
  const endIdx = existing.indexOf(END);
47217
47331
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -47428,7 +47542,7 @@ async function cmdDash(args2) {
47428
47542
  const hotspotScanMark = /* @__PURE__ */ new Map();
47429
47543
  const HOTSPOT_FANIN = 20;
47430
47544
  const runNightlyPass = async () => {
47431
- const yieldToLoop2 = () => new Promise((resolve5) => setImmediate(resolve5));
47545
+ const yieldToLoop2 = () => new Promise((resolve6) => setImmediate(resolve6));
47432
47546
  const fullReclusterPass = nightlyCount++ % FULL_RECLUSTER_EVERY === 0;
47433
47547
  const m = await handle2.nightlyAll();
47434
47548
  let skillsLearned = 0;
@@ -47503,7 +47617,7 @@ async function cmdDash(args2) {
47503
47617
  await yieldToLoop2();
47504
47618
  try {
47505
47619
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
47506
- const res = bleedRules(join23(r.root, ".claude", "rules"), items);
47620
+ const res = bleedRules(join24(r.root, ".claude", "rules"), items);
47507
47621
  if (res.written || res.pruned) {
47508
47622
  console.log(
47509
47623
  `[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.43",
3
+ "version": "2.0.0-dev.44",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
package/pass-worker.mjs CHANGED
@@ -15024,6 +15024,13 @@ var init_wire = __esm({
15024
15024
  }
15025
15025
  });
15026
15026
 
15027
+ // ../../packages/shared/src/repo-locator.ts
15028
+ var init_repo_locator = __esm({
15029
+ "../../packages/shared/src/repo-locator.ts"() {
15030
+ "use strict";
15031
+ }
15032
+ });
15033
+
15027
15034
  // ../../packages/shared/src/nlp/canonicalize.ts
15028
15035
  var init_canonicalize = __esm({
15029
15036
  "../../packages/shared/src/nlp/canonicalize.ts"() {
@@ -15048,6 +15055,7 @@ var init_src = __esm({
15048
15055
  init_wire();
15049
15056
  init_edge_rules();
15050
15057
  init_symbol_intent();
15058
+ init_repo_locator();
15051
15059
  init_hash();
15052
15060
  init_error_signature();
15053
15061
  init_canonicalize();