claude-launchpad 1.14.0 → 1.15.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.
Files changed (39) hide show
  1. package/dist/{chunk-D6RAMWH6.js → chunk-7KB5YGQZ.js} +2 -2
  2. package/dist/{chunk-UN43OVRW.js → chunk-DLDVXHI3.js} +2 -2
  3. package/dist/{chunk-M6GVFN67.js → chunk-IPGNXDJF.js} +2 -2
  4. package/dist/{chunk-VF7U63AI.js → chunk-LCKV24Q3.js} +3 -3
  5. package/dist/{chunk-OPORVSAF.js → chunk-MX3T2VEX.js} +3 -3
  6. package/dist/{chunk-QEPE3WVF.js → chunk-U2TFIUGE.js} +57 -5
  7. package/dist/chunk-U2TFIUGE.js.map +1 -0
  8. package/dist/cli.js +135 -61
  9. package/dist/cli.js.map +1 -1
  10. package/dist/commands/memory/server.js +4 -4
  11. package/dist/{context-YIPO4LBS.js → context-3GHG7KW6.js} +6 -6
  12. package/dist/{doctor-DCHFJ3XV.js → doctor-EKGJ2YAO.js} +4 -4
  13. package/dist/{install-D32PV7SF.js → install-543ZKMXX.js} +6 -6
  14. package/dist/{pull-YUQTDRUP.js → pull-ULSZEVCR.js} +8 -8
  15. package/dist/{push-U4IVTFOU.js → push-JXCWX4NY.js} +8 -8
  16. package/dist/{require-deps-WDMHDGBN.js → require-deps-AEDO5YRM.js} +3 -3
  17. package/dist/{stats-77BYLKYP.js → stats-63L7C24W.js} +7 -7
  18. package/dist/{sync-DTCWK2CY.js → sync-QTJ6BXQ4.js} +5 -5
  19. package/dist/{sync-clean-ACZCB3NZ.js → sync-clean-OJEK4XH4.js} +3 -3
  20. package/dist/{sync-status-2V2RCYZO.js → sync-status-EAX527SC.js} +8 -8
  21. package/dist/{tui-HVJNLRY2.js → tui-3KITZCNS.js} +5 -5
  22. package/package.json +1 -1
  23. package/dist/chunk-QEPE3WVF.js.map +0 -1
  24. /package/dist/{chunk-D6RAMWH6.js.map → chunk-7KB5YGQZ.js.map} +0 -0
  25. /package/dist/{chunk-UN43OVRW.js.map → chunk-DLDVXHI3.js.map} +0 -0
  26. /package/dist/{chunk-M6GVFN67.js.map → chunk-IPGNXDJF.js.map} +0 -0
  27. /package/dist/{chunk-VF7U63AI.js.map → chunk-LCKV24Q3.js.map} +0 -0
  28. /package/dist/{chunk-OPORVSAF.js.map → chunk-MX3T2VEX.js.map} +0 -0
  29. /package/dist/{context-YIPO4LBS.js.map → context-3GHG7KW6.js.map} +0 -0
  30. /package/dist/{doctor-DCHFJ3XV.js.map → doctor-EKGJ2YAO.js.map} +0 -0
  31. /package/dist/{install-D32PV7SF.js.map → install-543ZKMXX.js.map} +0 -0
  32. /package/dist/{pull-YUQTDRUP.js.map → pull-ULSZEVCR.js.map} +0 -0
  33. /package/dist/{push-U4IVTFOU.js.map → push-JXCWX4NY.js.map} +0 -0
  34. /package/dist/{require-deps-WDMHDGBN.js.map → require-deps-AEDO5YRM.js.map} +0 -0
  35. /package/dist/{stats-77BYLKYP.js.map → stats-63L7C24W.js.map} +0 -0
  36. /package/dist/{sync-DTCWK2CY.js.map → sync-QTJ6BXQ4.js.map} +0 -0
  37. /package/dist/{sync-clean-ACZCB3NZ.js.map → sync-clean-OJEK4XH4.js.map} +0 -0
  38. /package/dist/{sync-status-2V2RCYZO.js.map → sync-status-EAX527SC.js.map} +0 -0
  39. /package/dist/{tui-HVJNLRY2.js.map → tui-3KITZCNS.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readSyncConfig
4
- } from "./chunk-M6GVFN67.js";
4
+ } from "./chunk-IPGNXDJF.js";
5
5
  import {
6
6
  BACKLOG_CONTENT,
7
7
  ENHANCE_SKILL_VERSION,
8
+ FORCE_PUSH_ERE,
8
9
  LP_STUB_OPEN,
9
10
  OFF_LIMITS_CONTENT,
10
11
  SESSION_START_CONTENT,
@@ -40,11 +41,11 @@ import {
40
41
  sprintReviewsContent,
41
42
  writeSprintHygieneScripts,
42
43
  writeWorkflowCheckScript
43
- } from "./chunk-QEPE3WVF.js";
44
+ } from "./chunk-U2TFIUGE.js";
44
45
 
