@inerrata-corporation/errata 2.0.6-dev.2564 → 2.0.6-dev.2571

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/errata.mjs +611 -533
  2. package/package.json +1 -1
package/errata.mjs CHANGED
@@ -20549,6 +20549,7 @@ function upgradeAnchorHints(store, workspaceId2, ts) {
20549
20549
  let upgraded = 0;
20550
20550
  let standing = 0;
20551
20551
  let unresolvable = 0;
20552
+ let blocked = 0;
20552
20553
  const filesByPath = /* @__PURE__ */ new Map();
20553
20554
  for (const f of store.findNodesByLabel("File")) {
20554
20555
  if (f.attrs["workspaceId"] && f.attrs["workspaceId"] !== workspaceId2) continue;
@@ -20571,9 +20572,11 @@ function upgradeAnchorHints(store, workspaceId2, ts) {
20571
20572
  consumeAnchorHint(store, p, ts);
20572
20573
  upgraded++;
20573
20574
  standing--;
20575
+ } else {
20576
+ blocked++;
20574
20577
  }
20575
20578
  }
20576
- return { upgraded, standing, unresolvable };
20579
+ return { upgraded, standing, unresolvable, blocked };
20577
20580
  }
20578
20581
  function resolveDesignProblemByStatement(store, statement, fixNote, t) {
20579
20582
  const problemId = identityId({ kind: "DesignProblem", statement });
@@ -23699,10 +23702,14 @@ var init_mechanism_liveness = __esm({
23699
23702
  // "the field exists at all", the revisit-sweep precedent.
23700
23703
  fed: { labels: ["Problem"], attr: "anchorHint", minFraction: 0 },
23701
23704
  effectCounter: "anchorHintsUpgraded",
23702
- // The standing hints ARE the queue — without the gauge, "found nothing"
23703
- // and "runs forever against work it can never clear" read identically.
23704
- backlogCounter: "anchorHintsStanding",
23705
- note: "drains as hinted files change; contentChangedAt is forward-only so the backlog moves with real edits"
23705
+ // The gauge is the work the mechanism CAN act on and didn't: hints whose file
23706
+ // changed after the hint yet never upgraded. `anchorHintsStanding` also
23707
+ // counts hints still waiting for their file to be edited — a queue that
23708
+ // drains on the user's schedule, which read STUCK over any quiet stretch
23709
+ // (2026-09-23: 71 standing, none edited, toasted daily). Standing stays in
23710
+ // the ledger as information; it just cannot declare a stall.
23711
+ backlogCounter: "anchorHintsBlocked",
23712
+ note: "a hint upgrades when its file is next edited; stuck means an edited file's hint failed to anchor"
23706
23713
  },
23707
23714
  {
23708
23715
  id: "fold-candidate-resolve",
@@ -28996,6 +29003,186 @@ var init_review2 = __esm({
28996
29003
  }
28997
29004
  });
28998
29005
 
29006
+ // src/consent.ts
29007
+ function effectiveConsent(config2, profile) {
29008
+ const c = profile?.consoleConsents;
29009
+ if (c) return { sync: c.sync, telemetry: c.telemetry, contributePackages: c.contributePackages };
29010
+ return {
29011
+ sync: config2.consent.sync,
29012
+ telemetry: config2.consent.telemetry,
29013
+ contributePackages: config2.consent.contributePackages
29014
+ };
29015
+ }
29016
+ var init_consent = __esm({
29017
+ "src/consent.ts"() {
29018
+ "use strict";
29019
+ }
29020
+ });
29021
+
29022
+ // src/git-remote.ts
29023
+ import { existsSync as existsSync8, readFileSync as readFileSync6, statSync } from "node:fs";
29024
+ import { isAbsolute, join as join6, resolve } from "node:path";
29025
+ function resolveGitDir(root) {
29026
+ const dotGit = join6(root, ".git");
29027
+ try {
29028
+ const st = statSync(dotGit);
29029
+ if (st.isDirectory()) return dotGit;
29030
+ const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync6(dotGit, "utf8"));
29031
+ if (!m) return null;
29032
+ const dir = m[1];
29033
+ return isAbsolute(dir) ? dir : resolve(root, dir);
29034
+ } catch {
29035
+ return null;
29036
+ }
29037
+ }
29038
+ function gitConfigPath(gitDir) {
29039
+ const commondirFile = join6(gitDir, "commondir");
29040
+ if (existsSync8(commondirFile)) {
29041
+ const common = readFileSync6(commondirFile, "utf8").trim();
29042
+ const commonDir = isAbsolute(common) ? common : resolve(gitDir, common);
29043
+ return join6(commonDir, "config");
29044
+ }
29045
+ return join6(gitDir, "config");
29046
+ }
29047
+ function readRemotes(root) {
29048
+ const gitDir = resolveGitDir(root);
29049
+ if (!gitDir) return [];
29050
+ const cfgPath = gitConfigPath(gitDir);
29051
+ if (!existsSync8(cfgPath)) return [];
29052
+ let txt;
29053
+ try {
29054
+ txt = readFileSync6(cfgPath, "utf8");
29055
+ } catch {
29056
+ return [];
29057
+ }
29058
+ const out2 = [];
29059
+ const sectionRe = /^\s*\[remote "([^"]+)"\]\s*$([\s\S]*?)(?=^\s*\[|\s*$(?![\s\S]))/gm;
29060
+ for (const m of txt.matchAll(sectionRe)) {
29061
+ const url2 = /^\s*url\s*=\s*(.+?)\s*$/m.exec(m[2])?.[1];
29062
+ if (url2) out2.push({ name: m[1], url: url2 });
29063
+ }
29064
+ return out2;
29065
+ }
29066
+ function detectRepoLocator(root, remote) {
29067
+ const remotes = readRemotes(root);
29068
+ if (remotes.length === 0) return null;
29069
+ const pick2 = remote ? remotes.find((r) => r.name === remote) ?? null : remotes.find((r) => r.name === "origin") ?? (remotes.length === 1 ? remotes[0] : null);
29070
+ return pick2 ? normalizeRepoLocator(pick2.url) : null;
29071
+ }
29072
+ var init_git_remote = __esm({
29073
+ "src/git-remote.ts"() {
29074
+ "use strict";
29075
+ init_src();
29076
+ }
29077
+ });
29078
+
29079
+ // src/profile.ts
29080
+ import { existsSync as existsSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "node:fs";
29081
+ import { createHash as createHash3 } from "node:crypto";
29082
+ import { join as join7 } from "node:path";
29083
+ function workspaceId(root) {
29084
+ return "wp_" + createHash3("sha256").update(root).digest("hex").slice(0, 12);
29085
+ }
29086
+ function sessionOriginKey(sessionId) {
29087
+ if (!sessionId) return void 0;
29088
+ return "ws_" + createHash3("sha256").update(sessionId).digest("hex").slice(0, 12);
29089
+ }
29090
+ function refreshRepoLocator(root, profile) {
29091
+ const detected = detectRepoLocator(root, profile.repoRemote);
29092
+ if (!detected || detected === profile.repoLocator) return false;
29093
+ if (profile.repoLocator) {
29094
+ const aliases = new Set(profile.repoLocatorAliases ?? []);
29095
+ aliases.add(profile.repoLocator);
29096
+ aliases.delete(detected);
29097
+ profile.repoLocatorAliases = [...aliases];
29098
+ }
29099
+ profile.repoLocator = detected;
29100
+ saveProfile(root, profile);
29101
+ return true;
29102
+ }
29103
+ function loadProfile(root) {
29104
+ const p = workspacePaths(root);
29105
+ if (!existsSync9(p.workspaceJson)) return null;
29106
+ return JSON.parse(readFileSync7(p.workspaceJson, "utf8"));
29107
+ }
29108
+ function saveProfile(root, profile) {
29109
+ const p = workspacePaths(root);
29110
+ ensureDir(p.configDir);
29111
+ writeFileSync7(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
29112
+ }
29113
+ function autodetectProfile(root) {
29114
+ const id = workspaceId(root);
29115
+ const name2 = root.split(/[\\/]/).filter(Boolean).pop() ?? "workspace";
29116
+ const p = emptyProfile(id, name2);
29117
+ const locator = detectRepoLocator(root);
29118
+ if (locator) p.repoLocator = locator;
29119
+ const pkgPath = join7(root, "package.json");
29120
+ if (existsSync9(pkgPath)) {
29121
+ try {
29122
+ const pkg = JSON.parse(readFileSync7(pkgPath, "utf8"));
29123
+ const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
29124
+ p.languages.push("javascript");
29125
+ if (existsSync9(join7(root, "tsconfig.json")) || deps["typescript"]) {
29126
+ p.languages.push("typescript");
29127
+ }
29128
+ const nodeVer = pkg.engines?.node?.trim();
29129
+ p.stack.push(nodeVer ? `node@${nodeVer}` : "node");
29130
+ const interesting = [
29131
+ "next",
29132
+ "react",
29133
+ "vue",
29134
+ "svelte",
29135
+ "express",
29136
+ "hono",
29137
+ "fastify",
29138
+ "@modelcontextprotocol/sdk"
29139
+ ];
29140
+ for (const k of interesting) {
29141
+ if (deps[k]) p.stack.push(k);
29142
+ }
29143
+ } catch {
29144
+ }
29145
+ }
29146
+ const pyproject = join7(root, "pyproject.toml");
29147
+ if (existsSync9(pyproject)) {
29148
+ try {
29149
+ const txt = readFileSync7(pyproject, "utf8");
29150
+ const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
29151
+ p.languages.push("python");
29152
+ p.stack.push(`python@${py ?? "3"}`);
29153
+ const candidates = ["fastapi", "django", "flask", "mcp", "pytest"];
29154
+ for (const k of candidates) {
29155
+ if (new RegExp(`\\b${k}\\b`, "i").test(txt)) p.stack.push(k);
29156
+ }
29157
+ } catch {
29158
+ }
29159
+ }
29160
+ const reqs = join7(root, "requirements.txt");
29161
+ if (existsSync9(reqs)) {
29162
+ if (!p.languages.includes("python")) p.languages.push("python");
29163
+ if (!p.stack.includes("python@3")) p.stack.push("python@3");
29164
+ }
29165
+ if (existsSync9(join7(root, "go.mod"))) {
29166
+ p.languages.push("go");
29167
+ p.stack.push("go");
29168
+ }
29169
+ if (existsSync9(join7(root, "Cargo.toml"))) {
29170
+ p.languages.push("rust");
29171
+ p.stack.push("rust");
29172
+ }
29173
+ p.languages = [...new Set(p.languages)];
29174
+ p.stack = [...new Set(p.stack)];
29175
+ return p;
29176
+ }
29177
+ var init_profile2 = __esm({
29178
+ "src/profile.ts"() {
29179
+ "use strict";
29180
+ init_src2();
29181
+ init_paths();
29182
+ init_git_remote();
29183
+ }
29184
+ });
29185
+
28999
29186
  // src/identity.ts
29000
29187
  function resolveWorkspaceIdentity(cfg, entry, env2 = process.env) {
29001
29188
  if (env2["ERRATA_CONFIG_PATH"]) {
@@ -29071,70 +29258,13 @@ var init_identity2 = __esm({
29071
29258
  }
29072
29259
  });
29073
29260
 
29074
- // src/git-remote.ts
29075
- import { existsSync as existsSync8, readFileSync as readFileSync6, statSync } from "node:fs";
29076
- import { isAbsolute, join as join6, resolve } from "node:path";
29077
- function resolveGitDir(root) {
29078
- const dotGit = join6(root, ".git");
29079
- try {
29080
- const st = statSync(dotGit);
29081
- if (st.isDirectory()) return dotGit;
29082
- const m = /^gitdir:\s*(.+?)\s*$/m.exec(readFileSync6(dotGit, "utf8"));
29083
- if (!m) return null;
29084
- const dir = m[1];
29085
- return isAbsolute(dir) ? dir : resolve(root, dir);
29086
- } catch {
29087
- return null;
29088
- }
29089
- }
29090
- function gitConfigPath(gitDir) {
29091
- const commondirFile = join6(gitDir, "commondir");
29092
- if (existsSync8(commondirFile)) {
29093
- const common = readFileSync6(commondirFile, "utf8").trim();
29094
- const commonDir = isAbsolute(common) ? common : resolve(gitDir, common);
29095
- return join6(commonDir, "config");
29096
- }
29097
- return join6(gitDir, "config");
29098
- }
29099
- function readRemotes(root) {
29100
- const gitDir = resolveGitDir(root);
29101
- if (!gitDir) return [];
29102
- const cfgPath = gitConfigPath(gitDir);
29103
- if (!existsSync8(cfgPath)) return [];
29104
- let txt;
29105
- try {
29106
- txt = readFileSync6(cfgPath, "utf8");
29107
- } catch {
29108
- return [];
29109
- }
29110
- const out2 = [];
29111
- const sectionRe = /^\s*\[remote "([^"]+)"\]\s*$([\s\S]*?)(?=^\s*\[|\s*$(?![\s\S]))/gm;
29112
- for (const m of txt.matchAll(sectionRe)) {
29113
- const url2 = /^\s*url\s*=\s*(.+?)\s*$/m.exec(m[2])?.[1];
29114
- if (url2) out2.push({ name: m[1], url: url2 });
29115
- }
29116
- return out2;
29117
- }
29118
- function detectRepoLocator(root, remote) {
29119
- const remotes = readRemotes(root);
29120
- if (remotes.length === 0) return null;
29121
- const pick2 = remote ? remotes.find((r) => r.name === remote) ?? null : remotes.find((r) => r.name === "origin") ?? (remotes.length === 1 ? remotes[0] : null);
29122
- return pick2 ? normalizeRepoLocator(pick2.url) : null;
29123
- }
29124
- var init_git_remote = __esm({
29125
- "src/git-remote.ts"() {
29126
- "use strict";
29127
- init_src();
29128
- }
29129
- });
29130
-
29131
29261
  // src/checkout-root.ts
29132
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
29133
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute2, join as join7, resolve as resolve2 } from "node:path";
29262
+ import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
29263
+ import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute2, join as join8, resolve as resolve2 } from "node:path";
29134
29264
  function nearestGitRoot(dir) {
29135
29265
  let cur = resolve2(dir);
29136
29266
  for (; ; ) {
29137
- if (existsSync9(join7(cur, ".git"))) return cur;
29267
+ if (existsSync10(join8(cur, ".git"))) return cur;
29138
29268
  const parent = dirname6(cur);
29139
29269
  if (parent === cur) return null;
29140
29270
  cur = parent;
@@ -29142,19 +29272,19 @@ function nearestGitRoot(dir) {
29142
29272
  }
29143
29273
  function mainCheckoutOfWorktree(root) {
29144
29274
  const gitDir = resolveGitDir(root);
29145
- if (!gitDir || gitDir === join7(root, ".git")) return null;
29146
- const commondirFile = join7(gitDir, "commondir");
29147
- if (!existsSync9(commondirFile)) return null;
29275
+ if (!gitDir || gitDir === join8(root, ".git")) return null;
29276
+ const commondirFile = join8(gitDir, "commondir");
29277
+ if (!existsSync10(commondirFile)) return null;
29148
29278
  let common;
29149
29279
  try {
29150
- common = readFileSync7(commondirFile, "utf8").trim();
29280
+ common = readFileSync8(commondirFile, "utf8").trim();
29151
29281
  } catch {
29152
29282
  return null;
29153
29283
  }
29154
29284
  const commonDir = resolve2(isAbsolute2(common) ? common : resolve2(gitDir, common));
29155
29285
  if (basename2(commonDir) !== ".git") return null;
29156
29286
  const main2 = dirname6(commonDir);
29157
- return existsSync9(join7(main2, ".git")) ? main2 : null;
29287
+ return existsSync10(join8(main2, ".git")) ? main2 : null;
29158
29288
  }
29159
29289
  function checkoutRootOf(cwd) {
29160
29290
  const root = nearestGitRoot(cwd);
@@ -29172,16 +29302,16 @@ var init_checkout_root = __esm({
29172
29302
  });
29173
29303
 
29174
29304
  // src/registry.ts
29175
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "node:fs";
29176
- import { join as join8 } from "node:path";
29305
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "node:fs";
29306
+ import { join as join9 } from "node:path";
29177
29307
  function registryPath() {
29178
- return process.env["ERRATA_REGISTRY_PATH"] ?? join8(globalDir(), "workspaces.json");
29308
+ return process.env["ERRATA_REGISTRY_PATH"] ?? join9(globalDir(), "workspaces.json");
29179
29309
  }
29180
29310
  function read() {
29181
29311
  const p = registryPath();
29182
- if (!existsSync10(p)) return { version: 1, workspaces: {} };
29312
+ if (!existsSync11(p)) return { version: 1, workspaces: {} };
29183
29313
  try {
29184
- const parsed = JSON.parse(readFileSync8(p, "utf8"));
29314
+ const parsed = JSON.parse(readFileSync9(p, "utf8"));
29185
29315
  return { version: 1, workspaces: parsed.workspaces ?? {} };
29186
29316
  } catch {
29187
29317
  return { version: 1, workspaces: {} };
@@ -29189,9 +29319,9 @@ function read() {
29189
29319
  }
29190
29320
  function registryCorrupt() {
29191
29321
  const p = registryPath();
29192
- if (!existsSync10(p)) return false;
29322
+ if (!existsSync11(p)) return false;
29193
29323
  try {
29194
- JSON.parse(readFileSync8(p, "utf8"));
29324
+ JSON.parse(readFileSync9(p, "utf8"));
29195
29325
  return false;
29196
29326
  } catch {
29197
29327
  return true;
@@ -29199,7 +29329,7 @@ function registryCorrupt() {
29199
29329
  }
29200
29330
  function write(reg) {
29201
29331
  ensureDir(globalDir());
29202
- writeFileSync7(registryPath(), JSON.stringify(reg, null, 2), "utf8");
29332
+ writeFileSync8(registryPath(), JSON.stringify(reg, null, 2), "utf8");
29203
29333
  }
29204
29334
  function registerWorkspace(profile, root, now = Date.now()) {
29205
29335
  if (isLinkedWorktree(root)) return;
@@ -29244,7 +29374,7 @@ function pruneMissingWorkspaces() {
29244
29374
  const reg = read();
29245
29375
  const removed = [];
29246
29376
  for (const [id, entry] of Object.entries(reg.workspaces)) {
29247
- if (!existsSync10(entry.path)) {
29377
+ if (!existsSync11(entry.path)) {
29248
29378
  removed.push(entry);
29249
29379
  delete reg.workspaces[id];
29250
29380
  }
@@ -29253,13 +29383,13 @@ function pruneMissingWorkspaces() {
29253
29383
  return removed;
29254
29384
  }
29255
29385
  function workspaceStatus(entry) {
29256
- const missing = !existsSync10(entry.path);
29386
+ const missing = !existsSync11(entry.path);
29257
29387
  const lockPath = workspacePaths(entry.path).daemonLock;
29258
29388
  let running = false;
29259
29389
  let webUiUrl = null;
29260
- if (existsSync10(lockPath)) {
29390
+ if (existsSync11(lockPath)) {
29261
29391
  try {
29262
- const lock = JSON.parse(readFileSync8(lockPath, "utf8"));
29392
+ const lock = JSON.parse(readFileSync9(lockPath, "utf8"));
29263
29393
  if (lock.pid && lock.webUiUrl && pidAlive(lock.pid)) {
29264
29394
  running = true;
29265
29395
  webUiUrl = lock.webUiUrl;
@@ -30713,7 +30843,7 @@ var init_diagnostic_matcher = __esm({
30713
30843
  });
30714
30844
 
30715
30845
  // ../../packages/generalizer/src/generalizer.ts
30716
- import { isAbsolute as isAbsolute3, join as join9, relative } from "node:path";
30846
+ import { isAbsolute as isAbsolute3, join as join10, relative } from "node:path";
30717
30847
  async function runGeneralizer(opts) {
30718
30848
  const report = {
30719
30849
  eventsProcessed: 0,
@@ -30821,7 +30951,7 @@ function extractDiagnostics(ev) {
30821
30951
  function diagRelPath(file2, cwd, workspaceRoot) {
30822
30952
  const norm = (p) => p.replace(/\\/g, "/");
30823
30953
  if (!workspaceRoot) return norm(file2);
30824
- const abs = isAbsolute3(file2) ? file2 : join9(cwd ?? workspaceRoot, file2);
30954
+ const abs = isAbsolute3(file2) ? file2 : join10(cwd ?? workspaceRoot, file2);
30825
30955
  return norm(relative(workspaceRoot, abs));
30826
30956
  }
30827
30957
  function extractErrorSignature(ev) {
@@ -32463,23 +32593,23 @@ var init_src10 = __esm({
32463
32593
  });
32464
32594
 
32465
32595
  // ../../packages/indexer/src/parse-cache.ts
32466
- import { createHash as createHash3 } from "node:crypto";
32467
- import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync8 } from "node:fs";
32596
+ import { createHash as createHash4 } from "node:crypto";
32597
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync10, readdirSync as readdirSync2, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync9 } from "node:fs";
32468
32598
  import { homedir as homedir3 } from "node:os";
32469
- import { join as join10 } from "node:path";
32599
+ import { join as join11 } from "node:path";
32470
32600
  function parseCacheDir() {
32471
- return process.env["ERRATA_PARSE_CACHE"] ?? join10(homedir3(), ".errata", "parse-cache");
32601
+ return process.env["ERRATA_PARSE_CACHE"] ?? join11(homedir3(), ".errata", "parse-cache");
32472
32602
  }
32473
32603
  function parseCacheKey(source, providerId) {
32474
- return createHash3("sha256").update(`${PARSE_CACHE_VERSION}:${providerId}:${source}`).digest("hex");
32604
+ return createHash4("sha256").update(`${PARSE_CACHE_VERSION}:${providerId}:${source}`).digest("hex");
32475
32605
  }
32476
32606
  function entryPath(dir, key) {
32477
- return join10(dir, key.slice(0, 2), `${key.slice(2)}.json`);
32607
+ return join11(dir, key.slice(0, 2), `${key.slice(2)}.json`);
32478
32608
  }
32479
32609
  function readParseCache(dir, key) {
32480
32610
  const file2 = entryPath(dir, key);
32481
32611
  try {
32482
- const raw2 = readFileSync9(file2, "utf8");
32612
+ const raw2 = readFileSync10(file2, "utf8");
32483
32613
  const parsed = JSON.parse(raw2);
32484
32614
  if (parsed.v !== PARSE_CACHE_VERSION || !Array.isArray(parsed.symbols)) return null;
32485
32615
  return { symbols: parsed.symbols, reExports: parsed.reExports ?? [] };
@@ -32498,8 +32628,8 @@ function writeParseCache(dir, key, providerId, value) {
32498
32628
  const body2 = JSON.stringify(envelope);
32499
32629
  if (body2.length > MAX_ENTRY_BYTES) return;
32500
32630
  const file2 = entryPath(dir, key);
32501
- mkdirSync6(join10(dir, key.slice(0, 2)), { recursive: true });
32502
- writeFileSync8(file2, body2);
32631
+ mkdirSync6(join11(dir, key.slice(0, 2)), { recursive: true });
32632
+ writeFileSync9(file2, body2);
32503
32633
  } catch {
32504
32634
  }
32505
32635
  }
@@ -32508,9 +32638,9 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
32508
32638
  sweptThisProcess = true;
32509
32639
  let removed = 0;
32510
32640
  try {
32511
- if (!existsSync11(dir)) return 0;
32641
+ if (!existsSync12(dir)) return 0;
32512
32642
  for (const bucket of readdirSync2(dir)) {
32513
- const bucketDir = join10(dir, bucket);
32643
+ const bucketDir = join11(dir, bucket);
32514
32644
  let names;
32515
32645
  try {
32516
32646
  names = readdirSync2(bucketDir);
@@ -32518,7 +32648,7 @@ function sweepParseCacheOnce(dir, now = Date.now()) {
32518
32648
  continue;
32519
32649
  }
32520
32650
  for (const name2 of names) {
32521
- const file2 = join10(bucketDir, name2);
32651
+ const file2 = join11(bucketDir, name2);
32522
32652
  try {
32523
32653
  if (now - statSync2(file2).mtimeMs > ENTRY_TTL_MS) {
32524
32654
  rmSync2(file2, { force: true });
@@ -32766,10 +32896,10 @@ var init_identity3 = __esm({
32766
32896
  });
32767
32897
 
32768
32898
  // ../../packages/indexer/src/pipeline.ts
32769
- import { appendFileSync, readFileSync as readFileSync10, statSync as statSync3 } from "node:fs";
32899
+ import { appendFileSync, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
32770
32900
  import { readdir } from "node:fs/promises";
32771
- import { extname, join as join11, relative as relative2, sep } from "node:path";
32772
- import { createHash as createHash4 } from "node:crypto";
32901
+ import { extname, join as join12, relative as relative2, sep } from "node:path";
32902
+ import { createHash as createHash5 } from "node:crypto";
32773
32903
  import { execFileSync } from "node:child_process";
32774
32904
  function nowTs() {
32775
32905
  return indexNow ?? Date.now();
@@ -32778,7 +32908,7 @@ function fingerprintOf(signature, bodyHash) {
32778
32908
  return `${signature ?? ""}|${bodyHash ?? ""}`;
32779
32909
  }
32780
32910
  function sha(s) {
32781
- return createHash4("sha256").update(s).digest("hex").slice(0, 16);
32911
+ return createHash5("sha256").update(s).digest("hex").slice(0, 16);
32782
32912
  }
32783
32913
  function fileNodeId(workspaceId2, relPath) {
32784
32914
  return `file_${sha(workspaceId2 + ":" + relPath.replace(/\\/g, "/"))}`;
@@ -32906,7 +33036,7 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
32906
33036
  for (const rel of [...changedRelPaths]) {
32907
33037
  let h;
32908
33038
  try {
32909
- h = createHash4("sha256").update(readFileSync10(join11(rootPath, rel))).digest("hex");
33039
+ h = createHash5("sha256").update(readFileSync11(join12(rootPath, rel))).digest("hex");
32910
33040
  } catch {
32911
33041
  continue;
32912
33042
  }
@@ -32955,13 +33085,13 @@ async function incrementalReindex(store, rootPath, workspaceId2, changedAbsPaths
32955
33085
  let parsedFiles = 0;
32956
33086
  for (const rel of changedRelPaths) {
32957
33087
  if (parsedFiles++ > 0) await new Promise((r2) => setImmediate(r2));
32958
- const abs = join11(rootPath, ...rel.split("/"));
33088
+ const abs = join12(rootPath, ...rel.split("/"));
32959
33089
  const ext = extname(abs).toLowerCase();
32960
33090
  const provider = providers.find((p) => p.fileExtensions.includes(ext));
32961
33091
  if (!provider) continue;
32962
33092
  let symbols;
32963
33093
  try {
32964
- symbols = provider.extractSymbols(readFileSync10(abs, "utf8"), abs);
33094
+ symbols = provider.extractSymbols(readFileSync11(abs, "utf8"), abs);
32965
33095
  } catch {
32966
33096
  continue;
32967
33097
  }
@@ -33281,7 +33411,7 @@ async function runIndexer(store, opts) {
33281
33411
  report.filesSkipped++;
33282
33412
  continue;
33283
33413
  }
33284
- source = readFileSync10(f.absPath, "utf8");
33414
+ source = readFileSync11(f.absPath, "utf8");
33285
33415
  } catch {
33286
33416
  report.filesSkipped++;
33287
33417
  continue;
@@ -33353,7 +33483,7 @@ async function runIndexer(store, opts) {
33353
33483
  const depth = fileNode.relPath.split("/").length;
33354
33484
  if (depth !== 3) continue;
33355
33485
  try {
33356
- const pkg = JSON.parse(readFileSync10(fileNode.absPath, "utf8"));
33486
+ const pkg = JSON.parse(readFileSync11(fileNode.absPath, "utf8"));
33357
33487
  if (!pkg.name) continue;
33358
33488
  const pkgDir = fileNode.relPath.replace(/\/package\.json$/, "");
33359
33489
  const candidates = [
@@ -33741,7 +33871,7 @@ async function scan(root, current, ignores, providers, out2) {
33741
33871
  for (const ent of entries) {
33742
33872
  if (ignores.has(ent.name)) continue;
33743
33873
  if (ent.name.startsWith(".") && ent.name !== ".") continue;
33744
- const abs = join11(current, ent.name);
33874
+ const abs = join12(current, ent.name);
33745
33875
  if (ent.isDirectory()) {
33746
33876
  await scan(root, abs, ignores, providers, out2);
33747
33877
  } else if (ent.isFile()) {
@@ -33796,7 +33926,7 @@ function gitListFiles(root, ignores, providers) {
33796
33926
  if (rels === null) return null;
33797
33927
  const out2 = [];
33798
33928
  for (const rel of rels) {
33799
- const abs = join11(root, rel);
33929
+ const abs = join12(root, rel);
33800
33930
  let size;
33801
33931
  try {
33802
33932
  size = statSync3(abs).size;
@@ -33819,7 +33949,7 @@ function upsertFile(store, id, f, workspaceId2, skip) {
33819
33949
  const now = nowTs();
33820
33950
  let contentHash;
33821
33951
  try {
33822
- contentHash = createHash4("sha256").update(readFileSync10(f.absPath)).digest("hex");
33952
+ contentHash = createHash5("sha256").update(readFileSync11(f.absPath)).digest("hex");
33823
33953
  } catch {
33824
33954
  }
33825
33955
  const carried = { ...store.getNode(id)?.attrs ?? {} };
@@ -38192,8 +38322,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
38192
38322
 
38193
38323
  // ../../packages/indexer/src/languages/tree-sitter-loader.ts
38194
38324
  import { fileURLToPath } from "node:url";
38195
- import { dirname as dirname7, join as join12 } from "node:path";
38196
- import { existsSync as existsSync12, readdirSync as readdirSync3 } from "node:fs";
38325
+ import { dirname as dirname7, join as join13 } from "node:path";
38326
+ import { existsSync as existsSync13, readdirSync as readdirSync3 } from "node:fs";
38197
38327
  import { createRequire as createRequire2 } from "node:module";
38198
38328
  function entryDir() {
38199
38329
  try {
@@ -38207,27 +38337,27 @@ function entryDir() {
38207
38337
  }
38208
38338
  function findWasmDir() {
38209
38339
  const here = entryDir();
38210
- const seaWasm = join12(here, "resources", "wasm");
38211
- if (existsSync12(join12(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
38340
+ const seaWasm = join13(here, "resources", "wasm");
38341
+ if (existsSync13(join13(seaWasm, "tree-sitter-typescript.wasm"))) return seaWasm;
38212
38342
  let dir = here;
38213
38343
  for (let i2 = 0; i2 < 6; i2++) {
38214
- const flat = join12(
38344
+ const flat = join13(
38215
38345
  dir,
38216
38346
  "node_modules",
38217
38347
  "@vscode",
38218
38348
  "tree-sitter-wasm",
38219
38349
  "wasm"
38220
38350
  );
38221
- if (existsSync12(join12(flat, "tree-sitter-typescript.wasm"))) return flat;
38351
+ if (existsSync13(join13(flat, "tree-sitter-typescript.wasm"))) return flat;
38222
38352
  dir = dirname7(dir);
38223
38353
  }
38224
38354
  let root = here;
38225
38355
  for (let i2 = 0; i2 < 6; i2++) {
38226
- const pnpmDir = join12(root, "node_modules", ".pnpm");
38227
- if (existsSync12(pnpmDir)) {
38356
+ const pnpmDir = join13(root, "node_modules", ".pnpm");
38357
+ if (existsSync13(pnpmDir)) {
38228
38358
  for (const entry of readdirSync3(pnpmDir)) {
38229
38359
  if (entry.startsWith("@vscode+tree-sitter-wasm@")) {
38230
- const candidate = join12(
38360
+ const candidate = join13(
38231
38361
  pnpmDir,
38232
38362
  entry,
38233
38363
  "node_modules",
@@ -38235,7 +38365,7 @@ function findWasmDir() {
38235
38365
  "tree-sitter-wasm",
38236
38366
  "wasm"
38237
38367
  );
38238
- if (existsSync12(join12(candidate, "tree-sitter-typescript.wasm"))) {
38368
+ if (existsSync13(join13(candidate, "tree-sitter-typescript.wasm"))) {
38239
38369
  return candidate;
38240
38370
  }
38241
38371
  }
@@ -38249,27 +38379,27 @@ function findWasmDir() {
38249
38379
  }
38250
38380
  function findRuntimeDir() {
38251
38381
  const here = entryDir();
38252
- const seaRuntime = join12(here, "resources", "wasm");
38253
- if (existsSync12(join12(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
38382
+ const seaRuntime = join13(here, "resources", "wasm");
38383
+ if (existsSync13(join13(seaRuntime, "web-tree-sitter.wasm"))) return seaRuntime;
38254
38384
  let dir = here;
38255
38385
  for (let i2 = 0; i2 < 6; i2++) {
38256
- const flat = join12(dir, "node_modules", "web-tree-sitter");
38257
- if (existsSync12(join12(flat, "web-tree-sitter.wasm"))) return flat;
38386
+ const flat = join13(dir, "node_modules", "web-tree-sitter");
38387
+ if (existsSync13(join13(flat, "web-tree-sitter.wasm"))) return flat;
38258
38388
  dir = dirname7(dir);
38259
38389
  }
38260
38390
  let root = here;
38261
38391
  for (let i2 = 0; i2 < 6; i2++) {
38262
- const pnpmDir = join12(root, "node_modules", ".pnpm");
38263
- if (existsSync12(pnpmDir)) {
38392
+ const pnpmDir = join13(root, "node_modules", ".pnpm");
38393
+ if (existsSync13(pnpmDir)) {
38264
38394
  for (const entry of readdirSync3(pnpmDir)) {
38265
38395
  if (entry.startsWith("web-tree-sitter@")) {
38266
- const candidate = join12(
38396
+ const candidate = join13(
38267
38397
  pnpmDir,
38268
38398
  entry,
38269
38399
  "node_modules",
38270
38400
  "web-tree-sitter"
38271
38401
  );
38272
- if (existsSync12(join12(candidate, "web-tree-sitter.wasm"))) {
38402
+ if (existsSync13(join13(candidate, "web-tree-sitter.wasm"))) {
38273
38403
  return candidate;
38274
38404
  }
38275
38405
  }
@@ -38286,7 +38416,7 @@ async function loadWebTreeSitter() {
38286
38416
  void err2;
38287
38417
  }
38288
38418
  const here = entryDir();
38289
- const seaResourceBase = join12(here, "resources", "_resolve.js");
38419
+ const seaResourceBase = join13(here, "resources", "_resolve.js");
38290
38420
  const resourceRequire = createRequire2(seaResourceBase);
38291
38421
  return resourceRequire("web-tree-sitter");
38292
38422
  }
@@ -38301,9 +38431,9 @@ async function ensureTreeSitterReady() {
38301
38431
  await Parser2.init({
38302
38432
  locateFile: (name2) => {
38303
38433
  if (name2 === "tree-sitter.wasm" || name2 === "web-tree-sitter.wasm") {
38304
- return join12(runtime, name2);
38434
+ return join13(runtime, name2);
38305
38435
  }
38306
- return join12(grammars, name2);
38436
+ return join13(grammars, name2);
38307
38437
  }
38308
38438
  });
38309
38439
  })();
@@ -38315,7 +38445,7 @@ async function loadGrammar(name2) {
38315
38445
  if (cached2) return cached2;
38316
38446
  if (!languageClass) throw new Error("tree-sitter not initialized");
38317
38447
  const grammars = findWasmDir();
38318
- const lang = await languageClass.load(join12(grammars, `${name2}.wasm`));
38448
+ const lang = await languageClass.load(join13(grammars, `${name2}.wasm`));
38319
38449
  grammarCache.set(name2, lang);
38320
38450
  return lang;
38321
38451
  }
@@ -38338,7 +38468,7 @@ var init_tree_sitter_loader = __esm({
38338
38468
  });
38339
38469
 
38340
38470
  // ../../packages/indexer/src/languages/typescript-treesitter.ts
38341
- import { createHash as createHash5 } from "node:crypto";
38471
+ import { createHash as createHash6 } from "node:crypto";
38342
38472
  function extractNode(node2, source, containerQname, containerKind) {
38343
38473
  switch (node2.type) {
38344
38474
  case "function_declaration":
@@ -38551,7 +38681,7 @@ function scopeRecord(kind, name2, qname, node2, body2, source) {
38551
38681
  const sig = header.replace(/\s+/g, " ").trim();
38552
38682
  if (sig) rec.signature = sig;
38553
38683
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
38554
- rec.bodyHash = createHash5("sha256").update(bodyText).digest("hex").slice(0, 16);
38684
+ rec.bodyHash = createHash6("sha256").update(bodyText).digest("hex").slice(0, 16);
38555
38685
  rec.bodySimhash = toHex(simhash(bodyText));
38556
38686
  }
38557
38687
  }
@@ -38993,14 +39123,14 @@ var init_typescript_treesitter = __esm({
38993
39123
  });
38994
39124
 
38995
39125
  // ../../packages/indexer/src/languages/python-treesitter.ts
38996
- import { createHash as createHash6 } from "node:crypto";
39126
+ import { createHash as createHash7 } from "node:crypto";
38997
39127
  function sigAndHash(node2, body2, source) {
38998
39128
  if (!body2) return {};
38999
39129
  const out2 = {};
39000
39130
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
39001
39131
  if (sig) out2.signature = sig;
39002
39132
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
39003
- out2.bodyHash = createHash6("sha256").update(bodyText).digest("hex").slice(0, 16);
39133
+ out2.bodyHash = createHash7("sha256").update(bodyText).digest("hex").slice(0, 16);
39004
39134
  out2.bodySimhash = toHex(simhash(bodyText));
39005
39135
  return out2;
39006
39136
  }
@@ -39413,7 +39543,7 @@ var init_python_treesitter = __esm({
39413
39543
  });
39414
39544
 
39415
39545
  // ../../packages/indexer/src/languages/cpp-treesitter.ts
39416
- import { createHash as createHash7 } from "node:crypto";
39546
+ import { createHash as createHash8 } from "node:crypto";
39417
39547
  function extractNode3(node2, containerQname, containerIsClass, source) {
39418
39548
  switch (node2.type) {
39419
39549
  case "function_definition":
@@ -39597,7 +39727,7 @@ function sigAndHash2(node2, body2, source) {
39597
39727
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
39598
39728
  if (sig) out2.signature = sig;
39599
39729
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
39600
- out2.bodyHash = createHash7("sha256").update(bodyText).digest("hex").slice(0, 16);
39730
+ out2.bodyHash = createHash8("sha256").update(bodyText).digest("hex").slice(0, 16);
39601
39731
  out2.bodySimhash = toHex(simhash(bodyText));
39602
39732
  return out2;
39603
39733
  }
@@ -39758,7 +39888,7 @@ var init_cpp_treesitter = __esm({
39758
39888
  });
39759
39889
 
39760
39890
  // ../../packages/indexer/src/languages/go-treesitter.ts
39761
- import { createHash as createHash8 } from "node:crypto";
39891
+ import { createHash as createHash9 } from "node:crypto";
39762
39892
  function extractNode4(node2, containerQname, source) {
39763
39893
  switch (node2.type) {
39764
39894
  case "function_declaration": {
@@ -39920,7 +40050,7 @@ function sigAndHash3(node2, body2, source) {
39920
40050
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
39921
40051
  if (sig) out2.signature = sig;
39922
40052
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
39923
- out2.bodyHash = createHash8("sha256").update(bodyText).digest("hex").slice(0, 16);
40053
+ out2.bodyHash = createHash9("sha256").update(bodyText).digest("hex").slice(0, 16);
39924
40054
  out2.bodySimhash = toHex(simhash(bodyText));
39925
40055
  return out2;
39926
40056
  }
@@ -40064,7 +40194,7 @@ var init_go_treesitter = __esm({
40064
40194
  });
40065
40195
 
40066
40196
  // ../../packages/indexer/src/languages/rust-treesitter.ts
40067
- import { createHash as createHash9 } from "node:crypto";
40197
+ import { createHash as createHash10 } from "node:crypto";
40068
40198
  function extractNode5(node2, containerQname, containerIsClass, source) {
40069
40199
  switch (node2.type) {
40070
40200
  case "function_item":
@@ -40279,7 +40409,7 @@ function sigAndHash4(node2, body2, source) {
40279
40409
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
40280
40410
  if (sig) out2.signature = sig;
40281
40411
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
40282
- out2.bodyHash = createHash9("sha256").update(bodyText).digest("hex").slice(0, 16);
40412
+ out2.bodyHash = createHash10("sha256").update(bodyText).digest("hex").slice(0, 16);
40283
40413
  out2.bodySimhash = toHex(simhash(bodyText));
40284
40414
  return out2;
40285
40415
  }
@@ -40430,7 +40560,7 @@ var init_rust_treesitter = __esm({
40430
40560
  });
40431
40561
 
40432
40562
  // ../../packages/indexer/src/languages/ruby-treesitter.ts
40433
- import { createHash as createHash10 } from "node:crypto";
40563
+ import { createHash as createHash11 } from "node:crypto";
40434
40564
  function sigAndHash5(node2, body2, source) {
40435
40565
  if (!body2) {
40436
40566
  const sig2 = source.slice(node2.startIndex, node2.endIndex).replace(/\s+/g, " ").trim();
@@ -40440,7 +40570,7 @@ function sigAndHash5(node2, body2, source) {
40440
40570
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
40441
40571
  if (sig) out2.signature = sig;
40442
40572
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
40443
- out2.bodyHash = createHash10("sha256").update(bodyText).digest("hex").slice(0, 16);
40573
+ out2.bodyHash = createHash11("sha256").update(bodyText).digest("hex").slice(0, 16);
40444
40574
  out2.bodySimhash = toHex(simhash(bodyText));
40445
40575
  return out2;
40446
40576
  }
@@ -40786,7 +40916,7 @@ var init_ruby_treesitter = __esm({
40786
40916
  });
40787
40917
 
40788
40918
  // ../../packages/indexer/src/languages/csharp-treesitter.ts
40789
- import { createHash as createHash11 } from "node:crypto";
40919
+ import { createHash as createHash12 } from "node:crypto";
40790
40920
  function extractNode7(node2, containerQname, containerIsType, source, eof) {
40791
40921
  switch (node2.type) {
40792
40922
  case "method_declaration":
@@ -40988,7 +41118,7 @@ function sigAndHash6(node2, body2, source) {
40988
41118
  const sig = source.slice(node2.startIndex, body2.startIndex).replace(/\s+/g, " ").trim();
40989
41119
  if (sig) out2.signature = sig;
40990
41120
  const bodyText = source.slice(body2.startIndex, body2.endIndex);
40991
- out2.bodyHash = createHash11("sha256").update(bodyText).digest("hex").slice(0, 16);
41121
+ out2.bodyHash = createHash12("sha256").update(bodyText).digest("hex").slice(0, 16);
40992
41122
  out2.bodySimhash = toHex(simhash(bodyText));
40993
41123
  return out2;
40994
41124
  }
@@ -41219,7 +41349,7 @@ var init_src11 = __esm({
41219
41349
  // src/reconcile.ts
41220
41350
  import { execFileSync as execFileSync2 } from "node:child_process";
41221
41351
  import { readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
41222
- import { join as join13, relative as relative3, sep as sep2 } from "node:path";
41352
+ import { join as join14, relative as relative3, sep as sep2 } from "node:path";
41223
41353
  function indexerWouldScan(rel) {
41224
41354
  for (const seg of rel.split(/[\\/]/)) {
41225
41355
  if (seg.length === 0) continue;
@@ -41242,7 +41372,7 @@ function gitSourceFiles(root) {
41242
41372
  const out2 = [];
41243
41373
  for (const rel of stdout.split("\0")) {
41244
41374
  if (!rel || !SOURCE_RE.test(rel) || !indexerWouldScan(rel)) continue;
41245
- const abs = join13(root, rel);
41375
+ const abs = join14(root, rel);
41246
41376
  if (IGNORED.test(abs)) continue;
41247
41377
  out2.push(abs);
41248
41378
  }
@@ -41257,7 +41387,7 @@ function* walkSource(dir) {
41257
41387
  }
41258
41388
  for (const e of entries) {
41259
41389
  const name2 = String(e.name);
41260
- const full = join13(dir, name2);
41390
+ const full = join14(dir, name2);
41261
41391
  if (IGNORED.test(full)) continue;
41262
41392
  if (!indexerWouldScan(name2)) continue;
41263
41393
  if (e.isDirectory()) yield* walkSource(full);
@@ -41407,7 +41537,7 @@ __export(mcp_exports, {
41407
41537
  runTool: () => runTool,
41408
41538
  searchGraph: () => searchGraph
41409
41539
  });
41410
- import { existsSync as existsSync13, readFileSync as readFileSync11 } from "node:fs";
41540
+ import { existsSync as existsSync14, readFileSync as readFileSync12 } from "node:fs";
41411
41541
  import { resolve as resolve3 } from "node:path";
41412
41542
  function collectEnrichmentPulls(store, opts = {}) {
41413
41543
  const pending = store.findNodesByLabel("Solution").filter((s) => s.attrs["enrichmentPending"] === true).filter((s) => !opts.onlyUnsurfaced || s.attrs["enrichmentSurfaced"] !== true);
@@ -41444,7 +41574,7 @@ function takeEnrichmentNudge(store) {
41444
41574
  ` + items;
41445
41575
  }
41446
41576
  function takeDiscriminatorNudge(path2) {
41447
- if (!path2 || !existsSync13(path2)) return null;
41577
+ if (!path2 || !existsSync14(path2)) return null;
41448
41578
  let shared;
41449
41579
  try {
41450
41580
  shared = openGraphStore({ path: path2 });
@@ -41575,10 +41705,10 @@ function showNode(store, node2, maxLines) {
41575
41705
  if (!relPath) return { found: false, reason: "no file owner for node" };
41576
41706
  const workspaceRoot = process.cwd();
41577
41707
  const absPath = resolve3(workspaceRoot, relPath);
41578
- if (!existsSync13(absPath)) {
41708
+ if (!existsSync14(absPath)) {
41579
41709
  return { found: false, reason: `file not found on disk: ${absPath}` };
41580
41710
  }
41581
- const source = readFileSync11(absPath, "utf8");
41711
+ const source = readFileSync12(absPath, "utf8");
41582
41712
  const attrs = node2.attrs;
41583
41713
  let startByte = attrs["bodyStartByte"] ?? attrs["startByte"];
41584
41714
  let endByte = attrs["bodyEndByte"] ?? attrs["endByte"];
@@ -41805,6 +41935,7 @@ function buildToolContext(workspaceRoot) {
41805
41935
  try {
41806
41936
  const cfg = loadConfig();
41807
41937
  const entry = workspaceRoot ? workspaceEntryForPath(resolve3(workspaceRoot)) : null;
41938
+ const syncOk = effectiveConsent(cfg, entry ? loadProfile(entry.path) : null).sync;
41808
41939
  const identity = resolveWorkspaceIdentity(cfg, entry);
41809
41940
  if (identity.invalid) {
41810
41941
  console.error(`[errata mcp] cloud DISABLED for this workspace: ${identity.reason}`);
@@ -41812,13 +41943,13 @@ function buildToolContext(workspaceRoot) {
41812
41943
  }
41813
41944
  if (identity.rule === "workspace-binding" && identity.profileName) {
41814
41945
  const profile = identity.profile;
41815
- if (cfg.consent.sync && (profile.accessToken || profile.apiKey)) {
41946
+ if (syncOk && (profile.accessToken || profile.apiKey)) {
41816
41947
  console.error(`[errata mcp] workspace identity: profile "${identity.profileName}"`);
41817
41948
  return { ...base, cloud: authedCloudClientForProfile(cfg, identity.profileName) };
41818
41949
  }
41819
41950
  return base;
41820
41951
  }
41821
- if (cfg.consent.sync && hasCloudCredential(cfg) && cfg.cloudUrl) {
41952
+ if (syncOk && hasCloudCredential(cfg) && cfg.cloudUrl) {
41822
41953
  return { ...base, cloud: authedCloudClient(cfg) };
41823
41954
  }
41824
41955
  } catch {
@@ -41865,6 +41996,8 @@ var init_mcp = __esm({
41865
41996
  "use strict";
41866
41997
  init_cloud_auth();
41867
41998
  init_config();
41999
+ init_consent();
42000
+ init_profile2();
41868
42001
  init_identity2();
41869
42002
  init_registry();
41870
42003
  init_dual_augment();
@@ -42332,7 +42465,7 @@ var init_mcp = __esm({
42332
42465
  const local = causalChain(store, { seedId: id, direction: "both", maxHops, limit });
42333
42466
  try {
42334
42467
  const path2 = sharedStorePath();
42335
- if (!existsSync13(path2)) return { found: true, ...local };
42468
+ if (!existsSync14(path2)) return { found: true, ...local };
42336
42469
  const shared = openGraphStore({ path: path2 });
42337
42470
  try {
42338
42471
  if (!shared.getNode(id)) return { found: true, ...local };
@@ -42932,7 +43065,7 @@ var init_mcp = __esm({
42932
43065
  inputSchema: { type: "object", properties: {} },
42933
43066
  handler: () => {
42934
43067
  const path2 = sharedStorePath();
42935
- if (!existsSync13(path2)) return { count: 0, pending: [] };
43068
+ if (!existsSync14(path2)) return { count: 0, pending: [] };
42936
43069
  const shared = openGraphStore({ path: path2 });
42937
43070
  try {
42938
43071
  const pending = pendingAbstractions(shared);
@@ -42960,7 +43093,7 @@ var init_mcp = __esm({
42960
43093
  },
42961
43094
  handler: (args2) => {
42962
43095
  const path2 = sharedStorePath();
42963
- if (!existsSync13(path2)) return { count: 0, pending: [] };
43096
+ if (!existsSync14(path2)) return { count: 0, pending: [] };
42964
43097
  const shared = openGraphStore({ path: path2 });
42965
43098
  try {
42966
43099
  const pending = pendingDiscriminators(shared, {
@@ -43004,7 +43137,7 @@ var init_mcp = __esm({
43004
43137
  },
43005
43138
  handler: (args2) => {
43006
43139
  const path2 = sharedStorePath();
43007
- if (!existsSync13(path2)) return { count: 0, routes: [] };
43140
+ if (!existsSync14(path2)) return { count: 0, routes: [] };
43008
43141
  const shared = openGraphStore({ path: path2 });
43009
43142
  try {
43010
43143
  const result = triageOf(shared, {
@@ -43389,8 +43522,8 @@ __export(vfile_exports, {
43389
43522
  resolvePath: () => resolvePath,
43390
43523
  segmentsOf: () => segmentsOf
43391
43524
  });
43392
- import { writeFileSync as writeFileSync9 } from "node:fs";
43393
- import { join as join14, resolve as resolve4, sep as sep3 } from "node:path";
43525
+ import { writeFileSync as writeFileSync10 } from "node:fs";
43526
+ import { join as join15, resolve as resolve4, sep as sep3 } from "node:path";
43394
43527
  function segmentsOf(rawPath) {
43395
43528
  let p = rawPath.replace(/\\/g, "/");
43396
43529
  p = p.replace(/^.*\.errata\/g\//, "").replace(/^\/?g\//, "").replace(/^\/+/, "");
@@ -43464,14 +43597,14 @@ async function renderVFile(rawPath, store, ctx = {}) {
43464
43597
  }
43465
43598
  async function materializeVFile(rawPath, workspaceRoot, store, ctx = {}) {
43466
43599
  const segs = segmentsOf(rawPath);
43467
- const gRoot = join14(workspaceRoot, ".errata", "g");
43600
+ const gRoot = join15(workspaceRoot, ".errata", "g");
43468
43601
  const abs = resolve4(gRoot, ...segs.length ? segs : ["index"]);
43469
43602
  if (abs !== gRoot && !abs.startsWith(gRoot + sep3)) {
43470
43603
  throw new Error(`refusing to materialize outside .errata/g: ${rawPath}`);
43471
43604
  }
43472
43605
  const text = await renderVFile(rawPath, store, ctx);
43473
43606
  ensureParent(abs);
43474
- writeFileSync9(abs, text, "utf8");
43607
+ writeFileSync10(abs, text, "utf8");
43475
43608
  return abs;
43476
43609
  }
43477
43610
  async function materializeOverview(workspaceRoot, store, ctx = {}) {
@@ -50891,25 +51024,25 @@ var init_tool_index = __esm({
50891
51024
 
50892
51025
  // src/outbox.ts
50893
51026
  import {
50894
- existsSync as existsSync14,
51027
+ existsSync as existsSync15,
50895
51028
  readdirSync as readdirSync5,
50896
- readFileSync as readFileSync12,
51029
+ readFileSync as readFileSync13,
50897
51030
  renameSync,
50898
51031
  unlinkSync,
50899
- writeFileSync as writeFileSync10
51032
+ writeFileSync as writeFileSync11
50900
51033
  } from "node:fs";
50901
- import { join as join15 } from "node:path";
50902
- import { createHash as createHash12 } from "node:crypto";
51034
+ import { join as join16 } from "node:path";
51035
+ import { createHash as createHash13 } from "node:crypto";
50903
51036
  function enqueueOutbox(paths, payload) {
50904
51037
  ensureDir(paths.outbox);
50905
- const id = createHash12("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
50906
- const file2 = join15(paths.outbox, `${Date.now()}-${id}.json`);
50907
- writeFileSync10(file2, JSON.stringify(payload, null, 2), "utf8");
51038
+ const id = createHash13("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
51039
+ const file2 = join16(paths.outbox, `${Date.now()}-${id}.json`);
51040
+ writeFileSync11(file2, JSON.stringify(payload, null, 2), "utf8");
50908
51041
  return file2;
50909
51042
  }
50910
51043
  async function flushOutbox(paths, client, store) {
50911
51044
  ensureDir(paths.outbox);
50912
- const entries = existsSync14(paths.outbox) ? readdirSync5(paths.outbox) : [];
51045
+ const entries = existsSync15(paths.outbox) ? readdirSync5(paths.outbox) : [];
50913
51046
  let uploaded = 0;
50914
51047
  let failed = 0;
50915
51048
  const quarantine = (abs, reason) => {
@@ -50920,10 +51053,10 @@ async function flushOutbox(paths, client, store) {
50920
51053
  }
50921
51054
  };
50922
51055
  for (const f of entries.filter((e) => e.endsWith(".json")).sort()) {
50923
- const abs = join15(paths.outbox, f);
51056
+ const abs = join16(paths.outbox, f);
50924
51057
  let payload;
50925
51058
  try {
50926
- payload = JSON.parse(readFileSync12(abs, "utf8"));
51059
+ payload = JSON.parse(readFileSync13(abs, "utf8"));
50927
51060
  } catch {
50928
51061
  failed++;
50929
51062
  quarantine(abs, "unparseable JSON");
@@ -50968,7 +51101,7 @@ async function flushOutbox(paths, client, store) {
50968
51101
  }
50969
51102
  }
50970
51103
  }
50971
- const remainingFiles = existsSync14(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
51104
+ const remainingFiles = existsSync15(paths.outbox) ? readdirSync5(paths.outbox).filter((e) => e.endsWith(".json")) : [];
50972
51105
  return { uploaded, failed, remaining: remainingFiles.length };
50973
51106
  }
50974
51107
  var init_outbox = __esm({
@@ -70913,12 +71046,12 @@ var init_report_render = __esm({
70913
71046
 
70914
71047
  // src/cli.ts
70915
71048
  init_src6();
70916
- import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync33, renameSync as renameSync4, statSync as statSync8 } from "node:fs";
70917
- import { join as join38, resolve as pathResolve2 } from "node:path";
71049
+ import { closeSync as closeSync2, existsSync as existsSync34, openSync as openSync2, readFileSync as readFileSync34, renameSync as renameSync4, statSync as statSync8 } from "node:fs";
71050
+ import { join as join39, resolve as pathResolve2 } from "node:path";
70918
71051
  import { spawn as spawn3 } from "node:child_process";
70919
71052
 
70920
71053
  // src/daemon.ts
70921
- import { existsSync as existsSync26, writeFileSync as writeFileSync21 } from "node:fs";
71054
+ import { existsSync as existsSync26, writeFileSync as writeFileSync22 } from "node:fs";
70922
71055
 
70923
71056
  // ../../node_modules/.pnpm/@hono+node-server@1.19.11_hono@4.12.8/node_modules/@hono/node-server/dist/index.mjs
70924
71057
  import { createServer as createServerHTTP } from "http";
@@ -71498,8 +71631,8 @@ init_config();
71498
71631
 
71499
71632
  // src/engine.ts
71500
71633
  import { execFileSync as execFileSync4 } from "node:child_process";
71501
- import { existsSync as existsSync25, statSync as statSync7, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "node:fs";
71502
- import { join as join30, relative as relative6, sep as sep4 } from "node:path";
71634
+ import { existsSync as existsSync25, statSync as statSync7, appendFileSync as appendFileSync4, readdirSync as readdirSync10, renameSync as renameSync3, readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "node:fs";
71635
+ import { join as join31, relative as relative6, sep as sep4 } from "node:path";
71503
71636
 
71504
71637
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
71505
71638
  import { stat as statcb } from "fs";
@@ -73447,10 +73580,10 @@ init_src10();
73447
73580
  init_review2();
73448
73581
 
73449
73582
  // src/turn.ts
73450
- import { closeSync, existsSync as existsSync15, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync5 } from "node:fs";
73451
- import { basename as basename5, delimiter, dirname as dirname10, join as join18, normalize as normalize3 } from "node:path";
73583
+ import { closeSync, existsSync as existsSync16, fstatSync, openSync, readdirSync as readdirSync6, readSync, realpathSync, statSync as statSync5 } from "node:fs";
73584
+ import { basename as basename5, delimiter, dirname as dirname10, join as join19, normalize as normalize3 } from "node:path";
73452
73585
  import { homedir as homedir4 } from "node:os";
73453
- import { createHash as createHash13 } from "node:crypto";
73586
+ import { createHash as createHash14 } from "node:crypto";
73454
73587
  function readFrom(path2, fromByte, maxBytes) {
73455
73588
  let fd;
73456
73589
  try {
@@ -73826,11 +73959,11 @@ function turnsSince(turns, mark) {
73826
73959
  return at >= 0 ? turns.slice(at + 1) : turns;
73827
73960
  }
73828
73961
  function claudeProjectDir(cwd, home = homedir4()) {
73829
- return join18(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
73962
+ return join19(home, ".claude", "projects", cwd.replace(/[\\/:.]/g, "-"));
73830
73963
  }
73831
73964
  function recentTranscripts(cwd, opts = {}) {
73832
73965
  const dir = claudeProjectDir(cwd, opts.home ?? homedir4());
73833
- if (!existsSync15(dir)) return [];
73966
+ if (!existsSync16(dir)) return [];
73834
73967
  let names;
73835
73968
  try {
73836
73969
  names = readdirSync6(dir);
@@ -73841,7 +73974,7 @@ function recentTranscripts(cwd, opts = {}) {
73841
73974
  const refs = [];
73842
73975
  for (const name2 of names) {
73843
73976
  if (!name2.endsWith(".jsonl")) continue;
73844
- const path2 = join18(dir, name2);
73977
+ const path2 = join19(dir, name2);
73845
73978
  let mtimeMs;
73846
73979
  try {
73847
73980
  mtimeMs = statSync5(path2).mtimeMs;
@@ -73856,8 +73989,8 @@ function recentTranscripts(cwd, opts = {}) {
73856
73989
  }
73857
73990
  function subagentTranscripts(mainTranscriptPath, sessionId) {
73858
73991
  if (!mainTranscriptPath || !sessionId) return [];
73859
- const dir = join18(dirname10(mainTranscriptPath), sessionId, "subagents");
73860
- if (!existsSync15(dir)) return [];
73992
+ const dir = join19(dirname10(mainTranscriptPath), sessionId, "subagents");
73993
+ if (!existsSync16(dir)) return [];
73861
73994
  let names;
73862
73995
  try {
73863
73996
  names = readdirSync6(dir);
@@ -73867,7 +74000,7 @@ function subagentTranscripts(mainTranscriptPath, sessionId) {
73867
74000
  const refs = [];
73868
74001
  for (const name2 of names) {
73869
74002
  if (!name2.endsWith(".jsonl")) continue;
73870
- const path2 = join18(dir, name2);
74003
+ const path2 = join19(dir, name2);
73871
74004
  let mtimeMs;
73872
74005
  try {
73873
74006
  mtimeMs = statSync5(path2).mtimeMs;
@@ -73886,8 +74019,8 @@ function splitPathList(value, sep5 = delimiter) {
73886
74019
  function codexSessionRoots(env2 = process.env, home = homedir4()) {
73887
74020
  const roots = /* @__PURE__ */ new Set();
73888
74021
  for (const d of splitPathList(env2["ERRATA_CODEX_SESSIONS_DIRS"])) roots.add(d);
73889
- if (env2["CODEX_HOME"]) roots.add(join18(env2["CODEX_HOME"], "sessions"));
73890
- roots.add(join18(home, ".codex", "sessions"));
74022
+ if (env2["CODEX_HOME"]) roots.add(join19(env2["CODEX_HOME"], "sessions"));
74023
+ roots.add(join19(home, ".codex", "sessions"));
73891
74024
  return [...roots];
73892
74025
  }
73893
74026
  function readCodexRolloutCwd(path2) {
@@ -73932,7 +74065,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
73932
74065
  const limit = opts.limit ?? 25;
73933
74066
  const out2 = [];
73934
74067
  for (const root of codexSessionRoots(opts.env, opts.home)) {
73935
- if (!existsSync15(root)) continue;
74068
+ if (!existsSync16(root)) continue;
73936
74069
  const stack = [{ dir: root, depth: 0 }];
73937
74070
  while (stack.length > 0) {
73938
74071
  const { dir, depth } = stack.pop();
@@ -73943,7 +74076,7 @@ function codexRolloutsForCwd(cwd, opts = {}) {
73943
74076
  continue;
73944
74077
  }
73945
74078
  for (const name2 of names) {
73946
- const full = join18(dir, name2);
74079
+ const full = join19(dir, name2);
73947
74080
  let st;
73948
74081
  try {
73949
74082
  st = statSync5(full);
@@ -73968,12 +74101,12 @@ function codexRolloutsForCwd(cwd, opts = {}) {
73968
74101
  function geminiSessionRoots(env2 = process.env, home = homedir4()) {
73969
74102
  const roots = /* @__PURE__ */ new Set();
73970
74103
  for (const d of splitPathList(env2["ERRATA_GEMINI_SESSIONS_DIRS"])) roots.add(d);
73971
- if (env2["GEMINI_CLI_HOME"]) roots.add(join18(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
73972
- roots.add(join18(home, ".gemini", "tmp"));
74104
+ if (env2["GEMINI_CLI_HOME"]) roots.add(join19(env2["GEMINI_CLI_HOME"], ".gemini", "tmp"));
74105
+ roots.add(join19(home, ".gemini", "tmp"));
73973
74106
  return [...roots];
73974
74107
  }
73975
74108
  function geminiProjectHash(cwd) {
73976
- return createHash13("sha256").update(cwd).digest("hex");
74109
+ return createHash14("sha256").update(cwd).digest("hex");
73977
74110
  }
73978
74111
  function geminiHashesFor(cwd) {
73979
74112
  const variants = /* @__PURE__ */ new Set([cwd, cwd.replace(/\/+$/, "")]);
@@ -74009,7 +74142,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74009
74142
  const hashes = geminiHashesFor(cwd);
74010
74143
  const out2 = [];
74011
74144
  for (const root of geminiSessionRoots(opts.env, opts.home)) {
74012
- if (!existsSync15(root)) continue;
74145
+ if (!existsSync16(root)) continue;
74013
74146
  let slugs;
74014
74147
  try {
74015
74148
  slugs = readdirSync6(root);
@@ -74017,7 +74150,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74017
74150
  continue;
74018
74151
  }
74019
74152
  for (const slug2 of slugs) {
74020
- const chats = join18(root, slug2, "chats");
74153
+ const chats = join19(root, slug2, "chats");
74021
74154
  let names;
74022
74155
  try {
74023
74156
  names = readdirSync6(chats);
@@ -74026,7 +74159,7 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74026
74159
  }
74027
74160
  for (const name2 of names) {
74028
74161
  if (!name2.startsWith("session-") || !name2.endsWith(".jsonl")) continue;
74029
- const full = join18(chats, name2);
74162
+ const full = join19(chats, name2);
74030
74163
  let st;
74031
74164
  try {
74032
74165
  st = statSync5(full);
@@ -74046,8 +74179,8 @@ function geminiTranscriptsForCwd(cwd, opts = {}) {
74046
74179
  function opencodeSessionRoots(env2 = process.env, home = homedir4()) {
74047
74180
  const roots = /* @__PURE__ */ new Set();
74048
74181
  for (const d of splitPathList(env2["ERRATA_OPENCODE_SESSIONS_DIRS"])) roots.add(d);
74049
- if (env2["XDG_DATA_HOME"]) roots.add(join18(env2["XDG_DATA_HOME"], "opencode", "errata"));
74050
- roots.add(join18(home, ".local", "share", "opencode", "errata"));
74182
+ if (env2["XDG_DATA_HOME"]) roots.add(join19(env2["XDG_DATA_HOME"], "opencode", "errata"));
74183
+ roots.add(join19(home, ".local", "share", "opencode", "errata"));
74051
74184
  return [...roots];
74052
74185
  }
74053
74186
  function readOpencodeTranscriptDirectory(path2) {
@@ -74080,7 +74213,7 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
74080
74213
  }
74081
74214
  const out2 = [];
74082
74215
  for (const root of opencodeSessionRoots(opts.env, opts.home)) {
74083
- if (!existsSync15(root)) continue;
74216
+ if (!existsSync16(root)) continue;
74084
74217
  let names;
74085
74218
  try {
74086
74219
  names = readdirSync6(root);
@@ -74089,7 +74222,7 @@ function opencodeTranscriptsForCwd(cwd, opts = {}) {
74089
74222
  }
74090
74223
  for (const name2 of names) {
74091
74224
  if (!name2.endsWith(".jsonl")) continue;
74092
- const full = join18(root, name2);
74225
+ const full = join19(root, name2);
74093
74226
  let st;
74094
74227
  try {
74095
74228
  st = statSync5(full);
@@ -74112,7 +74245,7 @@ init_src2();
74112
74245
  init_agent_signals();
74113
74246
  init_tool_index();
74114
74247
  init_src5();
74115
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync11 } from "node:fs";
74248
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "node:fs";
74116
74249
  var NEG = /n['']t|\b(?:not|never|no|none|neither|nor|unrelated|irrelevant|would|might|could|if)\b/i;
74117
74250
  var CITE_GROUP_RE = /\(((?:[^()\n]|\([^()\n]*\)){1,200})\)/g;
74118
74251
  var HANDLE_RE = /\[([a-z0-9][\w-]{0,80})\]|((?:pat|sol|drc|dcause|dfix|dprob|prob|claim|err)_[0-9a-f]{6,})/gi;
@@ -74791,13 +74924,13 @@ function writePrimingHandles(path2, nodes, now = Date.now()) {
74791
74924
  entries.sort((a, b) => (b[1].seenAt ?? 0) - (a[1].seenAt ?? 0));
74792
74925
  entries.length = HANDLE_MAP_MAX;
74793
74926
  }
74794
- writeFileSync11(path2, JSON.stringify(Object.fromEntries(entries)));
74927
+ writeFileSync12(path2, JSON.stringify(Object.fromEntries(entries)));
74795
74928
  } catch {
74796
74929
  }
74797
74930
  }
74798
74931
  function readPrimingHandles(path2) {
74799
74932
  try {
74800
- return JSON.parse(readFileSync13(path2, "utf8"));
74933
+ return JSON.parse(readFileSync14(path2, "utf8"));
74801
74934
  } catch {
74802
74935
  return {};
74803
74936
  }
@@ -75272,8 +75405,8 @@ ${conversation}` }]
75272
75405
  // src/constraint-backfill.ts
75273
75406
  init_src5();
75274
75407
  init_src2();
75275
- import { existsSync as existsSync16, readFileSync as readFileSync14, readdirSync as readdirSync7, writeFileSync as writeFileSync12 } from "node:fs";
75276
- import { join as join19 } from "node:path";
75408
+ import { existsSync as existsSync17, readFileSync as readFileSync15, readdirSync as readdirSync7, writeFileSync as writeFileSync13 } from "node:fs";
75409
+ import { join as join20 } from "node:path";
75277
75410
  import { homedir as homedir5 } from "node:os";
75278
75411
  var BACKFILL_VERSION = 1;
75279
75412
  var EMPTY = {
@@ -75287,13 +75420,13 @@ var EMPTY = {
75287
75420
  recoverable: 0
75288
75421
  };
75289
75422
  function markerPath(configDir) {
75290
- return join19(configDir, "constraint-backfill.json");
75423
+ return join20(configDir, "constraint-backfill.json");
75291
75424
  }
75292
75425
  function alreadyDone(configDir) {
75293
75426
  const p = markerPath(configDir);
75294
- if (!existsSync16(p)) return false;
75427
+ if (!existsSync17(p)) return false;
75295
75428
  try {
75296
- const raw2 = JSON.parse(readFileSync14(p, "utf8"));
75429
+ const raw2 = JSON.parse(readFileSync15(p, "utf8"));
75297
75430
  return raw2?.version === BACKFILL_VERSION;
75298
75431
  } catch {
75299
75432
  return false;
@@ -75303,7 +75436,7 @@ function replay(root) {
75303
75436
  const statements = /* @__PURE__ */ new Set();
75304
75437
  const citedByFix = /* @__PURE__ */ new Set();
75305
75438
  const dir = claudeProjectDir(root, homedir5());
75306
- if (!existsSync16(dir)) return { statements, citedByFix };
75439
+ if (!existsSync17(dir)) return { statements, citedByFix };
75307
75440
  let names;
75308
75441
  try {
75309
75442
  names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
@@ -75313,7 +75446,7 @@ function replay(root) {
75313
75446
  for (const f of names) {
75314
75447
  let lines;
75315
75448
  try {
75316
- lines = readFileSync14(join19(dir, f), "utf8").split("\n");
75449
+ lines = readFileSync15(join20(dir, f), "utf8").split("\n");
75317
75450
  } catch {
75318
75451
  continue;
75319
75452
  }
@@ -75427,7 +75560,7 @@ function backfillConstraintKind(store, opts) {
75427
75560
  }
75428
75561
  });
75429
75562
  try {
75430
- writeFileSync12(
75563
+ writeFileSync13(
75431
75564
  markerPath(opts.configDir),
75432
75565
  JSON.stringify({ version: BACKFILL_VERSION, at: opts.now, ...report, cloudTwins: report.cloudTwins.length }, null, 2),
75433
75566
  "utf8"
@@ -75440,8 +75573,8 @@ function backfillConstraintKind(store, opts) {
75440
75573
  // src/edge-repair.ts
75441
75574
  init_src();
75442
75575
  init_src5();
75443
- import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "node:fs";
75444
- import { join as join20 } from "node:path";
75576
+ import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
75577
+ import { join as join21 } from "node:path";
75445
75578
  function citeEdgeId(from, type, to) {
75446
75579
  return `edge_${digest({ from, type, to })}`.slice(0, 24);
75447
75580
  }
@@ -75456,13 +75589,13 @@ var EMPTY2 = {
75456
75589
  byType: {}
75457
75590
  };
75458
75591
  function markerPath2(configDir) {
75459
- return join20(configDir, "edge-repair.json");
75592
+ return join21(configDir, "edge-repair.json");
75460
75593
  }
75461
75594
  function alreadyDone2(configDir) {
75462
75595
  const p = markerPath2(configDir);
75463
- if (!existsSync17(p)) return false;
75596
+ if (!existsSync18(p)) return false;
75464
75597
  try {
75465
- return JSON.parse(readFileSync15(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
75598
+ return JSON.parse(readFileSync16(p, "utf8"))?.version === EDGE_REPAIR_VERSION;
75466
75599
  } catch {
75467
75600
  return false;
75468
75601
  }
@@ -75511,7 +75644,7 @@ function repairInvalidEdges(store, opts) {
75511
75644
  });
75512
75645
  store.pruneEdgeRejections(opts.now - REJECTION_RETENTION_MS);
75513
75646
  try {
75514
- writeFileSync13(
75647
+ writeFileSync14(
75515
75648
  markerPath2(opts.configDir),
75516
75649
  JSON.stringify({ version: EDGE_REPAIR_VERSION, at: opts.now, ...report }, null, 2),
75517
75650
  "utf8"
@@ -75525,8 +75658,8 @@ function repairInvalidEdges(store, opts) {
75525
75658
  init_reconcile();
75526
75659
 
75527
75660
  // src/pass-ledger.ts
75528
- import { appendFileSync as appendFileSync2, existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync14 } from "node:fs";
75529
- import { join as join21 } from "node:path";
75661
+ import { appendFileSync as appendFileSync2, existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync15 } from "node:fs";
75662
+ import { join as join22 } from "node:path";
75530
75663
 
75531
75664
  // src/isolate-census.ts
75532
75665
  var live = 0;
@@ -75549,7 +75682,7 @@ var PER_KIND_MAX = 100;
75549
75682
  var TRIM_EVERY = 50;
75550
75683
  var appendsSinceTrim = /* @__PURE__ */ new Map();
75551
75684
  function passLedgerPath(configDir) {
75552
- return join21(configDir, "pass-ledger.jsonl");
75685
+ return join22(configDir, "pass-ledger.jsonl");
75553
75686
  }
75554
75687
  function appendPassLedger(configDir, kind, durationMs, counts) {
75555
75688
  const path2 = passLedgerPath(configDir);
@@ -75578,7 +75711,7 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
75578
75711
  return;
75579
75712
  }
75580
75713
  appendsSinceTrim.set(path2, 0);
75581
- const lines = readFileSync16(path2, "utf8").split("\n").filter(Boolean);
75714
+ const lines = readFileSync17(path2, "utf8").split("\n").filter(Boolean);
75582
75715
  const keptByKind = /* @__PURE__ */ new Map();
75583
75716
  const kept = [];
75584
75717
  for (let i2 = lines.length - 1; i2 >= 0; i2--) {
@@ -75594,16 +75727,16 @@ function appendPassLedger(configDir, kind, durationMs, counts) {
75594
75727
  kept.push(lines[i2]);
75595
75728
  }
75596
75729
  if (kept.length < lines.length) {
75597
- writeFileSync14(path2, kept.reverse().join("\n") + "\n");
75730
+ writeFileSync15(path2, kept.reverse().join("\n") + "\n");
75598
75731
  }
75599
75732
  } catch {
75600
75733
  }
75601
75734
  }
75602
75735
  function readPassLedger(configDir) {
75603
75736
  const path2 = passLedgerPath(configDir);
75604
- if (!existsSync18(path2)) return [];
75737
+ if (!existsSync19(path2)) return [];
75605
75738
  try {
75606
- return readFileSync16(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
75739
+ return readFileSync17(path2, "utf8").split("\n").filter(Boolean).map((l) => JSON.parse(l)).filter(
75607
75740
  (e) => typeof e?.ts === "number" && typeof e?.kind === "string" && typeof e?.durationMs === "number"
75608
75741
  ).map((e) => ({ ...e, counts: e.counts ?? {} }));
75609
75742
  } catch {
@@ -75971,11 +76104,11 @@ init_outbox();
75971
76104
  init_src9();
75972
76105
  init_src();
75973
76106
  init_src2();
75974
- import { readFileSync as readFileSync17 } from "node:fs";
75975
- import { join as join22 } from "node:path";
76107
+ import { readFileSync as readFileSync18 } from "node:fs";
76108
+ import { join as join23 } from "node:path";
75976
76109
  function loadClaimIgnorePatterns(workspaceRoot) {
75977
76110
  try {
75978
- return readFileSync17(join22(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
76111
+ return readFileSync18(join23(workspaceRoot, ".errataignore"), "utf8").split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0 && !l.startsWith("#")).map((l) => l.toLowerCase());
75979
76112
  } catch {
75980
76113
  return [];
75981
76114
  }
@@ -76338,9 +76471,9 @@ async function pullCloudTriage(shared, cloud, profile, limit = 50) {
76338
76471
  // src/retrieval-stack.ts
76339
76472
  init_src();
76340
76473
  import { execFileSync as execFileSync3 } from "node:child_process";
76341
- import { existsSync as existsSync19, readFileSync as readFileSync18, statSync as statSync6 } from "node:fs";
76474
+ import { existsSync as existsSync20, readFileSync as readFileSync19, statSync as statSync6 } from "node:fs";
76342
76475
  import { homedir as homedir6 } from "node:os";
76343
- import { join as join23 } from "node:path";
76476
+ import { join as join24 } from "node:path";
76344
76477
  var RETRIEVAL_STACK_CAP = 24;
76345
76478
  var MANIFEST_SCAN_CAP = 400;
76346
76479
  var RUNTIME_TOKENS = /* @__PURE__ */ new Set([
@@ -76630,51 +76763,51 @@ function mavenGroupIsSelfDisclosing(name2, selfTokens) {
76630
76763
  function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
76631
76764
  const read2 = (p) => {
76632
76765
  try {
76633
- return readFileSync18(p, "utf8");
76766
+ return readFileSync19(p, "utf8");
76634
76767
  } catch {
76635
76768
  return null;
76636
76769
  }
76637
76770
  };
76638
76771
  const texts = (...paths) => paths.map(read2).filter((t) => t !== null);
76639
76772
  const home = homedir6();
76640
- const npm = parseNpmrcPolicy(texts(join23(root, ".npmrc"), join23(home, ".npmrc")));
76773
+ const npm = parseNpmrcPolicy(texts(join24(root, ".npmrc"), join24(home, ".npmrc")));
76641
76774
  const blocked = /* @__PURE__ */ new Set();
76642
76775
  if (!npm.defaultPublic) blocked.add("npm");
76643
76776
  if (pypiIndexIsPrivate(
76644
76777
  texts(
76645
- join23(root, "pip.conf"),
76646
- join23(root, "pip.ini"),
76647
- join23(root, "pyproject.toml"),
76648
- join23(root, "requirements.txt"),
76649
- join23(home, ".pip", "pip.conf"),
76650
- join23(home, ".config", "pip", "pip.conf"),
76651
- join23(env2["APPDATA"] ?? home, "pip", "pip.ini")
76778
+ join24(root, "pip.conf"),
76779
+ join24(root, "pip.ini"),
76780
+ join24(root, "pyproject.toml"),
76781
+ join24(root, "requirements.txt"),
76782
+ join24(home, ".pip", "pip.conf"),
76783
+ join24(home, ".config", "pip", "pip.conf"),
76784
+ join24(env2["APPDATA"] ?? home, "pip", "pip.ini")
76652
76785
  )
76653
76786
  )) {
76654
76787
  blocked.add("pypi");
76655
76788
  }
76656
76789
  if (cargoRegistryIsPrivate(
76657
76790
  texts(
76658
- join23(root, ".cargo", "config.toml"),
76659
- join23(root, ".cargo", "config"),
76660
- join23(home, ".cargo", "config.toml"),
76661
- join23(home, ".cargo", "config")
76791
+ join24(root, ".cargo", "config.toml"),
76792
+ join24(root, ".cargo", "config"),
76793
+ join24(home, ".cargo", "config.toml"),
76794
+ join24(home, ".cargo", "config")
76662
76795
  )
76663
76796
  )) {
76664
76797
  blocked.add("cargo");
76665
76798
  }
76666
76799
  if (nugetSourcesArePrivate(
76667
76800
  texts(
76668
- join23(root, "NuGet.config"),
76669
- join23(root, "nuget.config"),
76670
- join23(root, "NuGet.Config"),
76671
- join23(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
76672
- join23(home, ".nuget", "NuGet", "NuGet.Config")
76801
+ join24(root, "NuGet.config"),
76802
+ join24(root, "nuget.config"),
76803
+ join24(root, "NuGet.Config"),
76804
+ join24(env2["APPDATA"] ?? home, "NuGet", "NuGet.Config"),
76805
+ join24(home, ".nuget", "NuGet", "NuGet.Config")
76673
76806
  )
76674
76807
  )) {
76675
76808
  blocked.add("nuget");
76676
76809
  }
76677
- const goEnvFile = env2["GOENV"] ?? join23(env2["APPDATA"] ?? join23(home, ".config"), "go", "env");
76810
+ const goEnvFile = env2["GOENV"] ?? join24(env2["APPDATA"] ?? join24(home, ".config"), "go", "env");
76678
76811
  const goEnvText = read2(goEnvFile) ?? "";
76679
76812
  const fromFile = ["GOPRIVATE", "GONOSUMDB", "GONOSUMCHECK"].map(
76680
76813
  (k) => new RegExp(`^${k}=(.*)$`, "m").exec(goEnvText)?.[1]
@@ -76685,10 +76818,10 @@ function loadRegistryPolicy(root, env2 = process.env, repoLocator) {
76685
76818
  env2["GONOSUMCHECK"],
76686
76819
  ...fromFile
76687
76820
  ]);
76688
- const gemfiles = texts(join23(root, "Gemfile"));
76821
+ const gemfiles = texts(join24(root, "Gemfile"));
76689
76822
  if (gemSourceIsPrivate(gemfiles)) blocked.add("gem");
76690
76823
  if (mavenReposArePrivate(
76691
- texts(join23(root, "pom.xml"), join23(home, ".m2", "settings.xml"))
76824
+ texts(join24(root, "pom.xml"), join24(home, ".m2", "settings.xml"))
76692
76825
  )) {
76693
76826
  blocked.add("maven");
76694
76827
  }
@@ -76855,8 +76988,8 @@ function readDirectDependencies(root) {
76855
76988
  const familiesSeen = /* @__PURE__ */ new Set();
76856
76989
  for (const c of LOCKFILES) {
76857
76990
  if (familiesSeen.has(c.family)) continue;
76858
- const p = join23(root, c.file);
76859
- if (!existsSync19(p)) continue;
76991
+ const p = join24(root, c.file);
76992
+ if (!existsSync20(p)) continue;
76860
76993
  try {
76861
76994
  const s = statSync6(p);
76862
76995
  stamps.push(`${c.file}:${s.mtimeMs}:${s.size}`);
@@ -76876,7 +77009,7 @@ function readDirectDependencies(root) {
76876
77009
  const direct = [];
76877
77010
  for (const { c, path: path2 } of found) {
76878
77011
  try {
76879
- direct.push(...c.parse(readFileSync18(path2, "utf8")).direct ?? []);
77012
+ direct.push(...c.parse(readFileSync19(path2, "utf8")).direct ?? []);
76880
77013
  } catch {
76881
77014
  }
76882
77015
  }
@@ -76919,14 +77052,14 @@ function manifestPaths(root) {
76919
77052
  "project.godot"
76920
77053
  ];
76921
77054
  return {
76922
- paths: ROOT_MANIFESTS.filter((f) => existsSync19(join23(root, f))),
77055
+ paths: ROOT_MANIFESTS.filter((f) => existsSync20(join24(root, f))),
76923
77056
  tracked: false,
76924
77057
  truncated: false
76925
77058
  };
76926
77059
  }
76927
77060
  var WORKSPACE_MARKERS = ["pnpm-workspace.yaml", "lerna.json", "go.work", "settings.gradle", "settings.gradle.kts"];
76928
77061
  function rootDeclaresWorkspace(root, texts) {
76929
- if (WORKSPACE_MARKERS.some((f) => existsSync19(join23(root, f)))) return true;
77062
+ if (WORKSPACE_MARKERS.some((f) => existsSync20(join24(root, f)))) return true;
76930
77063
  return /"workspaces"\s*:/.test(texts.get("package.json") ?? "") || /<modules>/.test(texts.get("pom.xml") ?? "") || /^\s*\[workspace\]/m.test(texts.get("Cargo.toml") ?? "");
76931
77064
  }
76932
77065
  var EMPTY_SCAN = { deps: [], self: [], complete: true };
@@ -76940,11 +77073,11 @@ function scanManifests(root) {
76940
77073
  const texts = /* @__PURE__ */ new Map();
76941
77074
  const stamps = [];
76942
77075
  for (const rel of paths) {
76943
- const abs = join23(root, rel);
77076
+ const abs = join24(root, rel);
76944
77077
  try {
76945
77078
  const s = statSync6(abs);
76946
77079
  stamps.push(`${rel}:${s.mtimeMs}:${s.size}`);
76947
- texts.set(rel, readFileSync18(abs, "utf8"));
77080
+ texts.set(rel, readFileSync19(abs, "utf8"));
76948
77081
  } catch {
76949
77082
  }
76950
77083
  }
@@ -76973,22 +77106,22 @@ function readManifestDependencies(root) {
76973
77106
  }
76974
77107
 
76975
77108
  // src/git-sensor.ts
76976
- import { existsSync as existsSync20, readFileSync as readFileSync19, watch as fsWatch } from "node:fs";
76977
- import { join as join24 } from "node:path";
77109
+ import { existsSync as existsSync21, readFileSync as readFileSync20, watch as fsWatch } from "node:fs";
77110
+ import { join as join25 } from "node:path";
76978
77111
  function readFirstLine(path2) {
76979
77112
  try {
76980
- return readFileSync19(path2, "utf8").split(/\r?\n/, 1)[0].trim();
77113
+ return readFileSync20(path2, "utf8").split(/\r?\n/, 1)[0].trim();
76981
77114
  } catch {
76982
77115
  return null;
76983
77116
  }
76984
77117
  }
76985
77118
  function readGitRefState(gitDir) {
76986
- const head2 = readFirstLine(join24(gitDir, "HEAD"));
77119
+ const head2 = readFirstLine(join25(gitDir, "HEAD"));
76987
77120
  const m = head2 ? /^ref:\s*refs\/heads\/(.+)$/.exec(head2) : null;
76988
77121
  const branch = m ? m[1] : null;
76989
77122
  let sha2 = null;
76990
77123
  if (branch) {
76991
- sha2 = readFirstLine(join24(gitDir, "refs", "heads", branch));
77124
+ sha2 = readFirstLine(join25(gitDir, "refs", "heads", branch));
76992
77125
  if (!sha2) sha2 = shaFromPackedRefs(gitDir, `refs/heads/${branch}`);
76993
77126
  } else if (head2 && /^[0-9a-f]{7,40}$/i.test(head2)) {
76994
77127
  sha2 = head2;
@@ -76996,13 +77129,13 @@ function readGitRefState(gitDir) {
76996
77129
  return {
76997
77130
  branch,
76998
77131
  sha: sha2,
76999
- mergeHeadExists: existsSync20(join24(gitDir, "MERGE_HEAD")),
77000
- origHeadExists: existsSync20(join24(gitDir, "ORIG_HEAD"))
77132
+ mergeHeadExists: existsSync21(join25(gitDir, "MERGE_HEAD")),
77133
+ origHeadExists: existsSync21(join25(gitDir, "ORIG_HEAD"))
77001
77134
  };
77002
77135
  }
77003
77136
  function shaFromPackedRefs(gitDir, ref) {
77004
77137
  try {
77005
- for (const line of readFileSync19(join24(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
77138
+ for (const line of readFileSync20(join25(gitDir, "packed-refs"), "utf8").split(/\r?\n/)) {
77006
77139
  const [sha2, name2] = line.split(/\s+/);
77007
77140
  if (name2 === ref && sha2) return sha2;
77008
77141
  }
@@ -77036,7 +77169,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
77036
77169
  const settle = () => {
77037
77170
  if (timer) clearTimeout(timer);
77038
77171
  timer = setTimeout(() => {
77039
- if (existsSync20(join24(gitDir, "index.lock"))) {
77172
+ if (existsSync21(join25(gitDir, "index.lock"))) {
77040
77173
  settle();
77041
77174
  return;
77042
77175
  }
@@ -77047,7 +77180,7 @@ function startGitSensor(gitDir, onEvent, opts = {}) {
77047
77180
  }, debounceMs);
77048
77181
  };
77049
77182
  for (const sub of ["HEAD", "logs/HEAD", "MERGE_HEAD", "ORIG_HEAD"]) {
77050
- const p = join24(gitDir, sub);
77183
+ const p = join25(gitDir, sub);
77051
77184
  try {
77052
77185
  watchers.push(fsWatch(p, settle));
77053
77186
  } catch {
@@ -77272,21 +77405,21 @@ var TelemetryRecorder = class {
77272
77405
 
77273
77406
  // src/skills.ts
77274
77407
  import {
77275
- existsSync as existsSync21,
77408
+ existsSync as existsSync22,
77276
77409
  mkdirSync as mkdirSync7,
77277
- readFileSync as readFileSync20,
77410
+ readFileSync as readFileSync21,
77278
77411
  readdirSync as readdirSync8,
77279
77412
  unlinkSync as unlinkSync2,
77280
- writeFileSync as writeFileSync15
77413
+ writeFileSync as writeFileSync16
77281
77414
  } from "node:fs";
77282
- import { basename as basename6, join as join25 } from "node:path";
77415
+ import { basename as basename6, join as join26 } from "node:path";
77283
77416
  function skillFileName(id) {
77284
77417
  return `${id.replace(/[^A-Za-z0-9_.-]/g, "_")}.md`;
77285
77418
  }
77286
77419
  function readSkillManifest(manifestPath) {
77287
- if (!existsSync21(manifestPath)) return [];
77420
+ if (!existsSync22(manifestPath)) return [];
77288
77421
  try {
77289
- const parsed = JSON.parse(readFileSync20(manifestPath, "utf8"));
77422
+ const parsed = JSON.parse(readFileSync21(manifestPath, "utf8"));
77290
77423
  return (parsed.skills ?? []).map((s) => ({
77291
77424
  title: s.title ?? "",
77292
77425
  layer: s.layer ?? "technique",
@@ -77310,7 +77443,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
77310
77443
  for (const s of res.skills) {
77311
77444
  const fileName = skillFileName(s.id);
77312
77445
  keep.add(fileName);
77313
- writeFileSync15(join25(paths.skillsDir, fileName), s.markdown, "utf8");
77446
+ writeFileSync16(join26(paths.skillsDir, fileName), s.markdown, "utf8");
77314
77447
  rows.push({
77315
77448
  id: s.id,
77316
77449
  title: s.title,
@@ -77323,7 +77456,7 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
77323
77456
  const fileName = skillFileName(p.id);
77324
77457
  if (keep.has(fileName)) continue;
77325
77458
  keep.add(fileName);
77326
- writeFileSync15(join25(paths.skillsDir, fileName), p.markdown, "utf8");
77459
+ writeFileSync16(join26(paths.skillsDir, fileName), p.markdown, "utf8");
77327
77460
  rows.push({
77328
77461
  id: p.id,
77329
77462
  title: p.title,
@@ -77337,13 +77470,13 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
77337
77470
  if (!f.endsWith(".md")) continue;
77338
77471
  if (keep.has(basename6(f))) continue;
77339
77472
  try {
77340
- unlinkSync2(join25(paths.skillsDir, f));
77473
+ unlinkSync2(join26(paths.skillsDir, f));
77341
77474
  pruned++;
77342
77475
  } catch {
77343
77476
  }
77344
77477
  }
77345
77478
  rows.sort((a, b) => a.id.localeCompare(b.id));
77346
- writeFileSync15(
77479
+ writeFileSync16(
77347
77480
  paths.skillsManifest,
77348
77481
  JSON.stringify({ generatedAt: Date.now(), skills: rows }, null, 2),
77349
77482
  "utf8"
@@ -77355,22 +77488,22 @@ async function syncSkills(paths, client, seed, pins = [], techSeed) {
77355
77488
  init_src2();
77356
77489
  import {
77357
77490
  cpSync,
77358
- existsSync as existsSync22,
77491
+ existsSync as existsSync23,
77359
77492
  lstatSync,
77360
77493
  mkdirSync as mkdirSync8,
77361
- readFileSync as readFileSync21,
77494
+ readFileSync as readFileSync22,
77362
77495
  readdirSync as readdirSync9,
77363
77496
  rmSync as rmSync3,
77364
77497
  symlinkSync,
77365
- writeFileSync as writeFileSync16
77498
+ writeFileSync as writeFileSync17
77366
77499
  } from "node:fs";
77367
- import { join as join26 } from "node:path";
77500
+ import { join as join27 } from "node:path";
77368
77501
  var SKILL_NS = "errata-";
77369
77502
  var HARNESS_SKILL_DIRS = [
77370
- { configDir: ".claude", skillsDir: join26(".claude", "skills") },
77503
+ { configDir: ".claude", skillsDir: join27(".claude", "skills") },
77371
77504
  // Cursor adopted the standard; its exact project dir is still moving — kept
77372
77505
  // best-effort and gated on `.cursor/` presence so we never create it blind.
77373
- { configDir: ".cursor", skillsDir: join26(".cursor", "skills") }
77506
+ { configDir: ".cursor", skillsDir: join27(".cursor", "skills") }
77374
77507
  ];
77375
77508
  function skillSlug(title, id) {
77376
77509
  const base = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "skill";
@@ -77415,12 +77548,12 @@ function skillCiteHandle(s) {
77415
77548
  return priorHandle({ id: s.id, description: s.title });
77416
77549
  }
77417
77550
  function reconcileNamespaced(dir, keep) {
77418
- if (!existsSync22(dir)) return 0;
77551
+ if (!existsSync23(dir)) return 0;
77419
77552
  let pruned = 0;
77420
77553
  for (const name2 of readdirSync9(dir)) {
77421
77554
  if (!name2.startsWith(SKILL_NS) || keep.has(name2)) continue;
77422
77555
  try {
77423
- rmSync3(join26(dir, name2), { recursive: true, force: true });
77556
+ rmSync3(join27(dir, name2), { recursive: true, force: true });
77424
77557
  pruned++;
77425
77558
  } catch {
77426
77559
  }
@@ -77429,7 +77562,7 @@ function reconcileNamespaced(dir, keep) {
77429
77562
  }
77430
77563
  function linkOrCopy(linkPath, target) {
77431
77564
  try {
77432
- if (existsSync22(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
77565
+ if (existsSync23(linkPath) || safeLstat(linkPath)) rmSync3(linkPath, { recursive: true, force: true });
77433
77566
  } catch {
77434
77567
  }
77435
77568
  try {
@@ -77450,7 +77583,7 @@ function safeLstat(p) {
77450
77583
  }
77451
77584
  }
77452
77585
  function emitAndProjectSkills(root, skills) {
77453
- const agentsSkillsDir = join26(root, ".agents", "skills");
77586
+ const agentsSkillsDir = join27(root, ".agents", "skills");
77454
77587
  mkdirSync8(agentsSkillsDir, { recursive: true });
77455
77588
  const slugs = [];
77456
77589
  const keep = /* @__PURE__ */ new Set();
@@ -77458,7 +77591,7 @@ function emitAndProjectSkills(root, skills) {
77458
77591
  for (const s of skills) {
77459
77592
  let body2;
77460
77593
  try {
77461
- body2 = readFileSync21(s.bodyPath, "utf8");
77594
+ body2 = readFileSync22(s.bodyPath, "utf8");
77462
77595
  } catch {
77463
77596
  continue;
77464
77597
  }
@@ -77467,9 +77600,9 @@ function emitAndProjectSkills(root, skills) {
77467
77600
  keep.add(slug2);
77468
77601
  slugs.push(slug2);
77469
77602
  const description = deriveDescription(s.title, s.layer, body2);
77470
- mkdirSync8(join26(agentsSkillsDir, slug2), { recursive: true });
77471
- writeFileSync16(
77472
- join26(agentsSkillsDir, slug2, "SKILL.md"),
77603
+ mkdirSync8(join27(agentsSkillsDir, slug2), { recursive: true });
77604
+ writeFileSync17(
77605
+ join27(agentsSkillsDir, slug2, "SKILL.md"),
77473
77606
  renderSkillMd(slug2, description, body2, skillCiteHandle(s)),
77474
77607
  "utf8"
77475
77608
  );
@@ -77478,11 +77611,11 @@ function emitAndProjectSkills(root, skills) {
77478
77611
  reconcileNamespaced(agentsSkillsDir, keep);
77479
77612
  let projected = 0;
77480
77613
  for (const h of HARNESS_SKILL_DIRS) {
77481
- if (!existsSync22(join26(root, h.configDir))) continue;
77482
- const dir = join26(root, h.skillsDir);
77614
+ if (!existsSync23(join27(root, h.configDir))) continue;
77615
+ const dir = join27(root, h.skillsDir);
77483
77616
  mkdirSync8(dir, { recursive: true });
77484
77617
  for (const slug2 of slugs) {
77485
- linkOrCopy(join26(dir, slug2), join26(agentsSkillsDir, slug2));
77618
+ linkOrCopy(join27(dir, slug2), join27(agentsSkillsDir, slug2));
77486
77619
  projected++;
77487
77620
  }
77488
77621
  reconcileNamespaced(dir, keep);
@@ -77491,15 +77624,15 @@ function emitAndProjectSkills(root, skills) {
77491
77624
  return { slugs, emitted, projected };
77492
77625
  }
77493
77626
  function emitInputsFromManifest(erretaDir, manifestPath) {
77494
- if (!existsSync22(manifestPath)) return [];
77627
+ if (!existsSync23(manifestPath)) return [];
77495
77628
  try {
77496
- const parsed = JSON.parse(readFileSync21(manifestPath, "utf8"));
77629
+ const parsed = JSON.parse(readFileSync22(manifestPath, "utf8"));
77497
77630
  return (parsed.skills ?? []).filter((s) => Boolean(s.id && s.file)).map((s) => ({
77498
77631
  id: s.id,
77499
77632
  title: s.title ?? s.id,
77500
77633
  layer: s.layer ?? "technique",
77501
77634
  confidence: s.confidence ?? 0,
77502
- bodyPath: join26(erretaDir, s.file)
77635
+ bodyPath: join27(erretaDir, s.file)
77503
77636
  }));
77504
77637
  } catch {
77505
77638
  return [];
@@ -77513,17 +77646,17 @@ var GITIGNORE_LINES = [
77513
77646
  ".cursor/skills/errata-*/"
77514
77647
  ];
77515
77648
  function ensureSkillGitignore(root) {
77516
- const path2 = join26(root, ".gitignore");
77649
+ const path2 = join27(root, ".gitignore");
77517
77650
  let current = "";
77518
77651
  try {
77519
- current = existsSync22(path2) ? readFileSync21(path2, "utf8") : "";
77652
+ current = existsSync23(path2) ? readFileSync22(path2, "utf8") : "";
77520
77653
  } catch {
77521
77654
  return;
77522
77655
  }
77523
77656
  if (current.includes(GITIGNORE_MARK)) return;
77524
77657
  const prefix = current.length > 0 && !current.endsWith("\n") ? "\n" : "";
77525
77658
  try {
77526
- writeFileSync16(path2, `${current}${prefix}
77659
+ writeFileSync17(path2, `${current}${prefix}
77527
77660
  ${GITIGNORE_LINES.join("\n")}
77528
77661
  `, "utf8");
77529
77662
  } catch {
@@ -77616,108 +77749,7 @@ function createToolRunState() {
77616
77749
  // src/engine.ts
77617
77750
  init_tool_index();
77618
77751
  init_paths();
77619
-
77620
- // src/profile.ts
77621
- init_src2();
77622
- init_paths();
77623
- init_git_remote();
77624
- import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync17 } from "node:fs";
77625
- import { createHash as createHash14 } from "node:crypto";
77626
- import { join as join27 } from "node:path";
77627
- function workspaceId(root) {
77628
- return "wp_" + createHash14("sha256").update(root).digest("hex").slice(0, 12);
77629
- }
77630
- function sessionOriginKey(sessionId) {
77631
- if (!sessionId) return void 0;
77632
- return "ws_" + createHash14("sha256").update(sessionId).digest("hex").slice(0, 12);
77633
- }
77634
- function refreshRepoLocator(root, profile) {
77635
- const detected = detectRepoLocator(root, profile.repoRemote);
77636
- if (!detected || detected === profile.repoLocator) return false;
77637
- if (profile.repoLocator) {
77638
- const aliases = new Set(profile.repoLocatorAliases ?? []);
77639
- aliases.add(profile.repoLocator);
77640
- aliases.delete(detected);
77641
- profile.repoLocatorAliases = [...aliases];
77642
- }
77643
- profile.repoLocator = detected;
77644
- saveProfile(root, profile);
77645
- return true;
77646
- }
77647
- function loadProfile(root) {
77648
- const p = workspacePaths(root);
77649
- if (!existsSync23(p.workspaceJson)) return null;
77650
- return JSON.parse(readFileSync22(p.workspaceJson, "utf8"));
77651
- }
77652
- function saveProfile(root, profile) {
77653
- const p = workspacePaths(root);
77654
- ensureDir(p.configDir);
77655
- writeFileSync17(p.workspaceJson, JSON.stringify(profile, null, 2), "utf8");
77656
- }
77657
- function autodetectProfile(root) {
77658
- const id = workspaceId(root);
77659
- const name2 = root.split(/[\\/]/).filter(Boolean).pop() ?? "workspace";
77660
- const p = emptyProfile(id, name2);
77661
- const locator = detectRepoLocator(root);
77662
- if (locator) p.repoLocator = locator;
77663
- const pkgPath = join27(root, "package.json");
77664
- if (existsSync23(pkgPath)) {
77665
- try {
77666
- const pkg = JSON.parse(readFileSync22(pkgPath, "utf8"));
77667
- const deps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
77668
- p.languages.push("javascript");
77669
- if (existsSync23(join27(root, "tsconfig.json")) || deps["typescript"]) {
77670
- p.languages.push("typescript");
77671
- }
77672
- const nodeVer = pkg.engines?.node?.trim();
77673
- p.stack.push(nodeVer ? `node@${nodeVer}` : "node");
77674
- const interesting = [
77675
- "next",
77676
- "react",
77677
- "vue",
77678
- "svelte",
77679
- "express",
77680
- "hono",
77681
- "fastify",
77682
- "@modelcontextprotocol/sdk"
77683
- ];
77684
- for (const k of interesting) {
77685
- if (deps[k]) p.stack.push(k);
77686
- }
77687
- } catch {
77688
- }
77689
- }
77690
- const pyproject = join27(root, "pyproject.toml");
77691
- if (existsSync23(pyproject)) {
77692
- try {
77693
- const txt = readFileSync22(pyproject, "utf8");
77694
- const py = /python\s*=\s*"([^"]+)"/.exec(txt)?.[1];
77695
- p.languages.push("python");
77696
- p.stack.push(`python@${py ?? "3"}`);
77697
- const candidates = ["fastapi", "django", "flask", "mcp", "pytest"];
77698
- for (const k of candidates) {
77699
- if (new RegExp(`\\b${k}\\b`, "i").test(txt)) p.stack.push(k);
77700
- }
77701
- } catch {
77702
- }
77703
- }
77704
- const reqs = join27(root, "requirements.txt");
77705
- if (existsSync23(reqs)) {
77706
- if (!p.languages.includes("python")) p.languages.push("python");
77707
- if (!p.stack.includes("python@3")) p.stack.push("python@3");
77708
- }
77709
- if (existsSync23(join27(root, "go.mod"))) {
77710
- p.languages.push("go");
77711
- p.stack.push("go");
77712
- }
77713
- if (existsSync23(join27(root, "Cargo.toml"))) {
77714
- p.languages.push("rust");
77715
- p.stack.push("rust");
77716
- }
77717
- p.languages = [...new Set(p.languages)];
77718
- p.stack = [...new Set(p.stack)];
77719
- return p;
77720
- }
77752
+ init_profile2();
77721
77753
 
77722
77754
  // src/witness-queue.ts
77723
77755
  import { readFileSync as readFileSync23, renameSync as renameSync2, writeFileSync as writeFileSync18 } from "node:fs";
@@ -77918,7 +77950,9 @@ var CausalBuffer = class {
77918
77950
  };
77919
77951
 
77920
77952
  // src/engine.ts
77953
+ init_profile2();
77921
77954
  init_config();
77955
+ init_consent();
77922
77956
  init_cloud_auth();
77923
77957
 
77924
77958
  // src/notify.ts
@@ -78049,6 +78083,8 @@ function maybeFlushDigests() {
78049
78083
 
78050
78084
  // src/liveness-watch.ts
78051
78085
  init_src5();
78086
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync20 } from "node:fs";
78087
+ import { join as join30 } from "node:path";
78052
78088
 
78053
78089
  // src/loop-lag.ts
78054
78090
  var HEARTBEAT_MS = 500;
@@ -78171,9 +78207,26 @@ function watchCensusLine(c = watchCensus(), now = Date.now()) {
78171
78207
  // src/liveness-watch.ts
78172
78208
  var LIVENESS_WATCH_INTERVAL_MS = 60 * 60 * 1e3;
78173
78209
  var ALARM_RENOTIFY_MS = 24 * 60 * 60 * 1e3;
78210
+ function alarmStatePath(configDir) {
78211
+ return join30(configDir, "liveness-alarms.json");
78212
+ }
78213
+ function loadAlarmState(configDir) {
78214
+ try {
78215
+ const raw2 = JSON.parse(readFileSync25(alarmStatePath(configDir), "utf8"));
78216
+ return new Map(Object.entries(raw2).filter((e) => typeof e[1] === "number"));
78217
+ } catch {
78218
+ return /* @__PURE__ */ new Map();
78219
+ }
78220
+ }
78221
+ function saveAlarmState(configDir, state) {
78222
+ try {
78223
+ writeFileSync20(alarmStatePath(configDir), JSON.stringify(Object.fromEntries(state)));
78224
+ } catch {
78225
+ }
78226
+ }
78174
78227
  function createLivenessWatch(deps) {
78175
78228
  let lastRunAt = 0;
78176
- const lastAlarmedAt = /* @__PURE__ */ new Map();
78229
+ const lastAlarmedAt = loadAlarmState(deps.configDir);
78177
78230
  return {
78178
78231
  maybeRun(nowMs = Date.now()) {
78179
78232
  if (nowMs - lastRunAt < LIVENESS_WATCH_INTERVAL_MS) return null;
@@ -78222,6 +78275,7 @@ function createLivenessWatch(deps) {
78222
78275
  const at = lastAlarmedAt.get(r.id) ?? 0;
78223
78276
  if (nowMs - at < ALARM_RENOTIFY_MS) continue;
78224
78277
  lastAlarmedAt.set(r.id, nowMs);
78278
+ saveAlarmState(deps.configDir, lastAlarmedAt);
78225
78279
  const line = lines.find((l) => l.includes(r.id)) ?? `${r.verdict} ${r.id}`;
78226
78280
  deps.onAlarm(r.id, `${line.trim()} \u2014 ${r.what}`);
78227
78281
  }
@@ -78335,7 +78389,7 @@ function createWatchBreaker(deps) {
78335
78389
  }
78336
78390
 
78337
78391
  // src/engine.ts
78338
- var DAEMON_VERSION = true ? "2.0.6-dev.2564" : "2.0.0-alpha.0";
78392
+ var DAEMON_VERSION = true ? "2.0.6-dev.2571" : "2.0.0-alpha.0";
78339
78393
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
78340
78394
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
78341
78395
  var GIT_OP_MUTE_MS = 4e3;
@@ -78356,7 +78410,7 @@ function appendIdentityAudit(path2, record2, line) {
78356
78410
  var yieldToLoop = () => new Promise((r) => setImmediate(r));
78357
78411
  function loadTurnCursors(path2) {
78358
78412
  try {
78359
- const raw2 = JSON.parse(readFileSync25(path2, "utf8"));
78413
+ const raw2 = JSON.parse(readFileSync26(path2, "utf8"));
78360
78414
  return new Map(
78361
78415
  Object.entries(raw2).map(([k, v]) => [k, typeof v === "string" ? v : String(v?.uuid ?? "")])
78362
78416
  );
@@ -78366,7 +78420,7 @@ function loadTurnCursors(path2) {
78366
78420
  }
78367
78421
  function loadTurnOffsets(path2) {
78368
78422
  try {
78369
- const raw2 = JSON.parse(readFileSync25(path2, "utf8"));
78423
+ const raw2 = JSON.parse(readFileSync26(path2, "utf8"));
78370
78424
  const out2 = /* @__PURE__ */ new Map();
78371
78425
  for (const [k, v] of Object.entries(raw2)) {
78372
78426
  const off = typeof v === "object" && v !== null ? v.offset : void 0;
@@ -78382,7 +78436,7 @@ function saveTurnCursors(path2, cursors, offsets) {
78382
78436
  const merged = {};
78383
78437
  for (const [k, uuid3] of cursors) merged[k] = { uuid: uuid3, offset: offsets.get(k) ?? 0 };
78384
78438
  for (const [k, offset] of offsets) if (!merged[k]) merged[k] = { uuid: "", offset };
78385
- writeFileSync20(path2, JSON.stringify(merged), "utf8");
78439
+ writeFileSync21(path2, JSON.stringify(merged), "utf8");
78386
78440
  } catch {
78387
78441
  }
78388
78442
  }
@@ -78404,7 +78458,7 @@ function gitSourceWatchTargets(root) {
78404
78458
  ["-C", root, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"],
78405
78459
  { encoding: "utf8", maxBuffer: 256 * 1024 * 1024, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] }
78406
78460
  );
78407
- ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join30(root, d) + sep4));
78461
+ ignoredDirs = igOut.split("\0").filter(Boolean).map((d) => d.replace(/\/+$/, "")).filter((d) => !IGNORED_PATH.test(join31(root, d) + sep4));
78408
78462
  } catch {
78409
78463
  }
78410
78464
  const hasIgnoredChild = (dir) => ignoredDirs.some((ig) => ig.startsWith(dir + "/"));
@@ -78416,19 +78470,19 @@ function gitSourceWatchTargets(root) {
78416
78470
  if (!f.startsWith(prefix)) continue;
78417
78471
  const rest2 = f.slice(prefix.length);
78418
78472
  if (rest2.includes("/")) children.add(dir === "" ? rest2.slice(0, rest2.indexOf("/")) : dir + "/" + rest2.slice(0, rest2.indexOf("/")));
78419
- else targets.add(join30(root, f));
78473
+ else targets.add(join31(root, f));
78420
78474
  }
78421
78475
  for (const c of children) {
78422
- if (IGNORED_PATH.test(join30(root, c) + sep4)) continue;
78476
+ if (IGNORED_PATH.test(join31(root, c) + sep4)) continue;
78423
78477
  if (hasIgnoredChild(c)) addUnder(c);
78424
- else targets.add(join30(root, c));
78478
+ else targets.add(join31(root, c));
78425
78479
  }
78426
78480
  };
78427
78481
  addUnder("");
78428
78482
  if (targets.size > 0) return [...targets];
78429
78483
  } catch {
78430
78484
  }
78431
- return readdirSync10(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join30(root, String(e.name)) + sep4)).map((e) => join30(root, String(e.name)));
78485
+ return readdirSync10(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !IGNORED_PATH.test(join31(root, String(e.name)) + sep4)).map((e) => join31(root, String(e.name)));
78432
78486
  }
78433
78487
  function createWorkspaceEngine(opts) {
78434
78488
  const paths = workspacePaths(opts.workspaceRoot);
@@ -78442,6 +78496,7 @@ function createWorkspaceEngine(opts) {
78442
78496
  } else {
78443
78497
  refreshRepoLocator(opts.workspaceRoot, profile);
78444
78498
  }
78499
+ const consentNow = () => effectiveConsent(loadConfig(), profile);
78445
78500
  const store = openGraphStore({ path: paths.castalia });
78446
78501
  const witnessLoad = loadWitnessQueueWithLosses(witnessQueuePath(paths.configDir));
78447
78502
  const witnessPrune = pruneWitnessQueueWithDispositions(witnessLoad.queue, Date.now());
@@ -78621,7 +78676,7 @@ function createWorkspaceEngine(opts) {
78621
78676
  const srcPaths = diff.changedPaths.filter((p) => /\.(ts|tsx|js|jsx|mjs|cjs|py)$/i.test(p));
78622
78677
  let episodeId2;
78623
78678
  if (srcPaths.length > 0) {
78624
- const abs = srcPaths.map((p) => join30(opts.workspaceRoot, p));
78679
+ const abs = srcPaths.map((p) => join31(opts.workspaceRoot, p));
78625
78680
  try {
78626
78681
  const r = await runReindexPass(
78627
78682
  `git-reindex:${profile.name} (${abs.length} files)`,
@@ -78657,7 +78712,7 @@ function createWorkspaceEngine(opts) {
78657
78712
  `[errata] git: ${ev.kind} ${ev.newSha.slice(0, 7)} by ${meta3.authorName} \u2014 ${diff.changedPaths.length} file(s), ${diff.renames.length} rename(s)`
78658
78713
  );
78659
78714
  };
78660
- const gitDir = join30(opts.workspaceRoot, ".git");
78715
+ const gitDir = join31(opts.workspaceRoot, ".git");
78661
78716
  if (existsSync25(gitDir)) {
78662
78717
  stopGit = startGitSensor(gitDir, (ev) => {
78663
78718
  void handleGitEvent(ev).catch((err2) => {
@@ -78839,10 +78894,10 @@ function createWorkspaceEngine(opts) {
78839
78894
  console.warn("[errata] render ledger failed:", err2.message?.slice(0, 120));
78840
78895
  }
78841
78896
  writeContextFile(opts.workspaceRoot, body2);
78842
- const target = join30(opts.workspaceRoot, "AGENTS.md");
78897
+ const target = join31(opts.workspaceRoot, "AGENTS.md");
78843
78898
  writeManagedBlock(target, { body: AGENTS_POINTER_BODY, stable: true, force: true });
78844
78899
  if (elicit) {
78845
- writePrimingHandles(join30(paths.configDir, "priming-handles.json"), [
78900
+ writePrimingHandles(join31(paths.configDir, "priming-handles.json"), [
78846
78901
  ...snapshot.recentProblems.map((r) => r.node),
78847
78902
  // Resolved-band handles: the ✓ problem AND its Solution are citable
78848
78903
  // (a fix tag on an already-resolved problem no-ops idempotently; the
@@ -78870,7 +78925,7 @@ function createWorkspaceEngine(opts) {
78870
78925
  // resolves each token against both the Package and Language namespaces,
78871
78926
  // and the profile keeps them in separate fields.
78872
78927
  languages: profile?.languages ?? [],
78873
- contributePackages: loadConfig().consent.contributePackages,
78928
+ contributePackages: consentNow().contributePackages,
78874
78929
  // `repoLocator` feeds the Maven self-disclosure rule ONLY: a groupId
78875
78930
  // carrying this project's own owner/repo token is the project naming
78876
78931
  // itself, not a library it depends on.
@@ -78881,7 +78936,7 @@ function createWorkspaceEngine(opts) {
78881
78936
  if (opts.skipContextWriter || remoteInFlight) return;
78882
78937
  const now = Date.now();
78883
78938
  if (now - lastRemoteAt < REMOTE_REFRESH_MS) return;
78884
- const syncOk = opts.syncConsent ?? loadConfig().consent.sync;
78939
+ const syncOk = opts.syncConsent ?? consentNow().sync;
78885
78940
  if (!syncOk) return;
78886
78941
  if (typeof cloud.search !== "function") return;
78887
78942
  remoteInFlight = true;
@@ -78921,7 +78976,7 @@ function createWorkspaceEngine(opts) {
78921
78976
  const maybeRefreshIntentPriors = (liveIntent) => {
78922
78977
  if (!liveIntent || opts.skipContextWriter || intentRemoteInFlight) return;
78923
78978
  if (intentRemote?.forIntent === liveIntent) return;
78924
- const syncOk = opts.syncConsent ?? loadConfig().consent.sync;
78979
+ const syncOk = opts.syncConsent ?? consentNow().sync;
78925
78980
  if (!syncOk) return;
78926
78981
  if (typeof cloud.search !== "function") return;
78927
78982
  intentRemoteInFlight = true;
@@ -79154,7 +79209,7 @@ function createWorkspaceEngine(opts) {
79154
79209
  resultSummary: { exitCode: e.exitCode ?? 1, errorTokens: e.errorTokens }
79155
79210
  });
79156
79211
  };
79157
- const turnCursorPath = join30(paths.configDir, "turn-cursors.json");
79212
+ const turnCursorPath = join31(paths.configDir, "turn-cursors.json");
79158
79213
  const lastTurnUuid = loadTurnCursors(turnCursorPath);
79159
79214
  const turnOffset = loadTurnOffsets(turnCursorPath);
79160
79215
  const readLosses = { parseFailures: 0, ioFailures: 0, bytesUnreachable: 0, sliceGuardHits: 0 };
@@ -79209,7 +79264,7 @@ function createWorkspaceEngine(opts) {
79209
79264
  let processedTurns = 0;
79210
79265
  const seqAtStart = store.currentIngestSeq();
79211
79266
  const elicit = isEdgeElicitationEnabled();
79212
- const handleMap = elicit ? readPrimingHandles(join30(paths.configDir, "priming-handles.json")) : {};
79267
+ const handleMap = elicit ? readPrimingHandles(join31(paths.configDir, "priming-handles.json")) : {};
79213
79268
  const wsRoot = (opts.workspaceRoot ?? "").replace(/\\/g, "/");
79214
79269
  const toRel = (abs) => {
79215
79270
  const p = abs.replace(/\\/g, "/");
@@ -79501,10 +79556,10 @@ function createWorkspaceEngine(opts) {
79501
79556
  let enclosing = {};
79502
79557
  if (p.location?.line !== void 0) {
79503
79558
  try {
79504
- const headSha = readGitRefState(join30(opts.workspaceRoot, ".git")).sha ?? void 0;
79559
+ const headSha = readGitRefState(join31(opts.workspaceRoot, ".git")).sha ?? void 0;
79505
79560
  enclosing = {
79506
79561
  line: p.location.line,
79507
- fileText: readFileSync25(join30(opts.workspaceRoot, anchorPath), "utf8"),
79562
+ fileText: readFileSync26(join31(opts.workspaceRoot, anchorPath), "utf8"),
79508
79563
  ...headSha ? { headSha } : {}
79509
79564
  };
79510
79565
  } catch {
@@ -80227,7 +80282,7 @@ B: ${b}`,
80227
80282
  });
80228
80283
  }
80229
80284
  const pullSkills = async () => {
80230
- if ((opts.syncConsent ?? loadConfig().consent.sync) === true) {
80285
+ if ((opts.syncConsent ?? consentNow().sync) === true) {
80231
80286
  for (const req of communityInductionRequests(store)) {
80232
80287
  try {
80233
80288
  const r = await cloud.induceSkill({ members: req.members, context: req.context });
@@ -80247,7 +80302,7 @@ B: ${b}`,
80247
80302
  const pins = profile?.projectId ? await cloud.getSkillPins(profile.projectId).then((r) => r.pins).catch(() => []) : [];
80248
80303
  const anchorMap = buildBucketTokenAnchors(
80249
80304
  profile.languages ?? [],
80250
- loadConfig().consent.contributePackages ? store.findNodesByLabel("Package").map((p) => ({
80305
+ consentNow().contributePackages ? store.findNodesByLabel("Package").map((p) => ({
80251
80306
  name: String(p.attrs["name"] ?? ""),
80252
80307
  purl: String(p.attrs["purl"] ?? p.id)
80253
80308
  })) : []
@@ -80262,7 +80317,7 @@ B: ${b}`,
80262
80317
  try {
80263
80318
  const inputs = emitInputsFromManifest(paths.configDir, paths.skillsManifest);
80264
80319
  emitAndProjectSkills(opts.workspaceRoot, inputs);
80265
- writePrimingHandles(join30(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
80320
+ writePrimingHandles(join31(paths.configDir, "priming-handles.json"), skillHandleNodes(inputs));
80266
80321
  } catch (err2) {
80267
80322
  console.warn("[skills] agent-skills projection failed (non-fatal):", err2 instanceof Error ? err2.message : err2);
80268
80323
  }
@@ -80354,7 +80409,7 @@ B: ${b}`,
80354
80409
  semanticMaintenance() {
80355
80410
  const seqBefore = store.currentIngestSeq();
80356
80411
  const report = runSemanticMaintenance(store);
80357
- let hintUpgrade = { upgraded: 0, standing: 0, unresolvable: 0 };
80412
+ let hintUpgrade = { upgraded: 0, standing: 0, unresolvable: 0, blocked: 0 };
80358
80413
  try {
80359
80414
  hintUpgrade = upgradeAnchorHints(store, profile.id, Date.now());
80360
80415
  } catch {
@@ -80372,7 +80427,8 @@ B: ${b}`,
80372
80427
  seqAdvanced: store.currentIngestSeq() - seqBefore,
80373
80428
  anchorHintsUpgraded: hintUpgrade.upgraded,
80374
80429
  anchorHintsStanding: hintUpgrade.standing,
80375
- anchorHintsUnresolvable: hintUpgrade.unresolvable
80430
+ anchorHintsUnresolvable: hintUpgrade.unresolvable,
80431
+ anchorHintsBlocked: hintUpgrade.blocked
80376
80432
  });
80377
80433
  if (report.revisitsCleared > 0 || report.fixCandidatesSettled > 0 || report.designResolved > 0) {
80378
80434
  refreshContextNow();
@@ -80553,7 +80609,7 @@ B: ${b}`,
80553
80609
  };
80554
80610
  },
80555
80611
  async syncNow() {
80556
- const syncOk = opts.syncConsent ?? loadConfig().consent.sync;
80612
+ const syncOk = opts.syncConsent ?? consentNow().sync;
80557
80613
  if (!syncOk) {
80558
80614
  console.log(
80559
80615
  "[errata] sync skipped \u2014 cloud sync consent is off (enable with `errata consent sync on`)"
@@ -80584,14 +80640,14 @@ B: ${b}`,
80584
80640
  }
80585
80641
  try {
80586
80642
  const freshCfg = loadConfig();
80587
- if (freshCfg.consent.telemetry) {
80643
+ if (consentNow().telemetry) {
80588
80644
  telemetry.event("graph_snapshot", store.nodeCount(), {
80589
80645
  problemsLive: store.findNodesByLabel("Problem").length
80590
80646
  });
80591
80647
  telemetry.event("heartbeat");
80592
80648
  }
80593
80649
  const t = await telemetry.flush(cloud, {
80594
- consent: freshCfg.consent.telemetry,
80650
+ consent: consentNow().telemetry,
80595
80651
  credentialPresent: Boolean(opts.apiKey) || hasCloudCredential(freshCfg)
80596
80652
  });
80597
80653
  if (t.sent > 0) {
@@ -80649,7 +80705,7 @@ async function startDaemon(opts) {
80649
80705
  reviewUrl: () => webUiUrl + "/review"
80650
80706
  });
80651
80707
  const writeLockFile = (url2) => {
80652
- writeFileSync21(
80708
+ writeFileSync22(
80653
80709
  engine.paths.daemonLock,
80654
80710
  JSON.stringify({ pid: process.pid, webUiUrl: url2, startedAt: Date.now() }),
80655
80711
  "utf8"
@@ -80714,7 +80770,7 @@ init_identity2();
80714
80770
  // src/multi.ts
80715
80771
  init_dist();
80716
80772
  init_src5();
80717
- import { existsSync as existsSync32, readFileSync as readFileSync31, unlinkSync as unlinkSync3, writeFileSync as writeFileSync23 } from "node:fs";
80773
+ import { existsSync as existsSync32, readFileSync as readFileSync32, unlinkSync as unlinkSync3, writeFileSync as writeFileSync24 } from "node:fs";
80718
80774
  import { resolve as pathResolve } from "node:path";
80719
80775
 
80720
80776
  // src/principle-sync.ts
@@ -80743,8 +80799,8 @@ init_reconcile();
80743
80799
 
80744
80800
  // src/lockfile-auto.ts
80745
80801
  init_src();
80746
- import { existsSync as existsSync27, readFileSync as readFileSync26 } from "node:fs";
80747
- import { join as join31 } from "node:path";
80802
+ import { existsSync as existsSync27, readFileSync as readFileSync27 } from "node:fs";
80803
+ import { join as join32 } from "node:path";
80748
80804
 
80749
80805
  // src/package-index.ts
80750
80806
  init_src();
@@ -80893,11 +80949,11 @@ function runLockfilePass(opts) {
80893
80949
  { file: "package-lock.json", parse: parsePackageLockJson }
80894
80950
  ];
80895
80951
  for (const c of candidates) {
80896
- const p = join31(opts.root, c.file);
80952
+ const p = join32(opts.root, c.file);
80897
80953
  if (!existsSync27(p)) continue;
80898
80954
  let sbom;
80899
80955
  try {
80900
- sbom = c.parse(readFileSync26(p, "utf8"));
80956
+ sbom = c.parse(readFileSync27(p, "utf8"));
80901
80957
  } catch {
80902
80958
  continue;
80903
80959
  }
@@ -80953,9 +81009,12 @@ function noveltyAgainst(node2, neighbors, opts = {}) {
80953
81009
  };
80954
81010
  }
80955
81011
 
81012
+ // src/instance-ingest.ts
81013
+ init_profile2();
81014
+
80956
81015
  // src/public-symbols.ts
80957
- import { readFileSync as readFileSync27, readdirSync as readdirSync11, existsSync as existsSync28 } from "node:fs";
80958
- import { join as join32 } from "node:path";
81016
+ import { readFileSync as readFileSync28, readdirSync as readdirSync11, existsSync as existsSync28 } from "node:fs";
81017
+ import { join as join33 } from "node:path";
80959
81018
  var HEAD_BYTES = 8 * 1024;
80960
81019
  var INDEX_TTL_MS = 10 * 60 * 1e3;
80961
81020
  var MIN_SYMBOL_LEN = 4;
@@ -80988,20 +81047,20 @@ function bindingNames(clause) {
80988
81047
  function internalPackageNames(workspaceRoot) {
80989
81048
  const names = /* @__PURE__ */ new Set();
80990
81049
  const tryRead = (dir) => {
80991
- const pj = join32(dir, "package.json");
81050
+ const pj = join33(dir, "package.json");
80992
81051
  if (!existsSync28(pj)) return;
80993
81052
  try {
80994
- const name2 = JSON.parse(readFileSync27(pj, "utf8")).name;
81053
+ const name2 = JSON.parse(readFileSync28(pj, "utf8")).name;
80995
81054
  if (typeof name2 === "string" && name2.length > 0) names.add(name2);
80996
81055
  } catch {
80997
81056
  }
80998
81057
  };
80999
81058
  tryRead(workspaceRoot);
81000
81059
  for (const group of ["packages", "apps"]) {
81001
- const groupDir = join32(workspaceRoot, group);
81060
+ const groupDir = join33(workspaceRoot, group);
81002
81061
  if (!existsSync28(groupDir)) continue;
81003
81062
  try {
81004
- for (const entry of readdirSync11(groupDir)) tryRead(join32(groupDir, entry));
81063
+ for (const entry of readdirSync11(groupDir)) tryRead(join33(groupDir, entry));
81005
81064
  } catch {
81006
81065
  }
81007
81066
  }
@@ -81014,7 +81073,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
81014
81073
  if (cached2 && now - cached2.builtAt < INDEX_TTL_MS) return cached2;
81015
81074
  const readHead = deps.readHead ?? ((absPath) => {
81016
81075
  try {
81017
- return readFileSync27(absPath, "utf8").slice(0, HEAD_BYTES);
81076
+ return readFileSync28(absPath, "utf8").slice(0, HEAD_BYTES);
81018
81077
  } catch {
81019
81078
  return "";
81020
81079
  }
@@ -81034,7 +81093,7 @@ function publicSymbolIndex(store, workspaceRoot, deps = {}) {
81034
81093
  }
81035
81094
  const symbols = /* @__PURE__ */ new Set();
81036
81095
  for (const rel of files) {
81037
- const head2 = readHead(join32(workspaceRoot, rel));
81096
+ const head2 = readHead(join33(workspaceRoot, rel));
81038
81097
  if (!head2) continue;
81039
81098
  for (const re of [NAMED_IMPORT_RE, REQUIRE_RE]) {
81040
81099
  re.lastIndex = 0;
@@ -81752,7 +81811,7 @@ function cloudTargetDrift(daemon, shell2) {
81752
81811
  }
81753
81812
 
81754
81813
  // src/lock.ts
81755
- import { existsSync as existsSync29, readFileSync as readFileSync28 } from "node:fs";
81814
+ import { existsSync as existsSync29, readFileSync as readFileSync29 } from "node:fs";
81756
81815
  function daemonLockPayload(lock) {
81757
81816
  return JSON.stringify({
81758
81817
  pid: lock.pid,
@@ -81792,7 +81851,7 @@ function isProcessAlive(pid) {
81792
81851
  function readDaemonLock(lockPath) {
81793
81852
  if (!existsSync29(lockPath)) return null;
81794
81853
  try {
81795
- const lock = JSON.parse(readFileSync28(lockPath, "utf8"));
81854
+ const lock = JSON.parse(readFileSync29(lockPath, "utf8"));
81796
81855
  return typeof lock.pid === "number" ? lock : null;
81797
81856
  } catch {
81798
81857
  return null;
@@ -81972,6 +82031,7 @@ function liveCloudClient(src) {
81972
82031
  init_identity2();
81973
82032
 
81974
82033
  // src/project-link.ts
82034
+ init_profile2();
81975
82035
  async function ensureProjectLink(root, profile, client) {
81976
82036
  if (profile.projectLinkDisabled) return { linked: false, reason: "disabled" };
81977
82037
  const locator = profile.repoLocator;
@@ -81996,10 +82056,12 @@ async function ensureProjectLink(root, profile, client) {
81996
82056
 
81997
82057
  // src/project-hydrate.ts
81998
82058
  init_src11();
82059
+ init_profile2();
81999
82060
 
82000
82061
  // src/project-reanchor.ts
82001
82062
  init_src();
82002
82063
  init_src11();
82064
+ init_profile2();
82003
82065
  var DEFAULT_LIMIT = 50;
82004
82066
  var ANCHOR_SYMBOL_KINDS2 = [
82005
82067
  "Function",
@@ -82307,8 +82369,8 @@ async function hydrateProject(opts) {
82307
82369
  init_src7();
82308
82370
  init_src();
82309
82371
  import { execFile as execFile3 } from "node:child_process";
82310
- import { readFileSync as readFileSync30 } from "node:fs";
82311
- import { join as join34 } from "node:path";
82372
+ import { readFileSync as readFileSync31 } from "node:fs";
82373
+ import { join as join35 } from "node:path";
82312
82374
  import { promisify } from "node:util";
82313
82375
 
82314
82376
  // src/history-walk.ts
@@ -82530,8 +82592,8 @@ function narrative(unit, group) {
82530
82592
 
82531
82593
  // src/history-bundle.ts
82532
82594
  import { execFile as execFile2 } from "node:child_process";
82533
- import { readFileSync as readFileSync29 } from "node:fs";
82534
- import { join as join33 } from "node:path";
82595
+ import { readFileSync as readFileSync30 } from "node:fs";
82596
+ import { join as join34 } from "node:path";
82535
82597
 
82536
82598
  // ../../packages/privacy/src/patterns/credentials.ts
82537
82599
  var CREDENTIAL_PATTERNS = [
@@ -83313,7 +83375,7 @@ function pathAllowedByFloor(path2) {
83313
83375
  function loadRepoIgnore(root, extraPatterns = []) {
83314
83376
  let source = "";
83315
83377
  try {
83316
- source = readFileSync29(join33(root, ".errataignore"), "utf8");
83378
+ source = readFileSync30(join34(root, ".errataignore"), "utf8");
83317
83379
  } catch {
83318
83380
  source = "";
83319
83381
  }
@@ -83715,6 +83777,7 @@ async function buildUnitBundle(root, unit, opts = {}) {
83715
83777
  }
83716
83778
 
83717
83779
  // src/project-history.ts
83780
+ init_profile2();
83718
83781
  var execFileAsync = promisify(execFile3);
83719
83782
  var HISTORY_EXTRACTOR_VERSION = "history-1";
83720
83783
  var LEASE_POLL_MS = 2e4;
@@ -83727,7 +83790,7 @@ async function defaultGit(root, args2) {
83727
83790
  function readIgnoreLines(root, profile) {
83728
83791
  let lines = [];
83729
83792
  try {
83730
- lines = readFileSync30(join34(root, ".errataignore"), "utf8").split("\n");
83793
+ lines = readFileSync31(join35(root, ".errataignore"), "utf8").split("\n");
83731
83794
  } catch {
83732
83795
  }
83733
83796
  return [...lines, ...profile.ignoreExtra ?? []].map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
@@ -84056,8 +84119,8 @@ async function startHistoryStage(root, input, client, walk10 = {}) {
84056
84119
  init_cloud_auth();
84057
84120
  import { createHash as createHash15 } from "node:crypto";
84058
84121
  import { execFileSync as execFileSync5 } from "node:child_process";
84059
- import { existsSync as existsSync30, writeFileSync as writeFileSync22 } from "node:fs";
84060
- import { join as join35 } from "node:path";
84122
+ import { existsSync as existsSync30, writeFileSync as writeFileSync23 } from "node:fs";
84123
+ import { join as join36 } from "node:path";
84061
84124
 
84062
84125
  // src/device-poll.ts
84063
84126
  var THROTTLED_POLL_MIN_WAIT_MS = 11e3;
@@ -84455,18 +84518,16 @@ fixtures/
84455
84518
  *.sql.gz
84456
84519
  `;
84457
84520
  function applyConsents(profile, config2, c, decidedAt, now = Date.now) {
84458
- const nextConfig = {
84459
- ...config2,
84460
- consent: {
84461
- ...config2.consent,
84462
- sync: c.sync !== "off",
84463
- telemetry: c.telemetry,
84464
- contributePackages: c.packages && c.sync !== "off"
84465
- },
84466
- onboardedAt: config2.onboardedAt ?? now()
84521
+ const nextConfig = { ...config2, onboardedAt: config2.onboardedAt ?? now() };
84522
+ const consoleConsents = {
84523
+ sync: c.sync !== "off",
84524
+ telemetry: c.telemetry,
84525
+ contributePackages: c.packages && c.sync !== "off",
84526
+ decidedAt
84467
84527
  };
84468
84528
  const nextProfile = {
84469
84529
  ...profile,
84530
+ consoleConsents,
84470
84531
  syncConsent: c.sync === "automatic" ? "automatic" : c.sync === "ask" ? "ask-each-time" : "disabled",
84471
84532
  linkConsents: {
84472
84533
  structure: c.structure,
@@ -84476,7 +84537,8 @@ function applyConsents(profile, config2, c, decidedAt, now = Date.now) {
84476
84537
  }
84477
84538
  };
84478
84539
  const prev = profile.linkConsents;
84479
- const changed = profile.syncConsent !== nextProfile.syncConsent || config2.consent.sync !== nextConfig.consent.sync || config2.consent.telemetry !== nextConfig.consent.telemetry || config2.consent.contributePackages !== nextConfig.consent.contributePackages || !prev || prev.structure !== nextProfile.linkConsents.structure || prev.mineHistory !== nextProfile.linkConsents.mineHistory || prev.contributeHistory !== nextProfile.linkConsents.contributeHistory;
84540
+ const prevConsole = profile.consoleConsents;
84541
+ const changed = profile.syncConsent !== nextProfile.syncConsent || prevConsole?.sync !== consoleConsents.sync || prevConsole?.telemetry !== consoleConsents.telemetry || prevConsole?.contributePackages !== consoleConsents.contributePackages || !prev || prev.structure !== nextProfile.linkConsents.structure || prev.mineHistory !== nextProfile.linkConsents.mineHistory || prev.contributeHistory !== nextProfile.linkConsents.contributeHistory;
84480
84542
  return { profile: nextProfile, config: nextConfig, changed };
84481
84543
  }
84482
84544
  function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
@@ -84490,9 +84552,9 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
84490
84552
  delete nextProfile.projectLinkDisabled;
84491
84553
  let wroteIgnore = false;
84492
84554
  if (decision.writeIgnoreStarter !== false) {
84493
- const target = join35(root, ".errataignore");
84555
+ const target = join36(root, ".errataignore");
84494
84556
  if (!existsSync30(target)) {
84495
- writeFileSync22(target, IGNORE_STARTER, "utf8");
84557
+ writeFileSync23(target, IGNORE_STARTER, "utf8");
84496
84558
  wroteIgnore = true;
84497
84559
  }
84498
84560
  }
@@ -84500,16 +84562,17 @@ function applyLinkDecision(root, profile, config2, decision, now = Date.now) {
84500
84562
  }
84501
84563
 
84502
84564
  // src/multi.ts
84565
+ init_consent();
84503
84566
  init_registry();
84504
84567
 
84505
84568
  // src/adopt.ts
84506
84569
  init_git_remote();
84507
84570
  import { existsSync as existsSync31 } from "node:fs";
84508
- import { dirname as dirname12, join as join36 } from "node:path";
84571
+ import { dirname as dirname12, join as join37 } from "node:path";
84509
84572
  function findGitRoot(absPath) {
84510
84573
  let dir = absPath;
84511
84574
  for (let depth = 0; depth < 64; depth++) {
84512
- if (existsSync31(join36(dir, ".git"))) return dir;
84575
+ if (existsSync31(join37(dir, ".git"))) return dir;
84513
84576
  const parent = dirname12(dir);
84514
84577
  if (parent === dir) return null;
84515
84578
  dir = parent;
@@ -84696,6 +84759,9 @@ function codexWakeCandidates(input) {
84696
84759
  return out2;
84697
84760
  }
84698
84761
 
84762
+ // src/multi.ts
84763
+ init_profile2();
84764
+
84699
84765
  // src/hook-route.ts
84700
84766
  function msysToWindowsPath(p, platform = process.platform) {
84701
84767
  if (platform !== "win32") return p;
@@ -85124,7 +85190,7 @@ async function startMultiDaemon(opts = {}) {
85124
85190
  records.push(rec);
85125
85191
  void ambientLinkAll();
85126
85192
  try {
85127
- writeFileSync23(
85193
+ writeFileSync24(
85128
85194
  rec.engine.paths.daemonLock,
85129
85195
  daemonLockPayload({
85130
85196
  pid: process.pid,
@@ -85443,7 +85509,7 @@ async function startMultiDaemon(opts = {}) {
85443
85509
  baseUrl = `http://127.0.0.1:${port}`;
85444
85510
  try {
85445
85511
  ensureDir(globalDir());
85446
- writeFileSync23(
85512
+ writeFileSync24(
85447
85513
  lockPath,
85448
85514
  daemonLockPayload({ pid: process.pid, webUiUrl: baseUrl, processStartedAt: PROCESS_STARTED_AT, entry: SELF_ENTRY, version: DAEMON_VERSION }),
85449
85515
  "utf8"
@@ -85452,7 +85518,7 @@ async function startMultiDaemon(opts = {}) {
85452
85518
  }
85453
85519
  for (const r of records) {
85454
85520
  try {
85455
- writeFileSync23(
85521
+ writeFileSync24(
85456
85522
  r.engine.paths.daemonLock,
85457
85523
  daemonLockPayload({
85458
85524
  pid: process.pid,
@@ -85512,11 +85578,11 @@ async function startMultiDaemon(opts = {}) {
85512
85578
  const ANCHOR_PULL_INTERVAL_MS = 10 * 60 * 1e3;
85513
85579
  const anchorPullAll = async () => {
85514
85580
  const c = loadConfig();
85515
- if (!c.consent.sync || !hasCloudCredential(c)) return;
85581
+ if (!hasCloudCredential(c)) return;
85516
85582
  const client = cloudNow();
85517
85583
  for (const r of records) {
85518
85584
  const projectId = r.engine.profile.projectId;
85519
- if (!projectId) continue;
85585
+ if (!projectId || !effectiveConsent(c, r.engine.profile).sync) continue;
85520
85586
  try {
85521
85587
  const { salt } = await resolveProjectSymbolSalt(client, projectId);
85522
85588
  await pullProjectAnchors(r, client, salt);
@@ -85530,9 +85596,10 @@ async function startMultiDaemon(opts = {}) {
85530
85596
  }, ANCHOR_PULL_INTERVAL_MS);
85531
85597
  const ambientLinkAll = async () => {
85532
85598
  const c = loadConfig();
85533
- if (!c.consent.sync || !hasCloudCredential(c)) return;
85599
+ if (!hasCloudCredential(c)) return;
85534
85600
  const client = cloudNow();
85535
85601
  for (const r of records) {
85602
+ if (!effectiveConsent(c, r.engine.profile).sync) continue;
85536
85603
  const out2 = await ensureProjectLink(r.root, r.engine.profile, client);
85537
85604
  if (out2.linked) {
85538
85605
  console.log(
@@ -85599,14 +85666,14 @@ async function startMultiDaemon(opts = {}) {
85599
85666
  };
85600
85667
  void startHistoryStage(root, engine.profile, client, {
85601
85668
  anchors: { index: anchorIndex, salt },
85602
- // PS-web projects: the console's consents (Privacy tab) win over
85603
- // the profile's memory; applied to config and profile here, with
85669
+ // PS-web projects: the console's consents (Privacy tab) are this
85670
+ // project's, applied to ITS profile only (DC-consent-scope), with
85604
85671
  // the change printed so a flipped switch is visible in the log.
85605
85672
  applyConsents: (p, consents) => {
85606
85673
  const cfg2 = loadConfig();
85607
85674
  const applied = applyConsents(p, cfg2, consents, (/* @__PURE__ */ new Date()).toISOString());
85608
85675
  if (applied.changed) {
85609
- saveConfig(applied.config);
85676
+ if (applied.config.onboardedAt !== cfg2.onboardedAt) saveConfig(applied.config);
85610
85677
  Object.assign(engine.profile, applied.profile);
85611
85678
  saveProfile(root, engine.profile);
85612
85679
  console.log(
@@ -85888,7 +85955,7 @@ async function startMultiDaemon(opts = {}) {
85888
85955
  const ignore2 = loadClaimIgnorePatterns(globalDir());
85889
85956
  const primaryLanguage = machineDominantLanguage();
85890
85957
  const languages = records.flatMap((r) => r.engine.profile.languages ?? []);
85891
- const packages = cfg2.consent.contributePackages ? records.flatMap(
85958
+ const packages = cfg2.consent.contributePackages ? records.filter((r) => effectiveConsent(cfg2, r.engine.profile).contributePackages).flatMap(
85892
85959
  (r) => r.engine.store.findNodesByLabel("Package").map((p) => ({
85893
85960
  name: String(p.attrs["name"] ?? ""),
85894
85961
  purl: String(p.attrs["purl"] ?? p.id)
@@ -85907,7 +85974,9 @@ async function startMultiDaemon(opts = {}) {
85907
85974
  },
85908
85975
  async syncInstancesPublic() {
85909
85976
  const cfg2 = loadConfig();
85910
- if (!cfg2.consent.sync) return { uploaded: 0, skipped: "consent-off" };
85977
+ if (!records.some((r) => effectiveConsent(cfg2, r.engine.profile).sync)) {
85978
+ return { uploaded: 0, skipped: "consent-off" };
85979
+ }
85911
85980
  if (registryCorrupt()) {
85912
85981
  const msg = "workspace registry unreadable \u2014 holding ALL per-workspace cloud push (bindings unprovable; fail-closed)";
85913
85982
  console.error(`[identity] ${msg}`);
@@ -85983,6 +86052,8 @@ async function startMultiDaemon(opts = {}) {
85983
86052
  }
85984
86053
  };
85985
86054
  for (const r of records) {
86055
+ const recordConsent = effectiveConsent(cfg2, r.engine.profile);
86056
+ if (!recordConsent.sync) continue;
85986
86057
  const recordIdentity = identityFor(liveWorkspaceEntry(r.entry));
85987
86058
  if (recordIdentity.invalid) {
85988
86059
  noteIdentityBlock(r.id, r.entry.name, recordIdentity);
@@ -86018,7 +86089,7 @@ async function startMultiDaemon(opts = {}) {
86018
86089
  profile: r.engine.profile,
86019
86090
  daemonVersion: DAEMON_VERSION,
86020
86091
  ignorePatterns: [...ignore2],
86021
- includePackages: cfg2.consent.contributePackages
86092
+ includePackages: recordConsent.contributePackages
86022
86093
  });
86023
86094
  if (context) {
86024
86095
  await lane("context", projectName, async () => {
@@ -86049,7 +86120,7 @@ async function startMultiDaemon(opts = {}) {
86049
86120
  profile: r.engine.profile,
86050
86121
  daemonVersion: DAEMON_VERSION,
86051
86122
  ignorePatterns: [...ignore2],
86052
- includePackages: cfg2.consent.contributePackages,
86123
+ includePackages: recordConsent.contributePackages,
86053
86124
  workspaceRoot: r.root,
86054
86125
  ...project ? { project } : {}
86055
86126
  });
@@ -86317,7 +86388,7 @@ async function startMultiDaemon(opts = {}) {
86317
86388
  clearInterval(anchorPull);
86318
86389
  clearTimeout(codexWakeBoot);
86319
86390
  try {
86320
- const cur = readFileSync31(lockPath, "utf8");
86391
+ const cur = readFileSync32(lockPath, "utf8");
86321
86392
  if (JSON.parse(cur).pid === process.pid) unlinkSync3(lockPath);
86322
86393
  } catch {
86323
86394
  }
@@ -86365,6 +86436,8 @@ async function startMultiDaemon(opts = {}) {
86365
86436
 
86366
86437
  // src/cli.ts
86367
86438
  init_src5();
86439
+ init_profile2();
86440
+ init_consent();
86368
86441
  init_git_remote();
86369
86442
  init_config();
86370
86443
  init_src7();
@@ -86940,9 +87013,9 @@ function buildCodexHooksToml(port, options) {
86940
87013
  }
86941
87014
 
86942
87015
  // src/codex-hooks.ts
86943
- import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync32, writeFileSync as writeFileSync24 } from "node:fs";
87016
+ import { existsSync as existsSync33, mkdirSync as mkdirSync9, readFileSync as readFileSync33, writeFileSync as writeFileSync25 } from "node:fs";
86944
87017
  import { homedir as homedir7 } from "node:os";
86945
- import { join as join37 } from "node:path";
87018
+ import { join as join38 } from "node:path";
86946
87019
 
86947
87020
  // src/codex-hook-relay.ts
86948
87021
  var CODEX_RELAY_SOURCE = String.raw`// errata-managed: regenerated by errata install-hooks codex
@@ -86982,8 +87055,8 @@ try {
86982
87055
  `;
86983
87056
 
86984
87057
  // src/codex-hooks.ts
86985
- function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join37(homedir7(), ".codex")) {
86986
- return existsSync33(join37(root, ".codex")) || existsSync33(codexHome);
87058
+ function hasCodexConfig(root, codexHome = process.env["CODEX_HOME"] || join38(homedir7(), ".codex")) {
87059
+ return existsSync33(join38(root, ".codex")) || existsSync33(codexHome);
86987
87060
  }
86988
87061
  function replaceCodexHooks(existing, block) {
86989
87062
  const begin = existing.indexOf(CODEX_HOOKS_BEGIN);
@@ -86999,14 +87072,14 @@ function replaceCodexHooks(existing, block) {
86999
87072
  return existing.trimEnd() + (existing.trim() ? "\n\n" : "") + block;
87000
87073
  }
87001
87074
  function writeCodexHooks(root, port, nodePath = process.execPath) {
87002
- const dir = join37(root, ".codex");
87003
- const file2 = join37(dir, "config.toml");
87004
- const relay = join37(dir, "hooks", "errata-relay.mjs");
87075
+ const dir = join38(root, ".codex");
87076
+ const file2 = join38(dir, "config.toml");
87077
+ const relay = join38(dir, "hooks", "errata-relay.mjs");
87005
87078
  const block = buildCodexHooksToml(port, { nodePath, relayPath: relay });
87006
- const final = replaceCodexHooks(existsSync33(file2) ? readFileSync32(file2, "utf8") : "", block);
87007
- mkdirSync9(join37(dir, "hooks"), { recursive: true });
87008
- writeFileSync24(relay, CODEX_RELAY_SOURCE, "utf8");
87009
- writeFileSync24(file2, final, "utf8");
87079
+ const final = replaceCodexHooks(existsSync33(file2) ? readFileSync33(file2, "utf8") : "", block);
87080
+ mkdirSync9(join38(dir, "hooks"), { recursive: true });
87081
+ writeFileSync25(relay, CODEX_RELAY_SOURCE, "utf8");
87082
+ writeFileSync25(file2, final, "utf8");
87010
87083
  return file2;
87011
87084
  }
87012
87085
 
@@ -87416,13 +87489,13 @@ async function cmdInit() {
87416
87489
  console.log("");
87417
87490
  console.log("installing harness hooks...");
87418
87491
  const { existsSync: existsSync35 } = await import("node:fs");
87419
- const { join: join39 } = await import("node:path");
87492
+ const { join: join40 } = await import("node:path");
87420
87493
  try {
87421
87494
  await installClaudeHooks(port);
87422
87495
  } catch (err2) {
87423
87496
  console.warn(` \u26A0\uFE0F Claude hook install failed: ${err2 instanceof Error ? err2.message : err2}`);
87424
87497
  }
87425
- if (existsSync35(join39(ROOT, ".cursor"))) {
87498
+ if (existsSync35(join40(ROOT, ".cursor"))) {
87426
87499
  try {
87427
87500
  await installCursorMcpConfig();
87428
87501
  } catch (err2) {
@@ -87707,8 +87780,14 @@ async function cmdStatus() {
87707
87780
  );
87708
87781
  const cs = cfg.consent;
87709
87782
  console.log(
87710
- ` consent: sync ${cs.sync ? "on" : "off"} \xB7 telemetry ${cs.telemetry ? "on" : "off"} \xB7 packages ${cs.contributePackages ? "on" : "off"}`
87783
+ ` consent: sync ${cs.sync ? "on" : "off"} \xB7 telemetry ${cs.telemetry ? "on" : "off"} \xB7 packages ${cs.contributePackages ? "on" : "off"} (machine default)`
87711
87784
  );
87785
+ const pc = profile?.consoleConsents;
87786
+ if (pc) {
87787
+ console.log(
87788
+ ` this project (console): sync ${pc.sync ? "on" : "off"} \xB7 telemetry ${pc.telemetry ? "on" : "off"} \xB7 packages ${pc.contributePackages ? "on" : "off"}`
87789
+ );
87790
+ }
87712
87791
  console.log(` cloud:`);
87713
87792
  console.log(` url: ${cfg.cloudUrl}`);
87714
87793
  if (daemonCloud) {
@@ -88157,12 +88236,11 @@ async function cmdLoginOAuthDevice(cfg, input) {
88157
88236
  }
88158
88237
  }
88159
88238
  async function linkRegisteredWorkspaces(cfg) {
88160
- if (!cfg.consent.sync) return;
88161
88239
  const client = authedCloudClient(cfg);
88162
88240
  for (const w of listWorkspaces()) {
88163
88241
  try {
88164
88242
  const profile = loadProfile(w.path);
88165
- if (!profile) continue;
88243
+ if (!profile || !effectiveConsent(cfg, profile).sync) continue;
88166
88244
  refreshRepoLocator(w.path, profile);
88167
88245
  const out2 = await ensureProjectLink(w.path, profile, client);
88168
88246
  if (out2.linked) {
@@ -88247,7 +88325,7 @@ async function cmdLink(args2) {
88247
88325
  `linked${d.existed ? "" : " (created)"}: ${d.locator} \u2192 project ${d.projectId} \xB7 ${where} \xB7 ${d.visibility} \xB7 grant v${d.grantVersion}`
88248
88326
  );
88249
88327
  console.log(
88250
- `consents: sync=${d.consents.sync} telemetry=${d.consents.telemetry ? "on" : "off"} packages=${applied.config.consent.contributePackages ? "on" : "off"} structure=${d.consents.structure ? "on" : "off"} history=${d.consents.mineHistory ? applied.profile.linkConsents?.contributeHistory ? "mine+contribute" : "mine" : "off"}`
88328
+ `consents (this project): sync=${d.consents.sync} telemetry=${d.consents.telemetry ? "on" : "off"} packages=${applied.profile.consoleConsents?.contributePackages ? "on" : "off"} structure=${d.consents.structure ? "on" : "off"} history=${d.consents.mineHistory ? applied.profile.linkConsents?.contributeHistory ? "mine+contribute" : "mine" : "off"}`
88251
88329
  );
88252
88330
  await refreshLinkedCodexHooks(args2);
88253
88331
  if (applied.wroteIgnore) console.log("wrote .errataignore (starter) \u2014 edit it; it is your hard control");
@@ -88520,7 +88598,7 @@ async function cmdReview() {
88520
88598
  console.log("(review queue empty)");
88521
88599
  return;
88522
88600
  }
88523
- const queue = JSON.parse(readFileSync33(paths.reviewQueue, "utf8"));
88601
+ const queue = JSON.parse(readFileSync34(paths.reviewQueue, "utf8"));
88524
88602
  if (queue.length === 0) {
88525
88603
  console.log("(review queue empty)");
88526
88604
  return;
@@ -89230,7 +89308,7 @@ async function gatherReportData(generatedAt) {
89230
89308
  };
89231
89309
  }
89232
89310
  async function cmdReport(args2) {
89233
- const { mkdirSync: mkdirSync10, writeFileSync: writeFileSync25 } = await import("node:fs");
89311
+ const { mkdirSync: mkdirSync10, writeFileSync: writeFileSync26 } = await import("node:fs");
89234
89312
  const { renderReport: renderReport2 } = await Promise.resolve().then(() => (init_report_render(), report_render_exports));
89235
89313
  const includeFutureVerbs = args2.includes("--future-verbs");
89236
89314
  const now = /* @__PURE__ */ new Date();
@@ -89243,8 +89321,8 @@ async function cmdReport(args2) {
89243
89321
  const outDir = workspacePaths(ROOT).configDir;
89244
89322
  mkdirSync10(outDir, { recursive: true });
89245
89323
  const files = renderReport2(data, { includeFutureVerbs });
89246
- for (const f of files) writeFileSync25(join38(outDir, f.name), f.html, "utf8");
89247
- const indexPath = join38(outDir, "report.html");
89324
+ for (const f of files) writeFileSync26(join39(outDir, f.name), f.html, "utf8");
89325
+ const indexPath = join39(outDir, "report.html");
89248
89326
  console.log(`report \u2192 ${indexPath}`);
89249
89327
  console.log(
89250
89328
  ` ${data.repos.length} repo(s) \xB7 ${files.length} file(s) \xB7 ${data.rollup.nodes.toLocaleString("en-US")} nodes`
@@ -89364,24 +89442,24 @@ async function cmdInstallHooks(args2) {
89364
89442
  }
89365
89443
  }
89366
89444
  async function installOpencodePlugin(port) {
89367
- const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
89368
- const { join: join39 } = await import("node:path");
89369
- const dir = join39(ROOT, ".opencode", "plugin");
89445
+ const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync35, writeFileSync: writeFileSync26 } = await import("node:fs");
89446
+ const { join: join40 } = await import("node:path");
89447
+ const dir = join40(ROOT, ".opencode", "plugin");
89370
89448
  if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
89371
- const file2 = join39(dir, "inerrata.js");
89449
+ const file2 = join40(dir, "inerrata.js");
89372
89450
  if (existsSync35(file2)) {
89373
- const head2 = readFileSync34(file2, "utf8").split("\n")[0] ?? "";
89451
+ const head2 = readFileSync35(file2, "utf8").split("\n")[0] ?? "";
89374
89452
  if (head2.trim() !== OPENCODE_PLUGIN_MARKER) {
89375
89453
  console.error(`refusing to overwrite ${file2}: not an errata-managed plugin (line 1 lacks the marker)`);
89376
89454
  process.exit(2);
89377
89455
  }
89378
89456
  }
89379
- writeFileSync25(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
89380
- const cfgFile = join39(ROOT, "opencode.json");
89457
+ writeFileSync26(file2, buildOpencodePluginSource(port, { version: DAEMON_VERSION }), "utf8");
89458
+ const cfgFile = join40(ROOT, "opencode.json");
89381
89459
  let cfg = { $schema: "https://opencode.ai/config.json" };
89382
89460
  if (existsSync35(cfgFile)) {
89383
89461
  try {
89384
- cfg = JSON.parse(readFileSync34(cfgFile, "utf8"));
89462
+ cfg = JSON.parse(readFileSync35(cfgFile, "utf8"));
89385
89463
  } catch {
89386
89464
  console.error(`refusing to touch invalid JSON at ${cfgFile} \u2014 fix it and re-run`);
89387
89465
  process.exit(2);
@@ -89392,7 +89470,7 @@ async function installOpencodePlugin(port) {
89392
89470
  if (!hadErrata) {
89393
89471
  const inv = errataMcpInvocation();
89394
89472
  cfg.mcp["errata"] = { type: "local", command: [inv.command, ...inv.args] };
89395
- writeFileSync25(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
89473
+ writeFileSync26(cfgFile, JSON.stringify(cfg, null, 2) + "\n", "utf8");
89396
89474
  }
89397
89475
  console.log(`installed OpenCode plugin \u2192 ${file2}`);
89398
89476
  if (hadErrata) console.log(` mcp.errata already present in ${cfgFile} \u2014 left untouched`);
@@ -89412,15 +89490,15 @@ function errataMcpInvocation() {
89412
89490
  return { command: cmd2, args: args2 };
89413
89491
  }
89414
89492
  async function installClaudeHooks(port) {
89415
- const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
89416
- const { join: join39 } = await import("node:path");
89417
- const dir = join39(ROOT, ".claude");
89493
+ const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync35, writeFileSync: writeFileSync26 } = await import("node:fs");
89494
+ const { join: join40 } = await import("node:path");
89495
+ const dir = join40(ROOT, ".claude");
89418
89496
  if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
89419
- const file2 = join39(dir, "settings.json");
89497
+ const file2 = join40(dir, "settings.json");
89420
89498
  let settings = {};
89421
89499
  if (existsSync35(file2)) {
89422
89500
  try {
89423
- settings = JSON.parse(readFileSync34(file2, "utf8"));
89501
+ settings = JSON.parse(readFileSync35(file2, "utf8"));
89424
89502
  } catch {
89425
89503
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
89426
89504
  process.exit(2);
@@ -89466,10 +89544,10 @@ async function installClaudeHooks(port) {
89466
89544
  dropErrata(list);
89467
89545
  list.push({ hooks: [{ type: "command", command: injectCmd }] });
89468
89546
  }
89469
- writeFileSync25(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
89547
+ writeFileSync26(file2, JSON.stringify(settings, null, 2) + "\n", "utf8");
89470
89548
  console.log(`installed Claude Code hooks \u2192 ${file2}`);
89471
89549
  await installClaudeMcpConfig();
89472
- const claudeMd = join39(ROOT, "CLAUDE.md");
89550
+ const claudeMd = join40(ROOT, "CLAUDE.md");
89473
89551
  const recall = writeManagedBlock(claudeMd, { body: RECALL_FIRST_BLOCK });
89474
89552
  if (recall.kind === "collision") {
89475
89553
  console.warn(
@@ -89481,15 +89559,15 @@ async function installClaudeHooks(port) {
89481
89559
  console.log(` endpoint: http://127.0.0.1:${port}/api/hook`);
89482
89560
  }
89483
89561
  async function installClaudeMcpConfig() {
89484
- const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
89485
- const { join: join39, dirname: dirname13 } = await import("node:path");
89486
- const file2 = join39(ROOT, ".mcp.json");
89562
+ const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync35, writeFileSync: writeFileSync26 } = await import("node:fs");
89563
+ const { join: join40, dirname: dirname13 } = await import("node:path");
89564
+ const file2 = join40(ROOT, ".mcp.json");
89487
89565
  const dir = dirname13(file2);
89488
89566
  if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
89489
89567
  let cfg = {};
89490
89568
  if (existsSync35(file2)) {
89491
89569
  try {
89492
- cfg = JSON.parse(readFileSync34(file2, "utf8"));
89570
+ cfg = JSON.parse(readFileSync35(file2, "utf8"));
89493
89571
  } catch {
89494
89572
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
89495
89573
  process.exit(2);
@@ -89497,21 +89575,21 @@ async function installClaudeMcpConfig() {
89497
89575
  }
89498
89576
  cfg.mcpServers ??= {};
89499
89577
  cfg.mcpServers["errata"] = errataMcpInvocation();
89500
- writeFileSync25(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
89578
+ writeFileSync26(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
89501
89579
  console.log(`installed Claude Code MCP server config \u2192 ${file2}`);
89502
89580
  console.log(` Claude Code will spawn \`errata mcp\` on workspace open.`);
89503
89581
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses / show / similar`);
89504
89582
  }
89505
89583
  async function installCursorMcpConfig() {
89506
- const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync34, writeFileSync: writeFileSync25 } = await import("node:fs");
89507
- const { join: join39 } = await import("node:path");
89508
- const dir = join39(ROOT, ".cursor");
89584
+ const { mkdirSync: mkdirSync10, existsSync: existsSync35, readFileSync: readFileSync35, writeFileSync: writeFileSync26 } = await import("node:fs");
89585
+ const { join: join40 } = await import("node:path");
89586
+ const dir = join40(ROOT, ".cursor");
89509
89587
  if (!existsSync35(dir)) mkdirSync10(dir, { recursive: true });
89510
- const file2 = join39(dir, "mcp.json");
89588
+ const file2 = join40(dir, "mcp.json");
89511
89589
  let cfg = {};
89512
89590
  if (existsSync35(file2)) {
89513
89591
  try {
89514
- cfg = JSON.parse(readFileSync34(file2, "utf8"));
89592
+ cfg = JSON.parse(readFileSync35(file2, "utf8"));
89515
89593
  } catch {
89516
89594
  console.error(`refusing to overwrite invalid JSON at ${file2}`);
89517
89595
  process.exit(2);
@@ -89519,7 +89597,7 @@ async function installCursorMcpConfig() {
89519
89597
  }
89520
89598
  cfg.mcpServers ??= {};
89521
89599
  cfg.mcpServers["errata"] = errataMcpInvocation();
89522
- writeFileSync25(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
89600
+ writeFileSync26(file2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
89523
89601
  console.log(`installed Cursor MCP server config \u2192 ${file2}`);
89524
89602
  console.log(` Cursor will spawn \`errata mcp\` on workspace open.`);
89525
89603
  console.log(` Tools: errata.search / locate / neighbors / callers_of / what_uses`);
@@ -89871,7 +89949,7 @@ async function cmdDash(args2) {
89871
89949
  await yieldToLoop2();
89872
89950
  try {
89873
89951
  const items = selectDurableMemory(handle2.sharedStore, r.engine.profile);
89874
- const res = bleedRules(join38(r.root, ".claude", "rules"), items);
89952
+ const res = bleedRules(join39(r.root, ".claude", "rules"), items);
89875
89953
  if (res.written || res.pruned) {
89876
89954
  console.log(
89877
89955
  `[rules:${r.entry.name}] ${res.written} collective principle(s) \u2192 .claude/rules` + (res.pruned ? `, ${res.pruned} pruned` : "")