@launchsecure/launch-kit 0.0.30 → 0.0.32

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 (106) hide show
  1. package/dist/beacon/beacon.mjs +1027 -929
  2. package/dist/beacon/beacon.mjs.map +1 -1
  3. package/dist/beacon/beacon.umd.js +9 -9
  4. package/dist/beacon/beacon.umd.js.map +1 -1
  5. package/dist/beacon/types/internal/pick-mode-overlay.d.ts.map +1 -1
  6. package/dist/beacon/types/internal/picker.d.ts.map +1 -1
  7. package/dist/beacon/types/internal/pin-popover.d.ts.map +1 -1
  8. package/dist/beacon/types/internal/screenshot.d.ts +19 -1
  9. package/dist/beacon/types/internal/screenshot.d.ts.map +1 -1
  10. package/dist/beacon/types/internal/selector.d.ts.map +1 -1
  11. package/dist/beacon/types/plugins/domEle.d.ts.map +1 -1
  12. package/dist/chart-client/assets/{index-CJ4mgRRF.css → index-CDIhdgWg.css} +1 -1
  13. package/dist/chart-client/index.html +2 -2
  14. package/dist/client/assets/{index-DI5qSR_w.css → index-CfW4n40I.css} +1 -1
  15. package/dist/client/index.html +2 -2
  16. package/dist/council-client/assets/{index-C_-vAM9L.css → index-CZim6x1u.css} +1 -1
  17. package/dist/council-client/index.html +2 -2
  18. package/dist/deck-client/assets/{_baseUniq-DCt2IMRR.js → _baseUniq-C7GsHvgg.js} +1 -1
  19. package/dist/deck-client/assets/{arc-h-ifqmNR.js → arc-CSrZRINY.js} +1 -1
  20. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-C9dITSPv.js → architectureDiagram-Q4EWVU46-zoB-G17J.js} +1 -1
  21. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-BHuJT34t.js → blockDiagram-DXYQGD6D-BRjjtYH6.js} +1 -1
  22. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CpvMGtDG.js → c4Diagram-AHTNJAMY-C3D3sd2U.js} +1 -1
  23. package/dist/deck-client/assets/channel-8ReQnQfH.js +1 -0
  24. package/dist/deck-client/assets/{chunk-4BX2VUAB-B6md1VIm.js → chunk-4BX2VUAB-DhpDMOPO.js} +1 -1
  25. package/dist/deck-client/assets/{chunk-4TB4RGXK-BmEnX8ik.js → chunk-4TB4RGXK-BIRgPXRl.js} +1 -1
  26. package/dist/deck-client/assets/{chunk-55IACEB6-BZPUyZAZ.js → chunk-55IACEB6-BF24dwDZ.js} +1 -1
  27. package/dist/deck-client/assets/{chunk-EDXVE4YY-BWwNUK-l.js → chunk-EDXVE4YY-CW75Y61B.js} +1 -1
  28. package/dist/deck-client/assets/{chunk-FMBD7UC4-o7gSppGI.js → chunk-FMBD7UC4-B5-oyL79.js} +1 -1
  29. package/dist/deck-client/assets/{chunk-OYMX7WX6-C4KoTL5p.js → chunk-OYMX7WX6-BB2bHe_Q.js} +1 -1
  30. package/dist/deck-client/assets/{chunk-QZHKN3VN-jkf68sDs.js → chunk-QZHKN3VN-D80eZO4B.js} +1 -1
  31. package/dist/deck-client/assets/{chunk-YZCP3GAM-Cd4yBE7o.js → chunk-YZCP3GAM-Dz9787p_.js} +1 -1
  32. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-cRxTeGkK.js +1 -0
  33. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-cRxTeGkK.js +1 -0
  34. package/dist/deck-client/assets/clone-LSHZ3K6R.js +1 -0
  35. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-DeGFUgAV.js → cose-bilkent-S5V4N54A-MQjiZLcL.js} +1 -1
  36. package/dist/deck-client/assets/{dagre-KV5264BT-ekcYJuUV.js → dagre-KV5264BT-DG4EcLpJ.js} +1 -1
  37. package/dist/deck-client/assets/{diagram-5BDNPKRD-YHPk4rV2.js → diagram-5BDNPKRD-1n7hM3Gc.js} +1 -1
  38. package/dist/deck-client/assets/{diagram-G4DWMVQ6-DM-JCd_B.js → diagram-G4DWMVQ6-CYMarncV.js} +1 -1
  39. package/dist/deck-client/assets/{diagram-MMDJMWI5-l5FK1ybk.js → diagram-MMDJMWI5-DSisoipe.js} +1 -1
  40. package/dist/deck-client/assets/{diagram-TYMM5635-CIN4_1-j.js → diagram-TYMM5635-Btnq49OJ.js} +1 -1
  41. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-MyinSkEl.js → erDiagram-SMLLAGMA-Cu2Hb_Tz.js} +1 -1
  42. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Dk8nn42x.js → flowDiagram-DWJPFMVM-CGJzUzsO.js} +1 -1
  43. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-BU1ihicu.js → ganttDiagram-T4ZO3ILL-D9sqGUBT.js} +1 -1
  44. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-BjsTL13C.js → gitGraphDiagram-UUTBAWPF-C0QwX2od.js} +1 -1
  45. package/dist/deck-client/assets/{graph-DJmh-xi7.js → graph-CcBjOQCl.js} +1 -1
  46. package/dist/deck-client/assets/index-0arwoc0z.js +1195 -0
  47. package/dist/deck-client/assets/index-6sdqbm2o.js +2 -0
  48. package/dist/deck-client/assets/{index-DsIZ3LqL.css → index-BlTlhxFW.css} +1 -1
  49. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-Dxvy_RB4.js → infoDiagram-42DDH7IO-DTimhhhS.js} +1 -1
  50. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DPOaNF1l.js → ishikawaDiagram-UXIWVN3A-DxOxg_B4.js} +1 -1
  51. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-DMew3K5c.js → journeyDiagram-VCZTEJTY-Bpq0qa4j.js} +1 -1
  52. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-csciJFuk.js → kanban-definition-6JOO6SKY-aTIrpcVO.js} +1 -1
  53. package/dist/deck-client/assets/{layout-Dg4yyms2.js → layout-DqglLR2E.js} +1 -1
  54. package/dist/deck-client/assets/{linear-BA3zU6gq.js → linear-D5GxehPc.js} +1 -1
  55. package/dist/deck-client/assets/{min-lz-Ird-p.js → min-DXLfSREq.js} +1 -1
  56. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-CCEN8OQV.js → mindmap-definition-QFDTVHPH-mO5Vys7I.js} +1 -1
  57. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DM6n1HY7.js → pieDiagram-DEJITSTG-Dm0gzdAr.js} +1 -1
  58. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-_ULoR66n.js → quadrantDiagram-34T5L4WZ-Daq7j3qD.js} +1 -1
  59. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-BuwJs7Tn.js → requirementDiagram-MS252O5E-CmwV95um.js} +1 -1
  60. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BEsuzkW4.js → sankeyDiagram-XADWPNL6-BOYl3Nkf.js} +1 -1
  61. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-CP2H0YWf.js → sequenceDiagram-FGHM5R23-BuUjhIcW.js} +1 -1
  62. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-B5Gw_NNL.js → stateDiagram-FHFEXIEX-LUZ_uwio.js} +1 -1
  63. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CnnRwE5D.js +1 -0
  64. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-DsoYydQa.js → timeline-definition-GMOUNBTQ-CDUxCCAW.js} +1 -1
  65. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-Dz8JT_ob.js → vennDiagram-DHZGUBPP-BRb24Tf7.js} +1 -1
  66. package/dist/deck-client/assets/{wardley-RL74JXVD-DGHQ_Ijv.js → wardley-RL74JXVD-B0BYyVBY.js} +1 -1
  67. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-DN1LJMB1.js → wardleyDiagram-NUSXRM2D-BLGlYrQz.js} +1 -1
  68. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-nb0oSfrQ.js → xychartDiagram-5P7HB3ND-De31MSnk.js} +1 -1
  69. package/dist/deck-client/index.html +2 -2
  70. package/dist/server/cli.js +666 -12
  71. package/dist/server/council-entry.js +0 -0
  72. package/dist/server/deck-mcp-entry.js +224 -61
  73. package/dist/server/deck-serve.js +195 -41
  74. package/dist/server/fb-wizard.js +0 -0
  75. package/dist/server/graph-mcp-entry.js +666 -12
  76. package/dist/server/init-entry.js +231 -82
  77. package/package.json +23 -21
  78. package/scaffolds/ls-marketplace/plugins/kit/skills/analyse/SKILL.md +180 -0
  79. package/scaffolds/ls-marketplace/plugins/kit/skills/{blast-radius.md → blast-radius/SKILL.md} +28 -12
  80. package/scaffolds/ls-marketplace/plugins/kit/skills/{debug.md → debug/SKILL.md} +2 -9
  81. package/scaffolds/ls-marketplace/plugins/kit/skills/diagram/SKILL.md +174 -0
  82. package/scaffolds/ls-marketplace/plugins/kit/skills/{prototype.md → prototype/SKILL.md} +21 -1
  83. package/scaffolds/ls-marketplace/plugins/kit/skills/recovery/SKILL.md +95 -0
  84. package/scaffolds/ls-marketplace/plugins/kit/skills/{wireframe.md → wireframe/SKILL.md} +21 -1
  85. package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
  86. package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
  87. package/dist/deck-client/assets/channel-2PZVMiXf.js +0 -1
  88. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-Bt8xBAof.js +0 -1
  89. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-Bt8xBAof.js +0 -1
  90. package/dist/deck-client/assets/clone-BHQryoDl.js +0 -1
  91. package/dist/deck-client/assets/index-KsShfCV-.js +0 -476
  92. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-4T4wMDXr.js +0 -1
  93. package/scaffolds/ls-marketplace/plugins/kit/skills/diagram.md +0 -134
  94. package/scaffolds/ls-marketplace/plugins/kit/skills/recall.md +0 -83
  95. /package/dist/chart-client/assets/{index-Ccy-DpI-.js → index-B__ARB8k.js} +0 -0
  96. /package/dist/client/assets/{index-Dp0_okva.js → index-h8kMzVtG.js} +0 -0
  97. /package/dist/council-client/assets/{index-Dt4zWKSj.js → index-CWaDcsFR.js} +0 -0
  98. /package/scaffolds/ls-marketplace/plugins/kit/skills/{beacon-array.md → beacon-array/SKILL.md} +0 -0
  99. /package/scaffolds/ls-marketplace/plugins/kit/skills/{beacon-clear.md → beacon-clear/SKILL.md} +0 -0
  100. /package/scaffolds/ls-marketplace/plugins/kit/skills/{beacon-pulse.md → beacon-pulse/SKILL.md} +0 -0
  101. /package/scaffolds/ls-marketplace/plugins/kit/skills/{beacon-scan.md → beacon-scan/SKILL.md} +0 -0
  102. /package/scaffolds/ls-marketplace/plugins/kit/skills/{brief.md → brief/SKILL.md} +0 -0
  103. /package/scaffolds/ls-marketplace/plugins/kit/skills/{course.md → course/SKILL.md} +0 -0
  104. /package/scaffolds/ls-marketplace/plugins/kit/skills/{deploy-check.md → deploy-check/SKILL.md} +0 -0
  105. /package/scaffolds/ls-marketplace/plugins/kit/skills/{orbit.md → orbit/SKILL.md} +0 -0
  106. /package/scaffolds/ls-marketplace/plugins/kit/skills/{show-mcp-status.md → show-mcp-status/SKILL.md} +0 -0