45
46
  // src/cli.ts
46
47
  import { Command as Command5 } from "commander";
47
- import { join as join13 } from "path";
48
+ import { join as join14 } from "path";
48
49
 
49
50
  // src/commands/init/index.ts
50
51
  import { Command } from "commander";
@@ -95,7 +96,8 @@ ${STOP_AND_SWARM_CONTENT}`);
95
96
  sections.push("", `## Off-Limits
96
97
  ${OFF_LIMITS_CONTENT}`);
97
98
  sections.push("", `## Key Decisions
98
- <!-- Record architectural decisions as you make them -->`);
99
+ <!-- Append one entry per non-obvious choice, at the moment it's made \u2014 not at sprint close: -->
100
+ <!-- YYYY-MM-DD \u2014 Chose X over Y because Z. Revisit if W. -->`);
99
101
  return sections.join("\n") + "\n";
100
102
  }
101
103
 
@@ -144,7 +146,7 @@ function generateSettings(detected) {
144
146
  matcher: "Bash",
145
147
  hooks: [{
146
148
  type: "command",
147
- command: `cmd=${jqField("command")}; echo "$cmd" | grep -qE 'rm\\s+-rf\\s+/|DROP\\s+TABLE|DROP\\s+DATABASE|push.*--force|push.*-f' && { echo 'BLOCKED: Destructive command detected' >&2; exit 2; }; exit 0`
149
+ command: `cmd=${jqField("command")}; echo "$cmd" | grep -qE 'rm\\s+-rf\\s+/|DROP\\s+TABLE|DROP\\s+DATABASE|${FORCE_PUSH_ERE}' && { echo 'BLOCKED: Destructive command detected' >&2; exit 2; }; exit 0`
148
150
  }]
149
151
  });
150
152
  const editWriteHooks = [];
@@ -905,7 +907,28 @@ async function analyzeHooks(config, projectRoot = "") {
905
907
  });
906
908
  return { name: "Hooks", issues, score: 30 };
907
909
  }
908
- const formatPatterns = ["format", "prettier", "gofmt", "rustfmt", "rubocop", "pint", "ktlint", "swift-format", "dotnet format"];
910
+ const hasStaleForcePattern = config.hooks.some(
911
+ (h) => h.command?.includes("push.*--force|push.*-f")
912
+ );
913
+ if (hasStaleForcePattern) {
914
+ issues.push({
915
+ analyzer: "Hooks",
916
+ severity: "low",
917
+ message: "Force-push guard uses the outdated pattern \u2014 it false-positives on unrelated commands (git stash push, --frozen-lockfile, filenames)",
918
+ fix: "Run `doctor --fix` to upgrade it to the anchored pattern"
919
+ });
920
+ }
921
+ const formatPatterns = [
922
+ "format",
923
+ "prettier",
924
+ "gofmt",
925
+ "rustfmt",
926
+ "rubocop",
927
+ "pint",
928
+ "ktlint",
929
+ "swift-format",
930
+ "dotnet format"
931
+ ];
909
932
  const hasPostFormat = hooks.some(
910
933
  (h) => h.event === "PostToolUse" && h.matcher?.includes("Write") && formatPatterns.some((p) => h.command?.includes(p))
911
934
  );
@@ -1047,10 +1070,14 @@ async function analyzeHooks(config, projectRoot = "") {
1047
1070
  }
1048
1071
  async function hasStaleHygieneScript(projectRoot) {
1049
1072
  const { readFile: readFile7 } = await import("fs/promises");
1050
- const { join: join14 } = await import("path");
1073
+ const { join: join15 } = await import("path");
1051
1074
  for (const name of ["workflow-check.sh", "sprint-open-check.sh"]) {
1052
- const content = await readFile7(join14(projectRoot, ".claude", "hooks", name), "utf-8").catch(() => null);
1053
- if (content !== null && !content.includes("hookSpecificOutput")) return true;
1075
+ const content = await readFile7(
1076
+ join15(projectRoot, ".claude", "hooks", name),
1077
+ "utf-8"
1078
+ ).catch(() => null);
1079
+ if (content !== null && !content.includes("hookSpecificOutput"))
1080
+ return true;
1054
1081
  }
1055
1082
  return false;
1056
1083
  }
