ridgeline 0.7.21 → 0.8.1

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 (138) hide show
  1. package/dist/agents/core/builder.md +15 -0
  2. package/dist/cli.js +91 -42
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/build.js +0 -1
  5. package/dist/commands/build.js.map +1 -1
  6. package/dist/commands/check.d.ts +1 -5
  7. package/dist/commands/check.js +2 -60
  8. package/dist/commands/check.js.map +1 -1
  9. package/dist/commands/create.d.ts +0 -1
  10. package/dist/commands/create.js +0 -18
  11. package/dist/commands/create.js.map +1 -1
  12. package/dist/commands/design.d.ts +0 -1
  13. package/dist/commands/design.js +1 -2
  14. package/dist/commands/design.js.map +1 -1
  15. package/dist/commands/refine.d.ts +0 -1
  16. package/dist/commands/refine.js +0 -1
  17. package/dist/commands/refine.js.map +1 -1
  18. package/dist/commands/research.d.ts +0 -1
  19. package/dist/commands/research.js +0 -2
  20. package/dist/commands/research.js.map +1 -1
  21. package/dist/commands/retrospective.d.ts +0 -1
  22. package/dist/commands/retrospective.js +1 -2
  23. package/dist/commands/retrospective.js.map +1 -1
  24. package/dist/commands/shape.d.ts +30 -1
  25. package/dist/commands/shape.js +16 -5
  26. package/dist/commands/shape.js.map +1 -1
  27. package/dist/commands/spec.d.ts +0 -1
  28. package/dist/commands/spec.js +0 -1
  29. package/dist/commands/spec.js.map +1 -1
  30. package/dist/commands/ui.d.ts +7 -0
  31. package/dist/commands/ui.js +96 -0
  32. package/dist/commands/ui.js.map +1 -0
  33. package/dist/config.js +0 -1
  34. package/dist/config.js.map +1 -1
  35. package/dist/engine/claude/claude.exec.js +1 -1
  36. package/dist/engine/claude/claude.exec.js.map +1 -1
  37. package/dist/engine/detect/index.d.ts +15 -0
  38. package/dist/engine/detect/index.js +160 -0
  39. package/dist/engine/detect/index.js.map +1 -0
  40. package/dist/engine/discovery/agent.registry.d.ts +5 -6
  41. package/dist/engine/discovery/agent.registry.js +20 -54
  42. package/dist/engine/discovery/agent.registry.js.map +1 -1
  43. package/dist/engine/discovery/skill.check.d.ts +3 -3
  44. package/dist/engine/discovery/skill.check.js +4 -4
  45. package/dist/engine/discovery/skill.check.js.map +1 -1
  46. package/dist/engine/index.d.ts +0 -1
  47. package/dist/engine/index.js +1 -3
  48. package/dist/engine/index.js.map +1 -1
  49. package/dist/engine/pipeline/build.exec.js +19 -6
  50. package/dist/engine/pipeline/build.exec.js.map +1 -1
  51. package/dist/engine/pipeline/ensemble.exec.js +1 -2
  52. package/dist/engine/pipeline/ensemble.exec.js.map +1 -1
  53. package/dist/engine/pipeline/phase.sequence.js +88 -1
  54. package/dist/engine/pipeline/phase.sequence.js.map +1 -1
  55. package/dist/engine/pipeline/pipeline.shared.js +1 -2
  56. package/dist/engine/pipeline/pipeline.shared.js.map +1 -1
  57. package/dist/engine/pipeline/refine.exec.d.ts +0 -1
  58. package/dist/engine/pipeline/refine.exec.js +1 -2
  59. package/dist/engine/pipeline/refine.exec.js.map +1 -1
  60. package/dist/engine/pipeline/research.exec.d.ts +0 -1
  61. package/dist/engine/pipeline/research.exec.js +1 -2
  62. package/dist/engine/pipeline/research.exec.js.map +1 -1
  63. package/dist/engine/pipeline/review.exec.js +1 -2
  64. package/dist/engine/pipeline/review.exec.js.map +1 -1
  65. package/dist/engine/pipeline/sensors.collect.d.ts +6 -0
  66. package/dist/engine/pipeline/sensors.collect.js +34 -0
  67. package/dist/engine/pipeline/sensors.collect.js.map +1 -0
  68. package/dist/engine/pipeline/specify.exec.d.ts +0 -1
  69. package/dist/engine/pipeline/specify.exec.js +1 -2
  70. package/dist/engine/pipeline/specify.exec.js.map +1 -1
  71. package/dist/sensors/a11y.d.ts +36 -0
  72. package/dist/sensors/a11y.js +134 -0
  73. package/dist/sensors/a11y.js.map +1 -0
  74. package/dist/sensors/contrast.d.ts +3 -0
  75. package/dist/sensors/contrast.js +117 -0
  76. package/dist/sensors/contrast.js.map +1 -0
  77. package/dist/sensors/index.d.ts +27 -0
  78. package/dist/sensors/index.js +3 -0
  79. package/dist/sensors/index.js.map +1 -0
  80. package/dist/sensors/playwright.d.ts +69 -0
  81. package/dist/sensors/playwright.js +266 -0
  82. package/dist/sensors/playwright.js.map +1 -0
  83. package/dist/sensors/vision.d.ts +18 -0
  84. package/dist/sensors/vision.js +125 -0
  85. package/dist/sensors/vision.js.map +1 -0
  86. package/dist/stores/settings.d.ts +0 -1
  87. package/dist/stores/settings.js.map +1 -1
  88. package/dist/types.d.ts +0 -1
  89. package/dist/ui/color.d.ts +16 -0
  90. package/dist/ui/color.js +46 -0
  91. package/dist/ui/color.js.map +1 -0
  92. package/dist/ui/contrast.d.ts +2 -0
  93. package/dist/ui/contrast.js +94 -0
  94. package/dist/ui/contrast.js.map +1 -0
  95. package/dist/ui/dashboard/client.d.ts +1 -0
  96. package/dist/ui/dashboard/client.js +281 -0
  97. package/dist/ui/dashboard/client.js.map +1 -0
  98. package/dist/ui/dashboard/css.d.ts +1 -0
  99. package/dist/ui/dashboard/css.js +341 -0
  100. package/dist/ui/dashboard/css.js.map +1 -0
  101. package/dist/ui/dashboard/events.d.ts +15 -0
  102. package/dist/ui/dashboard/events.js +40 -0
  103. package/dist/ui/dashboard/events.js.map +1 -0
  104. package/dist/ui/dashboard/favicon.d.ts +2 -0
  105. package/dist/ui/dashboard/favicon.js +20 -0
  106. package/dist/ui/dashboard/favicon.js.map +1 -0
  107. package/dist/ui/dashboard/hex.d.ts +7 -0
  108. package/dist/ui/dashboard/hex.js +16 -0
  109. package/dist/ui/dashboard/hex.js.map +1 -0
  110. package/dist/ui/dashboard/html.d.ts +7 -0
  111. package/dist/ui/dashboard/html.js +69 -0
  112. package/dist/ui/dashboard/html.js.map +1 -0
  113. package/dist/ui/dashboard/server.d.ts +26 -0
  114. package/dist/ui/dashboard/server.js +257 -0
  115. package/dist/ui/dashboard/server.js.map +1 -0
  116. package/dist/ui/dashboard/snapshot.d.ts +29 -0
  117. package/dist/ui/dashboard/snapshot.js +71 -0
  118. package/dist/ui/dashboard/snapshot.js.map +1 -0
  119. package/dist/ui/dashboard/tokens.d.ts +19 -0
  120. package/dist/ui/dashboard/tokens.js +25 -0
  121. package/dist/ui/dashboard/tokens.js.map +1 -0
  122. package/dist/ui/dashboard/watcher.d.ts +13 -0
  123. package/dist/ui/dashboard/watcher.js +238 -0
  124. package/dist/ui/dashboard/watcher.js.map +1 -0
  125. package/dist/ui/output.js +3 -2
  126. package/dist/ui/output.js.map +1 -1
  127. package/dist/ui/preflight.d.ts +15 -0
  128. package/dist/ui/preflight.js +147 -0
  129. package/dist/ui/preflight.js.map +1 -0
  130. package/dist/ui/spinner.d.ts +0 -6
  131. package/dist/ui/spinner.js +25 -6
  132. package/dist/ui/spinner.js.map +1 -1
  133. package/dist/ui/transcript.js +2 -3
  134. package/dist/ui/transcript.js.map +1 -1
  135. package/dist/utils/flavour-removed.d.ts +12 -0
  136. package/dist/utils/flavour-removed.js +44 -0
  137. package/dist/utils/flavour-removed.js.map +1 -0
  138. package/package.json +16 -3
