@launchsecure/launch-kit 0.0.27 → 0.0.28

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 (45) hide show
  1. package/dist/beacon/beacon.mjs +1003 -440
  2. package/dist/beacon/beacon.mjs.map +1 -1
  3. package/dist/beacon/beacon.umd.js +45 -24
  4. package/dist/beacon/beacon.umd.js.map +1 -1
  5. package/dist/beacon/types/capture/events.d.ts +20 -0
  6. package/dist/beacon/types/capture/events.d.ts.map +1 -0
  7. package/dist/beacon/types/element.d.ts +1 -0
  8. package/dist/beacon/types/element.d.ts.map +1 -1
  9. package/dist/beacon/types/index.d.ts +2 -1
  10. package/dist/beacon/types/index.d.ts.map +1 -1
  11. package/dist/beacon/types/monitor/dom.d.ts +13 -0
  12. package/dist/beacon/types/monitor/dom.d.ts.map +1 -0
  13. package/dist/beacon/types/monitor/index.d.ts +19 -0
  14. package/dist/beacon/types/monitor/index.d.ts.map +1 -0
  15. package/dist/beacon/types/monitor/network.d.ts +12 -0
  16. package/dist/beacon/types/monitor/network.d.ts.map +1 -0
  17. package/dist/beacon/types/monitor/transport.d.ts +27 -0
  18. package/dist/beacon/types/monitor/transport.d.ts.map +1 -0
  19. package/dist/beacon/types/monitor/types.d.ts +117 -0
  20. package/dist/beacon/types/monitor/types.d.ts.map +1 -0
  21. package/dist/beacon/types/types.d.ts +10 -0
  22. package/dist/beacon/types/types.d.ts.map +1 -1
  23. package/dist/beacon/types/ui/drawer.d.ts +3 -1
  24. package/dist/beacon/types/ui/drawer.d.ts.map +1 -1
  25. package/dist/beacon/types/ui/monitor-panel.d.ts +19 -0
  26. package/dist/beacon/types/ui/monitor-panel.d.ts.map +1 -0
  27. package/dist/server/beacon-monitor-entry.js +353 -0
  28. package/dist/server/cli.js +50 -2
  29. package/dist/server/council-entry.js +0 -0
  30. package/dist/server/course-entry.js +246 -0
  31. package/dist/server/fb-wizard.js +0 -0
  32. package/dist/server/init-entry.js +394 -64
  33. package/dist/server/orbit-entry.js +187 -24
  34. package/package.json +24 -23
  35. package/scaffolds/ls-marketplace/.claude-plugin/marketplace.json +15 -0
  36. package/scaffolds/ls-marketplace/plugins/ls/.claude-plugin/plugin.json +28 -0
  37. package/scaffolds/ls-marketplace/plugins/ls/commands/activate-beacon.md +216 -0
  38. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-array.md +92 -0
  39. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-clear.md +68 -0
  40. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-pulse.md +80 -0
  41. package/scaffolds/ls-marketplace/plugins/ls/commands/beacon-scan.md +62 -0
  42. package/scaffolds/ls-marketplace/plugins/ls/commands/show-mcp-status.md +109 -0
  43. package/scaffolds/ls-marketplace/plugins/ls/commands/standup.md +177 -0
  44. package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
  45. package/scaffolds/recall-hook/scripts/ensure-recall.sh +69 -0
