mimetic-cli 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 (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/dist/argv.d.ts +1 -0
  4. package/dist/argv.js +8 -0
  5. package/dist/argv.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +5 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/feedback.d.ts +48 -0
  10. package/dist/feedback.js +243 -0
  11. package/dist/feedback.js.map +1 -0
  12. package/dist/index.d.ts +15 -0
  13. package/dist/index.js +9 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/init-templates.d.ts +12 -0
  16. package/dist/init-templates.js +251 -0
  17. package/dist/init-templates.js.map +1 -0
  18. package/dist/init.d.ts +26 -0
  19. package/dist/init.js +343 -0
  20. package/dist/init.js.map +1 -0
  21. package/dist/observer-assets.d.ts +2 -0
  22. package/dist/observer-assets.js +2322 -0
  23. package/dist/observer-assets.js.map +1 -0
  24. package/dist/observer-data.d.ts +53 -0
  25. package/dist/observer-data.js +123 -0
  26. package/dist/observer-data.js.map +1 -0
  27. package/dist/observer.d.ts +36 -0
  28. package/dist/observer.js +360 -0
  29. package/dist/observer.js.map +1 -0
  30. package/dist/oss-lab.d.ts +50 -0
  31. package/dist/oss-lab.js +298 -0
  32. package/dist/oss-lab.js.map +1 -0
  33. package/dist/oss-meta-lab.d.ts +43 -0
  34. package/dist/oss-meta-lab.js +901 -0
  35. package/dist/oss-meta-lab.js.map +1 -0
  36. package/dist/program.d.ts +36 -0
  37. package/dist/program.js +825 -0
  38. package/dist/program.js.map +1 -0
  39. package/dist/run.d.ts +206 -0
  40. package/dist/run.js +688 -0
  41. package/dist/run.js.map +1 -0
  42. package/package.json +78 -0
  43. package/skills/mimetic-cli/SKILL.md +92 -0
  44. package/skills/mimetic-cli/agents/openai.yaml +7 -0
@@ -0,0 +1,2322 @@
1
+ export function observerCss() {
2
+ return `
3
+ :root {
4
+ --obs-bg: #0a0a0a;
5
+ --obs-bg-1: #0f0f10;
6
+ --obs-bg-2: #141416;
7
+ --obs-bg-3: #1a1a1c;
8
+ --obs-bg-4: #232326;
9
+ --obs-line: rgba(255, 255, 255, 0.06);
10
+ --obs-line-2: rgba(255, 255, 255, 0.1);
11
+ --obs-line-3: rgba(255, 255, 255, 0.18);
12
+ --obs-fg-1: #f4f4f3;
13
+ --obs-fg-2: #b6b6b1;
14
+ --obs-fg-3: #7a7a75;
15
+ --obs-fg-4: #4d4d49;
16
+ --obs-blue: #3f71fa;
17
+ --obs-blue-soft: rgba(63, 113, 250, 0.16);
18
+ --obs-blue-line: rgba(63, 113, 250, 0.4);
19
+ --obs-sky: #70d8fa;
20
+ --obs-amber: #d48806;
21
+ --obs-amber-soft: rgba(212, 136, 6, 0.14);
22
+ --obs-red: #e0584a;
23
+ --obs-red-soft: rgba(224, 88, 74, 0.14);
24
+ --obs-green: #38b07a;
25
+ --obs-green-soft: rgba(56, 176, 122, 0.14);
26
+ --sans: "Geist", "Aptos", "Avenir Next", "Helvetica Neue", system-ui, sans-serif;
27
+ --mono: "ABCDiatypeMono", "Geist Mono", "SFMono-Regular", ui-monospace, Consolas, monospace;
28
+ --display: "Knapp", "Geist", ui-serif, Georgia, serif;
29
+ --ease: cubic-bezier(0.16, 1, 0.3, 1);
30
+ }
31
+
32
+ * { box-sizing: border-box; }
33
+
34
+ html,
35
+ body {
36
+ margin: 0;
37
+ padding: 0;
38
+ height: 100%;
39
+ overflow: hidden;
40
+ }
41
+
42
+ body {
43
+ background: var(--obs-bg);
44
+ color: var(--obs-fg-1);
45
+ font-family: var(--sans);
46
+ font-size: 13px;
47
+ line-height: 1.5;
48
+ -webkit-font-smoothing: antialiased;
49
+ }
50
+
51
+ button {
52
+ font-family: inherit;
53
+ cursor: pointer;
54
+ }
55
+
56
+ button:focus-visible,
57
+ a:focus-visible,
58
+ .tile:focus-visible {
59
+ outline: 2px solid var(--obs-blue);
60
+ outline-offset: 2px;
61
+ }
62
+
63
+ a { color: inherit; }
64
+
65
+ ::-webkit-scrollbar {
66
+ width: 8px;
67
+ height: 8px;
68
+ }
69
+
70
+ ::-webkit-scrollbar-track { background: transparent; }
71
+
72
+ ::-webkit-scrollbar-thumb {
73
+ background: rgba(255, 255, 255, 0.08);
74
+ border-radius: 8px;
75
+ }
76
+
77
+ ::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.16); }
78
+
79
+ .obs-eyebrow {
80
+ font-family: var(--mono);
81
+ font-size: 10px;
82
+ letter-spacing: 0.14em;
83
+ text-transform: uppercase;
84
+ color: var(--obs-fg-3);
85
+ }
86
+
87
+ .app {
88
+ display: flex;
89
+ flex-direction: column;
90
+ height: 100%;
91
+ background: var(--obs-bg);
92
+ }
93
+
94
+ .rp {
95
+ display: flex;
96
+ flex-direction: column;
97
+ border-bottom: 1px solid var(--obs-line);
98
+ background: var(--obs-bg-1);
99
+ flex: none;
100
+ }
101
+
102
+ .rp-bar {
103
+ display: flex;
104
+ align-items: center;
105
+ gap: 12px;
106
+ padding: 10px 16px;
107
+ flex-wrap: wrap;
108
+ row-gap: 8px;
109
+ container-type: inline-size;
110
+ container-name: rp-bar;
111
+ }
112
+
113
+ .rp-brand {
114
+ display: flex;
115
+ align-items: center;
116
+ gap: 10px;
117
+ flex-shrink: 0;
118
+ }
119
+
120
+ .rp-brand-mark {
121
+ width: 16px;
122
+ height: 16px;
123
+ border: 1px solid var(--obs-blue);
124
+ border-radius: 50%;
125
+ display: inline-block;
126
+ position: relative;
127
+ box-shadow: inset 0 0 0 3px rgba(63, 113, 250, 0.16);
128
+ }
129
+
130
+ .rp-brand-mark::after {
131
+ content: "";
132
+ position: absolute;
133
+ width: 6px;
134
+ height: 6px;
135
+ left: 4px;
136
+ top: 4px;
137
+ border: 1px solid var(--obs-sky);
138
+ transform: rotate(45deg);
139
+ }
140
+
141
+ .rp-brand-text {
142
+ font-family: var(--mono);
143
+ font-size: 10px;
144
+ letter-spacing: 0.16em;
145
+ text-transform: uppercase;
146
+ color: var(--obs-fg-2);
147
+ }
148
+
149
+ .rp-divider,
150
+ .sub-divider {
151
+ width: 1px;
152
+ height: 12px;
153
+ background: var(--obs-line-2);
154
+ flex-shrink: 0;
155
+ }
156
+
157
+ .rp-current {
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 8px;
161
+ min-width: 0;
162
+ flex-shrink: 0;
163
+ }
164
+
165
+ .pulse-dot,
166
+ .pip,
167
+ .rp-chip-dot,
168
+ .sub-filter-dot {
169
+ width: 6px;
170
+ height: 6px;
171
+ border-radius: 50%;
172
+ background: currentColor;
173
+ flex: none;
174
+ }
175
+
176
+ .pulse-dot { animation: pulse-dot 1.4s ease-in-out infinite; }
177
+
178
+ .rp-current .pulse-dot { color: var(--obs-blue); }
179
+
180
+ .rp-current-label {
181
+ font-family: var(--mono);
182
+ font-size: 10px;
183
+ letter-spacing: 0.12em;
184
+ text-transform: uppercase;
185
+ color: var(--obs-fg-1);
186
+ }
187
+
188
+ .rp-current-step {
189
+ font-family: var(--mono);
190
+ font-size: 10px;
191
+ letter-spacing: 0.06em;
192
+ color: var(--obs-fg-3);
193
+ }
194
+
195
+ .rp-progress {
196
+ flex: 1 1 80px;
197
+ height: 3px;
198
+ background: var(--obs-line);
199
+ border-radius: 2px;
200
+ overflow: hidden;
201
+ min-width: 60px;
202
+ max-width: 320px;
203
+ }
204
+
205
+ .rp-progress > span {
206
+ display: block;
207
+ height: 100%;
208
+ background: var(--obs-blue);
209
+ transition: width 600ms var(--ease);
210
+ width: 0%;
211
+ }
212
+
213
+ .rp-meta {
214
+ font-family: var(--mono);
215
+ font-size: 10px;
216
+ color: var(--obs-fg-3);
217
+ white-space: nowrap;
218
+ flex-shrink: 0;
219
+ }
220
+
221
+ .rp-meta strong {
222
+ color: var(--obs-fg-1);
223
+ font-weight: 500;
224
+ }
225
+
226
+ .rp-chips {
227
+ margin-left: auto;
228
+ display: flex;
229
+ align-items: center;
230
+ gap: 6px;
231
+ flex-shrink: 0;
232
+ }
233
+
234
+ .rp-chip {
235
+ display: inline-flex;
236
+ align-items: center;
237
+ gap: 6px;
238
+ padding: 3px 8px;
239
+ border: 1px solid var(--obs-line);
240
+ border-radius: 2px;
241
+ background: transparent;
242
+ font-family: var(--mono);
243
+ }
244
+
245
+ .rp-chip[data-active="true"] { background: var(--obs-bg-2); }
246
+
247
+ .rp-chip-label {
248
+ font-size: 10px;
249
+ letter-spacing: 0.1em;
250
+ text-transform: uppercase;
251
+ color: var(--obs-fg-3);
252
+ }
253
+
254
+ .rp-chip-count {
255
+ font-size: 11px;
256
+ color: var(--obs-fg-1);
257
+ font-weight: 500;
258
+ }
259
+
260
+ .rp-chip[data-dim="true"] { opacity: 0.55; }
261
+
262
+ .rp-toggle,
263
+ .sub-action,
264
+ .sub-filter,
265
+ .kind-filter,
266
+ .sub-density-btn {
267
+ border-radius: 2px;
268
+ background: transparent;
269
+ color: var(--obs-fg-2);
270
+ border: 1px solid var(--obs-line);
271
+ font-family: var(--mono);
272
+ font-size: 10px;
273
+ letter-spacing: 0.1em;
274
+ text-transform: uppercase;
275
+ }
276
+
277
+ .rp-toggle {
278
+ padding: 3px 8px;
279
+ display: inline-flex;
280
+ align-items: center;
281
+ gap: 5px;
282
+ }
283
+
284
+ .rp-stepper {
285
+ display: grid;
286
+ padding: 12px 20px 14px;
287
+ border-top: 1px solid var(--obs-line);
288
+ gap: 0;
289
+ }
290
+
291
+ .rp-stepper[hidden] { display: none; }
292
+
293
+ .rp-stepper-cell {
294
+ position: relative;
295
+ padding-right: 16px;
296
+ display: grid;
297
+ grid-template-rows: 14px auto auto;
298
+ row-gap: 6px;
299
+ align-content: start;
300
+ }
301
+
302
+ .rp-stepper-cell:last-child { padding-right: 0; }
303
+
304
+ .rp-stepper-mark {
305
+ position: relative;
306
+ display: flex;
307
+ align-items: center;
308
+ height: 14px;
309
+ z-index: 1;
310
+ }
311
+
312
+ .rp-stepper-mark > span {
313
+ width: 6px;
314
+ height: 6px;
315
+ border-radius: 50%;
316
+ flex: none;
317
+ }
318
+
319
+ .rp-stepper-mark[data-state="done"] > span { background: var(--obs-blue); }
320
+
321
+ .rp-stepper-mark[data-state="active"] > span {
322
+ width: 7px;
323
+ height: 7px;
324
+ background: var(--obs-sky);
325
+ animation: pulse-dot 1.4s ease-in-out infinite;
326
+ }
327
+
328
+ .rp-stepper-mark[data-state="pending"] > span { background: var(--obs-fg-4); }
329
+
330
+ .rp-stepper-label {
331
+ font-family: var(--mono);
332
+ font-size: 10px;
333
+ letter-spacing: 0.12em;
334
+ text-transform: uppercase;
335
+ color: var(--obs-fg-1);
336
+ white-space: nowrap;
337
+ }
338
+
339
+ .rp-stepper-desc {
340
+ font-size: 11px;
341
+ color: var(--obs-fg-3);
342
+ white-space: nowrap;
343
+ overflow: hidden;
344
+ text-overflow: ellipsis;
345
+ }
346
+
347
+ .rp-stepper-conn {
348
+ position: absolute;
349
+ left: 14px;
350
+ right: 0;
351
+ top: 6px;
352
+ height: 1px;
353
+ background: var(--obs-line);
354
+ z-index: 0;
355
+ }
356
+
357
+ .rp-stepper-cell[data-state="done"] .rp-stepper-conn { background: var(--obs-blue); }
358
+
359
+ .sub-bar {
360
+ display: flex;
361
+ align-items: center;
362
+ gap: 12px;
363
+ padding: 8px 16px;
364
+ border-bottom: 1px solid var(--obs-line);
365
+ background: var(--obs-bg);
366
+ flex: none;
367
+ min-height: 41px;
368
+ }
369
+
370
+ .sub-count {
371
+ font-family: var(--mono);
372
+ font-size: 11px;
373
+ color: var(--obs-fg-3);
374
+ }
375
+
376
+ .sub-count strong {
377
+ color: var(--obs-fg-1);
378
+ font-weight: 500;
379
+ }
380
+
381
+ .sub-filters,
382
+ .sub-kind-filters {
383
+ display: flex;
384
+ gap: 4px;
385
+ min-width: 0;
386
+ }
387
+
388
+ .sub-filter,
389
+ .kind-filter {
390
+ display: inline-flex;
391
+ align-items: center;
392
+ gap: 6px;
393
+ padding: 3px 9px;
394
+ white-space: nowrap;
395
+ }
396
+
397
+ .sub-filter[aria-pressed="true"],
398
+ .kind-filter[aria-pressed="true"],
399
+ .sub-density-btn[aria-pressed="true"] {
400
+ background: var(--obs-bg-3);
401
+ color: var(--obs-fg-1);
402
+ }
403
+
404
+ .sub-filter-count,
405
+ .kind-filter-count { color: var(--obs-fg-3); }
406
+
407
+ .sub-spacer {
408
+ margin-left: auto;
409
+ display: flex;
410
+ align-items: center;
411
+ gap: 8px;
412
+ }
413
+
414
+ .sub-density-btn {
415
+ width: 26px;
416
+ height: 22px;
417
+ color: var(--obs-fg-3);
418
+ }
419
+
420
+ .sub-action {
421
+ padding: 4px 9px;
422
+ display: inline-flex;
423
+ align-items: center;
424
+ gap: 6px;
425
+ }
426
+
427
+ .sub-action[aria-pressed="true"] {
428
+ background: var(--obs-amber-soft);
429
+ color: var(--obs-amber);
430
+ }
431
+
432
+ .sub-action[data-mode-toggle="true"][aria-pressed="true"] {
433
+ background: var(--obs-blue-soft);
434
+ color: #8aa9ff;
435
+ }
436
+
437
+ .history-panel {
438
+ position: fixed;
439
+ inset: 0 auto 0 0;
440
+ z-index: 30;
441
+ width: min(390px, calc(100vw - 32px));
442
+ display: flex;
443
+ flex-direction: column;
444
+ background: rgba(15, 15, 16, 0.98);
445
+ border-right: 1px solid var(--obs-line-2);
446
+ box-shadow: 24px 0 80px rgba(0, 0, 0, 0.45);
447
+ }
448
+
449
+ .history-panel[hidden] { display: none; }
450
+
451
+ .history-head {
452
+ display: flex;
453
+ align-items: flex-start;
454
+ justify-content: space-between;
455
+ gap: 16px;
456
+ padding: 16px;
457
+ border-bottom: 1px solid var(--obs-line);
458
+ }
459
+
460
+ .history-head h2 {
461
+ margin: 4px 0 0;
462
+ font-size: 18px;
463
+ line-height: 1.15;
464
+ font-weight: 500;
465
+ color: var(--obs-fg-1);
466
+ }
467
+
468
+ .history-close {
469
+ width: 28px;
470
+ height: 28px;
471
+ border: 1px solid var(--obs-line);
472
+ border-radius: 2px;
473
+ background: transparent;
474
+ color: var(--obs-fg-2);
475
+ font-size: 18px;
476
+ line-height: 1;
477
+ }
478
+
479
+ .history-current {
480
+ padding: 12px 16px;
481
+ border-bottom: 1px solid var(--obs-line);
482
+ font-family: var(--mono);
483
+ font-size: 10px;
484
+ color: var(--obs-fg-3);
485
+ }
486
+
487
+ .history-list {
488
+ flex: 1 1 0;
489
+ min-height: 0;
490
+ overflow: auto;
491
+ }
492
+
493
+ .history-run {
494
+ display: grid;
495
+ grid-template-columns: 1fr auto;
496
+ gap: 8px 12px;
497
+ padding: 12px 16px;
498
+ border: 0;
499
+ border-bottom: 1px solid var(--obs-line);
500
+ background: transparent;
501
+ color: inherit;
502
+ text-align: left;
503
+ text-decoration: none;
504
+ }
505
+
506
+ .history-run:hover,
507
+ .history-run[data-active="true"] { background: var(--obs-bg-3); }
508
+
509
+ .history-run[data-active="true"] { box-shadow: inset 2px 0 0 var(--obs-blue); }
510
+
511
+ .history-run-id {
512
+ font-family: var(--mono);
513
+ font-size: 11px;
514
+ color: var(--obs-fg-1);
515
+ white-space: nowrap;
516
+ overflow: hidden;
517
+ text-overflow: ellipsis;
518
+ }
519
+
520
+ .history-run-meta,
521
+ .history-run-counts {
522
+ font-family: var(--mono);
523
+ font-size: 10px;
524
+ color: var(--obs-fg-3);
525
+ white-space: nowrap;
526
+ overflow: hidden;
527
+ text-overflow: ellipsis;
528
+ }
529
+
530
+ .history-run-status {
531
+ display: inline-flex;
532
+ align-items: center;
533
+ gap: 6px;
534
+ font-family: var(--mono);
535
+ font-size: 10px;
536
+ color: var(--obs-fg-2);
537
+ text-transform: uppercase;
538
+ letter-spacing: 0.1em;
539
+ }
540
+
541
+ .history-empty {
542
+ padding: 16px;
543
+ color: var(--obs-fg-3);
544
+ }
545
+
546
+ .grid-shell {
547
+ flex: 1;
548
+ padding: 16px;
549
+ min-height: 0;
550
+ min-width: 0;
551
+ overflow: auto;
552
+ }
553
+
554
+ .grid-shell[hidden] { display: none; }
555
+
556
+ .tile-grid {
557
+ position: relative;
558
+ width: 100%;
559
+ }
560
+
561
+ .tile {
562
+ display: grid;
563
+ grid-template-columns: minmax(0, 1fr);
564
+ grid-template-rows: auto minmax(0, 1fr) auto;
565
+ background: var(--obs-bg-2);
566
+ border: 1px solid var(--obs-line);
567
+ position: relative;
568
+ overflow: hidden;
569
+ cursor: pointer;
570
+ min-width: 0;
571
+ }
572
+
573
+ .tile-grid > .tile {
574
+ position: absolute;
575
+ margin: 0;
576
+ }
577
+
578
+ .tile:hover { border-color: var(--obs-line-2); }
579
+
580
+ .tile[data-selected="true"] {
581
+ box-shadow:
582
+ 0 0 0 1px var(--obs-blue),
583
+ 0 0 0 4px var(--obs-blue-soft);
584
+ }
585
+
586
+ .tile-head {
587
+ display: flex;
588
+ align-items: center;
589
+ gap: 6px;
590
+ padding: 3px 7px;
591
+ height: 22px;
592
+ border-bottom: 1px solid var(--obs-line);
593
+ background: var(--obs-bg-1);
594
+ flex: none;
595
+ }
596
+
597
+ .tile-idx {
598
+ font-family: var(--mono);
599
+ font-size: 9px;
600
+ color: var(--obs-fg-3);
601
+ letter-spacing: 0.05em;
602
+ }
603
+
604
+ .tile-role {
605
+ font-family: var(--mono);
606
+ font-size: 9px;
607
+ letter-spacing: 0.08em;
608
+ text-transform: uppercase;
609
+ color: var(--obs-green);
610
+ flex: none;
611
+ }
612
+
613
+ .tile-name {
614
+ font-size: 11px;
615
+ color: var(--obs-fg-1);
616
+ white-space: nowrap;
617
+ overflow: hidden;
618
+ text-overflow: ellipsis;
619
+ flex: 1;
620
+ min-width: 0;
621
+ }
622
+
623
+ .tile-view {
624
+ font-family: var(--mono);
625
+ font-size: 9px;
626
+ color: var(--obs-fg-3);
627
+ letter-spacing: 0.06em;
628
+ text-transform: uppercase;
629
+ }
630
+
631
+ .tile-stream-shell {
632
+ position: relative;
633
+ background: #050505;
634
+ overflow: hidden;
635
+ min-height: 0;
636
+ min-width: 0;
637
+ height: 100%;
638
+ width: 100%;
639
+ max-width: 100%;
640
+ }
641
+
642
+ .tile-stream-shell::after {
643
+ content: "";
644
+ position: absolute;
645
+ inset: 0;
646
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.04);
647
+ pointer-events: none;
648
+ }
649
+
650
+ .media-surface {
651
+ position: absolute;
652
+ inset: 0;
653
+ display: flex;
654
+ align-items: center;
655
+ justify-content: center;
656
+ min-width: 0;
657
+ overflow: hidden;
658
+ }
659
+
660
+ .media-surface > iframe,
661
+ .media-surface > img {
662
+ display: block;
663
+ width: 100%;
664
+ height: 100%;
665
+ max-width: 100%;
666
+ object-fit: contain;
667
+ background: #050505;
668
+ border: 0;
669
+ }
670
+
671
+ .tile .media-surface > iframe,
672
+ .tile .media-surface > img { pointer-events: none; }
673
+
674
+ .terminal-surface,
675
+ .live-waiting-surface,
676
+ .synthetic-codex,
677
+ .placeholder-surface {
678
+ width: 100%;
679
+ height: 100%;
680
+ }
681
+
682
+ .terminal-surface {
683
+ display: grid;
684
+ grid-template-rows: auto minmax(0, 1fr);
685
+ background: #050505;
686
+ color: var(--obs-fg-2);
687
+ font-family: var(--mono);
688
+ overflow: hidden;
689
+ }
690
+
691
+ .terminal-bar {
692
+ display: grid;
693
+ grid-template-columns: auto minmax(0, 1fr) auto;
694
+ gap: 8px;
695
+ align-items: center;
696
+ padding: 6px 8px;
697
+ border-bottom: 1px solid var(--obs-line);
698
+ background: rgba(255, 255, 255, 0.03);
699
+ }
700
+
701
+ .terminal-prompt { color: var(--obs-green); }
702
+
703
+ .terminal-title {
704
+ min-width: 0;
705
+ overflow: hidden;
706
+ text-overflow: ellipsis;
707
+ white-space: nowrap;
708
+ color: var(--obs-fg-1);
709
+ font-size: 10px;
710
+ }
711
+
712
+ .terminal-status {
713
+ color: var(--obs-fg-3);
714
+ font-size: 9px;
715
+ text-transform: uppercase;
716
+ }
717
+
718
+ .terminal-body {
719
+ min-height: 0;
720
+ overflow: hidden;
721
+ padding: 8px;
722
+ font-size: 10px;
723
+ line-height: 1.45;
724
+ }
725
+
726
+ .focus .terminal-body {
727
+ overflow: auto;
728
+ font-size: 12px;
729
+ }
730
+
731
+ .terminal-line {
732
+ display: grid;
733
+ grid-template-columns: 28px minmax(0, 1fr);
734
+ gap: 8px;
735
+ min-width: 0;
736
+ }
737
+
738
+ .terminal-line-prefix {
739
+ color: var(--obs-fg-4);
740
+ text-align: right;
741
+ }
742
+
743
+ .terminal-line-text {
744
+ color: var(--obs-fg-2);
745
+ white-space: pre-wrap;
746
+ overflow-wrap: anywhere;
747
+ }
748
+
749
+ .synthetic-codex,
750
+ .placeholder-surface {
751
+ background: #101010;
752
+ padding: 10px;
753
+ color: #181b1a;
754
+ }
755
+
756
+ .codex-frame {
757
+ height: 100%;
758
+ border-radius: 8px;
759
+ overflow: hidden;
760
+ background: #f7f8f4;
761
+ box-shadow: 0 16px 40px rgba(0, 0, 0, 0.32);
762
+ display: grid;
763
+ grid-template-rows: auto minmax(0, 1fr);
764
+ }
765
+
766
+ .codex-chrome {
767
+ height: 30px;
768
+ display: flex;
769
+ align-items: center;
770
+ gap: 8px;
771
+ padding: 0 10px;
772
+ border-bottom: 1px solid #d9ded8;
773
+ background: #eef1ed;
774
+ font-family: var(--mono);
775
+ font-size: 9px;
776
+ color: #59645f;
777
+ }
778
+
779
+ .live-waiting-surface {
780
+ position: relative;
781
+ display: flex;
782
+ align-items: center;
783
+ justify-content: center;
784
+ overflow: hidden;
785
+ background: #020202;
786
+ color: var(--obs-fg-2);
787
+ font-family: var(--mono);
788
+ }
789
+
790
+ .live-waiting-surface::before {
791
+ content: "";
792
+ position: absolute;
793
+ inset: 0;
794
+ background:
795
+ radial-gradient(circle at 50% 42%, rgba(63, 113, 250, 0.12), transparent 34%),
796
+ linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px);
797
+ background-size: auto, 100% 28px;
798
+ opacity: 0.7;
799
+ }
800
+
801
+ .live-waiting-inner {
802
+ position: relative;
803
+ z-index: 1;
804
+ width: min(360px, calc(100% - 32px));
805
+ display: grid;
806
+ justify-items: center;
807
+ gap: 12px;
808
+ text-align: center;
809
+ }
810
+
811
+ .live-spinner {
812
+ width: 34px;
813
+ height: 34px;
814
+ border: 1px solid rgba(255, 255, 255, 0.18);
815
+ border-top-color: var(--obs-blue);
816
+ border-radius: 50%;
817
+ animation: live-spin 1s linear infinite;
818
+ }
819
+
820
+ .live-waiting-title {
821
+ color: var(--obs-fg-1);
822
+ font-size: 12px;
823
+ letter-spacing: 0.12em;
824
+ text-transform: uppercase;
825
+ }
826
+
827
+ .live-waiting-url {
828
+ max-width: 100%;
829
+ color: var(--obs-fg-3);
830
+ font-size: 10px;
831
+ overflow: hidden;
832
+ text-overflow: ellipsis;
833
+ white-space: nowrap;
834
+ }
835
+
836
+ .live-waiting-status {
837
+ max-width: 100%;
838
+ color: var(--obs-fg-2);
839
+ font-size: 10px;
840
+ line-height: 1.5;
841
+ overflow-wrap: anywhere;
842
+ }
843
+
844
+ .chrome-dot {
845
+ width: 7px;
846
+ height: 7px;
847
+ border-radius: 50%;
848
+ background: #c9d0ca;
849
+ }
850
+
851
+ .codex-url {
852
+ min-width: 0;
853
+ overflow: hidden;
854
+ text-overflow: ellipsis;
855
+ white-space: nowrap;
856
+ }
857
+
858
+ .codex-body {
859
+ min-height: 0;
860
+ display: grid;
861
+ grid-template-columns: 120px minmax(0, 1fr);
862
+ background: #f8f8f5;
863
+ }
864
+
865
+ .codex-rail {
866
+ border-right: 1px solid #dadfda;
867
+ padding: 12px;
868
+ display: grid;
869
+ align-content: start;
870
+ gap: 8px;
871
+ }
872
+
873
+ .codex-thread {
874
+ height: 24px;
875
+ border-radius: 4px;
876
+ background: #e8ece7;
877
+ }
878
+
879
+ .codex-main {
880
+ padding: 16px;
881
+ display: grid;
882
+ align-content: start;
883
+ gap: 12px;
884
+ }
885
+
886
+ .codex-bubble {
887
+ min-height: 38px;
888
+ border: 1px solid #d7ddd7;
889
+ border-radius: 8px;
890
+ background: white;
891
+ }
892
+
893
+ .codex-bubble.dark {
894
+ background: #17201d;
895
+ border-color: #17201d;
896
+ }
897
+
898
+ .placeholder-surface {
899
+ display: flex;
900
+ align-items: center;
901
+ justify-content: center;
902
+ }
903
+
904
+ .placeholder-box {
905
+ max-width: 320px;
906
+ padding: 18px;
907
+ border: 1px solid var(--obs-line-2);
908
+ color: var(--obs-fg-2);
909
+ background: var(--obs-bg-1);
910
+ font-family: var(--mono);
911
+ font-size: 11px;
912
+ line-height: 1.45;
913
+ }
914
+
915
+ .tile-cap {
916
+ height: 22px;
917
+ display: grid;
918
+ grid-template-columns: auto minmax(0, 1fr) 52px;
919
+ align-items: center;
920
+ gap: 8px;
921
+ padding: 0 7px;
922
+ border-top: 1px solid var(--obs-line);
923
+ background: var(--obs-bg-1);
924
+ }
925
+
926
+ .tile-cap-eyebrow {
927
+ font-family: var(--mono);
928
+ font-size: 9px;
929
+ letter-spacing: 0.1em;
930
+ color: var(--obs-fg-3);
931
+ text-transform: uppercase;
932
+ }
933
+
934
+ .tile-cap-text {
935
+ min-width: 0;
936
+ overflow: hidden;
937
+ text-overflow: ellipsis;
938
+ white-space: nowrap;
939
+ color: var(--obs-fg-2);
940
+ font-size: 11px;
941
+ }
942
+
943
+ .tile-cap-bar {
944
+ height: 2px;
945
+ background: var(--obs-line);
946
+ overflow: hidden;
947
+ }
948
+
949
+ .tile-cap-bar > span {
950
+ display: block;
951
+ height: 100%;
952
+ background: var(--obs-blue);
953
+ }
954
+
955
+ .tile-cap[data-status="failed"] .tile-cap-bar > span,
956
+ .tile-cap[data-status="blocked"] .tile-cap-bar > span { background: var(--obs-red); }
957
+
958
+ .tile-cap[data-status="complete"] .tile-cap-bar > span,
959
+ .tile-cap[data-status="contract_proof_only"] .tile-cap-bar > span { background: var(--obs-green); }
960
+
961
+ .pip[data-status="queued"] { color: var(--obs-fg-4); }
962
+ .pip[data-status="preparing"] { color: var(--obs-sky); }
963
+ .pip[data-status="running"] { color: var(--obs-blue); }
964
+ .pip[data-status="complete"] { color: var(--obs-green); }
965
+ .pip[data-status="contract_proof_only"] { color: var(--obs-green); }
966
+ .pip[data-status="blocked"] { color: var(--obs-amber); }
967
+ .pip[data-status="failed"] { color: var(--obs-red); }
968
+
969
+ .focus {
970
+ display: flex;
971
+ flex: 1 1 0;
972
+ min-height: 0;
973
+ height: 100%;
974
+ overflow: hidden;
975
+ background: var(--obs-bg);
976
+ }
977
+
978
+ .focus[hidden] { display: none; }
979
+
980
+ .focus-rail {
981
+ width: 56px;
982
+ flex: none;
983
+ border-right: 1px solid var(--obs-line);
984
+ background: var(--obs-bg-1);
985
+ display: flex;
986
+ flex-direction: column;
987
+ padding: 10px 0;
988
+ gap: 4px;
989
+ overflow-y: auto;
990
+ }
991
+
992
+ .focus-rail-item {
993
+ display: flex;
994
+ flex-direction: column;
995
+ align-items: center;
996
+ gap: 3px;
997
+ padding: 6px 4px;
998
+ background: transparent;
999
+ border: 0;
1000
+ border-left: 2px solid transparent;
1001
+ width: 100%;
1002
+ }
1003
+
1004
+ .focus-rail-item[data-selected="true"] {
1005
+ background: var(--obs-bg-3);
1006
+ border-left-color: var(--obs-blue);
1007
+ }
1008
+
1009
+ .focus-rail-idx {
1010
+ font-family: var(--mono);
1011
+ font-size: 9px;
1012
+ color: var(--obs-fg-3);
1013
+ }
1014
+
1015
+ .focus-rail-item[data-selected="true"] .focus-rail-idx { color: var(--obs-fg-1); }
1016
+
1017
+ .focus-stage {
1018
+ flex: 1 1 0;
1019
+ display: flex;
1020
+ flex-direction: column;
1021
+ min-width: 0;
1022
+ min-height: 0;
1023
+ background: #050505;
1024
+ }
1025
+
1026
+ .focus-toolbar {
1027
+ display: flex;
1028
+ align-items: center;
1029
+ gap: 16px;
1030
+ padding: 10px 16px;
1031
+ background: var(--obs-bg-1);
1032
+ border-bottom: 1px solid var(--obs-line);
1033
+ flex: none;
1034
+ }
1035
+
1036
+ .focus-back {
1037
+ display: inline-flex;
1038
+ align-items: center;
1039
+ gap: 6px;
1040
+ padding: 5px 10px;
1041
+ border-radius: 2px;
1042
+ background: transparent;
1043
+ color: var(--obs-fg-2);
1044
+ border: 1px solid var(--obs-line-2);
1045
+ font-family: var(--mono);
1046
+ font-size: 10px;
1047
+ letter-spacing: 0.12em;
1048
+ text-transform: uppercase;
1049
+ }
1050
+
1051
+ .focus-id {
1052
+ font-family: var(--mono);
1053
+ font-size: 10px;
1054
+ color: var(--obs-fg-3);
1055
+ letter-spacing: 0.1em;
1056
+ text-transform: uppercase;
1057
+ }
1058
+
1059
+ .focus-persona {
1060
+ font-size: 13px;
1061
+ color: var(--obs-fg-1);
1062
+ }
1063
+
1064
+ .focus-status-badge {
1065
+ display: inline-flex;
1066
+ align-items: center;
1067
+ gap: 6px;
1068
+ padding: 3px 8px;
1069
+ border-radius: 2px;
1070
+ font-family: var(--mono);
1071
+ font-size: 10px;
1072
+ letter-spacing: 0.12em;
1073
+ text-transform: uppercase;
1074
+ background: rgba(255, 255, 255, 0.06);
1075
+ color: var(--obs-fg-1);
1076
+ }
1077
+
1078
+ .focus-status-badge[data-status="running"],
1079
+ .focus-status-badge[data-status="preparing"] {
1080
+ background: var(--obs-blue-soft);
1081
+ color: #8aa9ff;
1082
+ }
1083
+
1084
+ .focus-status-badge[data-status="blocked"] {
1085
+ background: var(--obs-amber-soft);
1086
+ color: #e9b04b;
1087
+ }
1088
+
1089
+ .focus-status-badge[data-status="failed"] {
1090
+ background: var(--obs-red-soft);
1091
+ color: #ee8a7e;
1092
+ }
1093
+
1094
+ .focus-status-badge[data-status="complete"],
1095
+ .focus-status-badge[data-status="contract_proof_only"] {
1096
+ background: var(--obs-green-soft);
1097
+ color: #6dd0a3;
1098
+ }
1099
+
1100
+ .focus-stats {
1101
+ margin-left: auto;
1102
+ font-family: var(--mono);
1103
+ font-size: 11px;
1104
+ color: var(--obs-fg-3);
1105
+ }
1106
+
1107
+ .focus-stats strong {
1108
+ color: var(--obs-fg-1);
1109
+ font-weight: 500;
1110
+ }
1111
+
1112
+ .focus-stage-area {
1113
+ flex: 1 1 0;
1114
+ min-height: 0;
1115
+ min-width: 0;
1116
+ padding: 0;
1117
+ position: relative;
1118
+ display: flex;
1119
+ align-items: center;
1120
+ justify-content: center;
1121
+ overflow: auto;
1122
+ }
1123
+
1124
+ .focus-stage-area .tile-stream-shell {
1125
+ flex: none;
1126
+ width: auto;
1127
+ height: auto;
1128
+ margin: 0 auto;
1129
+ aspect-ratio: var(--stream-aspect, 16 / 9);
1130
+ }
1131
+
1132
+ .focus-side {
1133
+ width: 380px;
1134
+ flex: none;
1135
+ border-left: 1px solid var(--obs-line);
1136
+ background: var(--obs-bg-1);
1137
+ display: flex;
1138
+ flex-direction: column;
1139
+ min-height: 0;
1140
+ height: 100%;
1141
+ overflow: hidden;
1142
+ }
1143
+
1144
+ .focus-side-context {
1145
+ flex: 0 1 auto;
1146
+ max-height: min(46vh, 430px);
1147
+ min-height: 0;
1148
+ overflow-y: auto;
1149
+ border-bottom: 1px solid var(--obs-line);
1150
+ }
1151
+
1152
+ .focus-side-head { padding: 20px 20px 16px; }
1153
+
1154
+ .focus-side-head h2 {
1155
+ font-family: var(--display);
1156
+ font-size: 22px;
1157
+ font-weight: 400;
1158
+ margin: 6px 0 0;
1159
+ line-height: 1.15;
1160
+ color: var(--obs-fg-1);
1161
+ }
1162
+
1163
+ .focus-side-goal { margin-top: 14px; }
1164
+
1165
+ .focus-side-goal-text {
1166
+ font-size: 13px;
1167
+ color: var(--obs-fg-2);
1168
+ margin-top: 4px;
1169
+ line-height: 1.5;
1170
+ overflow-wrap: anywhere;
1171
+ }
1172
+
1173
+ .focus-side-thinking {
1174
+ padding: 14px 20px;
1175
+ background: var(--obs-bg-2);
1176
+ }
1177
+
1178
+ .focus-side-thinking-row {
1179
+ display: flex;
1180
+ align-items: center;
1181
+ gap: 6px;
1182
+ margin-bottom: 6px;
1183
+ }
1184
+
1185
+ .focus-side-thinking-row .obs-eyebrow { color: var(--obs-blue); }
1186
+
1187
+ .focus-side-thinking-text {
1188
+ font-size: 13px;
1189
+ color: var(--obs-fg-1);
1190
+ font-style: italic;
1191
+ line-height: 1.45;
1192
+ }
1193
+
1194
+ .focus-tabs {
1195
+ display: flex;
1196
+ border-bottom: 1px solid var(--obs-line);
1197
+ flex: none;
1198
+ overflow-x: auto;
1199
+ overflow-y: hidden;
1200
+ scrollbar-width: thin;
1201
+ }
1202
+
1203
+ .focus-tab {
1204
+ padding: 10px 12px;
1205
+ background: transparent;
1206
+ color: var(--obs-fg-3);
1207
+ border: 0;
1208
+ border-bottom: 1px solid transparent;
1209
+ font-family: var(--mono);
1210
+ font-size: 10px;
1211
+ letter-spacing: 0.12em;
1212
+ text-transform: uppercase;
1213
+ display: inline-flex;
1214
+ align-items: center;
1215
+ gap: 5px;
1216
+ flex: 0 0 auto;
1217
+ white-space: nowrap;
1218
+ }
1219
+
1220
+ .focus-tab[aria-selected="true"] {
1221
+ background: var(--obs-bg-2);
1222
+ color: var(--obs-fg-1);
1223
+ border-bottom-color: var(--obs-blue);
1224
+ }
1225
+
1226
+ .focus-tab-badge {
1227
+ font-size: 9px;
1228
+ color: var(--obs-fg-3);
1229
+ }
1230
+
1231
+ .focus-tabbody {
1232
+ flex: 1 1 0;
1233
+ min-height: 0;
1234
+ overflow-y: auto;
1235
+ }
1236
+
1237
+ .event-row,
1238
+ .artifact-row {
1239
+ display: flex;
1240
+ gap: 10px;
1241
+ padding: 10px 16px;
1242
+ border-bottom: 1px solid var(--obs-line);
1243
+ }
1244
+
1245
+ .event-row-icon {
1246
+ font-family: var(--mono);
1247
+ font-size: 11px;
1248
+ color: var(--obs-fg-3);
1249
+ flex: none;
1250
+ margin-top: 2px;
1251
+ text-transform: uppercase;
1252
+ letter-spacing: 0.08em;
1253
+ }
1254
+
1255
+ .event-row[data-kind="warn"] .event-row-icon,
1256
+ .event-row[data-kind="blocked"] .event-row-icon { color: var(--obs-amber); }
1257
+
1258
+ .event-row[data-kind="error"] .event-row-icon,
1259
+ .event-row[data-kind="failed"] .event-row-icon { color: var(--obs-red); }
1260
+
1261
+ .event-row[data-kind="complete"] .event-row-icon { color: var(--obs-green); }
1262
+
1263
+ .event-row-text,
1264
+ .artifact-row-text {
1265
+ font-size: 12px;
1266
+ color: var(--obs-fg-1);
1267
+ line-height: 1.4;
1268
+ overflow-wrap: anywhere;
1269
+ }
1270
+
1271
+ .event-row-meta,
1272
+ .artifact-row-meta {
1273
+ font-family: var(--mono);
1274
+ font-size: 10px;
1275
+ color: var(--obs-fg-3);
1276
+ letter-spacing: 0.08em;
1277
+ text-transform: uppercase;
1278
+ margin-top: 2px;
1279
+ }
1280
+
1281
+ .artifact-row a {
1282
+ color: var(--obs-fg-1);
1283
+ text-decoration: none;
1284
+ }
1285
+
1286
+ @container rp-bar (max-width: 1100px) {
1287
+ .rp-meta { display: none; }
1288
+ }
1289
+
1290
+ @keyframes pulse-dot {
1291
+ 0%, 100% { transform: scale(1); opacity: 0.65; }
1292
+ 50% { transform: scale(1.35); opacity: 1; }
1293
+ }
1294
+
1295
+ @keyframes live-spin {
1296
+ to { transform: rotate(360deg); }
1297
+ }
1298
+ `;
1299
+ }
1300
+ export function observerClientJs() {
1301
+ return `
1302
+ (function () {
1303
+ var DATA_FILE = "observer-data.json";
1304
+ var embedded = JSON.parse(document.getElementById("observer-data").textContent || "null");
1305
+ var currentData = embedded;
1306
+ var focusedId = focusedIdFromLocation();
1307
+ var preferScreenshots = false;
1308
+ var mediaPreferenceTouched = false;
1309
+ var activeStatus = "all";
1310
+ var activeKind = "all";
1311
+ var density = Number(readPref("density", 4));
1312
+ var stepperOpen = readPref("stepperOpen", false) === true;
1313
+ var historyOpen = readPref("historyOpen", false) === true;
1314
+ var historyIndex = null;
1315
+ var activeFocusTab = "events";
1316
+ var refreshTimer = null;
1317
+ var historyTimer = null;
1318
+
1319
+ var RUN_PHASES = [
1320
+ { id: "packet", label: "Packet prep", desc: "Reading run bundle" },
1321
+ { id: "persona", label: "Persona plan", desc: "Persona and scenario loaded" },
1322
+ { id: "streams", label: "Stream mount", desc: "Observer lanes mounted" },
1323
+ { id: "evidence", label: "Evidence review", desc: "Artifacts and events linked" },
1324
+ { id: "ready", label: "Observer ready", desc: "Operator console live" }
1325
+ ];
1326
+
1327
+ var GRID_SCALE_STREAM_HEIGHT = { 2: 180, 3: 260, 4: 360, 5: 500 };
1328
+
1329
+ function getElement(id) {
1330
+ var node = document.getElementById(id);
1331
+ if (!node) throw new Error("Missing observer element: " + id);
1332
+ return node;
1333
+ }
1334
+
1335
+ function render() {
1336
+ var liveAvailable = hasLiveStreams(currentData);
1337
+ if (!mediaPreferenceTouched || !liveAvailable) {
1338
+ preferScreenshots = preferredScreenshotMode(currentData);
1339
+ }
1340
+ document.title = "Mimetic Observer - " + currentData.run.runId;
1341
+ renderProgress();
1342
+ renderSubBar();
1343
+ renderStreams();
1344
+ renderFocus();
1345
+ renderHistoryPanel();
1346
+ }
1347
+
1348
+ function renderProgress() {
1349
+ var counts = countStatuses(currentData.streams);
1350
+ var total = currentData.streams.length || 1;
1351
+ var phaseIndex = currentData.run.status === "contract_proof_only" || currentData.run.status === "complete" ? 4 : 3;
1352
+ var progress = Math.min(1, (counts.complete + counts.proof + counts.running * 0.62 + counts.blocked) / total);
1353
+ var pulse = getElement("rp-current-pulse");
1354
+ var label = getElement("rp-current-label");
1355
+ var step = getElement("rp-current-step");
1356
+ var meta = getElement("rp-meta");
1357
+ var fill = getElement("rp-progress").querySelector("span");
1358
+
1359
+ pulse.style.color = currentData.run.status === "failed" ? "var(--obs-red)" : "var(--obs-blue)";
1360
+ label.textContent = currentData.run.status === "contract_proof_only" ? "Proof snapshot" : RUN_PHASES[phaseIndex].label;
1361
+ step.textContent = "- step " + String(phaseIndex + 1) + "/" + String(RUN_PHASES.length);
1362
+ if (fill) fill.style.width = String(Math.round(progress * 100)) + "%";
1363
+
1364
+ meta.replaceChildren();
1365
+ appendMeta(meta, currentData.run.runId, true);
1366
+ appendMeta(meta, shortTime(currentData.run.createdAt), false);
1367
+ appendMeta(meta, currentData.run.mode, false);
1368
+ appendMeta(meta, currentData.run.packageName || "local project", false);
1369
+ appendMeta(meta, currentData.publicSafety.publishable ? "publishable" : "local evidence", false);
1370
+
1371
+ getElement("rp-chips").replaceChildren(
1372
+ chip("Live", counts.running, "var(--obs-blue)"),
1373
+ chip("Blocked", counts.blocked, "var(--obs-amber)"),
1374
+ chip("Error", counts.failed, "var(--obs-red)"),
1375
+ chip("Done", counts.complete, "var(--obs-green)"),
1376
+ chip("Proof", counts.proof, "var(--obs-green)")
1377
+ );
1378
+
1379
+ var stepper = getElement("rp-stepper");
1380
+ var toggle = getElement("rp-toggle");
1381
+ toggle.setAttribute("aria-expanded", stepperOpen ? "true" : "false");
1382
+ toggle.textContent = stepperOpen ? "Collapse" : "Phases";
1383
+ stepper.hidden = !stepperOpen;
1384
+ if (stepperOpen) {
1385
+ stepper.style.gridTemplateColumns = "repeat(" + RUN_PHASES.length + ", 1fr)";
1386
+ stepper.replaceChildren.apply(stepper, RUN_PHASES.map(function (phase, index) {
1387
+ var cell = document.createElement("div");
1388
+ var state = index < phaseIndex ? "done" : index === phaseIndex ? "active" : "pending";
1389
+ cell.className = "rp-stepper-cell";
1390
+ cell.dataset.state = state;
1391
+ var mark = document.createElement("div");
1392
+ mark.className = "rp-stepper-mark";
1393
+ mark.dataset.state = state;
1394
+ mark.append(document.createElement("span"));
1395
+ var lbl = document.createElement("span");
1396
+ lbl.className = "rp-stepper-label";
1397
+ lbl.textContent = phase.label;
1398
+ var desc = document.createElement("span");
1399
+ desc.className = "rp-stepper-desc";
1400
+ desc.textContent = phase.desc;
1401
+ cell.append(mark, lbl, desc);
1402
+ if (index < RUN_PHASES.length - 1) {
1403
+ var conn = document.createElement("div");
1404
+ conn.className = "rp-stepper-conn";
1405
+ cell.append(conn);
1406
+ }
1407
+ return cell;
1408
+ }));
1409
+ } else {
1410
+ stepper.replaceChildren();
1411
+ }
1412
+ }
1413
+
1414
+ function appendMeta(root, value, strong) {
1415
+ if (!value) return;
1416
+ if (root.childNodes.length > 0) root.append(document.createTextNode(" - "));
1417
+ if (strong) {
1418
+ var node = document.createElement("strong");
1419
+ node.textContent = value;
1420
+ root.append(node);
1421
+ } else {
1422
+ root.append(document.createTextNode(value));
1423
+ }
1424
+ }
1425
+
1426
+ function chip(label, count, color) {
1427
+ var node = document.createElement("span");
1428
+ node.className = "rp-chip";
1429
+ node.dataset.active = String(count > 0);
1430
+ node.dataset.dim = String(count === 0);
1431
+ node.style.color = color;
1432
+ var dot = document.createElement("span");
1433
+ dot.className = "rp-chip-dot";
1434
+ var lbl = document.createElement("span");
1435
+ lbl.className = "rp-chip-label";
1436
+ lbl.textContent = label;
1437
+ var cnt = document.createElement("span");
1438
+ cnt.className = "rp-chip-count";
1439
+ cnt.textContent = String(count).padStart(2, "0");
1440
+ node.append(dot, lbl, cnt);
1441
+ return node;
1442
+ }
1443
+
1444
+ function renderSubBar() {
1445
+ var counts = countStatuses(currentData.streams);
1446
+ var kindCounts = countKinds(currentData.streams);
1447
+ getElement("sub-mode").textContent = focusedId ? "Watch focus" : "Watch grid";
1448
+ getElement("sub-count").textContent = String(currentData.streams.length);
1449
+ getElement("sub-filters").replaceChildren(
1450
+ statusFilter("all", "All", currentData.streams.length, null),
1451
+ statusFilter("running", "Live", counts.running, "var(--obs-blue)"),
1452
+ statusFilter("blocked", "Blocked", counts.blocked + counts.failed, "var(--obs-amber)"),
1453
+ statusFilter("complete", "Done", counts.complete, "var(--obs-green)"),
1454
+ statusFilter("proof", "Proof", counts.proof, "var(--obs-green)")
1455
+ );
1456
+ getElement("sub-kind-filters").replaceChildren(
1457
+ kindFilter("all", "All", currentData.streams.length),
1458
+ kindFilter("ui", "UI", kindCounts.ui + kindCounts.browser),
1459
+ kindFilter("terminal", "CLI", kindCounts.terminal),
1460
+ kindFilter("tui", "TUI", kindCounts.tui),
1461
+ kindFilter("codex-ui", "Codex", kindCounts["codex-ui"])
1462
+ );
1463
+
1464
+ Array.prototype.forEach.call(document.querySelectorAll(".sub-density-btn"), function (button) {
1465
+ button.setAttribute("aria-pressed", String(Number(button.dataset.density) === density));
1466
+ });
1467
+ getElement("streams").dataset.density = String(density);
1468
+
1469
+ var mediaToggle = getElement("media-toggle");
1470
+ var liveAvailable = hasLiveStreams(currentData);
1471
+ mediaToggle.disabled = !liveAvailable;
1472
+ mediaToggle.setAttribute("aria-disabled", String(!liveAvailable));
1473
+ mediaToggle.textContent = !liveAvailable ? "Replay" : preferScreenshots ? "Screenshot" : "Live";
1474
+ mediaToggle.setAttribute("aria-pressed", String(preferScreenshots));
1475
+
1476
+ var gridMode = getElement("grid-mode");
1477
+ var focusMode = getElement("focus-mode");
1478
+ gridMode.hidden = Boolean(focusedId);
1479
+ gridMode.setAttribute("aria-pressed", String(!focusedId));
1480
+ focusMode.setAttribute("aria-pressed", String(Boolean(focusedId)));
1481
+ focusMode.textContent = focusedId ? "Focused" : "Focus";
1482
+
1483
+ var historyToggle = getElement("history-toggle");
1484
+ var historyDivider = getElement("history-divider");
1485
+ var hasHistory = Boolean(historyIndex && historyIndex.runs && historyIndex.runs.length);
1486
+ historyToggle.hidden = !hasHistory;
1487
+ historyDivider.hidden = !hasHistory;
1488
+ historyToggle.setAttribute("aria-expanded", String(historyOpen));
1489
+ }
1490
+
1491
+ function statusFilter(id, label, count, color) {
1492
+ var button = document.createElement("button");
1493
+ button.className = "sub-filter";
1494
+ button.type = "button";
1495
+ button.setAttribute("aria-pressed", String(activeStatus === id));
1496
+ button.dataset.filter = id;
1497
+ if (color) {
1498
+ button.style.color = color;
1499
+ var dot = document.createElement("span");
1500
+ dot.className = "sub-filter-dot";
1501
+ button.append(dot);
1502
+ }
1503
+ var text = document.createElement("span");
1504
+ text.textContent = label;
1505
+ text.style.color = activeStatus === id ? "var(--obs-fg-1)" : "var(--obs-fg-2)";
1506
+ var cnt = document.createElement("span");
1507
+ cnt.className = "sub-filter-count";
1508
+ cnt.textContent = String(count).padStart(2, "0");
1509
+ button.append(text, cnt);
1510
+ button.addEventListener("click", function () {
1511
+ activeStatus = id;
1512
+ renderSubBar();
1513
+ renderStreams();
1514
+ });
1515
+ return button;
1516
+ }
1517
+
1518
+ function kindFilter(id, label, count) {
1519
+ var button = document.createElement("button");
1520
+ button.className = "kind-filter";
1521
+ button.type = "button";
1522
+ button.setAttribute("aria-pressed", String(activeKind === id));
1523
+ var text = document.createElement("span");
1524
+ text.textContent = label;
1525
+ var cnt = document.createElement("span");
1526
+ cnt.className = "kind-filter-count";
1527
+ cnt.textContent = String(count).padStart(2, "0");
1528
+ button.append(text, cnt);
1529
+ button.addEventListener("click", function () {
1530
+ activeKind = id;
1531
+ renderSubBar();
1532
+ renderStreams();
1533
+ });
1534
+ return button;
1535
+ }
1536
+
1537
+ function renderStreams() {
1538
+ var root = getElement("streams");
1539
+ var inFocus = Boolean(focusedId);
1540
+ getElement("grid-shell").hidden = inFocus;
1541
+ getElement("focus").hidden = !inFocus;
1542
+ if (inFocus) return;
1543
+ var visible = visibleStreams();
1544
+ var idsKey = JSON.stringify(visible.map(function (stream) { return stream.id; }));
1545
+ if (root.dataset.idsKey !== idsKey) {
1546
+ root.dataset.idsKey = idsKey;
1547
+ root.replaceChildren.apply(root, visible.map(function (stream, index) {
1548
+ var tile = renderTile(stream, index);
1549
+ tile.style.left = "0px";
1550
+ tile.style.top = "0px";
1551
+ tile.style.width = "100%";
1552
+ return tile;
1553
+ }));
1554
+ } else {
1555
+ Array.prototype.forEach.call(root.children, function (child, index) {
1556
+ var fresh = renderTile(visible[index], index);
1557
+ child.replaceWith(fresh);
1558
+ });
1559
+ }
1560
+ layoutPackedGrid();
1561
+ }
1562
+
1563
+ function renderTile(stream, index) {
1564
+ var tile = document.createElement("article");
1565
+ tile.className = "tile";
1566
+ tile.dataset.streamId = stream.id;
1567
+ tile.dataset.mediaKey = streamMediaKey(stream);
1568
+ tile.dataset.selected = String(stream.id === focusedId);
1569
+ var aspect = streamAspect(stream);
1570
+ tile.dataset.aspect = aspect.kind;
1571
+ tile.dataset.aspectWidth = String(aspect.width);
1572
+ tile.dataset.aspectHeight = String(aspect.height);
1573
+ tile.title = stream.sim.personaId + " - " + stream.label;
1574
+ tile.tabIndex = 0;
1575
+ tile.setAttribute("role", "button");
1576
+ tile.setAttribute("aria-label", "Open stream " + String(index + 1).padStart(2, "0") + ": " + stream.label);
1577
+ tile.addEventListener("click", function () { focusStream(stream.id, true); });
1578
+ tile.addEventListener("keydown", function (event) {
1579
+ if (event.key === "Enter" || event.key === " ") {
1580
+ event.preventDefault();
1581
+ focusStream(stream.id, true);
1582
+ }
1583
+ });
1584
+ tile.append(renderTileHead(stream, index), renderTileStream(stream, false), renderTileCap(stream));
1585
+ return tile;
1586
+ }
1587
+
1588
+ function renderTileHead(stream, index) {
1589
+ var head = document.createElement("header");
1590
+ head.className = "tile-head";
1591
+ var idx = document.createElement("span");
1592
+ idx.className = "tile-idx";
1593
+ idx.textContent = String(index + 1).padStart(2, "0");
1594
+ var pip = document.createElement("span");
1595
+ pip.className = "pip";
1596
+ pip.dataset.status = stream.status || "unknown";
1597
+ var role = document.createElement("span");
1598
+ role.className = "tile-role";
1599
+ role.textContent = stream.kindLabel || stream.kind;
1600
+ var name = document.createElement("span");
1601
+ name.className = "tile-name";
1602
+ name.textContent = compactLabel(stream.sim.personaId || stream.label);
1603
+ var view = document.createElement("span");
1604
+ view.className = "tile-view";
1605
+ view.textContent = viewLabel(stream);
1606
+ head.append(idx, pip, role, name, view);
1607
+ return head;
1608
+ }
1609
+
1610
+ function renderTileStream(stream, inFocus) {
1611
+ var shell = document.createElement("div");
1612
+ shell.className = "tile-stream-shell";
1613
+ shell.dataset.focus = String(Boolean(inFocus));
1614
+ var aspect = streamAspect(stream);
1615
+ shell.style.setProperty("--stream-aspect", aspect.width + " / " + aspect.height);
1616
+ shell.dataset.streamWidth = String(aspect.width);
1617
+ shell.dataset.streamHeight = String(aspect.height);
1618
+ var surface = document.createElement("div");
1619
+ surface.className = "media-surface";
1620
+
1621
+ if (preferScreenshots && stream.ui && stream.ui.screenshotUrl) {
1622
+ var img = document.createElement("img");
1623
+ img.src = stream.ui.screenshotUrl;
1624
+ img.alt = "Screenshot for " + stream.id;
1625
+ surface.append(img);
1626
+ } else if ((stream.kind === "terminal" || stream.kind === "tui") && stream.terminal) {
1627
+ appendTerminal(surface, stream, inFocus);
1628
+ } else if ((stream.kind === "ui" || stream.kind === "browser") && stream.embed && stream.embed.url && !preferScreenshots) {
1629
+ var iframe = document.createElement("iframe");
1630
+ iframe.src = stream.embed.url;
1631
+ iframe.title = stream.label;
1632
+ iframe.loading = "lazy";
1633
+ surface.append(iframe);
1634
+ } else if (stream.kind === "codex-ui") {
1635
+ appendCodex(surface, stream);
1636
+ } else if (stream.kind === "ui" || stream.kind === "browser") {
1637
+ appendBrowser(surface, stream);
1638
+ } else {
1639
+ appendPlaceholder(surface, stream);
1640
+ }
1641
+
1642
+ shell.append(surface);
1643
+ return shell;
1644
+ }
1645
+
1646
+ function appendTerminal(surface, stream, inFocus) {
1647
+ var terminal = document.createElement("div");
1648
+ terminal.className = "terminal-surface";
1649
+ var bar = document.createElement("div");
1650
+ bar.className = "terminal-bar";
1651
+ var prompt = document.createElement("span");
1652
+ prompt.className = "terminal-prompt";
1653
+ prompt.textContent = "$";
1654
+ var title = document.createElement("span");
1655
+ title.className = "terminal-title";
1656
+ title.textContent = stream.terminal.title || stream.label;
1657
+ var status = document.createElement("span");
1658
+ status.className = "terminal-status";
1659
+ status.textContent = stream.statusLabel || stream.status;
1660
+ bar.append(prompt, title, status);
1661
+ var body = document.createElement("div");
1662
+ body.className = "terminal-body";
1663
+ var lines = String(stream.terminalPlain || stream.terminal.tail || "").split("\\n").filter(Boolean);
1664
+ if (lines.length === 0) lines = ["No terminal transcript recorded yet."];
1665
+ var limit = inFocus ? 120 : 36;
1666
+ lines.slice(-limit).forEach(function (line, index) {
1667
+ var row = document.createElement("div");
1668
+ row.className = "terminal-line";
1669
+ var prefix = document.createElement("span");
1670
+ prefix.className = "terminal-line-prefix";
1671
+ prefix.textContent = String(index + 1).padStart(2, "0");
1672
+ var text = document.createElement("span");
1673
+ text.className = "terminal-line-text";
1674
+ text.textContent = line;
1675
+ row.append(prefix, text);
1676
+ body.append(row);
1677
+ });
1678
+ terminal.append(bar, body);
1679
+ surface.append(terminal);
1680
+ }
1681
+
1682
+ function appendBrowser(surface, stream) {
1683
+ var outer = document.createElement("div");
1684
+ outer.className = "live-waiting-surface";
1685
+ var inner = document.createElement("div");
1686
+ inner.className = "live-waiting-inner";
1687
+ var spinner = document.createElement("div");
1688
+ spinner.className = "live-spinner";
1689
+ spinner.setAttribute("aria-hidden", "true");
1690
+ var title = document.createElement("div");
1691
+ title.className = "live-waiting-title";
1692
+ title.textContent = stream.status === "contract_proof_only" ? "Contract proof only" : "Waiting for live desktop";
1693
+ var url = document.createElement("div");
1694
+ url.className = "live-waiting-url";
1695
+ url.textContent = stream.ui && stream.ui.route ? stream.ui.route : stream.label;
1696
+ var status = document.createElement("div");
1697
+ status.className = "live-waiting-status";
1698
+ status.textContent = stream.sim.currentStep || stream.summary || stream.statusLabel || "Live surface not connected yet.";
1699
+ inner.append(spinner, title, url, status);
1700
+ outer.append(inner);
1701
+ surface.append(outer);
1702
+ }
1703
+
1704
+ function appendCodex(surface, stream) {
1705
+ var outer = document.createElement("div");
1706
+ outer.className = "synthetic-codex";
1707
+ var frame = document.createElement("div");
1708
+ frame.className = "codex-frame";
1709
+ var chrome = document.createElement("div");
1710
+ chrome.className = "codex-chrome";
1711
+ chrome.append(dot(), dot(), dot());
1712
+ var url = document.createElement("span");
1713
+ url.className = "codex-url";
1714
+ url.textContent = "codex.app-server/session";
1715
+ chrome.append(url);
1716
+ var body = document.createElement("div");
1717
+ body.className = "codex-body";
1718
+ var rail = document.createElement("div");
1719
+ rail.className = "codex-rail";
1720
+ rail.append(thread(), thread(), thread());
1721
+ var main = document.createElement("div");
1722
+ main.className = "codex-main";
1723
+ main.append(bubble("dark"), bubble(""), bubble(""), bubble("dark"));
1724
+ body.append(rail, main);
1725
+ frame.append(chrome, body);
1726
+ outer.append(frame);
1727
+ surface.append(outer);
1728
+ }
1729
+
1730
+ function appendPlaceholder(surface, stream) {
1731
+ var holder = document.createElement("div");
1732
+ holder.className = "placeholder-surface";
1733
+ var box = document.createElement("div");
1734
+ box.className = "placeholder-box";
1735
+ box.textContent = stream.summary || "Observer lane awaiting evidence.";
1736
+ holder.append(box);
1737
+ surface.append(holder);
1738
+ }
1739
+
1740
+ function renderTileCap(stream) {
1741
+ var cap = document.createElement("footer");
1742
+ cap.className = "tile-cap";
1743
+ cap.dataset.status = stream.status || "unknown";
1744
+ var eyebrow = document.createElement("span");
1745
+ eyebrow.className = "tile-cap-eyebrow";
1746
+ eyebrow.textContent = stream.kindLabel || stream.kind;
1747
+ var text = document.createElement("span");
1748
+ text.className = "tile-cap-text";
1749
+ text.textContent = stream.sim.currentStep || stream.statusLabel || stream.status;
1750
+ var bar = document.createElement("div");
1751
+ bar.className = "tile-cap-bar";
1752
+ var fill = document.createElement("span");
1753
+ fill.style.width = String(Math.max(8, Math.min(100, Number(stream.sim.progress || 0)))) + "%";
1754
+ bar.append(fill);
1755
+ cap.append(eyebrow, text, bar);
1756
+ return cap;
1757
+ }
1758
+
1759
+ function renderFocus() {
1760
+ var focus = getElement("focus");
1761
+ document.body.classList.toggle("focused", Boolean(focusedId));
1762
+ if (!focusedId) {
1763
+ focus.replaceChildren();
1764
+ return;
1765
+ }
1766
+ var stream = currentData.streams.find(function (item) { return item.id === focusedId; });
1767
+ if (!stream) {
1768
+ focusedId = null;
1769
+ focus.replaceChildren();
1770
+ return;
1771
+ }
1772
+ var rail = document.createElement("aside");
1773
+ rail.className = "focus-rail";
1774
+ currentData.streams.forEach(function (candidate, index) {
1775
+ var item = document.createElement("button");
1776
+ item.className = "focus-rail-item";
1777
+ item.type = "button";
1778
+ item.dataset.selected = String(candidate.id === focusedId);
1779
+ item.addEventListener("click", function () { focusStream(candidate.id, true); });
1780
+ var idx = document.createElement("span");
1781
+ idx.className = "focus-rail-idx";
1782
+ idx.textContent = String(index + 1).padStart(2, "0");
1783
+ var pip = document.createElement("span");
1784
+ pip.className = "pip";
1785
+ pip.dataset.status = candidate.status || "unknown";
1786
+ item.append(idx, pip);
1787
+ rail.append(item);
1788
+ });
1789
+
1790
+ var stage = document.createElement("section");
1791
+ stage.className = "focus-stage";
1792
+ var toolbar = document.createElement("header");
1793
+ toolbar.className = "focus-toolbar";
1794
+ var back = document.createElement("button");
1795
+ back.className = "focus-back";
1796
+ back.type = "button";
1797
+ back.textContent = "Back to grid";
1798
+ back.addEventListener("click", exitFocus);
1799
+ var id = document.createElement("span");
1800
+ id.className = "focus-id";
1801
+ id.textContent = stream.id;
1802
+ var persona = document.createElement("span");
1803
+ persona.className = "focus-persona";
1804
+ persona.textContent = stream.sim.personaId + " / " + stream.kindLabel;
1805
+ var badge = document.createElement("span");
1806
+ badge.className = "focus-status-badge";
1807
+ badge.dataset.status = stream.status || "unknown";
1808
+ var badgePip = document.createElement("span");
1809
+ badgePip.className = "pip";
1810
+ badgePip.dataset.status = stream.status || "unknown";
1811
+ var badgeText = document.createElement("span");
1812
+ badgeText.textContent = stream.statusLabel || stream.status;
1813
+ badge.append(badgePip, badgeText);
1814
+ var stats = document.createElement("span");
1815
+ stats.className = "focus-stats";
1816
+ stats.textContent = viewLabel(stream) + " - events " + stream.timeline.length;
1817
+ toolbar.append(back, id, persona, badge, stats);
1818
+ var area = document.createElement("div");
1819
+ area.className = "focus-stage-area";
1820
+ area.append(renderTileStream(stream, true));
1821
+ stage.append(toolbar, area);
1822
+
1823
+ var side = renderFocusSide(stream);
1824
+ focus.replaceChildren(rail, stage, side);
1825
+ fitFocusMedia();
1826
+ }
1827
+
1828
+ function renderFocusSide(stream) {
1829
+ var side = document.createElement("aside");
1830
+ side.className = "focus-side";
1831
+ var context = document.createElement("div");
1832
+ context.className = "focus-side-context";
1833
+ var head = document.createElement("div");
1834
+ head.className = "focus-side-head";
1835
+ var eyebrow = document.createElement("span");
1836
+ eyebrow.className = "obs-eyebrow";
1837
+ eyebrow.textContent = "Persona";
1838
+ var h2 = document.createElement("h2");
1839
+ h2.textContent = currentData.run.persona.name;
1840
+ var goal = document.createElement("div");
1841
+ goal.className = "focus-side-goal";
1842
+ var goalEyebrow = document.createElement("span");
1843
+ goalEyebrow.className = "obs-eyebrow";
1844
+ goalEyebrow.textContent = "Goal";
1845
+ var goalText = document.createElement("div");
1846
+ goalText.className = "focus-side-goal-text";
1847
+ goalText.textContent = currentData.run.scenario.goal;
1848
+ goal.append(goalEyebrow, goalText);
1849
+ head.append(eyebrow, h2, goal);
1850
+ var think = document.createElement("div");
1851
+ think.className = "focus-side-thinking";
1852
+ var thinkRow = document.createElement("div");
1853
+ thinkRow.className = "focus-side-thinking-row";
1854
+ var dotNode = document.createElement("span");
1855
+ dotNode.className = "pulse-dot";
1856
+ var thinkEyebrow = document.createElement("span");
1857
+ thinkEyebrow.className = "obs-eyebrow";
1858
+ thinkEyebrow.textContent = "Now";
1859
+ thinkRow.append(dotNode, thinkEyebrow);
1860
+ var thinkText = document.createElement("div");
1861
+ thinkText.className = "focus-side-thinking-text";
1862
+ thinkText.textContent = stream.sim.currentStep || stream.summary || stream.statusLabel;
1863
+ think.append(thinkRow, thinkText);
1864
+ context.append(head, think);
1865
+
1866
+ var tabs = document.createElement("div");
1867
+ tabs.className = "focus-tabs";
1868
+ tabs.setAttribute("role", "tablist");
1869
+ var tabBody = document.createElement("div");
1870
+ tabBody.className = "focus-tabbody";
1871
+ var tabDefs = [
1872
+ { id: "events", label: "Events", count: stream.timeline.length },
1873
+ { id: "actions", label: "Trace", count: stream.timeline.length },
1874
+ { id: "artifacts", label: "Files", count: stream.artifacts.length },
1875
+ { id: "logs", label: "Logs", count: stream.terminalPlain ? stream.terminalPlain.split("\\n").length : 0 }
1876
+ ];
1877
+ tabDefs.forEach(function (tab) {
1878
+ var button = document.createElement("button");
1879
+ button.className = "focus-tab";
1880
+ button.type = "button";
1881
+ button.setAttribute("role", "tab");
1882
+ button.setAttribute("aria-selected", String(activeFocusTab === tab.id));
1883
+ button.textContent = tab.label + " ";
1884
+ var badge = document.createElement("span");
1885
+ badge.className = "focus-tab-badge";
1886
+ badge.textContent = String(tab.count);
1887
+ button.append(badge);
1888
+ button.addEventListener("click", function () {
1889
+ activeFocusTab = tab.id;
1890
+ renderFocus();
1891
+ });
1892
+ tabs.append(button);
1893
+ });
1894
+ fillTabBody(tabBody, stream);
1895
+ side.append(context, tabs, tabBody);
1896
+ return side;
1897
+ }
1898
+
1899
+ function fillTabBody(tabBody, stream) {
1900
+ if (activeFocusTab === "artifacts") {
1901
+ tabBody.replaceChildren.apply(tabBody, stream.artifacts.map(function (artifact) {
1902
+ var row = document.createElement("div");
1903
+ row.className = "artifact-row";
1904
+ var icon = document.createElement("span");
1905
+ icon.className = "event-row-icon";
1906
+ icon.textContent = "file";
1907
+ var text = document.createElement("div");
1908
+ text.className = "artifact-row-text";
1909
+ var link = document.createElement("a");
1910
+ link.href = artifact.path;
1911
+ link.textContent = artifact.label;
1912
+ text.append(link);
1913
+ var meta = document.createElement("div");
1914
+ meta.className = "artifact-row-meta";
1915
+ meta.textContent = artifact.kind + " - " + artifact.path;
1916
+ text.append(meta);
1917
+ row.append(icon, text);
1918
+ return row;
1919
+ }));
1920
+ return;
1921
+ }
1922
+ if (activeFocusTab === "logs") {
1923
+ var surface = document.createElement("div");
1924
+ surface.className = "terminal-surface";
1925
+ var body = document.createElement("div");
1926
+ body.className = "terminal-body";
1927
+ String(stream.terminalPlain || "No log text recorded.").split("\\n").filter(Boolean).forEach(function (line, index) {
1928
+ var row = document.createElement("div");
1929
+ row.className = "terminal-line";
1930
+ var prefix = document.createElement("span");
1931
+ prefix.className = "terminal-line-prefix";
1932
+ prefix.textContent = String(index + 1).padStart(2, "0");
1933
+ var text = document.createElement("span");
1934
+ text.className = "terminal-line-text";
1935
+ text.textContent = line;
1936
+ row.append(prefix, text);
1937
+ body.append(row);
1938
+ });
1939
+ surface.append(body);
1940
+ tabBody.replaceChildren(surface);
1941
+ return;
1942
+ }
1943
+ var rows = stream.timeline.length ? stream.timeline : currentData.events.slice(-12);
1944
+ tabBody.replaceChildren.apply(tabBody, rows.map(function (event) { return eventRow(event); }));
1945
+ }
1946
+
1947
+ function eventRow(event) {
1948
+ var row = document.createElement("div");
1949
+ row.className = "event-row";
1950
+ row.dataset.kind = event.level || event.type || "info";
1951
+ var icon = document.createElement("span");
1952
+ icon.className = "event-row-icon";
1953
+ icon.textContent = event.level || "info";
1954
+ var body = document.createElement("div");
1955
+ var text = document.createElement("div");
1956
+ text.className = "event-row-text";
1957
+ text.textContent = event.message;
1958
+ var meta = document.createElement("div");
1959
+ meta.className = "event-row-meta";
1960
+ meta.textContent = compact([shortTime(event.at), event.type, event.streamId]).join(" - ");
1961
+ body.append(text, meta);
1962
+ row.append(icon, body);
1963
+ return row;
1964
+ }
1965
+
1966
+ function renderHistoryPanel() {
1967
+ var panel = getElement("history-panel");
1968
+ var current = getElement("history-current");
1969
+ var list = getElement("history-list");
1970
+ var hasHistory = Boolean(historyIndex && historyIndex.runs && historyIndex.runs.length);
1971
+ panel.hidden = !historyOpen || !hasHistory;
1972
+ if (!hasHistory) {
1973
+ current.replaceChildren();
1974
+ list.replaceChildren();
1975
+ return;
1976
+ }
1977
+ current.textContent = "Current " + currentData.run.runId + " - Latest " + (historyIndex.latestRunId || "none");
1978
+ list.replaceChildren.apply(list, historyIndex.runs.slice(0, 80).map(function (run) {
1979
+ var link = document.createElement("a");
1980
+ link.className = "history-run";
1981
+ link.href = run.href;
1982
+ link.dataset.active = String(run.runId === currentData.run.runId);
1983
+ var id = document.createElement("span");
1984
+ id.className = "history-run-id";
1985
+ id.textContent = run.runId;
1986
+ var status = document.createElement("span");
1987
+ status.className = "history-run-status";
1988
+ var pip = document.createElement("span");
1989
+ pip.className = "pip";
1990
+ pip.dataset.status = run.status || "unknown";
1991
+ var statusText = document.createElement("span");
1992
+ statusText.textContent = run.status || "unknown";
1993
+ status.append(pip, statusText);
1994
+ var meta = document.createElement("span");
1995
+ meta.className = "history-run-meta";
1996
+ meta.textContent = compact([run.mode, run.createdAt ? shortTime(run.createdAt) : null]).join(" - ");
1997
+ var counts = document.createElement("span");
1998
+ counts.className = "history-run-counts";
1999
+ counts.textContent = String(run.streamCount || 0) + " streams";
2000
+ link.append(id, status, meta, counts);
2001
+ return link;
2002
+ }));
2003
+ }
2004
+
2005
+ function layoutPackedGrid() {
2006
+ var shell = getElement("grid-shell");
2007
+ var root = getElement("streams");
2008
+ var tiles = Array.prototype.slice.call(root.querySelectorAll(".tile"));
2009
+ if (tiles.length === 0) {
2010
+ root.style.height = "0px";
2011
+ return;
2012
+ }
2013
+ var styles = getComputedStyle(shell);
2014
+ var padX = parseFloat(styles.paddingLeft || "16") + parseFloat(styles.paddingRight || "16");
2015
+ var innerW = Math.max(0, shell.clientWidth - padX);
2016
+ var gap = 8;
2017
+ var headerH = 22;
2018
+ var captionH = 22;
2019
+ var rowStreamH = GRID_SCALE_STREAM_HEIGHT[density] || GRID_SCALE_STREAM_HEIGHT[4];
2020
+ var x = 0;
2021
+ var y = 0;
2022
+ var rowH = 0;
2023
+ tiles.forEach(function (tile) {
2024
+ var aspectW = Number(tile.dataset.aspectWidth) || 16;
2025
+ var aspectH = Number(tile.dataset.aspectHeight) || 9;
2026
+ var ratio = aspectW / aspectH || 16 / 9;
2027
+ var streamH = rowStreamH;
2028
+ var tileW = Math.round(streamH * ratio);
2029
+ if (tileW > innerW) {
2030
+ tileW = Math.round(innerW);
2031
+ streamH = tileW / ratio;
2032
+ }
2033
+ var tileH = Math.round(streamH + headerH + captionH);
2034
+ if (x > 0 && x + tileW > innerW) {
2035
+ x = 0;
2036
+ y = y + rowH + gap;
2037
+ rowH = 0;
2038
+ }
2039
+ tile.style.left = String(x) + "px";
2040
+ tile.style.top = String(y) + "px";
2041
+ tile.style.width = String(tileW) + "px";
2042
+ tile.style.height = String(tileH) + "px";
2043
+ x = x + tileW + gap;
2044
+ rowH = Math.max(rowH, tileH);
2045
+ });
2046
+ root.style.height = String(y + rowH) + "px";
2047
+ }
2048
+
2049
+ function fitFocusMedia() {
2050
+ requestAnimationFrame(function () {
2051
+ Array.prototype.forEach.call(document.querySelectorAll(".focus-stage-area .tile-stream-shell"), function (shell) {
2052
+ var area = shell.parentElement;
2053
+ if (!area) return;
2054
+ var width = Number(shell.dataset.streamWidth) || 16;
2055
+ var height = Number(shell.dataset.streamHeight) || 9;
2056
+ var rect = area.getBoundingClientRect();
2057
+ if (rect.width <= 0 || rect.height <= 0) return;
2058
+ var scale = Math.min(rect.width / width, rect.height / height);
2059
+ shell.style.width = String(Math.max(1, Math.floor(width * scale))) + "px";
2060
+ shell.style.height = String(Math.max(1, Math.floor(height * scale))) + "px";
2061
+ });
2062
+ });
2063
+ }
2064
+
2065
+ function visibleStreams() {
2066
+ return currentData.streams.filter(function (stream) {
2067
+ if (activeKind !== "all") {
2068
+ if (activeKind === "ui" && stream.kind !== "ui" && stream.kind !== "browser") return false;
2069
+ if (activeKind !== "ui" && stream.kind !== activeKind) return false;
2070
+ }
2071
+ if (activeStatus === "all") return true;
2072
+ if (activeStatus === "running") return stream.status === "running" || stream.status === "preparing";
2073
+ if (activeStatus === "blocked") return stream.status === "blocked" || stream.status === "failed";
2074
+ if (activeStatus === "complete") return stream.status === "complete";
2075
+ if (activeStatus === "proof") return stream.status === "contract_proof_only";
2076
+ return true;
2077
+ });
2078
+ }
2079
+
2080
+ function countStatuses(streams) {
2081
+ return streams.reduce(function (acc, stream) {
2082
+ if (stream.status === "running" || stream.status === "preparing") acc.running += 1;
2083
+ else if (stream.status === "blocked") acc.blocked += 1;
2084
+ else if (stream.status === "failed") acc.failed += 1;
2085
+ else if (stream.status === "complete") acc.complete += 1;
2086
+ else if (stream.status === "contract_proof_only") acc.proof += 1;
2087
+ else acc.queued += 1;
2088
+ return acc;
2089
+ }, { running: 0, blocked: 0, failed: 0, complete: 0, proof: 0, queued: 0 });
2090
+ }
2091
+
2092
+ function countKinds(streams) {
2093
+ return streams.reduce(function (acc, stream) {
2094
+ acc[stream.kind] = (acc[stream.kind] || 0) + 1;
2095
+ return acc;
2096
+ }, { ui: 0, browser: 0, terminal: 0, tui: 0, "codex-ui": 0, artifact: 0, summary: 0 });
2097
+ }
2098
+
2099
+ function streamAspect(stream) {
2100
+ if (stream.kind === "terminal" || stream.kind === "tui") return { kind: "terminal", width: 16, height: 10 };
2101
+ var vp = stream.viewport || {};
2102
+ var width = Number(vp.width) || (stream.kind === "codex-ui" ? 16 : 16);
2103
+ var height = Number(vp.height) || (stream.kind === "codex-ui" ? 10 : 9);
2104
+ return { kind: height > width ? "mobile" : "desktop", width: width, height: height };
2105
+ }
2106
+
2107
+ function streamMediaKey(stream) {
2108
+ return [stream.kind, stream.status, stream.updatedAt, preferScreenshots ? "screenshot" : "live"].join(":");
2109
+ }
2110
+
2111
+ function viewLabel(stream) {
2112
+ var vp = stream.viewport || {};
2113
+ if (stream.kind === "terminal") return "CLI";
2114
+ if (stream.kind === "tui") return "TUI";
2115
+ if (stream.kind === "codex-ui") return "CODEX";
2116
+ if (vp.width && vp.height) return Number(vp.height) > Number(vp.width) ? "MOB" : "DSK";
2117
+ return "SIM";
2118
+ }
2119
+
2120
+ function preferredScreenshotMode(data) {
2121
+ return !hasLiveStreams(data) && data.streams.some(function (stream) { return Boolean(stream.ui && stream.ui.screenshotUrl); });
2122
+ }
2123
+
2124
+ function hasLiveStreams(data) {
2125
+ return data.streams.some(function (stream) {
2126
+ return Boolean(stream.embed && stream.embed.url) || stream.transport === "sse" || stream.transport === "app-server" || stream.transport === "pty";
2127
+ });
2128
+ }
2129
+
2130
+ function focusStream(id, show) {
2131
+ focusedId = show ? knownFocusedId(id) : null;
2132
+ writeFocusLocation(focusedId);
2133
+ render();
2134
+ }
2135
+
2136
+ function exitFocus() {
2137
+ focusStream(null, false);
2138
+ }
2139
+
2140
+ function focusedIdFromLocation() {
2141
+ var match = (window.location.hash || "").match(/^#focus=(.+)$/);
2142
+ if (!match) return null;
2143
+ try { return decodeURIComponent(match[1]); } catch (_error) { return null; }
2144
+ }
2145
+
2146
+ function writeFocusLocation(id) {
2147
+ var url = new URL(window.location.href);
2148
+ url.hash = id ? "focus=" + encodeURIComponent(id) : "";
2149
+ if (url.href === window.location.href) return;
2150
+ window.history.replaceState({ focusedId: id }, "", url);
2151
+ }
2152
+
2153
+ function syncFocusFromLocation() {
2154
+ var next = knownFocusedId(focusedIdFromLocation());
2155
+ if (next === focusedId) return;
2156
+ focusedId = next;
2157
+ render();
2158
+ }
2159
+
2160
+ function knownFocusedId(id) {
2161
+ if (id && currentData.streams.some(function (stream) { return stream.id === id; })) return id;
2162
+ return currentData.streams.length ? currentData.streams[0].id : null;
2163
+ }
2164
+
2165
+ async function refresh() {
2166
+ if (location.protocol === "file:") return;
2167
+ try {
2168
+ var response = await fetch(DATA_FILE, { cache: "no-store" });
2169
+ if (response.ok) {
2170
+ currentData = await response.json();
2171
+ render();
2172
+ }
2173
+ } catch (_error) {}
2174
+ }
2175
+
2176
+ async function refreshHistoryIndex() {
2177
+ if (location.protocol === "file:") return;
2178
+ try {
2179
+ var response = await fetch("/_mimetic/history.json", { cache: "no-store" });
2180
+ if (!response.ok) throw new Error("history " + response.status);
2181
+ historyIndex = await response.json();
2182
+ renderSubBar();
2183
+ renderHistoryPanel();
2184
+ } catch (_error) {
2185
+ historyIndex = null;
2186
+ historyOpen = false;
2187
+ renderSubBar();
2188
+ renderHistoryPanel();
2189
+ }
2190
+ }
2191
+
2192
+ function readPref(key, fallback) {
2193
+ try {
2194
+ var raw = window.localStorage.getItem("mimetic-observer:" + key);
2195
+ return raw == null ? fallback : JSON.parse(raw);
2196
+ } catch (_error) {
2197
+ return fallback;
2198
+ }
2199
+ }
2200
+
2201
+ function writePref(key, value) {
2202
+ try { window.localStorage.setItem("mimetic-observer:" + key, JSON.stringify(value)); } catch (_error) {}
2203
+ }
2204
+
2205
+ function shortTime(value) {
2206
+ if (!value) return "";
2207
+ var date = new Date(value);
2208
+ if (Number.isNaN(date.getTime())) return value;
2209
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
2210
+ }
2211
+
2212
+ function compact(values) {
2213
+ return values.filter(function (value) { return value !== null && value !== undefined && value !== ""; });
2214
+ }
2215
+
2216
+ function compactLabel(value) {
2217
+ return String(value || "sim").replace(/^builtin-/, "").replace(/-/g, " ");
2218
+ }
2219
+
2220
+ function dot() {
2221
+ var node = document.createElement("span");
2222
+ node.className = "chrome-dot";
2223
+ return node;
2224
+ }
2225
+
2226
+ function thread() {
2227
+ var node = document.createElement("div");
2228
+ node.className = "codex-thread";
2229
+ return node;
2230
+ }
2231
+
2232
+ function bubble(extra) {
2233
+ var node = document.createElement("div");
2234
+ node.className = "codex-bubble " + extra;
2235
+ return node;
2236
+ }
2237
+
2238
+ Array.prototype.forEach.call(document.querySelectorAll(".sub-density-btn"), function (button) {
2239
+ button.addEventListener("click", function () {
2240
+ density = Number(button.dataset.density);
2241
+ writePref("density", density);
2242
+ renderSubBar();
2243
+ getElement("streams").dataset.density = String(density);
2244
+ layoutPackedGrid();
2245
+ });
2246
+ });
2247
+
2248
+ getElement("rp-toggle").addEventListener("click", function () {
2249
+ stepperOpen = !(getElement("rp-toggle").getAttribute("aria-expanded") === "true");
2250
+ writePref("stepperOpen", stepperOpen);
2251
+ renderProgress();
2252
+ });
2253
+
2254
+ getElement("media-toggle").addEventListener("click", function () {
2255
+ if (!hasLiveStreams(currentData)) return;
2256
+ mediaPreferenceTouched = true;
2257
+ preferScreenshots = !preferScreenshots;
2258
+ render();
2259
+ });
2260
+
2261
+ getElement("focus-mode").addEventListener("click", function () {
2262
+ focusStream(focusedId || (currentData.streams[0] && currentData.streams[0].id), true);
2263
+ });
2264
+
2265
+ getElement("grid-mode").addEventListener("click", exitFocus);
2266
+
2267
+ getElement("history-toggle").addEventListener("click", function () {
2268
+ historyOpen = !historyOpen;
2269
+ writePref("historyOpen", historyOpen);
2270
+ renderSubBar();
2271
+ renderHistoryPanel();
2272
+ });
2273
+
2274
+ getElement("history-close").addEventListener("click", function () {
2275
+ historyOpen = false;
2276
+ writePref("historyOpen", historyOpen);
2277
+ renderSubBar();
2278
+ renderHistoryPanel();
2279
+ });
2280
+
2281
+ document.addEventListener("keydown", function (event) {
2282
+ if (event.key === "Escape" && historyOpen) {
2283
+ historyOpen = false;
2284
+ writePref("historyOpen", historyOpen);
2285
+ renderSubBar();
2286
+ renderHistoryPanel();
2287
+ return;
2288
+ }
2289
+ if (event.key === "Escape" && focusedId) exitFocus();
2290
+ if (focusedId && (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
2291
+ var list = currentData.streams;
2292
+ var index = list.findIndex(function (stream) { return stream.id === focusedId; });
2293
+ if (index >= 0) {
2294
+ var next = event.key === "ArrowRight" ? (index + 1) % list.length : (index - 1 + list.length) % list.length;
2295
+ focusStream(list[next].id, true);
2296
+ }
2297
+ }
2298
+ });
2299
+
2300
+ window.addEventListener("popstate", syncFocusFromLocation);
2301
+ window.addEventListener("hashchange", syncFocusFromLocation);
2302
+ window.addEventListener("resize", function () {
2303
+ fitFocusMedia();
2304
+ layoutPackedGrid();
2305
+ });
2306
+
2307
+ if (typeof ResizeObserver !== "undefined") {
2308
+ new ResizeObserver(function () { layoutPackedGrid(); }).observe(getElement("grid-shell"));
2309
+ }
2310
+
2311
+ render();
2312
+ refresh().then(function () {
2313
+ if (location.protocol !== "file:") {
2314
+ refreshTimer = setInterval(refresh, 2500);
2315
+ void refreshHistoryIndex();
2316
+ historyTimer = setInterval(refreshHistoryIndex, 30000);
2317
+ }
2318
+ });
2319
+ }());
2320
+ `;
2321
+ }
2322
+ //# sourceMappingURL=observer-assets.js.map