cleargate 0.6.1 → 0.7.0

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/cli.cjs CHANGED
@@ -627,7 +627,7 @@ var import_commander = require("commander");
627
627
  // package.json
628
628
  var package_default = {
629
629
  name: "cleargate",
630
- version: "0.6.1",
630
+ version: "0.7.0",
631
631
  private: false,
632
632
  type: "module",
633
633
  description: "Planning framework for Claude Code agents \u2014 sprint/epic/story protocol, four-agent loop (architect/developer/qa/reporter), Karpathy-style awareness wiki.",
@@ -1897,8 +1897,8 @@ async function stampHandler(file, opts, cli) {
1897
1897
 
1898
1898
  // src/commands/init.ts
1899
1899
  init_cjs_shims();
1900
- var fs15 = __toESM(require("fs"), 1);
1901
- var path16 = __toESM(require("path"), 1);
1900
+ var fs16 = __toESM(require("fs"), 1);
1901
+ var path17 = __toESM(require("path"), 1);
1902
1902
  var import_node_url5 = require("url");
1903
1903
  var import_node_child_process3 = require("child_process");
1904
1904
 
@@ -1911,6 +1911,7 @@ var HOOK_FILES_WITH_PIN = /* @__PURE__ */ new Set([
1911
1911
  ".claude/hooks/stamp-and-gate.sh",
1912
1912
  ".claude/hooks/session-start.sh"
1913
1913
  ]);
1914
+ var SKIP_FILES = /* @__PURE__ */ new Set(["CLAUDE.md"]);
1914
1915
  function listFilesRecursive(dir) {
1915
1916
  const results = [];
1916
1917
  function walk(current, rel) {
@@ -1933,7 +1934,7 @@ function copyPayload(payloadDir, targetCwd, opts) {
1933
1934
  if (!fs7.existsSync(payloadDir)) {
1934
1935
  throw new Error(`copyPayload: payloadDir does not exist: ${payloadDir}`);
1935
1936
  }
1936
- const files = listFilesRecursive(payloadDir);
1937
+ const files = listFilesRecursive(payloadDir).filter((r) => !SKIP_FILES.has(r));
1937
1938
  for (const relPath of files) {
1938
1939
  const srcPath = path7.join(payloadDir, relPath);
1939
1940
  const dstPath = path7.join(targetCwd, relPath);
@@ -1944,9 +1945,14 @@ function copyPayload(payloadDir, targetCwd, opts) {
1944
1945
  srcContent = text;
1945
1946
  }
1946
1947
  const srcBuffer = typeof srcContent === "string" ? Buffer.from(srcContent, "utf8") : srcContent;
1948
+ const srcMode = fs7.statSync(srcPath).mode;
1949
+ const needsExec = (srcMode & 73) !== 0 || relPath.endsWith(".sh");
1947
1950
  if (fs7.existsSync(dstPath)) {
1948
1951
  const dstContent = fs7.readFileSync(dstPath);
1949
1952
  if (srcBuffer.equals(dstContent)) {
1953
+ if (needsExec && process.platform !== "win32") {
1954
+ fs7.chmodSync(dstPath, 493);
1955
+ }
1950
1956
  report.skipped++;
1951
1957
  report.actions.push({ action: "skipped", relPath });
1952
1958
  continue;
@@ -1957,10 +1963,16 @@ function copyPayload(payloadDir, targetCwd, opts) {
1957
1963
  continue;
1958
1964
  }
1959
1965
  fs7.writeFileSync(dstPath, srcBuffer);
1966
+ if (needsExec && process.platform !== "win32") {
1967
+ fs7.chmodSync(dstPath, 493);
1968
+ }
1960
1969
  report.overwritten++;
1961
1970
  report.actions.push({ action: "overwritten", relPath });
1962
1971
  } else {
1963
1972
  fs7.writeFileSync(dstPath, srcBuffer);
1973
+ if (needsExec && process.platform !== "win32") {
1974
+ fs7.chmodSync(dstPath, 493);
1975
+ }
1964
1976
  report.created++;
1965
1977
  report.actions.push({ action: "created", relPath });
1966
1978
  }
@@ -2029,15 +2041,49 @@ function injectClaudeMd(existing, block) {
2029
2041
  return existing.trimEnd() + "\n\n" + block + "\n";
2030
2042
  }
2031
2043
 
2044
+ // src/init/inject-mcp-json.ts
2045
+ init_cjs_shims();
2046
+ var fs8 = __toESM(require("fs"), 1);
2047
+ var path8 = __toESM(require("path"), 1);
2048
+ function mergeMcpJson(existing, entry) {
2049
+ const next = existing ? { ...existing } : {};
2050
+ const servers = { ...next.mcpServers ?? {} };
2051
+ servers.cleargate = entry;
2052
+ next.mcpServers = servers;
2053
+ return JSON.stringify(next, null, 2) + "\n";
2054
+ }
2055
+ function injectMcpJson(cwd, url) {
2056
+ const dst = path8.join(cwd, ".mcp.json");
2057
+ const entry = { type: "http", url };
2058
+ let existing = null;
2059
+ let existingRaw = null;
2060
+ if (fs8.existsSync(dst)) {
2061
+ existingRaw = fs8.readFileSync(dst, "utf8");
2062
+ try {
2063
+ existing = JSON.parse(existingRaw);
2064
+ } catch {
2065
+ throw new Error(
2066
+ `inject-mcp-json: ${dst} is not valid JSON; refusing to overwrite. Fix or remove the file and re-run init.`
2067
+ );
2068
+ }
2069
+ }
2070
+ const next = mergeMcpJson(existing, entry);
2071
+ if (existingRaw !== null && existingRaw === next) {
2072
+ return "unchanged";
2073
+ }
2074
+ fs8.writeFileSync(dst, next);
2075
+ return existingRaw === null ? "created" : "updated";
2076
+ }
2077
+
2032
2078
  // src/commands/wiki-build.ts
2033
2079
  init_cjs_shims();
2034
- var fs13 = __toESM(require("fs"), 1);
2035
- var path13 = __toESM(require("path"), 1);
2080
+ var fs14 = __toESM(require("fs"), 1);
2081
+ var path14 = __toESM(require("path"), 1);
2036
2082
 
2037
2083
  // src/wiki/scan.ts
2038
2084
  init_cjs_shims();
2039
- var fs8 = __toESM(require("fs"), 1);
2040
- var path8 = __toESM(require("path"), 1);
2085
+ var fs9 = __toESM(require("fs"), 1);
2086
+ var path9 = __toESM(require("path"), 1);
2041
2087
 
2042
2088
  // src/wiki/derive-bucket.ts
2043
2089
  init_cjs_shims();
@@ -2082,19 +2128,19 @@ var EXCLUDED_SUFFIXES = [
2082
2128
  function scanRawItems(deliveryRoot, repoRoot) {
2083
2129
  const results = [];
2084
2130
  for (const subdir of ["pending-sync", "archive"]) {
2085
- const dir = path8.join(deliveryRoot, subdir);
2086
- if (!fs8.existsSync(dir)) continue;
2087
- const entries = fs8.readdirSync(dir, { recursive: true, encoding: "utf8" });
2131
+ const dir = path9.join(deliveryRoot, subdir);
2132
+ if (!fs9.existsSync(dir)) continue;
2133
+ const entries = fs9.readdirSync(dir, { recursive: true, encoding: "utf8" });
2088
2134
  for (const rel of entries) {
2089
2135
  if (!rel.endsWith(".md")) continue;
2090
2136
  if (rel.includes("~") || rel.startsWith(".")) continue;
2091
- const absPath = path8.join(dir, rel);
2092
- const stat = fs8.statSync(absPath);
2137
+ const absPath = path9.join(dir, rel);
2138
+ const stat = fs9.statSync(absPath);
2093
2139
  if (!stat.isFile()) continue;
2094
- const rawPath = path8.relative(repoRoot, absPath).replace(/\\/g, "/");
2140
+ const rawPath = path9.relative(repoRoot, absPath).replace(/\\/g, "/");
2095
2141
  const isExcluded = EXCLUDED_SUFFIXES.some((excl) => rawPath.startsWith(excl));
2096
2142
  if (isExcluded) continue;
2097
- const filename = path8.basename(absPath);
2143
+ const filename = path9.basename(absPath);
2098
2144
  let bucketInfo;
2099
2145
  try {
2100
2146
  bucketInfo = deriveBucket(filename);
@@ -2107,7 +2153,7 @@ function scanRawItems(deliveryRoot, repoRoot) {
2107
2153
  } catch {
2108
2154
  continue;
2109
2155
  }
2110
- const raw = fs8.readFileSync(absPath, "utf8");
2156
+ const raw = fs9.readFileSync(absPath, "utf8");
2111
2157
  let fm;
2112
2158
  let body;
2113
2159
  try {
@@ -2222,8 +2268,8 @@ function parseFmRaw(raw) {
2222
2268
 
2223
2269
  // src/wiki/synthesis/active-sprint.ts
2224
2270
  init_cjs_shims();
2225
- var fs9 = __toESM(require("fs"), 1);
2226
- var path9 = __toESM(require("path"), 1);
2271
+ var fs10 = __toESM(require("fs"), 1);
2272
+ var path10 = __toESM(require("path"), 1);
2227
2273
  var import_node_url = require("url");
2228
2274
 
2229
2275
  // src/wiki/synthesis/render.ts
@@ -2263,7 +2309,7 @@ function renderSection(template, ctx) {
2263
2309
  // src/wiki/synthesis/active-sprint.ts
2264
2310
  function compile(state2, templateDir) {
2265
2311
  const tplDir = templateDir ?? resolveDefaultTemplateDir();
2266
- const tpl = fs9.readFileSync(path9.join(tplDir, "active-sprint.md"), "utf8");
2312
+ const tpl = fs10.readFileSync(path10.join(tplDir, "active-sprint.md"), "utf8");
2267
2313
  const sprints = state2.filter((i) => i.bucket === "sprints");
2268
2314
  const active = sprints.filter((s) => isSet(s.fm["activated_at"]) && !isSet(s.fm["completed_at"]));
2269
2315
  const completed = sprints.filter((s) => isSet(s.fm["completed_at"]));
@@ -2287,18 +2333,18 @@ function isSet(val) {
2287
2333
  return s !== "" && s !== "null";
2288
2334
  }
2289
2335
  function resolveDefaultTemplateDir() {
2290
- const __dirname = path9.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
2291
- return path9.resolve(__dirname, "..", "templates", "synthesis");
2336
+ const __dirname = path10.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
2337
+ return path10.resolve(__dirname, "..", "templates", "synthesis");
2292
2338
  }
2293
2339
 
2294
2340
  // src/wiki/synthesis/open-gates.ts
2295
2341
  init_cjs_shims();
2296
- var fs10 = __toESM(require("fs"), 1);
2297
- var path10 = __toESM(require("path"), 1);
2342
+ var fs11 = __toESM(require("fs"), 1);
2343
+ var path11 = __toESM(require("path"), 1);
2298
2344
  var import_node_url2 = require("url");
2299
2345
  function compile2(state2, templateDir) {
2300
2346
  const tplDir = templateDir ?? resolveDefaultTemplateDir2();
2301
- const tpl = fs10.readFileSync(path10.join(tplDir, "open-gates.md"), "utf8");
2347
+ const tpl = fs11.readFileSync(path11.join(tplDir, "open-gates.md"), "utf8");
2302
2348
  const gate1 = state2.filter((i) => {
2303
2349
  if (i.bucket !== "proposals") return false;
2304
2350
  const status = String(i.fm["status"] ?? "");
@@ -2327,18 +2373,18 @@ function compile2(state2, templateDir) {
2327
2373
  return renderTemplate(tpl, data);
2328
2374
  }
2329
2375
  function resolveDefaultTemplateDir2() {
2330
- const __dirname = path10.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
2331
- return path10.resolve(__dirname, "..", "templates", "synthesis");
2376
+ const __dirname = path11.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
2377
+ return path11.resolve(__dirname, "..", "templates", "synthesis");
2332
2378
  }
2333
2379
 
2334
2380
  // src/wiki/synthesis/product-state.ts
2335
2381
  init_cjs_shims();
2336
- var fs11 = __toESM(require("fs"), 1);
2337
- var path11 = __toESM(require("path"), 1);
2382
+ var fs12 = __toESM(require("fs"), 1);
2383
+ var path12 = __toESM(require("path"), 1);
2338
2384
  var import_node_url3 = require("url");
2339
2385
  function compile3(state2, templateDir) {
2340
2386
  const tplDir = templateDir ?? resolveDefaultTemplateDir3();
2341
- const tpl = fs11.readFileSync(path11.join(tplDir, "product-state.md"), "utf8");
2387
+ const tpl = fs12.readFileSync(path12.join(tplDir, "product-state.md"), "utf8");
2342
2388
  function countBucket(bucket) {
2343
2389
  return state2.filter((i) => i.bucket === bucket);
2344
2390
  }
@@ -2385,18 +2431,18 @@ function compile3(state2, templateDir) {
2385
2431
  return renderTemplate(tpl, data);
2386
2432
  }
2387
2433
  function resolveDefaultTemplateDir3() {
2388
- const __dirname = path11.dirname((0, import_node_url3.fileURLToPath)(importMetaUrl));
2389
- return path11.resolve(__dirname, "..", "templates", "synthesis");
2434
+ const __dirname = path12.dirname((0, import_node_url3.fileURLToPath)(importMetaUrl));
2435
+ return path12.resolve(__dirname, "..", "templates", "synthesis");
2390
2436
  }
2391
2437
 
2392
2438
  // src/wiki/synthesis/roadmap.ts
2393
2439
  init_cjs_shims();
2394
- var fs12 = __toESM(require("fs"), 1);
2395
- var path12 = __toESM(require("path"), 1);
2440
+ var fs13 = __toESM(require("fs"), 1);
2441
+ var path13 = __toESM(require("path"), 1);
2396
2442
  var import_node_url4 = require("url");
2397
2443
  function compile4(state2, templateDir) {
2398
2444
  const tplDir = templateDir ?? resolveDefaultTemplateDir4();
2399
- const tpl = fs12.readFileSync(path12.join(tplDir, "roadmap.md"), "utf8");
2445
+ const tpl = fs13.readFileSync(path13.join(tplDir, "roadmap.md"), "utf8");
2400
2446
  const sprints = state2.filter((i) => i.bucket === "sprints");
2401
2447
  const epics = state2.filter((i) => i.bucket === "epics");
2402
2448
  const inFlightSprints = sprints.filter(
@@ -2449,8 +2495,8 @@ function isShippedStatus(status) {
2449
2495
  return status === "Completed" || status === "Approved";
2450
2496
  }
2451
2497
  function resolveDefaultTemplateDir4() {
2452
- const __dirname = path12.dirname((0, import_node_url4.fileURLToPath)(importMetaUrl));
2453
- return path12.resolve(__dirname, "..", "templates", "synthesis");
2498
+ const __dirname = path13.dirname((0, import_node_url4.fileURLToPath)(importMetaUrl));
2499
+ return path13.resolve(__dirname, "..", "templates", "synthesis");
2454
2500
  }
2455
2501
 
2456
2502
  // src/commands/wiki-build.ts
@@ -2475,16 +2521,16 @@ async function wikiBuildHandler(opts = {}) {
2475
2521
  const exit = opts.exit ?? ((c) => process.exit(c));
2476
2522
  const gitRunner = opts.gitRunner;
2477
2523
  const templateDir = opts.templateDir;
2478
- const deliveryRoot = path13.join(cwd, ".cleargate", "delivery");
2479
- const wikiRoot = path13.join(cwd, ".cleargate", "wiki");
2480
- if (!fs13.existsSync(deliveryRoot)) {
2524
+ const deliveryRoot = path14.join(cwd, ".cleargate", "delivery");
2525
+ const wikiRoot = path14.join(cwd, ".cleargate", "wiki");
2526
+ if (!fs14.existsSync(deliveryRoot)) {
2481
2527
  stderr(`wiki build: .cleargate/delivery/ not found at ${deliveryRoot}
2482
2528
  `);
2483
2529
  exit(1);
2484
2530
  return;
2485
2531
  }
2486
2532
  for (const bucket of BUCKET_ORDER) {
2487
- fs13.mkdirSync(path13.join(wikiRoot, bucket), { recursive: true });
2533
+ fs14.mkdirSync(path14.join(wikiRoot, bucket), { recursive: true });
2488
2534
  }
2489
2535
  const items = scanRawItems(deliveryRoot, cwd);
2490
2536
  const timestamp = now();
@@ -2507,19 +2553,19 @@ async function wikiBuildHandler(opts = {}) {
2507
2553
  };
2508
2554
  const body = buildPageBody(item, wikiPage);
2509
2555
  const content = serializePage(wikiPage, body);
2510
- const pageDir = path13.join(wikiRoot, item.bucket);
2511
- fs13.mkdirSync(pageDir, { recursive: true });
2512
- fs13.writeFileSync(path13.join(pageDir, `${item.id}.md`), content, "utf8");
2556
+ const pageDir = path14.join(wikiRoot, item.bucket);
2557
+ fs14.mkdirSync(pageDir, { recursive: true });
2558
+ fs14.writeFileSync(path14.join(pageDir, `${item.id}.md`), content, "utf8");
2513
2559
  pagesWritten++;
2514
2560
  }
2515
2561
  const indexContent = buildIndex(items);
2516
- fs13.writeFileSync(path13.join(wikiRoot, "index.md"), indexContent, "utf8");
2562
+ fs14.writeFileSync(path14.join(wikiRoot, "index.md"), indexContent, "utf8");
2517
2563
  const logContent = buildLog(items, timestamp);
2518
- fs13.writeFileSync(path13.join(wikiRoot, "log.md"), logContent, "utf8");
2519
- fs13.writeFileSync(path13.join(wikiRoot, "active-sprint.md"), compile(items, templateDir), "utf8");
2520
- fs13.writeFileSync(path13.join(wikiRoot, "open-gates.md"), compile2(items, templateDir), "utf8");
2521
- fs13.writeFileSync(path13.join(wikiRoot, "product-state.md"), compile3(items, templateDir), "utf8");
2522
- fs13.writeFileSync(path13.join(wikiRoot, "roadmap.md"), compile4(items, templateDir), "utf8");
2564
+ fs14.writeFileSync(path14.join(wikiRoot, "log.md"), logContent, "utf8");
2565
+ fs14.writeFileSync(path14.join(wikiRoot, "active-sprint.md"), compile(items, templateDir), "utf8");
2566
+ fs14.writeFileSync(path14.join(wikiRoot, "open-gates.md"), compile2(items, templateDir), "utf8");
2567
+ fs14.writeFileSync(path14.join(wikiRoot, "product-state.md"), compile3(items, templateDir), "utf8");
2568
+ fs14.writeFileSync(path14.join(wikiRoot, "roadmap.md"), compile4(items, templateDir), "utf8");
2523
2569
  stdout(`wiki build: OK (${pagesWritten} pages written)
2524
2570
  `);
2525
2571
  }
@@ -2686,7 +2732,7 @@ function buildLog(items, timestamp) {
2686
2732
  init_cjs_shims();
2687
2733
  var import_promises2 = require("fs/promises");
2688
2734
  var import_node_fs = require("fs");
2689
- var path14 = __toESM(require("path"), 1);
2735
+ var path15 = __toESM(require("path"), 1);
2690
2736
 
2691
2737
  // src/lib/sha256.ts
2692
2738
  init_cjs_shims();
@@ -2710,23 +2756,23 @@ function shortHash(full) {
2710
2756
  // src/lib/manifest.ts
2711
2757
  function resolveDefaultPackageRoot() {
2712
2758
  const here = new URL(".", importMetaUrl).pathname;
2713
- const distCandidate = path14.join(here, "MANIFEST.json");
2759
+ const distCandidate = path15.join(here, "MANIFEST.json");
2714
2760
  if ((0, import_node_fs.existsSync)(distCandidate)) {
2715
2761
  return here;
2716
2762
  }
2717
- const oneLevelUp = path14.join(here, "..", "MANIFEST.json");
2763
+ const oneLevelUp = path15.join(here, "..", "MANIFEST.json");
2718
2764
  if ((0, import_node_fs.existsSync)(oneLevelUp)) {
2719
- return path14.join(here, "..");
2765
+ return path15.join(here, "..");
2720
2766
  }
2721
- const devCandidate = path14.join(here, "..", "..", "..", "cleargate-planning", "MANIFEST.json");
2767
+ const devCandidate = path15.join(here, "..", "..", "..", "cleargate-planning", "MANIFEST.json");
2722
2768
  if ((0, import_node_fs.existsSync)(devCandidate)) {
2723
- return path14.join(here, "..", "..", "..", "cleargate-planning");
2769
+ return path15.join(here, "..", "..", "..", "cleargate-planning");
2724
2770
  }
2725
2771
  return here;
2726
2772
  }
2727
2773
  function loadPackageManifest(opts) {
2728
2774
  const packageRoot = opts?.packageRoot ?? resolveDefaultPackageRoot();
2729
- const manifestPath = path14.join(packageRoot, "MANIFEST.json");
2775
+ const manifestPath = path15.join(packageRoot, "MANIFEST.json");
2730
2776
  if (!(0, import_node_fs.existsSync)(manifestPath)) {
2731
2777
  throw new Error(
2732
2778
  `MANIFEST.json not found at ${manifestPath}; run 'npm run build' to generate it.`
@@ -2743,7 +2789,7 @@ function loadPackageManifest(opts) {
2743
2789
  return JSON.parse(raw);
2744
2790
  }
2745
2791
  async function loadInstallSnapshot(projectRoot) {
2746
- const snapshotPath = path14.join(projectRoot, ".cleargate", ".install-manifest.json");
2792
+ const snapshotPath = path15.join(projectRoot, ".cleargate", ".install-manifest.json");
2747
2793
  try {
2748
2794
  const raw = await (0, import_promises2.readFile)(snapshotPath, "utf-8");
2749
2795
  return JSON.parse(raw);
@@ -2752,7 +2798,7 @@ async function loadInstallSnapshot(projectRoot) {
2752
2798
  }
2753
2799
  }
2754
2800
  async function computeCurrentSha(file, projectRoot) {
2755
- const filePath = path14.join(projectRoot, file.path);
2801
+ const filePath = path15.join(projectRoot, file.path);
2756
2802
  try {
2757
2803
  const raw = await (0, import_promises2.readFile)(filePath);
2758
2804
  return hashNormalized(raw);
@@ -2781,8 +2827,8 @@ function classify(pkgSha, installSha, currentSha, tier) {
2781
2827
  return "both-changed";
2782
2828
  }
2783
2829
  async function writeDriftState(projectRoot, state2, opts) {
2784
- const cleargatDir = path14.join(projectRoot, ".cleargate");
2785
- const finalPath = path14.join(cleargatDir, ".drift-state.json");
2830
+ const cleargatDir = path15.join(projectRoot, ".cleargate");
2831
+ const finalPath = path15.join(cleargatDir, ".drift-state.json");
2786
2832
  const tmpPath = `${finalPath}.tmp`;
2787
2833
  const lastRefreshed = opts?.lastRefreshed ?? (/* @__PURE__ */ new Date()).toISOString();
2788
2834
  const fileContent = { last_refreshed: lastRefreshed, drift: state2 };
@@ -2791,7 +2837,7 @@ async function writeDriftState(projectRoot, state2, opts) {
2791
2837
  await (0, import_promises2.rename)(tmpPath, finalPath);
2792
2838
  }
2793
2839
  async function readDriftState(projectRoot) {
2794
- const driftPath = path14.join(projectRoot, ".cleargate", ".drift-state.json");
2840
+ const driftPath = path15.join(projectRoot, ".cleargate", ".drift-state.json");
2795
2841
  try {
2796
2842
  const raw = await (0, import_promises2.readFile)(driftPath, "utf-8");
2797
2843
  const parsed = JSON.parse(raw);
@@ -2866,24 +2912,24 @@ async function promptEmail(question, defaultValue, opts) {
2866
2912
 
2867
2913
  // src/lib/identity.ts
2868
2914
  init_cjs_shims();
2869
- var fs14 = __toESM(require("fs"), 1);
2870
- var path15 = __toESM(require("path"), 1);
2915
+ var fs15 = __toESM(require("fs"), 1);
2916
+ var path16 = __toESM(require("path"), 1);
2871
2917
  var fsPromises = __toESM(require("fs/promises"), 1);
2872
2918
  var os5 = __toESM(require("os"), 1);
2873
2919
  var import_node_child_process2 = require("child_process");
2874
2920
  function readParticipant(projectRoot) {
2875
- const filePath = path15.join(projectRoot, ".cleargate", ".participant.json");
2921
+ const filePath = path16.join(projectRoot, ".cleargate", ".participant.json");
2876
2922
  try {
2877
- const raw = fs14.readFileSync(filePath, "utf8");
2923
+ const raw = fs15.readFileSync(filePath, "utf8");
2878
2924
  return JSON.parse(raw);
2879
2925
  } catch {
2880
2926
  return null;
2881
2927
  }
2882
2928
  }
2883
2929
  async function writeParticipant(projectRoot, email, source, now = () => (/* @__PURE__ */ new Date()).toISOString()) {
2884
- const cleargateDir = path15.join(projectRoot, ".cleargate");
2930
+ const cleargateDir = path16.join(projectRoot, ".cleargate");
2885
2931
  await fsPromises.mkdir(cleargateDir, { recursive: true });
2886
- const filePath = path15.join(cleargateDir, ".participant.json");
2932
+ const filePath = path16.join(cleargateDir, ".participant.json");
2887
2933
  const tmpPath = filePath + ".tmp." + Date.now();
2888
2934
  const content = {
2889
2935
  email,
@@ -2959,16 +3005,16 @@ var HOOK_ADDITION = {
2959
3005
  };
2960
3006
  function resolveDefaultPayloadDir() {
2961
3007
  const thisFile = (0, import_node_url5.fileURLToPath)(importMetaUrl);
2962
- const pkgRoot = path16.resolve(path16.dirname(thisFile), "..");
2963
- return path16.join(pkgRoot, "templates", "cleargate-planning");
3008
+ const pkgRoot = path17.resolve(path17.dirname(thisFile), "..");
3009
+ return path17.join(pkgRoot, "templates", "cleargate-planning");
2964
3010
  }
2965
3011
  function countDeliveryItems(cwd) {
2966
- const pendingSync = path16.join(cwd, ".cleargate", "delivery", "pending-sync");
2967
- const archive = path16.join(cwd, ".cleargate", "delivery", "archive");
3012
+ const pendingSync = path17.join(cwd, ".cleargate", "delivery", "pending-sync");
3013
+ const archive = path17.join(cwd, ".cleargate", "delivery", "archive");
2968
3014
  let count = 0;
2969
3015
  for (const dir of [pendingSync, archive]) {
2970
- if (!fs15.existsSync(dir)) continue;
2971
- const entries = fs15.readdirSync(dir);
3016
+ if (!fs16.existsSync(dir)) continue;
3017
+ const entries = fs16.readdirSync(dir);
2972
3018
  for (const f of entries) {
2973
3019
  if (f.endsWith(".md") && f !== ".gitkeep") count++;
2974
3020
  }
@@ -2977,12 +3023,12 @@ function countDeliveryItems(cwd) {
2977
3023
  }
2978
3024
  function writeAtomic(filePath, content) {
2979
3025
  const tmpPath = filePath + ".tmp." + Date.now();
2980
- fs15.writeFileSync(tmpPath, content, "utf8");
2981
- fs15.renameSync(tmpPath, filePath);
3026
+ fs16.writeFileSync(tmpPath, content, "utf8");
3027
+ fs16.renameSync(tmpPath, filePath);
2982
3028
  }
2983
3029
  function readPackageVersion(packageJsonPath) {
2984
3030
  try {
2985
- const raw = fs15.readFileSync(packageJsonPath, "utf8");
3031
+ const raw = fs16.readFileSync(packageJsonPath, "utf8");
2986
3032
  const pkg = JSON.parse(raw);
2987
3033
  if (typeof pkg.version === "string" && pkg.version.length > 0) {
2988
3034
  return pkg.version;
@@ -3002,16 +3048,16 @@ async function initHandler(opts = {}) {
3002
3048
  const promptYesNoFn = opts.promptYesNo ?? promptYesNo;
3003
3049
  const promptEmailFn = opts.promptEmail ?? promptEmail;
3004
3050
  const spawnSyncFn = opts.spawnSyncFn ?? import_node_child_process3.spawnSync;
3005
- if (!fs15.existsSync(cwd)) {
3051
+ if (!fs16.existsSync(cwd)) {
3006
3052
  stderr(`[cleargate init] ERROR: target directory does not exist: ${cwd}
3007
3053
  `);
3008
3054
  exit(1);
3009
3055
  return;
3010
3056
  }
3011
- const testWritePath = path16.join(cwd, `.cleargate-init-write-test-${Date.now()}`);
3057
+ const testWritePath = path17.join(cwd, `.cleargate-init-write-test-${Date.now()}`);
3012
3058
  try {
3013
- fs15.writeFileSync(testWritePath, "");
3014
- fs15.unlinkSync(testWritePath);
3059
+ fs16.writeFileSync(testWritePath, "");
3060
+ fs16.unlinkSync(testWritePath);
3015
3061
  } catch {
3016
3062
  stderr(`[cleargate init] ERROR: target directory is not writable: ${cwd}
3017
3063
  `);
@@ -3021,7 +3067,7 @@ async function initHandler(opts = {}) {
3021
3067
  stdout(`[cleargate init] Target: ${cwd}
3022
3068
  `);
3023
3069
  const payloadDir = opts.payloadDir ?? resolveDefaultPayloadDir();
3024
- if (!fs15.existsSync(payloadDir)) {
3070
+ if (!fs16.existsSync(payloadDir)) {
3025
3071
  stderr(`[cleargate init] ERROR: payload directory not found: ${payloadDir}
3026
3072
  `);
3027
3073
  stderr(`[cleargate init] Run \`npm run prebuild\` to copy the payload first.
@@ -3029,12 +3075,12 @@ async function initHandler(opts = {}) {
3029
3075
  exit(1);
3030
3076
  return;
3031
3077
  }
3032
- const uninstalledMarkerPath = path16.join(cwd, ".cleargate", ".uninstalled");
3078
+ const uninstalledMarkerPath = path17.join(cwd, ".cleargate", ".uninstalled");
3033
3079
  let uninstalledMarker = null;
3034
3080
  let userChoseRestore = false;
3035
- if (fs15.existsSync(uninstalledMarkerPath)) {
3081
+ if (fs16.existsSync(uninstalledMarkerPath)) {
3036
3082
  try {
3037
- const raw = fs15.readFileSync(uninstalledMarkerPath, "utf8");
3083
+ const raw = fs16.readFileSync(uninstalledMarkerPath, "utf8");
3038
3084
  uninstalledMarker = JSON.parse(raw);
3039
3085
  } catch {
3040
3086
  stderr(`[cleargate init] WARNING: .uninstalled marker is malformed; ignoring it.
@@ -3046,8 +3092,8 @@ async function initHandler(opts = {}) {
3046
3092
  userChoseRestore = await promptYesNoFn(question, true);
3047
3093
  if (userChoseRestore) {
3048
3094
  for (const preservedPath of preserved) {
3049
- const absPreserved = path16.isAbsolute(preservedPath) ? preservedPath : path16.join(cwd, preservedPath);
3050
- if (fs15.existsSync(absPreserved)) {
3095
+ const absPreserved = path17.isAbsolute(preservedPath) ? preservedPath : path17.join(cwd, preservedPath);
3096
+ if (fs16.existsSync(absPreserved)) {
3051
3097
  stdout(`[cleargate init] [preserved] ${preservedPath}
3052
3098
  `);
3053
3099
  } else {
@@ -3067,8 +3113,8 @@ async function initHandler(opts = {}) {
3067
3113
  if (opts.pin) {
3068
3114
  pinVersion = opts.pin;
3069
3115
  } else {
3070
- const payloadParent = path16.resolve(payloadDir, "..", "..");
3071
- pinVersion = readPackageVersion(path16.join(payloadParent, "package.json")) ?? readPackageVersion(path16.join(path16.dirname((0, import_node_url5.fileURLToPath)(importMetaUrl)), "..", "package.json")) ?? "latest";
3116
+ const payloadParent = path17.resolve(payloadDir, "..", "..");
3117
+ pinVersion = readPackageVersion(path17.join(payloadParent, "package.json")) ?? readPackageVersion(path17.join(path17.dirname((0, import_node_url5.fileURLToPath)(importMetaUrl)), "..", "package.json")) ?? "latest";
3072
3118
  }
3073
3119
  const copyReport = copyPayload(payloadDir, cwd, { force, pinVersion });
3074
3120
  for (const action of copyReport.actions) {
@@ -3076,33 +3122,33 @@ async function initHandler(opts = {}) {
3076
3122
  stdout(`[cleargate init] ${verb} ${action.relPath}
3077
3123
  `);
3078
3124
  }
3079
- const settingsPath = path16.join(cwd, ".claude", "settings.json");
3125
+ const settingsPath = path17.join(cwd, ".claude", "settings.json");
3080
3126
  let existingSettings = null;
3081
- if (fs15.existsSync(settingsPath)) {
3127
+ if (fs16.existsSync(settingsPath)) {
3082
3128
  try {
3083
- existingSettings = JSON.parse(fs15.readFileSync(settingsPath, "utf8"));
3129
+ existingSettings = JSON.parse(fs16.readFileSync(settingsPath, "utf8"));
3084
3130
  } catch {
3085
3131
  stderr(`[cleargate init] WARNING: could not parse ${settingsPath}; treating as empty.
3086
3132
  `);
3087
3133
  }
3088
3134
  }
3089
3135
  const mergedSettings = mergeSettings(existingSettings, HOOK_ADDITION);
3090
- fs15.mkdirSync(path16.dirname(settingsPath), { recursive: true });
3136
+ fs16.mkdirSync(path17.dirname(settingsPath), { recursive: true });
3091
3137
  writeAtomic(settingsPath, JSON.stringify(mergedSettings, null, 2) + "\n");
3092
3138
  stdout(`[cleargate init] Updated .claude/settings.json: merged PostToolUse hook
3093
3139
  `);
3094
- const claudeMdPath = path16.join(cwd, "CLAUDE.md");
3095
- const claudeMdSrcPath = path16.join(payloadDir, "CLAUDE.md");
3140
+ const claudeMdPath = path17.join(cwd, "CLAUDE.md");
3141
+ const claudeMdSrcPath = path17.join(payloadDir, "CLAUDE.md");
3096
3142
  let claudeMdBlock;
3097
3143
  try {
3098
- const claudeMdSrc = fs15.readFileSync(claudeMdSrcPath, "utf8");
3144
+ const claudeMdSrc = fs16.readFileSync(claudeMdSrcPath, "utf8");
3099
3145
  claudeMdBlock = extractBlock(claudeMdSrc);
3100
3146
  } catch (e) {
3101
3147
  stderr(`[cleargate init] WARNING: could not read CLAUDE.md block from payload: ${String(e)}
3102
3148
  `);
3103
3149
  claudeMdBlock = "<!-- CLEARGATE:START -->\n<!-- CLEARGATE:END -->";
3104
3150
  }
3105
- const existingClaudeMd = fs15.existsSync(claudeMdPath) ? fs15.readFileSync(claudeMdPath, "utf8") : null;
3151
+ const existingClaudeMd = fs16.existsSync(claudeMdPath) ? fs16.readFileSync(claudeMdPath, "utf8") : null;
3106
3152
  const newClaudeMd = injectClaudeMd(existingClaudeMd, claudeMdBlock);
3107
3153
  writeAtomic(claudeMdPath, newClaudeMd);
3108
3154
  if (existingClaudeMd === null) {
@@ -3113,6 +3159,26 @@ async function initHandler(opts = {}) {
3113
3159
  `);
3114
3160
  } else {
3115
3161
  stdout(`[cleargate init] CLAUDE.md unchanged (block already up to date)
3162
+ `);
3163
+ }
3164
+ try {
3165
+ const action = injectMcpJson(cwd, "https://cleargate-mcp.soula.ge/mcp");
3166
+ if (action === "created") {
3167
+ stdout(
3168
+ `[cleargate init] Created .mcp.json (cleargate MCP server registered) \u2014 restart Claude Code to load it.
3169
+ `
3170
+ );
3171
+ } else if (action === "updated") {
3172
+ stdout(
3173
+ `[cleargate init] Updated .mcp.json (cleargate MCP server entry merged) \u2014 restart Claude Code to pick up changes.
3174
+ `
3175
+ );
3176
+ } else {
3177
+ stdout(`[cleargate init] .mcp.json unchanged (cleargate entry already present)
3178
+ `);
3179
+ }
3180
+ } catch (e) {
3181
+ stderr(`[cleargate init] WARNING: ${String(e instanceof Error ? e.message : e)}
3116
3182
  `);
3117
3183
  }
3118
3184
  const itemCount = countDeliveryItems(cwd);
@@ -3126,9 +3192,9 @@ async function initHandler(opts = {}) {
3126
3192
  stdout(`[cleargate init] Bootstrap: no items to ingest, skipping build
3127
3193
  `);
3128
3194
  }
3129
- const cleargateDir = path16.join(cwd, ".cleargate");
3130
- fs15.mkdirSync(cleargateDir, { recursive: true });
3131
- const snapshotPath = path16.join(cleargateDir, ".install-manifest.json");
3195
+ const cleargateDir = path17.join(cwd, ".cleargate");
3196
+ fs16.mkdirSync(cleargateDir, { recursive: true });
3197
+ const snapshotPath = path17.join(cleargateDir, ".install-manifest.json");
3132
3198
  try {
3133
3199
  const readManifest = opts.readInstallManifest ?? (() => loadPackageManifest({ packageRoot: payloadDir }));
3134
3200
  const pkgManifest = readManifest();
@@ -3143,19 +3209,19 @@ async function initHandler(opts = {}) {
3143
3209
  stderr(`[cleargate init] WARNING: could not write install snapshot: ${String(e)}
3144
3210
  `);
3145
3211
  }
3146
- if (uninstalledMarker !== null && fs15.existsSync(uninstalledMarkerPath)) {
3212
+ if (uninstalledMarker !== null && fs16.existsSync(uninstalledMarkerPath)) {
3147
3213
  try {
3148
- fs15.unlinkSync(uninstalledMarkerPath);
3214
+ fs16.unlinkSync(uninstalledMarkerPath);
3149
3215
  } catch (e) {
3150
3216
  stderr(`[cleargate init] WARNING: could not remove .uninstalled marker: ${String(e)}
3151
3217
  `);
3152
3218
  }
3153
3219
  }
3154
3220
  {
3155
- const distCliPath = path16.join(cwd, "cleargate-cli", "dist", "cli.js");
3221
+ const distCliPath = path17.join(cwd, "cleargate-cli", "dist", "cli.js");
3156
3222
  let branch = null;
3157
3223
  let branchLabel = "";
3158
- if (fs15.existsSync(distCliPath)) {
3224
+ if (fs16.existsSync(distCliPath)) {
3159
3225
  branch = { cmd: "node", args: [distCliPath, "--version"] };
3160
3226
  branchLabel = `local dist (${distCliPath})`;
3161
3227
  } else {
@@ -3227,8 +3293,8 @@ async function initHandler(opts = {}) {
3227
3293
 
3228
3294
  // src/commands/wiki-ingest.ts
3229
3295
  init_cjs_shims();
3230
- var fs16 = __toESM(require("fs"), 1);
3231
- var path17 = __toESM(require("path"), 1);
3296
+ var fs17 = __toESM(require("fs"), 1);
3297
+ var path18 = __toESM(require("path"), 1);
3232
3298
  var import_node_child_process4 = require("child_process");
3233
3299
  var EXCLUDED_SUFFIXES2 = [
3234
3300
  ".cleargate/knowledge/",
@@ -3254,16 +3320,16 @@ async function wikiIngestHandler(opts) {
3254
3320
  const stderr = opts.stderr ?? ((s) => process.stderr.write(s));
3255
3321
  const exit = opts.exit ?? ((c) => process.exit(c));
3256
3322
  const gitRunner = opts.gitRunner;
3257
- const rename12 = opts.rename ?? fs16.renameSync;
3323
+ const rename12 = opts.rename ?? fs17.renameSync;
3258
3324
  const templateDir = opts.templateDir;
3259
3325
  const rawPath = opts.rawPath;
3260
- const absRawPath = path17.isAbsolute(rawPath) ? rawPath : path17.resolve(cwd, rawPath);
3261
- const relRawPath = path17.relative(cwd, absRawPath).replace(/\\/g, "/");
3262
- const deliveryRoot = path17.join(cwd, ".cleargate", "delivery");
3326
+ const absRawPath = path18.isAbsolute(rawPath) ? rawPath : path18.resolve(cwd, rawPath);
3327
+ const relRawPath = path18.relative(cwd, absRawPath).replace(/\\/g, "/");
3328
+ const deliveryRoot = path18.join(cwd, ".cleargate", "delivery");
3263
3329
  const deliveryRootNorm = deliveryRoot.replace(/\\/g, "/");
3264
3330
  const absDeliveryRoot = deliveryRoot;
3265
- const relToDelivery = path17.relative(absDeliveryRoot, absRawPath);
3266
- if (relToDelivery.startsWith("..") || path17.isAbsolute(relToDelivery)) {
3331
+ const relToDelivery = path18.relative(absDeliveryRoot, absRawPath);
3332
+ if (relToDelivery.startsWith("..") || path18.isAbsolute(relToDelivery)) {
3267
3333
  stderr(`wiki ingest: ${rawPath} not under .cleargate/delivery/
3268
3334
  `);
3269
3335
  exit(2);
@@ -3277,7 +3343,7 @@ async function wikiIngestHandler(opts) {
3277
3343
  exit(0);
3278
3344
  return;
3279
3345
  }
3280
- const filename = path17.basename(absRawPath);
3346
+ const filename = path18.basename(absRawPath);
3281
3347
  let bucketInfo;
3282
3348
  try {
3283
3349
  bucketInfo = deriveBucket(filename);
@@ -3297,12 +3363,12 @@ async function wikiIngestHandler(opts) {
3297
3363
  return;
3298
3364
  }
3299
3365
  const { type, id, bucket } = bucketInfo;
3300
- const wikiRoot = path17.join(cwd, ".cleargate", "wiki");
3301
- const pageDir = path17.join(wikiRoot, bucket);
3302
- const pagePath = path17.join(pageDir, `${id}.md`);
3366
+ const wikiRoot = path18.join(cwd, ".cleargate", "wiki");
3367
+ const pageDir = path18.join(wikiRoot, bucket);
3368
+ const pagePath = path18.join(pageDir, `${id}.md`);
3303
3369
  let rawContent;
3304
3370
  try {
3305
- rawContent = fs16.readFileSync(absRawPath, "utf8");
3371
+ rawContent = fs17.readFileSync(absRawPath, "utf8");
3306
3372
  } catch (e) {
3307
3373
  stderr(`wiki ingest: cannot read ${rawPath}: ${e.message}
3308
3374
  `);
@@ -3322,11 +3388,11 @@ async function wikiIngestHandler(opts) {
3322
3388
  return;
3323
3389
  }
3324
3390
  const currentSha = getGitSha(absRawPath, gitRunner) ?? "";
3325
- const pageExists = fs16.existsSync(pagePath);
3391
+ const pageExists = fs17.existsSync(pagePath);
3326
3392
  if (pageExists && currentSha !== "") {
3327
3393
  let isNoOp = false;
3328
3394
  try {
3329
- const existingPageContent = fs16.readFileSync(pagePath, "utf8");
3395
+ const existingPageContent = fs17.readFileSync(pagePath, "utf8");
3330
3396
  const existingPage = parsePage(existingPageContent);
3331
3397
  if (existingPage.last_ingest_commit === currentSha) {
3332
3398
  const contentUnchanged = checkContentUnchanged(absRawPath, currentSha, relRawPath, gitRunner);
@@ -3361,8 +3427,8 @@ async function wikiIngestHandler(opts) {
3361
3427
  };
3362
3428
  const pageBody = buildPageBody2({ id, fm, body });
3363
3429
  const pageContent = serializePage(wikiPage, pageBody);
3364
- fs16.mkdirSync(pageDir, { recursive: true });
3365
- fs16.writeFileSync(pagePath, pageContent, "utf8");
3430
+ fs17.mkdirSync(pageDir, { recursive: true });
3431
+ fs17.writeFileSync(pagePath, pageContent, "utf8");
3366
3432
  appendLogEntry(wikiRoot, { timestamp, action, id, relRawPath });
3367
3433
  updateIndex(wikiRoot, { id, type, status: wikiPage.status, relRawPath, rename: rename12 });
3368
3434
  recompileSynthesis(wikiRoot, cwd, templateDir);
@@ -3374,7 +3440,7 @@ function checkContentUnchanged(absRawPath, sha, relRawPath, gitRunner) {
3374
3440
  const run = gitRunner ?? defaultGitRunner;
3375
3441
  const gitContent = run("git", ["show", `${sha}:${relRawPath}`]);
3376
3442
  if (!gitContent && gitContent !== "") return false;
3377
- const currentContent = fs16.readFileSync(absRawPath, "utf8");
3443
+ const currentContent = fs17.readFileSync(absRawPath, "utf8");
3378
3444
  return gitContent === currentContent;
3379
3445
  } catch {
3380
3446
  return false;
@@ -3427,7 +3493,7 @@ function buildPageBody2(item) {
3427
3493
  ].join("\n");
3428
3494
  }
3429
3495
  function appendLogEntry(wikiRoot, entry) {
3430
- const logPath = path17.join(wikiRoot, "log.md");
3496
+ const logPath = path18.join(wikiRoot, "log.md");
3431
3497
  const logEntry = [
3432
3498
  `- timestamp: "${entry.timestamp}"`,
3433
3499
  ` actor: "cleargate wiki ingest"`,
@@ -3435,25 +3501,25 @@ function appendLogEntry(wikiRoot, entry) {
3435
3501
  ` target: "${entry.id}"`,
3436
3502
  ` path: "${entry.relRawPath}"`
3437
3503
  ].join("\n");
3438
- if (fs16.existsSync(logPath)) {
3439
- const existing = fs16.readFileSync(logPath, "utf8");
3504
+ if (fs17.existsSync(logPath)) {
3505
+ const existing = fs17.readFileSync(logPath, "utf8");
3440
3506
  const newContent = existing.trimEnd() + "\n" + logEntry + "\n";
3441
- fs16.writeFileSync(logPath, newContent, "utf8");
3507
+ fs17.writeFileSync(logPath, newContent, "utf8");
3442
3508
  } else {
3443
- fs16.mkdirSync(wikiRoot, { recursive: true });
3444
- fs16.writeFileSync(logPath, `# Wiki Event Log
3509
+ fs17.mkdirSync(wikiRoot, { recursive: true });
3510
+ fs17.writeFileSync(logPath, `# Wiki Event Log
3445
3511
 
3446
3512
  ${logEntry}
3447
3513
  `, "utf8");
3448
3514
  }
3449
3515
  }
3450
3516
  function updateIndex(wikiRoot, opts) {
3451
- const indexPath = path17.join(wikiRoot, "index.md");
3517
+ const indexPath = path18.join(wikiRoot, "index.md");
3452
3518
  const tmpPath = `${indexPath}.tmp`;
3453
3519
  const newRow = `| [[${opts.id}]] | ${opts.type} | ${opts.status} | ${opts.relRawPath} |`;
3454
3520
  let content;
3455
- if (fs16.existsSync(indexPath)) {
3456
- content = fs16.readFileSync(indexPath, "utf8");
3521
+ if (fs17.existsSync(indexPath)) {
3522
+ content = fs17.readFileSync(indexPath, "utf8");
3457
3523
  const idPattern = `[[${opts.id}]]`;
3458
3524
  const lines = content.split("\n");
3459
3525
  let replaced = false;
@@ -3472,7 +3538,7 @@ function updateIndex(wikiRoot, opts) {
3472
3538
  } else {
3473
3539
  content = buildMinimalIndex(opts.id, opts.type, opts.status, opts.relRawPath);
3474
3540
  }
3475
- fs16.writeFileSync(tmpPath, content, "utf8");
3541
+ fs17.writeFileSync(tmpPath, content, "utf8");
3476
3542
  opts.rename(tmpPath, indexPath);
3477
3543
  }
3478
3544
  function insertIntoSection(content, id, newRow) {
@@ -3567,41 +3633,41 @@ function buildMinimalIndex(id, type, status, relRawPath) {
3567
3633
  return lines.join("\n");
3568
3634
  }
3569
3635
  function recompileSynthesis(wikiRoot, cwd, templateDir) {
3570
- const deliveryRoot = path17.join(cwd, ".cleargate", "delivery");
3636
+ const deliveryRoot = path18.join(cwd, ".cleargate", "delivery");
3571
3637
  let items = [];
3572
- if (fs16.existsSync(deliveryRoot)) {
3638
+ if (fs17.existsSync(deliveryRoot)) {
3573
3639
  try {
3574
3640
  items = scanRawItems(deliveryRoot, cwd);
3575
3641
  } catch {
3576
3642
  }
3577
3643
  }
3578
- fs16.writeFileSync(path17.join(wikiRoot, "active-sprint.md"), compile(items, templateDir), "utf8");
3579
- fs16.writeFileSync(path17.join(wikiRoot, "open-gates.md"), compile2(items, templateDir), "utf8");
3580
- fs16.writeFileSync(path17.join(wikiRoot, "product-state.md"), compile3(items, templateDir), "utf8");
3581
- fs16.writeFileSync(path17.join(wikiRoot, "roadmap.md"), compile4(items, templateDir), "utf8");
3644
+ fs17.writeFileSync(path18.join(wikiRoot, "active-sprint.md"), compile(items, templateDir), "utf8");
3645
+ fs17.writeFileSync(path18.join(wikiRoot, "open-gates.md"), compile2(items, templateDir), "utf8");
3646
+ fs17.writeFileSync(path18.join(wikiRoot, "product-state.md"), compile3(items, templateDir), "utf8");
3647
+ fs17.writeFileSync(path18.join(wikiRoot, "roadmap.md"), compile4(items, templateDir), "utf8");
3582
3648
  }
3583
3649
 
3584
3650
  // src/commands/wiki-lint.ts
3585
3651
  init_cjs_shims();
3586
- var path21 = __toESM(require("path"), 1);
3652
+ var path22 = __toESM(require("path"), 1);
3587
3653
 
3588
3654
  // src/wiki/load-wiki.ts
3589
3655
  init_cjs_shims();
3590
- var fs17 = __toESM(require("fs"), 1);
3591
- var path18 = __toESM(require("path"), 1);
3656
+ var fs18 = __toESM(require("fs"), 1);
3657
+ var path19 = __toESM(require("path"), 1);
3592
3658
  var BUCKET_DIRS = ["epics", "stories", "sprints", "proposals", "crs", "bugs", "topics"];
3593
3659
  function loadWikiPages(wikiRoot) {
3594
3660
  const results = [];
3595
3661
  for (const bucket of BUCKET_DIRS) {
3596
- const dir = path18.join(wikiRoot, bucket);
3597
- if (!fs17.existsSync(dir)) continue;
3598
- const entries = fs17.readdirSync(dir, { encoding: "utf8" });
3662
+ const dir = path19.join(wikiRoot, bucket);
3663
+ if (!fs18.existsSync(dir)) continue;
3664
+ const entries = fs18.readdirSync(dir, { encoding: "utf8" });
3599
3665
  for (const filename of entries) {
3600
3666
  if (!filename.endsWith(".md")) continue;
3601
- const absPath = path18.join(dir, filename);
3602
- const stat = fs17.statSync(absPath);
3667
+ const absPath = path19.join(dir, filename);
3668
+ const stat = fs18.statSync(absPath);
3603
3669
  if (!stat.isFile()) continue;
3604
- const raw = fs17.readFileSync(absPath, "utf8");
3670
+ const raw = fs18.readFileSync(absPath, "utf8");
3605
3671
  let fm;
3606
3672
  let body;
3607
3673
  try {
@@ -3631,8 +3697,8 @@ function loadWikiPages(wikiRoot) {
3631
3697
 
3632
3698
  // src/wiki/lint-checks.ts
3633
3699
  init_cjs_shims();
3634
- var fs18 = __toESM(require("fs"), 1);
3635
- var path19 = __toESM(require("path"), 1);
3700
+ var fs19 = __toESM(require("fs"), 1);
3701
+ var path20 = __toESM(require("path"), 1);
3636
3702
  var import_node_child_process5 = require("child_process");
3637
3703
  var import_js_yaml3 = __toESM(require("js-yaml"), 1);
3638
3704
 
@@ -3692,9 +3758,9 @@ function checkOrphan(page, repoRoot) {
3692
3758
  if (!rawPath) return null;
3693
3759
  const isExcluded = EXCLUDED_DIRS.some((excl) => rawPath.startsWith(excl));
3694
3760
  if (isExcluded) return null;
3695
- const absRaw = path19.join(repoRoot, rawPath);
3696
- if (!fs18.existsSync(absRaw)) {
3697
- const relPage = path19.relative(path19.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3761
+ const absRaw = path20.join(repoRoot, rawPath);
3762
+ if (!fs19.existsSync(absRaw)) {
3763
+ const relPage = path20.relative(path20.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3698
3764
  return {
3699
3765
  category: "orphan",
3700
3766
  line: `orphan: ${relPage} -> missing ${rawPath} (raw missing)`
@@ -3712,7 +3778,7 @@ function checkRepoMismatch(page, repoRoot) {
3712
3778
  return null;
3713
3779
  }
3714
3780
  if (page.page.repo !== derivedRepo) {
3715
- const relPage = path19.relative(path19.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3781
+ const relPage = path20.relative(path20.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3716
3782
  return {
3717
3783
  category: "repo-mismatch",
3718
3784
  line: `repo-mismatch: ${relPage} declares repo:${page.page.repo} but raw_path implies repo:${derivedRepo}`
@@ -3737,7 +3803,7 @@ function checkStaleCommit(page, repoRoot, gitRunner) {
3737
3803
  }
3738
3804
  if (!currentSha) return null;
3739
3805
  if (storedSha !== currentSha) {
3740
- const relPage = path19.relative(path19.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3806
+ const relPage = path20.relative(path20.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3741
3807
  return {
3742
3808
  category: "stale-commit",
3743
3809
  line: `stale-commit: ${relPage} at ${storedSha}, current ${currentSha}`
@@ -3748,14 +3814,14 @@ function checkStaleCommit(page, repoRoot, gitRunner) {
3748
3814
  function checkMissingIngest(page, repoRoot) {
3749
3815
  const rawPath = page.page.raw_path;
3750
3816
  if (!rawPath) return null;
3751
- const absRaw = path19.join(repoRoot, rawPath);
3752
- if (!fs18.existsSync(absRaw)) return null;
3753
- const rawStat = fs18.statSync(absRaw);
3754
- const pageStat = fs18.statSync(page.absPath);
3817
+ const absRaw = path20.join(repoRoot, rawPath);
3818
+ if (!fs19.existsSync(absRaw)) return null;
3819
+ const rawStat = fs19.statSync(absRaw);
3820
+ const pageStat = fs19.statSync(page.absPath);
3755
3821
  const rawMtimeMs = rawStat.mtimeMs;
3756
3822
  const pageMtimeMs = pageStat.mtimeMs;
3757
3823
  if (rawMtimeMs - pageMtimeMs > 2e3) {
3758
- const relPage = path19.relative(path19.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3824
+ const relPage = path20.relative(path20.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3759
3825
  const rawMtime = rawStat.mtime.toISOString();
3760
3826
  const pageMtime = pageStat.mtime.toISOString();
3761
3827
  return {
@@ -3766,7 +3832,7 @@ function checkMissingIngest(page, repoRoot) {
3766
3832
  return null;
3767
3833
  }
3768
3834
  function checkBrokenBacklinks(pages, repoRoot) {
3769
- const wikiRoot = path19.join(repoRoot, ".cleargate", "wiki");
3835
+ const wikiRoot = path20.join(repoRoot, ".cleargate", "wiki");
3770
3836
  const byId = /* @__PURE__ */ new Map();
3771
3837
  for (const p of pages) {
3772
3838
  if (p.page.id) byId.set(p.page.id, p);
@@ -3780,7 +3846,7 @@ function checkBrokenBacklinks(pages, repoRoot) {
3780
3846
  const parentId = match[1];
3781
3847
  const parentPage = byId.get(parentId);
3782
3848
  if (!parentPage) {
3783
- const relChild = path19.relative(wikiRoot, childPage.absPath).replace(/\\/g, "/");
3849
+ const relChild = path20.relative(wikiRoot, childPage.absPath).replace(/\\/g, "/");
3784
3850
  findings.push({
3785
3851
  category: "broken-backlink",
3786
3852
  line: `broken-backlink: ${relChild} -> ${parentId} (parent missing child entry)`
@@ -3793,7 +3859,7 @@ function checkBrokenBacklinks(pages, repoRoot) {
3793
3859
  (c) => c === childRef || c === childId
3794
3860
  );
3795
3861
  if (!parentHasChild) {
3796
- const relChild = path19.relative(wikiRoot, childPage.absPath).replace(/\\/g, "/");
3862
+ const relChild = path20.relative(wikiRoot, childPage.absPath).replace(/\\/g, "/");
3797
3863
  findings.push({
3798
3864
  category: "broken-backlink",
3799
3865
  line: `broken-backlink: ${relChild} -> ${parentId} (parent missing child entry)`
@@ -3803,7 +3869,7 @@ function checkBrokenBacklinks(pages, repoRoot) {
3803
3869
  return findings;
3804
3870
  }
3805
3871
  function checkInvalidatedCitations(pages, repoRoot) {
3806
- const wikiRoot = path19.join(repoRoot, ".cleargate", "wiki");
3872
+ const wikiRoot = path20.join(repoRoot, ".cleargate", "wiki");
3807
3873
  const byId = /* @__PURE__ */ new Map();
3808
3874
  for (const p of pages) {
3809
3875
  if (p.page.id) byId.set(p.page.id, p);
@@ -3811,10 +3877,10 @@ function checkInvalidatedCitations(pages, repoRoot) {
3811
3877
  const findings = [];
3812
3878
  const topicPages = pages.filter((p) => p.page.type === "topic");
3813
3879
  for (const topicPage of topicPages) {
3814
- const relTopic = path19.relative(wikiRoot, topicPage.absPath).replace(/\\/g, "/");
3880
+ const relTopic = path20.relative(wikiRoot, topicPage.absPath).replace(/\\/g, "/");
3815
3881
  let citesList = [];
3816
3882
  try {
3817
- const raw = fs18.readFileSync(topicPage.absPath, "utf8");
3883
+ const raw = fs19.readFileSync(topicPage.absPath, "utf8");
3818
3884
  const { fm } = parseFrontmatter(raw);
3819
3885
  const rawCites = fm["cites"];
3820
3886
  if (Array.isArray(rawCites)) {
@@ -3850,7 +3916,7 @@ function checkExcludedPathIngested(page, repoRoot) {
3850
3916
  if (!rawPath) return null;
3851
3917
  const isExcluded = EXCLUDED_DIRS.some((excl) => rawPath.startsWith(excl));
3852
3918
  if (isExcluded) {
3853
- const relPage = path19.relative(path19.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3919
+ const relPage = path20.relative(path20.join(repoRoot, ".cleargate", "wiki"), page.absPath).replace(/\\/g, "/");
3854
3920
  return {
3855
3921
  category: "excluded-path-ingested",
3856
3922
  line: `excluded-path-ingested: ${relPage} (raw_path ${rawPath} is under an excluded directory)`
@@ -3861,7 +3927,7 @@ function checkExcludedPathIngested(page, repoRoot) {
3861
3927
  function checkPaginationNeeded(pages) {
3862
3928
  const bucketCounts = /* @__PURE__ */ new Map();
3863
3929
  for (const p of pages) {
3864
- const bucket = path19.basename(path19.dirname(p.absPath));
3930
+ const bucket = path20.basename(path20.dirname(p.absPath));
3865
3931
  bucketCounts.set(bucket, (bucketCounts.get(bucket) ?? 0) + 1);
3866
3932
  }
3867
3933
  const findings = [];
@@ -3899,11 +3965,11 @@ function parseCachedGateResult(raw) {
3899
3965
  function checkGateFailure(page, repoRoot) {
3900
3966
  const rawPath = page.page.raw_path;
3901
3967
  if (!rawPath) return null;
3902
- const absRaw = path19.join(repoRoot, rawPath);
3903
- if (!fs18.existsSync(absRaw)) return null;
3968
+ const absRaw = path20.join(repoRoot, rawPath);
3969
+ if (!fs19.existsSync(absRaw)) return null;
3904
3970
  let rawFm;
3905
3971
  try {
3906
- const raw = fs18.readFileSync(absRaw, "utf8");
3972
+ const raw = fs19.readFileSync(absRaw, "utf8");
3907
3973
  const { fm } = parseFrontmatter(raw);
3908
3974
  rawFm = fm;
3909
3975
  } catch {
@@ -3937,11 +4003,11 @@ function checkGateFailure(page, repoRoot) {
3937
4003
  function checkGateStaleness(page, repoRoot) {
3938
4004
  const rawPath = page.page.raw_path;
3939
4005
  if (!rawPath) return null;
3940
- const absRaw = path19.join(repoRoot, rawPath);
3941
- if (!fs18.existsSync(absRaw)) return null;
4006
+ const absRaw = path20.join(repoRoot, rawPath);
4007
+ if (!fs19.existsSync(absRaw)) return null;
3942
4008
  let rawFm;
3943
4009
  try {
3944
- const raw = fs18.readFileSync(absRaw, "utf8");
4010
+ const raw = fs19.readFileSync(absRaw, "utf8");
3945
4011
  const { fm } = parseFrontmatter(raw);
3946
4012
  rawFm = fm;
3947
4013
  } catch {
@@ -3964,7 +4030,7 @@ function checkGateStaleness(page, repoRoot) {
3964
4030
  return null;
3965
4031
  }
3966
4032
  function discoverPlainTextMentions(pages, repoRoot) {
3967
- const wikiRoot = path19.join(repoRoot, ".cleargate", "wiki");
4033
+ const wikiRoot = path20.join(repoRoot, ".cleargate", "wiki");
3968
4034
  const byId = /* @__PURE__ */ new Map();
3969
4035
  for (const p of pages) {
3970
4036
  if (p.page.id) byId.set(p.page.id, true);
@@ -3973,7 +4039,7 @@ function discoverPlainTextMentions(pages, repoRoot) {
3973
4039
  const ID_PATTERN = /\b((?:EPIC|STORY|SPRINT|PROPOSAL|CR|BUG)-[\w-]+)\b/g;
3974
4040
  const LINK_PATTERN = /\[\[[\w-]+\]\]/g;
3975
4041
  for (const page of pages) {
3976
- const relPage = path19.relative(wikiRoot, page.absPath).replace(/\\/g, "/");
4042
+ const relPage = path20.relative(wikiRoot, page.absPath).replace(/\\/g, "/");
3977
4043
  const wrappedRefs = /* @__PURE__ */ new Set();
3978
4044
  for (const m of page.body.matchAll(LINK_PATTERN)) {
3979
4045
  const inner = m[0].slice(2, -2);
@@ -3990,11 +4056,11 @@ function discoverPlainTextMentions(pages, repoRoot) {
3990
4056
  return suggestions;
3991
4057
  }
3992
4058
  function checkIndexBudget(repoRoot, indexTokenCeiling) {
3993
- const indexPath = path19.join(repoRoot, ".cleargate", "wiki", "index.md");
3994
- if (!fs18.existsSync(indexPath)) {
4059
+ const indexPath = path20.join(repoRoot, ".cleargate", "wiki", "index.md");
4060
+ if (!fs19.existsSync(indexPath)) {
3995
4061
  return { finding: null };
3996
4062
  }
3997
- const bytes = fs18.statSync(indexPath).size;
4063
+ const bytes = fs19.statSync(indexPath).size;
3998
4064
  const tokens = Math.round(bytes / 4);
3999
4065
  const ceiling = indexTokenCeiling;
4000
4066
  if (tokens > ceiling) {
@@ -4012,18 +4078,18 @@ function checkIndexBudget(repoRoot, indexTokenCeiling) {
4012
4078
 
4013
4079
  // src/lib/wiki-config.ts
4014
4080
  init_cjs_shims();
4015
- var fs19 = __toESM(require("fs"), 1);
4016
- var path20 = __toESM(require("path"), 1);
4081
+ var fs20 = __toESM(require("fs"), 1);
4082
+ var path21 = __toESM(require("path"), 1);
4017
4083
  var import_js_yaml4 = __toESM(require("js-yaml"), 1);
4018
4084
  var DEFAULT_INDEX_TOKEN_CEILING = 8e3;
4019
4085
  function loadWikiConfig(repoRoot) {
4020
- const configPath = path20.join(repoRoot, ".cleargate", "config.yml");
4021
- if (!fs19.existsSync(configPath)) {
4086
+ const configPath = path21.join(repoRoot, ".cleargate", "config.yml");
4087
+ if (!fs20.existsSync(configPath)) {
4022
4088
  return { wiki: { index_token_ceiling: DEFAULT_INDEX_TOKEN_CEILING }, gates: {} };
4023
4089
  }
4024
4090
  let raw;
4025
4091
  try {
4026
- raw = fs19.readFileSync(configPath, "utf8");
4092
+ raw = fs20.readFileSync(configPath, "utf8");
4027
4093
  } catch (err) {
4028
4094
  throw new Error(`Failed to read ${configPath}: ${String(err)}`);
4029
4095
  }
@@ -4084,7 +4150,7 @@ async function wikiLintHandler(opts = {}) {
4084
4150
  const exit = opts.exit ?? ((c) => process.exit(c));
4085
4151
  const gitRunner = opts.gitRunner;
4086
4152
  const mode = opts.mode ?? "enforce";
4087
- const wikiRoot = path21.join(cwd, ".cleargate", "wiki");
4153
+ const wikiRoot = path22.join(cwd, ".cleargate", "wiki");
4088
4154
  const repoRoot = cwd;
4089
4155
  let pages = loadWikiPages(wikiRoot);
4090
4156
  const findings = [];
@@ -4156,8 +4222,8 @@ async function wikiLintHandler(opts = {}) {
4156
4222
 
4157
4223
  // src/commands/wiki-query.ts
4158
4224
  init_cjs_shims();
4159
- var fs20 = __toESM(require("fs"), 1);
4160
- var path22 = __toESM(require("path"), 1);
4225
+ var fs21 = __toESM(require("fs"), 1);
4226
+ var path23 = __toESM(require("path"), 1);
4161
4227
  function computeSlug(query) {
4162
4228
  return query.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-{2,}/g, "-").slice(0, 40).replace(/-+$/, "");
4163
4229
  }
@@ -4187,9 +4253,9 @@ async function wikiQueryHandler(opts) {
4187
4253
  const query = opts.query;
4188
4254
  const persist = opts.persist ?? false;
4189
4255
  void stderr;
4190
- const wikiRoot = path22.join(cwd, ".cleargate", "wiki");
4191
- const indexPath = path22.join(wikiRoot, "index.md");
4192
- if (!fs20.existsSync(indexPath)) {
4256
+ const wikiRoot = path23.join(cwd, ".cleargate", "wiki");
4257
+ const indexPath = path23.join(wikiRoot, "index.md");
4258
+ if (!fs21.existsSync(indexPath)) {
4193
4259
  stdout(`wiki query: no index.md found at ${indexPath}
4194
4260
  `);
4195
4261
  stdout(`Run \`cleargate wiki build\` first.
@@ -4197,7 +4263,7 @@ async function wikiQueryHandler(opts) {
4197
4263
  exit(1);
4198
4264
  return;
4199
4265
  }
4200
- const indexContent = fs20.readFileSync(indexPath, "utf8");
4266
+ const indexContent = fs21.readFileSync(indexPath, "utf8");
4201
4267
  const matches = searchIndex(indexContent, query);
4202
4268
  if (matches.length === 0) {
4203
4269
  stdout(`wiki query: no matches for "${query}"
@@ -4222,8 +4288,8 @@ async function wikiQueryHandler(opts) {
4222
4288
  return;
4223
4289
  }
4224
4290
  const slug = computeSlug(query);
4225
- const topicsDir = path22.join(wikiRoot, "topics");
4226
- fs20.mkdirSync(topicsDir, { recursive: true });
4291
+ const topicsDir = path23.join(wikiRoot, "topics");
4292
+ fs21.mkdirSync(topicsDir, { recursive: true });
4227
4293
  const citesArray = matches.map(({ id }) => `"[[${id}]]"`);
4228
4294
  const createdAt = now();
4229
4295
  const frontmatter = [
@@ -4238,13 +4304,13 @@ async function wikiQueryHandler(opts) {
4238
4304
  const topicContent = `${frontmatter}
4239
4305
 
4240
4306
  ${body}`;
4241
- const topicPath = path22.join(topicsDir, `${slug}.md`);
4242
- fs20.writeFileSync(topicPath, topicContent, "utf8");
4307
+ const topicPath = path23.join(topicsDir, `${slug}.md`);
4308
+ fs21.writeFileSync(topicPath, topicContent, "utf8");
4243
4309
  updateIndexTopicsSection(indexPath, slug, query, createdAt);
4244
4310
  exit(0);
4245
4311
  }
4246
4312
  function updateIndexTopicsSection(indexPath, slug, query, createdAt) {
4247
- let content = fs20.readFileSync(indexPath, "utf8");
4313
+ let content = fs21.readFileSync(indexPath, "utf8");
4248
4314
  const row = `| ${slug} | ${query} | ${createdAt} |`;
4249
4315
  if (content.includes("## Topics")) {
4250
4316
  const topicsIdx = content.indexOf("## Topics");
@@ -4267,13 +4333,13 @@ ${row}
4267
4333
  ${row}
4268
4334
  `;
4269
4335
  }
4270
- fs20.writeFileSync(indexPath, content, "utf8");
4336
+ fs21.writeFileSync(indexPath, content, "utf8");
4271
4337
  }
4272
4338
 
4273
4339
  // src/commands/wiki-audit-status.ts
4274
4340
  init_cjs_shims();
4275
- var fs21 = __toESM(require("fs"), 1);
4276
- var path23 = __toESM(require("path"), 1);
4341
+ var fs22 = __toESM(require("fs"), 1);
4342
+ var path24 = __toESM(require("path"), 1);
4277
4343
  var readline4 = __toESM(require("readline"), 1);
4278
4344
  var TERMINAL = /* @__PURE__ */ new Set(["Completed", "Done", "Abandoned", "Closed", "Resolved"]);
4279
4345
  async function wikiAuditStatusHandler(opts = {}) {
@@ -4286,8 +4352,8 @@ async function wikiAuditStatusHandler(opts = {}) {
4286
4352
  });
4287
4353
  const exit = opts.exit ?? ((c) => process.exit(c));
4288
4354
  const isTTY = opts.isTTY ?? Boolean(process.stdout.isTTY);
4289
- const deliveryRoot = path23.join(cwd, ".cleargate", "delivery");
4290
- if (!fs21.existsSync(deliveryRoot)) {
4355
+ const deliveryRoot = path24.join(cwd, ".cleargate", "delivery");
4356
+ if (!fs22.existsSync(deliveryRoot)) {
4291
4357
  stderr(`audit-status: .cleargate/delivery/ not found at ${deliveryRoot}
4292
4358
  `);
4293
4359
  exit(1);
@@ -4427,7 +4493,7 @@ async function wikiAuditStatusHandler(opts = {}) {
4427
4493
  }
4428
4494
  }
4429
4495
  for (const d of fixable) {
4430
- const rawText = fs21.readFileSync(d.absPath, "utf8");
4496
+ const rawText = fs22.readFileSync(d.absPath, "utf8");
4431
4497
  const updated = applyStatusFix(rawText, d.suggestedStatus);
4432
4498
  if (!opts.quiet) {
4433
4499
  stdout(`--- ${d.rawPath}
@@ -4443,7 +4509,7 @@ async function wikiAuditStatusHandler(opts = {}) {
4443
4509
  stdout(`+${newLine}
4444
4510
  `);
4445
4511
  }
4446
- fs21.writeFileSync(d.absPath, updated, "utf8");
4512
+ fs22.writeFileSync(d.absPath, updated, "utf8");
4447
4513
  }
4448
4514
  stdout(`audit-status: applied ${fixable.length} fix(es)
4449
4515
  `);
@@ -4472,8 +4538,8 @@ function applyStatusFix(rawText, newStatus) {
4472
4538
 
4473
4539
  // src/commands/doctor.ts
4474
4540
  init_cjs_shims();
4475
- var fs22 = __toESM(require("fs"), 1);
4476
- var path24 = __toESM(require("path"), 1);
4541
+ var fs23 = __toESM(require("fs"), 1);
4542
+ var path25 = __toESM(require("path"), 1);
4477
4543
  var import_node_child_process6 = require("child_process");
4478
4544
 
4479
4545
  // src/lib/pricing.ts
@@ -4550,24 +4616,24 @@ function parseHookLogLine(line) {
4550
4616
  };
4551
4617
  }
4552
4618
  function runHookHealth(stdout, cwd, now, outcome) {
4553
- const cleargateDir = path24.join(cwd, ".cleargate");
4554
- if (!fs22.existsSync(cleargateDir)) {
4619
+ const cleargateDir = path25.join(cwd, ".cleargate");
4620
+ if (!fs23.existsSync(cleargateDir)) {
4555
4621
  stdout("cleargate misconfigured: no .cleargate/ found. Run: cleargate init");
4556
4622
  if (outcome) outcome.configError = true;
4557
4623
  return;
4558
4624
  }
4559
- const manifestPath = path24.join(cwd, "cleargate-planning", "MANIFEST.json");
4560
- if (!fs22.existsSync(manifestPath)) {
4625
+ const manifestPath = path25.join(cwd, "cleargate-planning", "MANIFEST.json");
4626
+ if (!fs23.existsSync(manifestPath)) {
4561
4627
  stdout(`cleargate misconfigured: cleargate-planning/MANIFEST.json not found. Run: cleargate init`);
4562
4628
  if (outcome) outcome.configError = true;
4563
4629
  }
4564
- const settingsPath = path24.join(cwd, ".claude", "settings.json");
4565
- if (!fs22.existsSync(settingsPath)) {
4630
+ const settingsPath = path25.join(cwd, ".claude", "settings.json");
4631
+ if (!fs23.existsSync(settingsPath)) {
4566
4632
  stdout("[doctor] No .claude/settings.json found \u2014 hook config unavailable.");
4567
4633
  return;
4568
4634
  }
4569
4635
  try {
4570
- const raw = fs22.readFileSync(settingsPath, "utf-8");
4636
+ const raw = fs23.readFileSync(settingsPath, "utf-8");
4571
4637
  const settings = JSON.parse(raw);
4572
4638
  const hasHooks = typeof settings === "object" && settings !== null && "hooks" in settings;
4573
4639
  if (hasHooks) {
@@ -4578,13 +4644,13 @@ function runHookHealth(stdout, cwd, now, outcome) {
4578
4644
  } catch {
4579
4645
  stdout("[doctor] .claude/settings.json is not valid JSON \u2014 cannot verify hook config.");
4580
4646
  }
4581
- const logPath = path24.join(cwd, ".cleargate", "hook-log", "gate-check.log");
4582
- if (!fs22.existsSync(logPath)) {
4647
+ const logPath = path25.join(cwd, ".cleargate", "hook-log", "gate-check.log");
4648
+ if (!fs23.existsSync(logPath)) {
4583
4649
  return;
4584
4650
  }
4585
4651
  let logContent;
4586
4652
  try {
4587
- logContent = fs22.readFileSync(logPath, "utf-8");
4653
+ logContent = fs23.readFileSync(logPath, "utf-8");
4588
4654
  } catch {
4589
4655
  return;
4590
4656
  }
@@ -4698,8 +4764,8 @@ function parseCachedGateResult2(raw) {
4698
4764
  };
4699
4765
  }
4700
4766
  function emitResolverStatusLine(cwd, stdout) {
4701
- const distCliPath = path24.join(cwd, "cleargate-cli", "dist", "cli.js");
4702
- if (fs22.existsSync(distCliPath)) {
4767
+ const distCliPath = path25.join(cwd, "cleargate-cli", "dist", "cli.js");
4768
+ if (fs23.existsSync(distCliPath)) {
4703
4769
  stdout(`cleargate CLI: local dist \u2014 ${distCliPath}`);
4704
4770
  return;
4705
4771
  }
@@ -4713,10 +4779,10 @@ function emitResolverStatusLine(cwd, stdout) {
4713
4779
  return;
4714
4780
  }
4715
4781
  let pinVersion = "unknown";
4716
- const hookPath = path24.join(cwd, ".claude", "hooks", "stamp-and-gate.sh");
4717
- if (fs22.existsSync(hookPath)) {
4782
+ const hookPath = path25.join(cwd, ".claude", "hooks", "stamp-and-gate.sh");
4783
+ if (fs23.existsSync(hookPath)) {
4718
4784
  try {
4719
- const hookContent = fs22.readFileSync(hookPath, "utf-8");
4785
+ const hookContent = fs23.readFileSync(hookPath, "utf-8");
4720
4786
  const pinMatch = hookContent.match(/^#\s*cleargate-pin:\s*(\S+)\s*$/m);
4721
4787
  if (pinMatch?.[1]) {
4722
4788
  pinVersion = pinMatch[1];
@@ -4748,10 +4814,10 @@ async function runSessionStart(cwd, stdout, outcome) {
4748
4814
  if (outcome && resolverLines.some((l) => l.includes("\u{1F534}"))) {
4749
4815
  outcome.configError = true;
4750
4816
  }
4751
- const pendingSyncDir = path24.join(cwd, ".cleargate", "delivery", "pending-sync");
4817
+ const pendingSyncDir = path25.join(cwd, ".cleargate", "delivery", "pending-sync");
4752
4818
  let files;
4753
4819
  try {
4754
- files = fs22.readdirSync(pendingSyncDir).filter((f) => f.endsWith(".md")).map((f) => path24.join(pendingSyncDir, f));
4820
+ files = fs23.readdirSync(pendingSyncDir).filter((f) => f.endsWith(".md")).map((f) => path25.join(pendingSyncDir, f));
4755
4821
  } catch {
4756
4822
  return;
4757
4823
  }
@@ -4760,7 +4826,7 @@ async function runSessionStart(cwd, stdout, outcome) {
4760
4826
  for (const filePath of files) {
4761
4827
  let raw;
4762
4828
  try {
4763
- raw = fs22.readFileSync(filePath, "utf-8");
4829
+ raw = fs23.readFileSync(filePath, "utf-8");
4764
4830
  } catch {
4765
4831
  continue;
4766
4832
  }
@@ -4786,13 +4852,13 @@ async function runSessionStart(cwd, stdout, outcome) {
4786
4852
  }
4787
4853
  }
4788
4854
  if (!itemId) {
4789
- itemId = path24.basename(filePath, ".md");
4855
+ itemId = path25.basename(filePath, ".md");
4790
4856
  }
4791
4857
  const firstCriterionId = gate2.failing_criteria.length > 0 ? gate2.failing_criteria[0]?.id ?? "" : "";
4792
4858
  blocked.push({ id: itemId, firstCriterionId });
4793
4859
  }
4794
- const activesentinel = path24.join(cwd, ".cleargate", "sprint-runs", ".active");
4795
- const sprintActive = fs22.existsSync(activesentinel);
4860
+ const activesentinel = path25.join(cwd, ".cleargate", "sprint-runs", ".active");
4861
+ const sprintActive = fs23.existsSync(activesentinel);
4796
4862
  const shouldRemind = !hasApprovedStory && !sprintActive;
4797
4863
  if (shouldRemind) {
4798
4864
  stdout(PLANNING_FIRST_REMINDER);
@@ -4827,10 +4893,10 @@ async function runPricing(filePath, cwd, stdout, stderr, exit, outcome) {
4827
4893
  exit(2);
4828
4894
  return;
4829
4895
  }
4830
- const absPath = path24.isAbsolute(filePath) ? filePath : path24.resolve(cwd, filePath);
4896
+ const absPath = path25.isAbsolute(filePath) ? filePath : path25.resolve(cwd, filePath);
4831
4897
  let raw;
4832
4898
  try {
4833
- raw = fs22.readFileSync(absPath, "utf-8");
4899
+ raw = fs23.readFileSync(absPath, "utf-8");
4834
4900
  } catch {
4835
4901
  stderr(`cleargate doctor --pricing: cannot read file: ${absPath}`);
4836
4902
  if (outcome) outcome.configError = true;
@@ -4892,7 +4958,7 @@ async function runPricing(filePath, cwd, stdout, stderr, exit, outcome) {
4892
4958
  const output = draftTokens.output ?? 0;
4893
4959
  const cacheRead = draftTokens.cache_read ?? 0;
4894
4960
  const cacheCreation = draftTokens.cache_creation ?? 0;
4895
- const fileName = path24.basename(absPath);
4961
+ const fileName = path25.basename(absPath);
4896
4962
  stdout(
4897
4963
  `${fileName}: ${model} \u2014 input:${input} output:${output} cache_read:${cacheRead} cache_creation:${cacheCreation} \u2248 $${usd.toFixed(4)}`
4898
4964
  );
@@ -4905,15 +4971,15 @@ function globMatch(pattern, filePath) {
4905
4971
  return re.test(normalFile);
4906
4972
  }
4907
4973
  async function runCanEdit(filePath, cwd, stdout, exit, outcome) {
4908
- const activeSentinel = path24.join(cwd, ".cleargate", "sprint-runs", ".active");
4909
- if (fs22.existsSync(activeSentinel)) {
4974
+ const activeSentinel = path25.join(cwd, ".cleargate", "sprint-runs", ".active");
4975
+ if (fs23.existsSync(activeSentinel)) {
4910
4976
  stdout("allowed: sprint active");
4911
4977
  return;
4912
4978
  }
4913
- const pendingSyncDir = path24.join(cwd, ".cleargate", "delivery", "pending-sync");
4979
+ const pendingSyncDir = path25.join(cwd, ".cleargate", "delivery", "pending-sync");
4914
4980
  let files;
4915
4981
  try {
4916
- files = fs22.readdirSync(pendingSyncDir).filter((f) => f.endsWith(".md")).map((f) => path24.join(pendingSyncDir, f));
4982
+ files = fs23.readdirSync(pendingSyncDir).filter((f) => f.endsWith(".md")).map((f) => path25.join(pendingSyncDir, f));
4917
4983
  } catch {
4918
4984
  stdout("blocked: no_approved_stories");
4919
4985
  if (outcome) outcome.blocker = true;
@@ -4925,7 +4991,7 @@ async function runCanEdit(filePath, cwd, stdout, exit, outcome) {
4925
4991
  for (const storyPath of files) {
4926
4992
  let raw;
4927
4993
  try {
4928
- raw = fs22.readFileSync(storyPath, "utf-8");
4994
+ raw = fs23.readFileSync(storyPath, "utf-8");
4929
4995
  } catch {
4930
4996
  continue;
4931
4997
  }
@@ -5023,14 +5089,14 @@ async function doctorHandler(flags, cli) {
5023
5089
 
5024
5090
  // src/commands/gate.ts
5025
5091
  init_cjs_shims();
5026
- var fs26 = __toESM(require("fs"), 1);
5027
- var path27 = __toESM(require("path"), 1);
5092
+ var fs27 = __toESM(require("fs"), 1);
5093
+ var path28 = __toESM(require("path"), 1);
5028
5094
  var import_node_child_process7 = require("child_process");
5029
5095
 
5030
5096
  // src/commands/execution-mode.ts
5031
5097
  init_cjs_shims();
5032
- var fs23 = __toESM(require("fs"), 1);
5033
- var path25 = __toESM(require("path"), 1);
5098
+ var fs24 = __toESM(require("fs"), 1);
5099
+ var path26 = __toESM(require("path"), 1);
5034
5100
  var V1_INERT_MESSAGE = "v1 mode active \u2014 command inert. Set execution_mode: v2 in sprint frontmatter to enable.";
5035
5101
  function parseFrontmatterSimple(raw) {
5036
5102
  const match = /^---\r?\n([\s\S]*?)\r?\n---/.exec(raw);
@@ -5048,24 +5114,24 @@ function parseFrontmatterSimple(raw) {
5048
5114
  }
5049
5115
  function discoverSprintFile(sprintId, cwd) {
5050
5116
  const searchDirs = [
5051
- path25.join(cwd, ".cleargate", "delivery", "pending-sync"),
5052
- path25.join(cwd, ".cleargate", "delivery", "archive")
5117
+ path26.join(cwd, ".cleargate", "delivery", "pending-sync"),
5118
+ path26.join(cwd, ".cleargate", "delivery", "archive")
5053
5119
  ];
5054
5120
  for (const dir of searchDirs) {
5055
- if (!fs23.existsSync(dir)) continue;
5121
+ if (!fs24.existsSync(dir)) continue;
5056
5122
  let entries;
5057
5123
  try {
5058
- entries = fs23.readdirSync(dir);
5124
+ entries = fs24.readdirSync(dir);
5059
5125
  } catch {
5060
5126
  continue;
5061
5127
  }
5062
5128
  const prefix = `${sprintId}_`;
5063
5129
  for (const entry of entries) {
5064
5130
  if (entry.startsWith(prefix) && entry.endsWith(".md")) {
5065
- return path25.join(dir, entry);
5131
+ return path26.join(dir, entry);
5066
5132
  }
5067
5133
  if (entry === `${sprintId}.md`) {
5068
- return path25.join(dir, entry);
5134
+ return path26.join(dir, entry);
5069
5135
  }
5070
5136
  }
5071
5137
  }
@@ -5073,9 +5139,9 @@ function discoverSprintFile(sprintId, cwd) {
5073
5139
  }
5074
5140
  function resolveSprintIdFromSentinel(cwd) {
5075
5141
  const resolvedCwd = cwd ?? process.cwd();
5076
- const sentinelPath = path25.join(resolvedCwd, ".cleargate", "sprint-runs", ".active");
5142
+ const sentinelPath = path26.join(resolvedCwd, ".cleargate", "sprint-runs", ".active");
5077
5143
  try {
5078
- const content = fs23.readFileSync(sentinelPath, "utf8").trim();
5144
+ const content = fs24.readFileSync(sentinelPath, "utf8").trim();
5079
5145
  return content.length > 0 ? content : null;
5080
5146
  } catch {
5081
5147
  return null;
@@ -5094,12 +5160,12 @@ function readSprintExecutionMode(sprintId, opts = {}) {
5094
5160
  if (!filePath) {
5095
5161
  filePath = discoverSprintFile(resolvedSprintId, cwd);
5096
5162
  }
5097
- if (!filePath || !fs23.existsSync(filePath)) {
5163
+ if (!filePath || !fs24.existsSync(filePath)) {
5098
5164
  return "v1";
5099
5165
  }
5100
5166
  let raw;
5101
5167
  try {
5102
- raw = fs23.readFileSync(filePath, "utf8");
5168
+ raw = fs24.readFileSync(filePath, "utf8");
5103
5169
  } catch {
5104
5170
  return "v1";
5105
5171
  }
@@ -5118,8 +5184,8 @@ var import_js_yaml6 = __toESM(require("js-yaml"), 1);
5118
5184
 
5119
5185
  // src/lib/readiness-predicates.ts
5120
5186
  init_cjs_shims();
5121
- var fs24 = __toESM(require("fs"), 1);
5122
- var path26 = __toESM(require("path"), 1);
5187
+ var fs25 = __toESM(require("fs"), 1);
5188
+ var path27 = __toESM(require("path"), 1);
5123
5189
  function parsePredicate(src) {
5124
5190
  const s = src.trim();
5125
5191
  const fmMatch = s.match(
@@ -5283,18 +5349,18 @@ function compareValues(actual, op, expected) {
5283
5349
  }
5284
5350
  function resolveLinkedPath(ref, docAbsPath, projectRoot) {
5285
5351
  const candidates = [
5286
- path26.resolve(path26.dirname(docAbsPath), ref),
5287
- path26.resolve(projectRoot, ref)
5352
+ path27.resolve(path27.dirname(docAbsPath), ref),
5353
+ path27.resolve(projectRoot, ref)
5288
5354
  ];
5289
5355
  for (const candidate of candidates) {
5290
5356
  if (!candidate.startsWith(projectRoot)) continue;
5291
- if (fs24.existsSync(candidate)) return candidate;
5357
+ if (fs25.existsSync(candidate)) return candidate;
5292
5358
  }
5293
5359
  return null;
5294
5360
  }
5295
5361
  function readFrontmatterFromFile(absPath) {
5296
5362
  try {
5297
- const raw = fs24.readFileSync(absPath, "utf8");
5363
+ const raw = fs25.readFileSync(absPath, "utf8");
5298
5364
  const lines = raw.split("\n");
5299
5365
  if (lines[0] !== "---") return {};
5300
5366
  let closeIdx = -1;
@@ -5438,14 +5504,14 @@ function applyCountOp(actual, op, n) {
5438
5504
  }
5439
5505
  }
5440
5506
  function evalFileExists(parsed, projectRoot) {
5441
- const resolved = path26.resolve(projectRoot, parsed.path);
5442
- if (!resolved.startsWith(projectRoot + path26.sep) && resolved !== projectRoot) {
5507
+ const resolved = path27.resolve(projectRoot, parsed.path);
5508
+ if (!resolved.startsWith(projectRoot + path27.sep) && resolved !== projectRoot) {
5443
5509
  return {
5444
5510
  pass: false,
5445
5511
  detail: `path '${parsed.path}' resolves outside project root (sandbox violation)`
5446
5512
  };
5447
5513
  }
5448
- const exists = fs24.existsSync(resolved);
5514
+ const exists = fs25.existsSync(resolved);
5449
5515
  return {
5450
5516
  pass: exists,
5451
5517
  detail: exists ? `${parsed.path} exists` : `${parsed.path} not found`
@@ -5453,13 +5519,13 @@ function evalFileExists(parsed, projectRoot) {
5453
5519
  }
5454
5520
  function evalLinkTargetExists(parsed, opts) {
5455
5521
  const projectRoot = opts?.projectRoot ?? process.cwd();
5456
- const wikiIndexPath = opts?.wikiIndexPath ?? path26.join(projectRoot, ".cleargate", "wiki", "index.md");
5522
+ const wikiIndexPath = opts?.wikiIndexPath ?? path27.join(projectRoot, ".cleargate", "wiki", "index.md");
5457
5523
  if (!wikiIndexPath.startsWith(projectRoot)) {
5458
5524
  return { pass: false, detail: "wikiIndexPath resolves outside project root" };
5459
5525
  }
5460
5526
  let indexContent;
5461
5527
  try {
5462
- indexContent = fs24.readFileSync(wikiIndexPath, "utf8");
5528
+ indexContent = fs25.readFileSync(wikiIndexPath, "utf8");
5463
5529
  } catch {
5464
5530
  return { pass: false, detail: `wiki index not found at ${wikiIndexPath}` };
5465
5531
  }
@@ -5470,13 +5536,13 @@ function evalLinkTargetExists(parsed, opts) {
5470
5536
  };
5471
5537
  }
5472
5538
  function evalStatusOf(parsed, opts, projectRoot) {
5473
- const wikiIndexPath = opts?.wikiIndexPath ?? path26.join(projectRoot, ".cleargate", "wiki", "index.md");
5539
+ const wikiIndexPath = opts?.wikiIndexPath ?? path27.join(projectRoot, ".cleargate", "wiki", "index.md");
5474
5540
  if (!wikiIndexPath.startsWith(projectRoot)) {
5475
5541
  return { pass: false, detail: "wikiIndexPath resolves outside project root" };
5476
5542
  }
5477
5543
  let indexContent;
5478
5544
  try {
5479
- indexContent = fs24.readFileSync(wikiIndexPath, "utf8");
5545
+ indexContent = fs25.readFileSync(wikiIndexPath, "utf8");
5480
5546
  } catch {
5481
5547
  return { pass: false, detail: `wiki index not found at ${wikiIndexPath}` };
5482
5548
  }
@@ -5487,7 +5553,7 @@ function evalStatusOf(parsed, opts, projectRoot) {
5487
5553
  return { pass: false, detail: `[[${parsed.id}]] not found in wiki index` };
5488
5554
  }
5489
5555
  const rawPath = rowMatch[1].trim();
5490
- const fullPath = path26.resolve(projectRoot, rawPath);
5556
+ const fullPath = path27.resolve(projectRoot, rawPath);
5491
5557
  if (!fullPath.startsWith(projectRoot)) {
5492
5558
  return { pass: false, detail: `wiki path for ${parsed.id} resolves outside project root` };
5493
5559
  }
@@ -5505,12 +5571,12 @@ function evalStatusOf(parsed, opts, projectRoot) {
5505
5571
 
5506
5572
  // src/lib/frontmatter-cache.ts
5507
5573
  init_cjs_shims();
5508
- var fs25 = __toESM(require("fs/promises"), 1);
5574
+ var fs26 = __toESM(require("fs/promises"), 1);
5509
5575
  var import_js_yaml5 = __toESM(require("js-yaml"), 1);
5510
5576
  async function readCachedGate(absPath) {
5511
5577
  let raw;
5512
5578
  try {
5513
- raw = await fs25.readFile(absPath, "utf8");
5579
+ raw = await fs26.readFile(absPath, "utf8");
5514
5580
  } catch {
5515
5581
  return null;
5516
5582
  }
@@ -5530,7 +5596,7 @@ async function writeCachedGate(absPath, result, opts) {
5530
5596
  failing_criteria: result.failing_criteria,
5531
5597
  last_gate_check: lastGateCheck
5532
5598
  };
5533
- const raw = await fs25.readFile(absPath, "utf8");
5599
+ const raw = await fs26.readFile(absPath, "utf8");
5534
5600
  let fm;
5535
5601
  let body;
5536
5602
  try {
@@ -5560,7 +5626,7 @@ async function writeCachedGate(absPath, result, opts) {
5560
5626
 
5561
5627
  ${body}` : `${fmBlock}
5562
5628
  `;
5563
- await fs25.writeFile(absPath, newContent, "utf8");
5629
+ await fs26.writeFile(absPath, newContent, "utf8");
5564
5630
  }
5565
5631
  function coerceCachedGate(val) {
5566
5632
  if (val === void 0 || val === null) return null;
@@ -5591,7 +5657,7 @@ function coerceCachedGate(val) {
5591
5657
 
5592
5658
  // src/commands/gate.ts
5593
5659
  function loadGateBlocks(gatesDocPath) {
5594
- const raw = fs26.readFileSync(gatesDocPath, "utf8");
5660
+ const raw = fs27.readFileSync(gatesDocPath, "utf8");
5595
5661
  const blocks = [];
5596
5662
  const fenceRe = /^```yaml\n([\s\S]*?)^```/gm;
5597
5663
  let match;
@@ -5626,14 +5692,14 @@ async function gateCheckHandler(file, opts, cli) {
5626
5692
  const exitFn = cli?.exit ?? ((code) => process.exit(code));
5627
5693
  const cwd = cli?.cwd ?? process.cwd();
5628
5694
  const nowFn = cli?.now ?? (() => /* @__PURE__ */ new Date());
5629
- const absPath = path27.isAbsolute(file) ? file : path27.resolve(cwd, file);
5630
- if (!fs26.existsSync(absPath)) {
5695
+ const absPath = path28.isAbsolute(file) ? file : path28.resolve(cwd, file);
5696
+ if (!fs27.existsSync(absPath)) {
5631
5697
  stderrFn(`[cleargate gate] error: file not found: ${absPath}`);
5632
5698
  return exitFn(1);
5633
5699
  }
5634
5700
  let raw;
5635
5701
  try {
5636
- raw = fs26.readFileSync(absPath, "utf8");
5702
+ raw = fs27.readFileSync(absPath, "utf8");
5637
5703
  } catch (err) {
5638
5704
  stderrFn(`[cleargate gate] error: cannot read file: ${absPath}`);
5639
5705
  return exitFn(1);
@@ -5652,8 +5718,8 @@ async function gateCheckHandler(file, opts, cli) {
5652
5718
  return exitFn(1);
5653
5719
  }
5654
5720
  const projectRoot = cwd;
5655
- const gatesDocPath = cli?.gatesDocPath ?? path27.join(projectRoot, ".cleargate", "knowledge", "readiness-gates.md");
5656
- if (!fs26.existsSync(gatesDocPath)) {
5721
+ const gatesDocPath = cli?.gatesDocPath ?? path28.join(projectRoot, ".cleargate", "knowledge", "readiness-gates.md");
5722
+ if (!fs27.existsSync(gatesDocPath)) {
5657
5723
  stderrFn(`[cleargate gate] error: readiness-gates.md not found at: ${gatesDocPath}`);
5658
5724
  return exitFn(1);
5659
5725
  }
@@ -5726,8 +5792,8 @@ async function gateExplainHandler(file, cli) {
5726
5792
  const stderrFn = cli?.stderr ?? ((s) => process.stderr.write(s + "\n"));
5727
5793
  const exitFn = cli?.exit ?? ((code) => process.exit(code));
5728
5794
  const cwd = cli?.cwd ?? process.cwd();
5729
- const absPath = path27.isAbsolute(file) ? file : path27.resolve(cwd, file);
5730
- if (!fs26.existsSync(absPath)) {
5795
+ const absPath = path28.isAbsolute(file) ? file : path28.resolve(cwd, file);
5796
+ if (!fs27.existsSync(absPath)) {
5731
5797
  stderrFn(`[cleargate gate] error: file not found: ${absPath}`);
5732
5798
  return exitFn(1);
5733
5799
  }
@@ -5738,7 +5804,7 @@ async function gateExplainHandler(file, cli) {
5738
5804
  }
5739
5805
  let raw;
5740
5806
  try {
5741
- raw = fs26.readFileSync(absPath, "utf8");
5807
+ raw = fs27.readFileSync(absPath, "utf8");
5742
5808
  } catch {
5743
5809
  stderrFn(`[cleargate gate] error: cannot read file: ${absPath}`);
5744
5810
  return exitFn(1);
@@ -5759,7 +5825,7 @@ async function gateExplainHandler(file, cli) {
5759
5825
  function resolveRunScriptForGate(opts) {
5760
5826
  if (opts.runScriptPath) return opts.runScriptPath;
5761
5827
  const cwd = opts.cwd ?? process.cwd();
5762
- return path27.join(cwd, ".cleargate", "scripts", "run_script.sh");
5828
+ return path28.join(cwd, ".cleargate", "scripts", "run_script.sh");
5763
5829
  }
5764
5830
  function gateQaHandler(opts, cli) {
5765
5831
  const stdoutFn = cli?.stdout ?? ((s) => process.stdout.write(s + "\n"));
@@ -5853,15 +5919,15 @@ function gateRunHandler(name, opts, cli) {
5853
5919
 
5854
5920
  // src/commands/sprint.ts
5855
5921
  init_cjs_shims();
5856
- var fs27 = __toESM(require("fs"), 1);
5857
- var path28 = __toESM(require("path"), 1);
5922
+ var fs28 = __toESM(require("fs"), 1);
5923
+ var path29 = __toESM(require("path"), 1);
5858
5924
  var import_node_child_process9 = require("child_process");
5859
5925
  var import_js_yaml7 = __toESM(require("js-yaml"), 1);
5860
5926
  var TERMINAL_STATUSES2 = /* @__PURE__ */ new Set(["Completed", "Done", "Abandoned", "Closed", "Resolved"]);
5861
5927
  function resolveRunScript(opts) {
5862
5928
  if (opts.runScriptPath) return opts.runScriptPath;
5863
5929
  const cwd = opts.cwd ?? process.cwd();
5864
- return path28.join(cwd, ".cleargate", "scripts", "run_script.sh");
5930
+ return path29.join(cwd, ".cleargate", "scripts", "run_script.sh");
5865
5931
  }
5866
5932
  function defaultExit(code) {
5867
5933
  return process.exit(code);
@@ -5955,8 +6021,8 @@ ${body}`;
5955
6021
  }
5956
6022
  function atomicWriteStr(filePath, content) {
5957
6023
  const tmp = `${filePath}.tmp.${process.pid}`;
5958
- fs27.writeFileSync(tmp, content, "utf8");
5959
- fs27.renameSync(tmp, filePath);
6024
+ fs28.writeFileSync(tmp, content, "utf8");
6025
+ fs28.renameSync(tmp, filePath);
5960
6026
  }
5961
6027
  function deriveSprintBranchForArchive(sprintId) {
5962
6028
  const match = /^SPRINT-(\d+)/.exec(sprintId);
@@ -5970,7 +6036,7 @@ function stampFile(raw, status, completedAt) {
5970
6036
  return serializeFileContent(fm, body);
5971
6037
  }
5972
6038
  function stampSprintClose(sprintPath, now) {
5973
- const previousContent = fs27.readFileSync(sprintPath, "utf8");
6039
+ const previousContent = fs28.readFileSync(sprintPath, "utf8");
5974
6040
  const { fm, body } = parseFileFrontmatter(previousContent);
5975
6041
  const currentStatus = typeof fm["status"] === "string" ? fm["status"] : "";
5976
6042
  const alreadyTerminal = TERMINAL_STATUSES2.has(currentStatus);
@@ -6030,14 +6096,14 @@ async function sprintArchiveHandler(opts, cli) {
6030
6096
  if (mode === "v1") {
6031
6097
  return printInertAndExit(stdoutFn, exitFn);
6032
6098
  }
6033
- const stateFile = path28.join(cwd, ".cleargate", "sprint-runs", opts.sprintId, "state.json");
6034
- if (!fs27.existsSync(stateFile)) {
6099
+ const stateFile = path29.join(cwd, ".cleargate", "sprint-runs", opts.sprintId, "state.json");
6100
+ if (!fs28.existsSync(stateFile)) {
6035
6101
  stderrFn(`[cleargate sprint archive] state.json not found at ${stateFile}`);
6036
6102
  return exitFn(1);
6037
6103
  }
6038
6104
  let state2;
6039
6105
  try {
6040
- state2 = JSON.parse(fs27.readFileSync(stateFile, "utf8"));
6106
+ state2 = JSON.parse(fs28.readFileSync(stateFile, "utf8"));
6041
6107
  } catch (err) {
6042
6108
  stderrFn(`[cleargate sprint archive] failed to parse state.json: ${err.message}`);
6043
6109
  return exitFn(1);
@@ -6049,18 +6115,18 @@ async function sprintArchiveHandler(opts, cli) {
6049
6115
  return exitFn(1);
6050
6116
  }
6051
6117
  const stateStories = state2.stories ?? {};
6052
- const pendingDir = path28.join(cwd, ".cleargate", "delivery", "pending-sync");
6053
- const archiveDir = path28.join(cwd, ".cleargate", "delivery", "archive");
6118
+ const pendingDir = path29.join(cwd, ".cleargate", "delivery", "pending-sync");
6119
+ const archiveDir = path29.join(cwd, ".cleargate", "delivery", "archive");
6054
6120
  let sprintFile = null;
6055
- for (const entry of fs27.readdirSync(pendingDir)) {
6121
+ for (const entry of fs28.readdirSync(pendingDir)) {
6056
6122
  if ((entry.startsWith(`${opts.sprintId}_`) || entry === `${opts.sprintId}.md`) && entry.endsWith(".md")) {
6057
- sprintFile = path28.join(pendingDir, entry);
6123
+ sprintFile = path29.join(pendingDir, entry);
6058
6124
  break;
6059
6125
  }
6060
6126
  }
6061
6127
  let epicIds = [];
6062
- if (sprintFile && fs27.existsSync(sprintFile)) {
6063
- const { fm } = parseFileFrontmatter(fs27.readFileSync(sprintFile, "utf8"));
6128
+ if (sprintFile && fs28.existsSync(sprintFile)) {
6129
+ const { fm } = parseFileFrontmatter(fs28.readFileSync(sprintFile, "utf8"));
6064
6130
  const epics = fm["epics"];
6065
6131
  if (Array.isArray(epics)) {
6066
6132
  epicIds = epics.map(String);
@@ -6070,15 +6136,15 @@ async function sprintArchiveHandler(opts, cli) {
6070
6136
  if (sprintFile) {
6071
6137
  plan.push({
6072
6138
  src: sprintFile,
6073
- destName: path28.basename(sprintFile),
6139
+ destName: path29.basename(sprintFile),
6074
6140
  status: "Completed"
6075
6141
  });
6076
6142
  }
6077
6143
  for (const epicId of epicIds) {
6078
- for (const entry of fs27.readdirSync(pendingDir)) {
6144
+ for (const entry of fs28.readdirSync(pendingDir)) {
6079
6145
  if ((entry.startsWith(`${epicId}_`) || entry === `${epicId}.md`) && entry.endsWith(".md")) {
6080
6146
  plan.push({
6081
- src: path28.join(pendingDir, entry),
6147
+ src: path29.join(pendingDir, entry),
6082
6148
  destName: entry,
6083
6149
  status: "Approved"
6084
6150
  });
@@ -6087,10 +6153,10 @@ async function sprintArchiveHandler(opts, cli) {
6087
6153
  }
6088
6154
  const storyKeys = storyKeysForEpic(stateStories, epicId);
6089
6155
  for (const storyId of storyKeys) {
6090
- for (const entry of fs27.readdirSync(pendingDir)) {
6156
+ for (const entry of fs28.readdirSync(pendingDir)) {
6091
6157
  if ((entry.startsWith(`${storyId}_`) || entry === `${storyId}.md`) && entry.endsWith(".md")) {
6092
6158
  plan.push({
6093
- src: path28.join(pendingDir, entry),
6159
+ src: path29.join(pendingDir, entry),
6094
6160
  destName: entry,
6095
6161
  status: "Done"
6096
6162
  });
@@ -6102,13 +6168,13 @@ async function sprintArchiveHandler(opts, cli) {
6102
6168
  const storyIdsInState = new Set(Object.keys(stateStories));
6103
6169
  const planSrcs = new Set(plan.map((p) => p.src));
6104
6170
  const orphans = [];
6105
- for (const entry of fs27.readdirSync(pendingDir)) {
6171
+ for (const entry of fs28.readdirSync(pendingDir)) {
6106
6172
  if (!entry.startsWith("STORY-") || !entry.endsWith(".md")) continue;
6107
- const candidate = path28.join(pendingDir, entry);
6173
+ const candidate = path29.join(pendingDir, entry);
6108
6174
  if (planSrcs.has(candidate)) continue;
6109
6175
  let raw;
6110
6176
  try {
6111
- raw = fs27.readFileSync(candidate, "utf8");
6177
+ raw = fs28.readFileSync(candidate, "utf8");
6112
6178
  } catch {
6113
6179
  continue;
6114
6180
  }
@@ -6125,18 +6191,18 @@ async function sprintArchiveHandler(opts, cli) {
6125
6191
  }
6126
6192
  const completedAt = (/* @__PURE__ */ new Date()).toISOString();
6127
6193
  const sprintBranch = deriveSprintBranchForArchive(opts.sprintId);
6128
- const activePath = path28.join(cwd, ".cleargate", "sprint-runs", ".active");
6194
+ const activePath = path29.join(cwd, ".cleargate", "sprint-runs", ".active");
6129
6195
  if (opts.dryRun) {
6130
6196
  stdoutFn(`[dry-run] Sprint archive plan for ${opts.sprintId}:`);
6131
6197
  stdoutFn(` Sprint branch: ${sprintBranch}`);
6132
6198
  stdoutFn(` Files to archive (${plan.length}):`);
6133
6199
  for (const entry of plan) {
6134
6200
  stdoutFn(
6135
- ` ${path28.basename(entry.src)} \u2192 archive/${entry.destName} [stamp: status=${entry.status}, completed_at=<now>]`
6201
+ ` ${path29.basename(entry.src)} \u2192 archive/${entry.destName} [stamp: status=${entry.status}, completed_at=<now>]`
6136
6202
  );
6137
6203
  }
6138
6204
  if (orphans.length > 0) {
6139
- stdoutFn(` Orphan files (${orphans.length}): ${orphans.map((o) => path28.basename(o)).join(", ")}`);
6205
+ stdoutFn(` Orphan files (${orphans.length}): ${orphans.map((o) => path29.basename(o)).join(", ")}`);
6140
6206
  }
6141
6207
  stdoutFn(` .active \u2192 "" (truncate)`);
6142
6208
  stdoutFn(` git checkout main`);
@@ -6145,9 +6211,9 @@ async function sprintArchiveHandler(opts, cli) {
6145
6211
  return exitFn(0);
6146
6212
  }
6147
6213
  let sprintFileSnapshot = null;
6148
- const wikiRoot = path28.join(cwd, ".cleargate", "wiki");
6149
- const wikiInitialised = fs27.existsSync(wikiRoot);
6150
- if (sprintFile && fs27.existsSync(sprintFile)) {
6214
+ const wikiRoot = path29.join(cwd, ".cleargate", "wiki");
6215
+ const wikiInitialised = fs28.existsSync(wikiRoot);
6216
+ if (sprintFile && fs28.existsSync(sprintFile)) {
6151
6217
  const { previousContent } = stampSprintClose(sprintFile, () => completedAt);
6152
6218
  sprintFileSnapshot = previousContent;
6153
6219
  if (wikiInitialised) {
@@ -6169,15 +6235,15 @@ async function sprintArchiveHandler(opts, cli) {
6169
6235
  }
6170
6236
  }
6171
6237
  for (const entry of plan) {
6172
- if (!fs27.existsSync(entry.src)) {
6238
+ if (!fs28.existsSync(entry.src)) {
6173
6239
  stderrFn(`[cleargate sprint archive] source not found: ${entry.src} \u2014 skipping`);
6174
6240
  continue;
6175
6241
  }
6176
- const raw = fs27.readFileSync(entry.src, "utf8");
6242
+ const raw = fs28.readFileSync(entry.src, "utf8");
6177
6243
  const stamped = stampFile(raw, entry.status, completedAt);
6178
- const dest = path28.join(archiveDir, entry.destName);
6244
+ const dest = path29.join(archiveDir, entry.destName);
6179
6245
  atomicWriteStr(entry.src, stamped);
6180
- fs27.renameSync(entry.src, dest);
6246
+ fs28.renameSync(entry.src, dest);
6181
6247
  stdoutFn(`archived: ${entry.destName}`);
6182
6248
  }
6183
6249
  try {
@@ -6220,8 +6286,8 @@ async function sprintArchiveHandler(opts, cli) {
6220
6286
 
6221
6287
  // src/commands/story.ts
6222
6288
  init_cjs_shims();
6223
- var fs28 = __toESM(require("fs"), 1);
6224
- var path29 = __toESM(require("path"), 1);
6289
+ var fs29 = __toESM(require("fs"), 1);
6290
+ var path30 = __toESM(require("path"), 1);
6225
6291
  var import_node_child_process10 = require("child_process");
6226
6292
  function defaultExit2(code) {
6227
6293
  return process.exit(code);
@@ -6229,7 +6295,7 @@ function defaultExit2(code) {
6229
6295
  function resolveRunScript2(opts) {
6230
6296
  if (opts.runScriptPath) return opts.runScriptPath;
6231
6297
  const cwd = opts.cwd ?? process.cwd();
6232
- return path29.join(cwd, ".cleargate", "scripts", "run_script.sh");
6298
+ return path30.join(cwd, ".cleargate", "scripts", "run_script.sh");
6233
6299
  }
6234
6300
  function deriveSprintBranch(sprintId) {
6235
6301
  const match = /^SPRINT-(\d+)/.exec(sprintId);
@@ -6238,11 +6304,11 @@ function deriveSprintBranch(sprintId) {
6238
6304
  }
6239
6305
  function atomicWriteString(filePath, text) {
6240
6306
  const tmpFile = `${filePath}.tmp.${process.pid}`;
6241
- fs28.writeFileSync(tmpFile, text, "utf8");
6242
- fs28.renameSync(tmpFile, filePath);
6307
+ fs29.writeFileSync(tmpFile, text, "utf8");
6308
+ fs29.renameSync(tmpFile, filePath);
6243
6309
  }
6244
6310
  function stateJsonPath(cwd, sprintId) {
6245
- return path29.join(cwd, ".cleargate", "sprint-runs", sprintId, "state.json");
6311
+ return path30.join(cwd, ".cleargate", "sprint-runs", sprintId, "state.json");
6246
6312
  }
6247
6313
  function storyStartHandler(opts, cli) {
6248
6314
  const stdoutFn = cli?.stdout ?? ((s) => process.stdout.write(s + "\n"));
@@ -6259,7 +6325,7 @@ function storyStartHandler(opts, cli) {
6259
6325
  return printInertAndExit(stdoutFn, exitFn);
6260
6326
  }
6261
6327
  const sprintBranch = deriveSprintBranch(sprintId);
6262
- const worktreePath = path29.join(cwd, ".worktrees", opts.storyId);
6328
+ const worktreePath = path30.join(cwd, ".worktrees", opts.storyId);
6263
6329
  const storyBranch = `story/${opts.storyId}`;
6264
6330
  const step1 = spawnFn(
6265
6331
  "git",
@@ -6291,13 +6357,13 @@ function storyStartHandler(opts, cli) {
6291
6357
  return exitFn(step2.status ?? 1);
6292
6358
  }
6293
6359
  const stateFile = stateJsonPath(cwd, sprintId);
6294
- if (!fs28.existsSync(stateFile)) {
6360
+ if (!fs29.existsSync(stateFile)) {
6295
6361
  stderrFn(`[cleargate story start] step 3: state.json not found at ${stateFile}`);
6296
6362
  return exitFn(1);
6297
6363
  }
6298
6364
  let state2;
6299
6365
  try {
6300
- state2 = JSON.parse(fs28.readFileSync(stateFile, "utf8"));
6366
+ state2 = JSON.parse(fs29.readFileSync(stateFile, "utf8"));
6301
6367
  } catch (err) {
6302
6368
  stderrFn(`[cleargate story start] step 3: failed to parse state.json: ${err.message}`);
6303
6369
  return exitFn(1);
@@ -6338,7 +6404,7 @@ function storyCompleteHandler(opts, cli) {
6338
6404
  }
6339
6405
  const sprintBranch = deriveSprintBranch(sprintId);
6340
6406
  const storyBranch = `story/${opts.storyId}`;
6341
- const worktreeRel = path29.join(".worktrees", opts.storyId);
6407
+ const worktreeRel = path30.join(".worktrees", opts.storyId);
6342
6408
  const step1 = spawnFn(
6343
6409
  "git",
6344
6410
  ["rev-list", "--count", `${sprintBranch}..${storyBranch}`],
@@ -6436,7 +6502,7 @@ function storyCompleteHandler(opts, cli) {
6436
6502
 
6437
6503
  // src/commands/state.ts
6438
6504
  init_cjs_shims();
6439
- var path30 = __toESM(require("path"), 1);
6505
+ var path31 = __toESM(require("path"), 1);
6440
6506
  var import_node_child_process11 = require("child_process");
6441
6507
  function defaultExit3(code) {
6442
6508
  return process.exit(code);
@@ -6444,7 +6510,7 @@ function defaultExit3(code) {
6444
6510
  function resolveRunScript3(opts) {
6445
6511
  if (opts.runScriptPath) return opts.runScriptPath;
6446
6512
  const cwd = opts.cwd ?? process.cwd();
6447
- return path30.join(cwd, ".cleargate", "scripts", "run_script.sh");
6513
+ return path31.join(cwd, ".cleargate", "scripts", "run_script.sh");
6448
6514
  }
6449
6515
  function stateUpdateHandler(opts, cli) {
6450
6516
  const stdoutFn = cli?.stdout ?? ((s) => process.stdout.write(s + "\n"));
@@ -6501,21 +6567,21 @@ function stateValidateHandler(opts, cli) {
6501
6567
 
6502
6568
  // src/commands/stamp-tokens.ts
6503
6569
  init_cjs_shims();
6504
- var fs30 = __toESM(require("fs"), 1);
6505
- var path32 = __toESM(require("path"), 1);
6570
+ var fs31 = __toESM(require("fs"), 1);
6571
+ var path33 = __toESM(require("path"), 1);
6506
6572
 
6507
6573
  // src/lib/ledger-reader.ts
6508
6574
  init_cjs_shims();
6509
- var fs29 = __toESM(require("fs"), 1);
6510
- var path31 = __toESM(require("path"), 1);
6575
+ var fs30 = __toESM(require("fs"), 1);
6576
+ var path32 = __toESM(require("path"), 1);
6511
6577
  function findSprintRunsRoot(startDir) {
6512
6578
  let dir = startDir;
6513
6579
  while (true) {
6514
- const candidate = path31.join(dir, ".cleargate", "sprint-runs");
6515
- if (fs29.existsSync(candidate)) {
6580
+ const candidate = path32.join(dir, ".cleargate", "sprint-runs");
6581
+ if (fs30.existsSync(candidate)) {
6516
6582
  return candidate;
6517
6583
  }
6518
- const parent = path31.dirname(dir);
6584
+ const parent = path32.dirname(dir);
6519
6585
  if (parent === dir) {
6520
6586
  return null;
6521
6587
  }
@@ -6568,13 +6634,13 @@ function readLedgerForWorkItem(workItemId, opts = {}) {
6568
6634
  }
6569
6635
  sprintRunsRoot = found;
6570
6636
  }
6571
- if (!fs29.existsSync(sprintRunsRoot)) {
6637
+ if (!fs30.existsSync(sprintRunsRoot)) {
6572
6638
  return [];
6573
6639
  }
6574
6640
  let ledgerFiles;
6575
6641
  try {
6576
- const entries = fs29.readdirSync(sprintRunsRoot, { withFileTypes: true });
6577
- ledgerFiles = entries.filter((e) => e.isDirectory()).map((e) => path31.join(sprintRunsRoot, e.name, "token-ledger.jsonl")).filter((f) => fs29.existsSync(f));
6642
+ const entries = fs30.readdirSync(sprintRunsRoot, { withFileTypes: true });
6643
+ ledgerFiles = entries.filter((e) => e.isDirectory()).map((e) => path32.join(sprintRunsRoot, e.name, "token-ledger.jsonl")).filter((f) => fs30.existsSync(f));
6578
6644
  } catch {
6579
6645
  return [];
6580
6646
  }
@@ -6582,7 +6648,7 @@ function readLedgerForWorkItem(workItemId, opts = {}) {
6582
6648
  for (const ledgerFile of ledgerFiles) {
6583
6649
  let content;
6584
6650
  try {
6585
- content = fs29.readFileSync(ledgerFile, "utf-8");
6651
+ content = fs30.readFileSync(ledgerFile, "utf-8");
6586
6652
  } catch {
6587
6653
  continue;
6588
6654
  }
@@ -6633,7 +6699,7 @@ async function stampTokensHandler(file, opts, cli) {
6633
6699
  });
6634
6700
  const nowFn = cli?.now ?? (() => /* @__PURE__ */ new Date());
6635
6701
  const cwd = cli?.cwd ?? process.cwd();
6636
- const absPath = path32.isAbsolute(file) ? file : path32.resolve(cwd, file);
6702
+ const absPath = path33.isAbsolute(file) ? file : path33.resolve(cwd, file);
6637
6703
  if (/\/\.cleargate\/delivery\/archive\//.test(absPath)) {
6638
6704
  stdoutFn(`[frozen] ${absPath}`);
6639
6705
  exitFn(0);
@@ -6641,7 +6707,7 @@ async function stampTokensHandler(file, opts, cli) {
6641
6707
  }
6642
6708
  let rawContent;
6643
6709
  try {
6644
- rawContent = fs30.readFileSync(absPath, "utf-8");
6710
+ rawContent = fs31.readFileSync(absPath, "utf-8");
6645
6711
  } catch {
6646
6712
  stdoutFn(`[stamp-tokens] error: cannot read file: ${absPath}`);
6647
6713
  exitFn(1);
@@ -6713,7 +6779,7 @@ async function stampTokensHandler(file, opts, cli) {
6713
6779
  return;
6714
6780
  }
6715
6781
  try {
6716
- fs30.writeFileSync(absPath, serialized, "utf-8");
6782
+ fs31.writeFileSync(absPath, serialized, "utf-8");
6717
6783
  } catch {
6718
6784
  stdoutFn(`[stamp-tokens] error: cannot write file: ${absPath}`);
6719
6785
  exitFn(1);
@@ -6730,7 +6796,7 @@ function extractWorkItemId(fm, absPath) {
6730
6796
  return val.trim();
6731
6797
  }
6732
6798
  }
6733
- const basename12 = path32.basename(absPath);
6799
+ const basename12 = path33.basename(absPath);
6734
6800
  const match = basename12.match(/^(STORY|EPIC|PROPOSAL|CR|BUG)-\d+(-\d+)?/i);
6735
6801
  if (match) {
6736
6802
  return match[0].toUpperCase();
@@ -6836,7 +6902,7 @@ ${body}`;
6836
6902
  // src/commands/upgrade.ts
6837
6903
  init_cjs_shims();
6838
6904
  var fsp = __toESM(require("fs/promises"), 1);
6839
- var path33 = __toESM(require("path"), 1);
6905
+ var path34 = __toESM(require("path"), 1);
6840
6906
 
6841
6907
  // src/lib/claude-md-surgery.ts
6842
6908
  init_cjs_shims();
@@ -6986,7 +7052,7 @@ async function writeAtomic2(filePath, content) {
6986
7052
  await fsp.rename(tmpPath, filePath);
6987
7053
  }
6988
7054
  async function updateSnapshotEntry(projectRoot, filePath, newSha) {
6989
- const snapshotPath = path33.join(projectRoot, ".cleargate", ".install-manifest.json");
7055
+ const snapshotPath = path34.join(projectRoot, ".cleargate", ".install-manifest.json");
6990
7056
  let snapshot;
6991
7057
  try {
6992
7058
  const raw = await fsp.readFile(snapshotPath, "utf-8");
@@ -7003,17 +7069,17 @@ async function updateSnapshotEntry(projectRoot, filePath, newSha) {
7003
7069
  await writeAtomic2(snapshotPath, JSON.stringify(updated, null, 2) + "\n");
7004
7070
  }
7005
7071
  function isClaudeMd(filePath) {
7006
- return path33.basename(filePath) === "CLAUDE.md";
7072
+ return path34.basename(filePath) === "CLAUDE.md";
7007
7073
  }
7008
7074
  function isSettingsJson(filePath) {
7009
- return path33.basename(filePath) === "settings.json" && filePath.includes(".claude");
7075
+ return path34.basename(filePath) === "settings.json" && filePath.includes(".claude");
7010
7076
  }
7011
7077
  async function applyAlwaysOverwrite(entry, projectRoot, packageRoot, stdout) {
7012
- const targetPath = path33.join(projectRoot, entry.path);
7013
- const sourcePath = path33.join(packageRoot, entry.path);
7078
+ const targetPath = path34.join(projectRoot, entry.path);
7079
+ const sourcePath = path34.join(packageRoot, entry.path);
7014
7080
  try {
7015
7081
  const pkgContent = await fsp.readFile(sourcePath, "utf-8");
7016
- await fsp.mkdir(path33.dirname(targetPath), { recursive: true });
7082
+ await fsp.mkdir(path34.dirname(targetPath), { recursive: true });
7017
7083
  await writeAtomic2(targetPath, pkgContent);
7018
7084
  await updateSnapshotEntry(projectRoot, entry.path, entry.sha256);
7019
7085
  stdout(`[always] overwritten: ${entry.path}`);
@@ -7023,8 +7089,8 @@ async function applyAlwaysOverwrite(entry, projectRoot, packageRoot, stdout) {
7023
7089
  }
7024
7090
  async function applyMerge3Way(entry, projectRoot, packageRoot, installSha, currentSha, flags, opts) {
7025
7091
  const { stdout, stderr, promptMergeChoiceFn, openInEditorFn, stdin } = opts;
7026
- const targetPath = path33.join(projectRoot, entry.path);
7027
- const sourcePath = path33.join(packageRoot, entry.path);
7092
+ const targetPath = path34.join(projectRoot, entry.path);
7093
+ const sourcePath = path34.join(packageRoot, entry.path);
7028
7094
  let ours = "";
7029
7095
  let theirs = "";
7030
7096
  try {
@@ -7087,7 +7153,7 @@ async function applyMerge3Way(entry, projectRoot, packageRoot, installSha, curre
7087
7153
  mergedContent = theirs;
7088
7154
  }
7089
7155
  }
7090
- await fsp.mkdir(path33.dirname(targetPath), { recursive: true });
7156
+ await fsp.mkdir(path34.dirname(targetPath), { recursive: true });
7091
7157
  await writeAtomic2(targetPath, mergedContent);
7092
7158
  const newSha2 = hashNormalized(mergedContent);
7093
7159
  await updateSnapshotEntry(projectRoot, entry.path, newSha2);
@@ -7099,7 +7165,7 @@ async function applyMerge3Way(entry, projectRoot, packageRoot, installSha, curre
7099
7165
  ${ours}=======
7100
7166
  ${theirs}>>>>>>> theirs (upstream)
7101
7167
  `;
7102
- await fsp.mkdir(path33.dirname(mergeFilePath), { recursive: true });
7168
+ await fsp.mkdir(path34.dirname(mergeFilePath), { recursive: true });
7103
7169
  await writeAtomic2(mergeFilePath, conflictContent);
7104
7170
  try {
7105
7171
  const result = await openInEditorFn(mergeFilePath);
@@ -7234,9 +7300,9 @@ async function upgradeHandler(flags, cli) {
7234
7300
 
7235
7301
  // src/commands/uninstall.ts
7236
7302
  init_cjs_shims();
7237
- var fs31 = __toESM(require("fs"), 1);
7303
+ var fs32 = __toESM(require("fs"), 1);
7238
7304
  var fsp2 = __toESM(require("fs/promises"), 1);
7239
- var path34 = __toESM(require("path"), 1);
7305
+ var path35 = __toESM(require("path"), 1);
7240
7306
  var import_node_child_process13 = require("child_process");
7241
7307
  var USER_ARTIFACT_TIERS = ["user-artifact"];
7242
7308
  var FRAMEWORK_TIERS = ["protocol", "template", "agent", "hook", "skill", "cli-config", "derived"];
@@ -7262,10 +7328,10 @@ function shouldPreserve(entry, preserveSet, removeSet) {
7262
7328
  return false;
7263
7329
  }
7264
7330
  function resolveProjectName(target) {
7265
- const pkgPath = path34.join(target, "package.json");
7266
- if (fs31.existsSync(pkgPath)) {
7331
+ const pkgPath = path35.join(target, "package.json");
7332
+ if (fs32.existsSync(pkgPath)) {
7267
7333
  try {
7268
- const raw = fs31.readFileSync(pkgPath, "utf-8");
7334
+ const raw = fs32.readFileSync(pkgPath, "utf-8");
7269
7335
  const parsed = JSON.parse(raw);
7270
7336
  if (parsed.name && typeof parsed.name === "string") {
7271
7337
  return parsed.name;
@@ -7273,7 +7339,7 @@ function resolveProjectName(target) {
7273
7339
  } catch {
7274
7340
  }
7275
7341
  }
7276
- return path34.basename(target);
7342
+ return path35.basename(target);
7277
7343
  }
7278
7344
  function detectUncommittedChanges(target, manifestPaths, gitRunner) {
7279
7345
  const run = gitRunner ?? ((args) => {
@@ -7302,8 +7368,8 @@ function detectUncommittedChanges(target, manifestPaths, gitRunner) {
7302
7368
  return changedFiles.filter((f) => manifestSet.has(f));
7303
7369
  }
7304
7370
  async function removeFromPackageJson(target, dryRun) {
7305
- const pkgPath = path34.join(target, "package.json");
7306
- if (!fs31.existsSync(pkgPath)) return false;
7371
+ const pkgPath = path35.join(target, "package.json");
7372
+ if (!fs32.existsSync(pkgPath)) return false;
7307
7373
  let raw;
7308
7374
  try {
7309
7375
  raw = await fsp2.readFile(pkgPath, "utf-8");
@@ -7344,7 +7410,7 @@ async function removeFile(filePath) {
7344
7410
  }
7345
7411
  async function removeDir(dirPath) {
7346
7412
  try {
7347
- fs31.rmSync(dirPath, { recursive: true, force: true });
7413
+ fs32.rmSync(dirPath, { recursive: true, force: true });
7348
7414
  } catch {
7349
7415
  }
7350
7416
  }
@@ -7364,12 +7430,12 @@ async function uninstallHandler(opts) {
7364
7430
  for (const t of FRAMEWORK_TIERS) removeSet.add(t);
7365
7431
  for (const u of USER_ARTIFACT_TIERS) removeSet.add(u);
7366
7432
  }
7367
- const target = opts.path ? path34.resolve(opts.path) : cwd;
7368
- const cleargateDir = path34.join(target, ".cleargate");
7369
- const manifestPath = path34.join(cleargateDir, ".install-manifest.json");
7370
- const uninstalledPath = path34.join(cleargateDir, ".uninstalled");
7371
- if (!fs31.existsSync(manifestPath)) {
7372
- if (fs31.existsSync(uninstalledPath)) {
7433
+ const target = opts.path ? path35.resolve(opts.path) : cwd;
7434
+ const cleargateDir = path35.join(target, ".cleargate");
7435
+ const manifestPath = path35.join(cleargateDir, ".install-manifest.json");
7436
+ const uninstalledPath = path35.join(cleargateDir, ".uninstalled");
7437
+ if (!fs32.existsSync(manifestPath)) {
7438
+ if (fs32.existsSync(uninstalledPath)) {
7373
7439
  stdout("already uninstalled");
7374
7440
  exit(0);
7375
7441
  return;
@@ -7378,7 +7444,7 @@ async function uninstallHandler(opts) {
7378
7444
  exit(0);
7379
7445
  return;
7380
7446
  }
7381
- if (fs31.existsSync(uninstalledPath) && !fs31.existsSync(manifestPath)) {
7447
+ if (fs32.existsSync(uninstalledPath) && !fs32.existsSync(manifestPath)) {
7382
7448
  stdout("already uninstalled");
7383
7449
  exit(0);
7384
7450
  return;
@@ -7400,10 +7466,10 @@ async function uninstallHandler(opts) {
7400
7466
  return;
7401
7467
  }
7402
7468
  }
7403
- const claudeMdPath = path34.join(target, "CLAUDE.md");
7469
+ const claudeMdPath = path35.join(target, "CLAUDE.md");
7404
7470
  let claudeMdContent = null;
7405
- if (fs31.existsSync(claudeMdPath)) {
7406
- claudeMdContent = fs31.readFileSync(claudeMdPath, "utf-8");
7471
+ if (fs32.existsSync(claudeMdPath)) {
7472
+ claudeMdContent = fs32.readFileSync(claudeMdPath, "utf-8");
7407
7473
  if (!claudeMdContent.includes(CLEARGATE_START)) {
7408
7474
  stderr("CLAUDE.md is missing <!-- CLEARGATE:START --> marker");
7409
7475
  exit(1);
@@ -7419,8 +7485,8 @@ async function uninstallHandler(opts) {
7419
7485
  const toPreserve = [];
7420
7486
  const toSkip = [];
7421
7487
  for (const entry of snapshot.files) {
7422
- const filePath = path34.join(target, entry.path);
7423
- if (!fs31.existsSync(filePath)) {
7488
+ const filePath = path35.join(target, entry.path);
7489
+ if (!fs32.existsSync(filePath)) {
7424
7490
  toSkip.push(entry);
7425
7491
  continue;
7426
7492
  }
@@ -7477,7 +7543,7 @@ async function uninstallHandler(opts) {
7477
7543
  const removedPaths = [];
7478
7544
  const preservedPaths = [];
7479
7545
  for (const entry of toRemove) {
7480
- const filePath = path34.join(target, entry.path);
7546
+ const filePath = path35.join(target, entry.path);
7481
7547
  await removeFile(filePath);
7482
7548
  removedPaths.push(entry.path);
7483
7549
  }
@@ -7493,10 +7559,10 @@ async function uninstallHandler(opts) {
7493
7559
  stderr(`Warning: could not strip CLAUDE.md block: ${err.message}`);
7494
7560
  }
7495
7561
  }
7496
- const settingsPath = path34.join(target, ".claude", "settings.json");
7497
- if (fs31.existsSync(settingsPath)) {
7562
+ const settingsPath = path35.join(target, ".claude", "settings.json");
7563
+ if (fs32.existsSync(settingsPath)) {
7498
7564
  try {
7499
- const raw = fs31.readFileSync(settingsPath, "utf-8");
7565
+ const raw = fs32.readFileSync(settingsPath, "utf-8");
7500
7566
  const settings = JSON.parse(raw);
7501
7567
  const cleaned = removeClearGateHooks(settings);
7502
7568
  await writeAtomic3(settingsPath, JSON.stringify(cleaned, null, 2) + "\n");
@@ -7511,7 +7577,7 @@ async function uninstallHandler(opts) {
7511
7577
  stdout("Removed @cleargate/cli from package.json. Run `npm install` to update package-lock.json.");
7512
7578
  }
7513
7579
  await removeFile(manifestPath);
7514
- await removeFile(path34.join(cleargateDir, ".drift-state.json"));
7580
+ await removeFile(path35.join(cleargateDir, ".drift-state.json"));
7515
7581
  const marker = {
7516
7582
  uninstalled_at: now().toISOString(),
7517
7583
  prior_version: snapshot.cleargate_version,
@@ -7536,30 +7602,30 @@ async function uninstallHandler(opts) {
7536
7602
  // src/commands/sync.ts
7537
7603
  init_cjs_shims();
7538
7604
  var fsPromises8 = __toESM(require("fs/promises"), 1);
7539
- var path42 = __toESM(require("path"), 1);
7605
+ var path43 = __toESM(require("path"), 1);
7540
7606
 
7541
7607
  // src/lib/sync-log.ts
7542
7608
  init_cjs_shims();
7543
- var fs32 = __toESM(require("fs"), 1);
7609
+ var fs33 = __toESM(require("fs"), 1);
7544
7610
  var fsPromises2 = __toESM(require("fs/promises"), 1);
7545
- var path35 = __toESM(require("path"), 1);
7611
+ var path36 = __toESM(require("path"), 1);
7546
7612
  function resolveActiveSprintDir(projectRoot, _opts) {
7547
- const sprintRunsRoot = path35.join(projectRoot, ".cleargate", "sprint-runs");
7548
- const offSprint = path35.join(sprintRunsRoot, "_off-sprint");
7549
- if (!fs32.existsSync(sprintRunsRoot)) {
7550
- fs32.mkdirSync(sprintRunsRoot, { recursive: true });
7551
- fs32.mkdirSync(offSprint, { recursive: true });
7613
+ const sprintRunsRoot = path36.join(projectRoot, ".cleargate", "sprint-runs");
7614
+ const offSprint = path36.join(sprintRunsRoot, "_off-sprint");
7615
+ if (!fs33.existsSync(sprintRunsRoot)) {
7616
+ fs33.mkdirSync(sprintRunsRoot, { recursive: true });
7617
+ fs33.mkdirSync(offSprint, { recursive: true });
7552
7618
  return offSprint;
7553
7619
  }
7554
- const entries = fs32.readdirSync(sprintRunsRoot, { withFileTypes: true });
7620
+ const entries = fs33.readdirSync(sprintRunsRoot, { withFileTypes: true });
7555
7621
  const sprintDirs = entries.filter((e) => e.isDirectory() && e.name !== "_off-sprint").map((e) => {
7556
- const fullPath = path35.join(sprintRunsRoot, e.name);
7557
- const stat = fs32.statSync(fullPath);
7622
+ const fullPath = path36.join(sprintRunsRoot, e.name);
7623
+ const stat = fs33.statSync(fullPath);
7558
7624
  return { name: e.name, fullPath, mtimeMs: stat.mtimeMs };
7559
7625
  }).sort((a, b) => b.mtimeMs - a.mtimeMs);
7560
7626
  if (sprintDirs.length === 0) {
7561
- if (!fs32.existsSync(offSprint)) {
7562
- fs32.mkdirSync(offSprint, { recursive: true });
7627
+ if (!fs33.existsSync(offSprint)) {
7628
+ fs33.mkdirSync(offSprint, { recursive: true });
7563
7629
  }
7564
7630
  return offSprint;
7565
7631
  }
@@ -7570,7 +7636,7 @@ function redactDetail(detail) {
7570
7636
  return detail.replace(/eyJ[A-Za-z0-9._-]+/g, "[REDACTED]");
7571
7637
  }
7572
7638
  async function appendSyncLog(sprintRoot, entry) {
7573
- const logPath = path35.join(sprintRoot, "sync-log.jsonl");
7639
+ const logPath = path36.join(sprintRoot, "sync-log.jsonl");
7574
7640
  await fsPromises2.mkdir(sprintRoot, { recursive: true });
7575
7641
  const safeEntry = {
7576
7642
  ...entry,
@@ -7580,7 +7646,7 @@ async function appendSyncLog(sprintRoot, entry) {
7580
7646
  await fsPromises2.appendFile(logPath, line, { encoding: "utf8" });
7581
7647
  }
7582
7648
  async function readSyncLog(sprintRoot, filters) {
7583
- const logPath = path35.join(sprintRoot, "sync-log.jsonl");
7649
+ const logPath = path36.join(sprintRoot, "sync-log.jsonl");
7584
7650
  let raw;
7585
7651
  try {
7586
7652
  raw = await fsPromises2.readFile(logPath, "utf8");
@@ -7686,7 +7752,7 @@ function classify2(local, remote, since) {
7686
7752
  init_cjs_shims();
7687
7753
  var import_node_fs2 = require("fs");
7688
7754
  var os6 = __toESM(require("os"), 1);
7689
- var path36 = __toESM(require("path"), 1);
7755
+ var path37 = __toESM(require("path"), 1);
7690
7756
  function promptFourChoice(opts) {
7691
7757
  const { stdin, stdout } = opts;
7692
7758
  stdout("[k]eep mine / [t]ake theirs / [e]dit in $EDITOR / [a]bort: ");
@@ -7756,7 +7822,7 @@ async function promptThreeWayMerge(opts) {
7756
7822
  case "a":
7757
7823
  return { resolution: "aborted", body: local };
7758
7824
  case "e": {
7759
- const tmpFile = path36.join(os6.tmpdir(), `cleargate-merge-${itemId}-${now()}.md`);
7825
+ const tmpFile = path37.join(os6.tmpdir(), `cleargate-merge-${itemId}-${now()}.md`);
7760
7826
  const markerContent = `<<<<<<< local
7761
7827
  ${local}
7762
7828
  =======
@@ -7856,12 +7922,12 @@ init_config();
7856
7922
  // src/lib/intake.ts
7857
7923
  init_cjs_shims();
7858
7924
  var fsPromises4 = __toESM(require("fs/promises"), 1);
7859
- var path38 = __toESM(require("path"), 1);
7925
+ var path39 = __toESM(require("path"), 1);
7860
7926
 
7861
7927
  // src/lib/slug.ts
7862
7928
  init_cjs_shims();
7863
7929
  var fsPromises3 = __toESM(require("fs/promises"), 1);
7864
- var path37 = __toESM(require("path"), 1);
7930
+ var path38 = __toESM(require("path"), 1);
7865
7931
  function slugify(title, max = 40) {
7866
7932
  const normalized = title.normalize("NFKD").replace(new RegExp("\\p{M}", "gu"), "");
7867
7933
  const lowered = normalized.toLowerCase();
@@ -7876,8 +7942,8 @@ function slugify(title, max = 40) {
7876
7942
  var PROPOSAL_ID_RE = /^proposal_id:\s*"?PROP-(\d+)"?/m;
7877
7943
  async function nextProposalId(projectRoot) {
7878
7944
  const dirs = [
7879
- path37.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
7880
- path37.join(projectRoot, ".cleargate", "delivery", "archive")
7945
+ path38.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
7946
+ path38.join(projectRoot, ".cleargate", "delivery", "archive")
7881
7947
  ];
7882
7948
  let maxN = 0;
7883
7949
  for (const dir of dirs) {
@@ -7889,7 +7955,7 @@ async function nextProposalId(projectRoot) {
7889
7955
  }
7890
7956
  for (const entry of entries) {
7891
7957
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
7892
- const fullPath = path37.join(dir, entry.name);
7958
+ const fullPath = path38.join(dir, entry.name);
7893
7959
  try {
7894
7960
  const raw = await fsPromises3.readFile(fullPath, "utf8");
7895
7961
  const fmEnd = extractFrontmatterBlock(raw);
@@ -7907,8 +7973,8 @@ async function nextProposalId(projectRoot) {
7907
7973
  }
7908
7974
  async function findByRemoteId(projectRoot, remoteId) {
7909
7975
  const dirs = [
7910
- path37.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
7911
- path37.join(projectRoot, ".cleargate", "delivery", "archive")
7976
+ path38.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
7977
+ path38.join(projectRoot, ".cleargate", "delivery", "archive")
7912
7978
  ];
7913
7979
  const escaped = remoteId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7914
7980
  const re = new RegExp(`^remote_id:\\s*"?${escaped}"?\\s*$`, "m");
@@ -7921,7 +7987,7 @@ async function findByRemoteId(projectRoot, remoteId) {
7921
7987
  }
7922
7988
  for (const entry of entries) {
7923
7989
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
7924
- const fullPath = path37.join(dir, entry.name);
7990
+ const fullPath = path38.join(dir, entry.name);
7925
7991
  try {
7926
7992
  const raw = await fsPromises3.readFile(fullPath, "utf8");
7927
7993
  const fm = extractFrontmatterBlock(raw);
@@ -7958,7 +8024,7 @@ async function runIntakeBranch(opts) {
7958
8024
  labelFilter = "cleargate:proposal",
7959
8025
  now = () => (/* @__PURE__ */ new Date()).toISOString()
7960
8026
  } = opts;
7961
- const pendingSyncDir = path38.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8027
+ const pendingSyncDir = path39.join(projectRoot, ".cleargate", "delivery", "pending-sync");
7962
8028
  let remoteItems = [];
7963
8029
  try {
7964
8030
  remoteItems = await mcp.call(
@@ -7989,7 +8055,7 @@ async function runIntakeBranch(opts) {
7989
8055
  const slug2 = slugify(item.title ?? "untitled");
7990
8056
  const num2 = proposalId2.replace("PROP-", "");
7991
8057
  const filename2 = `PROPOSAL-${num2}-remote-${slug2}.md`;
7992
- const targetPath2 = path38.join(pendingSyncDir, filename2);
8058
+ const targetPath2 = path39.join(pendingSyncDir, filename2);
7993
8059
  createdItems.push({
7994
8060
  proposalId: proposalId2,
7995
8061
  remoteId: item.remote_id,
@@ -8002,7 +8068,7 @@ async function runIntakeBranch(opts) {
8002
8068
  const num = proposalId.replace("PROP-", "");
8003
8069
  const slug = slugify(item.title ?? "untitled");
8004
8070
  const filename = `PROPOSAL-${num}-remote-${slug}.md`;
8005
- const targetPath = path38.join(pendingSyncDir, filename);
8071
+ const targetPath = path39.join(pendingSyncDir, filename);
8006
8072
  const nowTs = now();
8007
8073
  const fm = {
8008
8074
  proposal_id: proposalId,
@@ -8094,8 +8160,8 @@ path/to/new/file.ext - {Explanation of purpose}
8094
8160
  }
8095
8161
  async function hasAnyRemoteAuthored(projectRoot) {
8096
8162
  const dirs = [
8097
- path38.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
8098
- path38.join(projectRoot, ".cleargate", "delivery", "archive")
8163
+ path39.join(projectRoot, ".cleargate", "delivery", "pending-sync"),
8164
+ path39.join(projectRoot, ".cleargate", "delivery", "archive")
8099
8165
  ];
8100
8166
  for (const dir of dirs) {
8101
8167
  let entries;
@@ -8106,7 +8172,7 @@ async function hasAnyRemoteAuthored(projectRoot) {
8106
8172
  }
8107
8173
  for (const entry of entries) {
8108
8174
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
8109
- const fullPath = path38.join(dir, entry.name);
8175
+ const fullPath = path39.join(dir, entry.name);
8110
8176
  try {
8111
8177
  const raw = await fsPromises4.readFile(fullPath, "utf8");
8112
8178
  const fmEnd = raw.indexOf("\n---", 4);
@@ -8124,9 +8190,9 @@ async function hasAnyRemoteAuthored(projectRoot) {
8124
8190
 
8125
8191
  // src/lib/active-criteria.ts
8126
8192
  init_cjs_shims();
8127
- var fs34 = __toESM(require("fs"), 1);
8193
+ var fs35 = __toESM(require("fs"), 1);
8128
8194
  var fsPromises5 = __toESM(require("fs/promises"), 1);
8129
- var path39 = __toESM(require("path"), 1);
8195
+ var path40 = __toESM(require("path"), 1);
8130
8196
  async function resolveActiveItems(projectRoot, localItems, nowFn = () => (/* @__PURE__ */ new Date()).toISOString()) {
8131
8197
  const active = /* @__PURE__ */ new Set();
8132
8198
  const now = Date.parse(nowFn());
@@ -8151,7 +8217,7 @@ async function resolveInSprintIds(projectRoot) {
8151
8217
  const ids = /* @__PURE__ */ new Set();
8152
8218
  try {
8153
8219
  const sprintDir = resolveActiveSprintDir(projectRoot);
8154
- const sprintId = path39.basename(sprintDir);
8220
+ const sprintId = path40.basename(sprintDir);
8155
8221
  if (sprintId === "_off-sprint") return ids;
8156
8222
  const sprintFile = await findSprintFile(projectRoot, sprintId);
8157
8223
  if (!sprintFile) return ids;
@@ -8166,14 +8232,14 @@ async function resolveInSprintIds(projectRoot) {
8166
8232
  return ids;
8167
8233
  }
8168
8234
  async function findSprintFile(projectRoot, sprintId) {
8169
- const pendingSync = path39.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8170
- const archive = path39.join(projectRoot, ".cleargate", "delivery", "archive");
8235
+ const pendingSync = path40.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8236
+ const archive = path40.join(projectRoot, ".cleargate", "delivery", "archive");
8171
8237
  for (const dir of [pendingSync, archive]) {
8172
8238
  try {
8173
- const entries = fs34.readdirSync(dir, { withFileTypes: true });
8239
+ const entries = fs35.readdirSync(dir, { withFileTypes: true });
8174
8240
  for (const entry of entries) {
8175
8241
  if (entry.isFile() && entry.name.startsWith(sprintId) && entry.name.endsWith(".md")) {
8176
- return path39.join(dir, entry.name);
8242
+ return path40.join(dir, entry.name);
8177
8243
  }
8178
8244
  }
8179
8245
  } catch {
@@ -8185,12 +8251,12 @@ async function findSprintFile(projectRoot, sprintId) {
8185
8251
  // src/lib/comments-cache.ts
8186
8252
  init_cjs_shims();
8187
8253
  var fsPromises6 = __toESM(require("fs/promises"), 1);
8188
- var path40 = __toESM(require("path"), 1);
8254
+ var path41 = __toESM(require("path"), 1);
8189
8255
  function cacheDir(projectRoot) {
8190
- return path40.join(projectRoot, ".cleargate", ".comments-cache");
8256
+ return path41.join(projectRoot, ".cleargate", ".comments-cache");
8191
8257
  }
8192
8258
  function cachePath(projectRoot, remoteId) {
8193
- return path40.join(cacheDir(projectRoot), `${remoteId}.json`);
8259
+ return path41.join(cacheDir(projectRoot), `${remoteId}.json`);
8194
8260
  }
8195
8261
  async function writeCommentCache(projectRoot, remoteId, comments) {
8196
8262
  const dir = cacheDir(projectRoot);
@@ -8205,7 +8271,7 @@ async function writeCommentCache(projectRoot, remoteId, comments) {
8205
8271
  // src/lib/wiki-comments-render.ts
8206
8272
  init_cjs_shims();
8207
8273
  var fsPromises7 = __toESM(require("fs/promises"), 1);
8208
- var path41 = __toESM(require("path"), 1);
8274
+ var path42 = __toESM(require("path"), 1);
8209
8275
  var START = "<!-- cleargate:comments:start -->";
8210
8276
  var END = "<!-- cleargate:comments:end -->";
8211
8277
  function resolveBucket(fm) {
@@ -8250,7 +8316,7 @@ async function renderCommentsSection(opts) {
8250
8316
  const bucket = resolveBucket(localItem.fm);
8251
8317
  const primaryId = getPrimaryId(localItem.fm);
8252
8318
  if (!bucket || !primaryId) return;
8253
- const wikiPath = path41.join(
8319
+ const wikiPath = path42.join(
8254
8320
  projectRoot,
8255
8321
  ".cleargate",
8256
8322
  "wiki",
@@ -8286,7 +8352,7 @@ async function renderCommentsSection(opts) {
8286
8352
  await writeAtomic4(wikiPath, updated);
8287
8353
  }
8288
8354
  async function writeAtomic4(filePath, content) {
8289
- await fsPromises7.mkdir(path41.dirname(filePath), { recursive: true });
8355
+ await fsPromises7.mkdir(path42.dirname(filePath), { recursive: true });
8290
8356
  const tmpPath = `${filePath}.tmp.${Date.now()}`;
8291
8357
  await fsPromises7.writeFile(tmpPath, content, "utf8");
8292
8358
  await fsPromises7.rename(tmpPath, filePath);
@@ -8298,11 +8364,11 @@ async function syncCheckHandler(opts = {}) {
8298
8364
  const env = opts.env ?? process.env;
8299
8365
  const stdout = opts.stdout ?? ((s) => process.stdout.write(s));
8300
8366
  const nowFn = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
8301
- const markerPath = path42.join(projectRoot, ".cleargate", ".sync-marker.json");
8367
+ const markerPath = path43.join(projectRoot, ".cleargate", ".sync-marker.json");
8302
8368
  const updateMarker = async (nowIso2) => {
8303
8369
  try {
8304
8370
  const content = JSON.stringify({ last_check: nowIso2 });
8305
- await fsPromises8.mkdir(path42.dirname(markerPath), { recursive: true });
8371
+ await fsPromises8.mkdir(path43.dirname(markerPath), { recursive: true });
8306
8372
  const tmpPath = `${markerPath}.tmp.${Date.now()}`;
8307
8373
  await fsPromises8.writeFile(tmpPath, content, "utf8");
8308
8374
  await fsPromises8.rename(tmpPath, markerPath);
@@ -8385,7 +8451,7 @@ async function syncHandler(opts = {}) {
8385
8451
  const nowFn = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
8386
8452
  const identity = resolveIdentity(projectRoot);
8387
8453
  const sprintRoot = resolveActiveSprintDir(projectRoot);
8388
- const sprintId = path42.basename(sprintRoot);
8454
+ const sprintId = path43.basename(sprintRoot);
8389
8455
  let mcp;
8390
8456
  if (opts.mcp) {
8391
8457
  mcp = opts.mcp;
@@ -8446,7 +8512,7 @@ async function syncHandler(opts = {}) {
8446
8512
  exit(2);
8447
8513
  return;
8448
8514
  }
8449
- const wikiMetaPath = path42.join(projectRoot, ".cleargate", "wiki", "meta.json");
8515
+ const wikiMetaPath = path43.join(projectRoot, ".cleargate", "wiki", "meta.json");
8450
8516
  let lastRemoteSync = "1970-01-01T00:00:00.000Z";
8451
8517
  try {
8452
8518
  const metaRaw = await fsPromises8.readFile(wikiMetaPath, "utf8");
@@ -8687,7 +8753,7 @@ async function syncHandler(opts = {}) {
8687
8753
  };
8688
8754
  await appendSyncLog(sprintRoot, entry);
8689
8755
  }
8690
- const conflictsFile = path42.join(projectRoot, ".cleargate", ".conflicts.json");
8756
+ const conflictsFile = path43.join(projectRoot, ".cleargate", ".conflicts.json");
8691
8757
  const conflictsContent = {
8692
8758
  generated_at: nowFn(),
8693
8759
  sprint_id: sprintId,
@@ -8695,7 +8761,7 @@ async function syncHandler(opts = {}) {
8695
8761
  };
8696
8762
  await writeAtomic5(conflictsFile, JSON.stringify(conflictsContent, null, 2) + "\n");
8697
8763
  try {
8698
- await fsPromises8.mkdir(path42.dirname(wikiMetaPath), { recursive: true });
8764
+ await fsPromises8.mkdir(path43.dirname(wikiMetaPath), { recursive: true });
8699
8765
  let meta = {};
8700
8766
  try {
8701
8767
  const raw = await fsPromises8.readFile(wikiMetaPath, "utf8");
@@ -8736,13 +8802,13 @@ async function applyPull(item, localPath, fm, actorEmail, nowFn) {
8736
8802
  await writeAtomic5(localPath, newContent);
8737
8803
  }
8738
8804
  async function writeAtomic5(filePath, content) {
8739
- await fsPromises8.mkdir(path42.dirname(filePath), { recursive: true });
8805
+ await fsPromises8.mkdir(path43.dirname(filePath), { recursive: true });
8740
8806
  const tmpPath = `${filePath}.tmp.${Date.now()}`;
8741
8807
  await fsPromises8.writeFile(tmpPath, content, "utf8");
8742
8808
  await fsPromises8.rename(tmpPath, filePath);
8743
8809
  }
8744
8810
  async function scanLocalItems(projectRoot) {
8745
- const pendingSync = path42.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8811
+ const pendingSync = path43.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8746
8812
  const results = [];
8747
8813
  let entries;
8748
8814
  try {
@@ -8752,7 +8818,7 @@ async function scanLocalItems(projectRoot) {
8752
8818
  }
8753
8819
  for (const entry of entries) {
8754
8820
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
8755
- const fullPath = path42.join(pendingSync, entry.name);
8821
+ const fullPath = path43.join(pendingSync, entry.name);
8756
8822
  try {
8757
8823
  const raw = await fsPromises8.readFile(fullPath, "utf8");
8758
8824
  const { fm, body } = parseFrontmatter(raw);
@@ -8775,7 +8841,7 @@ function getItemId(fm) {
8775
8841
  // src/commands/pull.ts
8776
8842
  init_cjs_shims();
8777
8843
  var fsPromises9 = __toESM(require("fs/promises"), 1);
8778
- var path43 = __toESM(require("path"), 1);
8844
+ var path44 = __toESM(require("path"), 1);
8779
8845
  init_acquire();
8780
8846
  init_config();
8781
8847
  async function pullHandler(idOrRemoteId, opts = {}) {
@@ -8890,7 +8956,7 @@ async function pullHandler(idOrRemoteId, opts = {}) {
8890
8956
  result: "ok"
8891
8957
  };
8892
8958
  await appendSyncLog(sprintRoot, entry);
8893
- stdout(`pull: ${remoteId} applied to ${path43.relative(projectRoot, localPath)}
8959
+ stdout(`pull: ${remoteId} applied to ${path44.relative(projectRoot, localPath)}
8894
8960
  `);
8895
8961
  if (opts.comments) {
8896
8962
  const comments = await mcp.call(
@@ -8913,7 +8979,7 @@ async function resolveRemoteId(idOrRemoteId, projectRoot) {
8913
8979
  if (/^[A-Z]+-\d+/.test(idOrRemoteId)) {
8914
8980
  return idOrRemoteId;
8915
8981
  }
8916
- const pendingSync = path43.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8982
+ const pendingSync = path44.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8917
8983
  let entries;
8918
8984
  try {
8919
8985
  entries = await fsPromises9.readdir(pendingSync, { withFileTypes: true });
@@ -8923,7 +8989,7 @@ async function resolveRemoteId(idOrRemoteId, projectRoot) {
8923
8989
  for (const entry of entries) {
8924
8990
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
8925
8991
  try {
8926
- const raw = await fsPromises9.readFile(path43.join(pendingSync, entry.name), "utf8");
8992
+ const raw = await fsPromises9.readFile(path44.join(pendingSync, entry.name), "utf8");
8927
8993
  const { fm } = parseFrontmatter(raw);
8928
8994
  for (const key of ["story_id", "epic_id", "proposal_id", "cr_id", "bug_id"]) {
8929
8995
  if (fm[key] === idOrRemoteId && typeof fm["remote_id"] === "string") {
@@ -8936,7 +9002,7 @@ async function resolveRemoteId(idOrRemoteId, projectRoot) {
8936
9002
  return null;
8937
9003
  }
8938
9004
  async function findLocalFile(remoteId, projectRoot) {
8939
- const pendingSync = path43.join(projectRoot, ".cleargate", "delivery", "pending-sync");
9005
+ const pendingSync = path44.join(projectRoot, ".cleargate", "delivery", "pending-sync");
8940
9006
  let entries;
8941
9007
  try {
8942
9008
  entries = await fsPromises9.readdir(pendingSync, { withFileTypes: true });
@@ -8945,7 +9011,7 @@ async function findLocalFile(remoteId, projectRoot) {
8945
9011
  }
8946
9012
  for (const entry of entries) {
8947
9013
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
8948
- const fullPath = path43.join(pendingSync, entry.name);
9014
+ const fullPath = path44.join(pendingSync, entry.name);
8949
9015
  try {
8950
9016
  const raw = await fsPromises9.readFile(fullPath, "utf8");
8951
9017
  const { fm } = parseFrontmatter(raw);
@@ -8956,7 +9022,7 @@ async function findLocalFile(remoteId, projectRoot) {
8956
9022
  return null;
8957
9023
  }
8958
9024
  async function writeAtomic6(filePath, content) {
8959
- await fsPromises9.mkdir(path43.dirname(filePath), { recursive: true });
9025
+ await fsPromises9.mkdir(path44.dirname(filePath), { recursive: true });
8960
9026
  const tmpPath = `${filePath}.tmp.${Date.now()}`;
8961
9027
  await fsPromises9.writeFile(tmpPath, content, "utf8");
8962
9028
  await fsPromises9.rename(tmpPath, filePath);
@@ -8972,7 +9038,7 @@ function getItemId2(fm) {
8972
9038
  // src/commands/push.ts
8973
9039
  init_cjs_shims();
8974
9040
  var fsPromises10 = __toESM(require("fs/promises"), 1);
8975
- var path44 = __toESM(require("path"), 1);
9041
+ var path45 = __toESM(require("path"), 1);
8976
9042
  init_acquire();
8977
9043
  init_config();
8978
9044
  async function pushHandler(fileOrId, opts = {}) {
@@ -9048,7 +9114,7 @@ async function pushHandler(fileOrId, opts = {}) {
9048
9114
  }
9049
9115
  async function handlePush(filePath, ctx) {
9050
9116
  const { projectRoot, identity, sprintRoot, nowFn, resolveMcp, stdout, stderr, exit } = ctx;
9051
- const resolvedPath = path44.isAbsolute(filePath) ? filePath : path44.resolve(projectRoot, filePath);
9117
+ const resolvedPath = path45.isAbsolute(filePath) ? filePath : path45.resolve(projectRoot, filePath);
9052
9118
  let rawContent;
9053
9119
  try {
9054
9120
  rawContent = await fsPromises10.readFile(resolvedPath, "utf8");
@@ -9174,8 +9240,8 @@ async function handleRevert(idOrRemoteId, ctx) {
9174
9240
  void localPath;
9175
9241
  }
9176
9242
  async function resolveLocalItem(idOrRemoteId, projectRoot) {
9177
- const pendingSync = path44.join(projectRoot, ".cleargate", "delivery", "pending-sync");
9178
- const archive = path44.join(projectRoot, ".cleargate", "delivery", "archive");
9243
+ const pendingSync = path45.join(projectRoot, ".cleargate", "delivery", "pending-sync");
9244
+ const archive = path45.join(projectRoot, ".cleargate", "delivery", "archive");
9179
9245
  for (const dir of [pendingSync, archive]) {
9180
9246
  let entries;
9181
9247
  try {
@@ -9185,7 +9251,7 @@ async function resolveLocalItem(idOrRemoteId, projectRoot) {
9185
9251
  }
9186
9252
  for (const entry of entries) {
9187
9253
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
9188
- const fullPath = path44.join(dir, entry.name);
9254
+ const fullPath = path45.join(dir, entry.name);
9189
9255
  try {
9190
9256
  const raw = await fsPromises10.readFile(fullPath, "utf8");
9191
9257
  const { fm } = parseFrontmatter(raw);
@@ -9204,7 +9270,7 @@ async function resolveLocalItem(idOrRemoteId, projectRoot) {
9204
9270
  return null;
9205
9271
  }
9206
9272
  async function writeAtomic7(filePath, content) {
9207
- await fsPromises10.mkdir(path44.dirname(filePath), { recursive: true });
9273
+ await fsPromises10.mkdir(path45.dirname(filePath), { recursive: true });
9208
9274
  const tmpPath = `${filePath}.tmp.${Date.now()}`;
9209
9275
  await fsPromises10.writeFile(tmpPath, content, "utf8");
9210
9276
  await fsPromises10.rename(tmpPath, filePath);
@@ -9233,7 +9299,7 @@ function getItemType(fm) {
9233
9299
  // src/commands/conflicts.ts
9234
9300
  init_cjs_shims();
9235
9301
  var fsPromises11 = __toESM(require("fs/promises"), 1);
9236
- var path45 = __toESM(require("path"), 1);
9302
+ var path46 = __toESM(require("path"), 1);
9237
9303
  init_acquire();
9238
9304
  init_config();
9239
9305
  var RESOLUTION_HINTS = {
@@ -9271,7 +9337,7 @@ async function conflictsHandler(opts = {}) {
9271
9337
  }
9272
9338
  }
9273
9339
  }
9274
- const conflictsFile = path45.join(projectRoot, ".cleargate", ".conflicts.json");
9340
+ const conflictsFile = path46.join(projectRoot, ".cleargate", ".conflicts.json");
9275
9341
  let data;
9276
9342
  try {
9277
9343
  const raw = await fsPromises11.readFile(conflictsFile, "utf8");
@@ -9359,8 +9425,8 @@ function formatEntry(entry) {
9359
9425
 
9360
9426
  // src/commands/admin-login.ts
9361
9427
  init_cjs_shims();
9362
- var fs35 = __toESM(require("fs"), 1);
9363
- var path46 = __toESM(require("path"), 1);
9428
+ var fs36 = __toESM(require("fs"), 1);
9429
+ var path47 = __toESM(require("path"), 1);
9364
9430
  var os7 = __toESM(require("os"), 1);
9365
9431
  var DEFAULT_MCP_URL = "http://localhost:3000";
9366
9432
  function resolveMcpUrl(mcpUrlFlag, env) {
@@ -9369,14 +9435,14 @@ function resolveMcpUrl(mcpUrlFlag, env) {
9369
9435
  function resolveAuthFilePath(opts) {
9370
9436
  if (opts.authFilePath) return opts.authFilePath;
9371
9437
  const homedirFn = opts.homedir ?? os7.homedir;
9372
- return path46.join(homedirFn(), ".cleargate", "admin-auth.json");
9438
+ return path47.join(homedirFn(), ".cleargate", "admin-auth.json");
9373
9439
  }
9374
9440
  function writeAdminAuth(filePath, token) {
9375
- const dir = path46.dirname(filePath);
9376
- fs35.mkdirSync(dir, { recursive: true });
9441
+ const dir = path47.dirname(filePath);
9442
+ fs36.mkdirSync(dir, { recursive: true });
9377
9443
  const payload = JSON.stringify({ version: 1, token }, null, 2);
9378
- fs35.writeFileSync(filePath, payload, { encoding: "utf8", mode: 384 });
9379
- fs35.chmodSync(filePath, 384);
9444
+ fs36.writeFileSync(filePath, payload, { encoding: "utf8", mode: 384 });
9445
+ fs36.chmodSync(filePath, 384);
9380
9446
  }
9381
9447
  async function adminLoginHandler(opts = {}) {
9382
9448
  const fetchFn = opts.fetch ?? globalThis.fetch;
@@ -9486,8 +9552,8 @@ async function adminLoginHandler(opts = {}) {
9486
9552
 
9487
9553
  // src/commands/hotfix.ts
9488
9554
  init_cjs_shims();
9489
- var fs36 = __toESM(require("fs"), 1);
9490
- var path47 = __toESM(require("path"), 1);
9555
+ var fs37 = __toESM(require("fs"), 1);
9556
+ var path48 = __toESM(require("path"), 1);
9491
9557
  function defaultExit4(code) {
9492
9558
  return process.exit(code);
9493
9559
  }
@@ -9497,7 +9563,7 @@ function maxHotfixId(pendingDir) {
9497
9563
  let max = 0;
9498
9564
  let entries;
9499
9565
  try {
9500
- entries = fs36.readdirSync(pendingDir);
9566
+ entries = fs37.readdirSync(pendingDir);
9501
9567
  } catch {
9502
9568
  return 0;
9503
9569
  }
@@ -9511,13 +9577,13 @@ function maxHotfixId(pendingDir) {
9511
9577
  return max;
9512
9578
  }
9513
9579
  function countActiveHotfixes(repoRoot) {
9514
- const pendingDir = path47.join(repoRoot, ".cleargate", "delivery", "pending-sync");
9515
- const archiveDir = path47.join(repoRoot, ".cleargate", "delivery", "archive");
9580
+ const pendingDir = path48.join(repoRoot, ".cleargate", "delivery", "pending-sync");
9581
+ const archiveDir = path48.join(repoRoot, ".cleargate", "delivery", "archive");
9516
9582
  const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1e3;
9517
9583
  let count = 0;
9518
9584
  let pendingEntries = [];
9519
9585
  try {
9520
- pendingEntries = fs36.readdirSync(pendingDir);
9586
+ pendingEntries = fs37.readdirSync(pendingDir);
9521
9587
  } catch {
9522
9588
  }
9523
9589
  for (const entry of pendingEntries) {
@@ -9525,13 +9591,13 @@ function countActiveHotfixes(repoRoot) {
9525
9591
  }
9526
9592
  let archiveEntries = [];
9527
9593
  try {
9528
- archiveEntries = fs36.readdirSync(archiveDir);
9594
+ archiveEntries = fs37.readdirSync(archiveDir);
9529
9595
  } catch {
9530
9596
  }
9531
9597
  for (const entry of archiveEntries) {
9532
9598
  if (entry.startsWith("HOTFIX-") && entry.endsWith(".md")) {
9533
9599
  try {
9534
- const stat = fs36.statSync(path47.join(archiveDir, entry));
9600
+ const stat = fs37.statSync(path48.join(archiveDir, entry));
9535
9601
  if (stat.mtimeMs >= sevenDaysAgo) count++;
9536
9602
  } catch {
9537
9603
  }
@@ -9540,7 +9606,7 @@ function countActiveHotfixes(repoRoot) {
9540
9606
  return count;
9541
9607
  }
9542
9608
  function resolveTemplatePath(repoRoot) {
9543
- return path47.join(repoRoot, ".cleargate", "templates", "hotfix.md");
9609
+ return path48.join(repoRoot, ".cleargate", "templates", "hotfix.md");
9544
9610
  }
9545
9611
  function hotfixNewHandler(opts, cli) {
9546
9612
  const stdoutFn = cli?.stdout ?? ((s) => process.stdout.write(s + "\n"));
@@ -9559,14 +9625,14 @@ function hotfixNewHandler(opts, cli) {
9559
9625
  );
9560
9626
  return exitFn(1);
9561
9627
  }
9562
- const pendingDir = path47.join(repoRoot, ".cleargate", "delivery", "pending-sync");
9628
+ const pendingDir = path48.join(repoRoot, ".cleargate", "delivery", "pending-sync");
9563
9629
  const maxId = maxHotfixId(pendingDir);
9564
9630
  const nextId = maxId + 1;
9565
9631
  const idStr = `HOTFIX-${String(nextId).padStart(3, "0")}`;
9566
9632
  const templatePath = resolveTemplatePath(repoRoot);
9567
9633
  let templateContent;
9568
9634
  try {
9569
- templateContent = fs36.readFileSync(templatePath, "utf8");
9635
+ templateContent = fs37.readFileSync(templatePath, "utf8");
9570
9636
  } catch {
9571
9637
  stderrFn(`[cleargate hotfix new] template not found: ${templatePath}`);
9572
9638
  return exitFn(2);
@@ -9574,10 +9640,10 @@ function hotfixNewHandler(opts, cli) {
9574
9640
  const content = templateContent.replace(/\{ID\}/g, idStr).replace(/\{SLUG\}/g, opts.slug).replace(/\{ISO\}/g, now);
9575
9641
  const fileSlug = opts.slug.replace(/-/g, "_");
9576
9642
  const fileName = `${idStr}_${fileSlug}.md`;
9577
- const outPath = path47.join(pendingDir, fileName);
9643
+ const outPath = path48.join(pendingDir, fileName);
9578
9644
  try {
9579
- fs36.mkdirSync(pendingDir, { recursive: true });
9580
- fs36.writeFileSync(outPath, content, "utf8");
9645
+ fs37.mkdirSync(pendingDir, { recursive: true });
9646
+ fs37.writeFileSync(outPath, content, "utf8");
9581
9647
  } catch (err) {
9582
9648
  const msg = err instanceof Error ? err.message : String(err);
9583
9649
  stderrFn(`[cleargate hotfix new] write failed: ${msg}`);