@@ -0,0 +1,216 @@
1
+ ---
2
+ description: Wire @launchsecure/launch-kit/beacon into this app — mounts the <launch-kit-beacon> Web Component in the root layout and scaffolds /api/feedback forwarding to LaunchSecure. Detects the framework, asks scope/endpoint/trigger decisions, then writes a real PR-shaped change.
3
+ ---
4
+
5
+ # Activate launch-kit-beacon
6
+
7
+ Integrate the in-app feedback widget into the current project. Beacon is a vanilla Web Component shipped via the `@launchsecure/launch-kit/beacon` subpath export. It captures a written description, severity (bug/idea/UX/a11y), a viewport screenshot with auto-numbered element pins, and runtime errors (`window.error` + `unhandledrejection`). Reports POST to a feedback endpoint that forwards into LaunchSecure as feedback comments in the Comm Hub.
8
+
9
+ This command does the integration as a normal dev cycle — read the layout, propose the diff, install deps, verify in the browser. It is NOT a one-shot script.
10
+
11
+ ## Preflight
12
+
13
+ 1. Confirm `.launch-secure.cred.config` exists at the repo root. If missing, stop and tell the user to run `npx launch-kit init` first — without the cred file the scaffolded `/api/feedback` route has no upstream credentials.
14
+ 2. Read `package.json` to detect framework:
15
+ - **Next.js App Router** — `next` in deps AND `app/` or `src/app/` directory present.
16
+ - **Next.js Pages Router** — `next` in deps AND `pages/` directory (no `app/`).
17
+ - **Vite + React** — `vite` + `react` in deps; no server route available (Vite is client-only — feedback POSTs will need a user-supplied endpoint).
18
+ - **Other** — Astro, SvelteKit, Nuxt, plain HTML, Express, etc. Print the integration snippet and stop; the user wires it themselves.
19
+ 3. Grep the source for `launch-kit-beacon` to check if beacon is already mounted. If found, ask the user whether to update the existing mount or abort.
20
+ 4. Use the `launch-chart` MCP (`detect_project_stack`, `read_graph` with `type: "page"`) to confirm the root layout file path before editing.
21
+
22
+ ## Decisions
23
+
24
+ Ask the user three questions before touching files:
25
+
26
+ 1. **Mount scope**
27
+ - (a) Whole app — mount in the root layout, shown on every route
28
+ - (b) Auth-gated only — mount in an authenticated layout group (e.g. `(authenticated)/layout.tsx`)
29
+ - (c) Specific route group — user picks the layout file
30
+
31
+ 2. **Feedback endpoint**
32
+ - (a) Scaffold `/api/feedback` forwarding to LaunchSecure (recommended). Reads `.launch-secure.cred.config` server-side, POSTs to `<serverUrl>/api/feedback` with the PAT in the `Authorization` header. Secrets stay server-side.
33
+ - (b) Skip — user will wire their own endpoint and set `endpoint=` attribute manually.
34
+
35
+ 3. **Trigger**
36
+ - (a) Default floating button, position `bottom-right`
37
+ - (b) User provides a custom trigger via `slot="trigger"`; widget renders no default button
38
+
39
+ Echo the chosen answers back before writing.
40
+
41
+ ## Implementation — Next.js App Router (v1 target)
42
+
43
+ ### 1. Add dependency
44
+
45
+ Check if `@launchsecure/launch-kit` is already in `dependencies` in `package.json`. If not, add it (pinned to a caret range of the current major). Then run install with the detected package manager (`pnpm install` / `npm install` / `yarn install` / `bun install`). Detect the PM from `packageManager` field first, then lockfile presence (pnpm-lock.yaml > yarn.lock > bun.lock > package-lock.json).
46
+
47
+ ### 2. Mount the widget
48
+
49
+ Web Components cannot SSR. The beacon module calls `customElements.define` at import time, which throws in a Node SSR environment. Mount via a small Client Component, not directly in the Server Component layout.
50
+
51
+ Create `src/app/_components/BeaconMount.tsx` (or `app/_components/BeaconMount.tsx` if the project uses `app/` at the repo root):
52
+
53
+ ```tsx
54
+ 'use client';
55
+
56
+ import { useEffect } from 'react';
57
+
58
+ export function BeaconMount() {
59
+ useEffect(() => {
60
+ void import('@launchsecure/launch-kit/beacon');
61
+ }, []);
62
+ return (
63
+ <launch-kit-beacon
64
+ endpoint="/api/feedback"
65
+ position="bottom-right"
66
+ />
67
+ );
68
+ }
69
+ ```
70
+
71
+ Then read the target layout file (root layout for scope (a), authenticated layout for (b), or user-specified layout for (c)) and add the mount near the end of `<body>`:
72
+
73
+ ```tsx
74
+ import { BeaconMount } from '@/app/_components/BeaconMount';
75
+ // ... inside the layout's return, just before </body>:
76
+ <BeaconMount />
77
+ ```
78
+
79
+ If the user picked trigger option (b) (custom trigger via slot), set `position="hidden"` on the element and pass children through:
80
+
81
+ ```tsx
82
+ <launch-kit-beacon endpoint="/api/feedback" position="hidden">
83
+ <button slot="trigger">Send feedback</button>
84
+ </launch-kit-beacon>
85
+ ```
86
+
87
+ ### 3. Add TypeScript declaration
88
+
89
+ Create `src/types/launch-kit-beacon.d.ts` (or `types/launch-kit-beacon.d.ts` at repo root if the project has no `src/`):
90
+
91
+ ```ts
92
+ import type { DetailedHTMLProps, HTMLAttributes } from 'react';
93
+
94
+ declare global {
95
+ namespace JSX {
96
+ interface IntrinsicElements {
97
+ 'launch-kit-beacon': DetailedHTMLProps<
98
+ HTMLAttributes<HTMLElement> & {
99
+ endpoint?: string;
100
+ position?: 'bottom-right' | 'bottom-left' | 'hidden';
101
+ theme?: 'auto' | 'light' | 'dark';
102
+ severities?: string;
103
+ },
104
+ HTMLElement
105
+ >;
106
+ }
107
+ }
108
+ }
109
+
110
+ export {};
111
+ ```
112
+
113
+ Confirm `tsconfig.json` includes the types directory (most Next.js setups already cover `src/**/*.d.ts` via the default `"include": ["**/*.ts", "**/*.tsx"]`). If not, add the file's path to `include`.
114
+
115
+ ### 4. Scaffold /api/feedback (if user chose endpoint option (a))
116
+
117
+ Create `src/app/api/feedback/route.ts` (or `app/api/feedback/route.ts`):
118
+
119
+ ```ts
120
+ import { readFileSync } from 'node:fs';
121
+ import { join } from 'node:path';
122
+
123
+ import type { NextRequest } from 'next/server';
124
+
125
+ interface Profile {
126
+ pat: string;
127
+ orgSlug: string;
128
+ projectSlug: string;
129
+ serverUrl: string;
130
+ }
131
+
132
+ interface CredConfig extends Partial<Profile> {
133
+ active?: string;
134
+ profiles?: Record<string, Profile>;
135
+ }
136
+
137
+ function readCred(): Profile {
138
+ // Resolved relative to the working directory of the Next.js server, which
139
+ // is the repo root in both `next dev` and `next start`. For production
140
+ // deploys (Vercel, Docker, etc.) where the cred file is not present,
141
+ // switch to env vars: LS_PAT, LS_ORG_SLUG, LS_PROJECT_SLUG, LS_SERVER_URL.
142
+ //
143
+ // Handles both shapes: nested multi-profile (written by `launch-course`)
144
+ // and legacy flat (written by older `launch-kit init` runs).
145
+ const p = join(process.cwd(), '.launch-secure.cred.config');
146
+ const raw = JSON.parse(readFileSync(p, 'utf-8')) as CredConfig;
147
+ const block = raw.profiles && raw.active ? raw.profiles[raw.active] : raw;
148
+ if (!block?.pat || !block.orgSlug || !block.projectSlug || !block.serverUrl) {
149
+ throw new Error('.launch-secure.cred.config is missing required fields');
150
+ }
151
+ return { pat: block.pat, orgSlug: block.orgSlug, projectSlug: block.projectSlug, serverUrl: block.serverUrl };
152
+ }
153
+
154
+ export async function POST(req: NextRequest) {
155
+ const cred = readCred();
156
+ const body = await req.text();
157
+ const upstream = await fetch(`${cred.serverUrl}/api/feedback`, {
158
+ method: 'POST',
159
+ headers: {
160
+ 'Content-Type': 'application/json',
161
+ Authorization: `Bearer ${cred.pat}`,
162
+ 'X-Org-Slug': cred.orgSlug,
163
+ 'X-Project-Slug': cred.projectSlug,
164
+ },
165
+ body,
166
+ });
167
+ return new Response(upstream.body, {
168
+ status: upstream.status,
169
+ headers: { 'Content-Type': upstream.headers.get('Content-Type') ?? 'application/json' },
170
+ });
171
+ }
172
+ ```
173
+
174
+ Tell the user explicitly: this works for local dev. For production, replace `readCred()` with `process.env.LS_PAT` / `LS_ORG_SLUG` / `LS_PROJECT_SLUG` / `LS_SERVER_URL` and set those env vars in their deployment platform.
175
+
176
+ ### 5. Verify
177
+
178
+ After all edits:
179
+ 1. Run install with the detected PM.
180
+ 2. Run `pnpm dev` (or detected dev command from `package.json` scripts).
181
+ 3. Open the app in the browser. Confirm the floating beacon button is visible bottom-right (or that the custom slot trigger renders, for option (b)).
182
+ 4. Click it, fill in a description, pick severity, capture a screenshot, submit.
183
+ 5. Confirm via the `launch-secure` MCP: call `communication_read` and look for a new feedback comment landing in the project's Comm Hub.
184
+ 6. Report the verification result to the user (which steps passed, anything that didn't).
185
+
186
+ ## Implementation — Next.js Pages Router
187
+
188
+ Same as App Router but adjust paths:
189
+ - Mount in `pages/_app.tsx` instead of `app/layout.tsx`. `_app.tsx` is already a Client Component, so the dynamic `import` workaround in step 2 is unnecessary — import `@launchsecure/launch-kit/beacon` at the top of the file directly.
190
+ - Feedback endpoint becomes `pages/api/feedback.ts` with a default-exported handler matching the Pages API signature (`req: NextApiRequest, res: NextApiResponse`).
191
+ - TypeScript declaration is identical.
192
+
193
+ ## Implementation — Vite + React
194
+
195
+ - Mount: add `import '@launchsecure/launch-kit/beacon';` to `src/main.tsx` (or whatever entry the Vite config points at), and add `<launch-kit-beacon endpoint="...">` inside the root `<App>` render. No SSR concerns — Vite is client-only.
196
+ - No server route — Vite does not provide one. Print the beacon snippet and tell the user they need either (a) to stand up their own backend with a forwarding handler matching the Next.js scaffold, or (b) to wait until LS exposes a public per-project ingest URL.
197
+ - TypeScript declaration is identical.
198
+
199
+ ## Implementation — other frameworks
200
+
201
+ For Astro, SvelteKit, Nuxt, Express, plain HTML, etc.: do NOT attempt to edit application source automatically. Print the integration snippet and the API forwarding handler skeleton (translated to Node `http`/Express), and tell the user the two changes they need to make in their stack. Frameworks vary too much to mechanize this correctly.
202
+
203
+ ## Idempotency
204
+
205
+ Re-running `/ls:activate-beacon`:
206
+ - If `BeaconMount.tsx` exists, leave it alone unless the user explicitly asks to regenerate.
207
+ - If `<launch-kit-beacon>` is already mounted in the layout, do NOT add a duplicate. Offer to update attributes (endpoint, position) or migrate trigger mode.
208
+ - If `app/api/feedback/route.ts` exists, do NOT overwrite. Diff against the scaffold template and ask whether to merge.
209
+ - If `@launchsecure/launch-kit` is already a dependency, skip the install step (but still run install if other files changed).
210
+
211
+ ## Notes for the assistant
212
+
213
+ - Use the `launch-chart` MCP for file discovery instead of grep/glob (per project CLAUDE.md). `read_graph` with `type: "page"` finds layout files; `grep_nodes` with a `launch-kit-beacon` pattern finds existing mounts.
214
+ - Use the `launch-secure` MCP `communication_read` to verify a test feedback landed in the Comm Hub after the user submits.
215
+ - Show the diff before applying edits. The user reviews and approves like any PR.
216
+ - This is the user's application code. Default to the smallest possible edit — do not "improve" surrounding code, restyle the layout, or refactor unrelated files.
@@ -0,0 +1,92 @@
1
+ ---
2
+ description: Show the array of launch-beacon monitor sessions in `.launchsecure/` — which is most recent, how many events each has, last event time, suspected liveness. Use to confirm a session is being recorded, find an old session to inspect, or audit disk usage. Read-only.
3
+ ---
4
+
5
+ # /ls:beacon-array
6
+
7
+ Liveness + inventory across every `launch-beacon monitor` session this repo has recorded — one row per beacon in the array.
8
+
9
+ `$ARGUMENTS` may be `full` for an expanded report. Empty → terse one-line-per-session summary.
10
+
11
+ ## Preflight
12
+
13
+ List the NDJSON files. If none, say so plainly:
14
+
15
+ ```bash
16
+ ls -t .launchsecure/beacon-*.ndjson 2>/dev/null || { echo "No beacon sessions found in .launchsecure/. Start one with: npx launch-beacon monitor"; exit 0; }
17
+ ```
18
+
19
+ If the listing is empty (the command above succeeded but produced no output because `2>/dev/null` swallowed the error and no files matched), check explicitly:
20
+
21
+ ```bash
22
+ SESSIONS=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null)
23
+ test -n "$SESSIONS" || { echo "No beacon sessions found in .launchsecure/. Start one with: npx launch-beacon monitor"; exit 0; }
24
+ ```
25
+
26
+ ## Per-session facts to collect
27
+
28
+ For each session file (newest first), gather:
29
+ - **token** — slice between `beacon-` and `.ndjson` in the filename
30
+ - **events** — `wc -l < <file>`
31
+ - **last_ts** — parse the last JSON line's `.ts` field (epoch ms). Use a one-liner like:
32
+ ```bash
33
+ tail -n 1 "$F" | sed -n 's/.*"ts":\([0-9]*\).*/\1/p'
34
+ ```
35
+ - **last_kind** — same trick on `.kind` from the last line
36
+ - **mtime** — `stat -f "%m" "$F"` on macOS or `stat -c "%Y" "$F"` on Linux. Use whichever your shell supports; fall back to `ls -lt` parse if neither.
37
+ - **size** — file size in bytes (`stat` again; or `wc -c < "$F"`)
38
+
39
+ Use the mtime to compute **age** ("just now", "2m ago", "1h ago"). Do the arithmetic yourself (current epoch minus mtime); don't shell out for time formatting.
40
+
41
+ ## Liveness heuristic
42
+
43
+ Mark a session as **active** if its mtime is within the last 5 seconds — that's the maximum interval the receiver flushes batches. Otherwise **idle**. Sessions older than 30 minutes are **stale** (the receiver enforces a 30-min cap, so anything older is from a previous monitor run).
44
+
45
+ ## Default output (no arguments)
46
+
47
+ ```
48
+ .launchsecure/
49
+ ● 8f3c2a91 247 events click (just now) ACTIVE
50
+ a1b2c3d4 89 events error (12m ago) idle
51
+ 2557799f 1,247 events route (2h ago) stale
52
+
53
+ 3 sessions, 1 active.
54
+ ```
55
+
56
+ Rules:
57
+ - Glyph: `●` (filled) for active, blank for idle/stale.
58
+ - Columns: token (8 chars) — events (right-aligned) — last event "kind (age)" — status word.
59
+ - Summary line: total count + how many active.
60
+ - Plain text, monospace alignment.
61
+
62
+ ## Full output (`/ls:beacon-array full`)
63
+
64
+ Same per-session block as default, but expand each into a block with extra fields:
65
+
66
+ ```
67
+ ● 8f3c2a91 — ACTIVE
68
+ file: .launchsecure/beacon-8f3c2a91.ndjson
69
+ size: 42.1 KB
70
+ events: 247
71
+ started: 2026-05-21T07:12:33Z (8m ago)
72
+ last event: 2026-05-21T07:20:51Z (just now)
73
+ last kind: click
74
+ kinds: click 142, fetch 71, route 12, error 3, dialog 9, probe 10
75
+
76
+ a1b2c3d4 — idle
77
+ file: .launchsecure/beacon-a1b2c3d4.ndjson
78
+ ...
79
+ ```
80
+
81
+ `kinds:` is a histogram from `grep -oE '"kind":"[a-z]+"' <file> | sort | uniq -c | sort -rn`. Format as `kind1 N1, kind2 N2, …` newest-first by count.
82
+
83
+ `started:` = first line's `.ts`; `last event:` = last line's `.ts`.
84
+
85
+ End with the same summary line as default.
86
+
87
+ ## Constraints
88
+
89
+ - **Read-only.** No deletion, no rotation, no auto-cleanup.
90
+ - **Fast.** Default view should be sub-second even with many session files. Don't full-parse JSON — line counts + first/last line sed is enough.
91
+ - **Plain text.** No markdown tables, no fenced blocks in the actual output.
92
+ - **Don't suggest cleanup.** That's `/ls:beacon-clear`'s job. Stale sessions are informational, not an error.
@@ -0,0 +1,68 @@
1
+ ---
2
+ description: Wipe launch-beacon monitor session NDJSON files. Default clears only the latest session (so you can start a clean repro); pass `all` to remove every `.launchsecure/beacon-*.ndjson`. Always shows what will be deleted and asks for confirmation. Destructive.
3
+ ---
4
+
5
+ # /ls:beacon-clear
6
+
7
+ Clean slate before a fresh repro. The receiver appends to the same NDJSON file across reconnects of the same session, so an existing file accumulates noise from earlier attempts — clearing first makes the new stream easier to reason about.
8
+
9
+ Parse `$ARGUMENTS`:
10
+ - empty → clear the most recent session file only
11
+ - `all` → clear every `.launchsecure/beacon-*.ndjson`
12
+ - a specific token or filename → clear that one file (must match a real path)
13
+
14
+ ## Preflight
15
+
16
+ List candidate files. If none, say so and stop:
17
+
18
+ ```bash
19
+ SESSIONS=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null)
20
+ test -n "$SESSIONS" || { echo "No beacon sessions found in .launchsecure/. Nothing to clear."; exit 0; }
21
+ ```
22
+
23
+ Decide the **target set** based on `$ARGUMENTS`:
24
+ - empty → first line of `$SESSIONS` (the newest)
25
+ - `all` → all lines of `$SESSIONS`
26
+ - otherwise → resolve to a single path (try `.launchsecure/beacon-<arg>.ndjson` first, then the literal arg). If it doesn't exist or isn't inside `.launchsecure/`, refuse with a clear message.
27
+
28
+ ## Refusal rule
29
+
30
+ Refuse with a clear message if:
31
+ - the target set is empty
32
+ - any target path resolves outside `.launchsecure/` (defence against `..` injection from `$ARGUMENTS`)
33
+ - the active monitor session is being written *right now* (mtime within the last 5 seconds) — print a one-line warning and ask the user to stop the monitor first, e.g.:
34
+ ```
35
+ ⚠ .launchsecure/beacon-8f3c2a91.ndjson was written 2s ago — looks active.
36
+ Stop the receiver (Ctrl+C in the launch-beacon monitor terminal) and re-run /ls:beacon-clear.
37
+ ```
38
+ The user can still force by passing the token explicitly as the argument — but never silently nuke an actively-written file.
39
+
40
+ ## Confirmation
41
+
42
+ Print what's about to be deleted and ask before doing it.
43
+
44
+ ```
45
+ About to delete 1 file:
46
+ .launchsecure/beacon-a1b2c3d4.ndjson 89 events, 12m ago
47
+
48
+ Confirm? (y/N)
49
+ ```
50
+
51
+ For `all`, list every file with its size + age. Don't truncate the list — the user should see all of it.
52
+
53
+ Wait for explicit `y`/`yes`. Anything else → abort with `Cancelled. No files were deleted.`
54
+
55
+ ## Delete
56
+
57
+ `rm` each target. After deletion, print a one-line summary:
58
+
59
+ ```
60
+ ✓ deleted 1 file (89 events freed).
61
+ ```
62
+
63
+ ## Constraints
64
+
65
+ - **Destructive — always confirm.** Even if `$ARGUMENTS` is `all`, ask first.
66
+ - **Scope-locked to `.launchsecure/`.** Reject anything outside that directory, even if the user passes an absolute path. We never delete files we didn't write.
67
+ - **No undo.** NDJSON is local-only; we don't ship recall integration for it (recall is for source files). Be explicit in the confirmation message.
68
+ - **Don't stop the monitor server.** This command only clears files. The receiver keeps running and will reopen the same file on its next write — which is fine, the file just starts empty again.
@@ -0,0 +1,80 @@
1
+ ---
2
+ description: Show the most recent error from the active launch-beacon monitor session, plus the N events that preceded it (default 10). Answers "what was happening when it broke" without scrolling through the full stream. Read-only.
3
+ ---
4
+
5
+ # /ls:beacon-pulse
6
+
7
+ The "what happened just before this error" command — a single pulse, freezing the moment the beacon caught a failure. When a bug fires, the actual story is usually the chain of events leading up to it: the click that triggered a state change, the failed fetch that left auth in a bad state, the route change that mounted the wrong component.
8
+
9
+ Parse `$ARGUMENTS` as one optional integer — the count of preceding events to include. Default 10. Cap at 100.
10
+
11
+ ## Preflight
12
+
13
+ Same as `/ls:beacon-scan` — find the latest NDJSON; if none, stop:
14
+
15
+ ```bash
16
+ LATEST=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null | head -1)
17
+ test -n "$LATEST" || { echo "No beacon sessions found. Start one with: npx launch-beacon monitor"; exit 0; }
18
+ ```
19
+
20
+ ## Locate the most recent error
21
+
22
+ Errors are events with `"kind":"error"` or `"kind":"unhandledrejection"`. Find the line number of the LAST such line in the file:
23
+
24
+ ```bash
25
+ ERR_LINE=$(grep -nE '"kind":"(error|unhandledrejection)"' "$LATEST" | tail -1 | cut -d: -f1)
26
+ test -n "$ERR_LINE" || { echo "No errors in the current session. Use /ls:beacon-scan to browse all events."; exit 0; }
27
+ ```
28
+
29
+ ## Pull the window
30
+
31
+ `N` is the user-supplied count (default 10). Read the file lines from `max(1, ERR_LINE-N)` through `ERR_LINE`:
32
+
33
+ ```bash
34
+ N="${1:-10}"
35
+ START=$(( ERR_LINE - N ))
36
+ [ "$START" -lt 1 ] && START=1
37
+ sed -n "${START},${ERR_LINE}p" "$LATEST"
38
+ ```
39
+
40
+ That's your input. The error itself is the last line; everything before is context.
41
+
42
+ ## Output
43
+
44
+ Render a **timeline** with the error visually separated at the bottom:
45
+
46
+ ```
47
+ session: .launchsecure/beacon-<token>.ndjson
48
+ window: 10 events before error at line 247
49
+
50
+ 12:34:51 click button.submit-btn
51
+ 12:34:51 fetch POST 401 /api/sessions (120ms) FAILED
52
+ 12:34:51 fetch GET 401 /api/me (45ms) FAILED
53
+ 12:34:52 route /login → /dashboard (pushState)
54
+ ...
55
+
56
+ ╴╴╴╴ ERROR ╴╴╴╴
57
+ 12:34:53 error Cannot read properties of undefined (reading 'orgSlug')
58
+ at apps/Console.tsx:42:18
59
+ stack: Console.render
60
+ React.renderWithHooks
61
+ React.beginWork
62
+ ```
63
+
64
+ Format rules:
65
+ - One line per event, same SUMMARY format as `/ls:beacon-scan`.
66
+ - The error block at the end gets the message + (truncated) stack frames if present.
67
+ - Separator above the error is the visual cue.
68
+
69
+ After the timeline, write **one short paragraph** of analysis: what does the chain *look* like? Common patterns:
70
+ - 401s → error referencing user/org → "auth expired or org context missing"
71
+ - click → no observable effect → click again → error → "first click handler crashed silently; second click landed on something else"
72
+ - route change → error → "component on the new route blew up during initial render"
73
+
74
+ Don't dive into a fix — name the suspected proximate cause, suggest one concrete next step (which file to read, which probe to add, which `/ls:beacon-scan <kind>` to drill into).
75
+
76
+ ## Constraints
77
+
78
+ - **Read-only.**
79
+ - **Most recent error only.** If the user wants an earlier one, they can clear the session (`/ls:beacon-clear`) and reproduce, or grep manually.
80
+ - **Plain text.** Same monospace conventions as `/ls:beacon-scan`.
@@ -0,0 +1,62 @@
1
+ ---
2
+ description: Scan recent events from the active launch-beacon monitor session. Defaults to last 50 events across all kinds; pass a kind (`error`, `click`, `fetch`, `route`, `dialog`, `probe`, etc.) to filter, and/or a numeric limit. Reads `.launchsecure/beacon-*.ndjson` — the file written by `launch-beacon monitor`. Read-only.
3
+ ---
4
+
5
+ # /ls:beacon-scan
6
+
7
+ Recent runtime events captured by a `launch-beacon monitor` session. Use this as the first step when investigating something that just happened in the browser — clicks, failed network calls, errors, route changes, probe() calls, dialog mount/unmount.
8
+
9
+ Parse `$ARGUMENTS` as up to two tokens (space-separated):
10
+ - A **kind filter**: one of `error`, `unhandledrejection`, `fetch`, `xhr`, `click`, `mousedown`, `route`, `dialog`, `probe`. Anything else is treated as a limit.
11
+ - A **limit**: integer. Default 50.
12
+
13
+ Examples:
14
+ - `/ls:beacon-scan` → last 50 events of any kind
15
+ - `/ls:beacon-scan error` → last 50 errors only
16
+ - `/ls:beacon-scan click 20` → last 20 click events
17
+ - `/ls:beacon-scan 100` → last 100 events of any kind
18
+
19
+ ## Preflight
20
+
21
+ Find the most recent NDJSON file via Bash. If none exist, say so plainly and stop — there's nothing to scan.
22
+
23
+ ```bash
24
+ LATEST=$(ls -t .launchsecure/beacon-*.ndjson 2>/dev/null | head -1)
25
+ test -n "$LATEST" || { echo "No beacon sessions found in .launchsecure/. Start one with: npx launch-beacon monitor"; exit 0; }
26
+ echo "session: $LATEST"
27
+ ```
28
+
29
+ ## Scan
30
+
31
+ If no kind filter, `tail -n <limit> "$LATEST"`.
32
+
33
+ If a kind filter is set, `grep '"kind":"<kind>"' "$LATEST" | tail -n <limit>`. The events are NDJSON, one per line — `grep` over the literal `"kind":"X"` substring is safe because the `kind` field is always the first or near-first key serialised by the beacon client.
34
+
35
+ Capture the raw JSON lines as the input to your analysis.
36
+
37
+ ## Output
38
+
39
+ Group events visually by **time** (most recent last — chronological order matches the user's intuition for "what happened"). For each event, render one line:
40
+
41
+ ```
42
+ HH:MM:SS KIND SUMMARY
43
+ ```
44
+
45
+ Where SUMMARY is a one-liner pulled from the event body:
46
+ - **error / unhandledrejection** → `message` (truncate ≤ 80 chars)
47
+ - **fetch / xhr** → `METHOD status url (durationMs)` — flag `FAILED` if `failed:true`
48
+ - **click / mousedown** → `target.selector` and, when `hitMatchesTarget === false`, also append `(occluded by <hitTarget.selector>)` — that's exactly the diagnostic the user is here for
49
+ - **route** → `from → to (via)`
50
+ - **dialog** → `<action> <selector>` (e.g. `mount dialog#xyz` or `unmount section[role=dialog]`)
51
+ - **probe** → `<label>: <truncated JSON>`
52
+
53
+ After the timeline, if anything looks suspicious (clusters of failed network calls, a click followed by no observable effect, a `hitMatchesTarget:false` event, an unhandled rejection), call it out in **one short paragraph** at the end. Don't analyze every event — only surface the standouts.
54
+
55
+ If the buffer is empty after filtering, say so: `No events match that filter in <session>.`
56
+
57
+ ## Constraints
58
+
59
+ - **Read-only.** Never delete, modify, or write to the NDJSON file. Wiping is `/ls:beacon-clear`.
60
+ - **Always use the latest session by default.** If the user wants a specific session, they'll pass it as a third token — accept any of `<token>`, `<filename>`, or absolute path, and resolve to a valid `.launchsecure/beacon-*.ndjson` path before scanning. Reject with a clear error if it doesn't exist.
61
+ - **Plain text output.** Monospace alignment beats markdown tables here. The user is reading this fast during a debug loop.
62
+ - **Don't speculate on root cause.** Surface anomalies; let the user direct the next query (often: `/ls:beacon-pulse` for context around the latest error).
@@ -0,0 +1,109 @@
1
+ ---
2
+ description: Show the health of launch-kit's daemon-style MCPs (today just launch-recall). Default output is a terse one-line summary per daemon; pass `full` for expanded details — PID, pidfile, last snapshot, debounce, shadow repo size, recent activity. Read-only; never mutates state.
3
+ ---
4
+
5
+ # /ls:show-mcp-status
6
+
7
+ Reports the liveness and recent activity of launch-kit's long-running MCP daemons. The recall watcher is the only daemon today; this command is structured so additional daemons can be added without changing its interface.
8
+
9
+ Read $ARGUMENTS to decide output verbosity:
10
+ - empty (`/ls:show-mcp-status`) → terse one-liner per daemon. Goal: fits in one or two visual lines.
11
+ - `full` (`/ls:show-mcp-status full`) → expanded report per daemon. Goal: enough detail to diagnose health problems.
12
+
13
+ ## Preflight
14
+
15
+ 1. Verify the launch-recall MCP is wired by checking whether `mcp__launch-recall__recall_status` (or `mcp__local-launch-recall__recall_status` for dev repos) is callable. If neither is available, say so plainly: "launch-recall MCP not wired in this project — nothing to report" and stop.
16
+ 2. Pick whichever recall MCP is available. Prefer the project-level published one (`mcp__launch-recall__*`) unless only the local dev one is wired.
17
+
18
+ ## Daemons
19
+
20
+ Today: **launch-recall** (the shadow-git file watcher).
21
+
22
+ Structure your output so adding more daemons later is a copy-paste — one section per daemon, same shape.
23
+
24
+ ## Default output (no arguments)
25
+
26
+ Call `mcp__launch-recall__recall_status`. Format as ONE LINE per daemon, then a single summary line. Example:
27
+
28
+ ```
29
+ recall ✓ alive pid 12456 last snap 2m ago
30
+
31
+ All daemons healthy.
32
+ ```
33
+
34
+ Or if dead:
35
+
36
+ ```
37
+ recall ✗ dead pidfile missing/stale
38
+
39
+ 1 daemon down. Run /ls:show-mcp-status full for details, or restart the watcher (kill any stale pid, then either start a new Claude Code session — the SessionStart hook respawns it — or run `node packages/cli/dist/server/recall-entry.js watch` from this repo).
40
+ ```
41
+
42
+ Rules for the default view:
43
+ - One line per daemon — name, glyph, status word, key metric.
44
+ - `✓` (green) for alive, `✗` (red) for dead.
45
+ - "X ago" for timestamps — relative time, easier to scan than ISO.
46
+ - Summary line on a fresh line at the end. If anything is wrong, include a one-sentence recovery hint.
47
+ - No JSON, no PID files paths, no debug info — that's for `full`.
48
+
49
+ ## Full output (`/ls:show-mcp-status full`)
50
+
51
+ For each daemon, call BOTH `recall_status` AND `recall_report`. Combine into a per-daemon block:
52
+
53
+ ```
54
+ recall — launch-recall watcher (shadow-git backup)
55
+
56
+ Status: ✓ alive
57
+ PID: 12456
58
+ Watch tree: /Users/prajyot/Documents/Work/AutomateWithUs/launchsecure-v2
59
+ Shadow repo: /Users/prajyot/Documents/Work/AutomateWithUs/launchsecure-v2/.recall/repo.git
60
+
61
+ Last snapshot: 2026-05-21T12:05:45+05:30 (2m ago)
62
+ Total snaps: 1,247
63
+ Shadow size: 1.4 MB
64
+ Debounce: 3000ms
65
+ Retention: keepLast 5000, maxAgeDays 30
66
+
67
+ Recent activity (last 5 snaps):
68
+ a1b2c3d 2m ago snap 2026-05-21T06:35:45Z
69
+ 9f8e7d6 14m ago snap 2026-05-21T06:21:42Z
70
+ 2557799 53m ago snap 2026-05-21T05:52:35Z
71
+ 8349edb 17h ago snap 2026-05-20T13:36:39Z
72
+ e5a05cf 17h ago snap 2026-05-20T13:32:05Z
73
+
74
+ All daemons healthy.
75
+ ```
76
+
77
+ If a daemon is dead, the block should still appear but with status `✗ dead` and as many fields as can be derived from the on-disk shadow repo + pidfile. Include a concrete recovery command at the end of the block (the same SessionStart restart path from the default view, plus the manual command for impatient users).
78
+
79
+ Rules for the full view:
80
+ - Two-column field labels — visually aligned, easier to skim.
81
+ - Times: ISO timestamp + relative ("2m ago") in parens.
82
+ - Sizes: human-readable (KB/MB), not bytes.
83
+ - Last 5 snapshots only — newer first.
84
+ - One blank line between daemon blocks (for when there are more than one).
85
+ - Summary line at the end, same as the default view.
86
+
87
+ ## Health classification
88
+
89
+ Use these rules to decide alive vs dead vs degraded:
90
+
91
+ - **alive**: `recall_status.running === true` AND `lastSnapshotAt` is within the last 6 hours (heuristic — for an active repo, snaps happen every few minutes; 6h of silence suggests the watcher is wedged or no files have changed, both worth surfacing).
92
+ - **dead**: `recall_status.running === false` OR `recall_status` errors out.
93
+ - **degraded** (still print as alive but note it): `running === true` BUT `lastSnapshotAt` is older than 6h. Add a single inline note `(no activity in 6h — possibly idle or wedged)`.
94
+
95
+ Don't over-warn — if a repo has genuinely been idle (e.g. you opened it for the first time today after a week), a 6h+ gap is normal. The note is informational, not an error.
96
+
97
+ ## Constraints
98
+
99
+ - **Read-only.** This command never mutates state, never restarts watchers, never modifies config. Recovery is a recommendation in the output, not an automatic action.
100
+ - **Fast.** Default view should be sub-second. The MCP tools are cheap; don't add scrubbing or heavy formatting.
101
+ - **Plain text.** No markdown headers, no fenced blocks in the actual output — Claude Code renders them but the human eye scans monospace plain text fastest.
102
+ - **Output what the user asked for.** If they ran the default, don't dump the full report "just in case." If they ran `full`, don't abbreviate.
103
+
104
+ ## Notes for the assistant
105
+
106
+ - Use the wired `launch-recall` MCP tools — do not shell out to `node packages/cli/dist/server/recall-entry.js status` even though it works. Going through MCP makes this command portable across projects that have launch-kit init'd via npx vs dev-build.
107
+ - When listing recent snaps, use the `recentSnapshots` array from `recall_report`. It's already sorted newest-first; just truncate.
108
+ - For "X ago" formatting, do the math yourself. Don't fetch any time service.
109
+ - If you find yourself wanting to add features beyond status display (restart the watcher, prune snaps, etc.) — stop. Those belong in separate `/ls:*` commands. This one is a status pane.