@@ -1480,6 +1507,11 @@ function extractAllow(settings) {
1480
1507
  return Array.isArray(allow) ? allow.filter((e) => typeof e === "string") : [];
1481
1508
  }
1482
1509
 
1510
+ // src/commands/doctor/analyzers/quality.ts
1511
+ import { execSync } from "child_process";
1512
+ import { existsSync as existsSync2 } from "fs";
1513
+ import { join as join6 } from "path";
1514
+
1483
1515
  // src/commands/doctor/analyzers/hook-resolver.ts
1484
1516
  import { readFile as readFile3, realpath } from "fs/promises";
1485
1517
  import { resolve as resolve2, sep } from "path";
@@ -1894,7 +1926,10 @@ function documentSatisfiesIntent(sections, rule) {
1894
1926
 
1895
1927
  // src/commands/doctor/analyzers/quality.ts
1896
1928
  var VAGUE_PATTERNS = [
1897
- { pattern: /write (good|clean|quality|nice) code/i, label: "write good code" },
1929
+ {
1930
+ pattern: /write (good|clean|quality|nice) code/i,
1931
+ label: "write good code"
1932
+ },
1898
1933
  { pattern: /be (careful|thorough|diligent)/i, label: "be careful" },
1899
1934
  { pattern: /follow best practices/i, label: "follow best practices" },
1900
1935
  { pattern: /make sure (everything|it) works/i, label: "make sure it works" }
@@ -1977,17 +2012,56 @@ async function analyzeQuality(config, projectRoot) {
1977
2012
  fix: "Run `doctor --fix` to collapse them"
1978
2013
  });
1979
2014
  }
2015
+ if (isKeyDecisionsPlaceholder(content) && commitCount(projectRoot) >= 20) {
2016
+ issues.push({
2017
+ analyzer: "Quality",
2018
+ severity: "low",
2019
+ message: "Key Decisions is still placeholder-only after 20+ commits \u2014 decisions are being made but not logged",
2020
+ fix: "Append entries at decision time: `YYYY-MM-DD \u2014 Chose X over Y because Z. Revisit if W.`"
2021
+ });
2022
+ }
1980
2023
  const criticals = issues.filter((i) => i.severity === "critical").length;
1981
2024
  const highs = issues.filter((i) => i.severity === "high").length;
1982
2025
  const mediums = issues.filter((i) => i.severity === "medium").length;
1983
2026
  const lows = issues.filter((i) => i.severity === "low").length;
1984
- const score = Math.max(0, 100 - criticals * 40 - highs * 30 - mediums * 15 - lows * 5);
2027
+ const score = Math.max(
2028
+ 0,
2029
+ 100 - criticals * 40 - highs * 30 - mediums * 15 - lows * 5
2030
+ );
1985
2031
  return { name: "CLAUDE.md Quality", issues, score };
1986
2032
  }
