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