@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.
- package/dist/beacon/beacon.mjs +308 -298
- package/dist/beacon/beacon.mjs.map +1 -1
- package/dist/beacon/beacon.umd.js +6 -6
- package/dist/beacon/beacon.umd.js.map +1 -1
- package/dist/beacon/types/internal/screenshot.d.ts.map +1 -1
- package/dist/chart-client/assets/index-CWJFFDPu.css +1 -0
- package/dist/chart-client/index.html +2 -2
- package/dist/client/assets/index-CTzFcfGV.css +32 -0
- package/dist/client/index.html +2 -2
- package/dist/council-client/assets/index-ArgRc5mN.css +1 -0
- package/dist/council-client/index.html +2 -2
- package/dist/deck-client/assets/{_baseUniq-CgW32Gdk.js → _baseUniq-BZP7n41F.js} +1 -1
- package/dist/deck-client/assets/{arc-D-Mg9gvM.js → arc-31biU3Az.js} +1 -1
- package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-CdTsXsgl.js → architectureDiagram-Q4EWVU46-DHg6Ss--.js} +1 -1
- package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-mwTneYyB.js → blockDiagram-DXYQGD6D-CUdblaWk.js} +1 -1
- package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-C4R8IbjO.js → c4Diagram-AHTNJAMY-MfAO5lak.js} +1 -1
- package/dist/deck-client/assets/channel-BBkRLdnC.js +1 -0
- package/dist/deck-client/assets/{chunk-4BX2VUAB-ZWuRIUwb.js → chunk-4BX2VUAB-DQ1MrGgN.js} +1 -1
- package/dist/deck-client/assets/{chunk-4TB4RGXK-PNHX10sF.js → chunk-4TB4RGXK-BUJtZ7jO.js} +1 -1
- package/dist/deck-client/assets/{chunk-55IACEB6-CD9MUgPr.js → chunk-55IACEB6-BdSnXB6g.js} +1 -1
- package/dist/deck-client/assets/{chunk-EDXVE4YY-C_CpORb3.js → chunk-EDXVE4YY-94yZIUI8.js} +1 -1
- package/dist/deck-client/assets/{chunk-FMBD7UC4-Bg5RoVC-.js → chunk-FMBD7UC4-PnZ9v6ey.js} +1 -1
- package/dist/deck-client/assets/{chunk-OYMX7WX6-DhTwgQwd.js → chunk-OYMX7WX6-DXrWNOsV.js} +1 -1
- package/dist/deck-client/assets/{chunk-QZHKN3VN-C5VLMaFa.js → chunk-QZHKN3VN-CsIGIDKX.js} +1 -1
- package/dist/deck-client/assets/{chunk-YZCP3GAM-NAGHy4Sr.js → chunk-YZCP3GAM-DVkBO9tn.js} +1 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-DFCaeF-7.js +1 -0
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-DFCaeF-7.js +1 -0
- package/dist/deck-client/assets/clone-GCEVRScB.js +1 -0
- package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-CpUczjZk.js → cose-bilkent-S5V4N54A-m126Oh3b.js} +1 -1
- package/dist/deck-client/assets/{dagre-KV5264BT-BOvb07MG.js → dagre-KV5264BT-C2aig8U5.js} +1 -1
- package/dist/deck-client/assets/{diagram-5BDNPKRD-BPxwTiC-.js → diagram-5BDNPKRD-CKpoRfGn.js} +1 -1
- package/dist/deck-client/assets/{diagram-G4DWMVQ6-Dz_gsHgx.js → diagram-G4DWMVQ6-Cjh115Ep.js} +1 -1
- package/dist/deck-client/assets/{diagram-MMDJMWI5-B7z-oVTW.js → diagram-MMDJMWI5-DKlBv_2L.js} +1 -1
- package/dist/deck-client/assets/{diagram-TYMM5635-CAIAglLQ.js → diagram-TYMM5635-CdBh4cEn.js} +1 -1
- package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BiViTWF3.js → erDiagram-SMLLAGMA-56pn_93p.js} +1 -1
- package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-DYVemp0H.js → flowDiagram-DWJPFMVM-BtV3M5xJ.js} +1 -1
- package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-Chc1Iyu1.js → ganttDiagram-T4ZO3ILL-DTIsC6Zg.js} +1 -1
- package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B7eFgaj5.js → gitGraphDiagram-UUTBAWPF-CJYeyCLe.js} +1 -1
- package/dist/deck-client/assets/{graph-CKaIoNwb.js → graph-BDvMu1Ss.js} +1 -1
- package/dist/deck-client/assets/index-D4eSxcBn.css +1 -0
- package/dist/deck-client/assets/{index-BRawc7RA.js → index-QnGVE9PZ.js} +83 -83
- package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BxsVq7vO.js → infoDiagram-42DDH7IO-BWyKJnpW.js} +1 -1
- package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DAM7vPwa.js → ishikawaDiagram-UXIWVN3A-DXYkdO3T.js} +1 -1
- package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-Xe20Nf7R.js → journeyDiagram-VCZTEJTY-C2zBr-J5.js} +1 -1
- package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-DS8YguzB.js → kanban-definition-6JOO6SKY-CdoYLS4Z.js} +1 -1
- package/dist/deck-client/assets/{layout-DKMBpzR-.js → layout-vOnxnCQU.js} +1 -1
- package/dist/deck-client/assets/{linear-DTNtBg5h.js → linear-B0J0WCGz.js} +1 -1
- package/dist/deck-client/assets/{min-C4DrxCcA.js → min-B0AXlT9L.js} +1 -1
- package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-B4nEtsw5.js → mindmap-definition-QFDTVHPH-oAybLedr.js} +1 -1
- package/dist/deck-client/assets/{pieDiagram-DEJITSTG-BzHdGNu5.js → pieDiagram-DEJITSTG-BjHyHxGk.js} +1 -1
- package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-CaX0SD4-.js → quadrantDiagram-34T5L4WZ-dtluDZXs.js} +1 -1
- package/dist/deck-client/assets/{requirementDiagram-MS252O5E-QeG4p2ni.js → requirementDiagram-MS252O5E-Cq8l7bOl.js} +1 -1
- package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BoAwgAj-.js → sankeyDiagram-XADWPNL6-C1Vih91z.js} +1 -1
- package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-Dn4pYYgu.js → sequenceDiagram-FGHM5R23-CYkd7oQK.js} +1 -1
- package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-Is6KRmQV.js → stateDiagram-FHFEXIEX-CtyG8wBK.js} +1 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BLyKWfcN.js +1 -0
- package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-v64IZGuY.js → timeline-definition-GMOUNBTQ-DZIxSyd1.js} +1 -1
- package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-noh9eouF.js → vennDiagram-DHZGUBPP-Ct4JVRDM.js} +1 -1
- package/dist/deck-client/assets/{wardley-RL74JXVD-cJ_1is2S.js → wardley-RL74JXVD-V29ycxOW.js} +1 -1
- package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-DxR4j737.js → wardleyDiagram-NUSXRM2D-D-Ua6Cmi.js} +1 -1
- package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-B26vodaL.js → xychartDiagram-5P7HB3ND-BPCOuRVl.js} +1 -1
- package/dist/deck-client/index.html +2 -2
- package/dist/server/beacon-monitor-entry.js +106 -24
- package/dist/server/chart-serve.js +544 -247
- package/dist/server/cli.js +743 -324
- package/dist/server/council-entry.js +16 -3
- package/dist/server/council-serve.js +15 -2
- package/dist/server/deck-mcp-entry.js +270 -108
- package/dist/server/deck-serve.js +101 -23
- package/dist/server/fb-wizard.js +0 -0
- package/dist/server/graph-mcp-entry.js +866 -357
- package/dist/server/init-entry.js +152 -25
- package/dist/server/orbit-entry.js +91 -7
- package/dist/server/radar-docker-init-entry.js +0 -0
- package/dist/server/radar-entrypoint-entry.js +0 -0
- package/dist/server/radar-teardown-entry.js +0 -0
- package/dist/server/recall-entry.js +94 -12
- package/dist/server/rover-entry.js +44 -1
- package/package.json +23 -22
- package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +8 -7
- package/scaffolds/ls-marketplace/plugins/kit/commands/deactivate-statusline.md +2 -2
- package/scaffolds/ls-marketplace/plugins/kit/skills/comms/SKILL.md +88 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/project-info/SKILL.md +88 -0
- package/scaffolds/ls-marketplace/plugins/kit/skills/slides/SKILL.md +118 -0
- package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
- package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
- package/scaffolds/statusline/statusline-base.sh +20 -0
- package/scaffolds/statusline/statusline-mcp.sh +68 -19
- package/scaffolds/statusline/statusline-wrapper.sh +12 -9
- package/dist/chart-client/assets/index-B6rR0CWx.css +0 -1
- package/dist/client/assets/index-D6uX1lQe.css +0 -32
- package/dist/council-client/assets/index-CleYLarJ.css +0 -1
- package/dist/deck-client/assets/channel-CuSee7GO.js +0 -1
- package/dist/deck-client/assets/classDiagram-6PBFFD2Q-_kTisqzs.js +0 -1
- package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-_kTisqzs.js +0 -1
- package/dist/deck-client/assets/clone-kb3zkY60.js +0 -1
- package/dist/deck-client/assets/index-55P73aS_.css +0 -1
- package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-Cy45Ttqq.js +0 -1
- /package/dist/chart-client/assets/{index-C_xCi3gW.js → index-Dzlj-oCj.js} +0 -0
- /package/dist/client/assets/{index-CRecYFUA.js → index-tTg_ezUF.js} +0 -0
- /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,
|
|
288
|
-
const pid = Number((0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
428
|
+
if ((0, import_node_fs2.existsSync)(cfgPath)) {
|
|
429
429
|
try {
|
|
430
|
-
config = JSON.parse((0,
|
|
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,
|
|
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,
|
|
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
|
|
554
|
+
void import_node_fs2.statSync;
|
|
555
555
|
}
|
|
556
|
-
var import_node_child_process2,
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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 →
|
|
13
|
-
2. Writes
|
|
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
|
|
16
|
-
|
|
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.
|