2033
+ function isKeyDecisionsPlaceholder(content) {
2034
+ const lines = content.split("\n");
2035
+ const start = lines.findIndex((l) => /^## Key Decisions\s*$/.test(l));
2036
+ if (start === -1) return false;
2037
+ let end = lines.length;
2038
+ for (let i = start + 1; i < lines.length; i++) {
2039
+ if (/^## /.test(lines[i])) {
2040
+ end = i;
2041
+ break;
2042
+ }
2043
+ }
2044
+ const body = lines.slice(start + 1, end).join("\n").replace(/<!--[\s\S]*?-->/g, "").trim();
2045
+ return body.length === 0;
2046
+ }
2047
+ function commitCount(projectRoot) {
2048
+ if (!existsSync2(join6(projectRoot, ".git"))) return 0;
2049
+ try {
2050
+ return parseInt(
2051
+ execSync("git rev-list --count HEAD", {
2052
+ cwd: projectRoot,
2053
+ stdio: ["ignore", "pipe", "ignore"]
2054
+ }).toString().trim(),
2055
+ 10
2056
+ ) || 0;
2057
+ } catch {
2058
+ return 0;
2059
+ }
2060
+ }
1987
2061
 
1988
2062
  // src/commands/doctor/analyzers/workflow.ts
1989
2063
  import { readFile as readFile4 } from "fs/promises";
1990
- import { join as join6 } from "path";
2064
+ import { join as join7 } from "path";
1991
2065
  var WP_FIELDS = [
1992
2066
  "Priority:",
1993
2067
  "Proposed:",
@@ -2000,7 +2074,7 @@ var WP_FIELDS = [
2000
2074
  var STALE_P0_DAYS = 14;
2001
2075
  var STALE_CHANGELOG_DAYS = 30;
2002
2076
  async function analyzeWorkflow(projectRoot, now = /* @__PURE__ */ new Date()) {
2003
- const backlog = await readFile4(join6(projectRoot, "BACKLOG.md"), "utf-8").catch(() => null);
2077
+ const backlog = await readFile4(join7(projectRoot, "BACKLOG.md"), "utf-8").catch(() => null);
2004
2078
  if (backlog === null) return null;
2005
2079
  const issues = [];
2006
2080
  const pSections = extractPSections(backlog);
@@ -2081,7 +2155,7 @@ function daysBetween(isoDate, now) {
2081
2155
 
2082
2156
  // src/commands/doctor/watcher.ts
2083
2157
  import { readdir as readdir2, stat } from "fs/promises";
2084
- import { join as join7 } from "path";
2158
+ import { join as join8 } from "path";
2085
2159
  async function watchConfig(projectRoot) {
2086
2160
  await runAndDisplay(projectRoot);
2087
2161
  log.blank();
@@ -2104,16 +2178,16 @@ async function watchConfig(projectRoot) {
2104
2178
  }
2105
2179
  async function getFileSnapshot(projectRoot) {
2106
2180
  const files = [
2107
- join7(projectRoot, "CLAUDE.md"),
2108
- join7(projectRoot, ".claudeignore")
2181
+ join8(projectRoot, "CLAUDE.md"),
2182
+ join8(projectRoot, ".claudeignore")
2109
2183
  ];
2110
- const claudeDir = join7(projectRoot, ".claude");
2184
+ const claudeDir = join8(projectRoot, ".claude");
2111
2185
  try {
2112
2186
  const entries = await readdir2(claudeDir, { withFileTypes: true, recursive: true });
2113
2187
  for (const entry of entries) {
2114
2188
  if (entry.isFile()) {
2115
2189
  const parentPath = entry.parentPath ?? claudeDir;
2116
- files.push(join7(parentPath, entry.name));
2190
+ files.push(join8(parentPath, entry.name));
2117
2191
  }
2118
2192
  }
2119
2193
  } catch {
@@ -2257,11 +2331,11 @@ import { select as select2 } from "@inquirer/prompts";
2257
2331
  import ora from "ora";
2258
2332
  import chalk2 from "chalk";
2259
2333
  import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
2260
- import { join as join11 } from "path";
2334
+ import { join as join12 } from "path";
2261
2335
 
2262
2336
  // src/commands/eval/loader.ts
2263
2337
  import { readFile as readFile5, readdir as readdir3 } from "fs/promises";
2264
- import { join as join8, resolve as resolve3, dirname as dirname2 } from "path";
2338
+ import { join as join9, resolve as resolve3, dirname as dirname2 } from "path";
2265
2339
  import { fileURLToPath } from "url";
2266
2340
  import { parse as parseYaml } from "yaml";
2267
2341
 
@@ -2390,7 +2464,7 @@ async function findScenariosDir() {
2390
2464
  async function loadScenarios(options) {
2391
2465
  const { suite, customPath } = options;
2392
2466
  const scenarioDir = customPath ? resolve3(customPath) : await findScenariosDir();
2393
- const dirs = suite ? [join8(scenarioDir, suite)] : await getSubdirectories(scenarioDir);
2467
+ const dirs = suite ? [join9(scenarioDir, suite)] : await getSubdirectories(scenarioDir);
2394
2468
  const allDirs = [scenarioDir, ...dirs];
2395
2469
  const scenarios = [];
2396
2470
  for (const dir of allDirs) {
@@ -2412,7 +2486,7 @@ async function loadScenarios(options) {
2412
2486
  async function getSubdirectories(dir) {
2413
2487
  try {
2414
2488
  const entries = await readdir3(dir, { withFileTypes: true });
2415
- return entries.filter((e) => e.isDirectory()).map((e) => join8(dir, e.name));
2489
+ return entries.filter((e) => e.isDirectory()).map((e) => join9(dir, e.name));
2416
2490
  } catch {
2417
2491
  return [];
2418
2492
  }
@@ -2420,7 +2494,7 @@ async function getSubdirectories(dir) {
2420
2494
  async function listYamlFiles(dir) {
2421
2495
  try {
2422
2496
  const entries = await readdir3(dir, { withFileTypes: true });
2423
- return entries.filter((e) => e.isFile() && (e.name.endsWith(".yaml") || e.name.endsWith(".yml"))).map((e) => join8(dir, e.name));
2497
+ return entries.filter((e) => e.isFile() && (e.name.endsWith(".yaml") || e.name.endsWith(".yml"))).map((e) => join9(dir, e.name));
2424
2498
  } catch {
2425
2499
  return [];
2426
2500
  }
@@ -2432,7 +2506,7 @@ function resolveRuns(scenarioRuns, cliRuns, userChoseRuns) {
2432
2506
 
2433
2507
  // src/commands/eval/runner.ts
2434
2508
  import { mkdir as mkdir2, writeFile as writeFile2, rm, cp } from "fs/promises";
2435
- import { join as join10, dirname as dirname3 } from "path";
2509
+ import { join as join11, dirname as dirname3 } from "path";
2436
2510
  import { tmpdir as tmpdir2 } from "os";
2437
2511
  import { randomUUID } from "crypto";
2438
2512
  import { execFile as execFile2 } from "child_process";
@@ -2440,7 +2514,7 @@ import { promisify as promisify2 } from "util";
2440
2514
 
2441
2515
  // src/commands/eval/checks.ts
2442
2516
  import { readFile as readFile6, readdir as readdir4 } from "fs/promises";
2443
- import { join as join9 } from "path";
2517
+ import { join as join10 } from "path";
2444
2518
  import { tmpdir } from "os";
2445
2519
  import { execFile } from "child_process";
2446
2520
  import { promisify } from "util";
@@ -2475,7 +2549,7 @@ async function evaluateSingleCheck(check, sandboxDir, context) {
2475
2549
  async function checkGrep(check, sandboxDir) {
2476
2550
  if (!check.pattern || !check.target) return false;
2477
2551
  try {
2478
- const content = await readFile6(join9(sandboxDir, check.target), "utf-8");
2552
+ const content = await readFile6(join10(sandboxDir, check.target), "utf-8");
2479
2553
  let found;
2480
2554
  try {
2481
2555
  found = new RegExp(check.pattern).test(content);
@@ -2490,7 +2564,7 @@ async function checkGrep(check, sandboxDir) {
2490
2564
  async function checkFilePresence(check, sandboxDir) {
2491
2565
  if (!check.target) return false;
2492
2566
  try {
2493
- await readFile6(join9(sandboxDir, check.target));
2567
+ await readFile6(join10(sandboxDir, check.target));
2494
2568
  return check.expect === "present";
2495
2569
  } catch {
2496
2570
  return check.expect === "absent";
@@ -2500,7 +2574,7 @@ async function checkMaxLines(check, sandboxDir) {
2500
2574
  if (!check.target) return false;
2501
2575
  const maxLines = parseInt(check.pattern ?? "800", 10);
2502
2576
  try {
2503
- const files = await listAllFiles(join9(sandboxDir, check.target));
2577
+ const files = await listAllFiles(join10(sandboxDir, check.target));
2504
2578
  for (const file of files) {
2505
2579
  const content = await readFile6(file, "utf-8");
2506
2580
  if (content.split("\n").length > maxLines) {
@@ -2576,7 +2650,7 @@ async function listAllFiles(dir) {
2576
2650
  try {
2577
2651
  const entries = await readdir4(dir, { withFileTypes: true });
2578
2652
  for (const entry of entries) {
2579
- const fullPath = join9(dir, entry.name);
2653
+ const fullPath = join10(dir, entry.name);
2580
2654
  if (entry.isDirectory()) {
2581
2655
  results.push(...await listAllFiles(fullPath));
2582
2656
  } else {
@@ -2591,7 +2665,7 @@ async function listAllFiles(dir) {
2591
2665
  // src/commands/eval/runner.ts
2592
2666
  var exec2 = promisify2(execFile2);
2593
2667
  async function runScenario(scenario, options) {
2594
- const sandboxDir = join10(tmpdir2(), `claude-eval-${randomUUID()}`);
2668
+ const sandboxDir = join11(tmpdir2(), `claude-eval-${randomUUID()}`);
2595
2669
  try {
2596
2670
  await setupSandbox(sandboxDir, scenario, options.projectRoot);
2597
2671
  const transcript = await runClaudeInSandbox(sandboxDir, scenario.prompt, options.timeout, options.model);
@@ -2617,14 +2691,14 @@ async function runScenarioWithRetries(scenario, options) {
2617
2691
  async function setupSandbox(sandboxDir, scenario, projectRoot) {
2618
2692
  await mkdir2(sandboxDir, { recursive: true });
2619
2693
  for (const file of scenario.setup.files) {
2620
- const filePath = join10(sandboxDir, file.path);
2694
+ const filePath = join11(sandboxDir, file.path);
2621
2695
  await mkdir2(dirname3(filePath), { recursive: true });
2622
2696
  await writeFile2(filePath, file.content);
2623
2697
  }
2624
2698
  await copyProjectConfig(sandboxDir, projectRoot);
2625
2699
  if (scenario.setup.instructions) {
2626
2700
  await writeFile2(
2627
- join10(sandboxDir, "CLAUDE.md"),
2701
+ join11(sandboxDir, "CLAUDE.md"),
2628
2702
  `# Eval Scenario
2629
2703
 
2630
2704
  ${scenario.setup.instructions}
@@ -2645,20 +2719,20 @@ ${scenario.setup.instructions}
2645
2719
  ], { cwd: sandboxDir });
2646
2720
  }
2647
2721
  async function copyProjectConfig(sandboxDir, projectRoot) {
2648
- const claudeDir = join10(projectRoot, ".claude");
2649
- const sandboxClaudeDir = join10(sandboxDir, ".claude");
2650
- const settingsPath = join10(claudeDir, "settings.json");
2722
+ const claudeDir = join11(projectRoot, ".claude");
2723
+ const sandboxClaudeDir = join11(sandboxDir, ".claude");
2724
+ const settingsPath = join11(claudeDir, "settings.json");
2651
2725
  if (await fileExists(settingsPath)) {
2652
2726
  await mkdir2(sandboxClaudeDir, { recursive: true });
2653
- await cp(settingsPath, join10(sandboxClaudeDir, "settings.json"));
2727
+ await cp(settingsPath, join11(sandboxClaudeDir, "settings.json"));
2654
2728
  }
2655
- const rulesDir = join10(claudeDir, "rules");
2729
+ const rulesDir = join11(claudeDir, "rules");
2656
2730
  if (await fileExists(rulesDir)) {
2657
- await cp(rulesDir, join10(sandboxClaudeDir, "rules"), { recursive: true });
2731
+ await cp(rulesDir, join11(sandboxClaudeDir, "rules"), { recursive: true });
2658
2732
  }
2659
- const ignorePath = join10(projectRoot, ".claudeignore");
2733
+ const ignorePath = join11(projectRoot, ".claudeignore");
2660
2734
  if (await fileExists(ignorePath)) {
2661
- await cp(ignorePath, join10(sandboxDir, ".claudeignore"));
2735
+ await cp(ignorePath, join11(sandboxDir, ".claudeignore"));
2662
2736
  }
2663
2737
  }
2664
2738
  async function runClaudeInSandbox(cwd, prompt, timeout, model) {
@@ -2958,10 +3032,10 @@ async function saveEvalReport(results, projectRoot, suite, model) {
2958
3032
  lines.push("");
2959
3033
  }
2960
3034
  }
2961
- const evalDir = join11(projectRoot, ".claude", "eval");
3035
+ const evalDir = join12(projectRoot, ".claude", "eval");
2962
3036
  await mkdir3(evalDir, { recursive: true });
2963
3037
  const filename = `eval-${suite ?? "all"}-${timestamp}.md`;
2964
- await writeFile3(join11(evalDir, filename), lines.join("\n"));
3038
+ await writeFile3(join12(evalDir, filename), lines.join("\n"));
2965
3039
  log.success(`Report saved to .claude/eval/${filename}`);
2966
3040
  }
2967
3041
  async function checkClaudeCli() {
@@ -2978,7 +3052,7 @@ async function checkClaudeCli() {
2978
3052
 
2979
3053
  // src/commands/memory/index.ts
2980
3054
  import { readFileSync as readFileSync2 } from "fs";
2981
- import { join as join12 } from "path";
3055
+ import { join as join13 } from "path";
2982
3056
  import { Command as Command4 } from "commander";
2983
3057
  import { confirm as confirm2 } from "@inquirer/prompts";
2984
3058
  async function handleSyncErrors(fn) {
@@ -2991,7 +3065,7 @@ async function handleSyncErrors(fn) {
2991
3065
  }
2992
3066
  function isMemoryInstalled() {
2993
3067
  const cwd = process.cwd();
2994
- const hookPresent = hasMemoryHook(join12(cwd, ".claude", "settings.json")) || hasMemoryHook(join12(cwd, ".claude", "settings.local.json"));
3068
+ const hookPresent = hasMemoryHook(join13(cwd, ".claude", "settings.json")) || hasMemoryHook(join13(cwd, ".claude", "settings.local.json"));
2995
3069
  if (!hookPresent) return false;
2996
3070
  return isMemoryMcpRegistered(cwd);
2997
3071
  }
@@ -3022,9 +3096,9 @@ function createMemoryCommand() {
3022
3096
  );
3023
3097
  return;
3024
3098
  }
3025
- const { requireMemoryDeps } = await import("./require-deps-WDMHDGBN.js");
3099
+ const { requireMemoryDeps } = await import("./require-deps-AEDO5YRM.js");
3026
3100
  await requireMemoryDeps();
3027
- const { startTui } = await import("./tui-HVJNLRY2.js");
3101
+ const { startTui } = await import("./tui-3KITZCNS.js");
3028
3102
  await startTui();
3029
3103
  return;
3030
3104
  }
@@ -3036,7 +3110,7 @@ function createMemoryCommand() {
3036
3110
  process.exitCode = 1;
3037
3111
  return;
3038
3112
  }
3039
- const { detectExistingSetup } = await import("./install-D32PV7SF.js");
3113
+ const { detectExistingSetup } = await import("./install-543ZKMXX.js");
3040
3114
  const existing = detectExistingSetup(process.cwd());
3041
3115
  const mcpMissing = existing !== null && !isMemoryMcpRegistered(process.cwd());
3042
3116
  if (existing) {
@@ -3073,12 +3147,12 @@ function createMemoryCommand() {
3073
3147
  log.info("Skipped.");
3074
3148
  return;
3075
3149
  }
3076
- const { runInstall } = await import("./install-D32PV7SF.js");
3150
+ const { runInstall } = await import("./install-543ZKMXX.js");
3077
3151
  await runInstall({});
3078
3152
  } else {
3079
- const { requireMemoryDeps } = await import("./require-deps-WDMHDGBN.js");
3153
+ const { requireMemoryDeps } = await import("./require-deps-AEDO5YRM.js");
3080
3154
  await requireMemoryDeps();
3081
- const { runStats } = await import("./stats-77BYLKYP.js");
3155
+ const { runStats } = await import("./stats-63L7C24W.js");
3082
3156
  await runStats({});
3083
3157
  }
3084
3158
  });
@@ -3090,7 +3164,7 @@ function createMemoryCommand() {
3090
3164
  "Non-interactive: accept defaults (shared placement)"
3091
3165
  ).action(async (opts) => {
3092
3166
  try {
3093
- const { runInstall } = await import("./install-D32PV7SF.js");
3167
+ const { runInstall } = await import("./install-543ZKMXX.js");
3094
3168
  await runInstall({
3095
3169
  ...opts.dbPath ? { dbPath: opts.dbPath } : {},
3096
3170
  yes: opts.yes === true
@@ -3103,21 +3177,21 @@ function createMemoryCommand() {
3103
3177
  );
3104
3178
  memory.addCommand(
3105
3179
  new Command4("stats").description("Show memory counts, health, and injection stats").option("--json", "JSON output").action(async (opts) => {
3106
- const { requireMemoryDeps } = await import("./require-deps-WDMHDGBN.js");
3180
+ const { requireMemoryDeps } = await import("./require-deps-AEDO5YRM.js");
3107
3181
  await requireMemoryDeps();
3108
- const { runStats } = await import("./stats-77BYLKYP.js");
3182
+ const { runStats } = await import("./stats-63L7C24W.js");
3109
3183
  await runStats(opts);
3110
3184
  })
3111
3185
  );
3112
3186
  memory.addCommand(
3113
3187
  new Command4("doctor").description("Diagnose the memory setup (DB, hooks, MCP registration)").option("--json", "JSON output").action(async (opts) => {
3114
- const { runMemoryDoctor } = await import("./doctor-DCHFJ3XV.js");
3188
+ const { runMemoryDoctor } = await import("./doctor-EKGJ2YAO.js");
3115
3189
  await runMemoryDoctor(opts);
3116
3190
  })
3117
3191
  );
3118
3192
  memory.addCommand(
3119
3193
  new Command4("context").description("Load session context (hook handler)").option("--json", "JSON output").action(async (opts) => {
3120
- const { runContext } = await import("./context-YIPO4LBS.js");
3194
+ const { runContext } = await import("./context-3GHG7KW6.js");
3121
3195
  await runContext(opts);
3122
3196
  }).helpCommand(false),
3123
3197
  { hidden: true }
@@ -3132,7 +3206,7 @@ function createMemoryCommand() {
3132
3206
  memory.addCommand(
3133
3207
  new Command4("push").description("Push current project's memories to GitHub Gist").option("--all", "Push all projects").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
3134
3208
  await handleSyncErrors(async () => {
3135
- const { runPush } = await import("./push-U4IVTFOU.js");
3209
+ const { runPush } = await import("./push-JXCWX4NY.js");
3136
3210
  await runPush(opts);
3137
3211
  });
3138
3212
  })
@@ -3143,7 +3217,7 @@ function createMemoryCommand() {
3143
3217
  "Non-interactive (accepted for symmetry with push; pull never prompts)"
3144
3218
  ).action(async (opts) => {
3145
3219
  await handleSyncErrors(async () => {
3146
- const { runPull } = await import("./pull-YUQTDRUP.js");
3220
+ const { runPull } = await import("./pull-ULSZEVCR.js");
3147
3221
  await runPull(opts);
3148
3222
  });
3149
3223
  })
@@ -3152,14 +3226,14 @@ function createMemoryCommand() {
3152
3226
  "Sync memories with the gist (pull + push); subcommands manage sync state"
3153
3227
  ).option("--all", "Sync all projects").option("-y, --yes", "Skip confirmation prompt").action(async (opts) => {
3154
3228
  await handleSyncErrors(async () => {
3155
- const { runSync } = await import("./sync-DTCWK2CY.js");
3229
+ const { runSync } = await import("./sync-QTJ6BXQ4.js");
3156
3230
  await runSync(opts);
3157
3231
  });
3158
3232
  });
3159
3233
  sync.addCommand(
3160
3234
  new Command4("status").description("Show local vs remote memory counts per project").action(async () => {
3161
3235
  await handleSyncErrors(async () => {
3162
- const { runSyncStatus } = await import("./sync-status-2V2RCYZO.js");
3236
+ const { runSyncStatus } = await import("./sync-status-EAX527SC.js");
3163
3237
  await runSyncStatus();
3164
3238
  });
3165
3239
  })
@@ -3167,7 +3241,7 @@ function createMemoryCommand() {
3167
3241
  sync.addCommand(
3168
3242
  new Command4("clean").description("Remove a project from the sync gist").argument("<project>", "Project slug to remove").option("-y, --yes", "Skip confirmation prompt").action(async (project, opts) => {
3169
3243
  await handleSyncErrors(async () => {
3170
- const { runSyncClean } = await import("./sync-clean-ACZCB3NZ.js");
3244
+ const { runSyncClean } = await import("./sync-clean-OJEK4XH4.js");
3171
3245
  await runSyncClean(project, opts);
3172
3246
  });
3173
3247
  })
@@ -3178,7 +3252,7 @@ function createMemoryCommand() {
3178
3252
 
3179
3253
  // src/cli.ts
3180
3254
  var program = new Command5().name("claude-launchpad").description("Score your Claude Code config, fix the gaps, prove Claude follows your rules.").version("1.14.0", "-v, --version").action(async () => {
3181
- const hasConfig = await fileExists(join13(process.cwd(), "CLAUDE.md")) || await fileExists(join13(process.cwd(), ".claude", "settings.json"));
3255
+ const hasConfig = await fileExists(join14(process.cwd(), "CLAUDE.md")) || await fileExists(join14(process.cwd(), ".claude", "settings.json"));
3182
3256
  if (hasConfig) {
3183
3257
  await program.commands.find((c) => c.name() === "doctor")?.parseAsync([], { from: "user" });
3184
3258
  } else {