@tea-agent/loop-agent 0.25.5 → 0.26.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 (173) hide show
  1. package/AGENTS.md +2 -1
  2. package/CHANGELOG.md +1020 -986
  3. package/bin/loop-agent.js +21 -21
  4. package/dist/commands/cursor-prompt.js +6 -6
  5. package/dist/commands/init.js +68 -129
  6. package/dist/commands/loop-benchmark.js +11 -11
  7. package/dist/commands/pi-reuse-benchmark.js +16 -16
  8. package/dist/executors/dag-pi-executor.js +26 -20
  9. package/dist/executors/model-routing.js +34 -18
  10. package/dist/executors/shell-executor.js +1 -1
  11. package/dist/governance/manifest-types.js +33 -5
  12. package/dist/sidecars/cursor-prompt/executor.js +1 -1
  13. package/dist/task/task-demand-routing.js +3 -1
  14. package/dist/worker/console/chat/model-resolver.js +15 -3
  15. package/dist/worker/observe/static/constants.js +3 -2
  16. package/dist/worker/observe/static/copy.js +67 -67
  17. package/dist/worker/observe/static/dag-layout.d.ts +31 -31
  18. package/dist/worker/observe/static/dag-layout.js +83 -83
  19. package/dist/worker/observe/static/dag-model.js +1 -0
  20. package/dist/worker/observe/static/dom.js +220 -220
  21. package/dist/worker/observe/static/relations.js +133 -133
  22. package/dist/worker/observe/static/router.js +93 -93
  23. package/dist/worker/observe/static/run-processing.js +148 -148
  24. package/dist/worker/observe/static/styles.css +182 -42
  25. package/dist/worker/observe/static/views/batch.js +227 -227
  26. package/dist/worker/observe/static/views/dag-graph.js +172 -172
  27. package/dist/worker/observe/static/views/failures.js +143 -143
  28. package/dist/worker/observe/static/views/feature.js +492 -492
  29. package/dist/worker/observe/static/views/run.js +453 -453
  30. package/dist/worker/observe/static/views/shell.js +7 -7
  31. package/dist/worker/observe/static/views/timeline.js +163 -163
  32. package/dist/workflows/dag/backend-test-case-coverage-analysis.js +362 -45
  33. package/dist/workflows/dag/backend-test-case-manifest.js +20 -0
  34. package/dist/workflows/dag/backend-test-markdown-workflow.js +17 -0
  35. package/dist/workflows/dag/canvas-observer.js +275 -275
  36. package/dist/workflows/dag/init-hybrid.js +18 -15
  37. package/dist/workflows/dag/lifecycle.js +40 -30
  38. package/dist/workflows/dag/node-execution.js +13 -0
  39. package/dist/workflows/dag/types.js +59 -19
  40. package/docs/init-surface.manifest.json +3 -1
  41. package/docs/skills/README.md +7 -7
  42. package/docs/templates/README.md +1 -0
  43. package/docs/templates/adr.md +60 -60
  44. package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
  45. package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
  46. package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
  47. package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
  48. package/docs/templates/agent-dag-report.schema.json +473 -473
  49. package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
  50. package/docs/templates/backend-test-dag.json +9 -9
  51. package/docs/templates/backend-test-result.schema.json +99 -99
  52. package/docs/templates/feature-spec.md +53 -53
  53. package/docs/templates/frontend-design-contract.md +42 -42
  54. package/docs/templates/frontend-eval/fixtures/failures/01-type-build-error.md +17 -17
  55. package/docs/templates/frontend-eval/fixtures/failures/02-unit-component-test-fail.md +16 -16
  56. package/docs/templates/frontend-eval/fixtures/failures/03-fixture-schema-drift.md +16 -16
  57. package/docs/templates/frontend-eval/fixtures/failures/04-missing-loading-empty-error-state.md +16 -16
  58. package/docs/templates/frontend-eval/fixtures/failures/05-forbidden-write-writeset-expansion.md +16 -16
  59. package/docs/templates/frontend-eval/fixtures/failures/06-unapproved-dependency-add.md +16 -16
  60. package/docs/templates/frontend-eval/fixtures/failures/07-mock-production-on.md +21 -21
  61. package/docs/templates/frontend-eval/fixtures/functional/01-simple-component-style.md +29 -29
  62. package/docs/templates/frontend-eval/fixtures/functional/02-form-validation.md +28 -28
  63. package/docs/templates/frontend-eval/fixtures/functional/03-list-detail-page.md +28 -28
  64. package/docs/templates/frontend-eval/fixtures/functional/04-api-mock.md +29 -29
  65. package/docs/templates/frontend-eval/fixtures/functional/05-permission-auth-gated-ui.md +27 -27
  66. package/docs/templates/frontend-eval/fixtures/functional/06-ssr-server-client-boundary.md +28 -28
  67. package/docs/templates/frontend-eval/fixtures/functional/07-shared-public-component-api.md +28 -28
  68. package/docs/templates/frontend-eval/fixtures/functional/08-pure-local-no-remote.md +27 -27
  69. package/docs/templates/frontend-eval/metrics.md +138 -138
  70. package/docs/templates/frontend-eval/smoke-targets.md +53 -53
  71. package/docs/templates/frontend-task-constraints.md +35 -35
  72. package/docs/templates/frontend-task-requirement.md +70 -70
  73. package/docs/templates/harness.schema.json +29 -7
  74. package/docs/templates/init-evolution-review.md +35 -35
  75. package/docs/templates/init-managed-agents.md +137 -0
  76. package/docs/templates/interactive-ui-round2-experiment.md +66 -66
  77. package/docs/templates/knowledge-graph-bootstrap-dag.json +118 -118
  78. package/docs/templates/knowledge-sync-dag.json +178 -178
  79. package/docs/templates/knowledge-sync-draft.schema.json +71 -71
  80. package/docs/templates/product-line/closeout.yaml +9 -9
  81. package/docs/templates/product-line/design.md +13 -13
  82. package/docs/templates/product-line/links.md +10 -10
  83. package/docs/templates/product-line/requirement.md +17 -17
  84. package/docs/templates/product-line/test-plan.md +7 -7
  85. package/docs/templates/production-readiness-checklist.md +57 -57
  86. package/docs/templates/project-start-checklist.md +9 -9
  87. package/docs/templates/qa-report.md +48 -48
  88. package/docs/templates/sprint-contract.md +29 -29
  89. package/docs/templates/worker-dogfood-evidence.md +80 -80
  90. package/docs/templates/worker-dogfood-setup.md +68 -68
  91. package/harness.json +1 -2
  92. package/package.json +1 -1
  93. package/scripts/kb-bootstrap-init-skeleton.sh +0 -0
  94. package/scripts/kb-graph-incremental-prepare.mjs +386 -386
  95. package/scripts/kb-graph-materialize.mjs +105 -105
  96. package/scripts/kb-graph-promote.mjs +164 -164
  97. package/scripts/kb-query.mjs +554 -554
  98. package/skills/ai-engineering-context/SKILL.md +48 -48
  99. package/skills/analyze-product-dependencies/SKILL.md +67 -67
  100. package/skills/analyze-product-dependencies/agents/openai.yaml +4 -4
  101. package/skills/analyze-product-dependencies/references/api-documentation-schema.md +30 -30
  102. package/skills/analyze-product-dependencies/references/dependency-analysis-schema.md +28 -28
  103. package/skills/analyze-product-dependencies/references/example.md +76 -76
  104. package/skills/analyze-product-dependencies/references/forward-test-cases.md +35 -35
  105. package/skills/analyze-product-dependencies/references/input-contract.md +11 -11
  106. package/skills/analyze-product-dependencies/references/scouting-rules.md +61 -61
  107. package/skills/analyze-product-dependencies/scripts/test-validators.mjs +267 -267
  108. package/skills/analyze-product-dependencies/scripts/validate-api-documentation.mjs +101 -101
  109. package/skills/analyze-product-dependencies/scripts/validate-dependency-analysis.mjs +142 -142
  110. package/skills/analyze-product-dependencies/scripts/validate-product-requirement-input.mjs +76 -76
  111. package/skills/analyze-product-dependencies/scripts/validation-helpers.mjs +146 -146
  112. package/skills/analyze-product-requirements/SKILL.md +90 -90
  113. package/skills/analyze-product-requirements/agents/openai.yaml +4 -4
  114. package/skills/analyze-product-requirements/references/acceptance-criteria.md +91 -91
  115. package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +56 -56
  116. package/skills/analyze-product-requirements/references/example.md +86 -86
  117. package/skills/analyze-product-requirements/references/forward-test-cases.md +66 -66
  118. package/skills/analyze-product-requirements/references/product-analysis-schema.md +32 -32
  119. package/skills/analyze-product-requirements/references/product-requirement-schema.md +33 -33
  120. package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +35 -35
  121. package/skills/analyze-product-requirements/scripts/test-validators.mjs +193 -193
  122. package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +69 -69
  123. package/skills/analyze-product-requirements/scripts/validate-product-requirement.mjs +97 -97
  124. package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +98 -98
  125. package/skills/analyze-product-requirements/scripts/validation-helpers.mjs +156 -156
  126. package/skills/browser-tools/browser-content.js +103 -103
  127. package/skills/browser-tools/browser-cookies.js +35 -35
  128. package/skills/browser-tools/browser-eval.js +53 -53
  129. package/skills/browser-tools/browser-hn-scraper.js +108 -108
  130. package/skills/browser-tools/browser-nav.js +44 -44
  131. package/skills/browser-tools/browser-pick.js +162 -162
  132. package/skills/browser-tools/browser-screenshot.js +34 -34
  133. package/skills/browser-tools/browser-start.js +86 -86
  134. package/skills/browser-tools/package-lock.json +2556 -2556
  135. package/skills/browser-tools/package.json +19 -19
  136. package/skills/code-review-core/SKILL.md +20 -20
  137. package/skills/codebase-scout/SKILL.md +19 -19
  138. package/skills/grill-me/SKILL.md +10 -10
  139. package/skills/loop-agent/references/README.md +67 -67
  140. package/skills/loop-agent/references/command-reference.md +5 -4
  141. package/skills/loop-agent/references/docs-converge.md +126 -126
  142. package/skills/loop-agent/references/hybrid-dag.md +2 -2
  143. package/skills/loop-agent/references/learned/README.md +21 -21
  144. package/skills/loop-agent/references/long-running-loop.md +57 -57
  145. package/skills/loop-agent/references/model-routing.md +2 -0
  146. package/skills/loop-agent/references/one-shot-runs.md +85 -85
  147. package/skills/loop-agent/references/pi-prompt.md +23 -23
  148. package/skills/loop-agent/references/pi-subagent-assisted-mode.md +84 -84
  149. package/skills/playwright-cli/SKILL.md +420 -420
  150. package/skills/playwright-cli/references/element-attributes.md +23 -23
  151. package/skills/playwright-cli/references/playwright-tests.md +39 -39
  152. package/skills/playwright-cli/references/request-mocking.md +87 -87
  153. package/skills/playwright-cli/references/running-code.md +241 -241
  154. package/skills/playwright-cli/references/session-management.md +225 -225
  155. package/skills/playwright-cli/references/storage-state.md +275 -275
  156. package/skills/playwright-cli/references/test-generation.md +433 -433
  157. package/skills/playwright-cli/references/tracing.md +139 -139
  158. package/skills/playwright-cli/references/video-recording.md +143 -143
  159. package/skills/requesting-code-review/SKILL.md +101 -101
  160. package/skills/requesting-code-review/code-reviewer.md +168 -168
  161. package/skills/systematic-debugging/CREATION-LOG.md +119 -119
  162. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
  163. package/skills/systematic-debugging/condition-based-waiting.md +115 -115
  164. package/skills/systematic-debugging/defense-in-depth.md +122 -122
  165. package/skills/systematic-debugging/find-polluter.sh +63 -63
  166. package/skills/systematic-debugging/root-cause-tracing.md +169 -169
  167. package/skills/systematic-debugging/test-academic.md +14 -14
  168. package/skills/systematic-debugging/test-pressure-1.md +58 -58
  169. package/skills/systematic-debugging/test-pressure-2.md +68 -68
  170. package/skills/systematic-debugging/test-pressure-3.md +69 -69
  171. package/skills/using-git-worktrees/SKILL.md +215 -215
  172. package/skills/verification-before-completion/SKILL.md +154 -154
  173. package/skills/webapp-testing/SKILL.md +19 -19