@@ -295,6 +295,50 @@ function recoverCred(targetDir, opts) {
295
295
  init_statusline_install();
296
296
  var DEFAULT_SERVER_URL = "https://launchsecure-v2.vercel.app";
297
297
  var ONBOARD_SCRIPT_NAME = "onboard";
298
+ var TTY = process.stdout.isTTY === true && process.env.NO_COLOR !== "1";
299
+ var c = {
300
+ dim: (s) => TTY ? `\x1B[2m${s}\x1B[0m` : s,
301
+ bold: (s) => TTY ? `\x1B[1m${s}\x1B[0m` : s,
302
+ cyan: (s) => TTY ? `\x1B[36m${s}\x1B[0m` : s,
303
+ green: (s) => TTY ? `\x1B[32m${s}\x1B[0m` : s,
304
+ yellow: (s) => TTY ? `\x1B[33m${s}\x1B[0m` : s,
305
+ red: (s) => TTY ? `\x1B[31m${s}\x1B[0m` : s
306
+ };
307
+ var PHASE_NAME_COL = 16;
308
+ var HEADER_WIDTH = 64;
309
+ function header(title, kv) {
310
+ if (VERBOSE) return;
311
+ const dashes = "\u2500".repeat(Math.max(3, HEADER_WIDTH - title.length - 5));
312
+ console.log("");
313
+ console.log(c.cyan(`\u2500\u2500\u2500 ${c.bold(title)} ${dashes}`));
314
+ if (kv.length > 0) {
315
+ const labelWidth = Math.max(...kv.map(([k]) => k.length));
316
+ for (const [k, v] of kv) console.log(` ${c.dim(k.padEnd(labelWidth))} ${v}`);
317
+ }
318
+ console.log("");
319
+ }
320
+ function phase(name, result) {
321
+ if (VERBOSE) return;
322
+ const mark = result.status === "ok" ? c.green("\u2713") : result.status === "in-sync" ? c.dim("\xB7") : result.status === "skipped" ? c.dim("\u2212") : c.yellow("\u26A0");
323
+ const summary = result.status === "in-sync" || result.status === "skipped" ? c.dim(result.summary) : result.summary;
324
+ const label = name.padEnd(PHASE_NAME_COL);
325
+ console.log(` ${result.status === "warn" ? c.yellow(label) : label} ${mark} ${summary}`);
326
+ }
327
+ function section(title) {
328
+ if (VERBOSE) return;
329
+ console.log("");
330
+ console.log(` ${c.dim("\u2500 " + title + " \u2500")}`);
331
+ }
332
+ function footer(msg, hints = []) {
333
+ if (VERBOSE) return;
334
+ console.log("");
335
+ console.log(` ${c.bold(msg)}`);
336
+ for (const h of hints) console.log(` ${c.dim(h)}`);
337
+ console.log("");
338
+ }
339
+ function warn(msg) {
340
+ console.log(` ${c.yellow("\u26A0")} ${msg}`);
341
+ }
298
342
  var LAUNCH_KIT_PKG = "@launchsecure/launch-kit";
299
343
  var LAUNCH_KIT_TOOLS_GUIDE_STATIC_HEAD = `
300
344
  Wired in Claude Code (.mcp.json):
@@ -317,24 +361,30 @@ var LAUNCH_KIT_TOOLS_GUIDE_STATIC_TAIL = `
317
361
  Open this repo in Claude Code; on first open you'll be prompted to install
318
362
  the "launch-secure" marketplace \u2014 accept to enable the commands above.
319
363
  `;
320
- function renderEntries(dir, kindLabel) {
364
+ function listEntries(dir, kind) {
365
+ if (kind === "commands") {
366
+ return fs4.readdirSync(dir).filter((f) => f.endsWith(".md")).sort().map((f) => ({ name: f.replace(/\.md$/, ""), file: path4.join(dir, f) }));
367
+ }
368
+ return fs4.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && fs4.existsSync(path4.join(dir, e.name, "SKILL.md"))).map((e) => e.name).sort().map((name) => ({ name, file: path4.join(dir, name, "SKILL.md") }));
369
+ }
370
+ function renderEntries(dir, kind) {
321
371
  if (!fs4.existsSync(dir)) return `
322
- LS slash ${kindLabel}: (scaffold dir not bundled \u2014 this is a packaging bug)
372
+ LS slash ${kind}: (scaffold dir not bundled \u2014 this is a packaging bug)
323
373
  `;
324
- const files = fs4.readdirSync(dir).filter((f) => f.endsWith(".md")).sort();
325
- if (files.length === 0) return `
326
- LS slash ${kindLabel}: (none defined)
374
+ const entries = listEntries(dir, kind);
375
+ if (entries.length === 0) return `
376
+ LS slash ${kind}: (none defined)
327
377
  `;
328
- const names = files.map((file) => `/${PLUGIN_ID}:${file.replace(/\.md$/, "")}`);
378
+ const names = entries.map((e) => `/${PLUGIN_ID}:${e.name}`);
329
379
  const colWidth = Math.max(26, ...names.map((n) => n.length + 2));
330
- const lines = files.map((file, i) => {
331
- const text = fs4.readFileSync(path4.join(dir, file), "utf-8");
380
+ const lines = entries.map((entry, i) => {
381
+ const text = fs4.readFileSync(entry.file, "utf-8");
332
382
  const fmMatch = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
333
383
  const desc = fmMatch?.[1].match(/^description:\s*(.+)$/m)?.[1]?.trim() ?? "";
334
384
  return ` ${names[i].padEnd(colWidth)} \u2014 ${desc}`;
335
385
  });
336
386
  return `
337
- LS slash ${kindLabel} (run inside Claude Code in this project):
387
+ LS slash ${kind} (run inside Claude Code in this project):
338
388
  ${lines.join("\n")}
339
389
  `;
340
390
  }
@@ -363,7 +413,10 @@ var KNOWN_BOOL_FLAGS = /* @__PURE__ */ new Set([
363
413
  "--refresh-scaffolds",
364
414
  "--quiet",
365
415
  "--force",
366
- "--dry-run"
416
+ "--dry-run",
417
+ "--verbose",
418
+ "--guide",
419
+ "--no-guide"
367
420
  ]);
368
421
  var KNOWN_KV_KEYS = /* @__PURE__ */ new Set(["token", "org", "project", "url", "dir", "course"]);
369
422
  function parseArgs(argv) {
@@ -384,6 +437,8 @@ function parseArgs(argv) {
384
437
  quiet: false,
385
438
  force: false,
386
439
  dryRun: false,
440
+ verbose: false,
441
+ guide: null,
387
442
  help: false
388
443
  };
389
444
  const unknown = [];
@@ -434,6 +489,18 @@ function parseArgs(argv) {
434
489
  args.dryRun = true;
435
490
  continue;
436
491
  }
492
+ if (raw === "--verbose") {
493
+ args.verbose = true;
494
+ continue;
495
+ }
496
+ if (raw === "--guide") {
497
+ args.guide = true;
498
+ continue;
499
+ }
500
+ if (raw === "--no-guide") {
501
+ args.guide = false;
502
+ continue;
503
+ }
437
504
  const eq = raw.indexOf("=");
438
505
  if (raw.startsWith("--") && eq > 0) {
439
506
  const key = raw.slice(2, eq);
@@ -505,8 +572,15 @@ Options:
505
572
  --refresh-scaffolds Force-overwrite migrate-safety files (default is to
506
573
  preserve user edits). Use this to pull updates
507
574
  published to @launchsecure/launch-kit.
508
- --quiet Suppress the post-run tools guide.
575
+ --verbose Print the legacy per-line debug log instead of the
576
+ default compact phase summary. Useful when refresh
577
+ reports a warn-status phase and you want detail.
578
+ --guide Print the trailing tools guide (MCP table + every
579
+ /kit:* command). Off by default on refresh.
580
+ --quiet Suppress the tools guide and the next-steps hint.
581
+ Overrides --guide.
509
582
  --dry-run Preview every file write without making changes.
583
+ Implies --verbose.
510
584
  --help Show this help.
511
585
 
512
586
  Tip: prefix the command with @latest (\`launch-kit@latest refresh\`) to force
@@ -564,9 +638,17 @@ Options:
564
638
  user edits; use this to pull updates published to
565
639
  @launchsecure/launch-kit (e.g., a newer
566
640
  migrate-with-backup.sh).
567
- --quiet Suppress the post-run tools guide (the long block
568
- listing /kit:* commands and wired MCPs). Useful for
569
- idempotent re-runs in CI or scripts.
641
+ --verbose Print the legacy per-line debug log instead of the
642
+ default compact phase summary. Useful when a phase
643
+ reports a warn status and you want per-file detail.
644
+ --guide Print the trailing tools guide (MCP table + every
645
+ /kit:* command). On by default for init; pair with
646
+ --no-guide to suppress.
647
+ --no-guide Suppress the trailing tools guide (handy after the
648
+ first init, when you don't need the catalog again).
649
+ --quiet Suppress the post-run tools guide AND the next-steps
650
+ hint. Useful for idempotent re-runs in CI or scripts.
651
+ Overrides --guide.
570
652
  --force Skip the auto-delegate-to-refresh check. By default
571
653
  init detects an existing bootstrap (cred file +
572
654
  launch-secure MCP entry) and runs refresh instead.
@@ -617,11 +699,12 @@ function fail(msg) {
617
699
  console.error(`[launch-kit] \u2717 ${msg}`);
618
700
  process.exit(1);
619
701
  }
702
+ var VERBOSE = false;
620
703
  function info(msg) {
621
- console.log(`[launch-kit] ${msg}`);
704
+ if (VERBOSE) console.log(`[launch-kit] ${msg}`);
622
705
  }
623
706
  function ok(msg) {
624
- console.log(`[launch-kit] \u2713 ${msg}`);
707
+ if (VERBOSE) console.log(`[launch-kit] \u2713 ${msg}`);
625
708
  }
626
709
  var DRY_RUN = false;
627
710
  function dryNote(msg) {
@@ -679,7 +762,7 @@ function attemptProjectInfo(args) {
679
762
  },
680
763
  (res) => {
681
764
  const chunks = [];
682
- res.on("data", (c) => chunks.push(c));
765
+ res.on("data", (c2) => chunks.push(c2));
683
766
  res.on("end", () => {
684
767
  const text = Buffer.concat(chunks).toString("utf-8");
685
768
  if (res.statusCode === 401) {
@@ -930,13 +1013,15 @@ function mergeMcpFile(targetDir, launchKitEntries) {
930
1013
  }
931
1014
  }
932
1015
  if (DRY_RUN) {
933
- const action2 = hadExisting && existingServerCount > 0 ? "would merge into" : "would write";
934
- dryNote(`${action2} .mcp.json \u2014 overwriting [${overwrites.join(", ") || "none"}], adding [${additions.join(", ") || "none"}]`);
935
- return;
1016
+ const action = hadExisting && existingServerCount > 0 ? "would merge into" : "would write";
1017
+ dryNote(`${action} .mcp.json \u2014 overwriting [${overwrites.join(", ") || "none"}], adding [${additions.join(", ") || "none"}]`);
1018
+ return { status: "skipped", summary: "(dry-run)" };
936
1019
  }
937
1020
  fs4.writeFileSync(p, JSON.stringify(merged, null, 2) + "\n", "utf-8");
938
- const action = hadExisting && existingServerCount > 0 ? "merged into" : "wrote";
939
- ok(`${action} .mcp.json (${Object.keys(launchKitEntries).length} launch-kit entries)`);
1021
+ const verb = hadExisting && existingServerCount > 0 ? "merged" : "wrote";
1022
+ ok(`${verb === "merged" ? "merged into" : "wrote"} .mcp.json (${Object.keys(launchKitEntries).length} launch-kit entries)`);
1023
+ const total = Object.keys(launchKitEntries).length;
1024
+ return { status: "ok", summary: `${verb} ${total} entries` };
940
1025
  }
941
1026
  function detectPackageManager(repoDir) {
942
1027
  const pkgPath = path4.join(repoDir, "package.json");
@@ -1087,8 +1172,8 @@ function copyScaffoldDirAlways(srcDir, destDir, labelPrefix) {
1087
1172
  function scaffoldMigrateSafety(targetDir, refreshScaffolds = false) {
1088
1173
  const scaffoldsRoot = path4.resolve(__dirname, "..", "..", "scaffolds", "migrate-safety");
1089
1174
  if (!fs4.existsSync(scaffoldsRoot)) {
1090
- info(`\u26A0 migrate-safety scaffolds not found at ${scaffoldsRoot} \u2014 skipping (this is a packaging bug; main onboarding is unaffected)`);
1091
- return;
1175
+ warn(`migrate-safety scaffolds missing at ${scaffoldsRoot} \u2014 packaging bug; main onboarding unaffected`);
1176
+ return { status: "warn", summary: "scaffolds missing (packaging bug)" };
1092
1177
  }
1093
1178
  const files = [
1094
1179
  {
@@ -1108,9 +1193,33 @@ function scaffoldMigrateSafety(targetDir, refreshScaffolds = false) {
1108
1193
  }
1109
1194
  ];
1110
1195
  info(`scaffolding migrate-safety (pg_dump wrapper + GHA backup workflow + runbook)${refreshScaffolds ? " \u2014 --refresh-scaffolds active" : ""} \u2026`);
1111
- for (const f of files) copyScaffoldDriftAware(f.src, f.dest, f.label, refreshScaffolds);
1196
+ const counts = { wrote: 0, inSync: 0, drifted: 0, refreshed: 0, missing: 0 };
1197
+ for (const f of files) {
1198
+ const r = copyScaffoldDriftAware(f.src, f.dest, f.label, refreshScaffolds);
1199
+ if (r === "wrote") counts.wrote++;
1200
+ else if (r === "in-sync") counts.inSync++;
1201
+ else if (r === "drifted-preserved") counts.drifted++;
1202
+ else if (r === "drifted-refreshed") counts.refreshed++;
1203
+ else counts.missing++;
1204
+ }
1112
1205
  ensureGitignoreLine(targetDir, ".backups/");
1113
1206
  ok("migrate-safety ready \u2014 see docs/migrations-runbook.md for db:migrate wiring + PROD_DATABASE_URL secret setup");
1207
+ return summarizeFileCounts(counts);
1208
+ }
1209
+ function summarizeFileCounts(counts) {
1210
+ const total = counts.wrote + counts.inSync + counts.drifted + counts.refreshed + counts.missing;
1211
+ const parts = [];
1212
+ if (counts.wrote) parts.push(`${counts.wrote} written`);
1213
+ if (counts.refreshed) parts.push(`${counts.refreshed} refreshed`);
1214
+ if (counts.drifted) parts.push(`${counts.drifted} drifted (preserved \u2014 pass --refresh-scaffolds to update)`);
1215
+ if (counts.inSync && (counts.wrote || counts.refreshed || counts.drifted)) parts.push(`${counts.inSync} in sync`);
1216
+ if (counts.missing) parts.push(`${counts.missing} missing scaffold src`);
1217
+ if (parts.length === 0) parts.push(`in sync (${total} file${total === 1 ? "" : "s"})`);
1218
+ else if (!counts.wrote && !counts.refreshed && !counts.drifted && counts.inSync === total) {
1219
+ return { status: "in-sync", summary: `in sync (${total} file${total === 1 ? "" : "s"})` };
1220
+ }
1221
+ const status = counts.drifted || counts.missing ? "warn" : counts.wrote || counts.refreshed ? "ok" : "in-sync";
1222
+ return { status, summary: parts.join(", ") };
1114
1223
  }
1115
1224
  function hashFile(p) {
1116
1225
  try {
@@ -1180,21 +1289,22 @@ function isDogfoodMarketplace(targetDir) {
1180
1289
  function scaffoldLsMarketplace(targetDir) {
1181
1290
  const scaffoldsRoot = path4.resolve(__dirname, "..", "..", "scaffolds", "ls-marketplace");
1182
1291
  if (!fs4.existsSync(scaffoldsRoot)) {
1183
- info(`\u26A0 ls-marketplace scaffolds not found at ${scaffoldsRoot} \u2014 skipping (this is a packaging bug; main onboarding is unaffected)`);
1184
- return;
1292
+ warn(`ls-marketplace scaffolds missing at ${scaffoldsRoot} \u2014 packaging bug`);
1293
+ return { status: "warn", summary: "scaffolds missing (packaging bug)" };
1185
1294
  }
1186
1295
  const dogfood = isDogfoodMarketplace(targetDir);
1187
1296
  if (dogfood.isDogfood) {
1188
1297
  info(`dogfood marketplace pointer detected (${dogfood.existingPath}) \u2014 skipping copy, only refreshing enabledPlugins`);
1189
1298
  wireLsSettings(targetDir);
1190
1299
  ok(`launch-secure marketplace (dogfood) \u2014 Claude Code loads commands from ${dogfood.existingPath}`);
1191
- return;
1300
+ return { status: "ok", summary: `dogfood pointer (${dogfood.existingPath})` };
1192
1301
  }
1193
1302
  const marketplaceRoot = path4.join(targetDir, ".claude", "marketplace");
1194
1303
  info("scaffolding launch-secure marketplace (Claude Code /kit: namespace \u2014 refreshes every /kit:* command found in the scaffold) \u2026");
1195
1304
  copyScaffoldDirAlways(scaffoldsRoot, marketplaceRoot, ".claude/marketplace");
1196
1305
  wireLsSettings(targetDir);
1197
1306
  ok(`launch-secure marketplace ready \u2014 open this repo in Claude Code, approve the "${MARKETPLACE_ID}" marketplace prompt, then try /kit:activate-beacon, /kit:standup, or /kit:show-mcp-status`);
1307
+ return { status: "ok", summary: "marketplace tree + settings refreshed" };
1198
1308
  }
1199
1309
  function wireLsSettings(targetDir) {
1200
1310
  const p = path4.join(targetDir, ".claude", "settings.json");
@@ -1241,13 +1351,14 @@ var RECALL_HOOK_COMMAND = 'bash "${CLAUDE_PROJECT_DIR:-$PWD}/scripts/ensure-reca
1241
1351
  function scaffoldRecallHook(targetDir) {
1242
1352
  const scaffoldsRoot = path4.resolve(__dirname, "..", "..", "scaffolds", "recall-hook");
1243
1353
  if (!fs4.existsSync(scaffoldsRoot)) {
1244
- info(`\u26A0 recall-hook scaffolds not found at ${scaffoldsRoot} \u2014 skipping (this is a packaging bug; main onboarding is unaffected)`);
1245
- return;
1354
+ warn(`recall-hook scaffolds missing at ${scaffoldsRoot} \u2014 packaging bug`);
1355
+ return { status: "warn", summary: "scaffolds missing (packaging bug)" };
1246
1356
  }
1247
1357
  info("scaffolding recall-hook (SessionStart watcher-respawn hook + ensure-recall.sh) \u2026");
1248
1358
  copyScaffoldDirAlways(scaffoldsRoot, targetDir, "");
1249
- wireRecallHook(targetDir);
1359
+ const wired = wireRecallHook(targetDir);
1250
1360
  ok("recall-hook ready \u2014 opens with Claude Code will respawn the launch-recall watcher if it died between sessions");
1361
+ return wired ? { status: "ok", summary: "ensure-recall.sh refreshed + SessionStart hook appended" } : { status: "ok", summary: "ensure-recall.sh refreshed (hook already wired)" };
1251
1362
  }
1252
1363
  function wireRecallHook(targetDir) {
1253
1364
  const p = path4.join(targetDir, ".claude", "settings.json");
@@ -1267,7 +1378,7 @@ function wireRecallHook(targetDir) {
1267
1378
  );
1268
1379
  if (alreadyWired) {
1269
1380
  info(".claude/settings.json SessionStart hook already references ensure-recall.sh \u2014 leaving alone");
1270
- return;
1381
+ return false;
1271
1382
  }
1272
1383
  const newGroup = {
1273
1384
  hooks: [{ type: "command", command: RECALL_HOOK_COMMAND }]
@@ -1281,23 +1392,28 @@ function wireRecallHook(targetDir) {
1281
1392
  };
1282
1393
  if (DRY_RUN) {
1283
1394
  dryNote(`would append SessionStart hook to .claude/settings.json (bash scripts/ensure-recall.sh; preserves every other key + existing hooks)`);
1284
- return;
1395
+ return true;
1285
1396
  }
1286
1397
  fs4.mkdirSync(path4.dirname(p), { recursive: true });
1287
1398
  fs4.writeFileSync(p, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1288
1399
  ok(`appended SessionStart hook to .claude/settings.json (bash scripts/ensure-recall.sh)`);
1400
+ return true;
1289
1401
  }
1290
1402
  function tryActivateStatusline() {
1291
1403
  if (DRY_RUN) {
1292
1404
  dryNote(`would wrap ~/.claude/settings.json statusLine.command with launch-kit's MCP chip wrapper (skips silently if no statusline configured)`);
1293
- return;
1405
+ return { status: "skipped", summary: "(dry-run)" };
1294
1406
  }
1295
1407
  const res = activateStatusline();
1296
1408
  if (res.ok && res.outcome === "activated") {
1297
1409
  ok(`statusline wrapped \u2014 MCP chips will render alongside your existing statusline next session`);
1298
- } else if (res.ok && res.outcome === "refreshed") {
1410
+ return { status: "ok", summary: "wrapped \u2014 MCP chips render next session" };
1411
+ }
1412
+ if (res.ok && res.outcome === "refreshed") {
1299
1413
  info(`statusline already wrapped \u2014 refreshed chip scripts`);
1414
+ return { status: "ok", summary: "chip scripts refreshed" };
1300
1415
  }
1416
+ return null;
1301
1417
  }
1302
1418
  async function main() {
1303
1419
  const subcommand = process.argv[2];
@@ -1341,11 +1457,12 @@ async function main() {
1341
1457
  fail(`Unknown subcommand "${subcommand}". Supported: init, refresh, statusline. Run with --help for usage.`);
1342
1458
  }
1343
1459
  DRY_RUN = args.dryRun;
1460
+ VERBOSE = args.verbose || DRY_RUN;
1344
1461
  if (DRY_RUN) {
1345
- info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1346
- info("DRY RUN \u2014 no files will be written, no commands will run.");
1347
- info("Lines tagged (dry-run) show what would happen.");
1348
- info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1462
+ console.log(c.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1463
+ console.log(c.bold("DRY RUN") + c.dim(" \u2014 no files will be written, no commands will run."));
1464
+ console.log(c.dim("Lines tagged (dry-run) show what would happen."));
1465
+ console.log(c.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1349
1466
  }
1350
1467
  if (subcommand === "refresh") return mainRefresh(args);
1351
1468
  return mainInit(args);
@@ -1384,25 +1501,34 @@ async function mainRefresh(args) {
1384
1501
  const active = nested.profiles[nested.active];
1385
1502
  if (!active) fail(`${CONFIG_FILENAME} active profile "${nested.active}" is not present in profiles.`);
1386
1503
  info(`refreshing launch-kit in ${targetDir} (course: ${nested.active}, project: ${active.orgSlug}/${active.projectSlug}) \u2026`);
1504
+ header("launch-kit refresh", [
1505
+ ["course", nested.active],
1506
+ ["project", `${active.orgSlug}/${active.projectSlug}`],
1507
+ ["dir", path4.relative(cwd, targetDir) || "."]
1508
+ ]);
1387
1509
  const cfg = { pat: active.pat, orgSlug: active.orgSlug, projectSlug: active.projectSlug, serverUrl: active.serverUrl };
1388
- mergeMcpFile(targetDir, buildLaunchKitMcpEntries(cfg));
1510
+ phase(".mcp.json", mergeMcpFile(targetDir, buildLaunchKitMcpEntries(cfg)));
1389
1511
  ensureGitignoreLine(targetDir, CONFIG_FILENAME);
1390
- if (!args.noMigrateSafety) scaffoldMigrateSafety(targetDir, args.refreshScaffolds);
1391
- if (!args.noLsMarketplace) scaffoldLsMarketplace(targetDir);
1392
- if (!args.noRecallHook) scaffoldRecallHook(targetDir);
1393
- tryActivateStatusline();
1394
- console.log("");
1512
+ if (!args.noMigrateSafety) phase("migrate-safety", scaffoldMigrateSafety(targetDir, args.refreshScaffolds));
1513
+ if (!args.noLsMarketplace) phase("ls-marketplace", scaffoldLsMarketplace(targetDir));
1514
+ if (!args.noRecallHook) phase("recall-hook", scaffoldRecallHook(targetDir));
1515
+ const slR = tryActivateStatusline();
1516
+ if (slR) phase("statusline", slR);
1395
1517
  if (DRY_RUN) {
1396
- info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1397
- info(`DRY RUN COMPLETE \u2014 refresh would have applied the above; no files modified.`);
1398
- info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1518
+ console.log("");
1519
+ console.log(c.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1520
+ console.log(c.bold("DRY RUN COMPLETE") + c.dim(" \u2014 refresh would have applied the above; no files modified."));
1521
+ console.log(c.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1399
1522
  return;
1400
1523
  }
1401
1524
  ok(`refresh complete \u2014 restart Claude Code to pick up any new /kit:* commands`);
1402
- if (!args.quiet) {
1403
- console.log(`
1404
- Skipped (refresh never runs these): clone, dependency install, onboard script, launch-recall init. Use \`npx @launchsecure/launch-kit init\` for a full bootstrap.
1405
- ${getLaunchKitToolsGuide()}`);
1525
+ const showGuide = args.quiet ? false : args.guide === true;
1526
+ const hints = ["Restart Claude Code to pick up any new /kit:* commands."];
1527
+ if (!showGuide && !args.quiet) hints.push("Run with --guide to print the full MCP + slash-command catalog. --verbose for per-file detail.");
1528
+ footer("Refresh complete.", hints);
1529
+ if (showGuide) {
1530
+ console.log(c.dim(`(refresh never runs these: clone, dependency install, onboard script, launch-recall init \u2014 use \`launch-kit init\` for a full bootstrap)`));
1531
+ console.log(getLaunchKitToolsGuide());
1406
1532
  }
1407
1533
  }
1408
1534
  async function mainInit(args) {
@@ -1448,7 +1574,13 @@ async function mainInit(args) {
1448
1574
  if (!/^ls_pat_/.test(args.token)) fail("Token does not look like a LaunchSecure PAT (expected prefix ls_pat_).");
1449
1575
  if (!args.orgSlug) fail("--org=<orgSlug> is required.");
1450
1576
  if (!args.projectSlug) fail("--project=<projectSlug> is required.");
1577
+ header("launch-kit init", [
1578
+ ["org", args.orgSlug],
1579
+ ["project", args.projectSlug],
1580
+ ["server", args.serverUrl]
1581
+ ]);
1451
1582
  const { hasGh } = preflight();
1583
+ phase("preflight", { status: "ok", summary: `node ${process.versions.node}${hasGh ? " \xB7 git \xB7 gh" : " \xB7 git (gh not found \u2014 will use git for clone)"}` });
1452
1584
  info(`resolving project ${args.orgSlug}/${args.projectSlug} on ${args.serverUrl} \u2026`);
1453
1585
  let resolved;
1454
1586
  try {
@@ -1457,6 +1589,7 @@ async function mainInit(args) {
1457
1589
  fail(err instanceof Error ? err.message : String(err));
1458
1590
  }
1459
1591
  ok(`resolved "${resolved.projectName}"`);
1592
+ phase("project_info", { status: "ok", summary: `"${resolved.projectName}"` });
1460
1593
  if (!resolved.repositoryUrl) {
1461
1594
  fail(
1462
1595
  `Project "${resolved.projectSlug}" has no GitHub repository configured. Connect GitHub at ${args.serverUrl}/${resolved.orgSlug}/projects/${resolved.projectSlug}/settings/integrations, then re-run init.`
@@ -1480,7 +1613,14 @@ async function mainInit(args) {
1480
1613
  fail(`${targetDir} exists and is not empty (and not a matching git repo). Refusing to clone into it. Pass --dir=<other-path>.`);
1481
1614
  }
1482
1615
  }
1483
- if (!skipClone) cloneRepo(repoUrl, targetDir, hasGh);
1616
+ const relTarget = path4.relative(cwd, targetDir) || ".";
1617
+ if (!skipClone) {
1618
+ section(`Cloning ${repoUrl}`);
1619
+ cloneRepo(repoUrl, targetDir, hasGh);
1620
+ phase("clone", { status: "ok", summary: `\u2192 ${relTarget}` });
1621
+ } else {
1622
+ phase("clone", { status: "in-sync", summary: `${relTarget} (already a clone of this repo)` });
1623
+ }
1484
1624
  const cfg = {
1485
1625
  pat: args.token,
1486
1626
  orgSlug: resolved.orgSlug,
@@ -1489,7 +1629,8 @@ async function mainInit(args) {
1489
1629
  };
1490
1630
  const courseName = args.course ?? inferCourseName(cfg.serverUrl);
1491
1631
  writeConfigFile(targetDir, cfg, courseName);
1492
- mergeMcpFile(targetDir, buildLaunchKitMcpEntries(cfg));
1632
+ phase("cred file", { status: "ok", summary: `course=${courseName}, active` });
1633
+ phase(".mcp.json", mergeMcpFile(targetDir, buildLaunchKitMcpEntries(cfg)));
1493
1634
  ensureGitignoreLine(targetDir, CONFIG_FILENAME);
1494
1635
  let installSkippedReason = null;
1495
1636
  const detected = detectPackageManager(targetDir);
@@ -1499,43 +1640,51 @@ async function mainInit(args) {
1499
1640
  } else if (!detected) {
1500
1641
  installSkippedReason = "no package.json found";
1501
1642
  } else {
1643
+ section(`Installing dependencies (${detected.pm.name})`);
1502
1644
  runInstall(targetDir, detected);
1503
- if (!args.noOnboard && hasOnboardScript(targetDir)) runOnboard(targetDir, detected.pm);
1645
+ phase("install", { status: "ok", summary: `${detected.pm.binary} ${detected.pm.installArgs.join(" ")}` });
1646
+ if (!args.noOnboard && hasOnboardScript(targetDir)) {
1647
+ section(`Running ${detected.pm.binary} run ${ONBOARD_SCRIPT_NAME}`);
1648
+ runOnboard(targetDir, detected.pm);
1649
+ phase("onboard", { status: "ok", summary: `${detected.pm.binary} run ${ONBOARD_SCRIPT_NAME}` });
1650
+ }
1504
1651
  }
1505
1652
  const hasOnboard = hasOnboardScript(targetDir);
1506
- if (!args.noRecall) runRecallInit(targetDir);
1507
- if (!args.noMigrateSafety) scaffoldMigrateSafety(targetDir, args.refreshScaffolds);
1508
- if (!args.noLsMarketplace) scaffoldLsMarketplace(targetDir);
1509
- if (!args.noRecallHook) scaffoldRecallHook(targetDir);
1510
- tryActivateStatusline();
1511
- const relTarget = path4.relative(cwd, targetDir) || ".";
1512
- console.log("");
1653
+ if (installSkippedReason) phase("install", { status: "skipped", summary: installSkippedReason });
1654
+ if (!args.noRecall) {
1655
+ section("Initializing launch-recall (shadow git backup)");
1656
+ runRecallInit(targetDir);
1657
+ phase("launch-recall", { status: "ok", summary: "shadow git ready" });
1658
+ }
1659
+ if (!args.noMigrateSafety) phase("migrate-safety", scaffoldMigrateSafety(targetDir, args.refreshScaffolds));
1660
+ if (!args.noLsMarketplace) phase("ls-marketplace", scaffoldLsMarketplace(targetDir));
1661
+ if (!args.noRecallHook) phase("recall-hook", scaffoldRecallHook(targetDir));
1662
+ const slR = tryActivateStatusline();
1663
+ if (slR) phase("statusline", slR);
1513
1664
  if (DRY_RUN) {
1514
- info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1515
- info(`DRY RUN COMPLETE \u2014 no files were modified, no commands ran.`);
1516
- info(`Target: ${targetDir}`);
1517
- info(`Re-run without --dry-run to apply the changes shown above.`);
1518
- info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1665
+ console.log("");
1666
+ console.log(c.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1667
+ console.log(c.bold("DRY RUN COMPLETE") + c.dim(` \u2014 no files were modified, no commands ran.`));
1668
+ console.log(c.dim(`Target: ${targetDir}`));
1669
+ console.log(c.dim(`Re-run without --dry-run to apply the changes shown above.`));
1670
+ console.log(c.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1519
1671
  return;
1520
1672
  }
1521
1673
  ok(`done \u2014 ${resolved.projectName} is ready at ${targetDir}`);
1674
+ const showGuide = args.quiet ? false : args.guide ?? true;
1675
+ const nextSteps = [`cd ${relTarget}`];
1522
1676
  if (installSkippedReason) {
1523
- const installLine = detected ? ` ${detected.pm.binary} ${detected.pm.installArgs.join(" ")}` : ` npm install # or your package manager of choice`;
1524
- const onboardLine = hasOnboard && detected && !args.noOnboard ? `
1525
- ${detected.pm.binary} run ${ONBOARD_SCRIPT_NAME} # project setup hook` : "";
1526
- console.log(`
1527
- Next steps (install skipped: ${installSkippedReason}):
1528
- cd ${relTarget}
1529
- ${installLine}${onboardLine}
1530
- claude # launch Claude Code (5 MCPs wired)${args.quiet ? "" : `
1531
- ${getLaunchKitToolsGuide()}`}`);
1532
- } else if (!args.quiet) {
1533
- console.log(`
1534
- Next steps:
1535
- cd ${relTarget}
1536
- claude # launch Claude Code (5 MCPs wired)
1537
- ${getLaunchKitToolsGuide()}`);
1677
+ nextSteps.push(detected ? `${detected.pm.binary} ${detected.pm.installArgs.join(" ")} # install skipped: ${installSkippedReason}` : `npm install # install skipped: ${installSkippedReason}`);
1678
+ if (hasOnboard && detected && !args.noOnboard) {
1679
+ nextSteps.push(`${detected.pm.binary} run ${ONBOARD_SCRIPT_NAME} # project setup hook`);
1680
+ }
1538
1681
  }
1682
+ nextSteps.push("claude # launch Claude Code (5 MCPs wired)");
1683
+ footer(`${resolved.projectName} is ready at ${relTarget}.`, [
1684
+ "Next:",
1685
+ ...nextSteps.map((s) => " " + s)
1686
+ ]);
1687
+ if (showGuide) console.log(getLaunchKitToolsGuide());
1539
1688
  }
1540
1689
  main().catch((err) => {
1541
1690
  console.error(`[launch-kit] unexpected error: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchsecure/launch-kit",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "description": "LaunchSecure toolkit — launch-pod (pipeline), launch-chart (project graph MCP), launch-deck (visual playground MCP), launch-kit-beacon (feedback Web Component), launch-recall (file-watcher backup).",
5
5
  "license": "MIT",
6
6
  "author": "LaunchSecure - AutomateWithUs",
@@ -56,6 +56,24 @@
56
56
  "launch-course": "./dist/server/course-entry.js",
57
57
  "launch-beacon": "./dist/server/beacon-monitor-entry.js"
58
58
  },
59
+ "scripts": {
60
+ "build": "pnpm build:client && pnpm build:chart-client && pnpm build:deck-client && pnpm build:council-client && pnpm build:beacon && pnpm build:server",
61
+ "build:beacon": "vite build --config vite.beacon.config.ts && tsc -p tsconfig.beacon.json --emitDeclarationOnly --outDir dist/beacon/types",
62
+ "test:beacon": "vitest run --config vite.beacon.config.ts",
63
+ "test:radar": "vitest run --config vite.radar.config.ts",
64
+ "test:chart": "vitest run --config vite.chart.test.config.ts",
65
+ "build:deck-client": "vite build --config vite.deck.config.ts",
66
+ "build:council-client": "vite build --config vite.council.config.ts",
67
+ "build:client": "vite build",
68
+ "build:chart-client": "vite build --config vite.chart.config.ts",
69
+ "build:server": "esbuild src/server/cli.ts src/server/fb-wizard.ts src/server/graph-mcp-entry.ts src/server/chart-serve.ts src/server/deck-mcp-entry.ts src/server/deck-serve.ts src/server/council-entry.ts src/server/council-serve.ts src/server/recall-entry.ts src/server/init-entry.ts src/server/orbit-entry.ts src/server/course-entry.ts src/server/beacon-monitor-entry.ts src/server/parse-worker-entry.ts --bundle --platform=node --target=node18 --outdir=dist/server --external:node-pty --external:ws --external:typescript --external:web-tree-sitter --external:tree-sitter-typescript --external:cloudflared --external:pg --external:pg-native --external:pgsql-parser --external:libpg-query && rm -rf dist/server/public && cp -r ../claude-code-web/src/public dist/server/public && rm -rf dist/server/graph/queries && mkdir -p dist/server/graph && cp -r src/server/graph/queries dist/server/graph/queries",
70
+ "dev:client": "vite",
71
+ "dev:deck-serve": "cd ../.. && tsx watch packages/cli/src/server/deck-mcp-entry.ts serve",
72
+ "dev:chart": "pnpm build:server && pnpm build:chart-client && node dist/server/graph-mcp-entry.js serve",
73
+ "dev:server": "pnpm build:server && node dist/server/cli.js",
74
+ "dev": "pnpm build:server && concurrently -k -n client,server -c cyan,magenta \"vite\" \"node dist/server/cli.js\"",
75
+ "prepublishOnly": "pnpm build"
76
+ },
59
77
  "files": [
60
78
  "dist",
61
79
  "prompts",
@@ -76,6 +94,8 @@
76
94
  "ws": "^8.18.0"
77
95
  },
78
96
  "devDependencies": {
97
+ "@launchsecure/claude-code-web": "workspace:*",
98
+ "@launchsecure/ui": "workspace:*",
79
99
  "@types/node": "^20.0.0",
80
100
  "@types/pg": "^8.11.10",
81
101
  "@types/react": "^18.3.12",
@@ -99,24 +119,6 @@
99
119
  "react-router-dom": "^6.28.0",
100
120
  "tailwindcss": "^3.4.19",
101
121
  "vite": "^5.4.11",
102
- "vitest": "^1.6.0",
103
- "@launchsecure/claude-code-web": "0.0.1",
104
- "@launchsecure/ui": "0.0.1"
105
- },
106
- "scripts": {
107
- "build": "pnpm build:client && pnpm build:chart-client && pnpm build:deck-client && pnpm build:council-client && pnpm build:beacon && pnpm build:server",
108
- "build:beacon": "vite build --config vite.beacon.config.ts && tsc -p tsconfig.beacon.json --emitDeclarationOnly --outDir dist/beacon/types",
109
- "test:beacon": "vitest run --config vite.beacon.config.ts",
110
- "test:radar": "vitest run --config vite.radar.config.ts",
111
- "test:chart": "vitest run --config vite.chart.test.config.ts",
112
- "build:deck-client": "vite build --config vite.deck.config.ts",
113
- "build:council-client": "vite build --config vite.council.config.ts",
114
- "build:client": "vite build",
115
- "build:chart-client": "vite build --config vite.chart.config.ts",
116
- "build:server": "esbuild src/server/cli.ts src/server/fb-wizard.ts src/server/graph-mcp-entry.ts src/server/chart-serve.ts src/server/deck-mcp-entry.ts src/server/deck-serve.ts src/server/council-entry.ts src/server/council-serve.ts src/server/recall-entry.ts src/server/init-entry.ts src/server/orbit-entry.ts src/server/course-entry.ts src/server/beacon-monitor-entry.ts src/server/parse-worker-entry.ts --bundle --platform=node --target=node18 --outdir=dist/server --external:node-pty --external:ws --external:typescript --external:web-tree-sitter --external:tree-sitter-typescript --external:cloudflared --external:pg --external:pg-native --external:pgsql-parser --external:libpg-query && rm -rf dist/server/public && cp -r ../claude-code-web/src/public dist/server/public && rm -rf dist/server/graph/queries && mkdir -p dist/server/graph && cp -r src/server/graph/queries dist/server/graph/queries",
117
- "dev:client": "vite",
118
- "dev:chart": "pnpm build:server && pnpm build:chart-client && node dist/server/graph-mcp-entry.js serve",
119
- "dev:server": "pnpm build:server && node dist/server/cli.js",
120
- "dev": "pnpm build:server && concurrently -k -n client,server -c cyan,magenta \"vite\" \"node dist/server/cli.js\""
122
+ "vitest": "^1.6.0"
121
123
  }
122
- }
124
+ }