@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,54 @@
1
+ /**
2
+ * The daemon-served FOLDER PICKER — PRD-059b (b-AC-2 / b-AC-3 / b-AC-4 / b-AC-5).
3
+ *
4
+ * ── Why the daemon serves the tree ───────────────────────────────────────────
5
+ * A browser CANNOT hand back an absolute filesystem path — the File System Access API returns an
6
+ * opaque handle by design. The local daemon already has fs access, so it serves a dirs-only browse
7
+ * tree (`GET /api/diagnostics/fs/browse`) and the dashboard renders it; the user navigates, picks a
8
+ * folder, and the dashboard posts the chosen ABSOLUTE path back to bind. This is the ONLY component
9
+ * that can return a real, bindable absolute path (b-AC-2).
10
+ *
11
+ * ── What this component does ─────────────────────────────────────────────────
12
+ * It is a controlled, self-contained picker reused by BOTH 059b (the first-run empty-state CTA) and
13
+ * 059c (the Projects page "Add a project" flow). It:
14
+ * 1. Browses from the daemon's allowed root (home by default), letting the user descend into child
15
+ * directories and climb back to the parent (never above the root — the daemon clamps).
16
+ * 2. Marks git repos (a bind hint) and, on selecting a folder, pre-fills the project-name field
17
+ * from the daemon's CLI-identical suggestion when the chosen folder carries a git remote (b-AC-3)
18
+ * — derived daemon-side; the picker just surfaces it editably.
19
+ * 3. On confirm, POSTs `projects/bind { path, name }` and calls `onBound` with the bind ack so the
20
+ * caller advances (059b → the Projects page; 059c → re-list).
21
+ *
22
+ * ── Daemon-down / local-mode-off → plain message + CLI fallback (b-AC-5) ─────
23
+ * Every read/write degrades through the wire's fail-soft layer (an empty browse / a not-bound ack),
24
+ * never a hang. When the browse comes back empty AND errored (or the daemon is unreachable), the
25
+ * picker shows a plain message and the `honeycomb project bind` CLI hint — never a silent failure.
26
+ *
27
+ * Security (inherited): the surface is LOCAL-MODE-ONLY (the daemon routes 404 otherwise); every path
28
+ * renders as ESCAPED TEXT (React default); NO token/secret rides any browse/bind body. Every visual
29
+ * value is an existing `var(--…)` design token (no new token).
30
+ */
31
+ import React from "react";
32
+ import { type BindAckWire, type WireClient } from "./wire.js";
33
+ /** The CLI command shown in the daemon-down / local-mode-off fallback (b-AC-5). */
34
+ export declare const CLI_BIND_HINT: "honeycomb project bind";
35
+ /** Derive a default project-name suggestion from a chosen folder's basename (the picker's local fallback). */
36
+ export declare function basenameOf(absPath: string): string;
37
+ /** Props for {@link FolderPicker}. */
38
+ export interface FolderPickerProps {
39
+ /** The shared wire client (the caller passes the SAME one — never `createWireClient`). */
40
+ readonly wire: WireClient;
41
+ /**
42
+ * Called with the bind ack after a SUCCESSFUL bind (`bound:true`). The caller advances: 059b routes
43
+ * to the Projects page; 059c re-lists + closes. A rejected bind stays in the picker with the error.
44
+ */
45
+ readonly onBound: (ack: BindAckWire) => void;
46
+ /** Optional cancel affordance (059c renders the picker in a modal with a Cancel). Omitted ⇒ no cancel. */
47
+ readonly onCancel?: () => void;
48
+ }
49
+ /**
50
+ * The folder picker (059b). Browses the daemon's dirs-only tree, lets the user pick a folder (with a
51
+ * git-derived name suggestion), and binds the chosen absolute path. Reused by the first-run CTA (059b)
52
+ * and the Projects page "Add a project" flow (059c).
53
+ */
54
+ export declare function FolderPicker({ wire, onBound, onCancel }: FolderPickerProps): React.JSX.Element;
@@ -0,0 +1,125 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * The daemon-served FOLDER PICKER — PRD-059b (b-AC-2 / b-AC-3 / b-AC-4 / b-AC-5).
4
+ *
5
+ * ── Why the daemon serves the tree ───────────────────────────────────────────
6
+ * A browser CANNOT hand back an absolute filesystem path — the File System Access API returns an
7
+ * opaque handle by design. The local daemon already has fs access, so it serves a dirs-only browse
8
+ * tree (`GET /api/diagnostics/fs/browse`) and the dashboard renders it; the user navigates, picks a
9
+ * folder, and the dashboard posts the chosen ABSOLUTE path back to bind. This is the ONLY component
10
+ * that can return a real, bindable absolute path (b-AC-2).
11
+ *
12
+ * ── What this component does ─────────────────────────────────────────────────
13
+ * It is a controlled, self-contained picker reused by BOTH 059b (the first-run empty-state CTA) and
14
+ * 059c (the Projects page "Add a project" flow). It:
15
+ * 1. Browses from the daemon's allowed root (home by default), letting the user descend into child
16
+ * directories and climb back to the parent (never above the root — the daemon clamps).
17
+ * 2. Marks git repos (a bind hint) and, on selecting a folder, pre-fills the project-name field
18
+ * from the daemon's CLI-identical suggestion when the chosen folder carries a git remote (b-AC-3)
19
+ * — derived daemon-side; the picker just surfaces it editably.
20
+ * 3. On confirm, POSTs `projects/bind { path, name }` and calls `onBound` with the bind ack so the
21
+ * caller advances (059b → the Projects page; 059c → re-list).
22
+ *
23
+ * ── Daemon-down / local-mode-off → plain message + CLI fallback (b-AC-5) ─────
24
+ * Every read/write degrades through the wire's fail-soft layer (an empty browse / a not-bound ack),
25
+ * never a hang. When the browse comes back empty AND errored (or the daemon is unreachable), the
26
+ * picker shows a plain message and the `honeycomb project bind` CLI hint — never a silent failure.
27
+ *
28
+ * Security (inherited): the surface is LOCAL-MODE-ONLY (the daemon routes 404 otherwise); every path
29
+ * renders as ESCAPED TEXT (React default); NO token/secret rides any browse/bind body. Every visual
30
+ * value is an existing `var(--…)` design token (no new token).
31
+ */
32
+ import React from "react";
33
+ import { Badge, Button, Input } from "./primitives.js";
34
+ import { EMPTY_BROWSE } from "./wire.js";
35
+ /** The CLI command shown in the daemon-down / local-mode-off fallback (b-AC-5). */
36
+ export const CLI_BIND_HINT = "honeycomb project bind";
37
+ /** Derive a default project-name suggestion from a chosen folder's basename (the picker's local fallback). */
38
+ export function basenameOf(absPath) {
39
+ const trimmed = absPath.replace(/[\\/]+$/, "");
40
+ const parts = trimmed.split(/[\\/]/);
41
+ const base = parts[parts.length - 1] ?? "";
42
+ return base;
43
+ }
44
+ /** One row in the browse tree — a child directory (descend on click), marked if it is a git repo. */
45
+ function BrowseRow({ child, onDescend }) {
46
+ return (_jsxs("button", { type: "button", "data-testid": "browse-row", "data-path": child.path, onClick: () => onDescend(child.path), style: {
47
+ display: "flex",
48
+ alignItems: "center",
49
+ gap: 10,
50
+ width: "100%",
51
+ textAlign: "left",
52
+ padding: "9px 12px",
53
+ background: "var(--bg-elevated)",
54
+ border: "1px solid var(--border-default)",
55
+ borderRadius: "var(--radius-md)",
56
+ cursor: "pointer",
57
+ color: "var(--text-primary)",
58
+ }, children: [_jsx("svg", { width: 15, height: 15, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", style: { flex: "none", color: "var(--text-tertiary)" }, children: _jsx("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }) }), _jsx("span", { style: { flex: 1, fontFamily: "var(--font-mono)", fontSize: 13, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", minWidth: 0 }, children: child.name }), child.isGitRepo && (_jsx(Badge, { tone: "honey", mono: true, children: "git" }))] }));
59
+ }
60
+ /**
61
+ * The folder picker (059b). Browses the daemon's dirs-only tree, lets the user pick a folder (with a
62
+ * git-derived name suggestion), and binds the chosen absolute path. Reused by the first-run CTA (059b)
63
+ * and the Projects page "Add a project" flow (059c).
64
+ */
65
+ export function FolderPicker({ wire, onBound, onCancel }) {
66
+ const [browse, setBrowse] = React.useState(EMPTY_BROWSE);
67
+ const [hydrated, setHydrated] = React.useState(false);
68
+ // The folder the user has SELECTED to bind (distinct from the dir being browsed). Null = none yet.
69
+ const [selected, setSelected] = React.useState(null);
70
+ const [name, setName] = React.useState("");
71
+ const [busy, setBusy] = React.useState(false);
72
+ const [error, setError] = React.useState("");
73
+ // A synchronous in-flight guard so a rapid double-click never fires two binds.
74
+ const inFlightRef = React.useRef(false);
75
+ /** Browse a dir (or the root when `path` is undefined). Fail-soft via the wire. */
76
+ const goTo = React.useCallback(async (path) => {
77
+ const body = await wire.fsBrowse(path);
78
+ setBrowse(body);
79
+ setHydrated(true);
80
+ }, [wire]);
81
+ // Hydrate the root on mount.
82
+ React.useEffect(() => {
83
+ void goTo(undefined);
84
+ }, [goTo]);
85
+ // b-AC-5: the daemon is unreachable / local-mode is off (or the dir is unreadable) when the browse
86
+ // returns no children AND an error (or no resolved path at all). Show the plain message + CLI hint.
87
+ const unavailable = hydrated && browse.path === "" && browse.children.length === 0;
88
+ const dirErrored = browse.error !== undefined && browse.error !== "";
89
+ /** Select the CURRENTLY-BROWSED dir as the folder to bind, pre-filling the name (b-AC-3). */
90
+ const selectCurrent = React.useCallback(() => {
91
+ if (browse.path === "")
92
+ return;
93
+ setSelected({ path: browse.path, isGitRepo: false });
94
+ // The name suggestion: the daemon derives the git-remote-or-basename name on bind, but we
95
+ // pre-fill the basename locally so the field is never blank; the user edits before confirm.
96
+ setName(basenameOf(browse.path));
97
+ setError("");
98
+ }, [browse.path]);
99
+ /** Select a CHILD folder (without descending) as the folder to bind. */
100
+ const selectChild = React.useCallback((child) => {
101
+ setSelected({ path: child.path, isGitRepo: child.isGitRepo });
102
+ setName(basenameOf(child.path));
103
+ setError("");
104
+ }, []);
105
+ /** Confirm the bind: POST the absolute path + name, advance on success, surface the error otherwise. */
106
+ const confirm = React.useCallback(async () => {
107
+ if (selected === null || inFlightRef.current)
108
+ return;
109
+ inFlightRef.current = true;
110
+ setBusy(true);
111
+ setError("");
112
+ const ack = await wire.bindProject({ path: selected.path, ...(name.trim() !== "" ? { name: name.trim() } : {}) });
113
+ setBusy(false);
114
+ inFlightRef.current = false;
115
+ if (ack.bound) {
116
+ onBound(ack);
117
+ return;
118
+ }
119
+ // A rejected bind (the reserved inbox, a degenerate name, a non-absolute path, or daemon-down)
120
+ // stays in the picker with the daemon's redacted reason — never a silent failure (b-AC-5).
121
+ setError(ack.error !== undefined && ack.error !== "" ? ack.error : "Could not bind that folder.");
122
+ }, [selected, name, wire, onBound]);
123
+ return (_jsx("div", { "data-testid": "folder-picker", style: { display: "flex", flexDirection: "column", gap: 14 }, children: unavailable ? (_jsxs("div", { "data-testid": "picker-unavailable", style: { display: "flex", flexDirection: "column", gap: 8, padding: "16px", background: "var(--bg-surface)", border: "1px solid var(--border-default)", borderRadius: "var(--radius-lg)" }, children: [_jsx("span", { style: { fontSize: 14, color: "var(--text-secondary)" }, children: "The folder browser isn\u2019t available right now." }), _jsxs("span", { style: { fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--text-tertiary)" }, children: ["Bind a folder from your terminal instead: ", _jsx("code", { style: { color: "var(--honey)" }, children: CLI_BIND_HINT })] }), onCancel !== undefined && (_jsx("div", { children: _jsx(Button, { variant: "ghost", size: "sm", onClick: onCancel, children: "Close" }) }))] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }, children: [_jsx("span", { "data-testid": "picker-path", style: { flex: 1, minWidth: 0, fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--text-secondary)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: browse.path !== "" ? browse.path : "loading…" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => void goTo(browse.parent ?? undefined), disabled: browse.parent === null, title: browse.parent === null ? "at the allowed root" : "up one level", children: "\u2191 up" }), _jsx(Button, { variant: "secondary", size: "sm", onClick: selectCurrent, disabled: browse.path === "", "data-testid": "select-current", children: "Use this folder" })] }), _jsx("div", { "data-testid": "browse-list", style: { display: "flex", flexDirection: "column", gap: 6, maxHeight: 280, overflowY: "auto" }, children: !hydrated ? (_jsx("div", { style: { fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--text-tertiary)" }, children: "loading\u2026" })) : browse.children.length === 0 ? (_jsx("div", { style: { padding: "10px 4px", fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--text-tertiary)" }, children: dirErrored ? "This folder couldn’t be read." : "No sub-folders here — use this folder, or go up." })) : (browse.children.map((child) => (_jsxs("div", { style: { display: "flex", gap: 8 }, children: [_jsx("div", { style: { flex: 1, minWidth: 0 }, children: _jsx(BrowseRow, { child: child, onDescend: (p) => void goTo(p) }) }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => selectChild(child), "data-testid": "select-child", title: "select this folder to bind", children: "select" })] }, child.path)))) }), selected !== null && (_jsxs("div", { "data-testid": "picker-confirm", style: { display: "flex", flexDirection: "column", gap: 10, padding: 14, background: "var(--bg-surface)", border: "1px solid var(--border-default)", borderRadius: "var(--radius-lg)" }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [_jsx("span", { style: { fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--text-tertiary)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: "folder" }), _jsx("span", { style: { fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--text-secondary)", wordBreak: "break-all" }, children: selected.path }), selected.isGitRepo && _jsx(Badge, { tone: "honey", mono: true, children: "git" })] }), _jsxs("label", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [_jsx("span", { style: { fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--text-tertiary)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: "project name" }), _jsx(Input, { mono: true, value: name, placeholder: "project name", onChange: (e) => setName(e.target.value), "data-testid": "picker-name" })] }), _jsxs("div", { style: { display: "flex", gap: 10, alignItems: "center" }, children: [_jsx(Button, { variant: "primary", onClick: () => void confirm(), disabled: busy || name.trim() === "", "data-testid": "picker-bind", children: busy ? "Binding…" : "Bind project" }), onCancel !== undefined && (_jsx(Button, { variant: "ghost", onClick: onCancel, disabled: busy, children: "Cancel" })), error !== "" && (_jsx("span", { "data-testid": "picker-error", style: { fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--severity-critical)" }, children: error }))] })] }))] })) }));
124
+ }
125
+ //# sourceMappingURL=folder-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-picker.js","sourceRoot":"","sources":["../../../src/dashboard/web/folder-picker.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * The codebase-graph LAYOUT — PRD-035c (D-1, FR-2, FR-8).
3
+ *
4
+ * A pure, deterministic node-placement function shared by the dashboard mini-widget
5
+ * ({@link import("./panels.js").GraphCanvas}) and, later, the PRD-041 full-page graph. It
6
+ * replaces the old hardcoded `NODE_POS` map (which keyed on six fixed ids like `daemon`/`recall`
7
+ * that REAL snapshot ids — file paths / symbols — never matched, so every node was skipped and
8
+ * the canvas rendered blank). Here every node gets a computed position, so an arbitrary-id
9
+ * snapshot draws every node and edge.
10
+ *
11
+ * Determinism is the contract: the placement is a pure function of (node order, count, viewBox)
12
+ * with NO randomness, NO animation loop, and NO time/Date input — so a render is stable and a
13
+ * unit test can assert exact coordinates (PRD-035c AC-7 / OQ-1). The shape is the radial/grid
14
+ * placement OQ-1 settled on: one node is centered, the rest sit on a ring around it, ordered by
15
+ * their index in the input array.
16
+ */
17
+ /** A graph node as the wire ships it — id + display label + kind (drives fill color). */
18
+ export interface LayoutNode {
19
+ readonly id: string;
20
+ readonly label: string;
21
+ readonly kind: string;
22
+ }
23
+ /** A graph edge as the wire ships it — endpoint ids + a kind. */
24
+ export interface LayoutEdge {
25
+ readonly from: string;
26
+ readonly to: string;
27
+ readonly kind: string;
28
+ }
29
+ /** A computed 2-D position inside the canvas viewBox. */
30
+ export interface Point {
31
+ readonly x: number;
32
+ readonly y: number;
33
+ }
34
+ /** The canvas box the layout fits inside (origin is `0,0`; width/height are the SVG viewBox extent). */
35
+ export interface ViewBox {
36
+ readonly width: number;
37
+ readonly height: number;
38
+ }
39
+ /**
40
+ * Compute a deterministic position for every node, keyed on its index in `nodes` (D-1, FR-2).
41
+ *
42
+ * Placement (radial, stable):
43
+ * - 0 nodes → an empty map.
44
+ * - 1 node → centered.
45
+ * - 2+ nodes → the FIRST node is centered; the remaining `n-1` sit evenly on a ring around it,
46
+ * starting at the top (−90°) and going clockwise. The ring radius is the largest circle that
47
+ * fits inside the padded box, so marks never clip.
48
+ *
49
+ * The result is a `Map<id, Point>` so the caller looks a position up by node id (and an edge looks
50
+ * up its two endpoints). A later node with a duplicate id would overwrite an earlier one in the
51
+ * map; real snapshots have unique ids (file paths / symbols), so this is a non-issue in practice
52
+ * and keeps the function total. The `edges` argument is accepted for signature stability with a
53
+ * future force-directed variant (PRD-041) but is not consulted by this deterministic placement.
54
+ *
55
+ * @param nodes the graph nodes, in render order (the order fixes each node's slot).
56
+ * @param _edges the graph edges (unused by the deterministic radial placement; kept for the
57
+ * shared signature PRD-041 reuses).
58
+ * @param viewBox the canvas extent the positions must fit inside.
59
+ * @returns a map from node id to its computed `{x, y}` position.
60
+ */
61
+ export declare function layout(nodes: readonly LayoutNode[], _edges: readonly LayoutEdge[], viewBox: ViewBox): Map<string, Point>;
62
+ /**
63
+ * The neighbor ids of `id` in `edges` (D-3, FR-5): every node reachable by an edge with `id` on
64
+ * either end (`from === id` OR `to === id`). Self-loops and an id absent from the edge set yield an
65
+ * empty list. The result is de-duplicated and preserves first-seen edge order so the detail surface
66
+ * lists neighbors stably. Pure — no DOM, no state — so it is unit-assertable alongside {@link layout}.
67
+ *
68
+ * @param id the selected node's id.
69
+ * @param edges the graph edges.
70
+ * @returns the de-duplicated neighbor ids, in first-seen order.
71
+ */
72
+ export declare function neighborsOf(id: string, edges: readonly LayoutEdge[]): string[];
73
+ /** One related-node group: the relation `kind` (e.g. `imports`/`calls`/`depends_on`) + its neighbor ids. */
74
+ export interface RelationGroup {
75
+ /** The edge `kind` this group collects (the relation, verbatim from the snapshot). */
76
+ readonly kind: string;
77
+ /** The de-duplicated neighbor ids reached by an edge of this `kind`, in first-seen order. */
78
+ readonly ids: readonly string[];
79
+ }
80
+ /**
81
+ * The neighbors of `id` split by DIRECTION and RELATION (PRD-041a D-4 / FR-4) — the full-page
82
+ * detail-panel breakdown the mini-widget's flat {@link neighborsOf} cannot express.
83
+ *
84
+ * - `outgoing` = edges where `from === id`, grouped by `edge.kind` (what `id` imports / calls).
85
+ * - `incoming` = edges where `to === id`, grouped by `edge.kind` (what imports / calls `id`).
86
+ *
87
+ * Self-loops (`from === to === id`) are dropped (they are not a neighbor). Within each relation
88
+ * group the neighbor ids are de-duplicated and kept in first-seen edge order so the panel lists
89
+ * stably. Relation groups themselves are ordered by first appearance. The split is purely derived
90
+ * from `edges` (no extra fetch), and works for ANY relation kind — the codebase graph's
91
+ * `imports`/`calls` AND the memory graph's `depends_on`/`supersedes`/`mentions` render with no
92
+ * special-casing (041b D-3). Pure — no DOM, no state — so it is unit-assertable.
93
+ *
94
+ * @param id the selected node's id.
95
+ * @param edges the graph edges.
96
+ * @returns `{ outgoing, incoming }`, each an ordered list of {@link RelationGroup}.
97
+ */
98
+ export declare function splitNeighbors(id: string, edges: readonly LayoutEdge[]): {
99
+ readonly outgoing: readonly RelationGroup[];
100
+ readonly incoming: readonly RelationGroup[];
101
+ };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-layout.js","sourceRoot":"","sources":["../../../src/dashboard/web/graph-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA4BH,+FAA+F;AAC/F,MAAM,OAAO,GAAG,EAAE,CAAC;AAEnB;;;;;;GAMG;AACH,MAAM,QAAQ,GAAG,EAAE,CAAC;AAEpB;;;;;GAKG;AACH,SAAS,UAAU,CAAC,KAA4B,EAAE,OAAgB;IACjE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC3C,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC;IACzD,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACjC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YACtB,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC;YACpD,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;SACrD,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,MAAM,CACrB,KAA4B,EAC5B,MAA6B,EAC7B,OAAgB;IAEhB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiB,CAAC;IAC3C,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE9B,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IAC7B,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAE9B,0BAA0B;IAC1B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACjE,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,+FAA+F;IAC/F,IAAI,CAAC,GAAG,QAAQ;QAAE,OAAO,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAEpD,4FAA4F;IAC5F,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACb,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACzC,SAAS;QACV,CAAC;QACD,qFAAqF;QACrF,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;QACjE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE;YACtB,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAChC,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;SAChC,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU,EAAE,KAA4B;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,KAAK,GAAkB,IAAI,CAAC;QAChC,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE;YAAE,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;aAC1C,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE;YAAE,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC;QACtD,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAChB,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACF,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAUD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,cAAc,CAC7B,EAAU,EACV,KAA4B;IAE5B,uFAAuF;IACvF,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;IACxC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAoB,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC,CAAC,2DAA2D;IAC9F,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,sEAAsE;IACtE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;YAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACpB,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACvB,CAAC;gBACD,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;QACF,CAAC;QACD,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACjB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;oBACtB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACpB,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACvB,CAAC;gBACD,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO;QACN,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtE,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;KACtE,CAAC;AACH,CAAC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The home page's HARNESS STRIP — PRD-038c (the third home area, below the recall center).
3
+ *
4
+ * An at-a-glance surface answering three dogfooder questions from the PRD-039 registry/telemetry
5
+ * (the shared `wire.harnesses()` backbone — the REAL endpoint, not the OQ-1 log-inference fallback,
6
+ * which has shipped):
7
+ * 1. WIRED-IN CHIPS (c-AC-1) — one `Badge` chip per INSTALLED harness, toned active/idle from
8
+ * last-seen recency; an uninstalled harness renders NO chip.
9
+ * 2. SHORT-TAIL LIVE STREAM (c-AC-2) — a tighter-capped reuse of the SAME `/api/logs` feed the
10
+ * Dashboard live log polls (`wire.logs`), rendered through the existing `LiveLog` panel. The
11
+ * records are `RequestLogRecord`s (method/path/status/mode/org — NO header/token/body), so no
12
+ * secret can leak (c-AC-5 / parent D-7). `/api/logs` carries no per-line harness field (c-OQ-3),
13
+ * so the home tail is labeled generically rather than per-harness.
14
+ * 3. PER-HARNESS KPI TILES (c-AC-3) — produced by `installed.map(...)` over the resolved
15
+ * installed set (turns-captured + last-seen). DYNAMIC by construction: there is NO literal
16
+ * six-harness array in the render path, so adding/removing a harness changes which tiles appear.
17
+ *
18
+ * This is the home STRIP only — the deep Harnesses page (`#/harnesses`, PRD-039) and the full Logs
19
+ * page (`#/logs`, PRD-043) own the deep experiences. It reuses the shared `AGENT_DOT` palette and the
20
+ * `relativeLastSeen` / `uiStatus` helpers from the Harnesses page (one source, no fork — jscpd),
21
+ * composes only the existing `Panel` / `Badge` / `Kpi` / `LiveLog` primitives, and adds NO new daemon
22
+ * route, token, or design system (c-AC-5).
23
+ */
24
+ import React from "react";
25
+ import type { HarnessStatusWire } from "./wire.js";
26
+ /** Props for {@link HarnessStrip}. The installed set + the short-tail feed are resolved by the page. */
27
+ export interface HarnessStripProps {
28
+ /** The full six-harness telemetry rows from `wire.harnesses()` (the page filters to installed). */
29
+ readonly harnesses: readonly HarnessStatusWire[];
30
+ /** The short-tail, pre-formatted, secret-free log lines (a tighter `wire.logs` cap than the full log). */
31
+ readonly streamLines: readonly string[];
32
+ }
33
+ /**
34
+ * The home harness area (c-AC-1/2/3). Filters the telemetry to the INSTALLED set, then renders the
35
+ * wired-in chips, the per-harness KPI tiles, and the short-tail live stream. Every chip/tile derives
36
+ * from `installed.map(...)` — uninstalled harnesses produce nothing (dynamic, no hardcoded list).
37
+ */
38
+ export declare function HarnessStrip({ harnesses, streamLines }: HarnessStripProps): React.JSX.Element;
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The home page's HARNESS STRIP — PRD-038c (the third home area, below the recall center).
4
+ *
5
+ * An at-a-glance surface answering three dogfooder questions from the PRD-039 registry/telemetry
6
+ * (the shared `wire.harnesses()` backbone — the REAL endpoint, not the OQ-1 log-inference fallback,
7
+ * which has shipped):
8
+ * 1. WIRED-IN CHIPS (c-AC-1) — one `Badge` chip per INSTALLED harness, toned active/idle from
9
+ * last-seen recency; an uninstalled harness renders NO chip.
10
+ * 2. SHORT-TAIL LIVE STREAM (c-AC-2) — a tighter-capped reuse of the SAME `/api/logs` feed the
11
+ * Dashboard live log polls (`wire.logs`), rendered through the existing `LiveLog` panel. The
12
+ * records are `RequestLogRecord`s (method/path/status/mode/org — NO header/token/body), so no
13
+ * secret can leak (c-AC-5 / parent D-7). `/api/logs` carries no per-line harness field (c-OQ-3),
14
+ * so the home tail is labeled generically rather than per-harness.
15
+ * 3. PER-HARNESS KPI TILES (c-AC-3) — produced by `installed.map(...)` over the resolved
16
+ * installed set (turns-captured + last-seen). DYNAMIC by construction: there is NO literal
17
+ * six-harness array in the render path, so adding/removing a harness changes which tiles appear.
18
+ *
19
+ * This is the home STRIP only — the deep Harnesses page (`#/harnesses`, PRD-039) and the full Logs
20
+ * page (`#/logs`, PRD-043) own the deep experiences. It reuses the shared `AGENT_DOT` palette and the
21
+ * `relativeLastSeen` / `uiStatus` helpers from the Harnesses page (one source, no fork — jscpd),
22
+ * composes only the existing `Panel` / `Badge` / `Kpi` / `LiveLog` primitives, and adds NO new daemon
23
+ * route, token, or design system (c-AC-5).
24
+ */
25
+ import React from "react";
26
+ import { Badge, Kpi } from "./primitives.js";
27
+ import { AGENT_DOT, AGENT_DOT_FALLBACK, LiveLog, Panel } from "./panels.js";
28
+ import { relativeLastSeen, uiStatus } from "./pages/harnesses.js";
29
+ /** The Badge tone per at-a-glance harness status — verified for active, neutral for idle. */
30
+ const CHIP_TONE = { active: "verified", idle: "neutral" };
31
+ /**
32
+ * One wired-in chip (c-AC-1): a mono dot `Badge` toned by recency. Only ever rendered for an INSTALLED
33
+ * harness (the caller filters), so `uiStatus` here is `active` or `idle` — never `not installed`.
34
+ */
35
+ function HarnessChip({ h }) {
36
+ const status = uiStatus(h);
37
+ const tone = status === "active" ? CHIP_TONE.active : CHIP_TONE.idle;
38
+ return (_jsx("span", { "data-testid": `harness-chip-${h.name}`, "data-harness": h.name, title: `${h.name} · last seen ${relativeLastSeen(h.lastSeen)}`, style: { display: "inline-flex" }, children: _jsxs(Badge, { tone: tone, mono: true, dot: true, style: { background: "transparent" }, children: [_jsx("span", { style: { width: 6, height: 6, borderRadius: "50%", flex: "none", background: AGENT_DOT[h.name] ?? AGENT_DOT_FALLBACK } }), h.name] }) }));
39
+ }
40
+ /**
41
+ * One per-harness KPI cell (c-AC-3): the harness name + dot, a turns-captured `Kpi`, and a last-seen
42
+ * line. Composed from the existing `Kpi` primitive (borderless inner — the cell carries the frame).
43
+ */
44
+ function HarnessTile({ h }) {
45
+ return (_jsxs("div", { "data-testid": `harness-tile-${h.name}`, "data-harness": h.name, style: {
46
+ display: "flex",
47
+ flexDirection: "column",
48
+ gap: 10,
49
+ padding: 14,
50
+ background: "var(--bg-surface)",
51
+ border: "1px solid var(--border-default)",
52
+ borderRadius: "var(--radius-lg)",
53
+ }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [_jsx("span", { style: { width: 8, height: 8, borderRadius: "50%", flex: "none", background: AGENT_DOT[h.name] ?? AGENT_DOT_FALLBACK } }), _jsx("span", { style: { fontFamily: "var(--font-mono)", fontSize: 13, fontWeight: 600, color: "var(--text-primary)" }, children: h.name })] }), _jsx(Kpi, { label: "turns captured", value: h.turnsCaptured.toLocaleString(), accent: h.active ? "verified" : "neutral", style: { padding: 0, background: "transparent", border: "none" } }), _jsxs("span", { title: h.lastSeen ?? "never", style: { fontFamily: "var(--font-mono)", fontSize: 12, color: "var(--text-tertiary)" }, children: ["last seen ", relativeLastSeen(h.lastSeen)] })] }));
54
+ }
55
+ /**
56
+ * The home harness area (c-AC-1/2/3). Filters the telemetry to the INSTALLED set, then renders the
57
+ * wired-in chips, the per-harness KPI tiles, and the short-tail live stream. Every chip/tile derives
58
+ * from `installed.map(...)` — uninstalled harnesses produce nothing (dynamic, no hardcoded list).
59
+ */
60
+ export function HarnessStrip({ harnesses, streamLines }) {
61
+ // The render path keys off the live installed subset only — no literal harness array (D-5).
62
+ const installed = React.useMemo(() => harnesses.filter((h) => h.installed), [harnesses]);
63
+ return (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 16 }, children: [_jsx(Panel, { title: "Harnesses", eyebrow: `${installed.length} wired in`, children: installed.length === 0 ? (_jsx("div", { style: { padding: "10px 4px", fontSize: 13, color: "var(--text-tertiary)" }, children: "No harnesses wired in yet." })) : (_jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 14 }, children: [_jsx("div", { "data-testid": "harness-chips", style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: installed.map((h) => (_jsx(HarnessChip, { h: h }, h.name))) }), _jsx("div", { "data-testid": "harness-tiles", style: { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))", gap: 12 }, children: installed.map((h) => (_jsx(HarnessTile, { h: h }, h.name))) })] })) }), _jsx(LiveLog, { lines: streamLines })] }));
64
+ }
65
+ //# sourceMappingURL=harness-strip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness-strip.js","sourceRoot":"","sources":["../../../src/dashboard/web/harness-strip.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The top HEALTH RAIL — hive PRD-005a. A strip of per-service status pills, mounted once in
3
+ * the {@link Shell} (`app.tsx`) so it is present on EVERY in-app route (hr-AC-1), giving an
4
+ * operator constant fleet awareness without leaving their current page.
5
+ *
6
+ * Fed by the SAME shared {@link useFleetTelemetry} hook `/buzzing` uses (SSE-first, `/api/fleet-status`
7
+ * fail-soft — hr-AC-3/hr-AC-4/hr-AC-5) and the SAME shared {@link ServiceStateIcon} vocabulary
8
+ * (PRD-004b) as `/buzzing`'s tiles, so a state means the same icon on both surfaces (hr-AC-2).
9
+ *
10
+ * Memory (hr-AC-7): the rail renders only the hook's CURRENT `services` snapshot on every render —
11
+ * it holds no history of its own, so nothing here grows with connection time.
12
+ */
13
+ import React from "react";
14
+ /** The `/health` page's route (PRD-005b), so the rail can link an operator straight to detail. */
15
+ export declare const HEALTH_ROUTE: "/health";
16
+ /** Props for {@link HealthRail}. */
17
+ export interface HealthRailProps {
18
+ /** Navigate to the full `/health` page (the shell's path router). */
19
+ readonly onOpenHealth?: () => void;
20
+ }
21
+ /**
22
+ * The health rail (hr-AC-1/hr-AC-2). Renders one pill per KNOWN service (from the registered-name
23
+ * enumeration + whatever telemetry has reported), a `role="status"` region so a screen reader
24
+ * announces changes, and — when a handler is supplied — a link to the full `/health` page.
25
+ */
26
+ export declare function HealthRail({ onOpenHealth }?: HealthRailProps): React.JSX.Element;
@@ -0,0 +1,61 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { SERVICE_STATE_COLOR, SERVICE_STATE_LABEL, ServiceStateIcon } from "./service-icons.js";
3
+ import { useFleetTelemetry } from "./use-fleet-telemetry.js";
4
+ /** The `/health` page's route (PRD-005b), so the rail can link an operator straight to detail. */
5
+ export const HEALTH_ROUTE = "/health";
6
+ /**
7
+ * Standard visually-hidden style: real text content for assistive tech (the rail is an aria-live
8
+ * region, so the STATE must live in the accessible text, not only in `title`/the aria-hidden icon),
9
+ * invisible to sighted operators who already get the icon + color.
10
+ */
11
+ const VISUALLY_HIDDEN_STYLE = {
12
+ position: "absolute",
13
+ width: 1,
14
+ height: 1,
15
+ padding: 0,
16
+ margin: -1,
17
+ overflow: "hidden",
18
+ clip: "rect(0, 0, 0, 0)",
19
+ whiteSpace: "nowrap",
20
+ border: 0,
21
+ };
22
+ /** One rail pill: the shared state icon + the service name, colored by state (never color-only, svg-AC-2). */
23
+ function ServicePill({ service }) {
24
+ const label = `${service.name}: ${SERVICE_STATE_LABEL[service.state]}`;
25
+ return (_jsxs("span", { "data-testid": `health-rail-pill-${service.name}`, "data-state": service.state, title: label, style: {
26
+ display: "inline-flex",
27
+ alignItems: "center",
28
+ gap: 6,
29
+ height: 26,
30
+ padding: "0 10px",
31
+ borderRadius: "var(--radius-full)",
32
+ border: "1px solid var(--border-default)",
33
+ background: "var(--bg-elevated)",
34
+ flex: "none",
35
+ }, children: [_jsx("span", { style: { color: SERVICE_STATE_COLOR[service.state], display: "inline-flex", width: 14, height: 14 }, "aria-hidden": "true", children: _jsx(ServiceStateIcon, { state: service.state }) }), _jsxs("span", { style: { fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--text-secondary)", whiteSpace: "nowrap" }, children: [service.name, _jsxs("span", { style: VISUALLY_HIDDEN_STYLE, children: [": ", SERVICE_STATE_LABEL[service.state]] })] })] }));
36
+ }
37
+ /**
38
+ * The health rail (hr-AC-1/hr-AC-2). Renders one pill per KNOWN service (from the registered-name
39
+ * enumeration + whatever telemetry has reported), a `role="status"` region so a screen reader
40
+ * announces changes, and — when a handler is supplied — a link to the full `/health` page.
41
+ */
42
+ export function HealthRail({ onOpenHealth } = {}) {
43
+ const telemetry = useFleetTelemetry();
44
+ return (_jsxs("div", { "data-testid": "health-rail", role: "status", "aria-live": "polite", "aria-label": "Fleet health", style: {
45
+ display: "flex",
46
+ alignItems: "center",
47
+ gap: 8,
48
+ padding: "8px 28px",
49
+ borderBottom: "1px solid var(--border-subtle)",
50
+ overflowX: "auto",
51
+ }, children: [telemetry.services.length === 0 ? (_jsx("span", { "data-testid": "health-rail-empty", style: { fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--text-tertiary)" }, children: "no services registered" })) : (telemetry.services.map((service) => _jsx(ServicePill, { service: service }, service.name))), _jsx("span", { style: { flex: 1 } }), onOpenHealth !== undefined && (_jsx("button", { type: "button", "data-testid": "health-rail-open-health", onClick: onOpenHealth, style: {
52
+ background: "transparent",
53
+ border: "none",
54
+ color: "var(--text-tertiary)",
55
+ fontFamily: "var(--font-mono)",
56
+ fontSize: 11,
57
+ cursor: "pointer",
58
+ padding: 0,
59
+ }, children: "health details \u2192" }))] }));
60
+ }
61
+ //# sourceMappingURL=health-rail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-rail.js","sourceRoot":"","sources":["../../../src/dashboard/web/health-rail.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The dashboard web-app ENTRY — PRD-024 Wave 2 (AC-1, D-1) · PRD-037b (renders the multi-page Shell)
3
+ * · PRD-003c (m-AC-6 / m-AC-7 / m-AC-8, the server-gated boot).
4
+ *
5
+ * This is the esbuild bundle entry. esbuild compiles the JSX at BUILD time and bundles
6
+ * React + ReactDOM in (no CDN React, no `@babel/standalone`, no `type="text/babel"` — the
7
+ * three things the UI kit's `index.html` did that D-1 forbids). The host serves the produced
8
+ * bundle as a single static `<script>`; this module finds `#root` (created by the host shell HTML)
9
+ * and mounts the screen the SERVER already authorized for the current path.
10
+ *
11
+ * PRD-003a moved the landing decision (fleet health, then auth) onto hive's server gate
12
+ * (`hive/src/daemon/gate.ts`): every request either gets redirected to `/buzzing` or `/login`
13
+ * before the shell ever renders, or is served the shell for the path it actually requested. This
14
+ * RETIRES the nested `<ReadinessSplash>` → `<SetupGate>` pre-mount gate that used to make that
15
+ * decision client-side (m-AC-6): this module now does a single, path-keyed lookup
16
+ * ({@link resolveBootScreen}) and mounts exactly one top-level screen — no polling-driven swap, no
17
+ * risk of flashing the wrong screen before a client gate resolves.
18
+ *
19
+ * The host stamps the asset base path onto `#root` as `data-asset-base` so the app knows
20
+ * where the host serves the DS logo (loopback, no secret in the attribute).
21
+ */
22
+ export {};
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * The dashboard web-app ENTRY — PRD-024 Wave 2 (AC-1, D-1) · PRD-037b (renders the multi-page Shell)
4
+ * · PRD-003c (m-AC-6 / m-AC-7 / m-AC-8, the server-gated boot).
5
+ *
6
+ * This is the esbuild bundle entry. esbuild compiles the JSX at BUILD time and bundles
7
+ * React + ReactDOM in (no CDN React, no `@babel/standalone`, no `type="text/babel"` — the
8
+ * three things the UI kit's `index.html` did that D-1 forbids). The host serves the produced
9
+ * bundle as a single static `<script>`; this module finds `#root` (created by the host shell HTML)
10
+ * and mounts the screen the SERVER already authorized for the current path.
11
+ *
12
+ * PRD-003a moved the landing decision (fleet health, then auth) onto hive's server gate
13
+ * (`hive/src/daemon/gate.ts`): every request either gets redirected to `/buzzing` or `/login`
14
+ * before the shell ever renders, or is served the shell for the path it actually requested. This
15
+ * RETIRES the nested `<ReadinessSplash>` → `<SetupGate>` pre-mount gate that used to make that
16
+ * decision client-side (m-AC-6): this module now does a single, path-keyed lookup
17
+ * ({@link resolveBootScreen}) and mounts exactly one top-level screen — no polling-driven swap, no
18
+ * risk of flashing the wrong screen before a client gate resolves.
19
+ *
20
+ * The host stamps the asset base path onto `#root` as `data-asset-base` so the app knows
21
+ * where the host serves the DS logo (loopback, no secret in the attribute).
22
+ */
23
+ import React from "react";
24
+ import { createRoot } from "react-dom/client";
25
+ import { Shell } from "./app.js";
26
+ import { resolveBootScreen } from "./boot-route.js";
27
+ import { BuzzingScreen } from "./buzzing-screen.js";
28
+ import { LoginScreen } from "./setup-gate.js";
29
+ /** Mount the screen the server already authorized for `location.pathname`. Idempotent-safe per load. */
30
+ function mount() {
31
+ const root = document.getElementById("root");
32
+ if (root === null)
33
+ return;
34
+ // Sanitize the DOM-read base path before it flows into any asset `src` (e.g. the sidebar
35
+ // mark `<img>`). Only a safe relative path is allowed — letters/digits/`. _ - /` — so a value
36
+ // carrying a scheme (`javascript:`) or markup meta-characters can never reach a URL/HTML sink.
37
+ // The host (not the user) sets `data-asset-base`, but this hard barrier closes the DOM-text→sink
38
+ // taint flow by construction (CodeQL js/xss-through-dom) and fails safe to the default.
39
+ const rawAssetBase = root.getAttribute("data-asset-base") ?? "assets";
40
+ const assetBase = /^[A-Za-z0-9._/-]*$/.test(rawAssetBase) ? rawAssetBase : "assets";
41
+ // PRD-003c (m-AC-6/7/8): the boot decision is a PURE lookup from the already-server-authorized
42
+ // path, not a re-derivation of health/auth. `/buzzing` and `/login` are the two gate-exempt
43
+ // screens; every other path mounts the authenticated Shell (its own path router then resolves
44
+ // the specific registry page — PRD-003c m-AC-1 through m-AC-5).
45
+ const pathname = typeof window === "undefined" ? "/" : window.location.pathname;
46
+ const screen = resolveBootScreen(pathname);
47
+ const element = screen === "buzzing" ? (_jsx(BuzzingScreen, { assetBase: assetBase })) : screen === "login" ? (_jsx(LoginScreen, { assetBase: assetBase })) : (_jsx(Shell, { assetBase: assetBase }));
48
+ createRoot(root).render(_jsx(React.StrictMode, { children: element }));
49
+ }
50
+ mount();
51
+ //# sourceMappingURL=main.js.map