@launchsecure/launch-kit 0.0.31 → 0.0.33

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 (95) hide show
  1. package/dist/beacon/beacon.mjs +550 -521
  2. package/dist/beacon/beacon.mjs.map +1 -1
  3. package/dist/beacon/beacon.umd.js +9 -9
  4. package/dist/beacon/beacon.umd.js.map +1 -1
  5. package/dist/beacon/types/internal/pick-mode-overlay.d.ts.map +1 -1
  6. package/dist/beacon/types/internal/picker.d.ts.map +1 -1
  7. package/dist/beacon/types/internal/pin-popover.d.ts.map +1 -1
  8. package/dist/beacon/types/internal/selector.d.ts.map +1 -1
  9. package/dist/chart-client/assets/{index-B__ARB8k.js → index-DFu2xIrM.js} +2 -2
  10. package/dist/chart-client/assets/index-DpKO9p0s.css +1 -0
  11. package/dist/chart-client/index.html +2 -2
  12. package/dist/client/assets/{index-h8kMzVtG.js → index-Cbw6bVdx.js} +2 -2
  13. package/dist/client/assets/index-Dv6dD2zY.css +32 -0
  14. package/dist/client/index.html +2 -2
  15. package/dist/council-client/assets/index-AqQ9Sei6.css +1 -0
  16. package/dist/council-client/assets/{index-CWaDcsFR.js → index-CAsmGTzg.js} +2 -2
  17. package/dist/council-client/index.html +2 -2
  18. package/dist/deck-client/assets/{_baseUniq-DdHaBFYO.js → _baseUniq-BiVx0WO_.js} +1 -1
  19. package/dist/deck-client/assets/{arc-D98e_18X.js → arc-DGMkiEzS.js} +1 -1
  20. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-DNFZzh-4.js → architectureDiagram-Q4EWVU46-Y2WRmHtk.js} +1 -1
  21. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-DeQvGUdX.js → blockDiagram-DXYQGD6D-_Lbfu5BQ.js} +1 -1
  22. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-B6ekZf1n.js → c4Diagram-AHTNJAMY-CTqpYTBX.js} +1 -1
  23. package/dist/deck-client/assets/channel-DB6LxW_l.js +1 -0
  24. package/dist/deck-client/assets/{chunk-4BX2VUAB-9aDWymq2.js → chunk-4BX2VUAB-liEIbPHs.js} +1 -1
  25. package/dist/deck-client/assets/{chunk-4TB4RGXK-DtKQqaI7.js → chunk-4TB4RGXK-CCc6lYvL.js} +1 -1
  26. package/dist/deck-client/assets/{chunk-55IACEB6-COy9hEae.js → chunk-55IACEB6-D02jJUR2.js} +1 -1
  27. package/dist/deck-client/assets/{chunk-EDXVE4YY-D_f861An.js → chunk-EDXVE4YY-BFmGMbLD.js} +1 -1
  28. package/dist/deck-client/assets/{chunk-FMBD7UC4-CmuA5UKn.js → chunk-FMBD7UC4-6wFLOVcJ.js} +1 -1
  29. package/dist/deck-client/assets/{chunk-OYMX7WX6-vT8z8D-0.js → chunk-OYMX7WX6-Bnr8RiBf.js} +1 -1
  30. package/dist/deck-client/assets/{chunk-QZHKN3VN-CTlwwg-R.js → chunk-QZHKN3VN-Ct82MksJ.js} +1 -1
  31. package/dist/deck-client/assets/{chunk-YZCP3GAM-C44yr620.js → chunk-YZCP3GAM-BXmN1diQ.js} +1 -1
  32. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-g944ZyG8.js +1 -0
  33. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-g944ZyG8.js +1 -0
  34. package/dist/deck-client/assets/clone-DiIRH1pI.js +1 -0
  35. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-DBB2J2nL.js → cose-bilkent-S5V4N54A-CmQCT-mH.js} +1 -1
  36. package/dist/deck-client/assets/{dagre-KV5264BT-DxDTYbKl.js → dagre-KV5264BT-DDdSa9EX.js} +1 -1
  37. package/dist/deck-client/assets/{diagram-5BDNPKRD-DByWrWd1.js → diagram-5BDNPKRD-Bccks2xJ.js} +1 -1
  38. package/dist/deck-client/assets/{diagram-G4DWMVQ6-B8B6ddMq.js → diagram-G4DWMVQ6-CPPNgxmQ.js} +1 -1
  39. package/dist/deck-client/assets/{diagram-MMDJMWI5-BMUZ2PWK.js → diagram-MMDJMWI5-KrD300pS.js} +1 -1
  40. package/dist/deck-client/assets/{diagram-TYMM5635-Bk9e8BB-.js → diagram-TYMM5635-DefnLuQf.js} +1 -1
  41. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-DcOSwSol.js → erDiagram-SMLLAGMA-DI9FfnFP.js} +1 -1
  42. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-DI-4BR0F.js → flowDiagram-DWJPFMVM-twKyd3Fx.js} +1 -1
  43. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-BeZuXBoU.js → ganttDiagram-T4ZO3ILL-Wau3jhBr.js} +1 -1
  44. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-Bcki__f-.js → gitGraphDiagram-UUTBAWPF-D9GgYXwb.js} +1 -1
  45. package/dist/deck-client/assets/{graph-CifKx6G1.js → graph-BhNLzyXS.js} +1 -1
  46. package/dist/deck-client/assets/index-B-YQq5b5.css +1 -0
  47. package/dist/deck-client/assets/{index-CB-qlwRT.js → index-BtQBaQ7s.js} +76 -76
  48. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-CReN1nFN.js → infoDiagram-42DDH7IO-TylGlSG-.js} +1 -1
  49. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-CDF_VLN_.js → ishikawaDiagram-UXIWVN3A-DAT8icpg.js} +1 -1
  50. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-DwgGrNVB.js → journeyDiagram-VCZTEJTY-D3v_XL72.js} +1 -1
  51. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-DB_zohh5.js → kanban-definition-6JOO6SKY-DNUOBiNr.js} +1 -1
  52. package/dist/deck-client/assets/{layout-DFfX1O3z.js → layout-COfodgwF.js} +1 -1
  53. package/dist/deck-client/assets/{linear-CtKb4EXj.js → linear-DmTsuIvK.js} +1 -1
  54. package/dist/deck-client/assets/{min-DCRRwUZv.js → min-BW1F7i1D.js} +1 -1
  55. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-D0QBOiFe.js → mindmap-definition-QFDTVHPH-CErFzKWl.js} +1 -1
  56. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-CD-EV5WB.js → pieDiagram-DEJITSTG-DW5F757o.js} +1 -1
  57. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-B-JXZ8xI.js → quadrantDiagram-34T5L4WZ-B1S2-TfI.js} +1 -1
  58. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-D2_OK5Dp.js → requirementDiagram-MS252O5E-BY5BAR-5.js} +1 -1
  59. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BbBJqVSC.js → sankeyDiagram-XADWPNL6-CE1Cp9HS.js} +1 -1
  60. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-Db8A-Rkk.js → sequenceDiagram-FGHM5R23-IaHnbKye.js} +1 -1
  61. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-DGJnanjS.js → stateDiagram-FHFEXIEX-CwPJm9hU.js} +1 -1
  62. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-DQYa2M1q.js +1 -0
  63. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-BRkr6T4w.js → timeline-definition-GMOUNBTQ-DVFGGSgN.js} +1 -1
  64. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-d0rsTqFo.js → vennDiagram-DHZGUBPP-C1194MJi.js} +1 -1
  65. package/dist/deck-client/assets/{wardley-RL74JXVD-2t7cMqdS.js → wardley-RL74JXVD-CHZiUbBa.js} +1 -1
  66. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-DzboAsHh.js → wardleyDiagram-NUSXRM2D-hpwdFfGj.js} +1 -1
  67. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CgTP9u2V.js → xychartDiagram-5P7HB3ND-DYkotwy8.js} +1 -1
  68. package/dist/deck-client/index.html +2 -2
  69. package/dist/server/cli.js +91 -13
  70. package/dist/server/council-entry.js +0 -0
  71. package/dist/server/deck-mcp-entry.js +83 -40
  72. package/dist/server/deck-serve.js +54 -20
  73. package/dist/server/fb-wizard.js +0 -0
  74. package/dist/server/init-entry.js +952 -290
  75. package/dist/server/radar-docker-init-entry.js +239 -0
  76. package/dist/server/radar-entrypoint-entry.js +99 -0
  77. package/dist/server/radar-teardown-entry.js +477 -0
  78. package/dist/server/recall-entry.js +4 -1
  79. package/package.json +22 -23
  80. package/scaffolds/ls-marketplace/plugins/kit/commands/activate-statusline.md +5 -5
  81. package/scaffolds/ls-marketplace/plugins/kit/skills/diagram/SKILL.md +27 -5
  82. package/scaffolds/ls-marketplace/plugins/kit/skills/ship/SKILL.md +274 -0
  83. package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +0 -0
  84. package/scaffolds/recall-hook/scripts/ensure-recall.sh +0 -0
  85. package/scaffolds/statusline/statusline-mcp.sh +82 -2
  86. package/scaffolds/statusline/statusline-wrapper.sh +8 -1
  87. package/dist/chart-client/assets/index-CDIhdgWg.css +0 -1
  88. package/dist/client/assets/index-CfW4n40I.css +0 -32
  89. package/dist/council-client/assets/index-CZim6x1u.css +0 -1
  90. package/dist/deck-client/assets/channel-DmR7Tyyt.js +0 -1
  91. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-Bl4ozQWs.js +0 -1
  92. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-Bl4ozQWs.js +0 -1
  93. package/dist/deck-client/assets/clone-BAy58j24.js +0 -1
  94. package/dist/deck-client/assets/index-BlTlhxFW.css +0 -1
  95. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CR7riiab.js +0 -1
