@launchsecure/launch-kit 0.0.25 → 0.0.27

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 (132) hide show
  1. package/README.md +50 -0
  2. package/dist/beacon/beacon.mjs +1016 -0
  3. package/dist/beacon/beacon.mjs.map +1 -0
  4. package/dist/beacon/beacon.umd.js +87 -0
  5. package/dist/beacon/beacon.umd.js.map +1 -0
  6. package/dist/beacon/index-DAIDnjfR.mjs +513 -0
  7. package/dist/beacon/index-DAIDnjfR.mjs.map +1 -0
  8. package/dist/beacon/types/capture/element.d.ts +3 -0
  9. package/dist/beacon/types/capture/element.d.ts.map +1 -0
  10. package/dist/beacon/types/capture/framework.d.ts +3 -0
  11. package/dist/beacon/types/capture/framework.d.ts.map +1 -0
  12. package/dist/beacon/types/capture/metadata.d.ts +3 -0
  13. package/dist/beacon/types/capture/metadata.d.ts.map +1 -0
  14. package/dist/beacon/types/capture/overlay.d.ts +7 -0
  15. package/dist/beacon/types/capture/overlay.d.ts.map +1 -0
  16. package/dist/beacon/types/capture/picker.d.ts +12 -0
  17. package/dist/beacon/types/capture/picker.d.ts.map +1 -0
  18. package/dist/beacon/types/capture/screenshot.d.ts +7 -0
  19. package/dist/beacon/types/capture/screenshot.d.ts.map +1 -0
  20. package/dist/beacon/types/capture/selector.d.ts +2 -0
  21. package/dist/beacon/types/capture/selector.d.ts.map +1 -0
  22. package/dist/beacon/types/element.d.ts +50 -0
  23. package/dist/beacon/types/element.d.ts.map +1 -0
  24. package/dist/beacon/types/index.d.ts +4 -0
  25. package/dist/beacon/types/index.d.ts.map +1 -0
  26. package/dist/beacon/types/transport/submit.d.ts +3 -0
  27. package/dist/beacon/types/transport/submit.d.ts.map +1 -0
  28. package/dist/beacon/types/types.d.ts +88 -0
  29. package/dist/beacon/types/types.d.ts.map +1 -0
  30. package/dist/beacon/types/ui/button.d.ts +2 -0
  31. package/dist/beacon/types/ui/button.d.ts.map +1 -0
  32. package/dist/beacon/types/ui/drawer.d.ts +31 -0
  33. package/dist/beacon/types/ui/drawer.d.ts.map +1 -0
  34. package/dist/beacon/types/ui/icons.d.ts +9 -0
  35. package/dist/beacon/types/ui/icons.d.ts.map +1 -0
  36. package/dist/beacon/types/ui/pick-mode-overlay.d.ts +25 -0
  37. package/dist/beacon/types/ui/pick-mode-overlay.d.ts.map +1 -0
  38. package/dist/beacon/types/ui/pin-popover.d.ts +14 -0
  39. package/dist/beacon/types/ui/pin-popover.d.ts.map +1 -0
  40. package/dist/chart-client/assets/index-CJ4mgRRF.css +1 -0
  41. package/dist/chart-client/assets/{index-C8ANseEa.js → index-Ccy-DpI-.js} +82 -73
  42. package/dist/chart-client/index.html +2 -2
  43. package/dist/client/assets/index-DI5qSR_w.css +32 -0
  44. package/dist/client/assets/index-Dp0_okva.js +294 -0
  45. package/dist/client/index.html +2 -2
  46. package/dist/council-client/assets/index-C_-vAM9L.css +1 -0
  47. package/dist/council-client/assets/{index-Dc41S-R2.js → index-Dt4zWKSj.js} +14 -14
  48. package/dist/council-client/index.html +2 -2
  49. package/dist/deck-client/assets/{_baseUniq-2gclQXo7.js → _baseUniq-W2JQDmje.js} +1 -1
  50. package/dist/deck-client/assets/{arc-DcMY5Wm0.js → arc-DIBWAId9.js} +1 -1
  51. package/dist/deck-client/assets/{architectureDiagram-Q4EWVU46-B8iirmmJ.js → architectureDiagram-Q4EWVU46-CAIRMvJK.js} +1 -1
  52. package/dist/deck-client/assets/{blockDiagram-DXYQGD6D-B4JBLjmJ.js → blockDiagram-DXYQGD6D-BeNaNiOi.js} +1 -1
  53. package/dist/deck-client/assets/{c4Diagram-AHTNJAMY-CojrJAk8.js → c4Diagram-AHTNJAMY-B9Ozi62h.js} +1 -1
  54. package/dist/deck-client/assets/channel-CRdozqbp.js +1 -0
  55. package/dist/deck-client/assets/{chunk-4BX2VUAB-Bmb_BMDo.js → chunk-4BX2VUAB-D7AZ47dt.js} +1 -1
  56. package/dist/deck-client/assets/{chunk-4TB4RGXK-CumBy8qe.js → chunk-4TB4RGXK-DnVnNPcI.js} +1 -1
  57. package/dist/deck-client/assets/{chunk-55IACEB6-Ka8Hb1wD.js → chunk-55IACEB6-UKYs-YNd.js} +1 -1
  58. package/dist/deck-client/assets/{chunk-EDXVE4YY-B3sIPiQo.js → chunk-EDXVE4YY-D43b-SKn.js} +1 -1
  59. package/dist/deck-client/assets/{chunk-FMBD7UC4-C1tYkaqu.js → chunk-FMBD7UC4-QzBAoyyW.js} +1 -1
  60. package/dist/deck-client/assets/{chunk-OYMX7WX6-D7Wacbky.js → chunk-OYMX7WX6-Cjif4r6W.js} +1 -1
  61. package/dist/deck-client/assets/{chunk-QZHKN3VN-ChXI0vO3.js → chunk-QZHKN3VN-CqLDirEI.js} +1 -1
  62. package/dist/deck-client/assets/{chunk-YZCP3GAM-BXhiqf8u.js → chunk-YZCP3GAM-_FQvmMs4.js} +1 -1
  63. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-lIZMp57W.js +1 -0
  64. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-lIZMp57W.js +1 -0
  65. package/dist/deck-client/assets/clone-BtWeSTyJ.js +1 -0
  66. package/dist/deck-client/assets/{cose-bilkent-S5V4N54A-Bqp3p68D.js → cose-bilkent-S5V4N54A-rfrocesE.js} +1 -1
  67. package/dist/deck-client/assets/{dagre-KV5264BT-BS-rtyhZ.js → dagre-KV5264BT-Bv_7DJat.js} +1 -1
  68. package/dist/deck-client/assets/{diagram-5BDNPKRD-BIrj9YGI.js → diagram-5BDNPKRD-4F1414G5.js} +1 -1
  69. package/dist/deck-client/assets/{diagram-G4DWMVQ6-noHWPIg4.js → diagram-G4DWMVQ6-C4-Pszqm.js} +1 -1
  70. package/dist/deck-client/assets/{diagram-MMDJMWI5-C2qHxvqV.js → diagram-MMDJMWI5-B647TIx9.js} +1 -1
  71. package/dist/deck-client/assets/{diagram-TYMM5635-BytnGQr-.js → diagram-TYMM5635-BFAqpezd.js} +1 -1
  72. package/dist/deck-client/assets/{erDiagram-SMLLAGMA-BfK5m2YQ.js → erDiagram-SMLLAGMA-BfBfrJOC.js} +1 -1
  73. package/dist/deck-client/assets/{flowDiagram-DWJPFMVM-Cq925G1Z.js → flowDiagram-DWJPFMVM-DX9YAYes.js} +1 -1
  74. package/dist/deck-client/assets/{ganttDiagram-T4ZO3ILL-DhhHPAmj.js → ganttDiagram-T4ZO3ILL-DCuiy7wF.js} +1 -1
  75. package/dist/deck-client/assets/{gitGraphDiagram-UUTBAWPF-B3Lc0h9q.js → gitGraphDiagram-UUTBAWPF-CGp1IXUh.js} +1 -1
  76. package/dist/deck-client/assets/{graph-RTawgVWm.js → graph-B7g8aoxv.js} +1 -1
  77. package/dist/deck-client/assets/{index-BfIfJXmS.js → index-Dg1r-WSN.js} +68 -68
  78. package/dist/deck-client/assets/index-DsIZ3LqL.css +1 -0
  79. package/dist/deck-client/assets/{infoDiagram-42DDH7IO-BlR584kX.js → infoDiagram-42DDH7IO-L3fahMkF.js} +1 -1
  80. package/dist/deck-client/assets/{ishikawaDiagram-UXIWVN3A-DygKoNGY.js → ishikawaDiagram-UXIWVN3A-aS_EjWBZ.js} +1 -1
  81. package/dist/deck-client/assets/{journeyDiagram-VCZTEJTY-BnaiYp9N.js → journeyDiagram-VCZTEJTY-djTSQZF9.js} +1 -1
  82. package/dist/deck-client/assets/{kanban-definition-6JOO6SKY-BQBUBzJC.js → kanban-definition-6JOO6SKY-CcTHo4CM.js} +1 -1
  83. package/dist/deck-client/assets/{layout-DeZ8HI1T.js → layout-mEJiadb7.js} +1 -1
  84. package/dist/deck-client/assets/{linear-C6roLi_9.js → linear-XgTKqyRu.js} +1 -1
  85. package/dist/deck-client/assets/{min-CbUksbuI.js → min-Ct9jZdpd.js} +1 -1
  86. package/dist/deck-client/assets/{mindmap-definition-QFDTVHPH-iNxV62yN.js → mindmap-definition-QFDTVHPH-BaFxCGNU.js} +1 -1
  87. package/dist/deck-client/assets/{pieDiagram-DEJITSTG-DHVA0jaG.js → pieDiagram-DEJITSTG-CIbYYjtw.js} +1 -1
  88. package/dist/deck-client/assets/{quadrantDiagram-34T5L4WZ-DBeKKLUQ.js → quadrantDiagram-34T5L4WZ-D9EtCOvh.js} +1 -1
  89. package/dist/deck-client/assets/{requirementDiagram-MS252O5E-CBwITx7p.js → requirementDiagram-MS252O5E-xeni9eVG.js} +1 -1
  90. package/dist/deck-client/assets/{sankeyDiagram-XADWPNL6-BtE-1YTU.js → sankeyDiagram-XADWPNL6-LYeknz9h.js} +1 -1
  91. package/dist/deck-client/assets/{sequenceDiagram-FGHM5R23-DN96yPP2.js → sequenceDiagram-FGHM5R23-RDbsKFZf.js} +1 -1
  92. package/dist/deck-client/assets/{stateDiagram-FHFEXIEX-VUkKC2uJ.js → stateDiagram-FHFEXIEX-BH1Zjglk.js} +1 -1
  93. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-BrV78NDR.js +1 -0
  94. package/dist/deck-client/assets/{timeline-definition-GMOUNBTQ-oUeZhRns.js → timeline-definition-GMOUNBTQ-IFXxKptt.js} +1 -1
  95. package/dist/deck-client/assets/{vennDiagram-DHZGUBPP-D87fK90n.js → vennDiagram-DHZGUBPP-D-sLkQs9.js} +1 -1
  96. package/dist/deck-client/assets/wardley-RL74JXVD-C010F8l4.js +162 -0
  97. package/dist/deck-client/assets/{wardleyDiagram-NUSXRM2D-Ca_i0QRA.js → wardleyDiagram-NUSXRM2D-BTjjuDU3.js} +1 -1
  98. package/dist/deck-client/assets/{xychartDiagram-5P7HB3ND-CUOJVIvq.js → xychartDiagram-5P7HB3ND-AYbv92n-.js} +1 -1
  99. package/dist/deck-client/index.html +2 -2
  100. package/dist/server/chart-serve.js +4524 -3564
  101. package/dist/server/cli.js +27351 -5398
  102. package/dist/server/council-entry.js +17 -5
  103. package/dist/server/council-serve.js +8 -3
  104. package/dist/server/deck-mcp-entry.js +354 -13
  105. package/dist/server/deck-serve.js +298 -7
  106. package/dist/server/graph/queries/classify.scm +8 -0
  107. package/dist/server/graph/queries/exports.scm +7 -0
  108. package/dist/server/graph-mcp-entry.js +5943 -4361
  109. package/dist/server/init-entry.js +609 -0
  110. package/dist/server/orbit-entry.js +2272 -0
  111. package/dist/server/{server/chart-serve.js → parse-worker-entry.js} +1900 -1822
  112. package/dist/server/recall-entry.js +1450 -0
  113. package/package.json +40 -8
  114. package/scaffolds/migrate-safety/.github/workflows/backup-on-migration.yml +72 -0
  115. package/scaffolds/migrate-safety/docs/migrations-runbook.md +172 -0
  116. package/scaffolds/migrate-safety/scripts/migrate-with-backup.sh +294 -0
  117. package/dist/chart-client/assets/index--120d9P9.css +0 -1
  118. package/dist/client/assets/index-Bf8zdL3x.css +0 -32
  119. package/dist/client/assets/index-Ds9UP_cj.js +0 -291
  120. package/dist/council-client/assets/index-CofZh7pS.css +0 -1
  121. package/dist/deck-client/assets/channel-ERh5jKXV.js +0 -1
  122. package/dist/deck-client/assets/classDiagram-6PBFFD2Q-CMi1Gaev.js +0 -1
  123. package/dist/deck-client/assets/classDiagram-v2-HSJHXN6E-CMi1Gaev.js +0 -1
  124. package/dist/deck-client/assets/clone-DfWhlD4X.js +0 -1
  125. package/dist/deck-client/assets/index-765AIQ9z.css +0 -1
  126. package/dist/deck-client/assets/stateDiagram-v2-QKLJ7IA2-CA0IjulK.js +0 -1
  127. package/dist/deck-client/assets/wardley-RL74JXVD-DYbYcpDp.js +0 -162
  128. package/dist/server/deck-server/deck-mcp-entry.js +0 -1789
  129. package/dist/server/deck-server/deck-serve.js +0 -1275
  130. package/dist/server/server/cli.js +0 -13360
  131. package/dist/server/server/fb-wizard.js +0 -136
  132. package/dist/server/server/graph-mcp-entry.js +0 -6776