@@ -1,148 +1,148 @@
1
- /** Run step/command/artifact processing and task history rows. */
2
- import {
3
- STEP_LABELS,
4
- ARTIFACT_LABELS,
5
- STEP_ORDER,
6
- ARTIFACT_KEYS,
7
- } from "./constants.js";
8
- import { badge } from "./format.js";
9
- import { navigate } from "./router.js";
10
-
11
- export function stepDisplayLabel(label) {
12
- return STEP_LABELS[label] ?? label;
13
- }
14
-
15
- export function buildStepStates(events) {
16
- const states = new Map();
17
- for (const ev of events) {
18
- if (ev.type === "step.started") {
19
- states.set(ev.label, { status: "running", startedAt: ev.at });
20
- } else if (ev.type === "step.finished") {
21
- states.set(ev.label, {
22
- status: ev.status === "failed" ? "failed" : "succeeded",
23
- durationMs: ev.durationMs,
24
- });
25
- }
26
- }
27
-
28
- const ordered = [...STEP_ORDER];
29
- for (const label of states.keys()) {
30
- if (!ordered.includes(label)) ordered.push(label);
31
- }
32
-
33
- return ordered.map((label) => {
34
- const state = states.get(label);
35
- return {
36
- label,
37
- display: stepDisplayLabel(label),
38
- status: state?.status ?? "pending",
39
- durationMs: state?.durationMs,
40
- };
41
- });
42
- }
43
-
44
- export function stepMarker(status) {
45
- switch (status) {
46
- case "succeeded":
47
- return "✓";
48
- case "running":
49
- return "●";
50
- case "failed":
51
- return "✗";
52
- default:
53
- return "○";
54
- }
55
- }
56
-
57
- export function getCurrentCommand(events) {
58
- const active = new Map();
59
- for (const ev of events) {
60
- if (ev.type === "command.started") {
61
- active.set(ev.label, ev);
62
- } else if (ev.type === "command.finished") {
63
- active.delete(ev.label);
64
- }
65
- }
66
- let latest = null;
67
- for (const cmd of active.values()) {
68
- if (!latest || cmd.at > latest.at) latest = cmd;
69
- }
70
- if (latest?.at) {
71
- const elapsed = Date.now() - Date.parse(latest.at);
72
- latest = { ...latest, elapsedMs: Number.isFinite(elapsed) ? elapsed : 0 };
73
- }
74
- return latest;
75
- }
76
-
77
- export function getOutputTail(events, commandLabel) {
78
- if (!commandLabel) return "";
79
- const chunks = [];
80
- for (const ev of events) {
81
- if (
82
- ev.type === "command.output" &&
83
- ev.label === commandLabel &&
84
- ev.outputPreview
85
- ) {
86
- chunks.push(ev.outputPreview);
87
- }
88
- }
89
- return chunks.join("");
90
- }
91
-
92
- export function collectArtifacts(task, events) {
93
- const arts = new Map();
94
- const add = (label, artifactPath) => {
95
- if (artifactPath && !arts.has(label)) arts.set(label, artifactPath);
96
- };
97
-
98
- if (task?.artifactRefs) {
99
- for (const key of ARTIFACT_KEYS) {
100
- add(ARTIFACT_LABELS[key] ?? key, task.artifactRefs[key]);
101
- }
102
- }
103
-
104
- for (const ev of events) {
105
- if (!ev.artifactRefs) continue;
106
- for (const [key, artifactPath] of Object.entries(ev.artifactRefs)) {
107
- add(ARTIFACT_LABELS[key] ?? key, artifactPath);
108
- }
109
- }
110
-
111
- return arts;
112
- }
113
-
114
- export function findBatchRunIdForTask(snapshot, task) {
115
- if (!snapshot || !task) return null;
116
- const workerRunId = task.workerRunId;
117
- if (!workerRunId) return null;
118
- for (const batch of snapshot.batches ?? []) {
119
- for (const t of batch.tasks ?? []) {
120
- if (t.workerRunId === workerRunId) return batch.batchRunId;
121
- }
122
- }
123
- return null;
124
- }
125
-
126
- export function taskRunHistoryRow(run) {
127
- let runLink = run.workerRunId;
128
- if (run.workerRunId) {
129
- const a = document.createElement("a");
130
- a.href = `#/run/${encodeURIComponent(run.workerRunId)}`;
131
- a.textContent = run.workerRunId;
132
- a.addEventListener("click", (e) => {
133
- e.preventDefault();
134
- navigate(`#/run/${encodeURIComponent(run.workerRunId)}`);
135
- });
136
- runLink = a;
137
- }
138
- return {
139
- cells: [
140
- runLink,
141
- badge(run.status),
142
- run.recordedAt ?? run.finishedAt ?? "—",
143
- run.batchRunId ?? "—",
144
- run.retryOfWorkerRunId ?? "—",
145
- run.failureCategory ?? "—",
146
- ],
147
- };
148
- }
1
+ /** Run step/command/artifact processing and task history rows. */
2
+ import {
3
+ STEP_LABELS,
4
+ ARTIFACT_LABELS,
5
+ STEP_ORDER,
6
+ ARTIFACT_KEYS,
7
+ } from "./constants.js";
8
+ import { badge } from "./format.js";
9
+ import { navigate } from "./router.js";
10
+
11
+ export function stepDisplayLabel(label) {
12
+ return STEP_LABELS[label] ?? label;
13
+ }
14
+
15
+ export function buildStepStates(events) {
16
+ const states = new Map();
17
+ for (const ev of events) {
18
+ if (ev.type === "step.started") {
19
+ states.set(ev.label, { status: "running", startedAt: ev.at });
20
+ } else if (ev.type === "step.finished") {
21
+ states.set(ev.label, {
22
+ status: ev.status === "failed" ? "failed" : "succeeded",
23
+ durationMs: ev.durationMs,
24
+ });
25
+ }
26
+ }
27
+
28
+ const ordered = [...STEP_ORDER];
29
+ for (const label of states.keys()) {
30
+ if (!ordered.includes(label)) ordered.push(label);
31
+ }
32
+
33
+ return ordered.map((label) => {
34
+ const state = states.get(label);
35
+ return {
36
+ label,
37
+ display: stepDisplayLabel(label),
38
+ status: state?.status ?? "pending",
39
+ durationMs: state?.durationMs,
40
+ };
41
+ });
42
+ }
43
+
44
+ export function stepMarker(status) {
45
+ switch (status) {
46
+ case "succeeded":
47
+ return "✓";
48
+ case "running":
49
+ return "●";
50
+ case "failed":
51
+ return "✗";
52
+ default:
53
+ return "○";
54
+ }
55
+ }
56
+
57
+ export function getCurrentCommand(events) {
58
+ const active = new Map();
59
+ for (const ev of events) {
60
+ if (ev.type === "command.started") {
61
+ active.set(ev.label, ev);
62
+ } else if (ev.type === "command.finished") {
63
+ active.delete(ev.label);
64
+ }
65
+ }
66
+ let latest = null;
67
+ for (const cmd of active.values()) {
68
+ if (!latest || cmd.at > latest.at) latest = cmd;
69
+ }
70
+ if (latest?.at) {
71
+ const elapsed = Date.now() - Date.parse(latest.at);
72
+ latest = { ...latest, elapsedMs: Number.isFinite(elapsed) ? elapsed : 0 };
73
+ }
74
+ return latest;
75
+ }
76
+
77
+ export function getOutputTail(events, commandLabel) {
78
+ if (!commandLabel) return "";
79
+ const chunks = [];
80
+ for (const ev of events) {
81
+ if (
82
+ ev.type === "command.output" &&
83
+ ev.label === commandLabel &&
84
+ ev.outputPreview
85
+ ) {
86
+ chunks.push(ev.outputPreview);
87
+ }
88
+ }
89
+ return chunks.join("");
90
+ }
91
+
92
+ export function collectArtifacts(task, events) {
93
+ const arts = new Map();
94
+ const add = (label, artifactPath) => {
95
+ if (artifactPath && !arts.has(label)) arts.set(label, artifactPath);
96
+ };
97
+
98
+ if (task?.artifactRefs) {
99
+ for (const key of ARTIFACT_KEYS) {
100
+ add(ARTIFACT_LABELS[key] ?? key, task.artifactRefs[key]);
101
+ }
102
+ }
103
+
104
+ for (const ev of events) {
105
+ if (!ev.artifactRefs) continue;
106
+ for (const [key, artifactPath] of Object.entries(ev.artifactRefs)) {
107
+ add(ARTIFACT_LABELS[key] ?? key, artifactPath);
108
+ }
109
+ }
110
+
111
+ return arts;
112
+ }
113
+
114
+ export function findBatchRunIdForTask(snapshot, task) {
115
+ if (!snapshot || !task) return null;
116
+ const workerRunId = task.workerRunId;
117
+ if (!workerRunId) return null;
118
+ for (const batch of snapshot.batches ?? []) {
119
+ for (const t of batch.tasks ?? []) {
120
+ if (t.workerRunId === workerRunId) return batch.batchRunId;
121
+ }
122
+ }
123
+ return null;
124
+ }
125
+
126
+ export function taskRunHistoryRow(run) {
127
+ let runLink = run.workerRunId;
128
+ if (run.workerRunId) {
129
+ const a = document.createElement("a");
130
+ a.href = `#/run/${encodeURIComponent(run.workerRunId)}`;
131
+ a.textContent = run.workerRunId;
132
+ a.addEventListener("click", (e) => {
133
+ e.preventDefault();
134
+ navigate(`#/run/${encodeURIComponent(run.workerRunId)}`);
135
+ });
136
+ runLink = a;
137
+ }
138
+ return {
139
+ cells: [
140
+ runLink,
141
+ badge(run.status),
142
+ run.recordedAt ?? run.finishedAt ?? "—",
143
+ run.batchRunId ?? "—",
144
+ run.retryOfWorkerRunId ?? "—",
145
+ run.failureCategory ?? "—",
146
+ ],
147
+ };
148
+ }
@@ -47,8 +47,16 @@
47
47
 