@@ -0,0 +1,274 @@
1
+ ---
2
+ description: End-to-end ship flow — runs /kit:deploy-check, prints the exact commit list, pushes the named branch only after explicit confirmation, then appends a structured entry to .launchsecure/ship-log.ndjson describing what shipped. Pushing to a deploy-tracked branch (default master) triggers Vercel automatically; this skill never calls `vercel deploy` directly. No LS Comm Hub post — the local log is the source of truth and can be republished later by a separate skill.
3
+ ---
4
+
5
+ # /kit:ship
6
+
7
+ Compose `/kit:deploy-check` + `git push` + local ship-log append into one gated workflow. The skill is the human checklist for "I'm shipping now" — same checks a careful human would run, encoded so they cannot be skipped or reordered.
8
+
9
+ The ship log at `.launchsecure/ship-log.ndjson` is the durable record of what shipped, when, and by whom. Each successful ship appends one JSON object. A future skill (`/kit:ship-publish` or similar) can tail this log and emit an internal activity update / Comm Hub post / changelog page — but that's a separate concern. This skill writes the log; it does not publish.
10
+
11
+ Hard rule from project memory: **never push commits the user didn't explicitly name**, and **pushing to master = auto-deploy** — so this skill always asks per-action before pushing, even when invoked with arguments. There is no `--yes-i-mean-it` flag.
12
+
13
+ Parse `$ARGUMENTS`:
14
+
15
+ - (empty) — full flow on the current branch → its upstream (resolved via `git rev-parse --abbrev-ref @{u}` or, missing that, `origin/<current-branch>`).
16
+ - **--to=&lt;branch&gt;** — push to a different remote branch (e.g. `--to=staging-mirror`). The skill never creates a new remote branch silently — if the target doesn't exist on origin, surface that and ask.
17
+ - **--dry-run** — run deploy-check + build the ship-log entry preview, but do NOT push and do NOT append to the log. Useful for "what would shipping look like right now?".
18
+ - **--note=&lt;text&gt;** — free-form human note attached to the log entry's `note` field. Useful for hotfix context, rollout caveats, or named reviewer.
19
+ - **--skip-check=&lt;list&gt;** — forwarded verbatim to `/kit:deploy-check --skip=<list>`. Surface skipped checks in the final report; do not let `--skip-check=build` slip through silently.
20
+ - **--quick** — forwarded to deploy-check (skips the slow `build` step). Refuse if the target is a deploy-tracked branch (`master` or whatever the repo's default is) — for prod, build must run.
21
+
22
+ Examples:
23
+
24
+ - `/kit:ship` → check, confirm, push current branch to its upstream, append ship-log entry.
25
+ - `/kit:ship --dry-run` → check + preview the log entry only; no push, no log write.
26
+ - `/kit:ship --to=master` from `implementation` → cross-branch merge-and-deploy flow (see "Cross-branch ship" below).
27
+ - `/kit:ship --note="hotfix for feedback widget 500s"` → push + log entry with the note attached.
28
+
29
+ ## Preflight
30
+
31
+ 1. `git rev-parse --is-inside-work-tree` — abort if not a git repo.
32
+ 2. Resolve current branch and the **deploy-target branch**:
33
+ - If `--to=` given, use it.
34
+ - Else `git rev-parse --abbrev-ref @{u}` (the branch's tracked upstream).
35
+ - Else fall back to `origin/<current>` and warn that no upstream is set.
36
+ 3. Resolve the **deploy-tracked branch list** for "is this a prod push?" gating:
37
+ - Read `git symbolic-ref refs/remotes/origin/HEAD --short` (strip `origin/`) → that's the repo's default; treat as deploy-tracked.
38
+ - Always treat `master` and `main` as deploy-tracked if they exist on origin.
39
+ - If the resolved target is in this list, set `IS_PROD_PUSH=true`. Used to escalate confirmations and refuse `--quick` / `--skip-check=build`.
40
+ 4. Print the scope upfront — the user should never wonder what's about to happen:
41
+ ```
42
+ ship: <current-branch> → <target-branch> (prod: yes|no)
43
+ ```
44
+ 5. Stash check — if `git status --porcelain` shows uncommitted changes, refuse with `✗ working tree not clean — commit, stash, or discard before shipping`. Shipping with dirty state is never the right move; the deploy-check skill is lenient about it because it's read-only, this skill is not.
45
+
46
+ ## Step 1 — Gate (run /kit:deploy-check)
47
+
48
+ Invoke `/kit:deploy-check` against the resolved target. Forward `--quick` / `--skip-check=` / `--target=`. Do NOT re-implement any check here — single source of truth lives in `deploy-check/SKILL.md`.
49
+
50
+ Verdict handling:
51
+
52
+ - **NO-GO** → abort the ship. Print the failing checks verbatim from deploy-check. Tell the user what to fix. Do not offer to "force ship".
53
+ - **GO WITH CAVEATS** → surface the warnings, then ask:
54
+ > "deploy-check returned GO WITH CAVEATS (<N> warnings listed above). Continue with ship? Reply `yes` to continue, `cancel` to abort."
55
+ - **GO** → continue silently to step 2.
56
+
57
+ Hard rules:
58
+
59
+ - If `IS_PROD_PUSH=true` and the user passed `--quick` or `--skip-check=build`, refuse before running deploy-check: `✗ --quick / --skip-check=build are not allowed for prod pushes. Re-run without them.`
60
+ - If deploy-check's `migration_safety` row is anything other than ✓, treat as NO-GO regardless of overall verdict. Migration corruption incidents are why the project has the three-layer migration rule in CLAUDE.md — this skill enforces it.
61
+
62
+ ## Step 2 — Show the exact push payload
63
+
64
+ Print, verbatim, what's about to be pushed. This is the user's last chance to recognise an unexpected commit (per project memory: `push X` never includes other local commits).
65
+
66
+ ```
67
+ About to push <current-branch> → origin/<target-branch>:
68
+
69
+ <sha> <subject> <author-relative-time>
70
+ <sha> <subject> <author-relative-time>
71
+
72
+
73
+ <N> commits, <M> files changed (<+adds>/<-dels>)
74
+ ```
75
+
76
+ Generated from:
77
+
78
+ - `git log --pretty=format:' %h %s (%ar, %an)' origin/<target>..HEAD`
79
+ - `git diff --shortstat origin/<target>...HEAD`
80
+
81
+ If the list is empty → abort: `nothing to push — local branch is at or behind origin/<target>`.
82
+
83
+ If any commit author is not the current `git config user.email`, surface a `⚠ <N> commits authored by someone else (<emails>)` line — common in shared branches but worth flagging once.
84
+
85
+ ## Step 3 — Migration backup gate
86
+
87
+ If `git diff origin/<target>...HEAD --name-only -- prisma/migrations/` returns any files, surface:
88
+
89
+ ```
90
+ ⚠ This push includes <N> new migration(s):
91
+ - prisma/migrations/<dir>/migration.sql
92
+
93
+
94
+ Backup story:
95
+ - CI: .github/workflows/backup-on-migration.yml runs pg_dump server-side once the migration lands on <target-branch>.
96
+ - Local: if you have already applied locally, you've used scripts/migrate-with-backup.sh (per CLAUDE.md). If not, the CI workflow is the safety net.
97
+ ```
98
+
99
+ Then ask:
100
+
101
+ > "Migration push detected. Type `understood` to continue, or `cancel` to abort."
102
+
103
+ This is a deliberate friction point — typing a word is more honest than `y`. Do not accept `yes` here; require `understood`.
104
+
105
+ ## Step 4 — Push confirmation
106
+
107
+ Ask **exactly**:
108
+
109
+ - If `IS_PROD_PUSH=false`:
110
+ > "Push <N> commits to origin/<target-branch>? Reply `yes` to push, `cancel` to abort."
111
+ - If `IS_PROD_PUSH=true`:
112
+ > "Push <N> commits to origin/<target-branch>. This is a prod-tracked branch — Vercel will deploy automatically. Reply `ship it` to push, `cancel` to abort."
113
+
114
+ Accept exactly `yes` / `ship it` (case-insensitive). Anything else → treat as cancel. **Never** accept silence, `ok`, `sure`, free-form approval. If `--dry-run`, skip this step entirely.
115
+
116
+ On confirm: `git push origin <current-branch>:<target-branch>`. Stream stdout. If the push fails (non-fast-forward, hook reject, auth) — surface the error verbatim, do not retry, do not `--force`.
117
+
118
+ After a successful push to a deploy-tracked branch, surface the Vercel deployment lookup hint:
119
+
120
+ ```
121
+ Pushed. Vercel deploy will pick up the latest commit on <target-branch>.
122
+ → check status: `vercel ls --prod` or watch the Vercel dashboard
123
+ (do NOT run `vercel deploy` from here — that bypasses the GitHub→Vercel flow and double-deploys)
124
+ ```
125
+
126
+ ## Step 5 — Append ship-log entry
127
+
128
+ After a successful push, append exactly one JSON line to `.launchsecure/ship-log.ndjson`. This is the durable record of the ship event — the source of truth a future `/kit:ship-publish` (or any reader) consumes to emit activity feeds, changelogs, or Comm Hub posts.
129
+
130
+ If `--dry-run`, build the entry and show it in a fenced block but do NOT write it. If the push failed in step 4, do NOT write the entry (the log only records successful ships).
131
+
132
+ ### File location & format
133
+
134
+ - Path: `.launchsecure/ship-log.ndjson` (sibling of `.launchsecure/graphs/`, `.launchsecure/beacon-*.ndjson`).
135
+ - Format: NDJSON — one JSON object per line, append-only, never rewrite or compact.
136
+ - If the file does not exist, create it. Do NOT add a header line; readers should tolerate empty file = zero ship events.
137
+ - Ensure `.launchsecure/ship-log.ndjson` is gitignored — on first run, check `.gitignore` for `.launchsecure/ship-log.ndjson` or a covering pattern (`.launchsecure/*.ndjson`); if absent, surface a one-line warning suggesting the user add it. Do NOT silently edit `.gitignore` — that's a separate user decision per project memory on extending vs adding things.
138
+
139
+ ### Entry schema
140
+
141
+ Every entry conforms to schema `v: 1`. Forward-compatible reader rule: ignore unknown fields, never break on missing optional fields.
142
+
143
+ ```json
144
+ {
145
+ "v": 1,
146
+ "shipId": "<ulid or `${ts}-${shortSha}`>",
147
+ "ts": "2026-05-29T12:45:00.000Z",
148
+ "branch": "implementation",
149
+ "target": "master",
150
+ "isProdPush": true,
151
+ "author": { "name": "Prajyot", "email": "prajyot@automatewith.us" },
152
+ "commits": [
153
+ { "sha": "abc1234", "subject": "feat(ship): add ship skill", "author": "Prajyot", "ts": "2026-05-29T12:30:00.000Z" }
154
+ ],
155
+ "stats": { "files": 3, "insertions": 187, "deletions": 0 },
156
+ "migrations": ["prisma/migrations/2026_05_29_add_ship_log/migration.sql"],
157
+ "envVarsAdded": ["FEED_BACKEND_URL"],
158
+ "deployCheck": {
159
+ "verdict": "GO",
160
+ "warnings": ["lint: 12 warnings"],
161
+ "skipped": []
162
+ },
163
+ "themes": [
164
+ { "scope": "ship", "outcomes": ["End-to-end ship skill with deploy-check gate and append-only ship log"] }
165
+ ],
166
+ "summary": "Shipped 1 commit to master — ship skill scaffold",
167
+ "note": "<--note value, or null>",
168
+ "pushedAt": "2026-05-29T12:45:00.000Z",
169
+ "vercelDeployHint": "auto-triggered on push to master"
170
+ }
171
+ ```
172
+
173
+ Field sources:
174
+
175
+ - `shipId` — generate `${pushedAt-as-yyyymmdd-hhmmss}-${shortSha-of-HEAD}` for human-greppable IDs. ULID is fine if a generator is available.
176
+ - `ts` / `pushedAt` — current ISO timestamp at the moment the entry is written (just after `git push` succeeds).
177
+ - `branch` / `target` / `isProdPush` — from preflight (step 1).
178
+ - `author` — `git config user.name` + `git config user.email`.
179
+ - `commits` — `git log --pretty=format:'%H%x09%s%x09%an%x09%aI' origin/<target>..HEAD` (use the pre-push range — these are the commits that just landed).
180
+ - `stats` — `git diff --shortstat origin/<target>...<sha>` where `<sha>` is the new HEAD.
181
+ - `migrations` — `git diff --name-only origin/<target>...HEAD -- prisma/migrations/` (if step 3 fired, surface those exact paths; else empty array).
182
+ - `envVarsAdded` — pulled from deploy-check's `env_coverage` row, parsed from its `detail`. If deploy-check was skipped or didn't run that check, `[]`.
183
+ - `deployCheck.verdict` / `warnings` / `skipped` — from the deploy-check report in step 1.
184
+ - `themes` — group commits by conventional-commit scope (same default rule as `/kit:standup` step 3). Each theme: `{ scope, outcomes: [<outcome-bullets translated from commit subjects>] }`. Outcomes are short product-facing sentences, NOT raw subject lines. If commits lack scopes and there are ≥20 changed files across ≥5 dirs, escalate to launch-chart module grouping (same rule as standup step 3); otherwise bucket into `{scope: "misc", outcomes: […]}`.
185
+ - `summary` — one-line human-readable. Format: `Shipped <N> commit(s) to <target>${migrations ? " — includes migration" : ""}${themes ? " — " + topTheme : ""}`.
186
+ - `note` — verbatim `--note=` value, or `null` if absent.
187
+ - `vercelDeployHint` — `"auto-triggered on push to <target>"` if `isProdPush`, else `"no auto-deploy (target is not deploy-tracked)"`.
188
+
189
+ ### Preview + confirm
190
+
191
+ After step 4's push succeeds, build the entry and show it pretty-printed in a fenced code block:
192
+
193
+ ```
194
+ About to append to .launchsecure/ship-log.ndjson:
195
+
196
+ {
197
+ "v": 1,
198
+ "shipId": "20260529-124500-abc1234",
199
+
200
+ }
201
+
202
+ Append? Reply `yes` to write, `edit summary` to tweak the summary or themes, `skip` to ship without logging, or `cancel` to abort the append.
203
+ ```
204
+
205
+ - `yes` / `y` → append the entry as a single minified line (`JSON.stringify(entry) + "\n"`) using `>> .launchsecure/ship-log.ndjson`. Confirm with `appended shipId=<id>`.
206
+ - `edit summary` → ask what to change (summary text, theme grouping, note), redraft the entry, re-show, re-ask.
207
+ - `skip` → do not write. Print the entry once more so the user can manually save it elsewhere if they want. Ship is still considered successful — the push landed.
208
+ - `cancel` → do not write. Same as `skip` but no echo. **Do not** attempt to revert the push — surface clearly: `Push already landed on origin/<target>; cancel only stops the log append.`
209
+
210
+ ### Atomicity
211
+
212
+ Append must be atomic — partial writes corrupt the NDJSON file. Use:
213
+
214
+ ```
215
+ echo "<minified-json>" >> .launchsecure/ship-log.ndjson
216
+ ```
217
+
218
+ NOT `cat ... > tmp && mv tmp ...` (rewrite is wrong for an append-only log). NOT multi-line JSON. One line, one ship, one append.
219
+
220
+ If the write fails (disk full, permission), surface the entry verbatim in chat so the user can save it manually, and exit non-zero. Do NOT retry.
221
+
222
+ ## Cross-branch ship (--to=master from a feature branch)
223
+
224
+ When the user runs `/kit:ship --to=master` from a non-master branch, the flow is **push the current branch's commits onto master**, which is a fast-forward / merge, not a normal push. Handle this carefully:
225
+
226
+ 1. After deploy-check passes, before step 2, verify the current branch is ahead of `origin/master` (`git rev-list --left-right --count origin/master...HEAD` → left=behind, right=ahead). If behind, abort: `✗ <current> is behind origin/master by <N>; rebase or merge master first`.
227
+ 2. The push command becomes `git push origin <current-branch>:master`. Make sure step 2's "About to push" preamble shows this asymmetric refspec so the user sees it.
228
+ 3. On non-fast-forward reject from origin, do NOT suggest `--force`. Surface and stop.
229
+
230
+ ## Constraints
231
+
232
+ - **Never auto-push and auto-log in one breath.** Always two explicit confirmations (step 4 push, step 5 append). The `--dry-run` flag exists instead of bundling.
233
+ - **Never call `vercel deploy` CLI.** Deploys come from Vercel's GitHub integration on push to deploy-tracked branches. Calling the CLI double-deploys and bypasses the gate.
234
+ - **Never `git push --force` / `--force-with-lease`.** If a push fails, the user investigates.
235
+ - **Never `git push <branch>` without an explicit refspec.** Always `<local-branch>:<remote-branch>` so the destination is unambiguous in the printed command (and in shell history).
236
+ - **Never bypass migration_safety.** A ✓ on the deploy-check migration_safety row is the gate; anything else is NO-GO even if the overall verdict isn't.
237
+ - **Single source of truth for checks.** Do not duplicate `/kit:deploy-check` logic inline; invoke it.
238
+ - **Append-only log.** Never edit, delete, or rewrite past entries in `ship-log.ndjson`. Corrections happen via a new entry referencing the previous `shipId` (e.g. `correctionOf: "<prev shipId>"` — readers handle the merge).
239
+ - **Log only successful ships.** If `git push` fails, do NOT write an entry. The log records what actually landed on the remote, not what was attempted.
240
+ - **No publishing from this skill.** This skill writes the log; it does NOT post to LS Comm Hub, does NOT update activity feeds, does NOT trigger webhooks. Those are downstream consumers (future `/kit:ship-publish` or a server-side tailer).
241
+ - **Honest about deploy state.** This skill ends when the push completes and the log entry lands. It does NOT wait for Vercel to finish building, does NOT verify the prod URL is up, does NOT roll back. If the user needs deploy-monitoring, point them at `vercel ls --prod` or the Vercel dashboard.
242
+ - **Dry-run is truly dry.** `--dry-run` must NOT call `git push`, must NOT write to `ship-log.ndjson`. The preview is shown in chat only.
243
+
244
+ ## Idempotency
245
+
246
+ Re-running `/kit:ship` after a successful run:
247
+
248
+ - Step 2 will show "nothing to push" if the previous push landed cleanly — the natural no-op. No new log entry results.
249
+ - Each successful ship is a separate line in `ship-log.ndjson`. There is no per-day or per-branch coalescing — that's a reader's job. If a hotfix ships 10 minutes after a feature, both entries exist independently.
250
+ - The preview is never persisted before confirmation; cancelling at any step leaves no partial entry behind.
251
+
252
+ ## Reading the log
253
+
254
+ For ad-hoc inspection while the publisher skill doesn't exist yet:
255
+
256
+ ```
257
+ # last ship
258
+ tail -n 1 .launchsecure/ship-log.ndjson | jq
259
+
260
+ # ships to master in the last 7 days
261
+ jq -c 'select(.target == "master" and (.ts | fromdateiso8601) > (now - 7*86400))' .launchsecure/ship-log.ndjson
262
+
263
+ # count ships per day
264
+ jq -r '.ts[:10]' .launchsecure/ship-log.ndjson | sort | uniq -c
265
+ ```
266
+
267
+ These are documented for the user, not for this skill — `/kit:ship` itself never reads back the log.
268
+
269
+ ## Notes for the assistant
270
+
271
+ - The user has explicit project-memory rules against unauthorised pushes and dumb reverts. Treat every confirmation as load-bearing — don't paraphrase the prompt wording, don't accept ambiguous approval.
272
+ - "Ship" is the user's verb for "I want this in production." If the target isn't actually deploy-tracked, the skill should still work but should say so clearly in the scope line (step 4 phrasing changes).
273
+ - The ship log is the durable artifact. Future skills will read from it — keep the schema stable, additive only. Bump `v:` when you make a breaking schema change and update this file's schema block in the same commit.
274
+ - This skill assumes `/kit:deploy-check` exists. If missing (older launch-kit install), surface that as a preflight error pointing to `npx @launchsecure/launch-kit init`. No dependency on `/kit:standup` anymore — the log replaces the Comm Hub post.
File without changes
@@ -4,11 +4,17 @@
4
4
  # Composes into any existing statusline via the launch-kit wrapper.
5
5
  #
6
6
  # Usage:
7
- # statusline-mcp.sh # all known chips (recall, chart, deck, council)
7
+ # statusline-mcp.sh # all known chips (recall, chart, deck, council, secure)
8
8
  # statusline-mcp.sh --show=recall,chart # only the listed chips
9
9
  # statusline-mcp.sh --compact # collapse to `mcp <up>/<total>`
10
10
  # green when all up, red if any down
11
11
  #
12
+ # `secure` differs from the others: recall/chart/deck/council are local
13
+ # daemons probed via a pidfile/lockfile/freshness file, but launch-secure is
14
+ # the hosted MCP. Its chip is a reachability probe (curl) against the active
15
+ # profile's serverUrl, cached for SECURE_CACHE_TTL seconds so the statusline
16
+ # never blocks on the network on every render.
17
+ #
12
18
  # Project root is inferred from $LK_STATUSLINE_CWD (set by the wrapper) or
13
19
  # $PWD by walking up until a `.launchsecure` dir is found. Silent exit when
14
20
  # the cwd is not inside a launchsecure project.
@@ -22,7 +28,12 @@ for arg in "$@"; do
22
28
  --compact) compact=1 ;;
23
29
  esac
24
30
  done
25
- [ -z "$show" ] && show="recall,chart,deck,council"
31
+ [ -z "$show" ] && show="recall,chart,deck,council,secure"
32
+
33
+ # TTL for the cached launch-secure reachability probe (seconds). The statusline
34
+ # re-renders far too often to curl on every paint; one live probe per window is
35
+ # plenty for an "is the host up" signal.
36
+ SECURE_CACHE_TTL=30
26
37
 
27
38
  GREEN=$'\033[32m'
28
39
  ORANGE=$'\033[33m'
@@ -173,6 +184,74 @@ chip_council() {
173
184
  _state="orange"; _display="${ORANGE}council${RESET}"
174
185
  }
175
186
 
187
+ # Pull the active profile's serverUrl out of .launch-secure.cred.config without
188
+ # jq (the chip script stays coreutils-only). Handles both shapes the cred file
189
+ # can take — profiled ({active, profiles:{<name>:{serverUrl}}}) and flat
190
+ # ({serverUrl}) — mirroring the .mcp.json headersHelper's own fallback.
191
+ extract_secure_url() {
192
+ local cred="$1" active
193
+ active=$(grep -o '"active"[[:space:]]*:[[:space:]]*"[^"]*"' "$cred" 2>/dev/null | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
194
+ awk -v prof="$active" '
195
+ function opens(s){ return gsub(/{/,"&",s) }
196
+ function closes(s){ return gsub(/}/,"&",s) }
197
+ BEGIN { inprof = (prof == "") ? 1 : 0; depth = 0 }
198
+ {
199
+ if (prof != "" && !inprof) {
200
+ if (index($0, "\"" prof "\"") > 0 && index($0, "{") > 0) { inprof = 1; depth = opens($0) - closes($0) }
201
+ next
202
+ }
203
+ if (match($0, /"serverUrl"[[:space:]]*:[[:space:]]*"[^"]*"/)) {
204
+ s = substr($0, RSTART, RLENGTH)
205
+ sub(/.*:[[:space:]]*"/, "", s); sub(/".*/, "", s)
206
+ print s; exit
207
+ }
208
+ if (prof != "") { depth += opens($0) - closes($0); if (depth <= 0) exit }
209
+ }
210
+ ' "$cred" 2>/dev/null
211
+ }
212
+
213
+ _render_secure() {
214
+ # $1 = state (green|red|unknown), $2 = label (active profile name)
215
+ case "$1" in
216
+ green) _state="green"; _display="${GREEN}secure(${2})${RESET}" ;;
217
+ unknown) _state="orange"; _display="${ORANGE}secure(${2})${RESET}" ;;
218
+ *) _state="red"; _display="${RED}secure(${2})${RESET}" ;;
219
+ esac
220
+ }
221
+
222
+ chip_secure() {
223
+ local cred="$PROJECT_ROOT/.launch-secure.cred.config"
224
+ if [ ! -f "$cred" ]; then _state="orange"; _display="${ORANGE}secure(?)${RESET}"; return; fi
225
+
226
+ local active url label
227
+ active=$(grep -o '"active"[[:space:]]*:[[:space:]]*"[^"]*"' "$cred" 2>/dev/null | head -1 | sed 's/.*"\([^"]*\)".*/\1/')
228
+ url=$(extract_secure_url "$cred")
229
+ if [ -z "$url" ]; then _state="orange"; _display="${ORANGE}secure(?)${RESET}"; return; fi
230
+ label="${active:-secure}"
231
+
232
+ # Cache keyed on the URL so a course-switch (prod↔local) invalidates instantly.
233
+ local cache="$PROJECT_ROOT/.launchsecure/.statusline-secure.cache"
234
+ local now; now=$(date +%s)
235
+ if [ -f "$cache" ]; then
236
+ local c_ts c_url c_state
237
+ IFS='|' read -r c_ts c_url c_state < "$cache" 2>/dev/null || true
238
+ if [ -n "${c_ts:-}" ] && [ "${c_url:-}" = "$url" ] && [ $((now - c_ts)) -lt "$SECURE_CACHE_TTL" ]; then
239
+ _render_secure "$c_state" "$label"; return
240
+ fi
241
+ fi
242
+
243
+ # Live probe. Any HTTP status — including 401/403/404/405 — means the host is
244
+ # reachable; only a transport failure (curl writes 000) counts as down. No
245
+ # curl on PATH → unknown (orange), never a false red.
246
+ local state="unknown" code
247
+ if command -v curl >/dev/null 2>&1; then
248
+ code=$(curl -s -o /dev/null -m 2 -w '%{http_code}' "$url" 2>/dev/null || echo 000)
249
+ if [ -n "$code" ] && [ "$code" != "000" ]; then state="green"; else state="red"; fi
250
+ fi
251
+ printf '%s|%s|%s\n' "$now" "$url" "$state" > "$cache" 2>/dev/null || true
252
+ _render_secure "$state" "$label"
253
+ }
254
+
176
255
  show_list=$(echo "$show" | tr ',' ' ')
177
256
  total=0
178
257
  up=0
@@ -183,6 +262,7 @@ for d in $show_list; do
183
262
  chart) chip_chart ;;
184
263
  deck) chip_deck ;;
185
264
  council) chip_council ;;
265
+ secure) chip_secure ;;
186
266
  *) continue ;;
187
267
  esac
188
268
  total=$((total + 1))
@@ -40,7 +40,14 @@ if [ -x "$HOME/.launchsecure/statusline-mcp.sh" ]; then
40
40
  fi
41
41
  fi
42
42
 
43
- sep=$'\033[2m | \033[0m'
43
+ # Layout: by default the chips go on their OWN line below the user's original
44
+ # statusline (Claude Code renders each stdout newline as a new row). Set
45
+ # LK_STATUSLINE_INLINE=1 to keep the old single-line ` | `-joined layout.
46
+ if [ "${LK_STATUSLINE_INLINE:-0}" = "1" ]; then
47
+ sep=$'\033[2m | \033[0m'
48
+ else
49
+ sep=$'\n'
50
+ fi
44
51
  if [ -n "$original_output" ] && [ -n "$chips" ]; then
45
52
  printf '%s%s%s' "$original_output" "$sep" "$chips"
46
53
  elif [ -n "$original_output" ]; then