@@ -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;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.faviconDataUri = void 0;
4
+ const tokens_1 = require("./tokens");
5
+ const COLOR_BY_STATUS = {
6
+ running: tokens_1.PALETTE.info,
7
+ done: tokens_1.PALETTE.success,
8
+ failed: tokens_1.PALETTE.error,
9
+ idle: tokens_1.PALETTE.textDim,
10
+ };
11
+ const faviconSvg = (status) => {
12
+ const fill = COLOR_BY_STATUS[status];
13
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><circle cx="8" cy="8" r="7" fill="${fill}"/></svg>`;
14
+ };
15
+ const faviconDataUri = (status) => {
16
+ const svg = faviconSvg(status);
17
+ return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
18
+ };
19
+ exports.faviconDataUri = faviconDataUri;
20
+ //# sourceMappingURL=favicon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"favicon.js","sourceRoot":"","sources":["../../../src/ui/dashboard/favicon.ts"],"names":[],"mappings":";;;AAAA,qCAAkC;AAIlC,MAAM,eAAe,GAAkC;IACrD,OAAO,EAAE,gBAAO,CAAC,IAAI;IACrB,IAAI,EAAE,gBAAO,CAAC,OAAO;IACrB,MAAM,EAAE,gBAAO,CAAC,KAAK;IACrB,IAAI,EAAE,gBAAO,CAAC,OAAO;CACtB,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,MAAqB,EAAU,EAAE;IACnD,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IACpC,OAAO,iGAAiG,IAAI,WAAW,CAAA;AACzH,CAAC,CAAA;AAEM,MAAM,cAAc,GAAG,CAAC,MAAqB,EAAU,EAAE;IAC9D,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAA;IAC9B,OAAO,2BAA2B,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAA;AAC7D,CAAC,CAAA;AAHY,QAAA,cAAc,kBAG1B"}
@@ -0,0 +1,7 @@
1
+ export interface Rgb {
2
+ r: number;
3
+ g: number;
4
+ b: number;
5
+ }
6
+ export declare const parseHexRgb: (hex: string) => Rgb;
7
+ export declare const rgbaOf: (hex: string, alpha: number) => string;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.rgbaOf = exports.parseHexRgb = void 0;
4
+ const parseHexRgb = (hex) => {
5
+ const raw = hex.replace(/^#/, "");
6
+ const expanded = raw.length === 3 ? raw.split("").map((c) => c + c).join("") : raw;
7
+ const num = parseInt(expanded, 16);
8
+ return { r: (num >> 16) & 0xff, g: (num >> 8) & 0xff, b: num & 0xff };
9
+ };
10
+ exports.parseHexRgb = parseHexRgb;
11
+ const rgbaOf = (hex, alpha) => {
12
+ const { r, g, b } = (0, exports.parseHexRgb)(hex);
13
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
14
+ };
15
+ exports.rgbaOf = rgbaOf;
16
+ //# sourceMappingURL=hex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hex.js","sourceRoot":"","sources":["../../../src/ui/dashboard/hex.ts"],"names":[],"mappings":";;;AAEO,MAAM,WAAW,GAAG,CAAC,GAAW,EAAO,EAAE;IAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;IAClF,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;IAClC,OAAO,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,GAAG,IAAI,EAAE,CAAA;AACvE,CAAC,CAAA;AALY,QAAA,WAAW,eAKvB;AAEM,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,KAAa,EAAU,EAAE;IAC3D,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,IAAA,mBAAW,EAAC,GAAG,CAAC,CAAA;IACpC,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,GAAG,CAAA;AAC3C,CAAC,CAAA;AAHY,QAAA,MAAM,UAGlB"}
@@ -0,0 +1,7 @@
1
+ import type { DashboardSnapshot } from "./snapshot";
2
+ export interface RenderHtmlOptions {
3
+ buildName: string | null;
4
+ port: number;
5
+ snapshot: DashboardSnapshot;
6
+ }
7
+ export declare const renderHtml: (opts: RenderHtmlOptions) => string;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderHtml = void 0;
4
+ const css_1 = require("./css");
5
+ const client_1 = require("./client");
6
+ const favicon_1 = require("./favicon");
7
+ const escapeHtml = (s) => s
8
+ .replace(/&/g, "&amp;")
9
+ .replace(/</g, "&lt;")
10
+ .replace(/>/g, "&gt;")
11
+ .replace(/"/g, "&quot;")
12
+ .replace(/'/g, "&#39;");
13
+ const renderHtml = (opts) => {
14
+ const { buildName, port, snapshot } = opts;
15
+ const title = buildName
16
+ ? `● ridgeline · ${buildName} · ${snapshot.status ?? "idle"}`
17
+ : "● ridgeline";
18
+ const favicon = (0, favicon_1.faviconDataUri)(snapshot.status === "running"
19
+ ? "running"
20
+ : snapshot.status === "failed"
21
+ ? "failed"
22
+ : snapshot.status === "done"
23
+ ? "done"
24
+ : "idle");
25
+ const bootstrap = JSON.stringify({ buildName, port, snapshot });
26
+ return `<!doctype html>
27
+ <html lang="en">
28
+ <head>
29
+ <meta charset="utf-8">
30
+ <meta name="viewport" content="width=device-width, initial-scale=1">
31
+ <title>${escapeHtml(title)}</title>
32
+ <link id="favicon" rel="icon" href="${favicon}" type="image/svg+xml">
33
+ <style>
34
+ ${(0, css_1.renderCss)()}</style>
35
+ </head>
36
+ <body>
37
+ <div class="page">
38
+ <div id="disconnect-banner" class="disconnect-banner hidden" role="status" aria-live="polite">
39
+ <span class="spinner-dot" aria-hidden="true"></span>
40
+ <span>Disconnected from ridgeline process. Retrying…</span>
41
+ </div>
42
+ <header class="header">
43
+ <h1 id="build-name" class="build-name">${buildName ? escapeHtml(buildName) : "ridgeline"}</h1>
44
+ <span id="header-elapsed" class="header-elapsed mono"></span>
45
+ <span id="header-pill" class="pill pill-pending">pending</span>
46
+ <span class="wordmark">ridgeline</span>
47
+ </header>
48
+ <main id="main">
49
+ <section id="empty-state" class="panel empty" ${buildName ? 'hidden' : ''}>
50
+ <div>No build attached. Run <span class="mono">ridgeline &lt;name&gt; "intent"</span> in another terminal, then reload.</div>
51
+ <div class="empty-hint mono">http://127.0.0.1:${port}</div>
52
+ </section>
53
+ <section id="cost-meter" class="panel" ${buildName ? '' : 'hidden'}>
54
+ <div class="cost-label">Total cost</div>
55
+ <div id="cost-total" class="cost-total mono">$0.00</div>
56
+ <div id="cost-breakdown" class="cost-breakdown"></div>
57
+ </section>
58
+ <section id="phase-list" class="phase-list" aria-label="Phases"></section>
59
+ </main>
60
+ </div>
61
+ <script id="bootstrap" type="application/json">${bootstrap.replace(/</g, "\\u003c")}</script>
62
+ <script>
63
+ ${(0, client_1.renderClientScript)()}</script>
64
+ </body>
65
+ </html>
66
+ `;
67
+ };
68
+ exports.renderHtml = renderHtml;
69
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../../src/ui/dashboard/html.ts"],"names":[],"mappings":";;;AAAA,+BAAiC;AACjC,qCAA6C;AAC7C,uCAA0C;AAS1C,MAAM,UAAU,GAAG,CAAC,CAAS,EAAU,EAAE,CACvC,CAAC;KACE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;KACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;KACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;KACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;KACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AAEpB,MAAM,UAAU,GAAG,CAAC,IAAuB,EAAU,EAAE;IAC5D,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IAC1C,MAAM,KAAK,GAAG,SAAS;QACrB,CAAC,CAAC,iBAAiB,SAAS,MAAM,QAAQ,CAAC,MAAM,IAAI,MAAM,EAAE;QAC7D,CAAC,CAAC,aAAa,CAAA;IACjB,MAAM,OAAO,GAAG,IAAA,wBAAc,EAAC,QAAQ,CAAC,MAAM,KAAK,SAAS;QAC1D,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,QAAQ;YAC5B,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,MAAM;gBAC1B,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,MAAM,CAAC,CAAA;IAEf,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;IAE/D,OAAO;;;;;SAKA,UAAU,CAAC,KAAK,CAAC;sCACY,OAAO;;EAE3C,IAAA,eAAS,GAAE;;;;;;;;;6CASgC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW;;;;;;oDAMxC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;;sDAEvB,IAAI;;6CAEb,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ;;;;;;;;iDAQrB,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;;EAEjF,IAAA,2BAAkB,GAAE;;;CAGrB,CAAA;AACD,CAAC,CAAA;AAxDY,QAAA,UAAU,cAwDtB"}
@@ -0,0 +1,26 @@
1
+ import * as http from "node:http";
2
+ import { DashboardSnapshot } from "./snapshot";
3
+ import { EventName } from "./events";
4
+ export interface StartDashboardOptions {
5
+ buildName: string | null;
6
+ buildDir: string | null;
7
+ port: number;
8
+ host?: string;
9
+ }
10
+ export interface DashboardServer {
11
+ port: number;
12
+ host: string;
13
+ url: string;
14
+ close(): Promise<void>;
15
+ address(): string;
16
+ }
17
+ export interface DashboardApp {
18
+ handle(req: http.IncomingMessage, res: http.ServerResponse): void;
19
+ setPort(port: number): void;
20
+ broadcast(name: EventName, payload: unknown): void;
21
+ snapshot(): DashboardSnapshot;
22
+ clientCount(): number;
23
+ close(): void;
24
+ }
25
+ export declare const createDashboardApp: (opts: StartDashboardOptions) => DashboardApp;
26
+ export declare const startDashboard: (opts: StartDashboardOptions) => Promise<DashboardServer>;