48
48
  html {
49
49
  background:
50
- radial-gradient(1200px 480px at 8% -10%, rgb(241 216 203 / 45%), transparent 55%),
51
- radial-gradient(900px 420px at 100% 0%, rgb(216 234 213 / 35%), transparent 50%),
50
+ radial-gradient(
51
+ 1200px 480px at 8% -10%,
52
+ rgb(241 216 203 / 45%),
53
+ transparent 55%
54
+ ),
55
+ radial-gradient(
56
+ 900px 420px at 100% 0%,
57
+ rgb(216 234 213 / 35%),
58
+ transparent 50%
59
+ ),
52
60
  var(--canvas);
53
61
  min-height: 100%;
54
62
  scroll-behavior: smooth;
@@ -62,14 +70,8 @@ body {
62
70
  color: var(--ink);
63
71
  /* Keep system-ui first for shell contract tests; Chinese fonts follow. */
64
72
  font-family:
65
- system-ui,
66
- -apple-system,
67
- "Segoe UI",
68
- "PingFang SC",
69
- "Hiragino Sans GB",
70
- "Noto Sans SC",
71
- BlinkMacSystemFont,
72
- sans-serif;
73
+ system-ui, -apple-system, "Segoe UI", "PingFang SC", "Hiragino Sans GB",
74
+ "Noto Sans SC", BlinkMacSystemFont, sans-serif;
73
75
  font-size: 14px;
74
76
  line-height: 1.5;
75
77
  }
@@ -868,7 +870,7 @@ td:first-child,
868
870
  transition: opacity var(--transition-fast);
869
871
  }