@@ -43,6 +43,9 @@ var import_node_fs3 = __toESM(require("node:fs"));
43
43
  var import_node_path3 = __toESM(require("node:path"));
44
44
  var import_ws = require("ws");
45
45
 
46
+ // src/server/launch-kit-paths.ts
47
+ var LAUNCHSECURE_DIR = ".launchsecure";
48
+
46
49
  // src/server/deck-lockfile.ts
47
50
  var import_node_child_process = require("node:child_process");
48
51
  var import_node_fs = require("node:fs");
@@ -50,9 +53,9 @@ var import_node_os = require("node:os");
50
53
  var import_node_path = require("node:path");
51
54
  function lockDir(projectRoot) {
52
55
  if (projectRoot) {
53
- return (0, import_node_path.join)(projectRoot, ".launchsecure");
56
+ return (0, import_node_path.join)(projectRoot, LAUNCHSECURE_DIR);
54
57
  }
55
- return (0, import_node_path.join)((0, import_node_os.homedir)(), ".launchsecure");
58
+ return (0, import_node_path.join)((0, import_node_os.homedir)(), LAUNCHSECURE_DIR);
56
59
  }
57
60
  function lockPath(projectRoot) {
58
61
  return (0, import_node_path.join)(lockDir(projectRoot), "launch-deck.lock");
@@ -881,6 +884,271 @@ function contractToMarkdown(contract) {
881
884
  return md;
882
885
  }
883
886
 
887
+ // src/server/rich-html-render.ts
888
+ var WIRED_CDN = "https://unpkg.com/wired-elements?module";
889
+ var REVEAL_VER = "5.1.0";
890
+ var REVEAL_CSS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.css`;
891
+ var REVEAL_THEME = (t) => `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/theme/${t === "dark" ? "black" : "white"}.css`;
892
+ var REVEAL_JS = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/dist/reveal.js`;
893
+ var REVEAL_MD = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/markdown/markdown.js`;
894
+ var REVEAL_HL = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/highlight/highlight.js`;
895
+ var REVEAL_NOTES = `https://cdn.jsdelivr.net/npm/reveal.js@${REVEAL_VER}/plugin/notes/notes.js`;
896
+ function renderRichHtml(opts) {
897
+ const theme = opts.theme ?? "light";
898
+ const title = escapeHtml(opts.title ?? "LaunchDeck");
899
+ if (opts.framework === "wired") {
900
+ return renderWired(opts.content, theme, title);
901
+ }
902
+ if (opts.framework === "reveal") {
903
+ return renderReveal(opts.content, theme, title);
904
+ }
905
+ return opts.content;
906
+ }
907
+ function themeResolverScript(initial) {
908
+ return `<script>
909
+ (function () {
910
+ function applyTheme(t) {
911
+ if (t !== 'light' && t !== 'dark') return;
912
+ var prev = document.documentElement.dataset.theme;
913
+ document.documentElement.dataset.theme = t;
914
+ if (prev !== t) {
915
+ document.dispatchEvent(new CustomEvent('deck-theme', { detail: t }));
916
+ }
917
+ }
918
+ // 1) initial preference: URL > prefers-color-scheme (standalone) > baked-in default
919
+ var url = new URL(window.location.href);
920
+ var fromUrl = url.searchParams.get('theme');
921
+ if (fromUrl === 'light' || fromUrl === 'dark') {
922
+ applyTheme(fromUrl);
923
+ } else if (window.parent === window) {
924
+ var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
925
+ applyTheme(prefersDark ? 'dark' : 'light');
926
+ } else {
927
+ applyTheme(${JSON.stringify(initial)});
928
+ }
929
+ // 2) live updates from parent deck
930
+ window.addEventListener('message', function (e) {
931
+ if (e.data && e.data.type === 'deck-theme') applyTheme(e.data.theme);
932
+ });
933
+ // 3) tell parent we are ready so it can push the current theme back
934
+ if (window.parent !== window) {
935
+ window.parent.postMessage({ type: 'deck-iframe-ready' }, '*');
936
+ }
937
+ })();
938
+ </script>`;
939
+ }
940
+ function renderWired(body, initialTheme, title) {
941
+ const LIGHT = { bg: "#ffffff", fg: "#18181b", accent: "#7c3aed", cardBg: "#ffffff" };
942
+ const DARK = { bg: "#0e0e10", fg: "#e4e4e7", accent: "#a78bfa", cardBg: "#1a1a1d" };
943
+ const wiredVarsBlock = (vars) => `
944
+ --wired-card-background-fill: ${vars.cardBg};
945
+ --wired-button-color: ${vars.fg};
946
+ --wired-combo-popup-bg: ${vars.cardBg};
947
+ --wired-progress-color: ${vars.accent};
948
+ --wired-progress-label-background: ${vars.cardBg};
949
+ --wired-progress-label-color: ${vars.fg};
950
+ `;
951
+ return `<!DOCTYPE html>
952
+ <html lang="en" data-theme="${initialTheme}">
953
+ <head>
954
+ <meta charset="utf-8">
955
+ <meta name="viewport" content="width=device-width, initial-scale=1">
956
+ <title>${title}</title>
957
+ <script type="module" src="${WIRED_CDN}"></script>
958
+ <link href="https://fonts.googleapis.com/css2?family=Gloria+Hallelujah&family=DM+Sans:wght@400;600;700&display=swap" rel="stylesheet">
959
+ <style>
960
+ *, *::before, *::after { box-sizing: border-box; }
961
+ html, body {
962
+ margin: 0;
963
+ min-height: 100%;
964
+ font-family: 'Gloria Hallelujah', 'DM Sans', system-ui, sans-serif;
965
+ background: var(--page-bg);
966
+ color: var(--page-fg);
967
+ transition: background 0.15s, color 0.15s;
968
+ }
969
+ body { padding: 24px; }
970
+ h1, h2, h3, h4 { font-family: 'Gloria Hallelujah', cursive; margin: 0.5em 0; color: var(--page-fg); }
971
+ a { color: var(--page-accent); }
972
+ .row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; margin: 8px 0; }
973
+ .col { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
974
+ .card { padding: 16px; }
975
+
976
+ /* Light theme */
977
+ :root[data-theme="light"] {
978
+ --page-bg: ${LIGHT.bg};
979
+ --page-fg: ${LIGHT.fg};
980
+ --page-accent: ${LIGHT.accent};
981
+ ${wiredVarsBlock(LIGHT)}
982
+ }
983
+
984
+ /* Dark theme */
985
+ :root[data-theme="dark"] {
986
+ --page-bg: ${DARK.bg};
987
+ --page-fg: ${DARK.fg};
988
+ --page-accent: ${DARK.accent};
989
+ ${wiredVarsBlock(DARK)}
990
+ }
991
+
992
+ /* Hosts: text color inherits via component "color: inherit" rules.
993
+ Transparent background lets the page bg show through where the
994
+ rough.js rectangle leaves space. */
995
+ wired-button, wired-card, wired-checkbox, wired-radio, wired-toggle,
996
+ wired-input, wired-textarea, wired-search-input, wired-combo, wired-item,
997
+ wired-listbox, wired-link, wired-tabs, wired-tab, wired-fab,
998
+ wired-icon-button, wired-divider, wired-progress, wired-slider,
999
+ wired-calendar, wired-dialog {
1000
+ color: var(--page-fg);
1001
+ background: transparent;
1002
+ }
1003
+ </style>
1004
+ </head>
1005
+ <body>
1006
+ ${body}
1007
+ ${themeResolverScript(initialTheme)}
1008
+ <script type="module">
1009
+ // wired-input / wired-textarea / wired-search-input render their native
1010
+ // <input>/<textarea> INSIDE shadow DOM. Outer CSS cannot reach those, and
1011
+ // the native control has appearance:auto which the UA repaints over any
1012
+ // "background: transparent" rule. We must set inline styles directly on
1013
+ // the inner element with !important.
1014
+ //
1015
+ // We register one applier per theme. Re-runs when theme changes or new
1016
+ // nodes are added so the page reacts live to the deck sun/moon toggle.
1017
+ const FG = { light: ${JSON.stringify(LIGHT.fg)}, dark: ${JSON.stringify(DARK.fg)} };
1018
+ const TAGS = ['wired-input', 'wired-textarea', 'wired-search-input'];
1019
+ const DARK_PROPS = [
1020
+ 'appearance', '-webkit-appearance',
1021
+ 'background', 'background-color',
1022
+ 'color', '-webkit-text-fill-color', 'caret-color',
1023
+ 'border', 'outline',
1024
+ ];
1025
+
1026
+ function applyDark(node) {
1027
+ const s = node.style;
1028
+ s.setProperty('appearance', 'none', 'important');
1029
+ s.setProperty('-webkit-appearance', 'none', 'important');
1030
+ s.setProperty('background', 'transparent', 'important');
1031
+ s.setProperty('background-color', 'transparent', 'important');
1032
+ s.setProperty('color', FG.dark, 'important');
1033
+ s.setProperty('-webkit-text-fill-color', FG.dark, 'important');
1034
+ s.setProperty('caret-color', FG.dark, 'important');
1035
+ s.setProperty('border', 'none', 'important');
1036
+ s.setProperty('outline', 'none', 'important');
1037
+ }
1038
+
1039
+ function applyLight(node) {
1040
+ DARK_PROPS.forEach((p) => node.style.removeProperty(p));
1041
+ }
1042
+
1043
+ function placeholderStyle(host, theme) {
1044
+ const existing = host.shadowRoot.querySelector('style[data-deck-theme]');
1045
+ if (existing) existing.remove();
1046
+ if (theme !== 'dark') return;
1047
+ const style = document.createElement('style');
1048
+ style.dataset.deckTheme = '1';
1049
+ style.textContent =
1050
+ '::placeholder{color:' + FG.dark + '99 !important;' +
1051
+ '-webkit-text-fill-color:' + FG.dark + '99 !important;}';
1052
+ host.shadowRoot.appendChild(style);
1053
+ }
1054
+
1055
+ function sweepOnce() {
1056
+ const theme = document.documentElement.dataset.theme;
1057
+ for (const tag of TAGS) {
1058
+ for (const host of document.querySelectorAll(tag)) {
1059
+ if (!host.shadowRoot) continue;
1060
+ const inner = host.shadowRoot.querySelector('input, textarea');
1061
+ if (!inner) continue;
1062
+ if (theme === 'dark') applyDark(inner);
1063
+ else applyLight(inner);
1064
+ placeholderStyle(host, theme);
1065
+ }
1066
+ }
1067
+ }
1068
+
1069
+ // Initial + late-upgrade catch (CDN script loads async).
1070
+ sweepOnce();
1071
+ let elapsed = 0;
1072
+ function tick() {
1073
+ sweepOnce();
1074
+ elapsed += 100;
1075
+ if (elapsed < 3000) setTimeout(tick, 100);
1076
+ }
1077
+ setTimeout(tick, 100);
1078
+
1079
+ // Re-sweep on theme change.
1080
+ document.addEventListener('deck-theme', sweepOnce);
1081
+ // Re-sweep when new nodes are added.
1082
+ new MutationObserver(sweepOnce).observe(document.body, { subtree: true, childList: true });
1083
+
1084
+ // whenDefined fires when each tag is registered \u2014 allSettled-style, never hangs.
1085
+ TAGS.forEach((tag) => {
1086
+ customElements.whenDefined(tag).then(sweepOnce).catch(() => {});
1087
+ });
1088
+ </script>
1089
+ </body>
1090
+ </html>`;
1091
+ }
1092
+ function renderReveal(content, initialTheme, title) {
1093
+ const slides = content.includes("<section") ? content : content.split(/\n\s*---\s*\n/).map((md) => `<section data-markdown><textarea data-template>
1094
+ ${md.trim()}
1095
+ </textarea></section>`).join("\n");
1096
+ return `<!DOCTYPE html>
1097
+ <html lang="en" data-theme="${initialTheme}">
1098
+ <head>
1099
+ <meta charset="utf-8">
1100
+ <meta name="viewport" content="width=device-width, initial-scale=1">
1101
+ <title>${title}</title>
1102
+ <link rel="stylesheet" href="${REVEAL_CSS}">
1103
+ <link id="reveal-theme-light" rel="stylesheet" href="${REVEAL_THEME("light")}" ${initialTheme === "dark" ? "disabled" : ""}>
1104
+ <link id="reveal-theme-dark" rel="stylesheet" href="${REVEAL_THEME("dark")}" ${initialTheme === "dark" ? "" : "disabled"}>
1105
+ <style>
1106
+ html, body { margin: 0; height: 100%; }
1107
+ .reveal .slides { text-align: left; }
1108
+ .reveal .slides section { padding: 0 32px; }
1109
+ </style>
1110
+ </head>
1111
+ <body>
1112
+ <div class="reveal">
1113
+ <div class="slides">
1114
+ ${slides}
1115
+ </div>
1116
+ </div>
1117
+ <script src="${REVEAL_JS}"></script>
1118
+ <script src="${REVEAL_MD}"></script>
1119
+ <script src="${REVEAL_HL}"></script>
1120
+ <script src="${REVEAL_NOTES}"></script>
1121
+ <script>
1122
+ Reveal.initialize({
1123
+ hash: true,
1124
+ slideNumber: 'c/t',
1125
+ controls: true,
1126
+ progress: true,
1127
+ transition: 'slide',
1128
+ plugins: [RevealMarkdown, RevealHighlight, RevealNotes],
1129
+ });
1130
+ // React to theme changes: flip which stylesheet is enabled.
1131
+ function syncRevealTheme() {
1132
+ var dark = document.documentElement.dataset.theme === 'dark';
1133
+ var lightLink = document.getElementById('reveal-theme-light');
1134
+ var darkLink = document.getElementById('reveal-theme-dark');
1135
+ if (lightLink) lightLink.disabled = dark;
1136
+ if (darkLink) darkLink.disabled = !dark;
1137
+ }
1138
+ document.addEventListener('deck-theme', syncRevealTheme);
1139
+ syncRevealTheme();
1140
+ </script>
1141
+ ${themeResolverScript(initialTheme)}
1142
+ </body>
1143
+ </html>`;
1144
+ }
1145
+ function escapeHtml(s) {
1146
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1147
+ }
1148
+ function slugify(label) {
1149
+ return label.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "block";
1150
+ }
1151
+
884
1152
  // src/server/deck-serve.ts
885
1153
  var DEFAULT_PORT = 52829;
886
1154
  var MAX_PORT_SCAN = 3;
@@ -1047,7 +1315,7 @@ async function startDeckServer(opts = {}) {
1047
1315
  const baseUrl = `/deck-files/${sessionEncoded}`;
1048
1316
  const html = generateBlastRadiusHtml(block.manifest, baseUrl);
1049
1317
  const report = generateBlastRadiusReport(block.manifest);
1050
- const dir = import_node_path3.default.join(cwd, ".launchsecure", "deck-files", body.session);
1318
+ const dir = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", body.session);
1051
1319
  import_node_fs3.default.mkdirSync(dir, { recursive: true });
1052
1320
  import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, "blast-radius.html"), html);
