@launchsecure/launch-kit 0.0.38 → 0.0.40

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 (101) hide show
  1. package/dist/beacon/beacon.mjs +308 -298
  2. package/dist/beacon/beacon.mjs.map +1 -1
  3. package/dist/beacon/beacon.umd.js +6 -6
  4. package/dist/beacon/beacon.umd.js.map +1 -1
  5. package/dist/beacon/types/internal/screenshot.d.ts.map +1 -1
  6. package/dist/chart-client/assets/index-CWJFFDPu.css +1 -0
  7. package/dist/chart-client/index.html +2 -2
  8. package/dist/client/assets/index-CTzFcfGV.css +32 -0
  9. package/dist/client/index.html +2 -2
  10. package/dist/council-client/assets/index-ArgRc5mN.css +1 -0
  11. package/dist/council-client/index.html +2 -2
  12. package/dist/deck-client/assets/{_baseUniq-CgW32Gdk.js → _baseUniq-BZP7n41F.js} +1 -1
  13. package/dist/deck-client/assets/{arc-D-Mg9gvM.js → arc-31biU3Az.js} +1 -1
  14. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-CdTsXsgl.js → architectureDiagram-Q4EWVU46-DHg6Ss--.js} +1 -1
  15. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-mwTneYyB.js → blockDiagram-DXYQGD6D-CUdblaWk.js} +1 -1
  16. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-C4R8IbjO.js → c4Diagram-AHTNJAMY-MfAO5lak.js} +1 -1
  17. package/dist/deck-client/assets/channel-BBkRLdnC.js +1 -0
  18. package/dist/deck-client/assets/{chunk-4BX2VUAB-ZWuRIUwb.js → chunk-4BX2VUAB-DQ1MrGgN.js} +1 -1
  19. package/dist/deck-client/assets/{chunk-4TB4RGXK-PNHX10sF.js → chunk-4TB4RGXK-BUJtZ7jO.js} +1 -1
  20. package/dist/deck-client/assets/{chunk-55IACEB6-CD9MUgPr.js → chunk-55IACEB6-BdSnXB6g.js} +1 -1
  21. package/dist/deck-client/assets/{chunk-EDXVE4YY-C_CpORb3.js → chunk-EDXVE4YY-94yZIUI8.js} +1 -1
  22. package/dist/deck-client/assets/{chunk-FMBD7UC4-Bg5RoVC-.js → chunk-FMBD7UC4-PnZ9v6ey.js} +1 -1
  23. package/dist/deck-client/assets/{chunk-OYMX7WX6-DhTwgQwd.js → chunk-OYMX7WX6-DXrWNOsV.js} +1 -1
  24. package/dist/deck-client/assets/{chunk-QZHKN3VN-C5VLMaFa.js → chunk-QZHKN3VN-CsIGIDKX.js} +1 -1
  25. package/dist/deck-client/assets/{chunk-YZCP3GAM-NAGHy4Sr.js → chunk-YZCP3GAM-DVkBO9tn.js} +1 -1
  26. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-DFCaeF-7.js +1 -0
  27. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-DFCaeF-7.js +1 -0
  28. package/dist/deck-client/assets/clone-GCEVRScB.js +1 -0
  29. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-CpUczjZk.js → cose-bilkent-S5V4N54A-m126Oh3b.js} +1 -1
  30. package/dist/deck-client/assets/{dagre-KV5264BT-BOvb07MG.js → dagre-KV5264BT-C2aig8U5.js} +1 -1
  31. package/dist/deck-client/assets/{diagram-5BDNPKRD-BPxwTiC-.js → diagram-5BDNPKRD-CKpoRfGn.js} +1 -1
  32. package/dist/deck-client/assets/{diagram-G4DWMVQ6-Dz_gsHgx.js → diagram-G4DWMVQ6-Cjh115Ep.js} +1 -1
  33. package/dist/deck-client/assets/{diagram-MMDJMWI5-B7z-oVTW.js → diagram-MMDJMWI5-DKlBv_2L.js} +1 -1
  34. package/dist/deck-client/assets/{diagram-TYMM5635-CAIAglLQ.js → diagram-TYMM5635-CdBh4cEn.js} +1 -1
  35. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BiViTWF3.js → erDiagram-SMLLAGMA-56pn_93p.js} +1 -1
  36. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-DYVemp0H.js → flowDiagram-DWJPFMVM-BtV3M5xJ.js} +1 -1
  37. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-Chc1Iyu1.js → ganttDiagram-T4ZO3ILL-DTIsC6Zg.js} +1 -1
  38. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B7eFgaj5.js → gitGraphDiagram-UUTBAWPF-CJYeyCLe.js} +1 -1
  39. package/dist/deck-client/assets/{graph-CKaIoNwb.js → graph-BDvMu1Ss.js} +1 -1
  40. package/dist/deck-client/assets/index-D4eSxcBn.css +1 -0
  41. package/dist/deck-client/assets/{index-BRawc7RA.js → index-QnGVE9PZ.js} +83 -83
  42. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BxsVq7vO.js → infoDiagram-42DDH7IO-BWyKJnpW.js} +1 -1
  43. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DAM7vPwa.js → ishikawaDiagram-UXIWVN3A-DXYkdO3T.js} +1 -1
  44. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-Xe20Nf7R.js → journeyDiagram-VCZTEJTY-C2zBr-J5.js} +1 -1
  45. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-DS8YguzB.js → kanban-definition-6JOO6SKY-CdoYLS4Z.js} +1 -1
  46. package/dist/deck-client/assets/{layout-DKMBpzR-.js → layout-vOnxnCQU.js} +1 -1
  47. package/dist/deck-client/assets/{linear-DTNtBg5h.js → linear-B0J0WCGz.js} +1 -1
  48. package/dist/deck-client/assets/{min-C4DrxCcA.js → min-B0AXlT9L.js} +1 -1
  49. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-B4nEtsw5.js → mindmap-definition-QFDTVHPH-oAybLedr.js} +1 -1
  50. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-BzHdGNu5.js → pieDiagram-DEJITSTG-BjHyHxGk.js} +1 -1
  51. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-CaX0SD4-.js → quadrantDiagram-34T5L4WZ-dtluDZXs.js} +1 -1
  52. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-QeG4p2ni.js → requirementDiagram-MS252O5E-Cq8l7bOl.js} +1 -1
  53. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BoAwgAj-.js → sankeyDiagram-XADWPNL6-C1Vih91z.js} +1 -1
  54. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-Dn4pYYgu.js → sequenceDiagram-FGHM5R23-CYkd7oQK.js} +1 -1
  55. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-Is6KRmQV.js → stateDiagram-FHFEXIEX-CtyG8wBK.js} +1 -1
  56. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BLyKWfcN.js +1 -0
  57. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-v64IZGuY.js → timeline-definition-GMOUNBTQ-DZIxSyd1.js} +1 -1
  58. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-noh9eouF.js → vennDiagram-DHZGUBPP-Ct4JVRDM.js} +1 -1
  59. package/dist/deck-client/assets/{wardley-RL74JXVD-cJ_1is2S.js → wardley-RL74JXVD-V29ycxOW.js} +1 -1
  60. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-DxR4j737.js → wardleyDiagram-NUSXRM2D-D-Ua6Cmi.js} +1 -1
  61. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-B26vodaL.js → xychartDiagram-5P7HB3ND-BPCOuRVl.js} +1 -1
  62. package/dist/deck-client/index.html +2 -2
  63. package/dist/server/beacon-monitor-entry.js +106 -24
  64. package/dist/server/chart-serve.js +544 -247
  65. package/dist/server/cli.js +743 -324
  66. package/dist/server/council-entry.js +16 -3
  67. package/dist/server/council-serve.js +15 -2
  68. package/dist/server/deck-mcp-entry.js +270 -108
  69. package/dist/server/deck-serve.js +101 -23
  70. package/dist/server/fb-wizard.js +0 -0
  71. package/dist/server/graph-mcp-entry.js +866 -357
  72. package/dist/server/init-entry.js +152 -25
  73. package/dist/server/orbit-entry.js +91 -7
  74. package/dist/server/radar-docker-init-entry.js +0 -0
  75. package/dist/server/radar-entrypoint-entry.js +0 -0
  76. package/dist/server/radar-teardown-entry.js +0 -0
  77. package/dist/server/recall-entry.js +94 -12
  78. package/dist/server/rover-entry.js +44 -1
  79. package/package.json +23 -22
  80. package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +8 -7
  81. package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +2 -2
  82. package/scaffolds/ls-marketplace/plugins/kit/skills/comms/SKILL.md +88 -0
  83. package/scaffolds/ls-marketplace/plugins/kit/skills/project-info/SKILL.md +88 -0
  84. package/scaffolds/ls-marketplace/plugins/kit/skills/slides/SKILL.md +118 -0
  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/scaffolds/statusline/statusline-base.sh +20 -0
  88. package/scaffolds/statusline/statusline-mcp.sh +68 -19
  89. package/scaffolds/statusline/statusline-wrapper.sh +12 -9
  90. package/dist/chart-client/assets/index-B6rR0CWx.css +0 -1
  91. package/dist/client/assets/index-D6uX1lQe.css +0 -32
  92. package/dist/council-client/assets/index-CleYLarJ.css +0 -1
  93. package/dist/deck-client/assets/channel-CuSee7GO.js +0 -1
  94. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-_kTisqzs.js +0 -1
  95. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-_kTisqzs.js +0 -1
  96. package/dist/deck-client/assets/clone-kb3zkY60.js +0 -1
  97. package/dist/deck-client/assets/index-55P73aS_.css +0 -1
  98. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-Cy45Ttqq.js +0 -1
  99. /package/dist/chart-client/assets/{index-C_xCi3gW.js → index-Dzlj-oCj.js} +0 -0
  100. /package/dist/client/assets/{index-CRecYFUA.js → index-tTg_ezUF.js} +0 -0
  101. /package/dist/council-client/assets/{index-DO-Vn15O.js → index-B1v46vTE.js} +0 -0
