@inerrata-corporation/errata 2.0.0-dev.42 → 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
@@ -64,7 +64,7 @@ function toCloudAttrs(attrs) {
64
64
  }
65
65
  return rest2;
66
66
  }
67
- var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
67
+ var SEMANTIC_NODE_LABELS, CONTEXT_NODE_LABELS, CODE_NODE_LABELS, ALL_NODE_LABELS, STRUCTURAL_EDGES, CAUSAL_EDGES, RESOLUTION_EDGES, CONCEPTUAL_EDGES, EVIDENCE_EDGES, CODE_EDGES, BRIDGE_EDGES, IDENTITY_EDGES, JUSTIFICATION_EDGES, BELIEF_EDGES, ABSTRACTION_EDGES, DECOMPOSITION_EDGES, TRANSFER_EDGES, TAXONOMY_EDGES, TRIAGE_EDGES, GIT_EDGES, ALL_EDGE_TYPES, PAGERANK_EXCLUSIONS, EDGE_WEIGHT, EDGE_CONDUCTANCE_OVERRIDES, CAUSAL_PROTECT_EDGES, VALIDATION_SOURCES, TRUTH_KIND, ABSTRACTION_LEVEL, PROBLEM_RESOLUTION, DRIFT_KIND, TEST_PATH_RE, TEST_SCOPE_RE;
68
68
  var init_castalia = __esm({
69
69
  "../../packages/shared/src/castalia.ts"() {
70
70
  "use strict";
@@ -365,6 +365,12 @@ var init_castalia = __esm({
365
365
  PARENT: 0,
366
366
  AUTHORED_BY: 0
367
367
  };
368
+ EDGE_CONDUCTANCE_OVERRIDES = {
369
+ // 0.5 ⇒ a 3-hop dependency path scores 0.125 — survives burst's cut — while
370
+ // the weight-derived floor (≈0.1) buried the local lockfile graph's ~7k
371
+ // DEPENDS_ON edges at 0.001 for the same walk.
372
+ DEPENDS_ON: 0.5
373
+ };
368
374
  CAUSAL_PROTECT_EDGES = ["CAUSED_BY", "FIXED_BY", "SOLVED_BY"];
369
375
  VALIDATION_SOURCES = [
370
376
  "human-explicit",
@@ -15475,6 +15481,42 @@ var init_wire = __esm({
15475
15481
  }
15476
15482
  });
15477
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
+
15478
15520
  // ../../packages/shared/src/nlp/canonicalize.ts
15479
15521
  function canonicalize(value) {
15480
15522
  return value.normalize("NFC").trim().toLowerCase().replace(/\s+/g, " ");
@@ -15525,6 +15567,7 @@ __export(src_exports, {
15525
15567
  CastaliaIngestPayloadSchema: () => CastaliaIngestPayloadSchema,
15526
15568
  DECOMPOSITION_EDGES: () => DECOMPOSITION_EDGES,
15527
15569
  DRIFT_KIND: () => DRIFT_KIND,
15570
+ EDGE_CONDUCTANCE_OVERRIDES: () => EDGE_CONDUCTANCE_OVERRIDES,
15528
15571
  EDGE_RULES: () => EDGE_RULES,
15529
15572
  EDGE_WEIGHT: () => EDGE_WEIGHT,
15530
15573
  EVIDENCE_EDGES: () => EVIDENCE_EDGES,
@@ -15580,6 +15623,7 @@ __export(src_exports, {
15580
15623
  languageCanonicalId: () => languageCanonicalId,
15581
15624
  normalizeExtractionSource: () => normalizeExtractionSource,
15582
15625
  normalizePredicate: () => normalizePredicate,
15626
+ normalizeRepoLocator: () => normalizeRepoLocator,
15583
15627
  packageCanonicalId: () => packageCanonicalId,
15584
15628
  pagerankEdgeTypes: () => pagerankEdgeTypes,
15585
15629
  parsePackageRef: () => parsePackageRef,
@@ -15605,6 +15649,7 @@ var init_src = __esm({
15605
15649
  init_wire();
15606
15650
  init_edge_rules();
15607
15651
  init_symbol_intent();
15652
+ init_repo_locator();
15608
15653
  init_hash();
15609
15654
  init_error_signature();
15610
15655
  init_canonicalize();
@@ -16618,6 +16663,8 @@ var init_types = __esm({
16618
16663
 
16619
16664
  // ../../packages/local-graph/src/traversal.ts
16620
16665
  function staticConductance(edgeType) {
16666
+ const override = EDGE_CONDUCTANCE_OVERRIDES[edgeType];
16667
+ if (override != null) return override;
16621
16668
  const w = EDGE_WEIGHT[edgeType];
16622
16669
  if (w == null) return UNKNOWN_CONDUCTANCE;
16623
16670
  return Math.max(UNKNOWN_CONDUCTANCE, Math.min(1, w / MAX_EDGE_WEIGHT));
@@ -28343,13 +28390,13 @@ async function Module2(moduleArg = {}) {
28343
28390
  }
28344
28391
  readAsync = /* @__PURE__ */ __name(async (url2) => {
28345
28392
  if (isFileURI(url2)) {
28346
- return new Promise((resolve5, reject) => {
28393
+ return new Promise((resolve6, reject) => {
28347
28394
  var xhr = new XMLHttpRequest();
28348
28395
  xhr.open("GET", url2, true);
28349
28396
  xhr.responseType = "arraybuffer";
28350
28397
  xhr.onload = () => {
28351
28398
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
28352
- resolve5(xhr.response);
28399
+ resolve6(xhr.response);
28353
28400
  return;
28354
28401
  }
28355
28402
  reject(xhr.status);
@@ -28545,9 +28592,9 @@ async function Module2(moduleArg = {}) {
28545
28592
  __name(receiveInstantiationResult, "receiveInstantiationResult");
28546
28593
  var info2 = getWasmImports();
28547
28594
  if (Module["instantiateWasm"]) {
28548
- return new Promise((resolve5, reject) => {
28595
+ return new Promise((resolve6, reject) => {
28549
28596
  Module["instantiateWasm"](info2, (mod, inst) => {
28550
- resolve5(receiveInstance(mod, inst));
28597
+ resolve6(receiveInstance(mod, inst));
28551
28598
  });
28552
28599
  });
28553
28600
  }
@@ -29878,8 +29925,8 @@ async function Module2(moduleArg = {}) {
29878
29925
  if (runtimeInitialized) {
29879
29926
  moduleRtn = Module;
29880
29927
  } else {
29881
- moduleRtn = new Promise((resolve5, reject) => {
29882
- readyPromiseResolve = resolve5;
29928
+ moduleRtn = new Promise((resolve6, reject) => {
29929
+ readyPromiseResolve = resolve6;
29883
29930
  readyPromiseReject = reject;
29884
29931
  });
29885
29932
  }
@@ -38207,12 +38254,12 @@ var init_report_render = __esm({
38207
38254
 
38208
38255
  // src/cli.ts
38209
38256
  init_src5();
38210
- import { closeSync as closeSync2, existsSync as existsSync20, openSync as openSync2, readFileSync as readFileSync19, renameSync as renameSync3, statSync as statSync5 } from "node:fs";
38211
- 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";
38212
38259
  import { spawn as spawn3 } from "node:child_process";
38213
38260
 
38214
38261
  // src/daemon.ts
38215
- import { existsSync as existsSync16, writeFileSync as writeFileSync13 } from "node:fs";
38262
+ import { existsSync as existsSync17, writeFileSync as writeFileSync13 } from "node:fs";
38216
38263
 
38217
38264
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
38218
38265
  import { createServer as createServerHTTP } from "http";
@@ -38642,7 +38689,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
38642
38689
  });
38643
38690
  if (!chunk) {
38644
38691
  if (i2 === 1) {
38645
- await new Promise((resolve5) => setTimeout(resolve5));
38692
+ await new Promise((resolve6) => setTimeout(resolve6));
38646
38693
  maxReadCount = 3;
38647
38694
  continue;
38648
38695
  }
@@ -38792,8 +38839,8 @@ init_config();
38792
38839
 
38793
38840
  // src/engine.ts
38794
38841
  import { execFileSync as execFileSync3 } from "node:child_process";
38795
- 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";
38796
- 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";
38797
38844
 
38798
38845
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
38799
38846
  import { stat as statcb } from "fs";
@@ -39649,7 +39696,7 @@ var NodeFsHandler = class {
39649
39696
  this._addToNodeFs(path2, initialAdd, wh, depth + 1);
39650
39697
  }
39651
39698
  }).on(EV.ERROR, this._boundHandleError);
39652
- return new Promise((resolve5, reject) => {
39699
+ return new Promise((resolve6, reject) => {
39653
39700
  if (!stream)
39654
39701
  return reject();
39655
39702
  stream.once(STR_END, () => {
@@ -39658,7 +39705,7 @@ var NodeFsHandler = class {
39658
39705
  return;
39659
39706
  }
39660
39707
  const wasThrottled = throttler ? throttler.clear() : false;
39661
- resolve5(void 0);
39708
+ resolve6(void 0);
39662
39709
  previous.getChildren().filter((item) => {
39663
39710
  return item !== directory && !current.has(item);
39664
39711
  }).forEach((item) => {
@@ -41472,8 +41519,8 @@ var PassWorker = class {
41472
41519
  this.ensureWorker();
41473
41520
  const id = this.nextId++;
41474
41521
  return this.ready.then(
41475
- () => new Promise((resolve5, reject) => {
41476
- this.pending.set(id, { resolve: resolve5, reject });
41522
+ () => new Promise((resolve6, reject) => {
41523
+ this.pending.set(id, { resolve: resolve6, reject });
41477
41524
  this.worker.postMessage({ id, kind, ...payload !== void 0 ? { payload } : {} });
41478
41525
  })
41479
41526
  );
@@ -41483,12 +41530,12 @@ var PassWorker = class {
41483
41530
  const workerUrl = new URL("./pass-worker.mjs", import.meta.url);
41484
41531
  const worker = new Worker(workerUrl, { workerData: this.init, execArgv: process.execArgv });
41485
41532
  this.worker = worker;
41486
- this.ready = new Promise((resolve5, reject) => {
41533
+ this.ready = new Promise((resolve6, reject) => {
41487
41534
  const onReady = (m) => {
41488
41535
  if (m?.ready) {
41489
41536
  worker.off("message", onReady);
41490
41537
  worker.off("error", onErr);
41491
- resolve5();
41538
+ resolve6();
41492
41539
  }
41493
41540
  };
41494
41541
  const onErr = (err2) => reject(err2);
@@ -41930,7 +41977,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
41930
41977
  // src/git-delta.ts
41931
41978
  import { execFile } from "node:child_process";
41932
41979
  function git(repoDir, args2) {
41933
- return new Promise((resolve5, reject) => {
41980
+ return new Promise((resolve6, reject) => {
41934
41981
  execFile(
41935
41982
  "git",
41936
41983
  ["-C", repoDir, ...args2],
@@ -41941,7 +41988,7 @@ function git(repoDir, args2) {
41941
41988
  // git-sensor runs on every commit/checkout.
41942
41989
  windowsHide: true
41943
41990
  },
41944
- (err2, stdout) => err2 ? reject(err2) : resolve5(stdout)
41991
+ (err2, stdout) => err2 ? reject(err2) : resolve6(stdout)
41945
41992
  );
41946
41993
  });
41947
41994
  }
@@ -42329,16 +42376,77 @@ var CausalBuffer = class {
42329
42376
  // src/profile.ts
42330
42377
  init_src2();
42331
42378
  init_paths();
42332
- 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";
42333
42380
  import { createHash as createHash12 } from "node:crypto";
42334
- 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
42335
42436
  function workspaceId(root) {
42336
42437
  return "wp_" + createHash12("sha256").update(root).digest("hex").slice(0, 12);
42337
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
+ }
42338
42446
  function loadProfile(root) {
42339
42447
  const p = workspacePaths(root);
42340
- if (!existsSync14(p.workspaceJson)) return null;
42341
- return JSON.parse(readFileSync13(p.workspaceJson, "utf8"));
42448
+ if (!existsSync15(p.workspaceJson)) return null;
42449
+ return JSON.parse(readFileSync14(p.workspaceJson, "utf8"));
42342
42450
  }
42343
42451
  function saveProfile(root, profile) {
42344
42452
  const p = workspacePaths(root);
@@ -42349,10 +42457,12 @@ function autodetectProfile(root) {
42349
42457
  const id = workspaceId(root);
42350
42458
  const name2 = root.split(/[\\/]/).filter(Boolean).pop() ?? "workspace";
42351
42459
  const p = emptyProfile(id, name2);
42352
- const pkgPath = join19(root, "package.json");
42353
- 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)) {
42354
42464
  try {
42355
- const pkg = JSON.parse(readFileSync13(pkgPath, "utf8"));
42465
+ const pkg = JSON.parse(readFileSync14(pkgPath, "utf8"));
42356
42466
  p.languages.push("typescript", "javascript");
42357
42467
  const nodeVer = pkg.engines?.node ?? "node";
42358
42468
  p.stack.push(`node@${nodeVer}`);
@@ -42373,10 +42483,10 @@ function autodetectProfile(root) {
42373
42483
  } catch {
42374
42484
  }
42375
42485
  }
42376
- const pyproject = join19(root, "pyproject.toml");
42377
- if (existsSync14(pyproject)) {
42486
+ const pyproject = join20(root, "pyproject.toml");
42487
+ if (existsSync15(pyproject)) {
42378
42488
  try {
42379
- const txt = readFileSync13(pyproject, "utf8");
42489
+ const txt = readFileSync14(pyproject, "utf8");
42380
42490
  const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
42381
42491
  p.languages.push("python");
42382
42492
  p.stack.push(`python@${py ?? "3"}`);
@@ -42387,16 +42497,16 @@ function autodetectProfile(root) {
42387
42497
  } catch {
42388
42498
  }
42389
42499
  }
42390
- const reqs = join19(root, "requirements.txt");
42391
- if (existsSync14(reqs)) {
42500
+ const reqs = join20(root, "requirements.txt");
42501
+ if (existsSync15(reqs)) {
42392
42502
  if (!p.languages.includes("python")) p.languages.push("python");
42393
42503
  if (!p.stack.includes("python@3")) p.stack.push("python@3");
42394
42504
  }
42395
- if (existsSync14(join19(root, "go.mod"))) {
42505
+ if (existsSync15(join20(root, "go.mod"))) {
42396
42506
  p.languages.push("go");
42397
42507
  p.stack.push("go");
42398
42508
  }
42399
- if (existsSync14(join19(root, "Cargo.toml"))) {
42509
+ if (existsSync15(join20(root, "Cargo.toml"))) {
42400
42510
  p.languages.push("rust");
42401
42511
  p.stack.push("rust");
42402
42512
  }
@@ -42554,7 +42664,7 @@ function startLoopLagMonitor(thresholdMs = 1e3) {
42554
42664
  }
42555
42665
 
42556
42666
  // src/engine.ts
42557
- var DAEMON_VERSION = true ? "2.0.0-dev.42" : "2.0.0-alpha.0";
42667
+ var DAEMON_VERSION = true ? "2.0.0-dev.44" : "2.0.0-alpha.0";
42558
42668
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
42559
42669
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
42560
42670
  var GIT_OP_MUTE_MS = 4e3;
@@ -42564,7 +42674,7 @@ var TURN_REPLAY_LOOKBACK_MS = 7 * 24 * 60 * 6e4;
42564
42674
  function appendIdentityAudit(path2, record2, line) {
42565
42675
  if (!record2.accepted && record2.score <= 0) return;
42566
42676
  try {
42567
- if (existsSync15(path2) && statSync4(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
42677
+ if (existsSync16(path2) && statSync5(path2).size >= IDENTITY_AUDIT_MAX_BYTES) {
42568
42678
  renameSync2(path2, `${path2}.1`);
42569
42679
  }
42570
42680
  appendFileSync2(path2, line);
@@ -42574,7 +42684,7 @@ function appendIdentityAudit(path2, record2, line) {
42574
42684
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
42575
42685
  function loadTurnCursors(path2) {
42576
42686
  try {
42577
- return new Map(Object.entries(JSON.parse(readFileSync14(path2, "utf8"))));
42687
+ return new Map(Object.entries(JSON.parse(readFileSync15(path2, "utf8"))));
42578
42688
  } catch {
42579
42689
  return /* @__PURE__ */ new Map();
42580
42690
  }
@@ -42603,7 +42713,7 @@ function gitSourceWatchTargets(root) {
42603
42713
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
42604
42714
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
42605
42715
  );
42606
- 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));
42607
42717
  } catch {
42608
42718
  }
42609
42719
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -42615,19 +42725,19 @@ function gitSourceWatchTargets(root) {
42615
42725
  if (!f.startsWith(prefix)) continue;
42616
42726
  const rest2 = f.slice(prefix.length);
42617
42727
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
42618
- else targets.add(join20(root, f));
42728
+ else targets.add(join21(root, f));
42619
42729
  }
42620
42730
  for (const c of children) {
42621
- if (IGNORED_PATH.test(join20(root, c) + sep4)) continue;
42731
+ if (IGNORED_PATH.test(join21(root, c) + sep4)) continue;
42622
42732
  if (hasIgnoredChild(c)) addUnder(c);
42623
- else targets.add(join20(root, c));
42733
+ else targets.add(join21(root, c));
42624
42734
  }
42625
42735
  };
42626
42736
  addUnder("");
42627
42737
  if (targets.size > 0) return [...targets];
42628
42738
  } catch {
42629
42739
  }
42630
- 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)));
42631
42741
  }
42632
42742
  function createWorkspaceEngine(opts) {
42633
42743
  const paths = workspacePaths(opts.workspaceRoot);
@@ -42638,6 +42748,8 @@ function createWorkspaceEngine(opts) {
42638
42748
  if (!profile) {
42639
42749
  profile = autodetectProfile(opts.workspaceRoot);
42640
42750
  saveProfile(opts.workspaceRoot, profile);
42751
+ } else {
42752
+ refreshRepoLocator(opts.workspaceRoot, profile);
42641
42753
  }
42642
42754
  const store = openGraphStore({ path: paths.castalia });
42643
42755
  const log = openEventLog({ path: paths.eventLog });
@@ -42666,7 +42778,7 @@ function createWorkspaceEngine(opts) {
42666
42778
  if (IGNORED_PATH.test(path2) || IGNORED_NOISE.test(path2)) return;
42667
42779
  let size = 0;
42668
42780
  try {
42669
- size = statSync4(path2).size;
42781
+ size = statSync5(path2).size;
42670
42782
  } catch {
42671
42783
  }
42672
42784
  const base = { ts: Date.now(), kind, workspaceId: profile.id, path: path2, size };
@@ -42779,7 +42891,7 @@ function createWorkspaceEngine(opts) {
42779
42891
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
42780
42892
  let episodeId2;
42781
42893
  if (srcPaths.length > 0) {
42782
- const abs = srcPaths.map((p) => join20(opts.workspaceRoot, p));
42894
+ const abs = srcPaths.map((p) => join21(opts.workspaceRoot, p));
42783
42895
  try {
42784
42896
  const r = await runReindexPass(
42785
42897
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -42810,8 +42922,8 @@ function createWorkspaceEngine(opts) {
42810
42922
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
42811
42923
  );
42812
42924
  };
42813
- const gitDir = join20(opts.workspaceRoot, ".git");
42814
- if (existsSync15(gitDir)) {
42925
+ const gitDir = join21(opts.workspaceRoot, ".git");
42926
+ if (existsSync16(gitDir)) {
42815
42927
  stopGit = startGitSensor(gitDir, (ev) => {
42816
42928
  void handleGitEvent(ev);
42817
42929
  });
@@ -42877,10 +42989,10 @@ function createWorkspaceEngine(opts) {
42877
42989
  ...pendingUpdate ? { pendingUpdate } : {}
42878
42990
  });
42879
42991
  doneRender?.();
42880
- const target = join20(opts.workspaceRoot, "AGENTS.md");
42992
+ const target = join21(opts.workspaceRoot, "AGENTS.md");
42881
42993
  writeManagedBlock(target, { body: body2 });
42882
42994
  if (elicit) {
42883
- writePrimingHandles(join20(paths.configDir, "priming-handles.json"), [
42995
+ writePrimingHandles(join21(paths.configDir, "priming-handles.json"), [
42884
42996
  ...snapshot.recentProblems.map((r) => r.node),
42885
42997
  // Resolved-band handles: the ✓ problem AND its Solution are citable
42886
42998
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -43050,7 +43162,7 @@ function createWorkspaceEngine(opts) {
43050
43162
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
43051
43163
  });
43052
43164
  };
43053
- const turnCursorPath = join20(paths.configDir, "turn-cursors.json");
43165
+ const turnCursorPath = join21(paths.configDir, "turn-cursors.json");
43054
43166
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
43055
43167
  const sessionLastProblem = /* @__PURE__ */ new Map();
43056
43168
  const sessionThreads = /* @__PURE__ */ new Map();
@@ -43073,7 +43185,7 @@ function createWorkspaceEngine(opts) {
43073
43185
  const t = Date.now();
43074
43186
  let processedTurns = 0;
43075
43187
  const elicit = isEdgeElicitationEnabled();
43076
- const handleMap = elicit ? readPrimingHandles(join20(paths.configDir, "priming-handles.json")) : {};
43188
+ const handleMap = elicit ? readPrimingHandles(join21(paths.configDir, "priming-handles.json")) : {};
43077
43189
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
43078
43190
  const toRel = (abs) => {
43079
43191
  const p = abs.replace(/\\/g, "/");
@@ -43702,7 +43814,7 @@ function createWorkspaceEngine(opts) {
43702
43814
  console.log(
43703
43815
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
43704
43816
  );
43705
- 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;
43706
43818
  return { uploaded: 0, failed: 0, remaining: pending };
43707
43819
  }
43708
43820
  try {
@@ -43832,7 +43944,7 @@ async function startDaemon(opts) {
43832
43944
  );
43833
43945
  await engine.stop();
43834
43946
  try {
43835
- if (existsSync16(engine.paths.daemonLock)) {
43947
+ if (existsSync17(engine.paths.daemonLock)) {
43836
43948
  }
43837
43949
  } catch {
43838
43950
  }
@@ -43840,25 +43952,25 @@ async function startDaemon(opts) {
43840
43952
  };
43841
43953
  }
43842
43954
  async function listenServer(fetchFn, port) {
43843
- return new Promise((resolve5) => {
43955
+ return new Promise((resolve6) => {
43844
43956
  const server = serve({ fetch: fetchFn, hostname: "127.0.0.1", port }, (info2) => {
43845
- resolve5({ server, port: info2.port });
43957
+ resolve6({ server, port: info2.port });
43846
43958
  });
43847
43959
  });
43848
43960
  }
43849
43961
 
43850
43962
  // src/registry.ts
43851
43963
  init_paths();
43852
- import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync14 } from "node:fs";
43853
- 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";
43854
43966
  function registryPath() {
43855
- return process.env["ERRATA_REGISTRY_PATH"] ?? join21(globalDir(), "workspaces.json");
43967
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join22(globalDir(), "workspaces.json");
43856
43968
  }
43857
43969
  function read() {
43858
43970
  const p = registryPath();
43859
- if (!existsSync17(p)) return { version: 1, workspaces: {} };
43971
+ if (!existsSync18(p)) return { version: 1, workspaces: {} };
43860
43972
  try {
43861
- const parsed = JSON.parse(readFileSync15(p, "utf8"));
43973
+ const parsed = JSON.parse(readFileSync16(p, "utf8"));
43862
43974
  return { version: 1, workspaces: parsed.workspaces ?? {} };
43863
43975
  } catch {
43864
43976
  return { version: 1, workspaces: {} };
@@ -43883,7 +43995,7 @@ function pruneMissingWorkspaces() {
43883
43995
  const reg = read();
43884
43996
  const removed = [];
43885
43997
  for (const [id, entry] of Object.entries(reg.workspaces)) {
43886
- if (!existsSync17(entry.path)) {
43998
+ if (!existsSync18(entry.path)) {
43887
43999
  removed.push(entry);
43888
44000
  delete reg.workspaces[id];
43889
44001
  }
@@ -43892,13 +44004,13 @@ function pruneMissingWorkspaces() {
43892
44004
  return removed;
43893
44005
  }
43894
44006
  function workspaceStatus(entry) {
43895
- const missing = !existsSync17(entry.path);
44007
+ const missing = !existsSync18(entry.path);
43896
44008
  const lockPath = workspacePaths(entry.path).daemonLock;
43897
44009
  let running = false;
43898
44010
  let webUiUrl = null;
43899
- if (existsSync17(lockPath)) {
44011
+ if (existsSync18(lockPath)) {
43900
44012
  try {
43901
- const lock = JSON.parse(readFileSync15(lockPath, "utf8"));
44013
+ const lock = JSON.parse(readFileSync16(lockPath, "utf8"));
43902
44014
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
43903
44015
  running = true;
43904
44016
  webUiUrl = lock.webUiUrl;
@@ -43926,7 +44038,7 @@ function pidAlive(pid) {
43926
44038
  // src/multi.ts
43927
44039
  init_dist();
43928
44040
  init_src4();
43929
- 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";
43930
44042
 
43931
44043
  // src/principle-sync.ts
43932
44044
  init_src4();
@@ -43953,8 +44065,8 @@ async function syncPrinciples(store, cloud, opts) {
43953
44065
  init_reconcile();
43954
44066
 
43955
44067
  // src/lockfile-auto.ts
43956
- import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
43957
- 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";
43958
44070
 
43959
44071
  // src/package-index.ts
43960
44072
  init_src();
@@ -44218,11 +44330,11 @@ function runLockfilePass(opts) {
44218
44330
  { file: "package-lock.json", parse: parsePackageLockJson }
44219
44331
  ];
44220
44332
  for (const c of candidates) {
44221
- const p = join22(opts.root, c.file);
44222
- if (!existsSync18(p)) continue;
44333
+ const p = join23(opts.root, c.file);
44334
+ if (!existsSync19(p)) continue;
44223
44335
  let sbom;
44224
44336
  try {
44225
- sbom = c.parse(readFileSync16(p, "utf8"));
44337
+ sbom = c.parse(readFileSync17(p, "utf8"));
44226
44338
  } catch {
44227
44339
  continue;
44228
44340
  }
@@ -44440,8 +44552,8 @@ var ConsolidateWorker = class {
44440
44552
  this.ensureWorker();
44441
44553
  const id = this.nextId++;
44442
44554
  return this.ready.then(
44443
- () => new Promise((resolve5, reject) => {
44444
- this.pending.set(id, { resolve: resolve5, reject });
44555
+ () => new Promise((resolve6, reject) => {
44556
+ this.pending.set(id, { resolve: resolve6, reject });
44445
44557
  this.worker.postMessage({ ...req, id });
44446
44558
  })
44447
44559
  );
@@ -44451,12 +44563,12 @@ var ConsolidateWorker = class {
44451
44563
  const workerUrl = new URL("./consolidate-worker.mjs", import.meta.url);
44452
44564
  const worker = new Worker2(workerUrl, { workerData: {}, execArgv: process.execArgv });
44453
44565
  this.worker = worker;
44454
- this.ready = new Promise((resolve5, reject) => {
44566
+ this.ready = new Promise((resolve6, reject) => {
44455
44567
  const onReady = (m) => {
44456
44568
  if (m?.ready) {
44457
44569
  worker.off("message", onReady);
44458
44570
  worker.off("error", onErr);
44459
- resolve5();
44571
+ resolve6();
44460
44572
  }
44461
44573
  };
44462
44574
  const onErr = (err2) => {
@@ -44498,7 +44610,7 @@ var ConsolidateWorker = class {
44498
44610
  init_paths();
44499
44611
 
44500
44612
  // src/lock.ts
44501
- import { existsSync as existsSync19, readFileSync as readFileSync17 } from "node:fs";
44613
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "node:fs";
44502
44614
  function isProcessAlive(pid) {
44503
44615
  if (!pid || pid <= 0) return false;
44504
44616
  try {
@@ -44509,9 +44621,9 @@ function isProcessAlive(pid) {
44509
44621
  }
44510
44622
  }
44511
44623
  function readDaemonLock(lockPath) {
44512
- if (!existsSync19(lockPath)) return null;
44624
+ if (!existsSync20(lockPath)) return null;
44513
44625
  try {
44514
- const lock = JSON.parse(readFileSync17(lockPath, "utf8"));
44626
+ const lock = JSON.parse(readFileSync18(lockPath, "utf8"));
44515
44627
  return typeof lock.pid === "number" ? lock : null;
44516
44628
  } catch {
44517
44629
  return null;
@@ -44597,13 +44709,13 @@ function startUpdatePoller(opts) {
44597
44709
  };
44598
44710
  }
44599
44711
  function runNpmInstall(channel) {
44600
- return new Promise((resolve5) => {
44712
+ return new Promise((resolve6) => {
44601
44713
  const child = spawn2("npm", ["install", "-g", `${PACKAGE_NAME}@${channel}`], {
44602
44714
  stdio: "inherit",
44603
44715
  shell: true
44604
44716
  });
44605
- child.on("close", (code) => resolve5(code ?? 1));
44606
- child.on("error", () => resolve5(1));
44717
+ child.on("close", (code) => resolve6(code ?? 1));
44718
+ child.on("error", () => resolve6(1));
44607
44719
  });
44608
44720
  }
44609
44721
 
@@ -44966,7 +45078,7 @@ async function startMultiDaemon(opts = {}) {
44966
45078
  const packageAutoAll = async () => {
44967
45079
  const out2 = /* @__PURE__ */ new Map();
44968
45080
  for (const r of records) {
44969
- await new Promise((resolve5) => setImmediate(resolve5));
45081
+ await new Promise((resolve6) => setImmediate(resolve6));
44970
45082
  const done = markPass(`package-index:${r.entry.name}`);
44971
45083
  try {
44972
45084
  out2.set(
@@ -45036,7 +45148,10 @@ async function startMultiDaemon(opts = {}) {
45036
45148
  ts,
45037
45149
  workspaces: fileBacked.map((r) => ({
45038
45150
  recordId: r.id,
45039
- 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,
45040
45155
  castaliaPath: r.engine.paths.castalia
45041
45156
  }))
45042
45157
  });
@@ -45050,7 +45165,13 @@ async function startMultiDaemon(opts = {}) {
45050
45165
  for (const r of inlineRecords) {
45051
45166
  const done = markPass(`percolate-inline:${r.entry.name}`);
45052
45167
  try {
45053
- 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
+ );
45054
45175
  } catch (err2) {
45055
45176
  console.warn(
45056
45177
  `[errata] percolate failed for ${r.entry.name}: ${err2 instanceof Error ? err2.message : err2}`
@@ -45254,7 +45375,7 @@ async function startMultiDaemon(opts = {}) {
45254
45375
  },
45255
45376
  async stop() {
45256
45377
  try {
45257
- const cur = readFileSync18(lockPath, "utf8");
45378
+ const cur = readFileSync19(lockPath, "utf8");
45258
45379
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
45259
45380
  } catch {
45260
45381
  }
@@ -45452,7 +45573,7 @@ async function loginOAuthLoopback(opts) {
45452
45573
  const state = randomState();
45453
45574
  const scope = opts.scope ?? DEFAULT_OAUTH_SCOPE;
45454
45575
  const { code, redirectUri, clientId } = await new Promise(
45455
- (resolve5, reject) => {
45576
+ (resolve6, reject) => {
45456
45577
  const server = createServer((req, res) => {
45457
45578
  const u = new URL(req.url ?? "/", "http://127.0.0.1");
45458
45579
  if (u.pathname !== "/callback") {
@@ -45475,7 +45596,7 @@ async function loginOAuthLoopback(opts) {
45475
45596
  res.writeHead(200, { "content-type": "text/html" });
45476
45597
  res.end("<html><body>inErrata: you're logged in. You can close this tab.</body></html>");
45477
45598
  server.close();
45478
- 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 });
45479
45600
  });
45480
45601
  let activeClientId = oauthClientId();
45481
45602
  server.on("error", reject);
@@ -45815,27 +45936,28 @@ async function cmdInit() {
45815
45936
  console.log(`initialized errata workspace:`);
45816
45937
  console.log(` id: ${profile.id}`);
45817
45938
  console.log(` name: ${profile.name}`);
45939
+ console.log(` repo: ${profile.repoLocator ?? "(no git remote detected)"}`);
45818
45940
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
45819
45941
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
45820
45942
  }
45821
45943
  if (!skipHooks) {
45822
45944
  console.log("");
45823
45945
  console.log("installing harness hooks...");
45824
- const { existsSync: existsSync21 } = await import("node:fs");
45825
- const { join: join24 } = await import("node:path");
45946
+ const { existsSync: existsSync22 } = await import("node:fs");
45947
+ const { join: join25 } = await import("node:path");
45826
45948
  try {
45827
45949
  await installClaudeHooks(port);
45828
45950
  } catch (err2) {
45829
45951
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
45830
45952
  }
45831
- if (existsSync21(join24(ROOT, ".cursor"))) {
45953
+ if (existsSync22(join25(ROOT, ".cursor"))) {
45832
45954
  try {
45833
45955
  await installCursorMcpConfig();
45834
45956
  } catch (err2) {
45835
45957
  console.warn(` \u26A0\uFE0F Cursor MCP config failed: ${err2 instanceof Error ? err2.message : err2}`);
45836
45958
  }
45837
45959
  }
45838
- if (existsSync21(join24(ROOT, ".codex"))) {
45960
+ if (existsSync22(join25(ROOT, ".codex"))) {
45839
45961
  try {
45840
45962
  await installCodexHooks(port);
45841
45963
  } catch (err2) {
@@ -45949,11 +46071,12 @@ async function cmdStatus() {
45949
46071
  console.log(` version: ${DAEMON_VERSION} (update channel: ${cfg.updateChannel})`);
45950
46072
  console.log(` workspace: ${profile ? `${profile.name} (${profile.id})` : "(not initialized)"}`);
45951
46073
  if (profile) {
46074
+ console.log(` repo: ${profile.repoLocator ?? "(no git remote \u2014 unlinked)"}`);
45952
46075
  console.log(` stack: ${profile.stack.join(", ") || "(none)"}`);
45953
46076
  console.log(` languages: ${profile.languages.join(", ") || "(none)"}`);
45954
46077
  }
45955
- console.log(` graph db: ${existsSync20(paths.castalia) ? "yes" : "no"} (${paths.castalia})`);
45956
- 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})`);
45957
46080
  const lockPath = globalDaemonLock();
45958
46081
  const running = isDaemonAlive(lockPath) ? readDaemonLock(lockPath) : null;
45959
46082
  console.log(
@@ -46271,11 +46394,11 @@ async function cmdUse(args2) {
46271
46394
  }
46272
46395
  async function cmdReview() {
46273
46396
  const paths = workspacePaths(ROOT);
46274
- if (!existsSync20(paths.reviewQueue)) {
46397
+ if (!existsSync21(paths.reviewQueue)) {
46275
46398
  console.log("(review queue empty)");
46276
46399
  return;
46277
46400
  }
46278
- const queue = JSON.parse(readFileSync19(paths.reviewQueue, "utf8"));
46401
+ const queue = JSON.parse(readFileSync20(paths.reviewQueue, "utf8"));
46279
46402
  if (queue.length === 0) {
46280
46403
  console.log("(review queue empty)");
46281
46404
  return;
@@ -46905,7 +47028,7 @@ async function gatherRepo(store, ws) {
46905
47028
  };
46906
47029
  }
46907
47030
  async function gatherReportData(generatedAt) {
46908
- const { existsSync: existsSync21 } = await import("node:fs");
47031
+ const { existsSync: existsSync22 } = await import("node:fs");
46909
47032
  const { openGraphStore: openGraphStore2 } = await Promise.resolve().then(() => (init_src4(), src_exports2));
46910
47033
  const cfg = loadConfig();
46911
47034
  const outbound = cfg.consent.sync ? "auto" : "off";
@@ -46913,7 +47036,7 @@ async function gatherReportData(generatedAt) {
46913
47036
  for (const ws of listWorkspaces()) {
46914
47037
  if (ws.missing) continue;
46915
47038
  const dbPath = workspacePaths(ws.path).castalia;
46916
- if (!existsSync21(dbPath)) continue;
47039
+ if (!existsSync22(dbPath)) continue;
46917
47040
  let store = null;
46918
47041
  try {
46919
47042
  store = openGraphStore2({ path: dbPath });
@@ -46957,8 +47080,8 @@ async function cmdReport(args2) {
46957
47080
  const outDir = workspacePaths(ROOT).configDir;
46958
47081
  mkdirSync6(outDir, { recursive: true });
46959
47082
  const files = renderReport2(data, { includeFutureVerbs });
46960
- for (const f of files) writeFileSync16(join23(outDir, f.name), f.html, "utf8");
46961
- 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");
46962
47085
  console.log(`report \u2192 ${indexPath}`);
46963
47086
  console.log(` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`);
46964
47087
  console.log(` open: file://${indexPath.replace(/\\/g, "/")}`);
@@ -47010,7 +47133,7 @@ function spawnDaemonDetached() {
47010
47133
  try {
47011
47134
  const logPath = daemonLogPath();
47012
47135
  try {
47013
- if (statSync5(logPath).size > 5 * 1024 * 1024) renameSync3(logPath, `${logPath}.1`);
47136
+ if (statSync6(logPath).size > 5 * 1024 * 1024) renameSync3(logPath, `${logPath}.1`);
47014
47137
  } catch {
47015
47138
  }
47016
47139
  out2 = openSync2(logPath, "a");
@@ -47078,15 +47201,15 @@ function hookRelayCommand(port, path2) {
47078
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 '{}'`;
47079
47202
  }
47080
47203
  async function installClaudeHooks(port) {
47081
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47082
- const { join: join24 } = await import("node:path");
47083
- const dir = join24(ROOT, ".claude");
47084
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47085
- 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");
47086
47209
  let settings = {};
47087
- if (existsSync21(file2)) {
47210
+ if (existsSync22(file2)) {
47088
47211
  try {
47089
- settings = JSON.parse(readFileSync20(file2, "utf8"));
47212
+ settings = JSON.parse(readFileSync21(file2, "utf8"));
47090
47213
  } catch {
47091
47214
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47092
47215
  process.exit(2);
@@ -47135,7 +47258,7 @@ async function installClaudeHooks(port) {
47135
47258
  writeFileSync16(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
47136
47259
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
47137
47260
  await installClaudeMcpConfig();
47138
- const claudeMd = join24(ROOT, "CLAUDE.md");
47261
+ const claudeMd = join25(ROOT, "CLAUDE.md");
47139
47262
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
47140
47263
  if (recall.kind === "collision") {
47141
47264
  console.warn(
@@ -47147,15 +47270,15 @@ async function installClaudeHooks(port) {
47147
47270
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
47148
47271
  }
47149
47272
  async function installClaudeMcpConfig() {
47150
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47151
- const { join: join24, dirname: dirname8 } = await import("node:path");
47152
- 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");
47153
47276
  const dir = dirname8(file2);
47154
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47277
+ if (!existsSync22(dir)) mkdirSync6(dir, { recursive: true });
47155
47278
  let cfg = {};
47156
- if (existsSync21(file2)) {
47279
+ if (existsSync22(file2)) {
47157
47280
  try {
47158
- cfg = JSON.parse(readFileSync20(file2, "utf8"));
47281
+ cfg = JSON.parse(readFileSync21(file2, "utf8"));
47159
47282
  } catch {
47160
47283
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47161
47284
  process.exit(2);
@@ -47169,15 +47292,15 @@ async function installClaudeMcpConfig() {
47169
47292
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
47170
47293
  }
47171
47294
  async function installCursorMcpConfig() {
47172
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47173
- const { join: join24 } = await import("node:path");
47174
- const dir = join24(ROOT, ".cursor");
47175
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47176
- 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");
47177
47300
  let cfg = {};
47178
- if (existsSync21(file2)) {
47301
+ if (existsSync22(file2)) {
47179
47302
  try {
47180
- cfg = JSON.parse(readFileSync20(file2, "utf8"));
47303
+ cfg = JSON.parse(readFileSync21(file2, "utf8"));
47181
47304
  } catch {
47182
47305
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
47183
47306
  process.exit(2);
@@ -47193,16 +47316,16 @@ async function installCursorMcpConfig() {
47193
47316
  console.log(` \u26A0\uFE0F reload Cursor (Cmd/Ctrl-Shift-P \u2192 "Reload Window") to pick it up.`);
47194
47317
  }
47195
47318
  async function installCodexHooks(port) {
47196
- const { mkdirSync: mkdirSync6, existsSync: existsSync21, readFileSync: readFileSync20, writeFileSync: writeFileSync16 } = await import("node:fs");
47197
- const { join: join24 } = await import("node:path");
47198
- const dir = join24(ROOT, ".codex");
47199
- if (!existsSync21(dir)) mkdirSync6(dir, { recursive: true });
47200
- 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");
47201
47324
  const BEGIN = `# >>> errata hooks (errata-managed)`;
47202
47325
  const END = `# <<< errata hooks`;
47203
47326
  let existing = "";
47204
- if (existsSync21(file2)) {
47205
- existing = readFileSync20(file2, "utf8");
47327
+ if (existsSync22(file2)) {
47328
+ existing = readFileSync21(file2, "utf8");
47206
47329
  const beginIdx = existing.indexOf(BEGIN);
47207
47330
  const endIdx = existing.indexOf(END);
47208
47331
  if (beginIdx >= 0 && endIdx > beginIdx) {
@@ -47419,7 +47542,7 @@ async function cmdDash(args2) {
47419
47542
  const hotspotScanMark = /* @__PURE__ */ new Map();
47420
47543
  const HOTSPOT_FANIN = 20;
47421
47544
  const runNightlyPass = async () => {
47422
- const yieldToLoop2 = () => new Promise((resolve5) => setImmediate(resolve5));
47545
+ const yieldToLoop2 = () => new Promise((resolve6) => setImmediate(resolve6));
47423
47546
  const fullReclusterPass = nightlyCount++ % FULL_RECLUSTER_EVERY === 0;
47424
47547
  const m = await handle2.nightlyAll();
47425
47548
  let skillsLearned = 0;
@@ -47494,7 +47617,7 @@ async function cmdDash(args2) {
47494
47617
  await yieldToLoop2();
47495
47618
  try {
47496
47619
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
47497
- const res = bleedRules(join23(r.root, ".claude", "rules"), items);
47620
+ const res = bleedRules(join24(r.root, ".claude", "rules"), items);
47498
47621
  if (res.written || res.pruned) {
47499
47622
  console.log(
47500
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.42",
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();