arcane-cli 1.12.0 → 1.12.1

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.
package/dist/index.js CHANGED
@@ -6,11 +6,11 @@ const require = __createRequire(import.meta.url);
6
6
  import { Command } from "commander";
7
7
  import { createRequire as createRequire3 } from "module";
8
8
  import { fileURLToPath } from "url";
9
- import { dirname as dirname12, join as join22 } from "path";
9
+ import { dirname as dirname13, join as join23 } from "path";
10
10
 
11
11
  // src/commands/init.ts
12
12
  import { select as select3, confirm as confirm2, input as input3 } from "@inquirer/prompts";
13
- import { dirname as dirname4, join as join7 } from "path";
13
+ import { dirname as dirname5, join as join8 } from "path";
14
14
  import chalk2 from "chalk";
15
15
 
16
16
  // src/modules/copier.ts
@@ -1417,7 +1417,7 @@ var WORDMARK = [
1417
1417
  var INDENT = " ";
1418
1418
  var LOCKUP_WIDTH = INDENT.length + Math.max(...WORDMARK.map((l) => l.length));
1419
1419
  function sleep(ms) {
1420
- return new Promise((resolve5) => setTimeout(resolve5, ms));
1420
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
1421
1421
  }
1422
1422
  function isAnimatable() {
1423
1423
  return !!process.stdout.isTTY && process.env["TERM"] !== "dumb" && process.env["CI"] !== "true" && process.env["ARCANE_DISABLE_ANIMATION"] !== "true" && (process.stdout.columns ?? 80) >= LOCKUP_WIDTH;
@@ -2849,7 +2849,7 @@ function buildGitEnv() {
2849
2849
  function runGit(cwd, args, options = {}) {
2850
2850
  const commandClass = options.commandClass ?? classifyGitCommand(args);
2851
2851
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUTS_MS[commandClass] ?? DEFAULT_TIMEOUTS_MS.write;
2852
- return new Promise((resolve5, reject) => {
2852
+ return new Promise((resolve6, reject) => {
2853
2853
  const child = execFile(
2854
2854
  "git",
2855
2855
  args,
@@ -2883,7 +2883,7 @@ function runGit(cwd, args, options = {}) {
2883
2883
  reject(error);
2884
2884
  return;
2885
2885
  }
2886
- resolve5({ stdout, stderr });
2886
+ resolve6({ stdout, stderr });
2887
2887
  }
2888
2888
  );
2889
2889
  child.stdin?.end();
@@ -3336,7 +3336,27 @@ async function offerRegistryScaffold(targetDir, businessRoot) {
3336
3336
  // src/modules/push-safety.ts
3337
3337
  import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile8, chmod, access as access3, rm as rm4, readdir as readdir6 } from "fs/promises";
3338
3338
  import { constants } from "fs";
3339
- import { join as join6, resolve as resolve2, dirname as dirname3, basename } from "path";
3339
+ import { join as join7, resolve as resolve3, dirname as dirname4, basename as basename2 } from "path";
3340
+
3341
+ // src/modules/real-path.ts
3342
+ import { realpathSync } from "fs";
3343
+ import { basename, dirname as dirname3, join as join6, resolve as resolve2 } from "path";
3344
+ function resolveRealPath(path4) {
3345
+ const missing = [];
3346
+ let existing = path4;
3347
+ for (; ; ) {
3348
+ try {
3349
+ return join6(realpathSync.native(existing), ...missing);
3350
+ } catch {
3351
+ const parent = dirname3(existing);
3352
+ if (parent === existing) return resolve2(path4);
3353
+ missing.unshift(basename(existing));
3354
+ existing = parent;
3355
+ }
3356
+ }
3357
+ }
3358
+
3359
+ // src/modules/push-safety.ts
3340
3360
  var DISABLED_PUSH_URL = "arcane-push-blocked-run-spell-unblock-push://this-repository";
3341
3361
  var NO_PUSH_URL_MARKER = (remote) => `remote.${remote}.arcaneHadNoPushUrl`;
3342
3362
  var ARCANE_HOOKS_DIR = ".arcane/hooks";
@@ -3365,10 +3385,12 @@ function isArcaneHooksPath(root, value) {
3365
3385
  const windows = process.platform === "win32";
3366
3386
  const normalize = (p) => {
3367
3387
  const separated = windows ? p.replace(/\\/g, "/") : p;
3368
- const absolute = resolve2(root, separated).replace(/\\/g, "/").replace(/\/+$/, "");
3388
+ const resolved = resolve3(root, separated);
3389
+ const absolute = (windows ? resolved.replace(/\\/g, "/") : resolved).replace(/\/+$/, "");
3369
3390
  return windows ? absolute.toLowerCase() : absolute;
3370
3391
  };
3371
- return normalize(value) === normalize(ARCANE_HOOKS_DIR);
3392
+ if (normalize(value) === normalize(ARCANE_HOOKS_DIR)) return true;
3393
+ return normalize(resolveRealPath(resolve3(root, value))) === normalize(join7(resolveRealPath(root), ARCANE_HOOKS_DIR));
3372
3394
  }
3373
3395
  var PRE_PUSH_HOOK_BODY = `#!/bin/sh
3374
3396
  # Installed by Arcane because this repository's .arcane.json sets
@@ -3413,8 +3435,8 @@ async function repositoryRoot(cwd) {
3413
3435
  ]);
3414
3436
  const commonDir = stdout.trim();
3415
3437
  if (commonDir !== "") {
3416
- const parent = dirname3(commonDir);
3417
- if (basename(commonDir) === ".git" && parent !== "") return parent;
3438
+ const parent = dirname4(commonDir);
3439
+ if (basename2(commonDir) === ".git" && parent !== "") return parent;
3418
3440
  }
3419
3441
  } catch {
3420
3442
  }
@@ -3427,10 +3449,11 @@ async function repositoryRoot(cwd) {
3427
3449
  return cwd;
3428
3450
  }
3429
3451
  async function hookFilePath(cwd, hookName = "pre-push") {
3430
- return join6(await repositoryRoot(cwd), ARCANE_HOOKS_DIR, hookName);
3452
+ return join7(await repositoryRoot(cwd), ARCANE_HOOKS_DIR, hookName);
3431
3453
  }
3432
3454
  async function hooksPathValue(cwd) {
3433
- return join6(await repositoryRoot(cwd), ARCANE_HOOKS_DIR).replace(/\\/g, "/");
3455
+ const value = join7(await repositoryRoot(cwd), ARCANE_HOOKS_DIR);
3456
+ return process.platform === "win32" ? value.replace(/\\/g, "/") : value;
3434
3457
  }
3435
3458
  async function installHook(cwd, hookName, body) {
3436
3459
  const root = await repositoryRoot(cwd);
@@ -3449,11 +3472,11 @@ async function installHook(cwd, hookName, body) {
3449
3472
  return { status: "refused-default-hooks", hooks: displaced };
3450
3473
  }
3451
3474
  }
3452
- const hookPath = join6(root, ARCANE_HOOKS_DIR, hookName);
3475
+ const hookPath = join7(root, ARCANE_HOOKS_DIR, hookName);
3453
3476
  if (existing !== void 0 && await hookFileMatches(cwd, hookName, body)) {
3454
3477
  return { status: "already-ours" };
3455
3478
  }
3456
- await mkdir5(join6(root, ARCANE_HOOKS_DIR), { recursive: true });
3479
+ await mkdir5(join7(root, ARCANE_HOOKS_DIR), { recursive: true });
3457
3480
  await writeFile8(hookPath, body, "utf-8");
3458
3481
  await chmod(hookPath, 493);
3459
3482
  await runGit(cwd, ["config", "--local", "core.hooksPath", await hooksPathValue(cwd)]);
@@ -3498,7 +3521,7 @@ async function defaultHooks(cwd) {
3498
3521
  let hooksDir;
3499
3522
  try {
3500
3523
  const { stdout } = await runGit(cwd, ["rev-parse", "--git-common-dir"]);
3501
- hooksDir = join6(resolve2(cwd, stdout.trim()), "hooks");
3524
+ hooksDir = join7(resolve3(cwd, stdout.trim()), "hooks");
3502
3525
  } catch {
3503
3526
  return [];
3504
3527
  }
@@ -3534,7 +3557,7 @@ async function removeHook(cwd, hookName) {
3534
3557
  await rm4(await hookFilePath(cwd, hookName), { force: true });
3535
3558
  } catch {
3536
3559
  }
3537
- const hooksDir = join6(root, ARCANE_HOOKS_DIR);
3560
+ const hooksDir = join7(root, ARCANE_HOOKS_DIR);
3538
3561
  let remaining = [];
3539
3562
  try {
3540
3563
  remaining = await readdir6(hooksDir);
@@ -3937,7 +3960,7 @@ async function runInit(options, targetDir, assetsDir, packageVersion) {
3937
3960
  }
3938
3961
  let flags = {};
3939
3962
  try {
3940
- flags = resolveManifestFlags(options.manifestFlags, {}, join7(targetDir, ".arcane.json"));
3963
+ flags = resolveManifestFlags(options.manifestFlags, {}, join8(targetDir, ".arcane.json"));
3941
3964
  } catch (err) {
3942
3965
  if (!(err instanceof ManifestFlagError)) throw err;
3943
3966
  console.error(`
@@ -4072,7 +4095,7 @@ async function runInit(options, targetDir, assetsDir, packageVersion) {
4072
4095
  const installedFiles = [];
4073
4096
  const fileHashes = {};
4074
4097
  for (const file of component.files) {
4075
- const srcPath = join7(assetsDir, component.sourceOverrides?.[file] ?? file);
4098
+ const srcPath = join8(assetsDir, component.sourceOverrides?.[file] ?? file);
4076
4099
  if (options.dryRun) {
4077
4100
  printDryRun(`Would copy: ${file}`);
4078
4101
  } else {
@@ -4089,7 +4112,7 @@ async function runInit(options, targetDir, assetsDir, packageVersion) {
4089
4112
  fileCount++;
4090
4113
  }
4091
4114
  for (const dir of component.directories ?? []) {
4092
- const srcDirPath = join7(assetsDir, dir);
4115
+ const srcDirPath = join8(assetsDir, dir);
4093
4116
  if (options.dryRun) {
4094
4117
  printDryRun(`Would copy directory: ${dir}/`);
4095
4118
  } else {
@@ -4118,7 +4141,7 @@ async function runInit(options, targetDir, assetsDir, packageVersion) {
4118
4141
  if (options.dryRun) {
4119
4142
  if (hasAgents) {
4120
4143
  const agentFiles = await import("fs").then(
4121
- (fsModule) => fsModule.promises.readdir(join7(assetsDir, "agents"))
4144
+ (fsModule) => fsModule.promises.readdir(join8(assetsDir, "agents"))
4122
4145
  );
4123
4146
  const yamlFiles = agentFiles.filter((f) => f.endsWith(".yaml")).sort();
4124
4147
  printDryRun("Would run agent setup (interactive):");
@@ -4357,7 +4380,7 @@ async function runInitUser(options, storeRoot, assetsDir, packageVersion) {
4357
4380
  console.log(chalk2.hex("#a855f7")(`
4358
4381
  \u2726 Arcane v${packageVersion}
4359
4382
  `));
4360
- const homeDir = dirname4(storeRoot);
4383
+ const homeDir = dirname5(storeRoot);
4361
4384
  const components = USER_TIER_COMPONENTS.map(
4362
4385
  (name) => componentForScope(getComponent(name), "user")
4363
4386
  );
@@ -4375,7 +4398,7 @@ async function runInitUser(options, storeRoot, assetsDir, packageVersion) {
4375
4398
  for (const id of spellIds) {
4376
4399
  for (const client2 of ["codex", "claude"]) {
4377
4400
  const relativePath = USER_FANOUT_PATHS[client2](id);
4378
- if (await fileExists(join7(homeDir, relativePath))) {
4401
+ if (await fileExists(join8(homeDir, relativePath))) {
4379
4402
  printDryRun(`Would leave alone (exists, not written by Arcane): ~/${relativePath}`);
4380
4403
  } else {
4381
4404
  printDryRun(`Would write: ~/${relativePath}`);
@@ -4393,7 +4416,7 @@ async function runInitUser(options, storeRoot, assetsDir, packageVersion) {
4393
4416
  const installedFiles = [];
4394
4417
  const fileHashes = {};
4395
4418
  for (const file of component.files) {
4396
- const srcPath = join7(assetsDir, component.sourceOverrides?.[file] ?? file);
4419
+ const srcPath = join8(assetsDir, component.sourceOverrides?.[file] ?? file);
4397
4420
  fileHashes[file] = await copyFile(srcPath, storeRoot, file, { force: options.force });
4398
4421
  installedFiles.push(file);
4399
4422
  fileCount++;
@@ -4440,23 +4463,23 @@ async function runInitUser(options, storeRoot, assetsDir, packageVersion) {
4440
4463
 
4441
4464
  // src/modules/component-install.ts
4442
4465
  import { readFile as readFile8, stat, writeFile as writeFile9 } from "fs/promises";
4443
- import { join as join8 } from "path";
4466
+ import { join as join9 } from "path";
4444
4467
  async function planComponentInstall(component, targetDir, assetsDir, opts = {}) {
4445
4468
  const files = [];
4446
4469
  const stateOf = async (file, src) => {
4447
- const dest = join8(targetDir, file);
4470
+ const dest = join9(targetDir, file);
4448
4471
  if (!await fileExists(dest)) return { file, src, state: "missing" };
4449
4472
  if ((await stat(dest)).isDirectory()) return { file, src, state: "directory" };
4450
4473
  const same = await hashFile(dest) === await hashFile(src);
4451
4474
  return { file, src, state: same ? "identical" : "differs" };
4452
4475
  };
4453
4476
  for (const file of component.files) {
4454
- files.push(await stateOf(file, join8(assetsDir, component.sourceOverrides?.[file] ?? file)));
4477
+ files.push(await stateOf(file, join9(assetsDir, component.sourceOverrides?.[file] ?? file)));
4455
4478
  }
4456
4479
  for (const dir of component.directories ?? []) {
4457
- const srcDir = join8(assetsDir, dir);
4480
+ const srcDir = join9(assetsDir, dir);
4458
4481
  for (const file of await listDirectoryFiles(srcDir, dir)) {
4459
- files.push(await stateOf(file, join8(assetsDir, file)));
4482
+ files.push(await stateOf(file, join9(assetsDir, file)));
4460
4483
  }
4461
4484
  }
4462
4485
  const of = (...states) => files.filter((f) => states.includes(f.state));
@@ -4474,7 +4497,7 @@ async function executeInstallPlan(plan, targetDir) {
4474
4497
  const written = [];
4475
4498
  try {
4476
4499
  for (const { file, src, state } of plan.toCopy) {
4477
- const previous = state === "missing" ? null : await readFile8(join8(targetDir, file));
4500
+ const previous = state === "missing" ? null : await readFile8(join9(targetDir, file));
4478
4501
  fileHashes[file] = await copyFile(src, targetDir, file, { force: true });
4479
4502
  written.push({ file, previous });
4480
4503
  files.push(file);
@@ -4492,7 +4515,7 @@ async function rollback(written, targetDir) {
4492
4515
  await removeWithin(targetDir, file);
4493
4516
  await removeEmptyAncestors(targetDir, file);
4494
4517
  } else {
4495
- await writeFile9(join8(targetDir, file), previous);
4518
+ await writeFile9(join9(targetDir, file), previous);
4496
4519
  }
4497
4520
  } catch {
4498
4521
  }
@@ -4628,7 +4651,7 @@ async function runAdd(names, options, targetDir, assetsDir, packageVersion) {
4628
4651
  }
4629
4652
 
4630
4653
  // src/commands/update.ts
4631
- import { dirname as dirname5, join as join10 } from "path";
4654
+ import { dirname as dirname6, join as join11 } from "path";
4632
4655
  import { readFile as readFile9, writeFile as writeFile10 } from "fs/promises";
4633
4656
 
4634
4657
  // src/modules/merge3.ts
@@ -4760,7 +4783,7 @@ function merge3(base, ours, theirs) {
4760
4783
  }
4761
4784
 
4762
4785
  // src/modules/registry-changes.ts
4763
- import { join as join9 } from "path";
4786
+ import { join as join10 } from "path";
4764
4787
  function findMissingRequires(installed, profile) {
4765
4788
  const names = new Set(installed.flatMap((c) => LEGACY_COMPONENT_MIGRATIONS[c.name] ?? [c.name]));
4766
4789
  const promised = listProfiles().find((p) => p.id === profile)?.components;
@@ -4806,7 +4829,7 @@ async function findNewlyAvailable(targetDir, profile, installed, spellScope) {
4806
4829
  const alreadyPresent = [];
4807
4830
  if (component.skipExisting) {
4808
4831
  for (const file of component.files) {
4809
- if (await fileExists(join9(targetDir, file))) alreadyPresent.push(file);
4832
+ if (await fileExists(join10(targetDir, file))) alreadyPresent.push(file);
4810
4833
  }
4811
4834
  if (component.files.length > 0 && alreadyPresent.length === component.files.length) continue;
4812
4835
  }
@@ -5065,7 +5088,7 @@ async function resolveOrphan(targetDir, file, recordedHash, prune) {
5065
5088
  console.log(` ! Refused (path escapes the target directory): ${file}`);
5066
5089
  return "reported";
5067
5090
  }
5068
- const filePath = join10(targetDir, file);
5091
+ const filePath = join11(targetDir, file);
5069
5092
  if (!await fileExists(filePath)) return "not-found";
5070
5093
  if (!prune) return "reported";
5071
5094
  if (recordedHash === void 0) {
@@ -5087,7 +5110,7 @@ async function isReleasableUserOwnedFile(targetDir, file, recordedHash) {
5087
5110
  } catch {
5088
5111
  return false;
5089
5112
  }
5090
- const filePath = join10(targetDir, file);
5113
+ const filePath = join11(targetDir, file);
5091
5114
  if (!await fileExists(filePath)) return false;
5092
5115
  if (recordedHash === void 0) return true;
5093
5116
  return !await fileMatchesHash(filePath, recordedHash);
@@ -5098,7 +5121,7 @@ async function retainReportedOrphan(targetDir, file, recordedHash, into) {
5098
5121
  } catch {
5099
5122
  return;
5100
5123
  }
5101
- if (!await fileExists(join10(targetDir, file))) return;
5124
+ if (!await fileExists(join11(targetDir, file))) return;
5102
5125
  if (!into.files.includes(file)) into.files.push(file);
5103
5126
  if (recordedHash !== void 0) {
5104
5127
  into.fileHashes ??= {};
@@ -5127,7 +5150,7 @@ async function findMissingTrackedFiles(targetDir, components, scope = "repo", sp
5127
5150
  const candidates = readopted.has(installed.name) ? component.files : installed.files;
5128
5151
  for (const file of candidates) {
5129
5152
  if (!component.files.includes(file)) continue;
5130
- if (!await fileExists(join10(targetDir, file))) missing.push(file);
5153
+ if (!await fileExists(join11(targetDir, file))) missing.push(file);
5131
5154
  }
5132
5155
  }
5133
5156
  return missing;
@@ -5169,7 +5192,7 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5169
5192
  const movedFilesPresent = /* @__PURE__ */ new Set();
5170
5193
  for (const move of COMPONENT_FILE_MOVES) {
5171
5194
  for (const file of move.files) {
5172
- if (await fileExists(join10(targetDir, file))) movedFilesPresent.add(file);
5195
+ if (await fileExists(join11(targetDir, file))) movedFilesPresent.add(file);
5173
5196
  }
5174
5197
  }
5175
5198
  manifest = {
@@ -5200,7 +5223,7 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5200
5223
  return;
5201
5224
  }
5202
5225
  try {
5203
- flagPatch = resolveManifestFlags(options.manifestFlags, manifest, join10(targetDir, ".arcane.json"));
5226
+ flagPatch = resolveManifestFlags(options.manifestFlags, manifest, join11(targetDir, ".arcane.json"));
5204
5227
  } catch (err) {
5205
5228
  if (!(err instanceof ManifestFlagError)) throw err;
5206
5229
  console.error(`
@@ -5213,7 +5236,7 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5213
5236
  const answered = { ...manifest, ...flagPatch };
5214
5237
  const spellScope = effectiveSpellScope(manifest);
5215
5238
  const readopted = findReadoptedSpellComponents(manifest.components, scope, spellScope);
5216
- const homeDir = dirname5(targetDir);
5239
+ const homeDir = dirname6(targetDir);
5217
5240
  for (const line of await missingTierWarning(scope, spellScope)) console.log(line);
5218
5241
  if (scope === "repo") {
5219
5242
  console.warn(
@@ -5408,8 +5431,8 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5408
5431
  const updatedFiles = [];
5409
5432
  const fileHashes = {};
5410
5433
  for (const file of component.files) {
5411
- const srcPath = join10(assetsDir, component.sourceOverrides?.[file] ?? file);
5412
- const targetExists = await fileExists(join10(targetDir, file));
5434
+ const srcPath = join11(assetsDir, component.sourceOverrides?.[file] ?? file);
5435
+ const targetExists = await fileExists(join11(targetDir, file));
5413
5436
  const preserveExisting = Boolean(component.skipExisting) && targetExists;
5414
5437
  const recordedHash = installed.fileHashes?.[file];
5415
5438
  if (component.initOnly && !targetExists) {
@@ -5429,7 +5452,7 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5429
5452
  continue;
5430
5453
  }
5431
5454
  }
5432
- const editedByOperator = recordedHash !== void 0 && targetExists && !preserveExisting && !await fileMatchesHash(join10(targetDir, file), recordedHash);
5455
+ const editedByOperator = recordedHash !== void 0 && targetExists && !preserveExisting && !await fileMatchesHash(join11(targetDir, file), recordedHash);
5433
5456
  if (preserveExisting) {
5434
5457
  console.log(` ${options.dryRun ? "[dry-run] Would preserve" : "Preserved"}: ${file}`);
5435
5458
  } else if (editedByOperator && isClientShimPath(file)) {
@@ -5456,11 +5479,11 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5456
5479
  handled = true;
5457
5480
  } else {
5458
5481
  const [currentContent, newContent] = await Promise.all([
5459
- readFile9(join10(targetDir, file), "utf-8"),
5482
+ readFile9(join11(targetDir, file), "utf-8"),
5460
5483
  readFile9(srcPath, "utf-8")
5461
5484
  ]);
5462
5485
  const result = merge3(oldVendorContent, currentContent, newContent);
5463
- await writeFile10(join10(targetDir, file), result.content, "utf-8");
5486
+ await writeFile10(join11(targetDir, file), result.content, "utf-8");
5464
5487
  fileHashes[file] = await hashFile(srcPath);
5465
5488
  if (result.hasConflict) {
5466
5489
  conflictedFiles.push(file);
@@ -5482,7 +5505,7 @@ async function runUpdate(options, targetDir, assetsDir, packageVersion) {
5482
5505
  }
5483
5506
  }
5484
5507
  for (const dir of component.directories ?? []) {
5485
- const srcDirPath = join10(assetsDir, dir);
5508
+ const srcDirPath = join11(assetsDir, dir);
5486
5509
  if (options.dryRun) {
5487
5510
  console.log(` [dry-run] Would update directory: ${dir}/`);
5488
5511
  } else {
@@ -5642,11 +5665,11 @@ ${verb} ${orphansToReport.length} orphaned file(s) (tracked before this update,
5642
5665
  }
5643
5666
 
5644
5667
  // src/commands/status.ts
5645
- import { dirname as dirname7 } from "path";
5668
+ import { dirname as dirname8 } from "path";
5646
5669
 
5647
5670
  // src/modules/version-check.ts
5648
5671
  import { readFile as readFile10, writeFile as writeFile11, mkdir as mkdir6 } from "fs/promises";
5649
- import { dirname as dirname6, join as join11 } from "path";
5672
+ import { dirname as dirname7, join as join12 } from "path";
5650
5673
  import { homedir as homedir3 } from "os";
5651
5674
  import { createRequire } from "module";
5652
5675
  var require2 = createRequire(import.meta.url);
@@ -5660,7 +5683,7 @@ function getFeedUrl() {
5660
5683
  }
5661
5684
  return url;
5662
5685
  }
5663
- var DEFAULT_CACHE_PATH = join11(homedir3(), ".arcane", "version-cache.json");
5686
+ var DEFAULT_CACHE_PATH = join12(homedir3(), ".arcane", "version-cache.json");
5664
5687
  var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
5665
5688
  async function readCache(cachePath) {
5666
5689
  try {
@@ -5675,7 +5698,7 @@ async function readCache(cachePath) {
5675
5698
  }
5676
5699
  }
5677
5700
  async function writeCache(cachePath, latest) {
5678
- await mkdir6(dirname6(cachePath), { recursive: true });
5701
+ await mkdir6(dirname7(cachePath), { recursive: true });
5679
5702
  const entry = { latest, checkedAt: (/* @__PURE__ */ new Date()).toISOString() };
5680
5703
  await writeFile11(cachePath, JSON.stringify(entry, null, 2), "utf-8");
5681
5704
  }
@@ -5816,7 +5839,7 @@ async function runStatus(targetDir, packageVersion, options = {}) {
5816
5839
  console.log("");
5817
5840
  if (scope === "user") {
5818
5841
  console.log(` Scope: user \u2014 ${targetDir}`);
5819
- const health = await inspectUserTierFanout(dirname7(targetDir), manifest.fanout);
5842
+ const health = await inspectUserTierFanout(dirname8(targetDir), manifest.fanout);
5820
5843
  console.log(
5821
5844
  ` Client files: ${health.total} (${health.byClient.codex} ${FANOUT_CLIENT_LABELS.codex}, ${health.byClient.claude} ${FANOUT_CLIENT_LABELS.claude})`
5822
5845
  );
@@ -5879,7 +5902,7 @@ async function runStatus(targetDir, packageVersion, options = {}) {
5879
5902
 
5880
5903
  // src/commands/uninstall.ts
5881
5904
  import { rm as rm5 } from "fs/promises";
5882
- import { dirname as dirname8, join as join12 } from "path";
5905
+ import { dirname as dirname9, join as join13 } from "path";
5883
5906
  import { confirm as confirm3 } from "@inquirer/prompts";
5884
5907
  async function runUninstall(options, targetDir) {
5885
5908
  let manifest;
@@ -5962,16 +5985,16 @@ Run \`spell unblock-push\` first (interactive), then uninstall.`
5962
5985
  }
5963
5986
  }
5964
5987
  }
5965
- await rm5(join12(targetDir, ".arcane.json"), { force: true });
5988
+ await rm5(join13(targetDir, ".arcane.json"), { force: true });
5966
5989
  const agentDirs = [
5967
5990
  ".github/agents",
5968
5991
  ".arcane/agents",
5969
5992
  ".arcane/generated"
5970
5993
  ];
5971
5994
  for (const dir of agentDirs) {
5972
- await rm5(join12(targetDir, dir), { recursive: true, force: true });
5995
+ await rm5(join13(targetDir, dir), { recursive: true, force: true });
5973
5996
  }
5974
- await rm5(join12(targetDir, ".arcane/agents.yaml"), { force: true });
5997
+ await rm5(join13(targetDir, ".arcane/agents.yaml"), { force: true });
5975
5998
  const markerFiles = [
5976
5999
  "CLAUDE.md",
5977
6000
  "AGENTS.md",
@@ -5988,7 +6011,7 @@ Run \`spell unblock-push\` first (interactive), then uninstall.`
5988
6011
  \u2713 Uninstalled \u2014 ${removed} files removed.`);
5989
6012
  }
5990
6013
  async function uninstallUserTier(options, storeRoot, manifest) {
5991
- const homeDir = dirname8(storeRoot);
6014
+ const homeDir = dirname9(storeRoot);
5992
6015
  const storeFiles = manifest.components.flatMap((c) => c.files);
5993
6016
  const recordedCount = Object.keys(manifest.fanout ?? {}).length;
5994
6017
  if (options.dryRun) {
@@ -6033,10 +6056,10 @@ async function uninstallUserTier(options, storeRoot, manifest) {
6033
6056
  console.log(` ! Skipped ${file}: ${err instanceof Error ? err.message : String(err)}`);
6034
6057
  }
6035
6058
  }
6036
- await rm5(join12(storeRoot, ".arcane.json"), { force: true });
6037
- await rm5(join12(storeRoot, "agents"), { recursive: true, force: true });
6038
- await rm5(join12(storeRoot, "agents.yaml"), { force: true });
6039
- await removeDirectoryIfEmpty(join12(storeRoot, USER_TIER_SPELLS_DIR));
6059
+ await rm5(join13(storeRoot, ".arcane.json"), { force: true });
6060
+ await rm5(join13(storeRoot, "agents"), { recursive: true, force: true });
6061
+ await rm5(join13(storeRoot, "agents.yaml"), { force: true });
6062
+ await removeDirectoryIfEmpty(join13(storeRoot, USER_TIER_SPELLS_DIR));
6040
6063
  await removeDirectoryIfEmpty(storeRoot);
6041
6064
  for (const line of describeFanoutOutcomes(fanout.outcomes)) console.log(` ${line}`);
6042
6065
  const pruned = fanout.outcomes.filter((o) => o.status === "pruned").length;
@@ -6049,7 +6072,7 @@ async function uninstallUserTier(options, storeRoot, manifest) {
6049
6072
 
6050
6073
  // src/commands/doctor.ts
6051
6074
  import { access as access4, readdir as readdir9, readFile as readFile13, mkdir as mkdir7, copyFile as fsCopyFile } from "fs/promises";
6052
- import { join as join15, dirname as dirname9 } from "path";
6075
+ import { join as join16, dirname as dirname10 } from "path";
6053
6076
 
6054
6077
  // src/config/incidents.ts
6055
6078
  var INCIDENT_QUEUE = [
@@ -6118,7 +6141,7 @@ function evaluateIncidentGate(records) {
6118
6141
 
6119
6142
  // src/modules/denylist-scan.ts
6120
6143
  import { readFile as readFile11, readdir as readdir7 } from "fs/promises";
6121
- import { join as join13, relative } from "path";
6144
+ import { join as join14, relative } from "path";
6122
6145
  function escapeRegExp(value) {
6123
6146
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6124
6147
  }
@@ -6169,7 +6192,7 @@ async function collectScannableFiles(root, repoRoot = root, extensions = DEFAULT
6169
6192
  return collected;
6170
6193
  }
6171
6194
  for (const entry of entries) {
6172
- const absolutePath = join13(root, entry.name);
6195
+ const absolutePath = join14(root, entry.name);
6173
6196
  if (entry.isDirectory()) {
6174
6197
  if (SKIP_DIRECTORIES.has(entry.name)) continue;
6175
6198
  collected.push(...await collectScannableFiles(absolutePath, repoRoot, extensions));
@@ -6196,7 +6219,7 @@ import { existsSync, readFileSync } from "fs";
6196
6219
  import { win32 } from "path";
6197
6220
  var EXTERNAL_CLI_TIMEOUT_MS = 1e4;
6198
6221
  function execFileWithTimeout(file, args, timeoutMs, options = {}) {
6199
- return new Promise((resolve5, reject) => {
6222
+ return new Promise((resolve6, reject) => {
6200
6223
  const child = execFile2(
6201
6224
  file,
6202
6225
  args,
@@ -6212,7 +6235,7 @@ function execFileWithTimeout(file, args, timeoutMs, options = {}) {
6212
6235
  reject(error);
6213
6236
  return;
6214
6237
  }
6215
- resolve5({ stdout, stderr });
6238
+ resolve6({ stdout, stderr });
6216
6239
  }
6217
6240
  );
6218
6241
  child.stdin?.end();
@@ -6430,7 +6453,7 @@ function parseAdoRemote(url) {
6430
6453
 
6431
6454
  // src/modules/placeholders.ts
6432
6455
  import { readdir as readdir8, readFile as readFile12 } from "fs/promises";
6433
- import { join as join14 } from "path";
6456
+ import { join as join15 } from "path";
6434
6457
  var PLACEHOLDER_STANDARD_FILE = "spell-authoring-standards.md";
6435
6458
  var RUNTIME_PLACEHOLDERS_START = "<!-- runtime-placeholders:start -->";
6436
6459
  var RUNTIME_PLACEHOLDERS_END = "<!-- runtime-placeholders:end -->";
@@ -6525,7 +6548,7 @@ function parseRuntimePlaceholders(standardContent) {
6525
6548
  async function scanGovernancePlaceholders(governanceDir) {
6526
6549
  let standard;
6527
6550
  try {
6528
- standard = await readFile12(join14(governanceDir, PLACEHOLDER_STANDARD_FILE), "utf8");
6551
+ standard = await readFile12(join15(governanceDir, PLACEHOLDER_STANDARD_FILE), "utf8");
6529
6552
  } catch (err) {
6530
6553
  if (err.code === "ENOENT") {
6531
6554
  return { status: "skipped", reason: `${PLACEHOLDER_STANDARD_FILE} is not installed` };
@@ -6544,7 +6567,7 @@ async function scanGovernancePlaceholders(governanceDir) {
6544
6567
  const templateDocs = [];
6545
6568
  const findings = [];
6546
6569
  for (const file of files) {
6547
- const content = await readFile12(join14(governanceDir, file), "utf8");
6570
+ const content = await readFile12(join15(governanceDir, file), "utf8");
6548
6571
  const status = parseFrontmatterStatus(content);
6549
6572
  if (status === "template") templateDocs.push(file);
6550
6573
  if (status !== "active") continue;
@@ -6575,8 +6598,8 @@ async function checkNodeVersion() {
6575
6598
  async function checkVSCodeExtension(id, label2, homeDir = resolveHomeDir()) {
6576
6599
  const name = `VS Code extension: ${label2}`;
6577
6600
  const flavours = [
6578
- { dir: join15(homeDir, ".vscode", "extensions"), bin: "code" },
6579
- { dir: join15(homeDir, ".vscode-insiders", "extensions"), bin: "code-insiders" }
6601
+ { dir: join16(homeDir, ".vscode", "extensions"), bin: "code" },
6602
+ { dir: join16(homeDir, ".vscode-insiders", "extensions"), bin: "code-insiders" }
6580
6603
  ];
6581
6604
  let installBin = null;
6582
6605
  for (const flavour of flavours) {
@@ -6604,11 +6627,11 @@ async function checkVSCodeExtension(id, label2, homeDir = resolveHomeDir()) {
6604
6627
  }
6605
6628
  async function checkArcaneManifest(targetDir) {
6606
6629
  const name = "Arcane manifest (.arcane.json)";
6607
- const manifestPath2 = join15(targetDir, ".arcane.json");
6630
+ const manifestPath2 = join16(targetDir, ".arcane.json");
6608
6631
  try {
6609
6632
  await access4(manifestPath2);
6610
6633
  } catch {
6611
- const selfHostedManifestPath = join15(targetDir, "src", "assets", ".arcane.json");
6634
+ const selfHostedManifestPath = join16(targetDir, "src", "assets", ".arcane.json");
6612
6635
  try {
6613
6636
  const raw = await readFile13(selfHostedManifestPath, "utf8");
6614
6637
  const manifest = JSON.parse(raw);
@@ -6714,7 +6737,7 @@ async function checkSessionContinuity(targetDir) {
6714
6737
  const results = [];
6715
6738
  for (const file of SESSION_CONTINUITY_FILES) {
6716
6739
  const name = `Session file: ${file}`;
6717
- const filePath = join15(targetDir, file);
6740
+ const filePath = join16(targetDir, file);
6718
6741
  try {
6719
6742
  await access4(filePath);
6720
6743
  results.push({ name, passed: true, message: "present" });
@@ -6732,12 +6755,12 @@ async function checkSessionContinuity(targetDir) {
6732
6755
  async function fixSessionContinuity(targetDir, assetsDir) {
6733
6756
  const created = [];
6734
6757
  for (const file of SESSION_CONTINUITY_FILES) {
6735
- const destPath = join15(targetDir, file);
6758
+ const destPath = join16(targetDir, file);
6736
6759
  try {
6737
6760
  await access4(destPath);
6738
6761
  } catch {
6739
- const srcPath = join15(assetsDir, file);
6740
- await mkdir7(dirname9(destPath), { recursive: true });
6762
+ const srcPath = join16(assetsDir, file);
6763
+ await mkdir7(dirname10(destPath), { recursive: true });
6741
6764
  await fsCopyFile(srcPath, destPath);
6742
6765
  created.push(file);
6743
6766
  }
@@ -6864,7 +6887,7 @@ async function checkGovernancePlaceholders(targetDir) {
6864
6887
  const name = "Governance placeholders (ARC-051)";
6865
6888
  let scan;
6866
6889
  try {
6867
- scan = await scanGovernancePlaceholders(join15(targetDir, ".arcane", "governance"));
6890
+ scan = await scanGovernancePlaceholders(join16(targetDir, ".arcane", "governance"));
6868
6891
  } catch (err) {
6869
6892
  return {
6870
6893
  name,
@@ -6951,7 +6974,7 @@ async function checkNewlyAvailableComponents(targetDir) {
6951
6974
  }
6952
6975
  async function checkMcpConfig(targetDir) {
6953
6976
  const name = "MCP config (per-server timeout, I12)";
6954
- const filePath = join15(targetDir, ".mcp.json");
6977
+ const filePath = join16(targetDir, ".mcp.json");
6955
6978
  let raw;
6956
6979
  try {
6957
6980
  raw = await readFile13(filePath, "utf8");
@@ -7034,7 +7057,7 @@ function isDelegationsFile(value) {
7034
7057
  }
7035
7058
  async function checkDelegations(targetDir) {
7036
7059
  const name = "Standing delegations (T13)";
7037
- const filePath = join15(targetDir, ".arcane", "delegations.json");
7060
+ const filePath = join16(targetDir, ".arcane", "delegations.json");
7038
7061
  let raw;
7039
7062
  try {
7040
7063
  raw = await readFile13(filePath, "utf8");
@@ -7147,7 +7170,7 @@ async function checkSpellScope(targetDir, homeDir = resolveHomeDir()) {
7147
7170
  let probed = false;
7148
7171
  const probe = "spell-status.md";
7149
7172
  try {
7150
- const entries = await readdir9(join15(storeRoot, USER_TIER_SPELLS_DIR));
7173
+ const entries = await readdir9(join16(storeRoot, USER_TIER_SPELLS_DIR));
7151
7174
  const spells = entries.filter((e) => e.startsWith("spell-") && e.endsWith(".md"));
7152
7175
  spellCount = spells.length;
7153
7176
  probed = spells.includes(probe);
@@ -7261,7 +7284,7 @@ import { readFile as readFile15 } from "fs/promises";
7261
7284
 
7262
7285
  // src/modules/ward.ts
7263
7286
  import { readdir as readdir10, readFile as readFile14 } from "fs/promises";
7264
- import { join as join16, relative as relative2 } from "path";
7287
+ import { join as join17, relative as relative2 } from "path";
7265
7288
  async function scanFileAllRules(absolutePath, displayPath, rules) {
7266
7289
  const findings = [];
7267
7290
  let content;
@@ -7324,7 +7347,7 @@ async function scanFilenames(root, rules, repoRoot = root) {
7324
7347
  return findings;
7325
7348
  }
7326
7349
  for (const entry of entries) {
7327
- const absolutePath = join16(root, entry.name);
7350
+ const absolutePath = join17(root, entry.name);
7328
7351
  if (entry.isDirectory()) {
7329
7352
  if (SKIP_DIRECTORIES.has(entry.name)) continue;
7330
7353
  findings.push(...await scanFilenames(absolutePath, rules, repoRoot));
@@ -7439,7 +7462,7 @@ async function runWardCli(targetDir, options = {}, exclusions = []) {
7439
7462
  }
7440
7463
 
7441
7464
  // src/commands/unblock-push.ts
7442
- import { basename as basename2, resolve as resolve3 } from "path";
7465
+ import { basename as basename3, resolve as resolve4 } from "path";
7443
7466
  import { input as input4 } from "@inquirer/prompts";
7444
7467
  async function runUnblockPush(targetDir) {
7445
7468
  let manifest;
@@ -7471,7 +7494,7 @@ async function runUnblockPush(targetDir) {
7471
7494
  process.exit(1);
7472
7495
  return;
7473
7496
  }
7474
- const repoName = basename2(resolve3(targetDir));
7497
+ const repoName = basename3(resolve4(targetDir));
7475
7498
  if (repoName === "") {
7476
7499
  console.error(
7477
7500
  "Could not determine a repository name to confirm against (is this repository at a filesystem root?). Refusing to unblock."
@@ -7760,10 +7783,10 @@ import * as client from "openid-client";
7760
7783
  // src/modules/result-pages.ts
7761
7784
  import { createHash as createHash3 } from "crypto";
7762
7785
  import { readFile as readFile16 } from "fs/promises";
7763
- import { join as join17 } from "path";
7786
+ import { join as join18 } from "path";
7764
7787
  var RESULT_KINDS = ["success", "denied", "failure"];
7765
7788
  function resultPagePath(kind) {
7766
- return join17("sign-in", `sign-in-callback-${kind}.html`);
7789
+ return join18("sign-in", `sign-in-callback-${kind}.html`);
7767
7790
  }
7768
7791
  function styleHashes(html) {
7769
7792
  return [...html.matchAll(/<style\b[^>]*>([\s\S]*?)<\/style\s*>/gi)].map((match) => {
@@ -7811,7 +7834,7 @@ var PLAIN_RESULT_PAGES = {
7811
7834
  async function loadResultPages(assetsDir) {
7812
7835
  try {
7813
7836
  const [success, denied, failure] = await Promise.all(
7814
- RESULT_KINDS.map(async (kind) => resultPage(await readFile16(join17(assetsDir, resultPagePath(kind)), "utf8")))
7837
+ RESULT_KINDS.map(async (kind) => resultPage(await readFile16(join18(assetsDir, resultPagePath(kind)), "utf8")))
7815
7838
  );
7816
7839
  return { success, denied, failure };
7817
7840
  } catch {
@@ -7889,9 +7912,9 @@ async function browserLogin(config, options) {
7889
7912
  const state = client.randomState();
7890
7913
  const nonce = client.randomNonce();
7891
7914
  const server = createServer();
7892
- await new Promise((resolve5, reject) => {
7915
+ await new Promise((resolve6, reject) => {
7893
7916
  server.once("error", reject);
7894
- server.listen(0, "127.0.0.1", () => resolve5());
7917
+ server.listen(0, "127.0.0.1", () => resolve6());
7895
7918
  });
7896
7919
  const address = server.address();
7897
7920
  if (address === null || typeof address === "string") {
@@ -7917,7 +7940,7 @@ async function browserLogin(config, options) {
7917
7940
  server.closeAllConnections?.();
7918
7941
  server.close();
7919
7942
  };
7920
- const tokens = new Promise((resolve5, reject) => {
7943
+ const tokens = new Promise((resolve6, reject) => {
7921
7944
  server.on("request", (req, res) => {
7922
7945
  const url = new URL(req.url ?? "/", redirectUri);
7923
7946
  if (RESULT_PATHS.has(url.pathname)) {
@@ -7928,7 +7951,7 @@ async function browserLogin(config, options) {
7928
7951
  const served = browserResult;
7929
7952
  const page = pages[served.kind];
7930
7953
  const settle = () => {
7931
- if (served.kind === "success") resolve5(served.result);
7954
+ if (served.kind === "success") resolve6(served.result);
7932
7955
  else reject(served.error);
7933
7956
  };
7934
7957
  res.once("finish", settle).once("close", settle);
@@ -7957,7 +7980,7 @@ async function browserLogin(config, options) {
7957
7980
  }).end();
7958
7981
  if (result.kind === "success") {
7959
7982
  if (timer) clearTimeout(timer);
7960
- timer = setTimeout(() => resolve5(result.result), Math.min(timeoutMs, 5e3));
7983
+ timer = setTimeout(() => resolve6(result.result), Math.min(timeoutMs, 5e3));
7961
7984
  }
7962
7985
  };
7963
7986
  const errorCode = url.searchParams.get("error");
@@ -8009,12 +8032,12 @@ async function refreshSession(config, refreshToken, scopes) {
8009
8032
  }
8010
8033
  function openInDefaultBrowser(url) {
8011
8034
  const [command, args] = process.platform === "win32" ? ["rundll32", ["url.dll,FileProtocolHandler", url]] : process.platform === "darwin" ? ["open", [url]] : ["xdg-open", [url]];
8012
- return new Promise((resolve5) => {
8035
+ return new Promise((resolve6) => {
8013
8036
  try {
8014
- const child = execFile3(command, args, { windowsHide: true }, (error) => resolve5(!error));
8015
- child.on("error", () => resolve5(false));
8037
+ const child = execFile3(command, args, { windowsHide: true }, (error) => resolve6(!error));
8038
+ child.on("error", () => resolve6(false));
8016
8039
  } catch {
8017
- resolve5(false);
8040
+ resolve6(false);
8018
8041
  }
8019
8042
  });
8020
8043
  }
@@ -8023,7 +8046,7 @@ function openInDefaultBrowser(url) {
8023
8046
  import { execFileSync } from "child_process";
8024
8047
  import { mkdirSync, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync, existsSync as existsSync2 } from "fs";
8025
8048
  import { userInfo } from "os";
8026
- import { dirname as dirname10, join as join18 } from "path";
8049
+ import { dirname as dirname11, join as join19 } from "path";
8027
8050
 
8028
8051
  // src/modules/keychain-backend.ts
8029
8052
  import { createRequire as createRequire2 } from "module";
@@ -8112,7 +8135,7 @@ var FileSecretBackend = class {
8112
8135
  rmSync(this.filePath, { force: true });
8113
8136
  return;
8114
8137
  }
8115
- mkdirSync(dirname10(this.filePath), { recursive: true });
8138
+ mkdirSync(dirname11(this.filePath), { recursive: true });
8116
8139
  const tmp = `${this.filePath}.${process.pid}.tmp`;
8117
8140
  writeFileSync(tmp, JSON.stringify(entries), { encoding: "utf8", mode: 384 });
8118
8141
  try {
@@ -8157,7 +8180,7 @@ function restrictToCurrentUser(filePath) {
8157
8180
  });
8158
8181
  }
8159
8182
  function insecureSessionFilePath(homeDir) {
8160
- return join18(userTierRoot(homeDir), INSECURE_SESSION_FILE_NAME);
8183
+ return join19(userTierRoot(homeDir), INSECURE_SESSION_FILE_NAME);
8161
8184
  }
8162
8185
  function createSessionStorage(options = {}) {
8163
8186
  const keychain = new ChunkedSecretStore(options.keychainBackend ?? createKeychainBackend());
@@ -8425,15 +8448,15 @@ async function runWhoami(options, deps = defaultWhoamiDeps()) {
8425
8448
 
8426
8449
  // src/commands/report.ts
8427
8450
  import { access as access5 } from "fs/promises";
8428
- import { join as join21 } from "path";
8451
+ import { join as join22 } from "path";
8429
8452
 
8430
8453
  // src/modules/show-report/generate.ts
8431
8454
  import { mkdir as mkdir8, readdir as readdir11, readFile as readFile18, writeFile as writeFile12 } from "fs/promises";
8432
- import { basename as basename3, dirname as dirname11, isAbsolute, join as join20, relative as relative3, resolve as resolve4 } from "path";
8455
+ import { basename as basename4, dirname as dirname12, isAbsolute, join as join21, relative as relative3, resolve as resolve5 } from "path";
8433
8456
 
8434
8457
  // src/modules/show-report/model.ts
8435
8458
  import { readFile as readFile17 } from "fs/promises";
8436
- import { join as join19 } from "path";
8459
+ import { join as join20 } from "path";
8437
8460
 
8438
8461
  // src/modules/show-report/plan-parser.ts
8439
8462
  function parseFrontmatter(content) {
@@ -8802,11 +8825,11 @@ function buildCorrections(ledgerRows, programName) {
8802
8825
  };
8803
8826
  }
8804
8827
  async function buildShowReportModel(options) {
8805
- const planAbsPath = join19(options.rootDir, options.planRelPath);
8806
- const queueAbsPath = join19(options.rootDir, options.queueRelPath);
8828
+ const planAbsPath = join20(options.rootDir, options.planRelPath);
8829
+ const queueAbsPath = join20(options.rootDir, options.queueRelPath);
8807
8830
  const ledgerRelPath = "docs/verification-ledger.md";
8808
- const ledgerAbsPath = join19(options.rootDir, ledgerRelPath);
8809
- const decisionsAbsPath = join19(options.rootDir, "DECISIONS.md");
8831
+ const ledgerAbsPath = join20(options.rootDir, ledgerRelPath);
8832
+ const decisionsAbsPath = join20(options.rootDir, "DECISIONS.md");
8810
8833
  const [planContent, queueContent, ledgerContent, decisionsContent] = await Promise.all([
8811
8834
  readFile17(planAbsPath, "utf8"),
8812
8835
  readOptional(queueAbsPath),
@@ -9004,7 +9027,7 @@ function toPosix(path4) {
9004
9027
  async function programFromPlan(rootDir, slug, planRelPath) {
9005
9028
  let planContent;
9006
9029
  try {
9007
- planContent = await readFile18(join20(rootDir, planRelPath), "utf8");
9030
+ planContent = await readFile18(join21(rootDir, planRelPath), "utf8");
9008
9031
  } catch {
9009
9032
  return { skipped: { slug, reason: `no PLAN.md at ${planRelPath}` } };
9010
9033
  }
@@ -9016,13 +9039,13 @@ async function programFromPlan(rootDir, slug, planRelPath) {
9016
9039
  program: {
9017
9040
  slug,
9018
9041
  planRelPath,
9019
- queueRelPath: toPosix(join20(dirname11(planRelPath), "OPERATOR-QUEUE.md")),
9042
+ queueRelPath: toPosix(join21(dirname12(planRelPath), "OPERATOR-QUEUE.md")),
9020
9043
  ledgerProgramName: programNameFromTitle(frontmatter.title ?? slug)
9021
9044
  }
9022
9045
  };
9023
9046
  }
9024
9047
  async function discoverPrograms(rootDir) {
9025
- const plansDir = join20(rootDir, "docs", "plans");
9048
+ const plansDir = join21(rootDir, "docs", "plans");
9026
9049
  let entries;
9027
9050
  try {
9028
9051
  entries = (await readdir11(plansDir, { withFileTypes: true })).filter((e) => e.isDirectory());
@@ -9040,9 +9063,9 @@ async function discoverPrograms(rootDir) {
9040
9063
  return { programs, skipped };
9041
9064
  }
9042
9065
  async function programFromPlanPath(rootDir, planPath) {
9043
- const planAbs = isAbsolute(planPath) ? planPath : resolve4(rootDir, planPath);
9066
+ const planAbs = isAbsolute(planPath) ? planPath : resolve5(rootDir, planPath);
9044
9067
  const planRelPath = toPosix(relative3(rootDir, planAbs));
9045
- return programFromPlan(rootDir, basename3(dirname11(planAbs)), planRelPath);
9068
+ return programFromPlan(rootDir, basename4(dirname12(planAbs)), planRelPath);
9046
9069
  }
9047
9070
  function normalizeLineEndings2(content) {
9048
9071
  return content.replace(/\r\n?/g, "\n");
@@ -9056,7 +9079,7 @@ async function readOptionalFile(path4) {
9056
9079
  }
9057
9080
  }
9058
9081
  async function generateReport(rootDir, program2, templateHtml, theme = "auto") {
9059
- const planContent = await readFile18(join20(rootDir, program2.planRelPath), "utf8");
9082
+ const planContent = await readFile18(join21(rootDir, program2.planRelPath), "utf8");
9060
9083
  const frontmatter = parseFrontmatter(planContent);
9061
9084
  const model = await buildShowReportModel({
9062
9085
  rootDir,
@@ -9087,19 +9110,19 @@ async function runReportGeneration(options) {
9087
9110
  if (!generated.themeApplied) themeSkipped.push(program2.slug);
9088
9111
  const missing = JSON.parse(generated.json).sections.flatMap((section) => section.rows).filter((row) => row.descriptionState === "unwritten").map((row) => row.id);
9089
9112
  if (missing.length > 0) unwritten.push({ slug: program2.slug, ids: missing });
9090
- const outAbs = options.outDir ? isAbsolute(options.outDir) ? options.outDir : resolve4(options.rootDir, options.outDir) : resolve4(options.rootDir, dirname11(program2.planRelPath));
9113
+ const outAbs = options.outDir ? isAbsolute(options.outDir) ? options.outDir : resolve5(options.rootDir, options.outDir) : resolve5(options.rootDir, dirname12(program2.planRelPath));
9091
9114
  const outRel = toPosix(relative3(options.rootDir, outAbs));
9092
9115
  const outputs = [
9093
9116
  [`${outRel}/show-report.json`, generated.json],
9094
9117
  [`${outRel}/show-report.html`, generated.html]
9095
9118
  ];
9096
9119
  for (const [relPath, expected] of outputs) {
9097
- const actual = await readOptionalFile(join20(options.rootDir, relPath));
9120
+ const actual = await readOptionalFile(join21(options.rootDir, relPath));
9098
9121
  if (actual === null || normalizeLineEndings2(actual) !== normalizeLineEndings2(expected)) {
9099
9122
  drifted.push(`${relPath} does not match a regeneration from its sources.`);
9100
9123
  if (options.mode === "write") {
9101
9124
  await mkdir8(outAbs, { recursive: true });
9102
- await writeFile12(join20(options.rootDir, relPath), expected, "utf8");
9125
+ await writeFile12(join21(options.rootDir, relPath), expected, "utf8");
9103
9126
  repaired.push(relPath);
9104
9127
  }
9105
9128
  }
@@ -9110,7 +9133,7 @@ async function runReportGeneration(options) {
9110
9133
 
9111
9134
  // src/commands/report.ts
9112
9135
  async function runReport(targetDir, options = {}, assetsDir) {
9113
- const templatePath = join21(assetsDir, "report", "show-report.template.html");
9136
+ const templatePath = join22(assetsDir, "report", "show-report.template.html");
9114
9137
  try {
9115
9138
  await access5(templatePath);
9116
9139
  } catch {
@@ -9184,10 +9207,10 @@ async function runReport(targetDir, options = {}, assetsDir) {
9184
9207
  }
9185
9208
 
9186
9209
  // src/index.ts
9187
- import { realpathSync } from "fs";
9210
+ import { realpathSync as realpathSync2 } from "fs";
9188
9211
  var require3 = createRequire3(import.meta.url);
9189
9212
  var pkg = require3("../package.json");
9190
- var ASSETS_DIR = process.env["ARCANE_ASSETS_DIR"] ?? join22(dirname12(fileURLToPath(import.meta.url)), "assets");
9213
+ var ASSETS_DIR = process.env["ARCANE_ASSETS_DIR"] ?? join23(dirname13(fileURLToPath(import.meta.url)), "assets");
9191
9214
  var program = new Command();
9192
9215
  var USER_FLAG_DESCRIPTION = "Operate on the per-user tier at ~/.arcane \u2014 spells shared by every repository on this machine, fanned out to ~/.agents/skills (Codex, Copilot) and ~/.claude/commands (Claude Code)";
9193
9216
  var USER_TIER_AGENTS_DESCRIPTION = "Operate on the per-user tier at ~/.arcane \u2014 one agent roster shared by every repository on this machine, rendered to ~/.copilot/agents (VS Code agent modes)";
@@ -9397,7 +9420,7 @@ agentsCommand.command("list").description("Show the current agent roster with as
9397
9420
  const scope = opts.user ? "user" : "repo";
9398
9421
  await runAgentsList(agentsTargetDir(scope, process.cwd()), scope);
9399
9422
  });
9400
- if (realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
9423
+ if (realpathSync2(process.argv[1]) === fileURLToPath(import.meta.url)) {
9401
9424
  await program.parseAsync(process.argv);
9402
9425
  }
9403
9426
  export {