1053
1321
  import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, "blast-radius-report.md"), report);
@@ -1063,6 +1331,29 @@ async function startDeckServer(opts = {}) {
1063
1331
  console.error("Failed to generate blast radius HTML:", err);
1064
1332
  }
1065
1333
  }
1334
+ if (block.type === "rich-html" && block.content) {
1335
+ try {
1336
+ const html = renderRichHtml({
1337
+ framework: block.framework ?? "raw",
1338
+ content: block.content,
1339
+ theme: block.theme,
1340
+ title: block.label
1341
+ });
1342
+ const sessionEncoded = encodeURIComponent(body.session);
1343
+ const baseUrl = `/deck-files/${sessionEncoded}`;
1344
+ const filename = `${slugify(block.label)}.html`;
1345
+ const dir = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", body.session);
1346
+ import_node_fs3.default.mkdirSync(dir, { recursive: true });
1347
+ import_node_fs3.default.writeFileSync(import_node_path3.default.join(dir, filename), html);
1348
+ block.type = "iframe";
1349
+ block.src = `${baseUrl}/${filename}`;
1350
+ delete block.content;
1351
+ delete block.framework;
1352
+ delete block.theme;
1353
+ } catch (err) {
1354
+ console.error("Failed to generate rich-html:", err);
1355
+ }
1356
+ }
1066
1357
  }
