@tea-agent/loop-agent 0.5.0 → 0.7.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 (136) hide show
  1. package/AGENTS.md +142 -142
  2. package/CHANGELOG.md +132 -98
  3. package/README.md +195 -195
  4. package/bin/agent-worker.js +22 -22
  5. package/bin/loop-agent.js +21 -21
  6. package/dist/application/dag/args.js +9 -1
  7. package/dist/application/dag/run-dag.js +16 -2
  8. package/dist/cli/command-definitions.js +22 -4
  9. package/dist/cli/help.js +3 -2
  10. package/dist/cli/program.js +7 -5
  11. package/dist/commands/import-prd.js +76 -0
  12. package/dist/commands/init.js +467 -457
  13. package/dist/commands/instructions.js +90 -58
  14. package/dist/commands/loop-benchmark.js +11 -11
  15. package/dist/commands/pi-reuse-benchmark.js +16 -16
  16. package/dist/executors/cursor-executor.js +1 -1
  17. package/dist/executors/dag-pi-executor.js +1 -0
  18. package/dist/executors/pi-sdk-executor.js +63 -1
  19. package/dist/shared/preview.js +39 -0
  20. package/dist/task/config-types.js +3 -0
  21. package/dist/task/runtime.js +27 -27
  22. package/dist/task/source-references.js +221 -0
  23. package/dist/worker/cli.js +62 -1
  24. package/dist/worker/loop-agent/loop-agent-client.js +97 -5
  25. package/dist/worker/materialize/harness-task-materializer.js +166 -5
  26. package/dist/worker/observability/event-store.js +82 -0
  27. package/dist/worker/observability/events.js +79 -0
  28. package/dist/worker/observability/progress-composite.js +33 -0
  29. package/dist/worker/observability/read-model.js +1013 -0
  30. package/dist/worker/observability/snapshot-store.js +43 -0
  31. package/dist/worker/observability/types.js +1 -0
  32. package/dist/worker/observe/paths.js +64 -0
  33. package/dist/worker/observe/routes.js +423 -0
  34. package/dist/worker/observe/server.js +61 -0
  35. package/dist/worker/observe/static/app.js +1419 -0
  36. package/dist/worker/observe/static/index.html +63 -0
  37. package/dist/worker/observe/static/styles.css +613 -0
  38. package/dist/worker/pool/failure-routing.js +41 -6
  39. package/dist/worker/pool/run-store.js +50 -0
  40. package/dist/worker/progress-reporter.js +0 -18
  41. package/dist/worker/run-task/run-task.js +327 -92
  42. package/dist/worker/runner/run-ready.js +112 -4
  43. package/dist/worker/task-spec/schema.js +2 -1
  44. package/dist/workflows/dag/canvas-observer.js +275 -275
  45. package/dist/workflows/dag/event-observer.js +132 -0
  46. package/dist/workflows/dag/init-hybrid.js +182 -21
  47. package/dist/workflows/dag/observer-compose.js +52 -0
  48. package/docs/README.md +75 -72
  49. package/docs/agent-dag-recovery-playbook.md +184 -184
  50. package/docs/agent-dag-runner.md +42 -42
  51. package/docs/architecture/runtime-boundaries.md +162 -147
  52. package/docs/cursor-executor-usage.md +25 -25
  53. package/docs/decisions/README.md +3 -3
  54. package/docs/design/README.md +49 -36
  55. package/docs/development-principles.md +73 -73
  56. package/docs/dynamic-workflow-dag-engine-roadmap.md +1749 -1749
  57. package/docs/exec-plans/README.md +6 -6
  58. package/docs/exec-plans/active/README.md +12 -7
  59. package/docs/exec-plans/completed/README.md +32 -19
  60. package/docs/feature-workflow.md +186 -186
  61. package/docs/harness-methodology-debugging.md +153 -153
  62. package/docs/harness-methodology-tdd.md +130 -130
  63. package/docs/harness-methodology-verification.md +27 -27
  64. package/docs/init-surface.manifest.json +208 -199
  65. package/docs/loop-agent-harness.md +55 -42
  66. package/docs/production-readiness.md +96 -96
  67. package/docs/progress/README.md +3 -3
  68. package/docs/reports/README.md +9 -5
  69. package/docs/skills/README.md +6 -6
  70. package/docs/skills/vetted-skill-registry.md +26 -26
  71. package/docs/templates/adr.md +60 -60
  72. package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
  73. package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
  74. package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -117
  75. package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
  76. package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
  77. package/docs/templates/agent-dag-report.schema.json +454 -454
  78. package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
  79. package/docs/templates/agent-dag.base.json +195 -195
  80. package/docs/templates/agent-dag.final-verification.json +190 -190
  81. package/docs/templates/agent-dag.schema.json +316 -316
  82. package/docs/templates/agent-dag.supervised-implementation.json +500 -500
  83. package/docs/templates/exec-plan.md +64 -64
  84. package/docs/templates/feature-spec.md +53 -53
  85. package/docs/templates/hybrid-dag.json +193 -193
  86. package/docs/templates/init-evolution-review.md +33 -33
  87. package/docs/templates/interactive-ui-round2-experiment.md +66 -0
  88. package/docs/templates/production-readiness-checklist.md +57 -57
  89. package/docs/templates/progress-log.md +17 -17
  90. package/docs/templates/project-start-checklist.md +9 -9
  91. package/docs/templates/qa-report.md +48 -48
  92. package/docs/templates/sprint-contract.md +29 -29
  93. package/docs/templates/worker-dogfood-evidence.md +52 -0
  94. package/docs/templates/worker-dogfood-setup.md +48 -0
  95. package/docs/verification-matrix.md +41 -41
  96. package/examples/decision-gate-agent-dag.json +123 -123
  97. package/examples/example-dag.json +51 -51
  98. package/examples/hybrid-loop-agent-dag.json +194 -194
  99. package/harness.json +70 -69
  100. package/package.json +66 -66
  101. package/skills/ai-engineering-context/SKILL.md +48 -48
  102. package/skills/code-review-core/SKILL.md +20 -20
  103. package/skills/codebase-scout/SKILL.md +19 -19
  104. package/skills/init-capability-evolution/SKILL.md +69 -69
  105. package/skills/loop-agent/SKILL.md +149 -147
  106. package/skills/loop-agent/references/README.md +67 -67
  107. package/skills/loop-agent/references/command-reference.md +412 -403
  108. package/skills/loop-agent/references/harness-policy.md +263 -259
  109. package/skills/loop-agent/references/hybrid-dag.md +216 -216
  110. package/skills/loop-agent/references/learned/README.md +21 -21
  111. package/skills/loop-agent/references/long-running-loop.md +59 -59
  112. package/skills/loop-agent/references/model-routing.md +36 -36
  113. package/skills/loop-agent/references/multi-worktree.md +54 -54
  114. package/skills/loop-agent/references/one-shot-runs.md +85 -85
  115. package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -169
  116. package/skills/loop-agent/references/pi-prompt.md +23 -23
  117. package/skills/loop-agent/references/pi-subagent-assisted-mode.md +81 -81
  118. package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -44
  119. package/skills/loop-agent/references/task-workflow.md +89 -84
  120. package/skills/loop-agent/references/verification-and-failure-handling.md +128 -128
  121. package/skills/requesting-code-review/SKILL.md +101 -101
  122. package/skills/requesting-code-review/code-reviewer.md +168 -168
  123. package/skills/systematic-debugging/CREATION-LOG.md +119 -119
  124. package/skills/systematic-debugging/SKILL.md +296 -296
  125. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
  126. package/skills/systematic-debugging/condition-based-waiting.md +115 -115
  127. package/skills/systematic-debugging/defense-in-depth.md +122 -122
  128. package/skills/systematic-debugging/find-polluter.sh +63 -63
  129. package/skills/systematic-debugging/root-cause-tracing.md +169 -169
  130. package/skills/systematic-debugging/test-academic.md +14 -14
  131. package/skills/systematic-debugging/test-pressure-1.md +58 -58
  132. package/skills/systematic-debugging/test-pressure-2.md +68 -68
  133. package/skills/systematic-debugging/test-pressure-3.md +69 -69
  134. package/skills/test-driven-development/SKILL.md +20 -20
  135. package/skills/verification-before-completion/SKILL.md +154 -154
  136. package/skills/webapp-testing/SKILL.md +19 -19
