@legioncodeinc/hive 0.1.0

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 (190) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +262 -0
  3. package/dist/cli-commands.d.ts +41 -0
  4. package/dist/cli-commands.js +76 -0
  5. package/dist/cli-commands.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +46 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/daemon/dashboard/app.js +118 -0
  10. package/dist/daemon/dashboard/host.d.ts +90 -0
  11. package/dist/daemon/dashboard/host.js +172 -0
  12. package/dist/daemon/dashboard/host.js.map +1 -0
  13. package/dist/daemon/dashboard/web-assets.d.ts +88 -0
  14. package/dist/daemon/dashboard/web-assets.js +195 -0
  15. package/dist/daemon/dashboard/web-assets.js.map +1 -0
  16. package/dist/daemon/fleet-status.d.ts +15 -0
  17. package/dist/daemon/fleet-status.js +56 -0
  18. package/dist/daemon/fleet-status.js.map +1 -0
  19. package/dist/daemon/gate.d.ts +55 -0
  20. package/dist/daemon/gate.js +128 -0
  21. package/dist/daemon/gate.js.map +1 -0
  22. package/dist/daemon/proxy.d.ts +38 -0
  23. package/dist/daemon/proxy.js +126 -0
  24. package/dist/daemon/proxy.js.map +1 -0
  25. package/dist/daemon/registry.d.ts +31 -0
  26. package/dist/daemon/registry.js +120 -0
  27. package/dist/daemon/registry.js.map +1 -0
  28. package/dist/daemon/server.d.ts +41 -0
  29. package/dist/daemon/server.js +126 -0
  30. package/dist/daemon/server.js.map +1 -0
  31. package/dist/daemon/setup-auth.d.ts +37 -0
  32. package/dist/daemon/setup-auth.js +51 -0
  33. package/dist/daemon/setup-auth.js.map +1 -0
  34. package/dist/daemon/telemetry-proxy.d.ts +47 -0
  35. package/dist/daemon/telemetry-proxy.js +63 -0
  36. package/dist/daemon/telemetry-proxy.js.map +1 -0
  37. package/dist/dashboard/contracts.d.ts +235 -0
  38. package/dist/dashboard/contracts.js +43 -0
  39. package/dist/dashboard/contracts.js.map +1 -0
  40. package/dist/dashboard/web/app.d.ts +44 -0
  41. package/dist/dashboard/web/app.js +179 -0
  42. package/dist/dashboard/web/app.js.map +1 -0
  43. package/dist/dashboard/web/boot-route.d.ts +23 -0
  44. package/dist/dashboard/web/boot-route.js +29 -0
  45. package/dist/dashboard/web/boot-route.js.map +1 -0
  46. package/dist/dashboard/web/build-graph-button.d.ts +46 -0
  47. package/dist/dashboard/web/build-graph-button.js +81 -0
  48. package/dist/dashboard/web/build-graph-button.js.map +1 -0
  49. package/dist/dashboard/web/buzzing-screen.d.ts +30 -0
  50. package/dist/dashboard/web/buzzing-screen.js +135 -0
  51. package/dist/dashboard/web/buzzing-screen.js.map +1 -0
  52. package/dist/dashboard/web/folder-picker.d.ts +54 -0
  53. package/dist/dashboard/web/folder-picker.js +125 -0
  54. package/dist/dashboard/web/folder-picker.js.map +1 -0
  55. package/dist/dashboard/web/graph-layout.d.ts +101 -0
  56. package/dist/dashboard/web/graph-layout.js +0 -0
  57. package/dist/dashboard/web/graph-layout.js.map +1 -0
  58. package/dist/dashboard/web/harness-strip.d.ts +38 -0
  59. package/dist/dashboard/web/harness-strip.js +65 -0
  60. package/dist/dashboard/web/harness-strip.js.map +1 -0
  61. package/dist/dashboard/web/health-rail.d.ts +26 -0
  62. package/dist/dashboard/web/health-rail.js +61 -0
  63. package/dist/dashboard/web/health-rail.js.map +1 -0
  64. package/dist/dashboard/web/main.d.ts +22 -0
  65. package/dist/dashboard/web/main.js +51 -0
  66. package/dist/dashboard/web/main.js.map +1 -0
  67. package/dist/dashboard/web/needs-project.d.ts +51 -0
  68. package/dist/dashboard/web/needs-project.js +69 -0
  69. package/dist/dashboard/web/needs-project.js.map +1 -0
  70. package/dist/dashboard/web/page-frame.d.ts +95 -0
  71. package/dist/dashboard/web/page-frame.js +98 -0
  72. package/dist/dashboard/web/page-frame.js.map +1 -0
  73. package/dist/dashboard/web/pages/coming-soon.d.ts +23 -0
  74. package/dist/dashboard/web/pages/coming-soon.js +19 -0
  75. package/dist/dashboard/web/pages/coming-soon.js.map +1 -0
  76. package/dist/dashboard/web/pages/dashboard.d.ts +32 -0
  77. package/dist/dashboard/web/pages/dashboard.js +205 -0
  78. package/dist/dashboard/web/pages/dashboard.js.map +1 -0
  79. package/dist/dashboard/web/pages/graph.d.ts +72 -0
  80. package/dist/dashboard/web/pages/graph.js +362 -0
  81. package/dist/dashboard/web/pages/graph.js.map +1 -0
  82. package/dist/dashboard/web/pages/harnesses.d.ts +65 -0
  83. package/dist/dashboard/web/pages/harnesses.js +210 -0
  84. package/dist/dashboard/web/pages/harnesses.js.map +1 -0
  85. package/dist/dashboard/web/pages/health.d.ts +22 -0
  86. package/dist/dashboard/web/pages/health.js +91 -0
  87. package/dist/dashboard/web/pages/health.js.map +1 -0
  88. package/dist/dashboard/web/pages/lifecycle-panel.d.ts +60 -0
  89. package/dist/dashboard/web/pages/lifecycle-panel.js +187 -0
  90. package/dist/dashboard/web/pages/lifecycle-panel.js.map +1 -0
  91. package/dist/dashboard/web/pages/logs.d.ts +55 -0
  92. package/dist/dashboard/web/pages/logs.js +311 -0
  93. package/dist/dashboard/web/pages/logs.js.map +1 -0
  94. package/dist/dashboard/web/pages/memories.d.ts +35 -0
  95. package/dist/dashboard/web/pages/memories.js +439 -0
  96. package/dist/dashboard/web/pages/memories.js.map +1 -0
  97. package/dist/dashboard/web/pages/projects.d.ts +38 -0
  98. package/dist/dashboard/web/pages/projects.js +325 -0
  99. package/dist/dashboard/web/pages/projects.js.map +1 -0
  100. package/dist/dashboard/web/pages/roi-chart.d.ts +52 -0
  101. package/dist/dashboard/web/pages/roi-chart.js +133 -0
  102. package/dist/dashboard/web/pages/roi-chart.js.map +1 -0
  103. package/dist/dashboard/web/pages/roi.d.ts +93 -0
  104. package/dist/dashboard/web/pages/roi.js +375 -0
  105. package/dist/dashboard/web/pages/roi.js.map +1 -0
  106. package/dist/dashboard/web/pages/settings.d.ts +103 -0
  107. package/dist/dashboard/web/pages/settings.js +420 -0
  108. package/dist/dashboard/web/pages/settings.js.map +1 -0
  109. package/dist/dashboard/web/pages/sync.d.ts +59 -0
  110. package/dist/dashboard/web/pages/sync.js +280 -0
  111. package/dist/dashboard/web/pages/sync.js.map +1 -0
  112. package/dist/dashboard/web/panels.d.ts +178 -0
  113. package/dist/dashboard/web/panels.js +471 -0
  114. package/dist/dashboard/web/panels.js.map +1 -0
  115. package/dist/dashboard/web/primitives.d.ts +80 -0
  116. package/dist/dashboard/web/primitives.js +208 -0
  117. package/dist/dashboard/web/primitives.js.map +1 -0
  118. package/dist/dashboard/web/readiness-splash.d.ts +39 -0
  119. package/dist/dashboard/web/readiness-splash.js +201 -0
  120. package/dist/dashboard/web/readiness-splash.js.map +1 -0
  121. package/dist/dashboard/web/registry.d.ts +96 -0
  122. package/dist/dashboard/web/registry.js +99 -0
  123. package/dist/dashboard/web/registry.js.map +1 -0
  124. package/dist/dashboard/web/router.d.ts +48 -0
  125. package/dist/dashboard/web/router.js +76 -0
  126. package/dist/dashboard/web/router.js.map +1 -0
  127. package/dist/dashboard/web/scope-context.d.ts +155 -0
  128. package/dist/dashboard/web/scope-context.js +266 -0
  129. package/dist/dashboard/web/scope-context.js.map +1 -0
  130. package/dist/dashboard/web/service-icons.d.ts +33 -0
  131. package/dist/dashboard/web/service-icons.js +80 -0
  132. package/dist/dashboard/web/service-icons.js.map +1 -0
  133. package/dist/dashboard/web/setup-gate.d.ts +116 -0
  134. package/dist/dashboard/web/setup-gate.js +272 -0
  135. package/dist/dashboard/web/setup-gate.js.map +1 -0
  136. package/dist/dashboard/web/sidebar.d.ts +63 -0
  137. package/dist/dashboard/web/sidebar.js +91 -0
  138. package/dist/dashboard/web/sidebar.js.map +1 -0
  139. package/dist/dashboard/web/use-fleet-telemetry.d.ts +111 -0
  140. package/dist/dashboard/web/use-fleet-telemetry.js +278 -0
  141. package/dist/dashboard/web/use-fleet-telemetry.js.map +1 -0
  142. package/dist/dashboard/web/wire.d.ts +1937 -0
  143. package/dist/dashboard/web/wire.js +1837 -0
  144. package/dist/dashboard/web/wire.js.map +1 -0
  145. package/dist/errors.d.ts +5 -0
  146. package/dist/errors.js +11 -0
  147. package/dist/errors.js.map +1 -0
  148. package/dist/install/registry.d.ts +35 -0
  149. package/dist/install/registry.js +110 -0
  150. package/dist/install/registry.js.map +1 -0
  151. package/dist/lock.d.ts +10 -0
  152. package/dist/lock.js +87 -0
  153. package/dist/lock.js.map +1 -0
  154. package/dist/service/commands.d.ts +15 -0
  155. package/dist/service/commands.js +49 -0
  156. package/dist/service/commands.js.map +1 -0
  157. package/dist/service/index.d.ts +38 -0
  158. package/dist/service/index.js +174 -0
  159. package/dist/service/index.js.map +1 -0
  160. package/dist/service/platform.d.ts +37 -0
  161. package/dist/service/platform.js +67 -0
  162. package/dist/service/platform.js.map +1 -0
  163. package/dist/service/templates.d.ts +10 -0
  164. package/dist/service/templates.js +120 -0
  165. package/dist/service/templates.js.map +1 -0
  166. package/dist/shared/constants.d.ts +15 -0
  167. package/dist/shared/constants.js +19 -0
  168. package/dist/shared/constants.js.map +1 -0
  169. package/dist/shared/daemon-routing.d.ts +11 -0
  170. package/dist/shared/daemon-routing.js +38 -0
  171. package/dist/shared/daemon-routing.js.map +1 -0
  172. package/dist/shared/fleet-readiness.d.ts +18 -0
  173. package/dist/shared/fleet-readiness.js +9 -0
  174. package/dist/shared/fleet-readiness.js.map +1 -0
  175. package/dist/shared/fleet-telemetry.d.ts +68 -0
  176. package/dist/shared/fleet-telemetry.js +61 -0
  177. package/dist/shared/fleet-telemetry.js.map +1 -0
  178. package/dist/shared/lifecycle-flags.d.ts +34 -0
  179. package/dist/shared/lifecycle-flags.js +39 -0
  180. package/dist/shared/lifecycle-flags.js.map +1 -0
  181. package/dist/shared/memory-types.d.ts +55 -0
  182. package/dist/shared/memory-types.js +75 -0
  183. package/dist/shared/memory-types.js.map +1 -0
  184. package/dist/shared/service-status.d.ts +82 -0
  185. package/dist/shared/service-status.js +97 -0
  186. package/dist/shared/service-status.js.map +1 -0
  187. package/dist/telemetry/emit.d.ts +197 -0
  188. package/dist/telemetry/emit.js +196 -0
  189. package/dist/telemetry/emit.js.map +1 -0
  190. package/package.json +50 -0
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The dashboard APP SHELL — PRD-037b (the app-shell split).
3
+ *
4
+ * PRD-024 made `/dashboard` a single long-scrolling page (the old `App`). PRD-037 turns it into a
5
+ * left-nav MULTI-PAGE shell: a persistent `<Sidebar>` (037a) beside a content `<Outlet>` that mounts
6
+ * the registry-matched page (037c) for the active hash route (037b). The current monolithic content
7
+ * moved VERBATIM onto the Dashboard route (`pages/dashboard.tsx`, D-6 lift-and-shift) — this module
8
+ * no longer renders that body; it renders the CHROME and routes to it.
9
+ *
10
+ * What the shell OWNS (hoisted up from the old page, D-5):
11
+ * - The SHARED wire client (built ONCE, passed to every page via PageProps — pages never
12
+ * `createWireClient` themselves).
13
+ * - The path router (PRD-003c `usePathRoute`) → `{ route, navigate }`. The sidebar's `onNavigate`
14
+ * is a thin pass-through to `navigate` (037a never touches `location.pathname` directly).
15
+ * - The `/health` LIVENESS poll + `daemonUp`. When the daemon is unreachable the CONTENT region
16
+ * swaps for the `ConnectivityBanner` while the SIDEBAR stays mounted (D-5); on Retry/reconnect the
17
+ * active page restores and re-hydrates. The per-subsystem health STRIP stays page content (it
18
+ * polls `/health` reasons inside `DashboardPage`); the shell owns only the coarse up/down.
19
+ * - The org/workspace identity (the sidebar sub-line) + the "Pollinate now" action + the `pollinating`
20
+ * pulse, all relocated from the old `Header` into the shell chrome (D-5). `pollinating` flows DOWN to
21
+ * the active page (the Dashboard graph/cards pulse on it).
22
+ * - The collapsed/responsive state (037a AC-6): a manual toggle plus an auto-collapse under the
23
+ * host's `@media (max-width:900px)` breakpoint.
24
+ *
25
+ * PRD-003c: routing is now path-based (History API), with hive's server (`gate.ts`, `host.ts`)
26
+ * as the landing-decision authority — the client router only reflects the path the server already
27
+ * authorized. Still no new dependency. Security posture inherited unchanged (local-mode-only,
28
+ * XSS-safe, no token/secret in the shell/route/registry/pill — D-9).
29
+ */
30
+ import React from "react";
31
+ import { type WireClient } from "./wire.js";
32
+ /** Props for {@link Shell} — the injected wire client + the asset base (same contract as the old App). */
33
+ export interface ShellProps {
34
+ /** The wire client (injected by a unit test with a mocked fetch; defaults to the live one). */
35
+ readonly client?: WireClient;
36
+ /** The base path the logo/assets are served under (the host serves them beside the page). */
37
+ readonly assetBase?: string;
38
+ }
39
+ /**
40
+ * The dashboard shell (037b). Builds the shared wire, runs the hash router + the liveness poll, owns
41
+ * the pollinate action + the collapsed state, and renders the sidebar beside the routed content (or the
42
+ * ConnectivityBanner when the daemon is down — sidebar stays mounted, D-5).
43
+ */
44
+ export declare function Shell({ client, assetBase }?: ShellProps): React.JSX.Element;
@@ -0,0 +1,179 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The dashboard APP SHELL — PRD-037b (the app-shell split).
4
+ *
5
+ * PRD-024 made `/dashboard` a single long-scrolling page (the old `App`). PRD-037 turns it into a
6
+ * left-nav MULTI-PAGE shell: a persistent `<Sidebar>` (037a) beside a content `<Outlet>` that mounts
7
+ * the registry-matched page (037c) for the active hash route (037b). The current monolithic content
8
+ * moved VERBATIM onto the Dashboard route (`pages/dashboard.tsx`, D-6 lift-and-shift) — this module
9
+ * no longer renders that body; it renders the CHROME and routes to it.
10
+ *
11
+ * What the shell OWNS (hoisted up from the old page, D-5):
12
+ * - The SHARED wire client (built ONCE, passed to every page via PageProps — pages never
13
+ * `createWireClient` themselves).
14
+ * - The path router (PRD-003c `usePathRoute`) → `{ route, navigate }`. The sidebar's `onNavigate`
15
+ * is a thin pass-through to `navigate` (037a never touches `location.pathname` directly).
16
+ * - The `/health` LIVENESS poll + `daemonUp`. When the daemon is unreachable the CONTENT region
17
+ * swaps for the `ConnectivityBanner` while the SIDEBAR stays mounted (D-5); on Retry/reconnect the
18
+ * active page restores and re-hydrates. The per-subsystem health STRIP stays page content (it
19
+ * polls `/health` reasons inside `DashboardPage`); the shell owns only the coarse up/down.
20
+ * - The org/workspace identity (the sidebar sub-line) + the "Pollinate now" action + the `pollinating`
21
+ * pulse, all relocated from the old `Header` into the shell chrome (D-5). `pollinating` flows DOWN to
22
+ * the active page (the Dashboard graph/cards pulse on it).
23
+ * - The collapsed/responsive state (037a AC-6): a manual toggle plus an auto-collapse under the
24
+ * host's `@media (max-width:900px)` breakpoint.
25
+ *
26
+ * PRD-003c: routing is now path-based (History API), with hive's server (`gate.ts`, `host.ts`)
27
+ * as the landing-decision authority — the client router only reflects the path the server already
28
+ * authorized. Still no new dependency. Security posture inherited unchanged (local-mode-only,
29
+ * XSS-safe, no token/secret in the shell/route/registry/pill — D-9).
30
+ */
31
+ import React from "react";
32
+ import { Button } from "./primitives.js";
33
+ import { ConnectivityBanner } from "./panels.js";
34
+ import { HEALTH_ROUTE, HealthRail } from "./health-rail.js";
35
+ import { matchRoute, ROUTES } from "./registry.js";
36
+ import { Sidebar } from "./sidebar.js";
37
+ import { usePathRoute } from "./router.js";
38
+ import { PAGE_MAX_WIDTH, usePoll } from "./page-frame.js";
39
+ import { FirstRunBindCTA } from "./needs-project.js";
40
+ import { ScopeProvider, useScopeSwitcher } from "./scope-context.js";
41
+ import { createWireClient, EMPTY_SETTINGS } from "./wire.js";
42
+ /** How often the shell probes `/health` for coarse liveness (ms). */
43
+ const HEALTH_POLL_MS = 5000;
44
+ /** The narrow-viewport breakpoint that auto-collapses the sidebar (mirrors host.ts's media rule). */
45
+ const NARROW_BREAKPOINT = 900;
46
+ /**
47
+ * The content OUTLET — looks up the registry-matched page for the active route and mounts it with the
48
+ * shared {@link PageProps} (037b). Capped at the readable page max-width (D-8). When the daemon is
49
+ * down the shell renders the banner INSTEAD of this (so this only ever renders for an up daemon).
50
+ *
51
+ * PRD-059b (b-AC-1 / M-AC-2): on the DASHBOARD route, when the projects enumeration has resolved with
52
+ * ZERO locally-bound projects, the PRIMARY content is the first-run "Pick a folder to start" CTA — not
53
+ * an empty page. It keys off the switcher's `projectsHydrated` flag so it never flashes before the read
54
+ * resolves, and is gated to the Dashboard route so the Projects/Settings pages stay reachable to bind.
55
+ */
56
+ function Outlet({ route, pageProps, navigate }) {
57
+ const entry = matchRoute(route);
58
+ const PageComponent = entry.component;
59
+ const { projects, projectsHydrated } = useScopeSwitcher();
60
+ // 037c OQ-2: per-route document title from the registry label (cheap, nice for deep links).
61
+ React.useEffect(() => {
62
+ if (typeof document !== "undefined")
63
+ document.title = `honeycomb · ${entry.label}`;
64
+ }, [entry.label]);
65
+ // b-AC-1: zero locally-bound projects (after the read resolved) + the Dashboard route → the first-run
66
+ // CTA is the primary content. `boundLocally` is the per-device binding bit (the inbox/registry-only
67
+ // projects don't count as "active"); an unbound workspace shows the CTA, a bound one shows the page.
68
+ const hasBound = projects.some((p) => p.boundLocally && p.projectId !== "__unsorted__");
69
+ const showFirstRun = entry.route === "/" && projectsHydrated && !hasBound;
70
+ return (_jsx("div", { style: { flex: 1, minWidth: 0, padding: "28px 28px 48px" }, children: _jsx("div", { style: { maxWidth: PAGE_MAX_WIDTH, margin: "0 auto" }, children: showFirstRun ? _jsx(FirstRunBindCTA, { wire: pageProps.wire, navigate: navigate, assetBase: pageProps.assetBase }) : _jsx(PageComponent, { ...pageProps }) }) }));
71
+ }
72
+ /**
73
+ * The dashboard shell (037b). Builds the shared wire, runs the hash router + the liveness poll, owns
74
+ * the pollinate action + the collapsed state, and renders the sidebar beside the routed content (or the
75
+ * ConnectivityBanner when the daemon is down — sidebar stays mounted, D-5).
76
+ */
77
+ export function Shell({ client, assetBase = "assets" } = {}) {
78
+ const wire = React.useMemo(() => client ?? createWireClient(), [client]);
79
+ const { route, navigate } = usePathRoute();
80
+ // ── shell-owned state ──
81
+ const [daemonUp, setDaemonUp] = React.useState(true);
82
+ // The shell owns the SINGLE `/health` poll; `reasons` flow DOWN to the home's subsystem strip via
83
+ // PageProps so the page never polls `/health` a second time (the former double-poll, now deduped).
84
+ const [healthReasons, setHealthReasons] = React.useState(null);
85
+ const [settings, setSettings] = React.useState(EMPTY_SETTINGS);
86
+ const [pollinating, setPollinating] = React.useState(false);
87
+ // Collapsed: a manual toggle OR an auto-collapse under the narrow breakpoint (037a AC-6). We track
88
+ // both an explicit user choice and the viewport, preferring the user's choice once they toggle.
89
+ const [collapsed, setCollapsed] = React.useState(false);
90
+ const daemonUrl = settings.settings.port ? `http://127.0.0.1:${settings.settings.port}` : "http://127.0.0.1:3850";
91
+ /** Hydrate the org/workspace identity for the sidebar sub-line (the shell's slice of settings). */
92
+ const hydrateIdentity = React.useCallback(async () => {
93
+ setSettings(await wire.settings());
94
+ }, [wire]);
95
+ // Hydrate the identity once on mount.
96
+ React.useEffect(() => {
97
+ void hydrateIdentity();
98
+ }, [hydrateIdentity]);
99
+ // Track the previous liveness so identity re-hydration fires ONLY on a down→up recovery (the mount
100
+ // effect already hydrates once) — not on every healthy 5s tick. Null = no probe resolved yet.
101
+ const prevDaemonUpRef = React.useRef(null);
102
+ // D-5: the shell owns the /health LIVENESS poll + the daemon-down swap. On RECOVERY (down→up) re-hydrate
103
+ // the identity (the active page re-hydrates itself on remount). Via `usePoll` so it inherits the shared
104
+ // background-tab pause (a hidden dashboard stops probing) and stops on unmount. `reasons` are captured
105
+ // here and passed DOWN — the page's former duplicate /health poll is gone.
106
+ usePoll(async () => {
107
+ const { up, reasons } = await wire.health();
108
+ setDaemonUp(up);
109
+ setHealthReasons(reasons);
110
+ if (up && prevDaemonUpRef.current === false)
111
+ void hydrateIdentity();
112
+ prevDaemonUpRef.current = up;
113
+ }, HEALTH_POLL_MS);
114
+ // 037a AC-6: auto-collapse under the narrow breakpoint. Tracks the viewport via matchMedia; the
115
+ // listener is cleaned up on unmount. A manual toggle still works (it sets `collapsed` directly).
116
+ React.useEffect(() => {
117
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function")
118
+ return;
119
+ const mq = window.matchMedia(`(max-width: ${NARROW_BREAKPOINT}px)`);
120
+ const apply = (matches) => {
121
+ if (matches)
122
+ setCollapsed(true);
123
+ };
124
+ apply(mq.matches);
125
+ const onChange = (e) => apply(e.matches);
126
+ mq.addEventListener("change", onChange);
127
+ return () => mq.removeEventListener("change", onChange);
128
+ }, []);
129
+ // A SYNCHRONOUS in-flight guard for the pollinate action: `setPollinating(true)` is async, so a render-state
130
+ // guard alone leaves a race window where a rapid second activation fires `wire.pollinate()` twice. The ref
131
+ // flips immediately; the reset timer is tracked so it can be cleared on unmount.
132
+ const pollinateInFlightRef = React.useRef(false);
133
+ const pollinateResetTimerRef = React.useRef(null);
134
+ React.useEffect(() => {
135
+ return () => {
136
+ if (pollinateResetTimerRef.current !== null)
137
+ clearTimeout(pollinateResetTimerRef.current);
138
+ };
139
+ }, []);
140
+ // D-5: the "Pollinate now" action, relocated into the shell chrome. POST the Wave-1 trigger; reflect
141
+ // the 202 ack by pulsing the active page's graph/cards (`pollinating` flows down via PageProps).
142
+ const pollinate = React.useCallback(async () => {
143
+ if (pollinateInFlightRef.current)
144
+ return; // synchronous re-entry guard (no double POST on rapid clicks)
145
+ pollinateInFlightRef.current = true;
146
+ setPollinating(true);
147
+ const ack = await wire.pollinate();
148
+ if (ack.triggered) {
149
+ // A real pass was queued: pulse briefly while it streams into the live log, then settle.
150
+ pollinateResetTimerRef.current = setTimeout(() => {
151
+ setPollinating(false);
152
+ pollinateInFlightRef.current = false;
153
+ }, 4200);
154
+ }
155
+ else {
156
+ // Honestly reflect the skip (disabled / unavailable) — no fake forever spinner.
157
+ setPollinating(false);
158
+ pollinateInFlightRef.current = false;
159
+ }
160
+ }, [wire]);
161
+ const identity = `${settings.orgName || settings.orgId || "local"} · ${settings.workspace || "default"}`;
162
+ // The PageProps every routed page receives (D-7). One shared wire, the liveness flag, the asset
163
+ // base, and the shell-owned pollinating pulse.
164
+ const pageProps = { wire, daemonUp, assetBase, pollinating, healthReasons };
165
+ return (_jsx(ScopeProvider, { wire: wire, children: _jsxs("div", { style: { display: "flex", minHeight: "100vh", background: "var(--bg-canvas)" }, children: [_jsx(Sidebar, { entries: ROUTES, activeRoute: route, onNavigate: navigate, daemonUp: daemonUp, identity: identity, assetBase: assetBase, collapsed: collapsed, onToggleCollapsed: () => setCollapsed((c) => !c) }), _jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }, children: [_jsx(HealthRail, { onOpenHealth: () => navigate(HEALTH_ROUTE) }), _jsxs("div", { style: {
166
+ display: "flex",
167
+ alignItems: "center",
168
+ gap: 12,
169
+ padding: "16px 28px",
170
+ borderBottom: "1px solid var(--border-subtle)",
171
+ }, children: [_jsx("span", { style: { flex: 1 } }), _jsx(Button, { variant: "pollinate", onClick: () => void pollinate(), disabled: pollinating, children: pollinating ? "pollinating…" : "Pollinate now" })] }), daemonUp ? (_jsx(Outlet, { route: route, pageProps: pageProps, navigate: navigate })) : (_jsx("div", { style: { flex: 1, minWidth: 0, padding: "28px 28px 48px" }, children: _jsx("div", { style: { maxWidth: PAGE_MAX_WIDTH, margin: "0 auto" }, children: _jsx(ConnectivityBanner, { url: daemonUrl, onRetry: () => {
172
+ void wire.health().then(({ up }) => {
173
+ setDaemonUp(up);
174
+ if (up)
175
+ void hydrateIdentity();
176
+ });
177
+ } }) }) }))] })] }) }));
178
+ }
179
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/dashboard/web/app.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,EAAmB,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,OAAO,EAAkB,MAAM,iBAAiB,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAA8D,MAAM,WAAW,CAAC;AAEzH,qEAAqE;AACrE,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,qGAAqG;AACrG,MAAM,iBAAiB,GAAG,GAAY,CAAC;AAUvC;;;;;;;;;GASG;AACH,SAAS,MAAM,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAA0E;IACrH,MAAM,KAAK,GAAe,UAAU,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC;IACtC,MAAM,EAAE,QAAQ,EAAE,gBAAgB,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAC1D,4FAA4F;IAC5F,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,OAAO,QAAQ,KAAK,WAAW;YAAE,QAAQ,CAAC,KAAK,GAAG,eAAe,KAAK,CAAC,KAAK,EAAE,CAAC;IACpF,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAElB,sGAAsG;IACtG,oGAAoG;IACpG,qGAAqG;IACrG,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,CAAC,SAAS,KAAK,cAAc,CAAC,CAAC;IACxF,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,KAAK,GAAG,IAAI,gBAAgB,IAAI,CAAC,QAAQ,CAAC;IAE1E,OAAO,CACN,cAAK,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAC9D,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,YACxD,YAAY,CAAC,CAAC,CAAC,KAAC,eAAe,IAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,GAAI,CAAC,CAAC,CAAC,KAAC,aAAa,OAAK,SAAS,GAAI,GAC3I,GACD,CACN,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,GAAG,QAAQ,KAAiB,EAAE;IACtE,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAa,GAAG,EAAE,CAAC,MAAM,IAAI,gBAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACrF,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,CAAC;IAE3C,0BAA0B;IAC1B,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrD,kGAAkG;IAClG,mGAAmG;IACnG,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAA2B,IAAI,CAAC,CAAC;IACzF,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAe,cAAc,CAAC,CAAC;IAC7E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5D,mGAAmG;IACnG,gGAAgG;IAChG,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAElH,mGAAmG;IACnG,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAmB,EAAE;QACnE,WAAW,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,sCAAsC;IACtC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,KAAK,eAAe,EAAE,CAAC;IACxB,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;IAEtB,mGAAmG;IACnG,8FAA8F;IAC9F,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAC;IAE3D,yGAAyG;IACzG,wGAAwG;IACxG,uGAAuG;IACvG,2EAA2E;IAC3E,OAAO,CAAC,KAAK,IAAI,EAAE;QAClB,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5C,WAAW,CAAC,EAAE,CAAC,CAAC;QAChB,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC1B,IAAI,EAAE,IAAI,eAAe,CAAC,OAAO,KAAK,KAAK;YAAE,KAAK,eAAe,EAAE,CAAC;QACpE,eAAe,CAAC,OAAO,GAAG,EAAE,CAAC;IAC9B,CAAC,EAAE,cAAc,CAAC,CAAC;IAEnB,gGAAgG;IAChG,iGAAiG;IACjG,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO;QACrF,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,eAAe,iBAAiB,KAAK,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,CAAC,OAAgB,EAAQ,EAAE;YACxC,IAAI,OAAO;gBAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC;QACF,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QAClB,MAAM,QAAQ,GAAG,CAAC,CAAsB,EAAQ,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACpE,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACxC,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,6GAA6G;IAC7G,2GAA2G;IAC3G,iFAAiF;IACjF,MAAM,oBAAoB,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,sBAAsB,GAAG,KAAK,CAAC,MAAM,CAAuC,IAAI,CAAC,CAAC;IACxF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,OAAO,GAAG,EAAE;YACX,IAAI,sBAAsB,CAAC,OAAO,KAAK,IAAI;gBAAE,YAAY,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAC3F,CAAC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,qGAAqG;IACrG,iGAAiG;IACjG,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAmB,EAAE;QAC7D,IAAI,oBAAoB,CAAC,OAAO;YAAE,OAAO,CAAC,8DAA8D;QACxG,oBAAoB,CAAC,OAAO,GAAG,IAAI,CAAC;QACpC,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;YACnB,yFAAyF;YACzF,sBAAsB,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBAChD,cAAc,CAAC,KAAK,CAAC,CAAC;gBACtB,oBAAoB,CAAC,OAAO,GAAG,KAAK,CAAC;YACtC,CAAC,EAAE,IAAI,CAAC,CAAC;QACV,CAAC;aAAM,CAAC;YACP,gFAAgF;YAChF,cAAc,CAAC,KAAK,CAAC,CAAC;YACtB,oBAAoB,CAAC,OAAO,GAAG,KAAK,CAAC;QACtC,CAAC;IACF,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,QAAQ,GAAG,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,KAAK,IAAI,OAAO,MAAM,QAAQ,CAAC,SAAS,IAAI,SAAS,EAAE,CAAC;IAEzG,gGAAgG;IAChG,+CAA+C;IAC/C,MAAM,SAAS,GAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;IAEvF,OAAO,CAKN,KAAC,aAAa,IAAC,IAAI,EAAE,IAAI,YACzB,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,aAElF,KAAC,OAAO,IACP,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,KAAK,EAClB,UAAU,EAAE,QAAQ,EACpB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,EACpB,iBAAiB,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAC/C,EAEF,eAAK,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,aAG7E,KAAC,UAAU,IAAC,YAAY,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAI,EAG1D,eACC,KAAK,EAAE;gCACN,OAAO,EAAE,MAAM;gCACf,UAAU,EAAE,QAAQ;gCACpB,GAAG,EAAE,EAAE;gCACP,OAAO,EAAE,WAAW;gCACpB,YAAY,EAAE,gCAAgC;6BAC9C,aAED,eAAM,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAI,EAC5B,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,SAAS,EAAE,EAAE,QAAQ,EAAE,WAAW,YAChF,WAAW,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,eAAe,GACvC,IACJ,EAIL,QAAQ,CAAC,CAAC,CAAC,CACX,KAAC,MAAM,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,GAAI,CAClE,CAAC,CAAC,CAAC,CACH,cAAK,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,YAC9D,cAAK,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,YACzD,KAAC,kBAAkB,IAClB,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,GAAG,EAAE;wCACb,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;4CAClC,WAAW,CAAC,EAAE,CAAC,CAAC;4CAChB,IAAI,EAAE;gDAAE,KAAK,eAAe,EAAE,CAAC;wCAChC,CAAC,CAAC,CAAC;oCACJ,CAAC,GACA,GACG,GACD,CACN,IACI,IACD,GACU,CAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The bundle's BOOT SCREEN selector — PRD-003c (m-AC-6 / m-AC-7 / m-AC-8).
3
+ *
4
+ * By the time this bundle runs, hive's SERVER gate (`hive/src/daemon/gate.ts`, PRD-003a)
5
+ * has already evaluated health-then-auth and served the shell ONLY for a path it authorized:
6
+ * `/buzzing` (fleet not healthy, or landed there directly — always exempt), `/login` (logged out,
7
+ * or landed there directly — always exempt), or any other path (healthy + authenticated). This
8
+ * pure function is the whole boot decision `main.tsx` needs: a plain lookup from `location.pathname`
9
+ * to which top-level screen to mount. It never re-derives health or auth itself — doing so would
10
+ * resurrect the retired `ReadinessSplash`→`SetupGate` nested client gate (ADR-0004, m-AC-6).
11
+ */
12
+ export type BootScreen = "buzzing" | "login" | "shell";
13
+ /** The `/buzzing` route (PRD-002's readiness splash, now the gate-exempt readiness screen). */
14
+ export declare const BUZZING_PATH: "/buzzing";
15
+ /** The `/login` route (PRD-003b's device-flow guided setup, now the gate-exempt login screen). */
16
+ export declare const LOGIN_PATH: "/login";
17
+ /**
18
+ * Resolve which top-level screen `main.tsx` should mount for the current path. `/buzzing` and
19
+ * `/login` are the two gate-exempt screens (m-AC-7 / m-AC-8); every other path — including `/` and
20
+ * every registry route (`/projects`, `/harnesses`, ...) — mounts the authenticated `<Shell>`,
21
+ * whose own path router (`router.tsx`) then resolves the specific page via `registry.tsx`.
22
+ */
23
+ export declare function resolveBootScreen(pathname: string): BootScreen;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The bundle's BOOT SCREEN selector — PRD-003c (m-AC-6 / m-AC-7 / m-AC-8).
3
+ *
4
+ * By the time this bundle runs, hive's SERVER gate (`hive/src/daemon/gate.ts`, PRD-003a)
5
+ * has already evaluated health-then-auth and served the shell ONLY for a path it authorized:
6
+ * `/buzzing` (fleet not healthy, or landed there directly — always exempt), `/login` (logged out,
7
+ * or landed there directly — always exempt), or any other path (healthy + authenticated). This
8
+ * pure function is the whole boot decision `main.tsx` needs: a plain lookup from `location.pathname`
9
+ * to which top-level screen to mount. It never re-derives health or auth itself — doing so would
10
+ * resurrect the retired `ReadinessSplash`→`SetupGate` nested client gate (ADR-0004, m-AC-6).
11
+ */
12
+ /** The `/buzzing` route (PRD-002's readiness splash, now the gate-exempt readiness screen). */
13
+ export const BUZZING_PATH = "/buzzing";
14
+ /** The `/login` route (PRD-003b's device-flow guided setup, now the gate-exempt login screen). */
15
+ export const LOGIN_PATH = "/login";
16
+ /**
17
+ * Resolve which top-level screen `main.tsx` should mount for the current path. `/buzzing` and
18
+ * `/login` are the two gate-exempt screens (m-AC-7 / m-AC-8); every other path — including `/` and
19
+ * every registry route (`/projects`, `/harnesses`, ...) — mounts the authenticated `<Shell>`,
20
+ * whose own path router (`router.tsx`) then resolves the specific page via `registry.tsx`.
21
+ */
22
+ export function resolveBootScreen(pathname) {
23
+ if (pathname === BUZZING_PATH)
24
+ return "buzzing";
25
+ if (pathname === LOGIN_PATH)
26
+ return "login";
27
+ return "shell";
28
+ }
29
+ //# sourceMappingURL=boot-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boot-route.js","sourceRoot":"","sources":["../../../src/dashboard/web/boot-route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,+FAA+F;AAC/F,MAAM,CAAC,MAAM,YAAY,GAAG,UAAmB,CAAC;AAEhD,kGAAkG;AAClG,MAAM,CAAC,MAAM,UAAU,GAAG,QAAiB,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IACjD,IAAI,QAAQ,KAAK,YAAY;QAAE,OAAO,SAAS,CAAC;IAChD,IAAI,QAAQ,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC;IAC5C,OAAO,OAAO,CAAC;AAChB,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * The shared "Build graph" BUTTON — the codebase-graph build trigger, used on BOTH graph surfaces.
3
+ *
4
+ * Two places show the codebase-graph empty state — the full-page Graph (`pages/graph.tsx`) and the home
5
+ * GraphPanel (`panels.tsx`). Before, each showed a dead `honeycomb graph build` CLI hint (a command that
6
+ * does not exist — the graph is ONLY buildable from this UI). This single component replaces that with a
7
+ * working primary button wired to the daemon's already-served `POST /api/graph/build` (via
8
+ * `wire.buildGraph()`), so the logic lives in ONE place (jscpd discipline) and both surfaces behave
9
+ * identically.
10
+ *
11
+ * Behavior (mirrors the shell's `pollinate` action in `app.tsx`):
12
+ * - A SYNCHRONOUS in-flight ref guards re-entry: `setBuilding(true)` is async, so a render-state guard
13
+ * alone leaves a race where a rapid double-click fires `wire.buildGraph()` twice. The ref flips
14
+ * IMMEDIATELY, so exactly one POST goes out per build even on a double-click.
15
+ * - While in flight the button reads "Building…" and is disabled.
16
+ * - On a `{ built: true }` ack it calls `onBuilt()` so the surface RE-HYDRATES its graph source (re-run
17
+ * `wire.graph()`) and the fresh LOCAL snapshot renders WITHOUT a manual reload (no eventual-consistency
18
+ * wait — the build wrote a local file the next `GET /api/graph` reads immediately).
19
+ * - On a `{ built: false }` ack (the daemon rejected/failed, or the wire timed out/degraded) it shows an
20
+ * honest inline error line inviting a retry — the same button is right there, so there is NO CLI hint
21
+ * (the old `honeycomb graph build` command never existed).
22
+ *
23
+ * The wire NEVER throws (it degrades to a failure ack), but the host's `onBuilt` re-hydrate MAY (its type
24
+ * allows an async refresh). A `try/finally` therefore always clears the in-flight ref AND the "Building…"
25
+ * state, so a throwing re-hydrate can never wedge the button permanently disabled or stuck. Every visual
26
+ * value is an existing `var(--…)` DS token; no new dependency.
27
+ */
28
+ import React from "react";
29
+ import type { WireClient } from "./wire.js";
30
+ /** Props for {@link BuildGraphButton}. */
31
+ export interface BuildGraphButtonProps {
32
+ /** The shared wire client (the page/panel threads the one the shell built — never `createWireClient`). */
33
+ readonly wire: WireClient;
34
+ /**
35
+ * Called after a SUCCESSFUL build (`{ built: true }`) so the host surface re-hydrates its graph source
36
+ * (re-run `wire.graph()`) and the fresh snapshot renders without a reload. May be async; its result is
37
+ * awaited so the button stays in flight until the re-hydrate settles.
38
+ */
39
+ readonly onBuilt: () => void | Promise<void>;
40
+ }
41
+ /**
42
+ * The shared Build-graph button. Renders a primary button that triggers the real daemon build, re-hydrates
43
+ * the active graph on success, and surfaces an honest inline error inviting a retry on failure. Mirrors the
44
+ * `pollinateInFlightRef` synchronous re-entry guard so a double-click POSTs exactly once.
45
+ */
46
+ export declare function BuildGraphButton({ wire, onBuilt }: BuildGraphButtonProps): React.JSX.Element;
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The shared "Build graph" BUTTON — the codebase-graph build trigger, used on BOTH graph surfaces.
4
+ *
5
+ * Two places show the codebase-graph empty state — the full-page Graph (`pages/graph.tsx`) and the home
6
+ * GraphPanel (`panels.tsx`). Before, each showed a dead `honeycomb graph build` CLI hint (a command that
7
+ * does not exist — the graph is ONLY buildable from this UI). This single component replaces that with a
8
+ * working primary button wired to the daemon's already-served `POST /api/graph/build` (via
9
+ * `wire.buildGraph()`), so the logic lives in ONE place (jscpd discipline) and both surfaces behave
10
+ * identically.
11
+ *
12
+ * Behavior (mirrors the shell's `pollinate` action in `app.tsx`):
13
+ * - A SYNCHRONOUS in-flight ref guards re-entry: `setBuilding(true)` is async, so a render-state guard
14
+ * alone leaves a race where a rapid double-click fires `wire.buildGraph()` twice. The ref flips
15
+ * IMMEDIATELY, so exactly one POST goes out per build even on a double-click.
16
+ * - While in flight the button reads "Building…" and is disabled.
17
+ * - On a `{ built: true }` ack it calls `onBuilt()` so the surface RE-HYDRATES its graph source (re-run
18
+ * `wire.graph()`) and the fresh LOCAL snapshot renders WITHOUT a manual reload (no eventual-consistency
19
+ * wait — the build wrote a local file the next `GET /api/graph` reads immediately).
20
+ * - On a `{ built: false }` ack (the daemon rejected/failed, or the wire timed out/degraded) it shows an
21
+ * honest inline error line inviting a retry — the same button is right there, so there is NO CLI hint
22
+ * (the old `honeycomb graph build` command never existed).
23
+ *
24
+ * The wire NEVER throws (it degrades to a failure ack), but the host's `onBuilt` re-hydrate MAY (its type
25
+ * allows an async refresh). A `try/finally` therefore always clears the in-flight ref AND the "Building…"
26
+ * state, so a throwing re-hydrate can never wedge the button permanently disabled or stuck. Every visual
27
+ * value is an existing `var(--…)` DS token; no new dependency.
28
+ */
29
+ import React from "react";
30
+ import { Button } from "./primitives.js";
31
+ /**
32
+ * The shared Build-graph button. Renders a primary button that triggers the real daemon build, re-hydrates
33
+ * the active graph on success, and surfaces an honest inline error inviting a retry on failure. Mirrors the
34
+ * `pollinateInFlightRef` synchronous re-entry guard so a double-click POSTs exactly once.
35
+ */
36
+ export function BuildGraphButton({ wire, onBuilt }) {
37
+ const [building, setBuilding] = React.useState(false);
38
+ const [failed, setFailed] = React.useState(false);
39
+ // Synchronous re-entry guard (no double POST on rapid clicks — mirrors app.tsx's pollinateInFlightRef).
40
+ const inFlightRef = React.useRef(false);
41
+ // Guard against a state update after unmount (the build is slow; the surface may unmount mid-build).
42
+ const aliveRef = React.useRef(true);
43
+ React.useEffect(() => {
44
+ aliveRef.current = true;
45
+ return () => {
46
+ aliveRef.current = false;
47
+ };
48
+ }, []);
49
+ const onBuild = React.useCallback(async () => {
50
+ if (inFlightRef.current)
51
+ return; // synchronous guard — exactly one POST per build
52
+ inFlightRef.current = true;
53
+ setBuilding(true);
54
+ setFailed(false);
55
+ let built = false;
56
+ try {
57
+ const ack = await wire.buildGraph();
58
+ built = ack.built;
59
+ if (ack.built) {
60
+ // Re-hydrate the active graph source so the fresh LOCAL snapshot renders without a reload.
61
+ await onBuilt();
62
+ }
63
+ }
64
+ catch {
65
+ // The wire itself never throws; a throwing `onBuilt` re-hydrate must NOT wedge the guard. The
66
+ // build already succeeded if `built` is true (the snapshot is on disk) — we just couldn't refresh
67
+ // the view, so we don't flag it as a build failure; the `void onBuild()` caller swallows nothing.
68
+ }
69
+ finally {
70
+ // ALWAYS clear the guard + the in-flight visual, on every path — otherwise a throw leaves the
71
+ // button permanently disabled and stuck on "Building…".
72
+ inFlightRef.current = false;
73
+ if (aliveRef.current) {
74
+ setBuilding(false);
75
+ setFailed(!built);
76
+ }
77
+ }
78
+ }, [wire, onBuilt]);
79
+ return (_jsxs("div", { "data-testid": "build-graph", style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8 }, children: [_jsx(Button, { variant: "primary", onClick: () => void onBuild(), disabled: building, "data-testid": "build-graph-button", children: building ? "Building…" : "Build graph" }), failed && (_jsx("span", { "data-testid": "build-graph-error", style: { fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--severity-critical)" }, children: "Build failed \u2014 the daemon could not build the graph. Try again." }))] }));
80
+ }
81
+ //# sourceMappingURL=build-graph-button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-graph-button.js","sourceRoot":"","sources":["../../../src/dashboard/web/build-graph-button.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAezC;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAyB;IACxE,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,wGAAwG;IACxG,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,qGAAqG;IACrG,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;QACxB,OAAO,GAAG,EAAE;YACX,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;QAC1B,CAAC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,KAAK,CAAC,WAAW,CAAC,KAAK,IAAmB,EAAE;QAC3D,IAAI,WAAW,CAAC,OAAO;YAAE,OAAO,CAAC,iDAAiD;QAClF,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,SAAS,CAAC,KAAK,CAAC,CAAC;QACjB,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACpC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YAClB,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACf,2FAA2F;gBAC3F,MAAM,OAAO,EAAE,CAAC;YACjB,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,8FAA8F;YAC9F,kGAAkG;YAClG,kGAAkG;QACnG,CAAC;gBAAS,CAAC;YACV,8FAA8F;YAC9F,wDAAwD;YACxD,WAAW,CAAC,OAAO,GAAG,KAAK,CAAC;YAC5B,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACtB,WAAW,CAAC,KAAK,CAAC,CAAC;gBACnB,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC;YACnB,CAAC;QACF,CAAC;IACF,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpB,OAAO,CACN,8BAAiB,aAAa,EAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,aAC/G,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,iBAAc,oBAAoB,YAC3G,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa,GAC/B,EACR,MAAM,IAAI,CACV,8BAAkB,mBAAmB,EAAC,KAAK,EAAE,EAAE,UAAU,EAAE,kBAAkB,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,0BAA0B,EAAE,qFAEzH,CACP,IACI,CACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The `/buzzing` READINESS screen — hive PRD-004a. The addressable successor to PRD-002's
3
+ * `ReadinessSplash` (retired by this PRD, per PRD-004's "Overlap and supersession": "the
4
+ * `ReadinessSplash` becomes `/buzzing`"), now rendering the real per-service tile grid ADR-0004
5
+ * calls for instead of a coarse per-daemon list.
6
+ *
7
+ * Two independent concerns, kept deliberately separate:
8
+ * - DISMISSAL (bz-AC-9/bz-AC-10): polls `GET /api/fleet-status` and reuses the EXISTING, pinned
9
+ * `isFleetReady()` predicate (PRD-002a) — the identical rule the server gate (`gate.ts`)
10
+ * applies — so "ready" means one thing everywhere. Once ready, this screen hard-navigates to
11
+ * `/` so the SERVER gate re-evaluates health+auth on the fresh request and lands the operator
12
+ * on the dashboard or `/login`, whichever the (now-current) auth state calls for.
13
+ * - TILE RENDERING (bz-AC-1..8): the shared {@link useFleetTelemetry} hook (SSE-first,
14
+ * `/api/fleet-status` fail-soft), rendered one tile per registered service via the shared
15
+ * {@link ServiceStateIcon} vocabulary (PRD-004b). A single bad service only ever changes ITS
16
+ * tile (sd-AC-8/sd-AC-9) — the tile list itself is keyed by name and independent per row.
17
+ */
18
+ import React from "react";
19
+ export interface BuzzingScreenProps {
20
+ readonly assetBase: string;
21
+ /** Override the `/api/fleet-status` dismissal-poll interval (ms). Defaults to 1500. */
22
+ readonly pollMs?: number;
23
+ /** Test seam: called instead of the real navigation once the fleet is ready. */
24
+ readonly onReady?: () => void;
25
+ }
26
+ /**
27
+ * The `/buzzing` readiness screen. Uses the shared telemetry hook for the tile grid and its own,
28
+ * independent `isFleetReady()` poll for dismissal (see module doc for why the two are separate).
29
+ */
30
+ export declare function BuzzingScreen({ assetBase, pollMs, onReady }: BuzzingScreenProps): React.JSX.Element;
@@ -0,0 +1,135 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The `/buzzing` READINESS screen — hive PRD-004a. The addressable successor to PRD-002's
4
+ * `ReadinessSplash` (retired by this PRD, per PRD-004's "Overlap and supersession": "the
5
+ * `ReadinessSplash` becomes `/buzzing`"), now rendering the real per-service tile grid ADR-0004
6
+ * calls for instead of a coarse per-daemon list.
7
+ *
8
+ * Two independent concerns, kept deliberately separate:
9
+ * - DISMISSAL (bz-AC-9/bz-AC-10): polls `GET /api/fleet-status` and reuses the EXISTING, pinned
10
+ * `isFleetReady()` predicate (PRD-002a) — the identical rule the server gate (`gate.ts`)
11
+ * applies — so "ready" means one thing everywhere. Once ready, this screen hard-navigates to
12
+ * `/` so the SERVER gate re-evaluates health+auth on the fresh request and lands the operator
13
+ * on the dashboard or `/login`, whichever the (now-current) auth state calls for.
14
+ * - TILE RENDERING (bz-AC-1..8): the shared {@link useFleetTelemetry} hook (SSE-first,
15
+ * `/api/fleet-status` fail-soft), rendered one tile per registered service via the shared
16
+ * {@link ServiceStateIcon} vocabulary (PRD-004b). A single bad service only ever changes ITS
17
+ * tile (sd-AC-8/sd-AC-9) — the tile list itself is keyed by name and independent per row.
18
+ */
19
+ import React from "react";
20
+ import { isFleetReady } from "../../shared/fleet-readiness.js";
21
+ import { SERVICE_STATE_COLOR, SERVICE_STATE_LABEL, ServiceStateIcon } from "./service-icons.js";
22
+ import { useFleetTelemetry } from "./use-fleet-telemetry.js";
23
+ /** One service tile (bz-AC-3): the shared bee-state icon, the service name, and its state label. */
24
+ function ServiceTile({ service }) {
25
+ return (_jsxs("li", { "data-testid": `buzzing-tile-${service.name}`, "data-state": service.state, style: {
26
+ display: "flex",
27
+ alignItems: "center",
28
+ gap: 12,
29
+ padding: "10px 14px",
30
+ borderRadius: "var(--radius-md)",
31
+ border: "1px solid var(--border-subtle)",
32
+ background: "var(--bg-elevated)",
33
+ }, children: [_jsx("span", { style: { color: SERVICE_STATE_COLOR[service.state], display: "inline-flex", flex: "none" }, children: _jsx(ServiceStateIcon, { state: service.state }) }), _jsx("span", { style: { flex: 1, fontFamily: "var(--font-sans)", fontSize: "var(--text-sm)", color: "var(--text-primary)" }, children: service.name }), _jsx("span", { "data-testid": `buzzing-tile-state-${service.name}`, style: { fontFamily: "var(--font-mono)", fontSize: "var(--text-xs)", color: "var(--text-secondary)", textTransform: "lowercase" }, children: SERVICE_STATE_LABEL[service.state] })] }));
34
+ }
35
+ /** The distinct "no service enumerated yet" indicator (mirrors the old doctor-unreachable state). */
36
+ function AwaitingRegistrationIndicator() {
37
+ return (_jsxs("div", { "data-testid": "buzzing-empty", style: {
38
+ display: "flex",
39
+ flexDirection: "column",
40
+ alignItems: "center",
41
+ gap: 12,
42
+ width: "100%",
43
+ padding: "16px 20px",
44
+ background: "var(--bg-inset)",
45
+ border: "1px solid var(--border-subtle)",
46
+ borderRadius: "var(--radius-lg)",
47
+ }, children: [_jsx("span", { role: "img", "aria-label": "doctor supervisor: unreachable", style: { width: 8, height: 8, borderRadius: "50%", background: "var(--text-tertiary)", animation: "hc-readiness-pulse var(--dur-pollinate) var(--ease-in-out) infinite alternate" } }), _jsx("p", { style: { fontSize: "var(--text-sm)", color: "var(--text-secondary)", margin: 0, lineHeight: 1.5, textAlign: "center" }, children: "Waiting on doctor. No services are registered yet." })] }));
48
+ }
49
+ /**
50
+ * The `/buzzing` readiness screen. Uses the shared telemetry hook for the tile grid and its own,
51
+ * independent `isFleetReady()` poll for dismissal (see module doc for why the two are separate).
52
+ */
53
+ export function BuzzingScreen({ assetBase, pollMs = 1500, onReady }) {
54
+ const telemetry = useFleetTelemetry();
55
+ const [ready, setReady] = React.useState(false);
56
+ // bz-AC-9/bz-AC-10: reuse the pinned `isFleetReady()` rule so dismissal means the same thing
57
+ // here as it does in the server gate. Stops polling once ready (sticky, mirrors the retired
58
+ // ReadinessSplash's rs-AC-7/rs-AC-9 discipline).
59
+ React.useEffect(() => {
60
+ if (ready)
61
+ return;
62
+ let alive = true;
63
+ // One readiness request at a time: a slow/hung daemon must never stack overlapping polls
64
+ // (this screen already shares the endpoint with useFleetTelemetry's own fallback poll).
65
+ let inFlight = false;
66
+ const tick = async () => {
67
+ if (inFlight)
68
+ return;
69
+ inFlight = true;
70
+ try {
71
+ const response = await fetch("/api/fleet-status");
72
+ const next = (await response.json());
73
+ if (!alive)
74
+ return;
75
+ if (isFleetReady(next))
76
+ setReady(true);
77
+ }
78
+ catch {
79
+ // Keep the screen visible; the next poll retries.
80
+ }
81
+ finally {
82
+ inFlight = false;
83
+ }
84
+ };
85
+ void tick();
86
+ const id = setInterval(() => void tick(), pollMs);
87
+ return () => {
88
+ alive = false;
89
+ clearInterval(id);
90
+ };
91
+ }, [ready, pollMs]);
92
+ // On ready: navigate away. A HARD navigation (not a client-side route swap) so the SERVER gate
93
+ // re-runs health+auth on the fresh request (PRD-003a) and lands the operator correctly.
94
+ React.useEffect(() => {
95
+ if (!ready)
96
+ return;
97
+ if (onReady !== undefined) {
98
+ onReady();
99
+ return;
100
+ }
101
+ if (typeof window !== "undefined")
102
+ window.location.assign("/");
103
+ }, [ready, onReady]);
104
+ return (_jsxs("div", { "data-testid": "buzzing-screen", style: {
105
+ display: "flex",
106
+ alignItems: "center",
107
+ justifyContent: "center",
108
+ minHeight: "100vh",
109
+ padding: 32,
110
+ background: "var(--bg-canvas)",
111
+ textAlign: "center",
112
+ }, children: [_jsxs("div", { style: {
113
+ display: "flex",
114
+ flexDirection: "column",
115
+ alignItems: "center",
116
+ gap: 24,
117
+ width: "100%",
118
+ maxWidth: 460,
119
+ padding: "40px 32px",
120
+ background: "var(--bg-surface)",
121
+ border: "1px solid var(--border-default)",
122
+ borderRadius: "var(--radius-xl)",
123
+ }, children: [_jsx("span", { "aria-hidden": "true", style: {
124
+ display: "inline-flex",
125
+ alignItems: "center",
126
+ justifyContent: "center",
127
+ flex: "none",
128
+ width: 88,
129
+ height: 88,
130
+ borderRadius: "50%",
131
+ background: "var(--honey-subtle)",
132
+ border: "1px solid var(--honey-border)",
133
+ }, children: _jsx("img", { src: `${assetBase}/honeycomb-memory-cluster.svg`, width: 48, height: 48, alt: "" }) }), _jsx("h1", { style: { fontSize: "var(--text-xl)", fontWeight: 700, color: "var(--text-primary)", margin: 0, letterSpacing: "-0.02em" }, children: "Waiting for the hive\u2026" }), _jsxs("div", { "data-testid": "buzzing-status-region", role: "status", "aria-live": "polite", style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, width: "100%" }, children: [_jsx("p", { style: { fontSize: "var(--text-sm)", color: "var(--text-secondary)", margin: 0, lineHeight: 1.5 }, children: "Starting required services. This usually takes a few seconds on a cold boot." }), telemetry.services.length === 0 ? (_jsx(AwaitingRegistrationIndicator, {})) : (_jsx("ul", { "data-testid": "buzzing-tile-grid", style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 8, width: "100%", textAlign: "left" }, children: telemetry.services.map((service) => (_jsx(ServiceTile, { service: service }, service.name))) }))] })] }), _jsx("style", { children: "@keyframes hc-readiness-pulse { from { opacity: .45 } to { opacity: 1 } }" })] }));
134
+ }
135
+ //# sourceMappingURL=buzzing-screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buzzing-screen.js","sourceRoot":"","sources":["../../../src/dashboard/web/buzzing-screen.tsx"],"names":[],"mappings":"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"}