1067
1358
  broadcastToClients({
1068
1359
  type: "session",
@@ -1099,7 +1390,7 @@ async function startDeckServer(opts = {}) {
1099
1390
  resolveFeedback(session, { comment: "", closed: true });
1100
1391
  }
1101
1392
  try {
1102
- const deckFilesBase = import_node_path3.default.join(cwd, ".launchsecure", "deck-files");
1393
+ const deckFilesBase = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files");
1103
1394
  if (session === "all") {
1104
1395
  if (import_node_fs3.default.existsSync(deckFilesBase)) {
1105
1396
  import_node_fs3.default.rmSync(deckFilesBase, { recursive: true, force: true });
@@ -1127,7 +1418,7 @@ async function startDeckServer(opts = {}) {
1127
1418
  res.end("Forbidden");
1128
1419
  return;
1129
1420
  }
1130
- const filePath = import_node_path3.default.join(cwd, ".launchsecure", "deck-files", relative);
1421
+ const filePath = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", relative);
1131
1422
  if (serveStatic(res, filePath)) return;
1132
1423
  res.writeHead(404);
1133
1424
  res.end("Not found");
@@ -1140,7 +1431,7 @@ async function startDeckServer(opts = {}) {
1140
1431
  res.end("Forbidden");
1141
1432
  return;
1142
1433
  }
1143
- const filePath = import_node_path3.default.join(cwd, ".launchsecure", "deck-files", relative);
1434
+ const filePath = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files", relative);
1144
1435
  if (!import_node_fs3.default.existsSync(filePath) || !import_node_fs3.default.statSync(filePath).isFile()) {
1145
1436
  res.writeHead(404);
1146
1437
  res.end("Not found");
@@ -1225,7 +1516,7 @@ async function startDeckServer(opts = {}) {
1225
1516
  pendingFeedback.delete(id);
1226
1517
  }
1227
1518
  try {
1228
- const deckFilesBase = import_node_path3.default.join(cwd, ".launchsecure", "deck-files");
1519
+ const deckFilesBase = import_node_path3.default.join(cwd, LAUNCHSECURE_DIR, "deck-files");
1229
1520
  if (import_node_fs3.default.existsSync(deckFilesBase)) {
1230
1521
  import_node_fs3.default.rmSync(deckFilesBase, { recursive: true, force: true });
1231
1522
  }
@@ -40,6 +40,14 @@
40
40
  name: (identifier) @http_export_fn
41
41
  (#match? @http_export_fn "^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$")))
42
42
 
43
+ ; export const { GET, POST } = handlers (Auth.js v5 / NextAuth pattern)
44
+ (export_statement
45
+ declaration: (lexical_declaration
46
+ (variable_declarator
47
+ name: (object_pattern
48
+ (shorthand_property_identifier_pattern) @http_export
49
+ (#match? @http_export "^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)$")))))
50
+
43
51
  ; Detect Next.js Server Action directive: 'use server' at file top.
44
52
  ; Tree-sitter represents the directive as an expression_statement whose only
45
53
  ; child is a string literal — and it must be at program level.
@@ -31,6 +31,13 @@
31
31
  (variable_declarator
32
32
  name: (identifier) @export.named.const)))
33
33
 
34
+ ; export const { Foo, Bar } = ... (destructured re-export — Auth.js v5 pattern)
35
+ (export_statement
36
+ declaration: (lexical_declaration
37
+ (variable_declarator
38
+ name: (object_pattern
39
+ (shorthand_property_identifier_pattern) @export.named.const))))
40
+
34
41
  ; export type Foo = ...
35
42
  (export_statement
36
43
  declaration: (type_alias_declaration