@@ -284,14 +284,14 @@ function pidFilePath(recallDir) {
284
284
  function existingWatcherPid() {
285
285
  const { recallDir } = resolveRecallPaths();
286
286
  const pf = pidFilePath(recallDir);
287
- if (!(0, import_node_fs.existsSync)(pf)) return null;
288
- const pid = Number((0, import_node_fs.readFileSync)(pf, "utf-8").trim());
287
+ if (!(0, import_node_fs2.existsSync)(pf)) return null;
288
+ const pid = Number((0, import_node_fs2.readFileSync)(pf, "utf-8").trim());
289
289
  if (!Number.isFinite(pid) || pid <= 0) return null;
290
290
  return isPidAlive(pid) ? pid : null;
291
291
  }
292
292
  function ensureWatcher() {
293
293
  const { gitDir, workTree } = resolveRecallPaths();
294
- if (!(0, import_node_fs.existsSync)(gitDir)) {
294
+ if (!(0, import_node_fs2.existsSync)(gitDir)) {
295
295
  process.stderr.write(
296
296
  `[launch-recall mcp] shadow repo missing at ${gitDir} \u2014 run \`launch-recall init\` first. MCP tools will still serve read-only queries, but nothing will be captured.
297
297
  `
@@ -358,7 +358,7 @@ async function handleTool(name, args) {
358
358
  function doctorTool() {
359
359
  const { gitDir, recallDir } = resolveRecallPaths();
360
360
  const checks = [];
361
- const shadowOk = (0, import_node_fs.existsSync)(gitDir);
361
+ const shadowOk = (0, import_node_fs2.existsSync)(gitDir);
362
362
  checks.push({
363
363
  name: "shadow_repo",
364
364
  ok: shadowOk,
@@ -391,7 +391,7 @@ function doctorTool() {
391
391
  }
392
392
  function reportTool() {
393
393
  const { gitDir, recallDir, workTree } = resolveRecallPaths();
394
- if (!(0, import_node_fs.existsSync)(gitDir)) return { error: "shadow repo not initialised" };
394
+ if (!(0, import_node_fs2.existsSync)(gitDir)) return { error: "shadow repo not initialised" };
395
395
  let totalSnapshots = 0;
396
396
  try {
397
397
  const out = (0, import_node_child_process2.execFileSync)("git", [`--git-dir=${gitDir}`, "rev-list", "--count", "HEAD"], {
@@ -425,9 +425,9 @@ function reportTool() {
425
425
  }
426
426
  let config = null;
427
427
  const cfgPath = `${workTree}/.launch-recall.json`;
428
- if ((0, import_node_fs.existsSync)(cfgPath)) {
428
+ if ((0, import_node_fs2.existsSync)(cfgPath)) {
429
429
  try {
430
- config = JSON.parse((0, import_node_fs.readFileSync)(cfgPath, "utf-8"));
430
+ config = JSON.parse((0, import_node_fs2.readFileSync)(cfgPath, "utf-8"));
431
431
  } catch {
432
432
  }
433
433
  }
@@ -435,7 +435,7 @@ function reportTool() {
435
435
  }
436
436
  function historyTool(path7, limit) {
437
437
  const { gitDir, workTree } = resolveRecallPaths();
438
- if (!(0, import_node_fs.existsSync)(gitDir)) return { error: "shadow repo not initialised", path: path7, snapshots: [] };
438
+ if (!(0, import_node_fs2.existsSync)(gitDir)) return { error: "shadow repo not initialised", path: path7, snapshots: [] };
439
439
  const rel = path7.startsWith("/") ? path7.replace(`${workTree}/`, "").replace(/^\/+/, "") : path7;
440
440
  const snapshots = [];
441
441
  try {
@@ -456,7 +456,7 @@ function statusTool() {
456
456
  const { gitDir, workTree } = resolveRecallPaths();
457
457
  const pid = existingWatcherPid();
458
458
  let lastSnapshotAt = null;
459
- if ((0, import_node_fs.existsSync)(gitDir)) {
459
+ if ((0, import_node_fs2.existsSync)(gitDir)) {
460
460
  try {
461
461
  lastSnapshotAt = (0, import_node_child_process2.execFileSync)("git", [`--git-dir=${gitDir}`, "log", "-1", "--format=%aI"], {
462
462
  encoding: "utf-8",
@@ -551,14 +551,14 @@ function startRecallMcpServer() {
551
551
  process.stderr.write("[launch-recall mcp] stdin closed, exiting\n");
552
552
  teardown();
553
553
  });
554
- void import_node_fs.statSync;
554
+ void import_node_fs2.statSync;
555
555
  }
556
- var import_node_child_process2, import_node_fs, SERVER_INFO, TOOLS, childWatcher;
556
+ var import_node_child_process2, import_node_fs2, SERVER_INFO, TOOLS, childWatcher;
557
557
  var init_recall_mcp = __esm({
558
558
  "src/server/recall-mcp.ts"() {
559
559
  "use strict";
560
560
  import_node_child_process2 = require("node:child_process");
561
- import_node_fs = require("node:fs");
561
+ import_node_fs2 = require("node:fs");
562
562
  init_paths();
563
563
  SERVER_INFO = { name: "launch-recall", version: "0.0.1" };
564
564
  TOOLS = [
@@ -1355,6 +1355,87 @@ var init_uninstall = __esm({
1355
1355
  }
1356
1356
  });
1357
1357
 
1358
+ // src/server/prune-npx-cache.ts
1359
+ var import_node_fs = require("node:fs");
1360
+ var import_node_os = require("node:os");
1361
+ var import_node_path = require("node:path");
1362
+ var import_node_util = require("node:util");
1363
+ var PKG = "@launchsecure/launch-kit";
1364
+ var readFileAsync = (0, import_node_util.promisify)(import_node_fs.readFile);
1365
+ var readdirAsync = (0, import_node_util.promisify)(import_node_fs.readdir);
1366
+ var rmAsync = (0, import_node_util.promisify)(import_node_fs.rm);
1367
+ var realpathAsync = (0, import_node_util.promisify)(import_node_fs.realpath);
1368
+ function npxCacheRoot() {
1369
+ const cache = process.env.npm_config_cache;
1370
+ if (cache && cache.trim()) return (0, import_node_path.join)(cache, "_npx");
1371
+ if (process.platform === "win32") {
1372
+ const localAppData = process.env.LOCALAPPDATA;
1373
+ if (localAppData) return (0, import_node_path.join)(localAppData, "npm-cache", "_npx");
1374
+ }
1375
+ return (0, import_node_path.join)((0, import_node_os.homedir)(), ".npm", "_npx");
1376
+ }
1377
+ function ownVersion() {
1378
+ let dir = __dirname;
1379
+ for (let i = 0; i < 8; i++) {
1380
+ try {
1381
+ const pkg = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path.join)(dir, "package.json"), "utf8"));
1382
+ if (pkg && pkg.name === PKG) return typeof pkg.version === "string" ? pkg.version : null;
1383
+ } catch {
1384
+ }
1385
+ const parent = (0, import_node_path.dirname)(dir);
1386
+ if (parent === dir) break;
1387
+ dir = parent;
1388
+ }
1389
+ return null;
1390
+ }
1391
+ async function pruneStaleNpxCache() {
1392
+ try {
1393
+ const version = ownVersion();
1394
+ if (!version) return;
1395
+ const root = npxCacheRoot();
1396
+ let hashes;
1397
+ try {
1398
+ hashes = await readdirAsync(root);
1399
+ } catch {
1400
+ return;
1401
+ }
1402
+ const selfPath = await realpathAsync(process.argv[1] || __dirname).catch(() => __dirname);
1403
+ let reaped = 0;
1404
+ for (const hash of hashes) {
1405
+ const dir = (0, import_node_path.join)(root, hash);
1406
+ if (selfPath === dir || selfPath.startsWith(dir + import_node_path.sep)) continue;
1407
+ let ver;
1408
+ try {
1409
+ const lkPkg = JSON.parse(
1410
+ await readFileAsync((0, import_node_path.join)(dir, "node_modules", PKG, "package.json"), "utf8")
1411
+ );
1412
+ ver = lkPkg.version;
1413
+ } catch {
1414
+ continue;
1415
+ }
1416
+ if (ver === version) continue;
1417
+ try {
1418
+ const top = JSON.parse(await readFileAsync((0, import_node_path.join)(dir, "package.json"), "utf8"));
1419
+ const spec = top?.dependencies?.[PKG];
1420
+ if (typeof spec === "string" && spec.startsWith("file:")) continue;
1421
+ } catch {
1422
+ }
1423
+ try {
1424
+ await rmAsync(dir, { recursive: true, force: true });
1425
+ reaped++;
1426
+ } catch {
1427
+ }
1428
+ }
1429
+ if (reaped > 0) {
1430
+ process.stderr.write(
1431
+ `[launch-kit] npx-cache: reaped ${reaped} stale copy(ies), kept v${version}
1432
+ `
1433
+ );
1434
+ }
1435
+ } catch {
1436
+ }
1437
+ }
1438
+
1358
1439
  // src/server/recall-entry.ts
1359
1440
  function logStderr(msg) {
1360
1441
  process.stderr.write(`[launch-recall] ${msg}
@@ -1383,6 +1464,7 @@ function printUsage() {
1383
1464
  );
1384
1465
  }
1385
1466
  async function main() {
1467
+ void pruneStaleNpxCache();
1386
1468
  const argv = process.argv.slice(2);
1387
1469
  const subcommand = argv[0];
1388
1470
  if (!subcommand || subcommand === "--help" || subcommand === "-h") {
@@ -608,7 +608,7 @@ var require_package = __commonJS({
608
608
  "package.json"(exports2, module2) {
609
609
  module2.exports = {
610
610
  name: "@launchsecure/launch-kit",
611
- version: "0.0.38",
611
+ version: "0.0.40",
612
612
  description: "LaunchSecure toolkit \u2014 launch-sequencer (pipeline runner + terminal bridge), launch-radar (feedback webhook receiver), launch-chart (project graph MCP), launch-deck (visual playground MCP), launch-kit-beacon (feedback Web Component), launch-recall (file-watcher backup). launch-pod is the container image these run inside.",
613
613
  license: "MIT",
614
614
  author: "LaunchSecure - AutomateWithUs",
@@ -19868,6 +19868,23 @@ async function podsList(_state) {
19868
19868
  }
19869
19869
  return { pods };
19870
19870
  }
19871
+ async function podsPurgeAll(state) {
19872
+ const { pods } = await podsList(state);
19873
+ const projects = [];
19874
+ for (const pod of pods) {
19875
+ try {
19876
+ await stopAndRemove(pod.containerName);
19877
+ if (pod.projectSlug) {
19878
+ projects.push(pod.projectSlug);
19879
+ await dockerVolumeRmIfExists(`${VOLUME_PREFIX}${pod.projectSlug}-workspace`);
19880
+ await dockerVolumeRmIfExists(`${VOLUME_PREFIX}${pod.projectSlug}-claude`);
19881
+ }
19882
+ } catch (err) {
19883
+ console.warn(`[rover] purge of "${pod.containerName}" failed: ${err instanceof Error ? err.message : String(err)}`);
19884
+ }
19885
+ }
19886
+ return { purged: pods.length, projects };
19887
+ }
19871
19888
  async function stopAndRemove(containerName) {
19872
19889
  await dockerStopIfExists(containerName);
19873
19890
  await dockerRmIfExists(containerName);
@@ -20124,6 +20141,32 @@ async function handleRequest(req, res, state) {
20124
20141
  return json(res, 500, { error: err instanceof Error ? err.message : "internal_error" });
20125
20142
  }
20126
20143
  }
20144
+ if (method === "POST" && path === "/shutdown") {
20145
+ const rawBody = await readBody(req);
20146
+ const sigHeader = req.headers["x-ls-signature"];
20147
+ const sigStr = Array.isArray(sigHeader) ? sigHeader[0] : sigHeader;
20148
+ const failure = verifySignature(state.secret, rawBody, sigStr);
20149
+ if (failure) {
20150
+ console.warn(`[rover] POST /shutdown \u2192 401 (${failure})`);
20151
+ return json(res, 401, { error: "invalid_signature" });
20152
+ }
20153
+ json(res, 200, { ok: true, shuttingDown: true });
20154
+ void (async () => {
20155
+ try {
20156
+ const result = await podsPurgeAll(state);
20157
+ console.log(`[rover] /shutdown \u2014 purged ${result.purged} pod(s); stopping daemon`);
20158
+ } catch (err) {
20159
+ console.error("[rover] /shutdown pod purge failed:", err);
20160
+ } finally {
20161
+ try {
20162
+ process.kill(process.pid, "SIGTERM");
20163
+ } catch {
20164
+ process.exit(0);
20165
+ }
20166
+ }
20167
+ })();
20168
+ return;
20169
+ }
20127
20170
  return json(res, 404, { error: "not_found", path });
20128
20171
  }
20129
20172
  function json(res, status, body) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@launchsecure/launch-kit",
3
- "version": "0.0.38",
3
+ "version": "0.0.40",
4
4
  "description": "LaunchSecure toolkit — launch-sequencer (pipeline runner + terminal bridge), launch-radar (feedback webhook receiver), launch-chart (project graph MCP), launch-deck (visual playground MCP), launch-kit-beacon (feedback Web Component), launch-recall (file-watcher backup). launch-pod is the container image these run inside.",
5
5
  "license": "MIT",
6
6
  "author": "LaunchSecure - AutomateWithUs",
@@ -59,6 +59,24 @@
59
59
  "launch-rover": "./dist/server/rover-entry.js",
60
60
  "launch-bot": "./dist/server/launch-bot-entry.js"
61
61
  },
62
+ "scripts": {
63
+ "build": "pnpm build:client && pnpm build:chart-client && pnpm build:deck-client && pnpm build:council-client && pnpm build:beacon && pnpm build:server",
64
+ "build:beacon": "vite build --config vite.beacon.config.ts && tsc -p tsconfig.beacon.json --emitDeclarationOnly --outDir dist/beacon/types",
65
+ "test:beacon": "vitest run --config vite.beacon.config.ts",
66
+ "test:radar": "vitest run --config vite.radar.config.ts",
67
+ "test:chart": "vitest run --config vite.chart.test.config.ts",
68
+ "build:deck-client": "vite build --config vite.deck.config.ts",
69
+ "build:council-client": "vite build --config vite.council.config.ts",
70
+ "build:client": "vite build",
71
+ "build:chart-client": "vite build --config vite.chart.config.ts",
72
+ "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 src/server/radar-teardown-entry.ts src/server/radar-docker-init-entry.ts src/server/launch-radar-entry.ts src/server/rover-entry.ts src/server/launch-bot-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",
73
+ "dev:client": "vite",
74
+ "dev:deck-serve": "cd ../.. && tsx watch packages/cli/src/server/deck-mcp-entry.ts serve",
75
+ "dev:chart": "pnpm build:server && pnpm build:chart-client && node dist/server/graph-mcp-entry.js serve",
76
+ "dev:server": "pnpm build:server && node dist/server/cli.js",
77
+ "dev": "pnpm build:server && concurrently -k -n client,server -c cyan,magenta \"vite\" \"node dist/server/cli.js\"",
78
+ "prepublishOnly": "pnpm build"
79
+ },
62
80
  "files": [
63
81
  "dist",
64
82
  "prompts",
@@ -79,6 +97,8 @@
79
97
  "ws": "^8.18.0"
80
98
  },
81
99
  "devDependencies": {
100
+ "@launchsecure/claude-code-web": "workspace:*",
101
+ "@launchsecure/ui": "workspace:*",
82
102
  "@types/node": "^20.0.0",
83
103
  "@types/pg": "^8.11.10",
84
104
  "@types/react": "^18.3.12",
@@ -102,25 +122,6 @@
102
122
  "react-router-dom": "^6.28.0",
103
123
  "tailwindcss": "^3.4.19",
104
124
  "vite": "^5.4.11",
105
- "vitest": "^1.6.0",
106
- "@launchsecure/claude-code-web": "0.0.1",
107
- "@launchsecure/ui": "0.0.1"
108
- },
109
- "scripts": {
110
- "build": "pnpm build:client && pnpm build:chart-client && pnpm build:deck-client && pnpm build:council-client && pnpm build:beacon && pnpm build:server",
111
- "build:beacon": "vite build --config vite.beacon.config.ts && tsc -p tsconfig.beacon.json --emitDeclarationOnly --outDir dist/beacon/types",
112
- "test:beacon": "vitest run --config vite.beacon.config.ts",
113
- "test:radar": "vitest run --config vite.radar.config.ts",
114
- "test:chart": "vitest run --config vite.chart.test.config.ts",
115
- "build:deck-client": "vite build --config vite.deck.config.ts",
116
- "build:council-client": "vite build --config vite.council.config.ts",
117
- "build:client": "vite build",
118
- "build:chart-client": "vite build --config vite.chart.config.ts",
119
- "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 src/server/radar-teardown-entry.ts src/server/radar-docker-init-entry.ts src/server/launch-radar-entry.ts src/server/rover-entry.ts src/server/launch-bot-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",
120
- "dev:client": "vite",
121
- "dev:deck-serve": "cd ../.. && tsx watch packages/cli/src/server/deck-mcp-entry.ts serve",
122
- "dev:chart": "pnpm build:server && pnpm build:chart-client && node dist/server/graph-mcp-entry.js serve",
123
- "dev:server": "pnpm build:server && node dist/server/cli.js",
124
- "dev": "pnpm build:server && concurrently -k -n client,server -c cyan,magenta \"vite\" \"node dist/server/cli.js\""
125
+ "vitest": "^1.6.0"
125
126
  }
126
- }
127
+ }
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Wire launch-kit's MCP chips into the user's existing Claude Code statusline. Additive — does not create or replace an existing statusline, only appends colored chips (recall/chart/deck/council/secure) showing each daemon's liveness + last-activity age, plus a reachability probe for the hosted launch-secure MCP. Idempotent. Run /kit:deactivate-statusline to undo.
2
+ description: Wire launch-kit's MCP chips into the user's Claude Code statusline. Appends colored chips (recall/chart/deck/council/secure) showing each daemon's liveness + last-activity age, plus a reachability probe for the hosted launch-secure MCP. If the user has no statusline, scaffolds Claude Code's default base line first so the chips have something to attach to. Idempotent. Run /kit:deactivate-statusline to undo.
3
3
  ---
4
4
 
5
5
  # /kit:activate-statusline
@@ -9,11 +9,12 @@ Extends the user's existing `~/.claude/settings.json` statusline so MCP daemon h
9
9
  ## What it does
10
10
 
11
11
  1. Reads `~/.claude/settings.json` and checks for an existing `statusLine.command`.
12
- - If absent → reports plainly that the user must create their own statusline first. Do NOT scaffold one launch-kit only EXTENDS, never CREATES.
13
- 2. Writes two scripts under `~/.launchsecure/`:
12
+ - If absent → scaffolds `statusline-base.sh` (Claude Code's documented default base line: model · folder · context %) and stashes it as the original, so the chips render over a useful line instead of bailing. Creates `~/.claude/settings.json` if it doesn't exist.
13
+ 2. Writes scripts under `~/.launchsecure/`:
14
14
  - `statusline-mcp.sh` — emits the colored MCP chips.
15
- - `statusline-wrapper.sh` — runs the user's original command, then appends chips.
16
- 3. Replaces `statusLine.command` with the wrapper, stashing the original under `_launchKitStatuslineOriginal` inside the same settings.json (single source of truth, no sidecar state).
15
+ - `statusline-wrapper.sh` — runs the original (or scaffolded base) command, then appends chips.
16
+ - `statusline-base.sh` only when scaffolding; the default base line.
17
+ 3. Replaces `statusLine.command` with the wrapper, stashing the original (or scaffolded base) under `_launchKitStatuslineOriginal` inside the same settings.json (single source of truth, no sidecar state).
17
18
  4. Idempotent: if the wrapper is already wired, refreshes the chip scripts only.
18
19
 
19
20
  ## How to run
@@ -37,9 +38,9 @@ node packages/cli/dist/server/init-entry.js statusline activate [--show=...]
37
38
  If the user passed an argument to the slash command (e.g. `/kit:activate-statusline recall,chart`), forward it as `--show=$ARGUMENTS`.
38
39
 
39
40
  The command prints one of:
40
- - `✓ activated …` — newly wrapped
41
+ - `✓ activated …` — newly wrapped an existing statusline
42
+ - `✓ scaffolded …` — user had no statusline; scaffolded the default base line + chips
41
43
  - `✓ refreshed …` — already wrapped, scripts refreshed
42
- - `✗ no-statusline …` — user has no statusline; report this and stop, do not propose creating one
43
44
 
44
45
  ## After running
45
46
 
@@ -9,8 +9,8 @@ Reverses `/kit:activate-statusline`. Restores `~/.claude/settings.json`'s `statu
9
9
  ## What it does
10
10
 
11
11
  1. Reads `~/.claude/settings.json`.
12
- 2. If `_launchKitStatuslineOriginal` is present, copies it back to `statusLine` and deletes the stash key.
13
- 3. Removes `~/.launchsecure/statusline-wrapper.sh` and `~/.launchsecure/statusline-mcp.sh`.
12
+ 2. If `_launchKitStatuslineOriginal` is present, copies it back to `statusLine` and deletes the stash key. If the stash is launch-kit's own scaffolded base line (the user had no statusline before activation), removes `statusLine` entirely instead — back to no statusline.
13
+ 3. Removes `~/.launchsecure/statusline-wrapper.sh` and `~/.launchsecure/statusline-mcp.sh` (and `statusline-base.sh` if it was scaffolded).
14
14
  4. If `_launchKitStatuslineOriginal` is absent → reports "not active" and stops.
15
15
 
16
16
  ## How to run
@@ -0,0 +1,88 @@
1
+ ---
2
+ description: Read, search, and post to the LaunchSecure Communication Center (CapCom) via the launch-secure MCP. Use to find a comment/feedback/discussion by wording or author, list a channel, or post an update. Knows the default system tags and the resource_type↔channel mapping so you don't have to call tags_list or page-and-grep.
3
+ when_to_use: |
4
+ Auto-fire when the user wants to find, read, or post something in the LaunchSecure Communication Center / CapCom / Comm Hub. Trigger phrases: "find the feedback about X", "what did <person> say in comms", "search CapCom for Y", "read the feedback channel", "any discussions about Z", "post an update to comms", "what feedback did we get on W", "did anyone log X". Also auto-fire when an earlier attempt to find a comment failed and you reached for paging+grepping — that's the signal to use `q`/`author` server-side filters instead. Do NOT auto-fire for: writing a repo-backed long-form doc (use /kit:brief), drafting a daily standup (use /kit:standup), or filing a launch-kit bug/gap report (use kit_feedback_submit).
5
+ allowed-tools:
6
+ - mcp__launch-secure__communication_read
7
+ - mcp__launch-secure__communication_write
8
+ - mcp__launch-secure__communication_update
9
+ - mcp__launch-secure__communication_vote
10
+ - mcp__launch-secure__communication_delete
11
+ - mcp__launch-secure__tags_list
12
+ - mcp__launch-secure__members_list
13
+ ---
14
+
15
+ # /kit:comms
16
+
17
+ Find, read, and post in the LaunchSecure Communication Center ("CapCom" / Comm Hub) through the `launch-secure` MCP. This skill exists because the failure mode is predictable: people pull a whole channel and grep locally, miss a comment, and conclude "it's not there" or "I can't read it." Use the server-side filters instead.
18
+
19
+ `org_slug` / `project_slug` are **optional** — they default to the MCP's configured project (`.mcp.json` headers). Never ask the user for them unless a tool actually errors that they're missing.
20
+
21
+ ## The model that trips people up
22
+
23
+ The CapCom UI sub-tabs (**All · Comments · Discussions · Issues · Requirements · Feedback**) map to **`resource_type`**, NOT to tags:
24
+
25
+ | UI channel | `communication_read` filter |
26
+ |---|---|
27
+ | Comments | `resource_type: "comment"` |
28
+ | Discussions | `resource_type: "discussion"` |
29
+ | Issues | `resource_type: "issue"` |
30
+ | Requirements | `resource_type: "requirement"` |
31
+ | Feedback | `resource_type: "feedback"` |
32
+
33
+ **A comment can be `resource_type:"feedback"` and NOT carry the `feedback` tag** — beacon-submitted feedback gets both the resource type and the tag, but legacy / non-beacon / pre-ingest feedback often has only the resource type. So `tag:"feedback"` and `resource_type:"feedback"` return **different sets**. To read the Feedback channel, filter by `resource_type:"feedback"` — not the tag.
34
+
35
+ ## Finding one comment (don't page-and-grep)
36
+
37
+ `communication_read` filters compose with AND. The two that matter for search:
38
+
39
+ - **`q`** — case-insensitive substring across **title AND body**. This is how you find a comment by its wording. `q:"create deck"` finds it in one call; pulling 50 comments and grepping does not (and misses anything whose text is in `title` only, or that wasn't in your page).
40
+ - **`author`** — exact userId, or case-insensitive substring of the author's name/email. `author:"matt"` or `author:"hamann"`.
41
+
42
+ Examples:
43
+ - Find a feedback item by wording: `communication_read(resource_type:"feedback", q:"create deck")`
44
+ - Everything a person logged: `communication_read(author:"hamann")`
45
+ - A person's feedback only: `communication_read(resource_type:"feedback", author:"matt")`
46
+ - A discussion by topic: `communication_read(resource_type:"discussion", q:"runtime logs")`
47
+
48
+ If a search comes back empty, widen *before* concluding it's absent: drop `resource_type`, drop `tag`, try a shorter `q` stem (`"deck"` not `"create deck kit skill"`), try `author` alone. Only after the unfiltered `q`/`author` sweep is empty should you say it isn't there.
49
+
50
+ ## Default system tags
51
+
52
+ These ship on every org (from `tags_list`, `isSystem: true`) — you don't need to call `tags_list` to know them, only to get their **IDs** for a write. Numeric tags (e.g. `247`) are auto-created per work-item and are not in this list.
53
+
54
+ | Tag | Meaning |
55
+ |---|---|
56
+ | `announcement` | Team-wide announcement |
57
+ | `daily_update` | Daily standup or status update |
58
+ | `release` | Release note or changelog |
59
+ | `deployment` | Deployment note or rollback log |
60
+ | `decision` | Architectural or product decision |
61
+ | `feature` | Feature request or enhancement |
62
+ | `idea` | Feature idea or improvement suggestion |
63
+ | `feedback` | User-submitted feedback (via launch-kit beacon) |
64
+ | `bug` | Bug report or error |
65
+ | `blocker` | Blocking issue needing attention |
66
+ | `urgent` | Urgent priority item |
67
+ | `question` | Open question needing an answer |
68
+ | `review` | Code or design review thread |
69
+ | `documentation` | Documentation related |
70
+ | `Production` | Production incident, release, or hotfix |
71
+ | `staging` | Staging environment update |
72
+ | `a11y` | Accessibility concern |
73
+ | `ux` | UX or design issue |
74
+
75
+ To attach tags on a write you need their IDs: call `tags_list` once and map names → IDs (tag IDs are stable per org, names are not the API key).
76
+
77
+ ## Posting
78
+
79
+ `communication_write` requires `body` (plaintext — canonical for search/sync). Optional: `title`, `resource_type` (`comment` default; `discussion`/`feedback`/`requirement`/`issue`), `tag_ids` (from `tags_list`), `parent_id` (reply), `mentions` (user IDs — resolve via `members_list`; only ACTIVE org members notify), `fields` (structured JSONB, e.g. beacon feedback), `status` (discussions).
80
+
81
+ **Preview before you write.** CapCom posts are outward-facing and attributed to the user. Paste the full body in the terminal and wait for explicit "post it" before calling `communication_write` / `communication_update`. "Do it" / "go ahead" on an unrelated step does NOT authorize a Comm Hub write in the user's name. `communication_update` and `communication_delete` only work on the caller's own comments.
82
+
83
+ ## Constraints
84
+
85
+ - **Repo-backed long-form doc?** That's `/kit:brief` — it writes a file and the server syncs the comment; don't hand-post it here.
86
+ - **Daily standup?** That's `/kit:standup` — it has the voice/format conventions and the "since last push" diffing.
87
+ - **Bug/gap in launch-kit itself?** That's `kit_feedback_submit`, not a hand-written comment.
88
+ - **Reading is free; writing is gated.** Default to read/search freely; gate every write on an explicit go-ahead.
@@ -0,0 +1,88 @@
1
+ ---
2
+ description: Populate or refresh the local project-info snapshot (.claude/launch-kit/project-info.md) from LaunchSecure — members, providers/integrations, and environments — so Claude knows them every session without re-querying. Gitignored, CLAUDE.md-imported. Run after team/provider/env changes to refresh.
3
+ when_to_use: |
4
+ Auto-fire when the user wants to populate or refresh the project-info memory snapshot, or when the snapshot is stale. Trigger phrases: "refresh project info", "/kit:project-info", "update the project memory", "re-pull members/providers/environments", "who's on this project" (when the snapshot is empty/stale), "the project-info file says 'not populated'". Also auto-fire the first time you notice .claude/launch-kit/project-info.md exists but its Members/Providers/Environments sections are still the "_Not populated yet_" placeholder. Do NOT auto-fire for: a one-off "who's a member" question you can answer with a single members_list call (just call it), posting to comms (/kit:comms), or reading code structure (/kit:analyse).
5
+ allowed-tools:
6
+ - mcp__launch-secure__project_info
7
+ - mcp__launch-secure__members_list
8
+ - mcp__launch-secure__environments_list
9
+ - mcp__launch-secure__tags_list
10
+ - Read
11
+ - Write
12
+ - Bash
13
+ ---
14
+
15
+ # /kit:project-info
16
+
17
+ Regenerate `.claude/launch-kit/project-info.md` — the **local, git-ignored** snapshot of project facts (members, providers/integrations, environments) that Claude auto-loads every session via a CLAUDE.md `@`-import. `init` wires the file + import + gitignore and writes the identity block; **this skill fills and refreshes the cloud-sourced sections.**
18
+
19
+ It's a **cache, not a source of truth** — stamp it with the date and treat it as stale-able. Re-run after someone joins/leaves, a provider is connected, or an environment changes.
20
+
21
+ ## When the file/import isn't wired yet
22
+
23
+ `init` normally creates the file, the `@.claude/launch-kit/project-info.md` import in `CLAUDE.md`, and the `.gitignore` line. If the user never ran `init` (or hand-deleted them), ensure them yourself before writing:
24
+
25
+ ```bash
26
+ # 1. gitignore the snapshot (it can carry member names/emails — never commit it)
27
+ grep -qxF '.claude/launch-kit/project-info.md' .gitignore 2>/dev/null \
28
+ || printf '\n.claude/launch-kit/project-info.md\n' >> .gitignore
29
+
30
+ # 2. ensure CLAUDE.md imports it (Claude Code won't auto-load it otherwise)
31
+ grep -qF '@.claude/launch-kit/project-info.md' CLAUDE.md 2>/dev/null \
32
+ || printf '\n<!-- launch-kit:project-info -->\n@.claude/launch-kit/project-info.md\n<!-- /launch-kit:project-info -->\n' >> CLAUDE.md
33
+ ```
34
+
35
+ Don't duplicate either line — the `grep` guards keep it idempotent.
36
+
37
+ ## Gather (cloud LS — slugs default to the .mcp.json project)
38
+
39
+ Call these and keep only non-secret reference data:
40
+ 1. `mcp__launch-secure__project_info` → project name, counts, **active integration/provider flags**.
41
+ 2. `mcp__launch-secure__members_list` → member **name, email, role** (org + project role). Use the full list; note `mentionable`.
42
+ 3. `mcp__launch-secure__environments_list` → environment **slugs** + `defaultPullEnvSlug`.
43
+
44
+ Never write secret **values** — only provider *types*/names, env *slugs*, member identity. If a section legitimately has no data (e.g. no providers connected), write `_None connected._`, not a placeholder.
45
+
46
+ ## Write
47
+
48
+ Overwrite `.claude/launch-kit/project-info.md` (this skill owns the content; init only seeds it). Preserve the generated-header comment and the `## Identity` block if already present (re-derive Identity from `project_info` if you're regenerating from scratch). Shape:
49
+
50
+ ```markdown
51
+ # Project Info — <projectName>
52
+
53
+ <!-- launch-kit:generated — local, git-ignored snapshot. NOT a source of truth. -->
54
+ > Snapshot as of <YYYY-MM-DD>. Cache of LaunchSecure facts so Claude doesn't
55
+ > re-query each session. Re-run `/kit:project-info` after team/provider/env changes.
56
+
57
+ ## Identity
58
+ - **Org:** <orgSlug>
59
+ - **Project:** <projectName> (`<projectSlug>`)
60
+ - **Server:** <serverUrl>
61
+ - **Course:** <course>
62
+ - **Repo:** <repositoryUrl or —>
63
+
64
+ ## Members
65
+ | Name | Email | Org role | Project role |
66
+ |---|---|---|---|
67
+ | … | … | … | … |
68
+
69
+ ## Providers / integrations
70
+ - <Category>: <provider> (<connected|manual>)
71
+ _…or_ `_None connected._`
72
+
73
+ ## Environments
74
+ - `<slug>`<em> — default pull env</em> (mark the one matching defaultPullEnvSlug)
75
+ ```
76
+
77
+ Use the real values from the calls — no placeholders, no invented people (this is *this* project, cite real names/roles). Date the snapshot with today's date from context.
78
+
79
+ ## Output
80
+
81
+ After writing, print a one-line summary: `project-info refreshed — N members, M providers, K environments — snapshot <date>`. Mention it's git-ignored and loaded into context next session via the CLAUDE.md import.
82
+
83
+ ## Constraints
84
+
85
+ - **Cache, not truth.** Always date it and remind the user it can drift; this skill is the refresh path.
86
+ - **No secrets.** Provider/env *names and slugs* only — never pull or write secret values (that's `secrets_*`).
87
+ - **Local only.** The file is git-ignored on purpose (member PII). Don't commit it, don't move it out of `.claude/launch-kit/`.
88
+ - **Don't touch unrelated CLAUDE.md content.** Only ensure the single marked import block; never rewrite the user's CLAUDE.md.