ridgeline 0.7.21 → 0.8.2

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 (169) hide show
  1. package/dist/agents/core/builder.md +15 -0
  2. package/dist/catalog/build-catalog.js +2 -1
  3. package/dist/catalog/build-catalog.js.map +1 -1
  4. package/dist/catalog/classify.js +2 -1
  5. package/dist/catalog/classify.js.map +1 -1
  6. package/dist/catalog/pack-sprites.js +3 -2
  7. package/dist/catalog/pack-sprites.js.map +1 -1
  8. package/dist/catalog/vision-describe.js +3 -2
  9. package/dist/catalog/vision-describe.js.map +1 -1
  10. package/dist/cli.js +112 -44
  11. package/dist/cli.js.map +1 -1
  12. package/dist/commands/build.js +0 -1
  13. package/dist/commands/build.js.map +1 -1
  14. package/dist/commands/check.d.ts +1 -5
  15. package/dist/commands/check.js +2 -60
  16. package/dist/commands/check.js.map +1 -1
  17. package/dist/commands/create.d.ts +0 -1
  18. package/dist/commands/create.js +0 -18
  19. package/dist/commands/create.js.map +1 -1
  20. package/dist/commands/design.d.ts +0 -1
  21. package/dist/commands/design.js +1 -2
  22. package/dist/commands/design.js.map +1 -1
  23. package/dist/commands/qa-workflow.js +6 -5
  24. package/dist/commands/qa-workflow.js.map +1 -1
  25. package/dist/commands/refine.d.ts +0 -1
  26. package/dist/commands/refine.js +0 -1
  27. package/dist/commands/refine.js.map +1 -1
  28. package/dist/commands/research.d.ts +2 -1
  29. package/dist/commands/research.js +2 -2
  30. package/dist/commands/research.js.map +1 -1
  31. package/dist/commands/retrospective.d.ts +0 -1
  32. package/dist/commands/retrospective.js +1 -2
  33. package/dist/commands/retrospective.js.map +1 -1
  34. package/dist/commands/shape.d.ts +30 -1
  35. package/dist/commands/shape.js +16 -5
  36. package/dist/commands/shape.js.map +1 -1
  37. package/dist/commands/spec.d.ts +2 -1
  38. package/dist/commands/spec.js +2 -1
  39. package/dist/commands/spec.js.map +1 -1
  40. package/dist/commands/ui.d.ts +7 -0
  41. package/dist/commands/ui.js +96 -0
  42. package/dist/commands/ui.js.map +1 -0
  43. package/dist/config.js +2 -2
  44. package/dist/config.js.map +1 -1
  45. package/dist/engine/claude/claude.exec.d.ts +11 -0
  46. package/dist/engine/claude/claude.exec.js +73 -36
  47. package/dist/engine/claude/claude.exec.js.map +1 -1
  48. package/dist/engine/claude/stable.prompt.d.ts +31 -0
  49. package/dist/engine/claude/stable.prompt.js +137 -0
  50. package/dist/engine/claude/stable.prompt.js.map +1 -0
  51. package/dist/engine/claude/stream.display.d.ts +1 -1
  52. package/dist/engine/claude/stream.display.js +2 -1
  53. package/dist/engine/claude/stream.display.js.map +1 -1
  54. package/dist/engine/detect/index.d.ts +15 -0
  55. package/dist/engine/detect/index.js +160 -0
  56. package/dist/engine/detect/index.js.map +1 -0
  57. package/dist/engine/discovery/agent.registry.d.ts +5 -6
  58. package/dist/engine/discovery/agent.registry.js +20 -54
  59. package/dist/engine/discovery/agent.registry.js.map +1 -1
  60. package/dist/engine/discovery/skill.check.d.ts +3 -3
  61. package/dist/engine/discovery/skill.check.js +4 -4
  62. package/dist/engine/discovery/skill.check.js.map +1 -1
  63. package/dist/engine/index.d.ts +0 -1
  64. package/dist/engine/index.js +1 -3
  65. package/dist/engine/index.js.map +1 -1
  66. package/dist/engine/pipeline/build.exec.js +19 -6
  67. package/dist/engine/pipeline/build.exec.js.map +1 -1
  68. package/dist/engine/pipeline/ensemble.exec.d.ts +41 -3
  69. package/dist/engine/pipeline/ensemble.exec.js +295 -94
  70. package/dist/engine/pipeline/ensemble.exec.js.map +1 -1
  71. package/dist/engine/pipeline/phase.sequence.js +97 -4
  72. package/dist/engine/pipeline/phase.sequence.js.map +1 -1
  73. package/dist/engine/pipeline/pipeline.shared.d.ts +7 -0
  74. package/dist/engine/pipeline/pipeline.shared.js +21 -3
  75. package/dist/engine/pipeline/pipeline.shared.js.map +1 -1
  76. package/dist/engine/pipeline/refine.exec.d.ts +0 -1
  77. package/dist/engine/pipeline/refine.exec.js +1 -2
  78. package/dist/engine/pipeline/refine.exec.js.map +1 -1
  79. package/dist/engine/pipeline/research.exec.d.ts +2 -1
  80. package/dist/engine/pipeline/research.exec.js +53 -7
  81. package/dist/engine/pipeline/research.exec.js.map +1 -1
  82. package/dist/engine/pipeline/review.exec.d.ts +2 -1
  83. package/dist/engine/pipeline/review.exec.js +14 -6
  84. package/dist/engine/pipeline/review.exec.js.map +1 -1
  85. package/dist/engine/pipeline/sensors.collect.d.ts +6 -0
  86. package/dist/engine/pipeline/sensors.collect.js +34 -0
  87. package/dist/engine/pipeline/sensors.collect.js.map +1 -0
  88. package/dist/engine/pipeline/specialist.verdict.d.ts +19 -0
  89. package/dist/engine/pipeline/specialist.verdict.js +189 -0
  90. package/dist/engine/pipeline/specialist.verdict.js.map +1 -0
  91. package/dist/engine/pipeline/specify.exec.d.ts +2 -1
  92. package/dist/engine/pipeline/specify.exec.js +159 -7
  93. package/dist/engine/pipeline/specify.exec.js.map +1 -1
  94. package/dist/sensors/a11y.d.ts +36 -0
  95. package/dist/sensors/a11y.js +134 -0
  96. package/dist/sensors/a11y.js.map +1 -0
  97. package/dist/sensors/contrast.d.ts +3 -0
  98. package/dist/sensors/contrast.js +117 -0
  99. package/dist/sensors/contrast.js.map +1 -0
  100. package/dist/sensors/index.d.ts +27 -0
  101. package/dist/sensors/index.js +3 -0
  102. package/dist/sensors/index.js.map +1 -0
  103. package/dist/sensors/playwright.d.ts +69 -0
  104. package/dist/sensors/playwright.js +266 -0
  105. package/dist/sensors/playwright.js.map +1 -0
  106. package/dist/sensors/vision.d.ts +18 -0
  107. package/dist/sensors/vision.js +125 -0
  108. package/dist/sensors/vision.js.map +1 -0
  109. package/dist/stores/feedback.format.js +9 -0
  110. package/dist/stores/feedback.format.js.map +1 -1
  111. package/dist/stores/feedback.parse.js +2 -0
  112. package/dist/stores/feedback.parse.js.map +1 -1
  113. package/dist/stores/settings.d.ts +7 -1
  114. package/dist/stores/settings.js +10 -1
  115. package/dist/stores/settings.js.map +1 -1
  116. package/dist/stores/trajectory.d.ts +9 -2
  117. package/dist/stores/trajectory.js +6 -0
  118. package/dist/stores/trajectory.js.map +1 -1
  119. package/dist/types.d.ts +36 -3
  120. package/dist/ui/color.d.ts +16 -0
  121. package/dist/ui/color.js +46 -0
  122. package/dist/ui/color.js.map +1 -0
  123. package/dist/ui/contrast.d.ts +2 -0
  124. package/dist/ui/contrast.js +94 -0
  125. package/dist/ui/contrast.js.map +1 -0
  126. package/dist/ui/dashboard/client.d.ts +1 -0
  127. package/dist/ui/dashboard/client.js +281 -0
  128. package/dist/ui/dashboard/client.js.map +1 -0
  129. package/dist/ui/dashboard/css.d.ts +1 -0
  130. package/dist/ui/dashboard/css.js +341 -0
  131. package/dist/ui/dashboard/css.js.map +1 -0
  132. package/dist/ui/dashboard/events.d.ts +15 -0
  133. package/dist/ui/dashboard/events.js +40 -0
  134. package/dist/ui/dashboard/events.js.map +1 -0
  135. package/dist/ui/dashboard/favicon.d.ts +2 -0
  136. package/dist/ui/dashboard/favicon.js +20 -0
  137. package/dist/ui/dashboard/favicon.js.map +1 -0
  138. package/dist/ui/dashboard/hex.d.ts +7 -0
  139. package/dist/ui/dashboard/hex.js +16 -0
  140. package/dist/ui/dashboard/hex.js.map +1 -0
  141. package/dist/ui/dashboard/html.d.ts +7 -0
  142. package/dist/ui/dashboard/html.js +69 -0
  143. package/dist/ui/dashboard/html.js.map +1 -0
  144. package/dist/ui/dashboard/server.d.ts +26 -0
  145. package/dist/ui/dashboard/server.js +257 -0
  146. package/dist/ui/dashboard/server.js.map +1 -0
  147. package/dist/ui/dashboard/snapshot.d.ts +29 -0
  148. package/dist/ui/dashboard/snapshot.js +71 -0
  149. package/dist/ui/dashboard/snapshot.js.map +1 -0
  150. package/dist/ui/dashboard/tokens.d.ts +19 -0
  151. package/dist/ui/dashboard/tokens.js +25 -0
  152. package/dist/ui/dashboard/tokens.js.map +1 -0
  153. package/dist/ui/dashboard/watcher.d.ts +13 -0
  154. package/dist/ui/dashboard/watcher.js +238 -0
  155. package/dist/ui/dashboard/watcher.js.map +1 -0
  156. package/dist/ui/output.js +3 -2
  157. package/dist/ui/output.js.map +1 -1
  158. package/dist/ui/preflight.d.ts +21 -0
  159. package/dist/ui/preflight.js +159 -0
  160. package/dist/ui/preflight.js.map +1 -0
  161. package/dist/ui/spinner.d.ts +0 -6
  162. package/dist/ui/spinner.js +25 -6
  163. package/dist/ui/spinner.js.map +1 -1
  164. package/dist/ui/transcript.js +2 -3
  165. package/dist/ui/transcript.js.map +1 -1
  166. package/dist/utils/flavour-removed.d.ts +12 -0
  167. package/dist/utils/flavour-removed.js +44 -0
  168. package/dist/utils/flavour-removed.js.map +1 -0
  169. package/package.json +16 -3
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderClientScript = void 0;
4
+ const CLIENT_SCRIPT = `(function () {
5
+ "use strict";
6
+ var bootstrap = JSON.parse(document.getElementById("bootstrap").textContent);
7
+ var buildName = bootstrap.buildName;
8
+ var state = bootstrap.snapshot;
9
+ var lastEventId = 0;
10
+ var es = null;
11
+ var pollTimer = null;
12
+ var lastFavicon = null;
13
+ var lastTitle = null;
14
+ var disconnected = false;
15
+ var knownPhases = new Set();
16
+
17
+ function fmtCost(n) {
18
+ if (typeof n !== "number") return "$0.00";
19
+ return "$" + n.toFixed(2);
20
+ }
21
+ function fmtDuration(ms) {
22
+ if (ms == null) return "";
23
+ var s = Math.floor(ms / 1000);
24
+ var h = Math.floor(s / 3600);
25
+ var m = Math.floor((s % 3600) / 60);
26
+ var r = s % 60;
27
+ if (h > 0) return h + "h" + m + "m";
28
+ if (m > 0) return m + "m" + r + "s";
29
+ return r + "s";
30
+ }
31
+
32
+ function elapsedFromStart(startedAt) {
33
+ if (!startedAt) return "";
34
+ var t = Date.parse(startedAt);
35
+ if (isNaN(t)) return "";
36
+ return fmtDuration(Date.now() - t);
37
+ }
38
+
39
+ function pillClass(status) {
40
+ switch (status) {
41
+ case "building":
42
+ case "reviewing":
43
+ return "pill pill-running";
44
+ case "complete":
45
+ return "pill pill-done";
46
+ case "failed":
47
+ return "pill pill-failed";
48
+ case "skipped":
49
+ return "pill pill-skipped";
50
+ default:
51
+ return "pill pill-pending";
52
+ }
53
+ }
54
+ function pillText(status) {
55
+ switch (status) {
56
+ case "building": return "running";
57
+ case "reviewing": return "running";
58
+ case "complete": return "done";
59
+ case "failed": return "failed";
60
+ case "skipped": return "skipped";
61
+ default: return "pending";
62
+ }
63
+ }
64
+
65
+ function setTitle() {
66
+ var status = state.status || "idle";
67
+ var name = state.buildName || buildName || "";
68
+ var title = "● ridgeline" + (name ? " · " + name + " · " + status : "");
69
+ if (title === lastTitle) return;
70
+ lastTitle = title;
71
+ document.title = title;
72
+ }
73
+
74
+ function faviconColor(status) {
75
+ if (status === "running") return "#06B6D4";
76
+ if (status === "done") return "#10B981";
77
+ if (status === "failed") return "#EF4444";
78
+ return "#9CA3AF";
79
+ }
80
+ function setFavicon() {
81
+ var color = faviconColor(state.status || "idle");
82
+ if (color === lastFavicon) return;
83
+ lastFavicon = color;
84
+ var svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="' + color + '"/></svg>';
85
+ var href = "data:image/svg+xml;utf8," + encodeURIComponent(svg);
86
+ var link = document.getElementById("favicon");
87
+ if (link) link.setAttribute("href", href);
88
+ }
89
+
90
+ function renderHeader() {
91
+ var buildEl = document.getElementById("build-name");
92
+ if (buildEl) {
93
+ var name = state.buildName || buildName;
94
+ buildEl.textContent = name || "ridgeline";
95
+ }
96
+ var pill = document.getElementById("header-pill");
97
+ if (pill) {
98
+ pill.className = pillClass(state.status === "running" ? "building" : state.status === "done" ? "complete" : state.status === "failed" ? "failed" : "pending");
99
+ pill.textContent = (state.status || "pending").toUpperCase();
100
+ }
101
+ var elapsed = document.getElementById("header-elapsed");
102
+ if (elapsed) elapsed.textContent = elapsedFromStart(state.startedAt);
103
+ }
104
+
105
+ function renderCost() {
106
+ var total = document.getElementById("cost-total");
107
+ if (total) total.textContent = fmtCost(state.budget && state.budget.totalCostUsd);
108
+ var breakdown = document.getElementById("cost-breakdown");
109
+ if (!breakdown) return;
110
+ var html = "";
111
+ var roles = (state.budget && state.budget.perRole) || [];
112
+ for (var i = 0; i < roles.length; i++) {
113
+ var r = roles[i];
114
+ html += '<div><div class="dim">' + escape(r.role) + '</div><div class="cost-stage-value mono">' + escape(fmtCost(r.costUsd)) + '</div></div>';
115
+ }
116
+ breakdown.innerHTML = html;
117
+ }
118
+
119
+ function escape(s) {
120
+ if (s == null) return "";
121
+ return String(s).replace(/[&<>"']/g, function (c) {
122
+ return { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c];
123
+ });
124
+ }
125
+
126
+ function renderPhases(changedIds) {
127
+ var list = document.getElementById("phase-list");
128
+ if (!list) return;
129
+ var empty = document.getElementById("empty-state");
130
+ var meter = document.getElementById("cost-meter");
131
+ if (!state.buildName) {
132
+ if (empty) empty.hidden = false;
133
+ if (meter) meter.hidden = true;
134
+ list.innerHTML = "";
135
+ return;
136
+ }
137
+ if (empty) empty.hidden = true;
138
+ if (meter) meter.hidden = false;
139
+
140
+ var html = "";
141
+ var lastErr = state.lastError;
142
+ for (var i = 0; i < state.phases.length; i++) {
143
+ var p = state.phases[i];
144
+ var failed = p.status === "failed";
145
+ var cls = "phase-row" + (failed ? " failed" : "");
146
+ var elapsed = p.duration != null ? fmtDuration(p.duration) : "";
147
+ html += '<div class="' + cls + '" data-phase-id="' + escape(p.id) + '">';
148
+ html += '<span class="phase-id mono">' + escape(p.id) + '</span>';
149
+ html += '<span class="phase-slug">' + escape(p.slug) + '</span>';
150
+ html += '<span class="' + pillClass(p.status) + '">' + escape(pillText(p.status)) + '</span>';
151
+ html += '<span class="phase-elapsed mono">' + escape(elapsed) + '</span>';
152
+ if (failed && lastErr && lastErr.phaseId === p.id) {
153
+ html += '<div class="phase-error mono">' + escape(lastErr.message) + '</div>';
154
+ }
155
+ html += '</div>';
156
+ }
157
+ list.innerHTML = html;
158
+
159
+ if (changedIds && changedIds.size > 0) {
160
+ changedIds.forEach(function (id) {
161
+ var row = list.querySelector('[data-phase-id="' + id + '"]');
162
+ if (!row) return;
163
+ row.classList.remove("row-flash");
164
+ void row.offsetWidth;
165
+ row.classList.add("row-flash");
166
+ });
167
+ }
168
+ }
169
+
170
+ function renderAll(changedIds) {
171
+ setTitle();
172
+ setFavicon();
173
+ renderHeader();
174
+ renderCost();
175
+ renderPhases(changedIds);
176
+ for (var i = 0; i < state.phases.length; i++) knownPhases.add(state.phases[i].id);
177
+ }
178
+
179
+ function diffPhases(prev, next) {
180
+ var prevMap = {};
181
+ for (var i = 0; i < prev.length; i++) prevMap[prev[i].id] = prev[i];
182
+ var changed = new Set();
183
+ for (var j = 0; j < next.length; j++) {
184
+ var p = next[j];
185
+ var old = prevMap[p.id];
186
+ if (!old || old.status !== p.status || old.duration !== p.duration || old.retries !== p.retries) {
187
+ changed.add(p.id);
188
+ }
189
+ }
190
+ return changed;
191
+ }
192
+
193
+ function onState(data) {
194
+ var prevPhases = state.phases;
195
+ state = Object.assign({}, state, data);
196
+ var changed = diffPhases(prevPhases, state.phases);
197
+ renderAll(changed);
198
+ }
199
+ function onBudget(data) {
200
+ state = Object.assign({}, state, { budget: data });
201
+ renderCost();
202
+ }
203
+ function onTrajectory(_entry) {
204
+ }
205
+
206
+ function hideBanner() {
207
+ var b = document.getElementById("disconnect-banner");
208
+ if (!b || b.classList.contains("hidden")) return;
209
+ b.classList.add("fade-out");
210
+ setTimeout(function () {
211
+ b.classList.add("hidden");
212
+ b.classList.remove("fade-out");
213
+ }, 400);
214
+ }
215
+ function showBanner() {
216
+ var b = document.getElementById("disconnect-banner");
217
+ if (!b) return;
218
+ b.classList.remove("hidden");
219
+ b.classList.remove("fade-out");
220
+ }
221
+
222
+ function startPolling() {
223
+ if (pollTimer) return;
224
+ pollTimer = setInterval(function () {
225
+ fetch("/state").then(function (r) {
226
+ return r.ok ? r.json() : null;
227
+ }).then(function (snap) {
228
+ if (snap) onState(snap);
229
+ }).catch(function () {});
230
+ }, 2000);
231
+ }
232
+ function stopPolling() {
233
+ if (!pollTimer) return;
234
+ clearInterval(pollTimer);
235
+ pollTimer = null;
236
+ }
237
+
238
+ function openStream() {
239
+ try {
240
+ es = new EventSource("/events");
241
+ } catch (_e) {
242
+ startPolling();
243
+ return;
244
+ }
245
+ es.addEventListener("open", function () {
246
+ if (disconnected) {
247
+ disconnected = false;
248
+ hideBanner();
249
+ }
250
+ stopPolling();
251
+ });
252
+ es.addEventListener("state", function (ev) {
253
+ lastEventId = Number(ev.lastEventId) || lastEventId;
254
+ try { onState(JSON.parse(ev.data)); } catch (_e) {}
255
+ });
256
+ es.addEventListener("budget", function (ev) {
257
+ lastEventId = Number(ev.lastEventId) || lastEventId;
258
+ try { onBudget(JSON.parse(ev.data)); } catch (_e) {}
259
+ });
260
+ es.addEventListener("trajectory", function (ev) {
261
+ lastEventId = Number(ev.lastEventId) || lastEventId;
262
+ try { onTrajectory(JSON.parse(ev.data)); } catch (_e) {}
263
+ });
264
+ es.addEventListener("error", function () {
265
+ disconnected = true;
266
+ showBanner();
267
+ startPolling();
268
+ });
269
+ }
270
+
271
+ renderAll();
272
+ openStream();
273
+ setInterval(function () {
274
+ var el = document.getElementById("header-elapsed");
275
+ if (el) el.textContent = elapsedFromStart(state.startedAt);
276
+ }, 1000);
277
+ })();
278
+ `;
279
+ const renderClientScript = () => CLIENT_SCRIPT;
280
+ exports.renderClientScript = renderClientScript;
281
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/ui/dashboard/client.ts"],"names":[],"mappings":";;;AAAA,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkRrB,CAAA;AAEM,MAAM,kBAAkB,GAAG,GAAW,EAAE,CAAC,aAAa,CAAA;AAAhD,QAAA,kBAAkB,sBAA8B"}
@@ -0,0 +1 @@
1
+ export declare const renderCss: () => string;
@@ -0,0 +1,341 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderCss = void 0;
4
+ const tokens_1 = require("./tokens");
5
+ const hex_1 = require("./hex");
6
+ const renderCss = () => {
7
+ const accents = (0, tokens_1.resolveAccents)();
8
+ const byName = Object.fromEntries(accents.map((a) => [a.name, a]));
9
+ const pillRunningText = byName.info.text;
10
+ const pillRunningFill = byName.info.fill;
11
+ const pillDoneText = byName.success.text;
12
+ const pillDoneFill = byName.success.fill;
13
+ const pillFailedText = byName.error.text;
14
+ const pillFailedFill = byName.error.fill;
15
+ const warningText = byName.warning.text;
16
+ const warningFill = byName.warning.fill;
17
+ const rowFlashColor = (0, hex_1.rgbaOf)(tokens_1.PALETTE.info, 0.15);
18
+ return `:root {
19
+ --bg: ${tokens_1.PALETTE.bg};
20
+ --panel: ${tokens_1.PALETTE.panel};
21
+ --border: ${tokens_1.PALETTE.border};
22
+ --text: ${tokens_1.PALETTE.text};
23
+ --text-dim: ${tokens_1.PALETTE.textDim};
24
+ --error: ${tokens_1.PALETTE.error};
25
+ --success: ${tokens_1.PALETTE.success};
26
+ --warning: ${tokens_1.PALETTE.warning};
27
+ --info: ${tokens_1.PALETTE.info};
28
+ --pill-running-text: ${pillRunningText};
29
+ --pill-running-fill: ${pillRunningFill};
30
+ --pill-done-text: ${pillDoneText};
31
+ --pill-done-fill: ${pillDoneFill};
32
+ --pill-failed-text: ${pillFailedText};
33
+ --pill-failed-fill: ${pillFailedFill};
34
+ --banner-text: ${warningText};
35
+ --banner-fill: ${warningFill};
36
+ --row-flash: ${rowFlashColor};
37
+ }
38
+
39
+ *,
40
+ *::before,
41
+ *::after {
42
+ box-sizing: border-box;
43
+ }
44
+
45
+ html,
46
+ body {
47
+ margin: 0;
48
+ padding: 0;
49
+ background: var(--bg);
50
+ color: var(--text);
51
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
52
+ font-size: 14px;
53
+ line-height: 1.4;
54
+ }
55
+
56
+ .page {
57
+ max-width: 1280px;
58
+ margin: 0 auto;
59
+ padding: 16px;
60
+ }
61
+
62
+ .mono {
63
+ font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
64
+ }
65
+
66
+ .dim {
67
+ color: var(--text-dim);
68
+ }
69
+
70
+ .wordmark {
71
+ font-size: 14px;
72
+ color: var(--text-dim);
73
+ font-weight: normal;
74
+ text-transform: lowercase;
75
+ letter-spacing: 0;
76
+ }
77
+
78
+ .header {
79
+ position: sticky;
80
+ top: 0;
81
+ background: var(--bg);
82
+ padding: 12px 0;
83
+ border-bottom: 1px solid var(--border);
84
+ display: flex;
85
+ align-items: center;
86
+ gap: 16px;
87
+ z-index: 10;
88
+ }
89
+
90
+ .build-name {
91
+ font-size: 20px;
92
+ color: var(--text);
93
+ margin: 0;
94
+ font-weight: normal;
95
+ flex: 1;
96
+ }
97
+
98
+ .header-elapsed {
99
+ font-size: 14px;
100
+ color: var(--text-dim);
101
+ }
102
+
103
+ .panel {
104
+ background: var(--panel);
105
+ border: 1px solid var(--border);
106
+ border-radius: 4px;
107
+ padding: 12px;
108
+ margin-top: 16px;
109
+ }
110
+
111
+ .cost-total {
112
+ font-size: 20px;
113
+ }
114
+
115
+ .cost-label {
116
+ font-size: 13px;
117
+ color: var(--text-dim);
118
+ margin-bottom: 4px;
119
+ }
120
+
121
+ .cost-breakdown {
122
+ margin-top: 12px;
123
+ font-size: 13px;
124
+ color: var(--text-dim);
125
+ display: grid;
126
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
127
+ gap: 8px;
128
+ }
129
+
130
+ .cost-stage-value {
131
+ color: var(--text);
132
+ }
133
+
134
+ .phase-list {
135
+ margin-top: 16px;
136
+ display: flex;
137
+ flex-direction: column;
138
+ gap: 8px;
139
+ }
140
+
141
+ .phase-row {
142
+ background: var(--panel);
143
+ border: 1px solid var(--border);
144
+ border-radius: 4px;
145
+ padding: 12px;
146
+ display: grid;
147
+ grid-template-columns: auto 1fr auto auto;
148
+ align-items: center;
149
+ gap: 12px;
150
+ }
151
+
152
+ .phase-row.row-flash {
153
+ animation: row-flash 300ms ease-out 1;
154
+ }
155
+
156
+ .phase-row.failed {
157
+ border: 1px solid var(--error);
158
+ }
159
+
160
+ .phase-id {
161
+ font-size: 13px;
162
+ color: var(--text-dim);
163
+ }
164
+
165
+ .phase-slug {
166
+ font-size: 14px;
167
+ color: var(--text);
168
+ }
169
+
170
+ .phase-elapsed {
171
+ font-size: 13px;
172
+ color: var(--text-dim);
173
+ }
174
+
175
+ .phase-error {
176
+ grid-column: 1 / -1;
177
+ margin-top: 8px;
178
+ font-size: 13px;
179
+ color: var(--text);
180
+ }
181
+
182
+ .pill {
183
+ display: inline-block;
184
+ padding: 4px 8px;
185
+ border-radius: 4px;
186
+ font-size: 11px;
187
+ text-transform: uppercase;
188
+ letter-spacing: 0.08em;
189
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
190
+ font-weight: 600;
191
+ border: 1px solid transparent;
192
+ }
193
+
194
+ .pill-pending,
195
+ .pill-skipped {
196
+ color: var(--text-dim);
197
+ background: var(--border);
198
+ }
199
+
200
+ .pill-running {
201
+ color: var(--pill-running-text);
202
+ background: var(--pill-running-fill);
203
+ animation: pill-pulse 1500ms ease-in-out infinite;
204
+ }
205
+
206
+ .pill-done {
207
+ color: var(--pill-done-text);
208
+ background: var(--pill-done-fill);
209
+ }
210
+
211
+ .pill-failed {
212
+ color: var(--pill-failed-text);
213
+ background: var(--pill-failed-fill);
214
+ }
215
+
216
+ .empty {
217
+ padding: 48px;
218
+ text-align: center;
219
+ color: var(--text-dim);
220
+ font-size: 14px;
221
+ }
222
+
223
+ .empty-hint {
224
+ margin-top: 8px;
225
+ font-size: 13px;
226
+ }
227
+
228
+ .disconnect-banner {
229
+ position: sticky;
230
+ top: 0;
231
+ z-index: 20;
232
+ padding: 8px 12px;
233
+ color: var(--banner-text);
234
+ background: var(--banner-fill);
235
+ border: 1px solid var(--warning);
236
+ border-radius: 4px;
237
+ font-size: 13px;
238
+ display: flex;
239
+ align-items: center;
240
+ gap: 8px;
241
+ margin-bottom: 8px;
242
+ }
243
+
244
+ .disconnect-banner.hidden {
245
+ display: none;
246
+ }
247
+
248
+ .disconnect-banner.fade-out {
249
+ animation: banner-fade 400ms ease-out forwards;
250
+ }
251
+
252
+ .spinner-dot {
253
+ width: 8px;
254
+ height: 8px;
255
+ border-radius: 50%;
256
+ background: var(--info);
257
+ animation: pill-pulse 1500ms ease-in-out infinite;
258
+ }
259
+
260
+ .icon {
261
+ width: 16px;
262
+ height: 16px;
263
+ stroke-width: 1.5;
264
+ stroke: currentColor;
265
+ fill: none;
266
+ vertical-align: middle;
267
+ }
268
+
269
+ .copy-btn,
270
+ .link-btn {
271
+ background: none;
272
+ border: none;
273
+ color: var(--text-dim);
274
+ cursor: pointer;
275
+ padding: 4px;
276
+ }
277
+
278
+ .copy-btn:hover,
279
+ .link-btn:hover {
280
+ color: var(--text);
281
+ }
282
+
283
+ a,
284
+ button {
285
+ color: inherit;
286
+ }
287
+
288
+ a:focus-visible,
289
+ button:focus-visible,
290
+ .copy-btn:focus-visible,
291
+ .link-btn:focus-visible {
292
+ outline: 2px solid var(--info);
293
+ outline-offset: 2px;
294
+ }
295
+
296
+ @keyframes pill-pulse {
297
+ 0% { opacity: 0.6; }
298
+ 50% { opacity: 1; }
299
+ 100% { opacity: 0.6; }
300
+ }
301
+
302
+ @keyframes row-flash {
303
+ 0% { background-color: var(--row-flash); }
304
+ 100% { background-color: transparent; }
305
+ }
306
+
307
+ @keyframes banner-fade {
308
+ 0% { opacity: 1; }
309
+ 100% { opacity: 0; }
310
+ }
311
+
312
+ @media (prefers-reduced-motion: reduce) {
313
+ .pill-running {
314
+ animation: none;
315
+ border: 2px solid var(--info);
316
+ padding: 2px 6px;
317
+ }
318
+ .phase-row.row-flash {
319
+ animation: none;
320
+ }
321
+ .spinner-dot {
322
+ animation: none;
323
+ }
324
+ .disconnect-banner.fade-out {
325
+ animation: none;
326
+ display: none;
327
+ }
328
+ }
329
+
330
+ @media (max-width: 900px) {
331
+ .phase-row {
332
+ grid-template-columns: 1fr;
333
+ }
334
+ .cost-breakdown {
335
+ grid-template-columns: 1fr;
336
+ }
337
+ }
338
+ `;
339
+ };
340
+ exports.renderCss = renderCss;
341
+ //# sourceMappingURL=css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"css.js","sourceRoot":"","sources":["../../../src/ui/dashboard/css.ts"],"names":[],"mappings":";;;AAAA,qCAAkD;AAClD,+BAA8B;AAEvB,MAAM,SAAS,GAAG,GAAW,EAAE;IACpC,MAAM,OAAO,GAAG,IAAA,uBAAc,GAAE,CAAA;IAChC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAElE,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;IACxC,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;IACxC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;IACxC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;IACxC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAA;IACxC,MAAM,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAA;IACxC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;IACvC,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;IACvC,MAAM,aAAa,GAAG,IAAA,YAAM,EAAC,gBAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAEhD,OAAO;UACC,gBAAO,CAAC,EAAE;aACP,gBAAO,CAAC,KAAK;cACZ,gBAAO,CAAC,MAAM;YAChB,gBAAO,CAAC,IAAI;gBACR,gBAAO,CAAC,OAAO;aAClB,gBAAO,CAAC,KAAK;eACX,gBAAO,CAAC,OAAO;eACf,gBAAO,CAAC,OAAO;YAClB,gBAAO,CAAC,IAAI;yBACC,eAAe;yBACf,eAAe;sBAClB,YAAY;sBACZ,YAAY;wBACV,cAAc;wBACd,cAAc;mBACnB,WAAW;mBACX,WAAW;iBACb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8S7B,CAAA;AACD,CAAC,CAAA;AA/UY,QAAA,SAAS,aA+UrB"}
@@ -0,0 +1,15 @@
1
+ export type EventName = "state" | "budget" | "trajectory";
2
+ export interface DashboardEvent {
3
+ id: number;
4
+ name: EventName;
5
+ data: string;
6
+ }
7
+ export declare class EventBuffer {
8
+ private events;
9
+ private lastId;
10
+ private readonly perTypeCap;
11
+ constructor(perTypeCap?: number);
12
+ push(name: EventName, payload: unknown): DashboardEvent;
13
+ private prune;
14
+ replayAfter(id: number): DashboardEvent[];
15
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventBuffer = void 0;
4
+ class EventBuffer {
5
+ events = [];
6
+ lastId = 0;
7
+ perTypeCap;
8
+ constructor(perTypeCap = 200) {
9
+ this.perTypeCap = perTypeCap;
10
+ }
11
+ push(name, payload) {
12
+ this.lastId += 1;
13
+ const event = {
14
+ id: this.lastId,
15
+ name,
16
+ data: JSON.stringify(payload),
17
+ };
18
+ this.events.push(event);
19
+ this.prune();
20
+ return event;
21
+ }
22
+ prune() {
23
+ const byName = { state: [], budget: [], trajectory: [] };
24
+ for (const ev of this.events)
25
+ byName[ev.name].push(ev);
26
+ const keep = new Set();
27
+ for (const name of ["state", "budget", "trajectory"]) {
28
+ const arr = byName[name];
29
+ const slice = arr.slice(-this.perTypeCap);
30
+ for (const ev of slice)
31
+ keep.add(ev.id);
32
+ }
33
+ this.events = this.events.filter((ev) => keep.has(ev.id));
34
+ }
35
+ replayAfter(id) {
36
+ return this.events.filter((ev) => ev.id > id);
37
+ }
38
+ }
39
+ exports.EventBuffer = EventBuffer;
40
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/ui/dashboard/events.ts"],"names":[],"mappings":";;;AAQA,MAAa,WAAW;IACd,MAAM,GAAqB,EAAE,CAAA;IAC7B,MAAM,GAAG,CAAC,CAAA;IACD,UAAU,CAAQ;IAEnC,YAAY,aAAqB,GAAG;QAClC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,IAAI,CAAC,IAAe,EAAE,OAAgB;QACpC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAA;QAChB,MAAM,KAAK,GAAmB;YAC5B,EAAE,EAAE,IAAI,CAAC,MAAM;YACf,IAAI;YACJ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAA;QACD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvB,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,OAAO,KAAK,CAAA;IACd,CAAC;IAEO,KAAK;QACX,MAAM,MAAM,GAAwC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAA;QAC7F,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACtD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;QAC9B,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAU,EAAE,CAAC;YAC9D,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;YACxB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YACzC,KAAK,MAAM,EAAE,IAAI,KAAK;gBAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;QACzC,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IAC/C,CAAC;CACF;AApCD,kCAoCC"}
@@ -0,0 +1,2 @@
1
+ export type FaviconStatus = "running" | "done" | "failed" | "idle";
2
+ export declare const faviconDataUri: (status: FaviconStatus) => string;