@@ -0,0 +1,63 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>loop-agent 可观测</title>
7
+ <link rel="stylesheet" href="/styles.css">
8
+ </head>
9
+ <body>
10
+ <div id="app">
11
+ <header class="site-header">
12
+ <a href="#/" class="logo">loop-agent 可观测</a>
13
+ <nav class="top-nav">
14
+ <a href="#/" class="nav-link">总览</a>
15
+ <a href="#/dags" class="nav-link">DAG</a>
16
+ <a href="#/failures" class="nav-link">失败箱</a>
17
+ </nav>
18
+ <span id="header-refresh" class="header-refresh"></span>
19
+ <nav id="breadcrumb" class="breadcrumb"></nav>
20
+ </header>
21
+
22
+ <section data-view="dashboard" id="view-dashboard">
23
+ <h2>总览</h2>
24
+ <div id="dashboard-kpi" class="kpi-grid panel"></div>
25
+ <div id="dashboard-active-dags" class="panel"></div>
26
+ <div id="dashboard-dags" class="panel"></div>
27
+ <div id="dashboard-batches" class="panel"></div>
28
+ </section>
29
+
30
+ <section data-view="batch" id="view-batch" hidden>
31
+ <h2>批次详情</h2>
32
+ <div id="batch-meta" class="panel"></div>
33
+ <div id="batch-tasks" class="panel"></div>
34
+ </section>
35
+
36
+ <section data-view="run" id="view-run" hidden>
37
+ <h2>运行详情</h2>
38
+ <div id="run-meta" class="panel"></div>
39
+ <div id="run-dag-progress" class="panel"></div>
40
+ <div id="run-steps" class="panel"></div>
41
+ <div id="run-command" class="panel"></div>
42
+ <div id="run-output" class="panel"></div>
43
+ <div id="run-artifacts" class="panel"></div>
44
+ </section>
45
+
46
+ <section data-view="dag" id="view-dag" hidden>
47
+ <h2>DAG 详情</h2>
48
+ <div id="dag-meta" class="panel"></div>
49
+ <div id="dag-ranks" class="panel"></div>
50
+ <div id="dag-nodes" class="panel"></div>
51
+ <div id="dag-timeline" class="panel"></div>
52
+ <div id="dag-output" class="panel"></div>
53
+ </section>
54
+
55
+ <section data-view="failures" id="view-failures" hidden>
56
+ <h2>失败箱</h2>
57
+ <div id="failures-empty" class="panel" hidden>暂无失败或阻塞的任务。</div>
58
+ <div id="failures-list" class="panel"></div>
59
+ </section>
60
+ </div>
61
+ <script type="module" src="/app.js"></script>
62
+ </body>
63
+ </html>
@@ -0,0 +1,613 @@
1
+ :root {
2
+ --bg: #0d1117;
3
+ --surface: #161b22;
4
+ --border: #30363d;
5
+ --text: #c9d1d9;
6
+ --muted: #8b949e;
7
+ --link: #58a6ff;
8
+ --green: #3fb950;
9
+ --red: #f85149;
10
+ --yellow: #d29922;
11
+ --blue: #58a6ff;
12
+ --gray-red: #8b3a3a;
13
+ }
14
+
15
+ * {
16
+ box-sizing: border-box;
17
+ }
18
+
19
+ body {
20
+ margin: 0;
21
+ font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
22
+ font-size: 13px;
23
+ line-height: 1.5;
24
+ background: var(--bg);
25
+ color: var(--text);
26
+ }
27
+
28
+ #app {
29
+ max-width: 1200px;
30
+ margin: 0 auto;
31
+ padding: 1rem 1.5rem 2rem;
32
+ }
33
+
34
+ .site-header {
35
+ display: flex;
36
+ flex-wrap: wrap;
37
+ align-items: center;
38
+ gap: 1rem 1.5rem;
39
+ margin-bottom: 1.5rem;
40
+ padding-bottom: 0.75rem;
41
+ border-bottom: 1px solid var(--border);
42
+ }
43
+
44
+ .logo {
45
+ color: var(--text);
46
+ text-decoration: none;
47
+ font-weight: 600;
48
+ }
49
+
50
+ .logo:hover {
51
+ color: var(--link);
52
+ }
53
+
54
+ .top-nav {
55
+ display: flex;
56
+ gap: 1rem;
57
+ }
58
+
59
+ .nav-link {
60
+ color: var(--muted);
61
+ text-decoration: none;
62
+ font-size: 12px;
63
+ }
64
+
65
+ .nav-link:hover {
66
+ color: var(--link);
67
+ }
68
+
69
+ .header-refresh {
70
+ margin-left: auto;
71
+ color: var(--muted);
72
+ font-size: 11px;
73
+ }
74
+
75
+ .breadcrumb {
76
+ flex-basis: 100%;
77
+ color: var(--muted);
78
+ font-size: 12px;
79
+ }
80
+
81
+ .breadcrumb a {
82
+ color: var(--link);
83
+ text-decoration: none;
84
+ }
85
+
86
+ .breadcrumb a:hover {
87
+ text-decoration: underline;
88
+ }
89
+
90
+ h2 {
91
+ margin: 0 0 0.75rem;
92
+ font-size: 1.1rem;
93
+ font-weight: 600;
94
+ }
95
+
96
+ h3,
97
+ .section-heading {
98
+ margin: 0 0 0.5rem;
99
+ font-size: 0.95rem;
100
+ font-weight: 600;
101
+ }
102
+
103
+ .panel {
104
+ background: var(--surface);
105
+ border: 1px solid var(--border);
106
+ border-radius: 6px;
107
+ padding: 0.75rem 1rem;
108
+ margin-bottom: 1rem;
109
+ }
110
+
111
+ .kpi-grid {
112
+ display: grid;
113
+ grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
114
+ gap: 0.75rem;
115
+ padding: 0.75rem;
116
+ }
117
+
118
+ .kpi-card {
119
+ background: var(--bg);
120
+ border: 1px solid var(--border);
121
+ border-radius: 6px;
122
+ padding: 0.6rem 0.75rem;
123
+ text-align: center;
124
+ }
125
+
126
+ .kpi-card.kpi-highlight {
127
+ border-color: var(--yellow);
128
+ background: rgba(210, 153, 34, 0.08);
129
+ }
130
+
131
+ .kpi-card.kpi-danger {
132
+ border-color: var(--red);
133
+ }
134
+
135
+ .kpi-label {
136
+ color: var(--muted);
137
+ font-size: 10px;
138
+ text-transform: uppercase;
139
+ margin-bottom: 0.25rem;
140
+ }
141
+
142
+ .kpi-value {
143
+ font-size: 1.4rem;
144
+ font-weight: 700;
145
+ }
146
+
147
+ .active-dag-list {
148
+ display: flex;
149
+ flex-direction: column;
150
+ gap: 0.75rem;
151
+ }
152
+
153
+ .active-dag-card {
154
+ background: var(--bg);
155
+ border: 1px solid var(--border);
156
+ border-radius: 6px;
157
+ padding: 0.75rem 1rem;
158
+ }
159
+
160
+ .active-dag-card-running {
161
+ border-color: var(--yellow);
162
+ box-shadow: 0 0 0 1px rgba(210, 153, 34, 0.25);
163
+ animation: pulse-border 2s ease-in-out infinite;
164
+ }
165
+
166
+ @keyframes pulse-border {
167
+ 0%,
168
+ 100% {
169
+ border-color: var(--yellow);
170
+ }
171
+ 50% {
172
+ border-color: rgba(210, 153, 34, 0.5);
173
+ }
174
+ }
175
+
176
+ .active-dag-header {
177
+ display: flex;
178
+ align-items: center;
179
+ gap: 0.75rem;
180
+ margin-bottom: 0.35rem;
181
+ }
182
+
183
+ .active-dag-title {
184
+ font-weight: 600;
185
+ flex: 1;
186
+ }
187
+
188
+ .active-dag-meta {
189
+ display: flex;
190
+ flex-direction: column;
191
+ gap: 0.2rem;
192
+ color: var(--muted);
193
+ font-size: 12px;
194
+ margin-bottom: 0.5rem;
195
+ }
196
+
197
+ .active-dag-link {
198
+ color: var(--link);
199
+ text-decoration: none;
200
+ font-size: 12px;
201
+ }
202
+
203
+ .active-dag-link:hover {
204
+ text-decoration: underline;
205
+ }
206
+
207
+ .dashboard-footer {
208
+ margin-top: 0.75rem;
209
+ color: var(--muted);
210
+ font-size: 12px;
211
+ }
212
+
213
+ .meta-grid {
214
+ display: grid;
215
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
216
+ gap: 0.5rem 1.5rem;
217
+ }
218
+
219
+ .meta-item dt {
220
+ color: var(--muted);
221
+ font-size: 11px;
222
+ text-transform: uppercase;
223
+ margin: 0;
224
+ }
225
+
226
+ .meta-item dd {
227
+ margin: 0.15rem 0 0;
228
+ }
229
+
230
+ table {
231
+ width: 100%;
232
+ border-collapse: collapse;
233
+ }
234
+
235
+ th,
236
+ td {
237
+ text-align: left;
238
+ padding: 0.4rem 0.6rem;
239
+ border-bottom: 1px solid var(--border);
240
+ }
241
+
242
+ th {
243
+ color: var(--muted);
244
+ font-size: 11px;
245
+ text-transform: uppercase;
246
+ font-weight: 600;
247
+ }
248
+
249
+ tbody tr:hover {
250
+ background: rgba(255, 255, 255, 0.03);
251
+ }
252
+
253
+ tbody tr.clickable {
254
+ cursor: pointer;
255
+ }
256
+
257
+ tbody tr.dag-node-selected {
258
+ background: rgba(88, 166, 255, 0.12);
259
+ }
260
+
261
+ .timeline-node-label {
262
+ color: var(--muted);
263
+ font-size: 12px;
264
+ margin: 0 0 0.5rem;
265
+ }
266
+
267
+ .process-timeline-scroll {
268
+ max-height: 320px;
269
+ overflow-y: auto;
270
+ border: 1px solid var(--border);
271
+ border-radius: 4px;
272
+ background: var(--bg);
273
+ }
274
+
275
+ .process-timeline {
276
+ list-style: none;
277
+ margin: 0;
278
+ padding: 0.25rem 0;
279
+ }
280
+
281
+ .process-timeline-item {
282
+ display: flex;
283
+ gap: 0.75rem;
284
+ padding: 0.35rem 0.75rem;
285
+ border-bottom: 1px solid var(--border);
286
+ font-size: 12px;
287
+ }
288
+
289
+ .process-timeline-item:last-child {
290
+ border-bottom: none;
291
+ }
292
+
293
+ .process-timeline-time {
294
+ flex: 0 0 4.5rem;
295
+ color: var(--muted);
296
+ font-variant-numeric: tabular-nums;
297
+ }
298
+
299
+ .process-timeline-label {
300
+ flex: 1;
301
+ word-break: break-word;
302
+ }
303
+
304
+ tbody tr.active-task {
305
+ background: rgba(210, 153, 34, 0.12);
306
+ }
307
+
308
+ .badge {
309
+ display: inline-block;
310
+ padding: 0.1rem 0.45rem;
311
+ border-radius: 4px;
312
+ font-size: 11px;
313
+ font-weight: 600;
314
+ }
315
+
316
+ .badge-succeeded,
317
+ .badge-finished,
318
+ .badge-completed,
319
+ .badge-done {
320
+ background: rgba(63, 185, 80, 0.2);
321
+ color: var(--green);
322
+ }
323
+
324
+ .badge-failed,
325
+ .badge-error {
326
+ background: rgba(248, 81, 73, 0.2);
327
+ color: var(--red);
328
+ }
329
+
330
+ .badge-partial-failed {
331
+ background: rgba(248, 81, 73, 0.15);
332
+ color: #ff9a8b;
333
+ border: 1px solid rgba(248, 81, 73, 0.35);
334
+ }
335
+
336
+ .badge-running,
337
+ .badge-started {
338
+ background: rgba(210, 153, 34, 0.2);
339
+ color: var(--yellow);
340
+ }
341
+
342
+ .badge-skipped {
343
+ background: rgba(139, 148, 158, 0.15);
344
+ color: var(--muted);
345
+ }
346
+
347
+ .badge-stale {
348
+ background: rgba(139, 58, 58, 0.3);
349
+ color: #e06c75;
350
+ }
351
+
352
+ .badge-reused {
353
+ background: rgba(88, 166, 255, 0.2);
354
+ color: var(--blue);
355
+ }
356
+
357
+ .badge-pending,
358
+ .badge-blocked,
359
+ .badge-unknown,
360
+ .badge-queued {
361
+ background: rgba(139, 148, 158, 0.15);
362
+ color: var(--muted);
363
+ }
364
+
365
+ .liveness-active {
366
+ background: rgba(63, 185, 80, 0.2);
367
+ color: var(--green);
368
+ }
369
+
370
+ .liveness-quiet {
371
+ background: rgba(210, 153, 34, 0.2);
372
+ color: var(--yellow);
373
+ }
374
+
375
+ .liveness-stale {
376
+ background: rgba(139, 58, 58, 0.3);
377
+ color: #e06c75;
378
+ }
379
+
380
+ .liveness-timeout-risk {
381
+ background: rgba(248, 81, 73, 0.25);
382
+ color: var(--red);
383
+ }
384
+
385
+ .rank-lanes {
386
+ display: flex;
387
+ flex-direction: column;
388
+ gap: 0.75rem;
389
+ }
390
+
391
+ .rank-lane {
392
+ border-left: 3px solid var(--border);
393
+ padding-left: 0.75rem;
394
+ }
395
+
396
+ .rank-lane-label {
397
+ color: var(--muted);
398
+ font-size: 11px;
399
+ font-weight: 600;
400
+ margin-bottom: 0.35rem;
401
+ }
402
+
403
+ .rank-lane-nodes {
404
+ display: flex;
405
+ flex-wrap: wrap;
406
+ gap: 0.5rem;
407
+ }
408
+
409
+ .rank-node-chip {
410
+ display: inline-flex;
411
+ align-items: center;
412
+ gap: 0.35rem;
413
+ background: var(--bg);
414
+ border: 1px solid var(--border);
415
+ border-radius: 4px;
416
+ padding: 0.25rem 0.5rem;
417
+ font-size: 12px;
418
+ }
419
+
420
+ .rank-node-active {
421
+ border-color: var(--yellow);
422
+ background: rgba(210, 153, 34, 0.12);
423
+ }
424
+
425
+ .rank-node-error {
426
+ border-color: var(--red);
427
+ background: rgba(248, 81, 73, 0.1);
428
+ }
429
+
430
+ .rank-node-id {
431
+ font-weight: 600;
432
+ }
433
+
434
+ .rank-node-dur {
435
+ color: var(--muted);
436
+ font-size: 10px;
437
+ }
438
+
439
+ .step-timeline {
440
+ list-style: none;
441
+ margin: 0;
442
+ padding: 0;
443
+ }
444
+
445
+ .step-timeline li {
446
+ display: flex;
447
+ align-items: center;
448
+ gap: 0.75rem;
449
+ padding: 0.35rem 0;
450
+ border-bottom: 1px solid var(--border);
451
+ }
452
+
453
+ .step-timeline li:last-child {
454
+ border-bottom: none;
455
+ }
456
+
457
+ .step-marker {
458
+ width: 1.5rem;
459
+ text-align: center;
460
+ font-weight: 700;
461
+ }
462
+
463
+ .step-marker.succeeded {
464
+ color: var(--green);
465
+ }
466
+
467
+ .step-marker.running {
468
+ color: var(--yellow);
469
+ }
470
+
471
+ .step-marker.pending {
472
+ color: var(--muted);
473
+ }
474
+
475
+ .step-marker.failed {
476
+ color: var(--red);
477
+ }
478
+
479
+ .step-name {
480
+ flex: 1;
481
+ }
482
+
483
+ .step-duration {
484
+ color: var(--muted);
485
+ font-size: 11px;
486
+ }
487
+
488
+ .output-block {
489
+ background: var(--bg);
490
+ border: 1px solid var(--border);
491
+ border-radius: 4px;
492
+ padding: 0.5rem 0.75rem;
493
+ white-space: pre-wrap;
494
+ word-break: break-all;
495
+ max-height: 240px;
496
+ overflow-y: auto;
497
+ font-size: 12px;
498
+ }
499
+
500
+ .output-preview {
501
+ margin: 0.5rem 0;
502
+ }
503
+
504
+ .output-preview summary {
505
+ cursor: pointer;
506
+ color: var(--link);
507
+ font-size: 12px;
508
+ margin-bottom: 0.25rem;
509
+ }
510
+
511
+ .error-preview summary {
512
+ color: var(--red);
513
+ }
514
+
515
+ .artifact-list {
516
+ list-style: none;
517
+ margin: 0;
518
+ padding: 0;
519
+ }
520
+
521
+ .artifact-list li {
522
+ padding: 0.25rem 0;
523
+ }
524
+
525
+ .artifact-list a {
526
+ color: var(--link);
527
+ text-decoration: none;
528
+ }
529
+
530
+ .artifact-list a:hover {
531
+ text-decoration: underline;
532
+ }
533
+
534
+ .empty {
535
+ color: var(--muted);
536
+ font-style: italic;
537
+ }
538
+
539
+ .link {
540
+ color: var(--link);
541
+ text-decoration: none;
542
+ }
543
+
544
+ .link:hover {
545
+ text-decoration: underline;
546
+ }
547
+
548
+ [hidden] {
549
+ display: none !important;
550
+ }
551
+
552
+ .dag-active-node {
553
+ background: rgba(210, 153, 34, 0.18);
554
+ }
555
+
556
+ .dag-error-node {
557
+ background: rgba(248, 81, 73, 0.12);
558
+ }
559
+
560
+ tbody tr.dag-active-node:hover {
561
+ background: rgba(210, 153, 34, 0.25);
562
+ }
563
+
564
+ tbody tr.dag-error-node:hover {
565
+ background: rgba(248, 81, 73, 0.18);
566
+ }
567
+
568
+ .dag-output-node {
569
+ margin: 0.5rem 0 0.25rem;
570
+ font-size: 12px;
571
+ color: var(--muted);
572
+ }
573
+
574
+ .step-link {
575
+ margin-left: 0.5rem;
576
+ color: var(--link);
577
+ text-decoration: none;
578
+ font-size: 11px;
579
+ }
580
+
581
+ .step-link:hover {
582
+ text-decoration: underline;
583
+ }
584
+
585
+ .inbox-link,
586
+ .artifact-link {
587
+ color: var(--link);
588
+ text-decoration: none;
589
+ font-size: 11px;
590
+ }
591
+
592
+ .inbox-link:hover,
593
+ .artifact-link:hover {
594
+ text-decoration: underline;
595
+ }
596
+
597
+ .artifact-links {
598
+ display: inline-flex;
599
+ flex-wrap: wrap;
600
+ gap: 6px;
601
+ }
602
+
603
+ .artifact-links .muted {
604
+ color: var(--muted);
605
+ }
606
+
607
+ #failures-list .row-failed {
608
+ border-left: 3px solid var(--red, #e06c75);
609
+ }
610
+
611
+ #failures-list .row-blocked {
612
+ border-left: 3px solid var(--yellow, #d19a66);
613
+ }