870
872
  /* Five-column default: right two columns open inward (left) to avoid viewport overflow. */
871
- .kpi-grid:not(.pool-health-grid) > .kpi-card:nth-child(5n-1) .kpi-tip,
873
+ .kpi-grid:not(.pool-health-grid) > .kpi-card:nth-child(5n - 1) .kpi-tip,
872
874
  .kpi-grid:not(.pool-health-grid) > .kpi-card:nth-child(5n) .kpi-tip {
873
875
  left: auto;
874
876
  right: 12px;
@@ -1114,7 +1116,10 @@ td:first-child,
1114
1116
  }
1115
1117
  .feature-decision-row {
1116
1118
  display: grid;
1117
- grid-template-columns: minmax(120px, 0.9fr) minmax(88px, 0.55fr) minmax(0, 1.6fr) auto;
1119
+ grid-template-columns: minmax(120px, 0.9fr) minmax(88px, 0.55fr) minmax(
1120
+ 0,
1121
+ 1.6fr
1122
+ ) auto;
1118
1123
  align-items: center;
1119
1124
  gap: var(--space-3);
1120
1125
  padding: 12px 14px;
@@ -1254,8 +1259,8 @@ tr.clickable:focus-within {
1254
1259
  background: color-mix(in srgb, var(--red) 8%, var(--surface));
1255
1260
  }
1256
1261
  .badge-partial-failed {
1257
- color: color-mix(in srgb, var(--red) 70%, var(--ink));
1258
- background: color-mix(in srgb, var(--red) 6%, var(--surface));
1262
+ color: color-mix(in srgb, var(--amber) 80%, var(--ink));
1263
+ background: color-mix(in srgb, var(--amber) 10%, var(--surface));
1259
1264
  }
1260
1265
  .badge-running,
1261
1266
  .badge-started {
@@ -1494,7 +1499,11 @@ body.is-resizing-dag-graph {
1494
1499
  border: 1px solid var(--hairline);
1495
1500
  border-radius: var(--radius-lg);
1496
1501
  background:
1497
- radial-gradient(800px 280px at 0% 0%, rgb(241 216 203 / 28%), transparent 55%),
1502
+ radial-gradient(
1503
+ 800px 280px at 0% 0%,
1504
+ rgb(241 216 203 / 28%),
1505
+ transparent 55%
1506
+ ),
1498
1507
  var(--canvas-soft);
1499
1508
  scroll-behavior: auto;
1500
1509
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 60%);
@@ -2007,11 +2016,25 @@ body.is-resizing-dag-graph {
2007
2016
  font-weight: 700;
2008
2017
  }
2009
2018
 
2010
- .spec-evidence-section { padding-bottom: var(--space-4); border-bottom: 1px solid var(--hairline); }
2011
- .spec-evidence-section + .spec-evidence-section { margin-top: var(--space-4); }
2012
- .spec-evidence-section h4 { margin: 0 0 var(--space-2); color: var(--ink); font-size: 12px; font-weight: 700; }
2019
+ .spec-evidence-section {
2020
+ padding-bottom: var(--space-4);
2021
+ border-bottom: 1px solid var(--hairline);
2022
+ }
2023
+ .spec-evidence-section + .spec-evidence-section {
2024
+ margin-top: var(--space-4);
2025
+ }
2026
+ .spec-evidence-section h4 {
2027
+ margin: 0 0 var(--space-2);
2028
+ color: var(--ink);
2029
+ font-size: 12px;
2030
+ font-weight: 700;
2031
+ }
2013
2032
 
2014
- .node-input-root { display: flex; flex-direction: column; gap: var(--space-3); }
2033
+ .node-input-root {
2034
+ display: flex;
2035
+ flex-direction: column;
2036
+ gap: var(--space-3);
2037
+ }
2015
2038
  .node-input-semantics {
2016
2039
  margin: 0;
2017
2040
  font-size: 12px;
@@ -2084,24 +2107,141 @@ body.is-resizing-dag-graph {
2084
2107
  color: var(--danger, #b42318);
2085
2108
  font-size: 13px;
2086
2109
  }
2087
- .spec-evidence-summary { margin: var(--space-2) 0 0; color: var(--body); font-size: 12px; line-height: 1.6; }
2088
- .spec-evidence-list { display: grid; gap: 6px; margin: var(--space-2) 0 0; padding: 0; list-style: none; }
2089
- .spec-evidence-list li { display: flex; align-items: flex-start; gap: 6px; color: var(--body); font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
2090
- .spec-evidence-list li > i { flex-shrink: 0; margin-top: 2px; color: var(--muted); font-size: 13px; }
2091
- .spec-evidence-list code { font-size: 11px; }
2092
- .spec-evidence-time { margin-left: auto; color: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; white-space: nowrap; }
2093
- .spec-evidence-warning { display: flex; align-items: flex-start; gap: 8px; margin-top: var(--space-4); padding: 10px 12px; border: 1px solid var(--hairline); border-left: 3px solid color-mix(in srgb, var(--amber) 60%, var(--hairline)); border-radius: var(--radius-md); background: color-mix(in srgb, var(--amber) 8%, var(--surface)); color: var(--body); font-size: 12px; line-height: 1.6; }
2094
- .spec-evidence-warning > i { flex-shrink: 0; margin-top: 2px; color: var(--amber); }
2095
- .spec-evidence-file-btn { display: flex; align-items: flex-start; gap: 6px; width: 100%; padding: 6px 8px; background: none; border: none; text-align: left; cursor: pointer; color: inherit; font: inherit; line-height: 1.5; overflow-wrap: anywhere; border-radius: var(--radius-md); }
2096
- .spec-evidence-file-btn:hover, .spec-evidence-file-btn:focus-visible { background: var(--orange-soft); outline: none; }
2097
- .spec-evidence-file-btn:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--orange) 35%, transparent); }
2098
- .spec-evidence-detail { display: grid; gap: var(--space-3); }
2099
- .spec-evidence-back { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border: 1px solid var(--hairline); border-radius: var(--radius-pill); background: var(--surface); color: var(--ink); font-size: 12px; font-weight: 650; cursor: pointer; }
2100
- .spec-evidence-back:hover, .spec-evidence-back:focus-visible { background: var(--orange-soft); border-color: var(--orange); color: var(--orange-active); outline: none; }
2101
- .spec-evidence-detail-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 12px; color: var(--body); }
2102
- .spec-evidence-detail-content { min-height: 0; max-width: 100%; margin: 0; padding: var(--space-3); border: 1px solid var(--hairline); border-radius: var(--radius-md); background: var(--canvas-soft); overflow-wrap: anywhere; font-size: 12px; line-height: 1.6; }
2103
- .spec-evidence-detail-error { margin: 0; color: var(--red, #c00); font-size: 12px; }
2104
- .spec-evidence-detail-truncated { margin: 0; color: var(--muted); font-size: 11px; }
2110
+ .spec-evidence-summary {
2111
+ margin: var(--space-2) 0 0;
2112
+ color: var(--body);
2113
+ font-size: 12px;
2114
+ line-height: 1.6;
2115
+ }
2116
+ .spec-evidence-list {
2117
+ display: grid;
2118
+ gap: 6px;
2119
+ margin: var(--space-2) 0 0;
2120
+ padding: 0;
2121
+ list-style: none;
2122
+ }
2123
+ .spec-evidence-list li {
2124
+ display: flex;
2125
+ align-items: flex-start;
2126
+ gap: 6px;
2127
+ color: var(--body);
2128
+ font-size: 12px;
2129
+ line-height: 1.5;
2130
+ overflow-wrap: anywhere;
2131
+ }
2132
+ .spec-evidence-list li > i {
2133
+ flex-shrink: 0;
2134
+ margin-top: 2px;
2135
+ color: var(--muted);
2136
+ font-size: 13px;
2137
+ }
2138
+ .spec-evidence-list code {
2139
+ font-size: 11px;
2140
+ }
2141
+ .spec-evidence-time {
2142
+ margin-left: auto;
2143
+ color: var(--muted);
2144
+ font-size: 10px;
2145
+ font-variant-numeric: tabular-nums;
2146
+ white-space: nowrap;
2147
+ }
2148
+ .spec-evidence-warning {
2149
+ display: flex;
2150
+ align-items: flex-start;
2151
+ gap: 8px;
2152
+ margin-top: var(--space-4);
2153
+ padding: 10px 12px;
2154
+ border: 1px solid var(--hairline);
2155
+ border-left: 3px solid color-mix(in srgb, var(--amber) 60%, var(--hairline));
2156
+ border-radius: var(--radius-md);
2157
+ background: color-mix(in srgb, var(--amber) 8%, var(--surface));
2158
+ color: var(--body);
2159
+ font-size: 12px;
2160
+ line-height: 1.6;
2161
+ }
2162
+ .spec-evidence-warning > i {
2163
+ flex-shrink: 0;
2164
+ margin-top: 2px;
2165
+ color: var(--amber);
2166
+ }
2167
+ .spec-evidence-file-btn {
2168
+ display: flex;
2169
+ align-items: flex-start;
2170
+ gap: 6px;
2171
+ width: 100%;
2172
+ padding: 6px 8px;
2173
+ background: none;
2174
+ border: none;
2175
+ text-align: left;
2176
+ cursor: pointer;
2177
+ color: inherit;
2178
+ font: inherit;
2179
+ line-height: 1.5;
2180
+ overflow-wrap: anywhere;
2181
+ border-radius: var(--radius-md);
2182
+ }
2183
+ .spec-evidence-file-btn:hover,
2184
+ .spec-evidence-file-btn:focus-visible {
2185
+ background: var(--orange-soft);
2186
+ outline: none;
2187
+ }
2188
+ .spec-evidence-file-btn:focus-visible {
2189
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--orange) 35%, transparent);
2190
+ }
2191
+ .spec-evidence-detail {
2192
+ display: grid;
2193
+ gap: var(--space-3);
2194
+ }
2195
+ .spec-evidence-back {
2196
+ display: inline-flex;
2197
+ align-items: center;
2198
+ gap: 6px;
2199
+ padding: 6px 12px;
2200
+ border: 1px solid var(--hairline);
2201
+ border-radius: var(--radius-pill);
2202
+ background: var(--surface);
2203
+ color: var(--ink);
2204
+ font-size: 12px;
2205
+ font-weight: 650;
2206
+ cursor: pointer;
2207
+ }
2208
+ .spec-evidence-back:hover,
2209
+ .spec-evidence-back:focus-visible {
2210
+ background: var(--orange-soft);
2211
+ border-color: var(--orange);
2212
+ color: var(--orange-active);
2213
+ outline: none;
2214
+ }
2215
+ .spec-evidence-detail-meta {
2216
+ display: flex;
2217
+ flex-wrap: wrap;
2218
+ align-items: center;
2219
+ gap: 8px;
2220
+ font-size: 12px;
2221
+ color: var(--body);
2222
+ }
2223
+ .spec-evidence-detail-content {
2224
+ min-height: 0;
2225
+ max-width: 100%;
2226
+ margin: 0;
2227
+ padding: var(--space-3);
2228
+ border: 1px solid var(--hairline);
2229
+ border-radius: var(--radius-md);
2230
+ background: var(--canvas-soft);
2231
+ overflow-wrap: anywhere;
2232
+ font-size: 12px;
2233
+ line-height: 1.6;
2234
+ }
2235
+ .spec-evidence-detail-error {
2236
+ margin: 0;
2237
+ color: var(--red, #c00);
2238
+ font-size: 12px;
2239
+ }
2240
+ .spec-evidence-detail-truncated {
2241
+ margin: 0;
2242
+ color: var(--muted);
2243
+ font-size: 11px;
2244
+ }
2105
2245
 
2106
2246
  .run-layer-process {
2107
2247
  display: grid;
@@ -2312,10 +2452,12 @@ body.is-resizing-dag-graph {
2312
2452
  background: color-mix(in srgb, var(--green) 75%, white);
2313
2453
  }
2314
2454
  .dag-run-timeline-dot.status-failed,
2315
- .dag-run-timeline-dot.status-error,
2316
- .dag-run-timeline-dot.status-partial_failed {
2455
+ .dag-run-timeline-dot.status-error {
2317
2456
  background: color-mix(in srgb, var(--red) 75%, white);
2318
2457
  }
2458
+ .dag-run-timeline-dot.status-partial-failed {
2459
+ background: color-mix(in srgb, var(--amber) 75%, white);
2460
+ }
2319
2461
  .dag-run-timeline-dot.status-running,
2320
2462
  .dag-run-timeline-dot.status-started {
2321
2463
  background: var(--orange);
@@ -2374,7 +2516,7 @@ body.is-resizing-dag-graph {
2374
2516
  border-left: 0;
2375
2517
  }
2376
2518
  /* Three-column: reset five-column tip edges, then rightmost column opens inward. */
2377
- .kpi-grid:not(.pool-health-grid) > .kpi-card:nth-child(5n-1) .kpi-tip,
2519
+ .kpi-grid:not(.pool-health-grid) > .kpi-card:nth-child(5n - 1) .kpi-tip,
2378
2520
  .kpi-grid:not(.pool-health-grid) > .kpi-card:nth-child(5n) .kpi-tip {
2379
2521
  left: 12px;
2380
2522
  right: auto;
@@ -2662,8 +2804,6 @@ button.copy-command:focus-visible {
2662
2804
  margin: 0.15rem 0 0.35rem;
2663
2805
  }
2664
2806
 
2665
-
2666
-
2667
2807
  /* R5: unified view states + information hierarchy */
2668
2808
  .view-state {
2669
2809
  border-radius: var(--radius-lg);