dsh-harbor-evolution 0.4.0 → 0.6.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.
package/lib/client.js CHANGED
@@ -48,318 +48,840 @@ var harbor_ocean_default = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4
48
48
 
49
49
  // src/client/index.jsx
50
50
  var NS = "harbor-evolution";
51
- var ROUTE = "/_dsh/harbor-evolution/dashboard";
51
+ var API = "/_dsh/harbor-evolution";
52
+ var STAGES = ["candidate", "dataset", "integration", "renderer", "judge", "meta", "reporter", "optimizer", "gate"];
53
+ var REPORT_PAGE_SIZE = 10;
52
54
  var dictionaries = {
53
55
  zh: {
54
56
  tab: "Harbor",
55
57
  settings: "Harbor \u81EA\u8FDB\u5316",
56
- eyebrow: "HARBOR SELF-EVOLVING",
57
- heroTitle: "\u8BA9\u6BCF\u6B21 Agent \u6539\u52A8\u90FD\u6709\u8BC1\u636E",
58
- heroBody: "Candidate \u56FA\u5316\u80FD\u529B\uFF0CJob \u4FDD\u5B58\u5B9E\u9A8C\uFF0CPromotion Gate \u53EA\u8BA9\u53EF\u6BD4\u8F83\u3001\u65E0\u56DE\u5F52\u7684\u7248\u672C\u9760\u5CB8\u3002",
58
+ eyebrow: "EVALUATION WORKBENCH",
59
+ heroTitle: "\u770B\u89C1 Agent \u7684\u6BCF\u4E00\u6B21\u8FDB\u6B65\uFF0C\u4E5F\u770B\u89C1\u5206\u6570\u662F\u5426\u503C\u5F97\u76F8\u4FE1",
60
+ heroBody: "Harbor \u56FA\u5B9A\u5B9E\u9A8C\u8FB9\u754C\uFF1BTrial Lifecycle \u5C55\u793A\u771F\u5B9E\u8FD0\u884C\u8FC7\u7A0B\uFF1BScore Validity \u963B\u6B62\u57FA\u7840\u8BBE\u65BD\u6545\u969C\u4F2A\u88C5\u6210\u4E1A\u52A1 0 \u5206\u3002",
59
61
  refresh: "\u5237\u65B0",
60
- refreshed: "\u6700\u8FD1\u5237\u65B0",
61
- totalJobs: "\u8BC4\u6D4B\u6279\u6B21",
62
- completedJobs: "\u5DF2\u5B8C\u6210",
63
- activeJobs: "\u8FDB\u884C\u4E2D",
64
- failedJobs: "\u5931\u8D25",
65
- latestMetric: "\u6700\u65B0\u6307\u6807",
66
- jobs: "\u6700\u8FD1\u7684 Harbor Jobs",
67
- jobsHint: "\u6700\u591A\u5C55\u793A\u6700\u8FD1 50 \u4E2A\u6279\u6B21\u3002\u7ED3\u679C\u76F4\u63A5\u8BFB\u53D6\u7A33\u5B9A\u7684 evaluation-summary.json\u3002",
68
- emptyTitle: "\u8FD8\u6CA1\u6709\u8BC4\u6D4B\u7ED3\u679C",
69
- emptyBody: "\u8BA9 Agent \u8C03\u7528\u5B98\u65B9 Skill\uFF0C\u5148\u6F84\u6E05 Candidate\u3001Dataset \u4E0E Promotion Policy\uFF0C\u518D\u542F\u52A8\u7B2C\u4E00\u4E2A Job\u3002",
70
- startStep1: "1. \u56FA\u5316 Candidate",
71
- startStep2: "2. \u8FD0\u884C Harbor Job",
72
- startStep3: "3. \u6BD4\u8F83\u5E76\u51B3\u5B9A\u664B\u7EA7",
73
- candidate: "Candidate",
74
- context: "\u8BC4\u6D4B\u4E0A\u4E0B\u6587",
62
+ jobs: "\u8BC4\u6D4B\u6279\u6B21",
63
+ jobsHint: "\u70B9\u51FB Job \u540E\uFF0C\u6700\u591A\u518D\u70B9\u4E00\u6B21\u5373\u53EF\u8FDB\u5165\u5BF9\u5E94 Trial \u7684\u8BC1\u636E\u3002",
64
+ empty: "\u8FD8\u6CA1\u6709\u53EF\u8BFB\u53D6\u7684 Harbor Job\u3002\u8BF7\u7528\u5B98\u65B9 Skill \u5B8C\u6210\u9700\u6C42\u6F84\u6E05\u548C\u521D\u59CB\u5316\u3002",
65
+ completed: "\u5DF2\u5B8C\u6210",
66
+ partial: "\u5B8C\u6210\u4F46\u6709\u5F02\u5E38",
67
+ failed: "\u8BFB\u53D6\u5931\u8D25",
68
+ pending: "\u7B49\u5F85\u8FD0\u884C",
69
+ running: "\u8FD0\u884C\u4E2D",
70
+ attention: "\u9700\u6838\u67E5",
71
+ candidate: "\u5019\u9009\u7248\u672C",
72
+ dataset: "\u8BC4\u6D4B\u96C6",
73
+ integration: "\u96C6\u6210",
74
+ renderer: "\u4EA7\u7269\u5448\u73B0",
75
+ judge: "\u8BC4\u6D4B\u5668",
76
+ meta: "\u8BC4\u6D4B\u5668\u5143\u8BC4\u6D4B",
77
+ reporter: "\u8BC4\u6D4B\u62A5\u544A",
78
+ optimizer: "\u4F18\u5316\u5668",
79
+ gate: "\u664B\u7EA7\u95E8\u7981",
80
+ context: "Context v2",
75
81
  trials: "Trials",
76
- exceptions: "Exceptions",
77
- metrics: "\u6307\u6807",
78
- pending: "\u4E0B\u6F5C\u4E2D",
79
- completed: "\u5DF2\u9760\u5CB8",
80
- partial: "\u5E26\u5F02\u5E38\u5B8C\u6210",
81
- failed: "\u9047\u5230\u98CE\u66B4",
82
- promote: "\u664B\u7EA7",
83
- reject: "\u62D2\u7EDD\u664B\u7EA7",
84
- noMetrics: "\u6682\u65E0\u6307\u6807",
85
- loading: "\u6B63\u5728\u8BFB\u53D6 Harbor \u822A\u7EBF\u2026",
86
- loadError: "\u65E0\u6CD5\u8BFB\u53D6 Harbor \u72B6\u6001",
82
+ exceptions: "\u5F02\u5E38",
83
+ mode: "\u6A21\u5F0F",
84
+ close: "\u5173\u95ED",
87
85
  retry: "\u91CD\u8BD5",
88
- doctorTitle: "\u5B89\u88C5\u4E0E\u8FD0\u884C\u68C0\u67E5",
89
- doctorBody: "\u8FD9\u91CC\u68C0\u67E5 DSH Plugin \u5230 Harbor Runtime \u7684\u5173\u952E\u8DEF\u5F84\u3002\u914D\u7F6E\u4ECD\u7531 Cordis Profile \u7BA1\u7406\uFF0C\u4E0D\u4F1A\u88AB\u6D4F\u89C8\u5668\u9759\u9ED8\u6539\u5199\u3002",
90
- ready: "\u53EF\u4EE5\u5F00\u59CB\u8BC4\u6D4B",
91
- attention: "\u9700\u8981\u5904\u7406",
92
- projectRoot: "\u9879\u76EE\u6839\u76EE\u5F55",
93
- jobsDir: "Jobs \u76EE\u5F55",
94
- harbor: "Harbor CLI",
95
- harborDsh: "Promotion CLI",
96
- runtime: "\u8FD0\u884C\u5951\u7EA6",
97
- dshVersion: "DSH \u7248\u672C",
98
- agentImport: "Agent \u5165\u53E3",
99
- pluginImport: "Harbor Plugin",
100
- skillGuide: "\u5982\u4F55\u5F00\u59CB",
101
- skillBody: "\u5728\u5BF9\u8BDD\u4E2D\u8BF4\u660E\u201C\u8BF7\u7528 Harbor \u81EA\u8FDB\u5316 Skill \u521D\u59CB\u5316\u5E76\u8BC4\u6D4B\u6211\u7684 Agent\u201D\u3002Skill \u4F1A\u5148\u8865\u9F50\u9700\u6C42\uFF0C\u800C\u4E0D\u662F\u76F4\u63A5\u6267\u884C\u9AD8\u6210\u672C Job\u3002",
102
- toolSnapshot: "\u56FA\u5316 Candidate",
103
- toolRun: "\u8FD0\u884C Harbor \u8BC4\u6D4B",
104
- toolResult: "\u8BFB\u53D6\u8BC4\u6D4B\u7ED3\u679C",
105
- toolCompare: "\u6267\u884C Promotion Gate",
106
- running: "\u6267\u884C\u4E2D",
107
- toolFailed: "\u5DE5\u5177\u8C03\u7528\u5931\u8D25",
108
- noResult: "\u6CA1\u6709\u53EF\u89E3\u6790\u7684\u7ED3\u6784\u5316\u7ED3\u679C",
109
- digest: "Digest",
110
- version: "\u7248\u672C",
111
- job: "Job",
112
- decision: "\u51B3\u7B56",
113
- reasons: "Gate \u539F\u56E0",
114
- comparable: "\u540C\u4E00\u8BC4\u6D4B\u4E0A\u4E0B\u6587",
115
- changed: "Candidate \u5DF2\u6539\u53D8"
86
+ loading: "\u6B63\u5728\u8BFB\u53D6\u2026",
87
+ noData: "\u6682\u65E0\u6570\u636E",
88
+ currentStatus: "\u5F53\u524D\u72B6\u6001",
89
+ score: "\u4E1A\u52A1\u5206\u6570",
90
+ valid: "\u5206\u6570\u6709\u6548",
91
+ validScores: "\u6709\u6548\u5206\u6570",
92
+ invalid: "\u5206\u6570\u65E0\u6548",
93
+ unavailable: "\u4E0D\u53EF\u7528",
94
+ validity: "Score Validity",
95
+ progress: "\u8FDB\u5EA6",
96
+ health: "\u5065\u5EB7\u5EA6",
97
+ evidence: "\u8BC1\u636E",
98
+ capabilityUnavailable: "\u6B64 Job \u672A\u4EA7\u51FA\u8BE5\u7248\u672C\u80FD\u529B\uFF1B\u4EC5\u6309\u5386\u53F2\u4EA7\u7269\u53EA\u8BFB\u5C55\u793A\u3002",
99
+ search: "\u641C\u7D22 Query / Trial",
100
+ all: "\u5168\u90E8",
101
+ previous: "\u4E0A\u4E00\u9875",
102
+ next: "\u4E0B\u4E00\u9875",
103
+ datasetOrder: "Dataset \u987A\u5E8F",
104
+ latest: "\u6700\u8FD1\u5B8C\u6210",
105
+ lowest: "\u6700\u4F4E\u5206",
106
+ errorsFirst: "\u9519\u8BEF\u4F18\u5148",
107
+ findings: "\u4E3B\u8981\u53D1\u73B0",
108
+ recommendations: "\u5EFA\u8BAE",
109
+ output: "\u7528\u6237\u53EF\u89C1\u8F93\u51FA",
110
+ criteria: "\u8BC4\u5206\u7EF4\u5EA6",
111
+ provenance: "\u8BC1\u636E\u6765\u6E90",
112
+ timing: "\u6267\u884C\u65F6\u95F4",
113
+ audit: "\u5BA1\u8BA1\u539F\u6587",
114
+ compare: "\u56DE\u5F52\u6BD4\u8F83",
115
+ baseline: "Baseline Job",
116
+ comparable: "\u53EF\u6BD4\u8F83",
117
+ notComparable: "\u4E0D\u53EF\u6BD4\u8F83",
118
+ improved: "\u6539\u5584\u6837\u672C",
119
+ regressed: "\u56DE\u5F52\u6837\u672C",
120
+ explicitGate: "\u53EA\u8BFB\u6BD4\u8F83\u4E0D\u4F1A\u81EA\u52A8 Gate\uFF1B\u9700\u8981\u663E\u5F0F\u6388\u6743\u540E\u8FD0\u884C\u786E\u5B9A\u6027 Gate\u3002",
121
+ governance: "\u8BC4\u6D4B\u5668\u6CBB\u7406",
122
+ governanceHint: "\u8BFB\u53D6 Rubric / Evaluator / Judge \u8EAB\u4EFD\u4E0E\u6E90\u7801\u3002\u8BED\u4E49\u6539\u52A8\u5FC5\u987B\u521B\u5EFA\u65B0\u8EAB\u4EFD\uFF0C\u5E76\u5EFA\u7ACB\u65B0 Baseline\u3002",
123
+ artifacts: "Artifact Registry",
124
+ setupDoctor: "\u5B89\u88C5\u4E0E\u67B6\u6784\u68C0\u67E5",
125
+ setupHint: "\u6D4F\u89C8\u5668\u4EC5\u80FD\u6539\u5199 Evaluator \u58F0\u660E\u4E2D\u660E\u786E\u6388\u6743\u7684\u6587\u4EF6\uFF1B\u4E0D\u4F1A\u6539\u5199 Candidate \u6216\u81EA\u52A8\u53D1\u8D77\u8BC4\u6D4B\u3002",
126
+ stageNav: "\u8BC4\u6D4B\u9636\u6BB5",
127
+ datasetTasks: "\u8BC4\u6D4B\u4EFB\u52A1",
128
+ datasetSource: "\u4EFB\u52A1\u6765\u6E90",
129
+ taskInstruction: "\u5177\u4F53\u4EFB\u52A1\u8981\u6C42",
130
+ instructionFile: "\u6307\u4EE4\u6587\u4EF6",
131
+ snapshot: "Job \u56FA\u5316\u5FEB\u7167",
132
+ historicalFallback: "\u5386\u53F2 Job \u6E90\u6587\u4EF6\u56DE\u8BFB",
133
+ generatedOutput: "\u751F\u6210\u4EA7\u7269",
134
+ selectTrial: "\u9009\u62E9 Trial",
135
+ noRenderableOutput: "\u8FD9\u4E2A Trial \u6CA1\u6709\u53EF\u5448\u73B0\u7684\u9875\u9762\u3001\u6587\u6863\u6216\u7ED3\u6784\u5316\u4EA7\u7269\u3002\u8BF7\u8BA9 Agent \u5C06\u4E1A\u52A1\u7ED3\u679C\u5199\u5165 Harbor artifacts\u3002",
136
+ previewSource: "\u4EA7\u7269\u6765\u6E90",
137
+ pagePreview: "\u9875\u9762\u9884\u89C8",
138
+ documentPreview: "\u6587\u6863\u9884\u89C8",
139
+ structuredOutput: "\u7ED3\u6784\u5316\u4EA7\u7269",
140
+ rawOutput: "\u539F\u59CB\u4EA7\u7269",
141
+ currentEvaluator: "\u5F53\u524D\u8BC4\u6D4B\u5668",
142
+ evaluator: "Evaluator",
143
+ rubric: "Rubric",
144
+ judgeParameters: "Judge \u53C2\u6570",
145
+ scoringContract: "\u8BC4\u5206\u5408\u540C",
146
+ primaryMetric: "\u4E3B\u6307\u6807",
147
+ metricSemantics: "\u6307\u6807\u8BED\u4E49",
148
+ sourceCode: "\u67E5\u770B\u6E90\u7801",
149
+ upgradeEvaluator: "\u5982\u4F55\u5347\u7EA7\u8BC4\u6D4B\u5668",
150
+ upgradeHint: "\u8BC4\u6D4B\u5668\u5347\u7EA7\u4F1A\u6539\u53D8\u5206\u6570\u8BED\u4E49\u3002\u521B\u5EFA\u65B0\u8EAB\u4EFD\uFF0C\u5148\u505A\u5143\u8BC4\u6D4B\uFF0C\u518D\u5EFA\u7ACB\u65B0\u7684 Agent Baseline\u3002",
151
+ copyPrompt: "\u590D\u5236\u7ED9 Agent",
152
+ copied: "\u5DF2\u590D\u5236",
153
+ freshBaseline: "\u9700\u8981\u65B0 Baseline",
154
+ metaEvaluation: "\u5143\u8BC4\u6D4B\u8981\u6C42",
155
+ evaluatorImplementation: "\u8BC4\u6D4B\u5668\u5B9E\u73B0",
156
+ evaluatorKind: "\u5B9E\u73B0\u7C7B\u578B",
157
+ evaluatorProtocol: "\u63A5\u53E3\u534F\u8BAE",
158
+ editableFiles: "\u5141\u8BB8\u4FEE\u6539\u7684\u6587\u4EF6",
159
+ openFile: "\u6253\u5F00",
160
+ editingFile: "\u6B63\u5728\u4FEE\u6539",
161
+ editSource: "\u76F4\u63A5\u4FEE\u6539\u5F53\u524D\u6587\u4EF6",
162
+ evaluatorVersion: "\u65B0 Evaluator \u7248\u672C",
163
+ stackVersion: "\u65B0 Stack \u7248\u672C",
164
+ saveEvaluator: "\u4FDD\u5B58\u4E3A\u65B0\u8EAB\u4EFD",
165
+ saving: "\u6B63\u5728\u4FDD\u5B58\u2026",
166
+ saved: "\u5DF2\u4FDD\u5B58\uFF1B\u4E0B\u4E00\u6B65\u8BF7\u505A\u5143\u8BC4\u6D4B\u5E76\u5EFA\u7ACB\u65B0 Baseline\u3002",
167
+ reloadBeforeSave: "\u6E90\u7801\u5DF2\u53D8\u5316\uFF0C\u8BF7\u5237\u65B0\u540E\u518D\u4FDD\u5B58\u3002",
168
+ noEvaluatorInterface: "\u5F53\u524D Stack \u8FD8\u6CA1\u6709 harbor-dsh-evaluator/v1 \u63A5\u53E3\uFF0C\u4E0D\u80FD\u4ECE UI \u5B89\u5168\u7F16\u8F91\u3002",
169
+ editWarning: "\u4FDD\u5B58\u53EA\u66F4\u65B0\u6E90\u7801\u4E0E\u8EAB\u4EFD\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u8FD0\u884C\u8BC4\u6D4B\u6216 Gate\u3002",
170
+ upgradeStep1: "\u67E5\u770B\u5F53\u524D Evaluator\u3001Rubric\u3001Judge\u3001\u8BC4\u5206\u5408\u540C\u548C\u4EE3\u8868\u6027\u8BEF\u5224\u6837\u672C\u3002",
171
+ upgradeStep2: "\u521B\u5EFA\u65B0\u7684\u8BC4\u6D4B\u5668\u8EAB\u4EFD\u3001\u7248\u672C\u548C\u6E90\u6587\u4EF6\uFF1B\u4E0D\u8986\u76D6\u5386\u53F2\u8BC4\u6D4B\u5668\u3002",
172
+ upgradeStep3: "\u4F7F\u7528\u72EC\u7ACB\u3001\u53EF\u8FFD\u6EAF\u7684 GT \u8FD0\u884C\u5143\u8BC4\u6D4B\uFF0C\u68C0\u67E5 ESF\u3001SCE\u3001RCR\u3001\u5EF6\u8FDF\u548C\u6210\u672C\u3002",
173
+ upgradeStep4: "\u66F4\u65B0 Evaluation Stack \u8EAB\u4EFD\uFF0C\u5E76\u9884\u89C8 Context v2 \u53D8\u5316\u3002",
174
+ upgradeStep5: "\u5728\u65B0\u5206\u6570\u8BED\u4E49\u4E0B\u5EFA\u7ACB\u5168\u65B0 Agent Baseline\uFF0C\u518D\u6BD4\u8F83\u540E\u7EED Candidate\u3002",
175
+ evaluatorPrompt: "\u8BF7\u4F7F\u7528 evolve-agent-with-harbor \u5347\u7EA7\u5F53\u524D\u8BC4\u6D4B\u5668\u3002\u5148\u8BFB\u53D6 governance \u8BC1\u636E\uFF0C\u6F84\u6E05 GT \u7684\u6765\u6E90\u7C7B\u578B\u3001provenance\u3001\u7EF4\u62A4\u8005\u548C\u76EE\u6807\u5143\u6307\u6807\uFF0C\u518D\u63D0\u51FA\u65B0\u7684\u4E0D\u53EF\u53D8\u8BC4\u6D4B\u5668\u8EAB\u4EFD\u4E0E fresh-baseline \u65B9\u6848\u3002\u5728\u6211\u6279\u51C6\u53D7\u63A7\u6539\u52A8\u524D\uFF0C\u4E0D\u8981\u4FEE\u6539\u6587\u4EF6\u6216\u53D1\u8D77\u8BC4\u6D4B\u3002",
176
+ queryTrial: "\u4EFB\u52A1 / Trial",
177
+ statusLabel: "\u72B6\u6001",
178
+ attempt: "\u5C1D\u8BD5",
179
+ population: "\u4EFB\u52A1\u6570\u91CF",
180
+ experimentIdentity: "\u672C\u6B21\u5B9E\u9A8C\u56FA\u5B9A\u4E86\u4EC0\u4E48",
181
+ experimentIdentityHint: "Candidate\u3001Dataset\u3001Evaluation Stack \u4E0E Runtime \u5171\u540C\u5B9A\u4E49\u53EF\u590D\u73B0\u3001\u53EF\u6BD4\u8F83\u7684\u5B9E\u9A8C\u8EAB\u4EFD\u3002",
182
+ immutableCandidateFiles: "\u5019\u9009\u7248\u672C\u5185\u5BB9",
183
+ file: "\u6587\u4EF6",
184
+ size: "\u5927\u5C0F",
185
+ digest: "\u5185\u5BB9\u6307\u7EB9",
186
+ runtime: "\u8FD0\u884C\u65F6",
187
+ evaluationStack: "Evaluation Stack",
188
+ integrationBoundary: "\u6267\u884C\u4E0E\u8BC4\u5206\u8FB9\u754C",
189
+ hardRequirements: "\u5206\u6570\u751F\u6548\u524D\u5FC5\u987B\u6EE1\u8DB3",
190
+ populationEvidence: "\u603B\u4F53\u8BC4\u6D4B\u8BC1\u636E",
191
+ metric: "\u6307\u6807",
192
+ aggregate: "\u603B\u4F53\u503C",
193
+ coverage: "\u6709\u6548\u8986\u76D6",
194
+ trialGroups: "Trial \u72B6\u6001\u5206\u7EC4",
195
+ controlledHypotheses: "\u53D7\u63A7\u4F18\u5316\u5047\u8BBE",
196
+ rootCause: "\u8BC1\u636E\u6307\u5411",
197
+ affectedTrials: "\u5F71\u54CD\u6837\u672C",
198
+ expectedEffect: "\u9884\u671F\u6307\u6807\u53D8\u5316",
199
+ mutationSurface: "\u5141\u8BB8\u6539\u52A8",
200
+ forbiddenSurface: "\u7981\u6B62\u6539\u52A8",
201
+ guardrails: "\u4FDD\u62A4\u6761\u4EF6",
202
+ rollback: "\u56DE\u6EDA\u6761\u4EF6",
203
+ nextExperiment: "\u4E0B\u4E00\u6B21\u53D7\u63A7\u5B9E\u9A8C",
204
+ noHypotheses: "\u672C\u6279\u6B21\u6CA1\u6709\u751F\u6210\u53D7\u63A7\u4F18\u5316\u5047\u8BBE\u3002",
205
+ gateEvidence: "\u5DF2\u6267\u884C\u7684\u664B\u7EA7\u95E8\u7981",
206
+ decision: "\u95E8\u7981\u7ED3\u679C",
207
+ policy: "\u95E8\u7981\u7B56\u7565",
208
+ eligible: "\u6EE1\u8DB3\u95E8\u7981\u524D\u63D0",
209
+ notEligible: "\u4E0D\u6EE1\u8DB3\u95E8\u7981\u524D\u63D0",
210
+ metricDeltas: "\u6307\u6807\u53D8\u5316",
211
+ newExceptions: "\u65B0\u589E\u5F02\u5E38",
212
+ artifactRegressions: "\u4EA7\u7269\u56DE\u5F52",
213
+ reasons: "\u95E8\u7981\u4F9D\u636E",
214
+ trialAssessments: "\u9010 Trial \u8BC4\u6D4B",
215
+ trialAssessmentsHint: "\u6BCF\u4E00\u884C\u5BF9\u5E94\u4E00\u4E2A\u4E1A\u52A1\u4EA7\u7269\uFF1B\u9009\u62E9\u4EFB\u52A1\u540E\u53EF\u5E76\u6392\u67E5\u770B\u4EA7\u7269\u3001\u9010\u7EF4\u5206\u6570\u3001\u539F\u56E0\u548C\u8BC4\u6D4B\u5668\u5EFA\u8BAE\u3002",
216
+ overallScore: "\u7EFC\u5408\u5206",
217
+ artifact: "\u8BC4\u6D4B\u4EA7\u7269",
218
+ assessmentReason: "\u8BC4\u5206\u539F\u56E0",
219
+ assessmentRecommendation: "\u6539\u8FDB\u5EFA\u8BAE",
220
+ assessmentDetails: "\u8BC4\u6D4B\u8BE6\u60C5",
221
+ noAssessmentReason: "\u8BC4\u6D4B\u5668\u6CA1\u6709\u8FD4\u56DE\u8BC4\u5206\u539F\u56E0\uFF1B\u8BE5\u7ED3\u679C\u4E0D\u5E94\u8FDB\u5165\u6709\u6548\u603B\u4F53\u5206\u3002",
222
+ noAssessmentRecommendation: "\u8BC4\u6D4B\u5668\u6CA1\u6709\u8FD4\u56DE\u6539\u8FDB\u5EFA\u8BAE\uFF1B\u8BE5\u7ED3\u679C\u4E0D\u5E94\u8FDB\u5165\u6709\u6548\u603B\u4F53\u5206\u3002",
223
+ evaluatorAdvice: "\u8BC4\u6D4B\u5668\u5EFA\u8BAE",
224
+ reportPage: "\u62A5\u544A\u5206\u9875",
225
+ groundTruth: "Ground Truth\uFF08\u91D1\u6807\uFF09",
226
+ groundTruthRequired: "\u9700\u8981\u5148\u5EFA\u7ACB\u72EC\u7ACB Ground Truth",
227
+ gtSource: "GT \u6765\u6E90",
228
+ gtProvenance: "\u6765\u6E90\u8BC1\u660E",
229
+ gtCases: "\u91D1\u6807\u6837\u672C",
230
+ gtBadcases: "Badcase",
231
+ gtKinds: "\u53EF\u9009\u6765\u6E90\uFF1A\u4EBA\u5DE5\u3001\u7A0B\u5E8F\u3001\u591A\u65B9\u5171\u8BC6\u3001\u72EC\u7ACB\u6A21\u578B\u6216\u5916\u90E8\u6807\u51C6\u3002\u5173\u952E\u662F\u7248\u672C\u5316\u3001\u53EF\u8FFD\u6EAF\uFF0C\u5E76\u72EC\u7ACB\u4E8E\u5F85\u6D4B\u8BC4\u6D4B\u5668\u3002",
232
+ metaWorkflow: "\u72EC\u7ACB\u5143\u8BC4\u6D4B\u6D41\u7A0B",
233
+ metaWorkflowHint: "Evaluator \u662F Candidate\uFF1B\u56FA\u5B9A\u4EA7\u7269\u4E0E GT \u662F Dataset\uFF1B\u91CD\u590D\u89C2\u6D4B\u540E\u8BA1\u7B97 ESF\u3001SCE\u3001RCR\u3002",
234
+ metaNext: "\u4E0B\u4E00\u6B65",
235
+ disagreements: "\u5206\u6B67\u6837\u672C",
236
+ hookExecution: "\u7EC4\u4EF6\u6267\u884C\u72B6\u6001",
237
+ configuredHookNotRun: "Evaluation Stack \u5DF2\u914D\u7F6E\u8BE5\u4E1A\u52A1\u7EC4\u4EF6\uFF0C\u4F46\u672C\u6B21\u5E76\u672A\u6267\u884C\uFF1B\u5F53\u524D\u5185\u5BB9\u7531\u63D2\u4EF6\u5185\u7F6E\u786E\u5B9A\u6027 fallback \u751F\u6210\u3002",
238
+ configuredHookRun: "\u672C\u6B21\u6267\u884C\u4E86 Evaluation Stack \u914D\u7F6E\u7684\u4E1A\u52A1\u7EC4\u4EF6\u3002",
239
+ pluginFallback: "\u63D2\u4EF6\u5185\u7F6E fallback",
240
+ badcase: "Badcase"
116
241
  },
117
242
  en: {
118
243
  tab: "Harbor",
119
244
  settings: "Harbor Evolution",
120
- eyebrow: "HARBOR SELF-EVOLVING",
121
- heroTitle: "Make every Agent change evidence-based",
122
- heroBody: "Candidates freeze capabilities, Jobs preserve experiments, and the Promotion Gate admits only comparable, non-regressing versions.",
245
+ eyebrow: "EVALUATION WORKBENCH",
246
+ heroTitle: "See every Agent improvement\u2014and whether the score is trustworthy",
247
+ heroBody: "Harbor fixes the experiment boundary. Trial Lifecycle shows real execution, while Score Validity keeps infrastructure failures out of quality metrics.",
123
248
  refresh: "Refresh",
124
- refreshed: "Last refreshed",
125
- totalJobs: "Evaluation jobs",
126
- completedJobs: "Completed",
127
- activeJobs: "Active",
128
- failedJobs: "Failed",
129
- latestMetric: "Latest metric",
130
- jobs: "Recent Harbor Jobs",
131
- jobsHint: "Shows up to 50 recent jobs from stable evaluation-summary.json files.",
132
- emptyTitle: "No evaluation results yet",
133
- emptyBody: "Ask the official Skill to clarify the Candidate, Dataset, and Promotion Policy before starting the first Job.",
134
- startStep1: "1. Freeze Candidate",
135
- startStep2: "2. Run Harbor Job",
136
- startStep3: "3. Compare and promote",
249
+ jobs: "Evaluation jobs",
250
+ jobsHint: "Open a Job, then reach Trial evidence in at most one more interaction.",
251
+ empty: "No readable Harbor Jobs yet. Use the official Skill to clarify and initialize the project.",
252
+ completed: "Completed",
253
+ partial: "Completed with errors",
254
+ failed: "Read failed",
255
+ pending: "Queued",
256
+ running: "Running",
257
+ attention: "Needs review",
137
258
  candidate: "Candidate",
138
- context: "Evaluation context",
259
+ dataset: "Dataset",
260
+ integration: "Integration",
261
+ renderer: "Renderer",
262
+ judge: "Judge",
263
+ meta: "Evaluator meta-evaluation",
264
+ reporter: "Reporter",
265
+ optimizer: "Optimizer",
266
+ gate: "Gate",
267
+ context: "Context v2",
139
268
  trials: "Trials",
140
269
  exceptions: "Exceptions",
141
- metrics: "Metrics",
142
- pending: "Diving",
143
- completed: "Landed",
144
- partial: "Completed with exceptions",
145
- failed: "Storm",
146
- promote: "Promote",
147
- reject: "Reject",
148
- noMetrics: "No metrics",
149
- loading: "Reading Harbor routes\u2026",
150
- loadError: "Could not read Harbor status",
270
+ mode: "Mode",
271
+ close: "Close",
151
272
  retry: "Retry",
152
- doctorTitle: "Installation and runtime checks",
153
- doctorBody: "Checks the critical path from the DSH Plugin to the Harbor Runtime. Cordis Profile remains the configuration owner.",
154
- ready: "Ready to evaluate",
155
- attention: "Needs attention",
156
- projectRoot: "Project root",
157
- jobsDir: "Jobs directory",
158
- harbor: "Harbor CLI",
159
- harborDsh: "Promotion CLI",
160
- runtime: "Runtime contract",
161
- dshVersion: "DSH version",
162
- agentImport: "Agent entry",
163
- pluginImport: "Harbor plugin",
164
- skillGuide: "How to start",
165
- skillBody: "Say \u201Cuse the Harbor self-evolution Skill to initialize and evaluate my Agent\u201D. The Skill clarifies requirements before launching an expensive Job.",
166
- toolSnapshot: "Freeze Candidate",
167
- toolRun: "Run Harbor evaluation",
168
- toolResult: "Read evaluation result",
169
- toolCompare: "Run Promotion Gate",
170
- running: "Running",
171
- toolFailed: "Tool call failed",
172
- noResult: "No structured result could be parsed",
273
+ loading: "Loading\u2026",
274
+ noData: "No data",
275
+ currentStatus: "Current status",
276
+ score: "Quality score",
277
+ valid: "Score valid",
278
+ validScores: "Valid scores",
279
+ invalid: "Score invalid",
280
+ unavailable: "Unavailable",
281
+ validity: "Score Validity",
282
+ progress: "Progress",
283
+ health: "Health",
284
+ evidence: "Evidence",
285
+ capabilityUnavailable: "This historical Job did not produce this capability; available artifacts remain read-only.",
286
+ search: "Search Query / Trial",
287
+ all: "All",
288
+ previous: "Previous",
289
+ next: "Next",
290
+ datasetOrder: "Dataset order",
291
+ latest: "Latest completed",
292
+ lowest: "Lowest score",
293
+ errorsFirst: "Errors first",
294
+ findings: "Findings",
295
+ recommendations: "Recommendations",
296
+ output: "User-visible output",
297
+ criteria: "Criteria",
298
+ provenance: "Evidence provenance",
299
+ timing: "Timing",
300
+ audit: "Raw audit",
301
+ compare: "Regression comparison",
302
+ baseline: "Baseline Job",
303
+ comparable: "Comparable",
304
+ notComparable: "Not comparable",
305
+ improved: "Improved trials",
306
+ regressed: "Regressed trials",
307
+ explicitGate: "A read-only comparison never runs Gate. Run the deterministic Gate only with explicit authority.",
308
+ governance: "Evaluator governance",
309
+ governanceHint: "Read Rubric, Evaluator, Judge identity, and source. Semantic edits create a new identity and require a fresh baseline.",
310
+ artifacts: "Artifact Registry",
311
+ setupDoctor: "Installation and architecture checks",
312
+ setupHint: "The browser may only update files explicitly authorized by the Evaluator descriptor; it never rewrites a Candidate or launches evaluation automatically.",
313
+ stageNav: "Evaluation stages",
314
+ datasetTasks: "Evaluation tasks",
315
+ datasetSource: "Task source",
316
+ taskInstruction: "Task instruction",
317
+ instructionFile: "Instruction file",
318
+ snapshot: "Job snapshot",
319
+ historicalFallback: "Historical source fallback",
320
+ generatedOutput: "Generated output",
321
+ selectTrial: "Select Trial",
322
+ noRenderableOutput: "This Trial has no renderable page, document, or structured artifact. Publish the business result through Harbor artifacts.",
323
+ previewSource: "Output provenance",
324
+ pagePreview: "Page preview",
325
+ documentPreview: "Document preview",
326
+ structuredOutput: "Structured output",
327
+ rawOutput: "Raw output",
328
+ currentEvaluator: "Current evaluator",
329
+ evaluator: "Evaluator",
330
+ rubric: "Rubric",
331
+ judgeParameters: "Judge parameters",
332
+ scoringContract: "Scoring contract",
333
+ primaryMetric: "Primary metric",
334
+ metricSemantics: "Metric semantics",
335
+ sourceCode: "View source",
336
+ upgradeEvaluator: "How to upgrade the evaluator",
337
+ upgradeHint: "Evaluator upgrades change score semantics. Create a new identity, meta-evaluate it, then establish a fresh Agent baseline.",
338
+ copyPrompt: "Copy for Agent",
339
+ copied: "Copied",
340
+ freshBaseline: "Fresh baseline required",
341
+ metaEvaluation: "Meta-evaluation requirements",
342
+ evaluatorImplementation: "Evaluator implementation",
343
+ evaluatorKind: "Implementation kind",
344
+ evaluatorProtocol: "Interface protocol",
345
+ editableFiles: "Files you can modify",
346
+ openFile: "Open",
347
+ editingFile: "Editing",
348
+ editSource: "Edit the current file directly",
349
+ evaluatorVersion: "New Evaluator version",
350
+ stackVersion: "New Stack version",
351
+ saveEvaluator: "Save as new identity",
352
+ saving: "Saving\u2026",
353
+ saved: "Saved. Meta-evaluate it and establish a fresh Baseline next.",
354
+ reloadBeforeSave: "The source changed; reload before saving.",
355
+ noEvaluatorInterface: "This Stack has no harbor-dsh-evaluator/v1 interface, so safe UI editing is unavailable.",
356
+ editWarning: "Saving updates source and identities only. It never runs an evaluation or Gate.",
357
+ upgradeStep1: "Inspect the current Evaluator, Rubric, Judge, Contract, and representative false-positive or false-negative Trials.",
358
+ upgradeStep2: "Create a new evaluator identity, version, and source file; never overwrite the historical evaluator.",
359
+ upgradeStep3: "Meta-evaluate against independently maintained, provenance-bearing GT using ESF, SCE, RCR, latency, and cost as appropriate.",
360
+ upgradeStep4: "Update the Evaluation Stack identity and preview the Context v2 impact.",
361
+ upgradeStep5: "Establish a fresh Agent baseline under the new score semantics before comparing later Candidates.",
362
+ evaluatorPrompt: "Use evolve-agent-with-harbor to upgrade this evaluator. First inspect governance evidence, clarify GT source type, provenance, ownership, and target meta-metrics, then propose a new immutable evaluator identity and fresh-baseline plan. Do not edit files or run an evaluation until I approve the controlled change.",
363
+ queryTrial: "Task / Trial",
364
+ statusLabel: "Status",
365
+ attempt: "Attempt",
366
+ population: "Population",
367
+ experimentIdentity: "Fixed experiment identity",
368
+ experimentIdentityHint: "Candidate, Dataset, Evaluation Stack, and Runtime jointly define a reproducible and comparable experiment.",
369
+ immutableCandidateFiles: "Candidate contents",
370
+ file: "File",
371
+ size: "Size",
173
372
  digest: "Digest",
174
- version: "Version",
175
- job: "Job",
176
- decision: "Decision",
177
- reasons: "Gate reasons",
178
- comparable: "Same evaluation context",
179
- changed: "Candidate changed"
373
+ runtime: "Runtime",
374
+ evaluationStack: "Evaluation Stack",
375
+ integrationBoundary: "Execution and scoring boundary",
376
+ hardRequirements: "Required before a score is valid",
377
+ populationEvidence: "Population evidence",
378
+ metric: "Metric",
379
+ aggregate: "Aggregate",
380
+ coverage: "Valid coverage",
381
+ trialGroups: "Trial status groups",
382
+ controlledHypotheses: "Controlled optimization hypotheses",
383
+ rootCause: "Evidence points to",
384
+ affectedTrials: "Affected trials",
385
+ expectedEffect: "Expected metric effect",
386
+ mutationSurface: "Allowed mutation",
387
+ forbiddenSurface: "Forbidden mutation",
388
+ guardrails: "Guardrails",
389
+ rollback: "Rollback condition",
390
+ nextExperiment: "Next controlled experiment",
391
+ noHypotheses: "No controlled optimization hypothesis was generated for this Job.",
392
+ gateEvidence: "Executed promotion gate",
393
+ decision: "Gate result",
394
+ policy: "Gate policy",
395
+ eligible: "Gate prerequisites satisfied",
396
+ notEligible: "Gate prerequisites not satisfied",
397
+ metricDeltas: "Metric deltas",
398
+ newExceptions: "New exceptions",
399
+ artifactRegressions: "Artifact regressions",
400
+ reasons: "Gate evidence",
401
+ trialAssessments: "Per-Trial assessments",
402
+ trialAssessmentsHint: "Each row represents one business artifact. Select a task to compare the artifact with criterion scores, reasons, and evaluator recommendations side by side.",
403
+ overallScore: "Overall score",
404
+ artifact: "Assessed artifact",
405
+ assessmentReason: "Scoring reason",
406
+ assessmentRecommendation: "Recommendation",
407
+ assessmentDetails: "Assessment details",
408
+ noAssessmentReason: "The evaluator returned no scoring reason; this result should not enter valid aggregates.",
409
+ noAssessmentRecommendation: "The evaluator returned no recommendation; this result should not enter valid aggregates.",
410
+ evaluatorAdvice: "Evaluator recommendation",
411
+ reportPage: "Report page",
412
+ groundTruth: "Ground Truth",
413
+ groundTruthRequired: "Independent Ground Truth is required",
414
+ gtSource: "GT source",
415
+ gtProvenance: "Provenance",
416
+ gtCases: "GT cases",
417
+ gtBadcases: "Badcases",
418
+ gtKinds: "Allowed sources: human, programmatic, consensus, independently pinned model, or external standard. Versioning, provenance, and independence from the Candidate evaluator are mandatory.",
419
+ metaWorkflow: "Independent meta-evaluation flow",
420
+ metaWorkflowHint: "Evaluator is the Candidate; fixed artifacts plus GT form the Dataset; repeated observations produce ESF, SCE, and RCR.",
421
+ metaNext: "Next action",
422
+ disagreements: "Disagreements",
423
+ hookExecution: "Component execution",
424
+ configuredHookNotRun: "The Evaluation Stack configured this business component, but it did not run in this Job. The current content came from the plugin deterministic fallback.",
425
+ configuredHookRun: "The configured Evaluation Stack component executed in this Job.",
426
+ pluginFallback: "Plugin fallback",
427
+ badcase: "Badcase"
180
428
  }
181
429
  };
182
430
  var CSS = `
183
- .hse-root{--hse-blue:#2769ff;--hse-cyan:#3ed8ff;--hse-deep:#071d48;color:var(--dsw-alias-label-primary,#172033);height:100%;min-height:0;overflow:auto;background:var(--dsw-alias-bg-layer-1,#f5f8ff);font-family:inherit}
184
- .hse-page{width:min(1180px,calc(100% - 40px));margin:0 auto;padding:28px 0 56px}
185
- .hse-hero{position:relative;isolation:isolate;overflow:hidden;min-height:270px;border-radius:24px;padding:34px;color:#fff;background:#071d48 var(--hse-ocean) center/cover no-repeat;box-shadow:0 20px 60px rgba(4,27,74,.25)}
186
- .hse-hero:before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(90deg,rgba(3,19,53,.96) 0%,rgba(4,28,75,.83) 45%,rgba(5,33,82,.24) 78%,rgba(2,19,48,.12) 100%)}
187
- .hse-hero:after{content:"";position:absolute;width:340px;height:340px;left:-120px;bottom:-250px;border-radius:50%;border:1px solid rgba(98,222,255,.3);box-shadow:0 0 0 38px rgba(80,196,255,.06),0 0 0 84px rgba(80,196,255,.035)}
188
- .hse-hero-copy{position:relative;z-index:1;max-width:610px}
189
- .hse-eyebrow{display:flex;align-items:center;gap:9px;font-size:11px;font-weight:800;letter-spacing:.16em;color:#79e1ff}
190
- .hse-eyebrow:before{content:"";width:22px;height:2px;border-radius:2px;background:#53d6ff;box-shadow:0 0 12px #53d6ff}
191
- .hse-hero h1{margin:18px 0 12px;font-size:clamp(27px,4vw,44px);line-height:1.08;letter-spacing:-.035em;max-width:540px}
192
- .hse-hero p{margin:0;max-width:570px;color:rgba(235,247,255,.82);font-size:15px;line-height:1.75}
193
- .hse-refresh{position:absolute;z-index:2;top:24px;right:24px;display:inline-flex;align-items:center;gap:7px;border:1px solid rgba(255,255,255,.3);border-radius:999px;padding:8px 13px;background:rgba(3,21,55,.4);color:#fff;font:inherit;font-size:12px;cursor:pointer;backdrop-filter:blur(10px);transition:.18s ease}
194
- .hse-refresh:hover{background:rgba(34,112,235,.55);transform:translateY(-1px)}
195
- .hse-refresh:disabled{opacity:.55;cursor:wait}
196
- .hse-stats{position:relative;z-index:2;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px;margin-top:30px;max-width:670px}
197
- .hse-stat{min-height:64px;padding:12px 14px;border:1px solid rgba(255,255,255,.16);border-radius:14px;background:rgba(4,27,65,.42);backdrop-filter:blur(8px)}
198
- .hse-stat span{display:block;font-size:11px;color:rgba(225,243,255,.68)}
199
- .hse-stat strong{display:block;margin-top:4px;font-size:22px;line-height:1.1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
200
- .hse-section{margin-top:28px}
201
- .hse-section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:13px}
202
- .hse-section h2,.hse-doctor h2{margin:0;font-size:18px;letter-spacing:-.01em}
203
- .hse-section-head p,.hse-doctor-intro{margin:4px 0 0;color:var(--dsw-alias-label-secondary,#67728a);font-size:12px;line-height:1.55}
204
- .hse-job-list{display:grid;gap:12px}
205
- .hse-job{position:relative;padding:18px;border:1px solid var(--dsw-alias-border-l1,#dde5f2);border-radius:17px;background:var(--dsw-alias-bg-layer-2,#fff);box-shadow:var(--dsw-shadow-lv1,0 5px 18px rgba(27,54,93,.06));overflow:hidden}
206
- .hse-job:before{content:"";position:absolute;inset:0 auto 0 0;width:3px;background:#5e8cff}
207
- .hse-job[data-status="completed"]:before{background:#23ba83}.hse-job[data-status="partial"]:before{background:#f1a23c}.hse-job[data-status="failed"]:before{background:#ed5b6c}
208
- .hse-job-top{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
209
- .hse-job-title{min-width:0}.hse-job-title strong{display:block;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.hse-job-title small{display:block;margin-top:5px;color:var(--dsw-alias-label-secondary,#748096);font-size:11px}
210
- .hse-status{flex:none;display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:5px 9px;background:rgba(39,105,255,.1);color:#2769e8;font-size:11px;font-weight:700}
211
- .hse-status:before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor;box-shadow:0 0 0 3px currentColor;opacity:.7}
212
- .hse-status[data-status="completed"]{color:#12835d;background:rgba(35,186,131,.11)}.hse-status[data-status="partial"]{color:#b36a08;background:rgba(241,162,60,.13)}.hse-status[data-status="failed"]{color:#ca3145;background:rgba(237,91,108,.12)}
213
- .hse-job-meta{display:grid;grid-template-columns:1.4fr 1.4fr .55fr .55fr;gap:8px;margin-top:15px}
214
- .hse-meta{min-width:0;padding:9px 10px;border-radius:10px;background:var(--dsw-alias-bg-layer-1,#f5f8fc)}.hse-meta span{display:block;color:var(--dsw-alias-label-secondary,#748096);font-size:10px}.hse-meta code,.hse-meta strong{display:block;margin-top:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:11px;color:inherit}
215
- .hse-metrics{display:flex;flex-wrap:wrap;gap:7px;margin-top:11px}.hse-metric{display:inline-flex;gap:6px;align-items:center;border:1px solid var(--dsw-alias-border-l1,#dde5f2);border-radius:8px;padding:6px 8px;font-size:11px}.hse-metric b{color:#2769e8}
216
- .hse-promotion{margin-top:11px;padding:10px 12px;border-radius:10px;background:rgba(39,105,255,.07);font-size:11px}.hse-promotion[data-decision="PROMOTE"]{background:rgba(35,186,131,.1);color:#08734e}.hse-promotion[data-decision="REJECT"]{background:rgba(237,91,108,.09);color:#a92135}.hse-promotion strong{margin-right:8px}
217
- .hse-empty,.hse-error{padding:34px;border:1px dashed var(--dsw-alias-border-l1,#cfd9e8);border-radius:18px;text-align:center;background:var(--dsw-alias-bg-layer-2,#fff)}.hse-empty h3,.hse-error h3{margin:10px 0 7px}.hse-empty p,.hse-error p{max-width:600px;margin:0 auto;color:var(--dsw-alias-label-secondary,#748096);font-size:13px;line-height:1.6}
218
- .hse-steps{display:flex;justify-content:center;flex-wrap:wrap;gap:8px;margin-top:19px}.hse-steps span{padding:8px 11px;border-radius:9px;background:rgba(39,105,255,.08);color:#2769e8;font-size:11px;font-weight:700}
219
- .hse-spinner{width:28px;height:28px;margin:0 auto 12px;border:3px solid rgba(39,105,255,.14);border-top-color:#2769ff;border-radius:50%;animation:hse-spin .8s linear infinite}@keyframes hse-spin{to{transform:rotate(360deg)}}
220
- .hse-button{margin-top:13px;border:0;border-radius:9px;padding:8px 13px;background:#2769ff;color:#fff;font:inherit;font-size:12px;cursor:pointer}
221
- .hse-doctor{width:min(860px,calc(100% - 40px));margin:0 auto;padding:30px 0 54px}
222
- .hse-doctor-banner{display:flex;align-items:center;justify-content:space-between;gap:20px;margin:20px 0;padding:17px 19px;border-radius:15px;background:linear-gradient(135deg,rgba(39,105,255,.12),rgba(62,216,255,.08));border:1px solid rgba(39,105,255,.18)}
223
- .hse-doctor-banner strong{font-size:14px}.hse-doctor-banner span{font-size:12px;color:var(--dsw-alias-label-secondary,#748096)}
224
- .hse-checks{display:grid;grid-template-columns:1fr 1fr;gap:10px}.hse-check{display:flex;align-items:center;gap:11px;padding:13px;border:1px solid var(--dsw-alias-border-l1,#dde5f2);border-radius:12px;background:var(--dsw-alias-bg-layer-2,#fff)}
225
- .hse-check-dot{width:9px;height:9px;border-radius:50%;background:#27bb83;box-shadow:0 0 0 4px rgba(39,187,131,.12)}.hse-check[data-status="warning"] .hse-check-dot{background:#e6a036;box-shadow:0 0 0 4px rgba(230,160,54,.12)}.hse-check[data-status="error"] .hse-check-dot{background:#ed5b6c;box-shadow:0 0 0 4px rgba(237,91,108,.12)}
226
- .hse-check div{min-width:0}.hse-check strong,.hse-check small{display:block}.hse-check strong{font-size:12px}.hse-check small{margin-top:3px;color:var(--dsw-alias-label-secondary,#748096);font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
227
- .hse-contract{margin-top:20px;padding:18px;border:1px solid var(--dsw-alias-border-l1,#dde5f2);border-radius:15px;background:var(--dsw-alias-bg-layer-2,#fff)}.hse-contract h3{margin:0 0 12px;font-size:14px}.hse-contract dl{display:grid;grid-template-columns:130px minmax(0,1fr);gap:8px;margin:0;font-size:11px}.hse-contract dt{color:var(--dsw-alias-label-secondary,#748096)}.hse-contract dd{margin:0;overflow-wrap:anywhere}.hse-contract code{font-size:10px}
228
- .hse-skill-guide{margin-top:20px;padding:18px;border-radius:15px;color:#dff7ff;background:linear-gradient(135deg,#08275b,#0b4381);box-shadow:0 14px 35px rgba(5,39,91,.15)}.hse-skill-guide h3{margin:0 0 7px;font-size:14px}.hse-skill-guide p{margin:0;color:rgba(223,247,255,.78);font-size:12px;line-height:1.65}
229
- .hse-tool{border:1px solid var(--dsw-alias-border-l1,#dce4f1);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff);overflow:hidden}.hse-tool-head{display:flex;align-items:center;gap:10px;width:100%;padding:11px 13px;border:0;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.hse-tool-icon{display:grid;place-items:center;width:27px;height:27px;border-radius:9px;color:#2769ff;background:rgba(39,105,255,.1)}.hse-tool-title{font-size:12px;font-weight:700}.hse-tool-summary{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-secondary,#748096);font-size:11px}.hse-tool-state{margin-left:auto;font-size:10px;color:#238260}.hse-tool[data-state="running"] .hse-tool-state{color:#2769ff}.hse-tool[data-state="error"] .hse-tool-state{color:#cf3549}.hse-tool-body{display:grid;gap:8px;padding:0 13px 13px}.hse-tool-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px}.hse-tool-field{min-width:0;padding:8px 9px;border-radius:9px;background:var(--dsw-alias-bg-layer-1,#f5f8fc)}.hse-tool-field span,.hse-tool-field strong,.hse-tool-field code{display:block}.hse-tool-field span{font-size:9px;color:var(--dsw-alias-label-secondary,#748096)}.hse-tool-field strong,.hse-tool-field code{margin-top:3px;font-size:10px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hse-reasons{margin:0;padding-left:18px;color:var(--dsw-alias-label-secondary,#748096);font-size:10px;line-height:1.5}
230
- @media(max-width:760px){.hse-page,.hse-doctor{width:min(100% - 24px,1180px);padding-top:12px}.hse-hero{padding:26px 20px;min-height:310px}.hse-refresh{top:14px;right:14px}.hse-hero-copy{padding-top:28px}.hse-stats{grid-template-columns:repeat(2,1fr)}.hse-job-meta{grid-template-columns:1fr 1fr}.hse-checks{grid-template-columns:1fr}.hse-contract dl{grid-template-columns:1fr}.hse-contract dd{margin-bottom:5px}}
231
- @media(prefers-reduced-motion:reduce){.hse-spinner{animation:none}.hse-refresh{transition:none}}
431
+ .hse-root{--ocean-950:#03152f;--ocean-800:#07366f;--ocean-600:#1464c8;--ocean-300:#75b7ff;--foam-50:#f4fbff;--whale-500:#2875ff;--coral-500:#ee6478;--amber-500:#e4a23b;--kelp-500:#1f9b72;height:100%;min-height:0;overflow:auto;color:var(--dsw-alias-label-primary,#142038);background:var(--dsw-alias-bg-layer-1,#f2f7fc);font-family:inherit}.hse-page{width:min(1320px,calc(100% - 36px));margin:auto;padding:24px 0 56px}
432
+ .hse-hero{position:relative;isolation:isolate;overflow:hidden;min-height:225px;padding:32px;border-radius:24px;color:#fff;background:var(--ocean-950) var(--ocean-image) center/cover no-repeat;box-shadow:0 22px 65px #03152f38}.hse-hero:before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(90deg,#02132fea,#062b62d6 55%,#0e6dc42e)}.hse-hero:after{content:"";position:absolute;width:220px;height:220px;right:8%;bottom:-170px;border:1px solid #8be9ff66;border-radius:50%;box-shadow:0 0 0 28px #68dfff0b,0 0 0 60px #68dfff08;animation:hse-ripple 5s ease-out infinite}.hse-hero h1{max-width:780px;margin:15px 0 10px;font-size:clamp(28px,4vw,46px);line-height:1.08;letter-spacing:-.04em}.hse-hero p{max-width:760px;margin:0;color:#d9eeff;font-size:14px;line-height:1.75}.hse-eyebrow{color:#86e8ff;font-size:11px;font-weight:800;letter-spacing:.17em}.hse-whale{margin-right:8px;font-size:17px}.hse-refresh{position:absolute;right:22px;top:22px;padding:8px 13px;border:1px solid #ffffff52;border-radius:999px;color:#fff;background:#06245eb8;cursor:pointer}.hse-stats{display:flex;gap:9px;margin-top:24px;flex-wrap:wrap}.hse-stat{min-width:130px;padding:11px 13px;border:1px solid #ffffff29;border-radius:13px;background:#031a41a8;backdrop-filter:blur(8px)}.hse-stat span{display:block;color:#cde7fb;font-size:10px}.hse-stat b{display:block;margin-top:4px;font-size:20px}.hse-head{margin:28px 0 12px}.hse-head h2{margin:0;font-size:18px}.hse-head p{margin:4px 0 0;color:#728097;font-size:12px}
433
+ .hse-list{display:grid;gap:10px}.hse-job{display:block;width:100%;padding:0;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:16px;color:inherit;background:var(--dsw-alias-bg-layer-2,#fff);text-align:left;cursor:pointer;overflow:hidden;box-shadow:0 5px 18px #1736600d;transition:.18s ease}.hse-job:hover,.hse-job:focus-visible{border-color:var(--ocean-300);transform:translateY(-1px);outline:3px solid #2875ff20}.hse-job-body{padding:16px 18px}.hse-job-top{display:flex;justify-content:space-between;gap:14px}.hse-job-title{min-width:0}.hse-job-title strong{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px}.hse-job-title small{display:block;margin-top:4px;color:#7b879c;font-size:10px}.hse-status{flex:none;padding:5px 9px;border-radius:999px;color:#126d50;background:#23ba8318;font-size:10px;font-weight:700}.hse-status:before{content:"\u2713 ";}.hse-status[data-status=running],.hse-status[data-status=pending]{color:#245dcc;background:#2875ff18}.hse-status[data-status=running]:before{content:"\u25CF ";animation:hse-pulse 1.6s ease-in-out infinite}.hse-status[data-status=partial],.hse-status[data-status=attention]{color:#8e5b0c;background:#e4a23b1b}.hse-status[data-status=partial]:before,.hse-status[data-status=attention]:before{content:"\u25B3 "}.hse-status[data-status=failed]{color:#b52f45;background:#ee647818}.hse-status[data-status=failed]:before{content:"\xD7 "}.hse-meta-grid{display:grid;grid-template-columns:1.35fr 1fr .9fr .65fr .75fr .75fr;gap:7px;margin-top:13px}.hse-meta{min-width:0;padding:8px 9px;border-radius:9px;background:var(--dsw-alias-bg-layer-1,#f3f7fb)}.hse-meta span{display:block;color:#7b879c;font-size:9px}.hse-meta b,.hse-meta code{display:block;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:10px}.hse-progress{height:5px;margin-top:11px;border-radius:99px;background:#dbe8f5;overflow:hidden}.hse-progress i{display:block;height:100%;background:linear-gradient(90deg,var(--ocean-600),#54d7f5);transition:width .3s}.hse-metrics{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}.hse-pill{padding:5px 7px;border:1px solid var(--dsw-alias-border-l1,#dce4f0);border-radius:7px;font-size:10px}.hse-pill b{margin-left:5px;color:var(--ocean-600)}
434
+ .hse-empty,.hse-error{padding:34px;border:1px dashed #c4d3e5;border-radius:16px;text-align:center;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-secondary,#728097);font-size:12px}.hse-spin{width:25px;height:25px;margin:0 auto 10px;border:3px solid #2875ff22;border-top-color:var(--whale-500);border-radius:50%;animation:hse-spin .8s linear infinite}.hse-button,.hse-close{border:0;border-radius:9px;padding:8px 11px;color:#fff;background:var(--whale-500);cursor:pointer}.hse-overlay{position:fixed;inset:0;z-index:1000;display:flex;justify-content:flex-end;background:#03152f8c;backdrop-filter:blur(3px)}.hse-drawer{width:min(1180px,96vw);height:100%;overflow:auto;background:var(--dsw-alias-bg-layer-1,#f2f7fc);box-shadow:-24px 0 70px #03152f52}.hse-drawer-head{position:sticky;top:0;z-index:5;display:flex;justify-content:space-between;gap:15px;padding:16px 20px;border-bottom:1px solid var(--dsw-alias-border-l1,#dce4f0);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#fff) 94%,transparent);backdrop-filter:blur(12px)}.hse-drawer-head h2{margin:0;font-size:18px}.hse-drawer-head p{margin:5px 0 0;color:var(--dsw-alias-label-secondary,#748096);font-size:10px}.hse-close{align-self:flex-start;background:var(--ocean-950)}.hse-workbench{padding:14px 20px 48px}.hse-stage-nav{position:sticky;top:67px;z-index:4;display:grid;grid-template-columns:repeat(8,minmax(88px,1fr));gap:5px;margin:-1px -1px 14px;padding:8px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:13px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#fff) 94%,transparent);backdrop-filter:blur(10px);overflow:auto}.hse-stage-nav button{padding:9px 7px;border:0;border-radius:8px;color:var(--dsw-alias-label-secondary,#52627b);background:transparent;font:inherit;font-size:10px;cursor:pointer;white-space:nowrap}.hse-stage-nav button[data-active=true]{color:#fff;background:var(--ocean-600)}.hse-stage-nav button:focus-visible{outline:3px solid #2875ff2f}.hse-capability{margin-bottom:12px;padding:10px 12px;border-left:3px solid var(--amber-500);border-radius:8px;background:#e4a23b14;color:var(--dsw-alias-label-primary,#75500f);font-size:11px}.hse-section{margin-bottom:13px;padding:16px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:14px;background:var(--dsw-alias-bg-layer-2,#fff)}.hse-section h3{margin:0 0 11px;font-size:14px}.hse-kpis{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px}.hse-kpi{padding:11px;border-radius:10px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1,#edf7ff) 88%,var(--ocean-600) 12%)}.hse-kpi span{display:block;color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-kpi b{display:block;margin-top:4px;font-size:17px}.hse-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px}.hse-card{min-width:0;padding:11px;border-radius:10px;background:var(--dsw-alias-bg-layer-1,#f3f7fb)}.hse-card span,.hse-card b,.hse-card code{display:block}.hse-card span{color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-card b,.hse-card code{margin-top:4px;overflow-wrap:anywhere;font-size:10px}.hse-valid{color:var(--kelp-500)}.hse-invalid{color:#bd3148}.hse-muted{color:var(--dsw-alias-label-secondary,#75839a)}.hse-findings{display:grid;gap:6px}.hse-finding{padding:9px 10px;border-left:3px solid var(--ocean-300);border-radius:7px;background:#2875ff0c;font-size:10px}.hse-finding[data-level=error]{border-color:var(--coral-500);background:#ee64780d}.hse-finding[data-level=warning]{border-color:var(--amber-500);background:#e4a23b0d}.hse-components{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px}.hse-component{padding:10px;border-radius:9px;background:#0b4c9c12}.hse-component span{display:block;color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-component b,.hse-component code{display:block;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:9px}
435
+ .hse-trial-layout{display:grid;grid-template-columns:minmax(380px,1fr) minmax(360px,.9fr);gap:10px;align-items:start}.hse-trial-list,.hse-trial-detail{min-width:0}.hse-trial-tools{display:grid;grid-template-columns:minmax(150px,1fr) auto auto auto;gap:6px;margin-bottom:9px}.hse-input,.hse-select{min-width:0;padding:8px 9px;border:1px solid #c8d6e7;border-radius:8px;color:inherit;background:transparent;font:inherit;font-size:10px}.hse-table-wrap{overflow:auto}.hse-table{width:100%;border-collapse:collapse;font-size:10px}.hse-table th,.hse-table td{padding:8px;border-bottom:1px solid #e2eaf3;text-align:left;white-space:nowrap}.hse-table button{border:0;color:var(--ocean-600);background:none;cursor:pointer;font:inherit}.hse-table tr[data-selected=true]{background:#2875ff0c}.hse-pager{display:flex;justify-content:flex-end;align-items:center;gap:8px;margin-top:9px;font-size:10px}.hse-pager button{padding:5px 8px;border:1px solid #c8d6e7;border-radius:7px;background:transparent;color:inherit;cursor:pointer}.hse-trial-detail{position:sticky;top:132px;max-height:calc(100vh - 160px);overflow:auto;padding:14px;border-radius:12px;color:#dcecff;background:var(--ocean-950)}.hse-trial-score{display:flex;justify-content:space-between;gap:12px;padding-bottom:12px;border-bottom:1px solid #ffffff1f}.hse-trial-score b{font-size:25px}.hse-trial-score span{font-size:10px}.hse-detail-group{padding:11px 0;border-bottom:1px solid #ffffff16}.hse-detail-group h4{margin:0 0 7px;color:#8fe8ff;font-size:10px;text-transform:uppercase;letter-spacing:.08em}.hse-detail-group pre{max-height:280px;overflow:auto;margin:0;white-space:pre-wrap;word-break:break-word;font-size:9px;line-height:1.55}.hse-detail-group ul{margin:0;padding-left:17px;font-size:10px;line-height:1.6}.hse-criteria{display:grid;gap:5px}.hse-criterion{display:flex;justify-content:space-between;gap:8px;padding:7px;border-radius:6px;background:#ffffff0b;font-size:10px}.hse-provenance{display:flex;gap:5px;flex-wrap:wrap}.hse-provenance span{padding:5px 7px;border:1px solid #70cfff4a;border-radius:999px;font-size:9px}.hse-audit summary{cursor:pointer;font-size:11px;font-weight:700}.hse-audit pre,.hse-source{max-height:360px;overflow:auto;white-space:pre-wrap;word-break:break-word;font-size:9px;line-height:1.55}.hse-compare-select{display:flex;gap:7px;margin-bottom:10px}.hse-compare-select select{flex:1}.hse-delta{font-variant-numeric:tabular-nums}.hse-delta[data-positive=true]{color:var(--kelp-500)}.hse-delta[data-positive=false]{color:var(--coral-500)}.hse-source{padding:10px;border-radius:8px;color:#d9edff;background:var(--ocean-950)}.hse-settings{width:min(850px,calc(100% - 32px));margin:auto;padding:28px 0}.hse-checks{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px;margin-top:16px}.hse-check{padding:12px;border:1px solid #dce4f0;border-radius:10px;background:var(--dsw-alias-bg-layer-2,#fff)}.hse-check b,.hse-check small{display:block}.hse-check small{margin-top:4px;color:#748096}.hse-tool{border:1px solid #dce4f0;border-radius:11px;background:var(--dsw-alias-bg-layer-2,#fff);overflow:hidden}.hse-tool button{display:flex;gap:8px;width:100%;padding:10px;border:0;color:inherit;background:transparent;text-align:left;cursor:pointer}.hse-tool strong{font-size:11px}.hse-tool small{margin-left:auto}.hse-tool pre{max-height:260px;overflow:auto;margin:0;padding:11px;border-top:1px solid #e3e9f1;white-space:pre-wrap;font-size:9px}
436
+ .hse-task-list{display:grid;gap:10px}.hse-task{border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:12px;background:var(--dsw-alias-bg-layer-1,#f3f7fb);overflow:hidden}.hse-task summary{display:flex;align-items:center;gap:9px;padding:12px 14px;cursor:pointer;font-size:11px;font-weight:700}.hse-task summary span{margin-left:auto;color:var(--dsw-alias-label-secondary,#748096);font-size:9px;font-weight:400}.hse-task-body{padding:0 14px 14px}.hse-instruction{min-height:80px;margin:0;padding:15px;border-radius:10px;color:#e3f3ff;background:linear-gradient(145deg,#03152f,#07366f);white-space:pre-wrap;word-break:break-word;font:inherit;font-size:12px;line-height:1.75}.hse-inline-meta{display:flex;gap:7px;flex-wrap:wrap;margin:10px 0 0;color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-output-layout{display:grid;grid-template-columns:260px minmax(0,1fr);gap:10px;align-items:start}.hse-output-list{display:grid;gap:6px}.hse-output-item{width:100%;padding:10px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:9px;color:inherit;background:var(--dsw-alias-bg-layer-1,#f3f7fb);text-align:left;cursor:pointer}.hse-output-item[data-active=true]{border-color:var(--ocean-300);background:#2875ff16}.hse-output-item b,.hse-output-item span{display:block}.hse-output-item span{margin-top:3px;color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-preview{min-width:0;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:12px;overflow:hidden}.hse-preview-head{display:flex;justify-content:space-between;gap:12px;padding:12px 14px;background:var(--dsw-alias-bg-layer-1,#f3f7fb)}.hse-preview-head b,.hse-preview-head span{display:block}.hse-preview-head span{margin-top:3px;color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-document{min-height:210px;padding:22px;background:var(--dsw-alias-bg-layer-2,#fff);font-size:13px;line-height:1.8}.hse-document pre{margin:0;white-space:pre-wrap;word-break:break-word;font:inherit}.hse-document h4{margin:0 0 12px;font-size:17px}.hse-page-frame{display:block;width:100%;height:520px;border:0;background:#fff}.hse-output-structured{max-height:520px;overflow:auto;margin:0;padding:16px;color:#dcecff;background:var(--ocean-950);white-space:pre-wrap;word-break:break-word;font-size:10px}.hse-preview-empty{padding:60px 20px;text-align:center;color:var(--dsw-alias-label-secondary,#748096)}.hse-governance-id{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.hse-source-details{margin-top:9px;border-top:1px solid var(--dsw-alias-border-l1,#d7e2ef);padding-top:9px}.hse-source-details summary{cursor:pointer;font-size:10px;font-weight:700}.hse-upgrade{border-color:#2875ff55;background:linear-gradient(145deg,#2875ff0f,#44d9ff08)}.hse-upgrade ol{margin:10px 0;padding-left:20px;font-size:11px;line-height:1.75}.hse-prompt{margin-top:10px;padding:12px;border-radius:9px;color:#dcecff;background:var(--ocean-950);white-space:pre-wrap;font-size:10px;line-height:1.6}.hse-prompt-actions{display:flex;justify-content:flex-end;margin-top:8px}.hse-editor-head{display:flex;justify-content:space-between;gap:10px;align-items:start}.hse-editor-tabs{display:flex;gap:6px;flex-wrap:wrap;margin:12px 0 8px}.hse-editor-tab{display:grid;gap:2px;padding:8px 10px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:8px;color:inherit;background:transparent;text-align:left;cursor:pointer}.hse-editor-tab b{font-size:10px}.hse-editor-tab span{color:var(--dsw-alias-label-secondary,#748096);font-size:8px}.hse-editor-tab[data-active=true]{border-color:var(--ocean-600);color:#fff;background:var(--ocean-600)}.hse-editor-tab[data-active=true] span{color:#dcecff}.hse-editor-current{display:grid;gap:3px;margin:8px 0;padding:9px 11px;border-left:3px solid var(--ocean-600);border-radius:8px;background:var(--dsw-alias-bg-layer-1,#f3f7fb)}.hse-editor-current span{color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-editor-current b{font-size:11px}.hse-editor-current code{overflow-wrap:anywhere;font-size:9px}.hse-editor{display:block;width:100%;min-height:360px;box-sizing:border-box;padding:14px;border:1px solid #1f73ca;border-radius:10px;color:#dcecff;background:var(--ocean-950);resize:vertical;font:11px/1.55 ui-monospace,SFMono-Regular,Menlo,monospace}.hse-editor-versions{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:9px}.hse-editor-actions{display:flex;justify-content:space-between;gap:10px;align-items:center;margin-top:9px}.hse-editor-actions p{margin:0;font-size:10px}.hse-editor-actions button:disabled{opacity:.45;cursor:not-allowed}.hse-editor-error{color:#bd3148}.hse-editor-success{color:var(--kelp-500)}
437
+ .hse-identity-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.hse-evidence-table{width:100%;border-collapse:collapse;font-size:10px}.hse-evidence-table th,.hse-evidence-table td{padding:9px;border-bottom:1px solid var(--dsw-alias-border-l1,#dce4f0);text-align:left;vertical-align:top}.hse-evidence-table th{color:var(--dsw-alias-label-secondary,#748096);font-weight:500}.hse-evidence-table code{overflow-wrap:anywhere}.hse-chip-list{display:flex;gap:6px;flex-wrap:wrap}.hse-chip-list span{padding:6px 8px;border-radius:999px;background:#2875ff12;font-size:9px}.hse-hypotheses{display:grid;gap:10px}.hse-hypothesis{padding:14px;border:1px solid #2875ff3d;border-radius:12px;background:linear-gradient(145deg,#2875ff0c,#44d9ff05)}.hse-hypothesis h4{margin:0 0 10px;font-size:13px}.hse-hypothesis dl{display:grid;grid-template-columns:150px minmax(0,1fr);gap:8px 12px;margin:0;font-size:10px}.hse-hypothesis dt{color:var(--dsw-alias-label-secondary,#748096)}.hse-hypothesis dd{margin:0;overflow-wrap:anywhere}.hse-gate-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}.hse-decision{padding:8px 12px;border-radius:999px;color:#126d50;background:#23ba8318;font-weight:800}.hse-decision[data-pass=false]{color:#b52f45;background:#ee647818}
438
+ .hse-report-table button{border:0;color:var(--ocean-600);background:none;text-align:left;cursor:pointer;font:inherit}.hse-report-table tr[data-selected=true]{background:#2875ff10}.hse-report-score{font-size:15px;font-weight:800}.hse-report-score[data-valid=false]{color:var(--coral-500)}.hse-report-detail{margin-top:12px;border:1px solid #2875ff40;border-radius:13px;overflow:hidden}.hse-report-detail-head{display:flex;justify-content:space-between;gap:12px;padding:14px 16px;background:linear-gradient(145deg,#2875ff14,#44d9ff08)}.hse-report-detail-head h4{margin:0;font-size:14px}.hse-report-detail-head span,.hse-report-detail-head code{display:block;margin-top:4px;color:var(--dsw-alias-label-secondary,#748096);font-size:9px}.hse-report-detail-head b{font-size:25px}.hse-report-criteria{display:grid;gap:9px;padding:14px}.hse-report-criterion{padding:12px;border-radius:10px;background:var(--dsw-alias-bg-layer-1,#f3f7fb)}.hse-report-criterion header{display:flex;justify-content:space-between;gap:10px}.hse-report-criterion header b:last-child{font-size:17px}.hse-report-criterion dl{display:grid;grid-template-columns:92px minmax(0,1fr);gap:8px 10px;margin:10px 0 0;font-size:10px;line-height:1.55}.hse-report-criterion dt{color:var(--dsw-alias-label-secondary,#748096)}.hse-report-criterion dd{margin:0;overflow-wrap:anywhere}.hse-report-recommendation{color:var(--ocean-600)}
439
+ .hse-stage-nav{grid-template-columns:repeat(9,minmax(88px,1fr))}.hse-report-compare{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;padding:14px;align-items:start}.hse-report-compare .hse-report-criteria{padding:0}.hse-meta-flow{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.hse-meta-flow div{position:relative;padding:13px;border-radius:10px;background:#2875ff0f;font-size:10px}.hse-meta-flow div:not(:last-child):after{content:'\u2192';position:absolute;right:-8px;top:50%;z-index:1;color:var(--ocean-600);font-weight:800}.hse-badcase{color:#b52f45;background:#ee647817!important}.hse-hook-state{margin-bottom:12px;padding:11px 13px;border-left:3px solid var(--ocean-600);border-radius:8px;background:#2875ff0d;font-size:10px}.hse-hook-state[data-executed=false]{border-color:var(--amber-500);background:#e4a23b12}
440
+ @keyframes hse-spin{to{transform:rotate(360deg)}}@keyframes hse-pulse{50%{opacity:.38}}@keyframes hse-ripple{0%{transform:scale(.75);opacity:.4}70%,100%{transform:scale(1.12);opacity:0}}
441
+ @media(max-width:900px){.hse-page{width:calc(100% - 20px)}.hse-meta-grid,.hse-kpis,.hse-identity-grid{grid-template-columns:repeat(2,1fr)}.hse-trial-layout,.hse-output-layout{grid-template-columns:1fr}.hse-trial-detail{position:static;max-height:none}.hse-components,.hse-governance-id{grid-template-columns:repeat(2,1fr)}.hse-drawer{width:100vw}.hse-workbench{padding:12px}.hse-stage-nav{top:62px}.hse-trial-tools{grid-template-columns:1fr 1fr}.hse-grid,.hse-checks{grid-template-columns:1fr}.hse-hypothesis dl{grid-template-columns:1fr}}
442
+ @media(prefers-reduced-motion:reduce){.hse-spin,.hse-status:before,.hse-hero:after{animation:none}.hse-job{transition:none}.hse-job:hover{transform:none}}
443
+ @media(max-width:900px){.hse-report-compare,.hse-meta-flow{grid-template-columns:1fr}.hse-meta-flow div:after{display:none}}
232
444
  `;
233
445
  function installStyles() {
234
446
  const id = "dsh-harbor-evolution/client";
235
447
  if (document.querySelector(`style[data-plugin-css="${id}"]`)) return () => {
236
448
  };
237
449
  const style = document.createElement("style");
238
- style.dataset.plugin = "dsh-harbor-evolution";
239
450
  style.dataset.pluginCss = id;
240
451
  style.textContent = CSS;
241
452
  document.head.appendChild(style);
242
453
  return () => style.remove();
243
454
  }
244
455
  function isRecord(value) {
245
- return typeof value === "object" && value !== null && !Array.isArray(value);
456
+ return value && typeof value === "object" && !Array.isArray(value);
246
457
  }
247
- function blockText(block) {
248
- if (!isRecord(block) || !("kind" in block) || !Array.isArray(block.content)) return "";
249
- return block.content.filter((entry) => entry?.type === "text").map((entry) => entry.text).join("\n");
458
+ function format(value) {
459
+ return typeof value === "number" ? value.toFixed(4).replace(/0+$/, "").replace(/\.$/, "") : String(value ?? "\u2014");
250
460
  }
251
- function decodeToolResult(block) {
252
- if (!isRecord(block) || !("kind" in block) || block.isError) return void 0;
253
- if (isRecord(block.meta)) return block.meta;
254
- const text = blockText(block).trim();
255
- if (!text) return void 0;
256
- try {
257
- const parsed = JSON.parse(text);
258
- return isRecord(parsed) ? parsed : void 0;
259
- } catch {
260
- return void 0;
261
- }
461
+ function short(value) {
462
+ return typeof value === "string" && value.length > 25 ? `${value.slice(0, 17)}\u2026${value.slice(-6)}` : value ?? "\u2014";
463
+ }
464
+ function pretty(value) {
465
+ return JSON.stringify(value, null, 2);
466
+ }
467
+ function gateReasonText(value) {
468
+ if (!isRecord(value)) return String(value ?? "\u2014");
469
+ return [value.code, value.message].filter(Boolean).join(" \xB7 ") || pretty(value);
470
+ }
471
+ async function api(route, params = {}) {
472
+ const query = new URLSearchParams(Object.entries(params).filter(([, value]) => value !== void 0 && value !== ""));
473
+ const response = await fetch(`${API}/${route}${query.size ? `?${query}` : ""}`, { credentials: "same-origin", cache: "no-store" });
474
+ const body = await response.json();
475
+ if (!response.ok || !body?.ok) throw new Error(body?.error?.message ?? `HTTP ${response.status}`);
476
+ return body.value;
262
477
  }
263
- async function fetchDashboard() {
264
- const response = await fetch(ROUTE, { credentials: "same-origin", cache: "no-store" });
478
+ async function mutate(route, value) {
479
+ const response = await fetch(`${API}/${route}`, {
480
+ method: "POST",
481
+ credentials: "same-origin",
482
+ cache: "no-store",
483
+ headers: { "content-type": "application/json" },
484
+ body: JSON.stringify(value)
485
+ });
265
486
  const body = await response.json();
266
487
  if (!response.ok || !body?.ok) throw new Error(body?.error?.message ?? `HTTP ${response.status}`);
267
488
  return body.value;
268
489
  }
490
+ function nextVersion(value) {
491
+ const match = String(value ?? "").match(/^(\d+)\.(\d+)\.(\d+)$/);
492
+ return match ? `${match[1]}.${match[2]}.${Number(match[3]) + 1}` : "";
493
+ }
269
494
  function useDashboard(poll = true) {
270
495
  const [state, setState] = (0, import_react.useState)({ status: "loading" });
271
496
  const load = (0, import_react.useCallback)(async (quiet = false) => {
272
- if (!quiet) setState((current) => ({ ...current, status: current.value ? "refreshing" : "loading", error: void 0 }));
497
+ if (!quiet) setState((current) => ({ ...current, status: current.value ? "refreshing" : "loading" }));
273
498
  try {
274
- const value = await fetchDashboard();
275
- setState({ status: "ready", value });
499
+ setState({ status: "ready", value: await api("dashboard") });
276
500
  } catch (error) {
277
- setState((current) => ({ ...current, status: "error", error: error instanceof Error ? error.message : String(error) }));
501
+ setState((current) => ({ ...current, status: "error", error: error.message }));
278
502
  }
279
503
  }, []);
280
504
  (0, import_react.useEffect)(() => {
281
505
  void load();
282
- if (!poll) return void 0;
283
- const timer = window.setInterval(() => {
284
- void load(true);
285
- }, 5e3);
286
- return () => window.clearInterval(timer);
287
- }, [load, poll]);
506
+ }, [load]);
507
+ (0, import_react.useEffect)(() => {
508
+ if (!poll || !state.value) return void 0;
509
+ const timer = window.setTimeout(() => void load(true), state.value.overview?.activeJobs ? 2500 : 15e3);
510
+ return () => window.clearTimeout(timer);
511
+ }, [load, poll, state.value]);
288
512
  return { ...state, load };
289
513
  }
290
- function WhaleIcon({ size = 18 }) {
291
- return /* @__PURE__ */ import_react.default.createElement("svg", { viewBox: "0 0 24 24", width: size, height: size, fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" }, /* @__PURE__ */ import_react.default.createElement("path", { d: "M3 13c2.1 3.8 6.4 5.2 10.1 3.7 2.4-1 3.9-3 4.3-5.1 1.3.2 2.7-.3 3.6-1.4-1.5-.2-2.3-1-2.8-2.2-.7.8-1.2 1.8-1.2 2.8-2.9-.1-4.4-2.2-7.7-2.2C6.5 8.6 4.3 10 3 13Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M7.2 12.3h.1" }));
514
+ function MetricPills({ metrics }) {
515
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-metrics" }, Object.entries(metrics ?? {}).map(([key, value]) => /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-pill", key }, key, /* @__PURE__ */ import_react.default.createElement("b", null, format(value)))));
516
+ }
517
+ function JobCard({ job, t, open }) {
518
+ const candidate = job.candidate ?? {};
519
+ const progress = job.progress ?? {};
520
+ return /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "hse-job", onClick: () => open(job.name) }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-body" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-top" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-title" }, /* @__PURE__ */ import_react.default.createElement("strong", null, job.name), /* @__PURE__ */ import_react.default.createElement("small", null, new Date(job.updatedAt).toLocaleString(), " \xB7 ", progress.health ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-status", "data-status": job.status }, t(job.status))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("candidate")), /* @__PURE__ */ import_react.default.createElement("b", null, candidate.candidate_id ?? "\u2014", " \xB7 ", candidate.version ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("dataset")), /* @__PURE__ */ import_react.default.createElement("b", null, job.dataset?.dataset_id ?? "\u2014", " \xB7 ", job.dataset?.version ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("mode")), /* @__PURE__ */ import_react.default.createElement("b", null, job.mode ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("progress")), /* @__PURE__ */ import_react.default.createElement("b", null, progress.completed ?? 0, "/", progress.total ?? job.nTrials ?? 0)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("validity")), /* @__PURE__ */ import_react.default.createElement("b", null, typeof job.nValidScores === "number" ? `${t("validScores")} ${job.nValidScores}` : t("unavailable"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("exceptions")), /* @__PURE__ */ import_react.default.createElement("b", null, job.nExceptions))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-progress", "aria-label": `${progress.percent ?? 0}%` }, /* @__PURE__ */ import_react.default.createElement("i", { style: { width: `${progress.percent ?? 0}%` } })), /* @__PURE__ */ import_react.default.createElement(MetricPills, { metrics: job.metrics })));
521
+ }
522
+ function TrialDetail({ detail, t }) {
523
+ if (!detail) return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-detail hse-muted" }, t("evidence"), " \u2014");
524
+ const assessment = detail.assessment;
525
+ if (!assessment) return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-detail" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-score" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("span", null, detail.lifecycle?.name ?? detail.trial), /* @__PURE__ */ import_react.default.createElement("b", null, "\u2014")), /* @__PURE__ */ import_react.default.createElement("span", null, detail.status)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("currentStatus")), /* @__PURE__ */ import_react.default.createElement("pre", null, pretty(detail.lifecycle))));
526
+ const score = assessment.score ?? { value: assessment.rewards?.reward, valid: assessment.status === "assessed" };
527
+ return /* @__PURE__ */ import_react.default.createElement("article", { className: "hse-trial-detail", "aria-live": "polite" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-score" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("span", null, t("score")), /* @__PURE__ */ import_react.default.createElement("b", null, score.valid ? format(score.value) : "\u2014")), /* @__PURE__ */ import_react.default.createElement("span", { className: score.valid ? "hse-valid" : "hse-invalid" }, score.valid ? `\u2713 ${t("valid")}` : `\xD7 ${t("invalid")}`)), !score.valid ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("validity")), /* @__PURE__ */ import_react.default.createElement("ul", null, (score.invalid_reasons ?? []).map((reason) => /* @__PURE__ */ import_react.default.createElement("li", { key: reason }, reason)))) : null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("findings")), /* @__PURE__ */ import_react.default.createElement("ul", null, (assessment.findings ?? []).length ? assessment.findings.map((item, index) => /* @__PURE__ */ import_react.default.createElement("li", { key: index }, item.code ? `${item.code}: ` : "", item.message ?? String(item))) : /* @__PURE__ */ import_react.default.createElement("li", null, "\u2014"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("recommendations")), /* @__PURE__ */ import_react.default.createElement("ul", null, (assessment.recommendations ?? []).length ? assessment.recommendations.map((item, index) => /* @__PURE__ */ import_react.default.createElement("li", { key: index }, item.message ?? String(item))) : /* @__PURE__ */ import_react.default.createElement("li", null, "\u2014"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("output")), /* @__PURE__ */ import_react.default.createElement("pre", null, pretty(assessment.output))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("criteria")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-criteria" }, (assessment.criteria ?? Object.entries(assessment.rewards ?? {}).map(([id, value]) => ({ id, score: value }))).map((item) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-criterion", key: item.id }, /* @__PURE__ */ import_react.default.createElement("span", null, item.label ?? item.id), /* @__PURE__ */ import_react.default.createElement("b", null, format(item.score)))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("provenance")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-provenance" }, (assessment.evidence_provenance ?? assessment.evidence ?? []).map((item, index) => /* @__PURE__ */ import_react.default.createElement("span", { key: item.id ?? index, title: item.artifact_ref }, item.label ?? item.kind ?? "Evidence")))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("timing")), /* @__PURE__ */ import_react.default.createElement("pre", null, pretty(assessment.process))), /* @__PURE__ */ import_react.default.createElement("details", { className: "hse-detail-group" }, /* @__PURE__ */ import_react.default.createElement("summary", null, t("audit")), /* @__PURE__ */ import_react.default.createElement("pre", null, pretty(assessment))));
528
+ }
529
+ function TrialExplorer({ job, active, t }) {
530
+ const [query, setQuery] = (0, import_react.useState)("");
531
+ const [status, setStatus] = (0, import_react.useState)("");
532
+ const [validity, setValidity] = (0, import_react.useState)("");
533
+ const [sort, setSort] = (0, import_react.useState)("dataset-order");
534
+ const [offset, setOffset] = (0, import_react.useState)(0);
535
+ const [page, setPage] = (0, import_react.useState)();
536
+ const [selected, setSelected] = (0, import_react.useState)();
537
+ const [detail, setDetail] = (0, import_react.useState)();
538
+ (0, import_react.useEffect)(() => {
539
+ let cancelled = false;
540
+ const load = () => api("trials", { job, offset, limit: 100, query, status, validity, sort }).then((value) => {
541
+ if (!cancelled) setPage(value);
542
+ });
543
+ const debounce = window.setTimeout(() => void load(), 120);
544
+ const poll = active ? window.setInterval(() => void load(), 2500) : void 0;
545
+ return () => {
546
+ cancelled = true;
547
+ window.clearTimeout(debounce);
548
+ if (poll) window.clearInterval(poll);
549
+ };
550
+ }, [job, offset, query, status, validity, sort, active]);
551
+ const choose = async (trial) => {
552
+ setSelected(trial);
553
+ setDetail(await api("trial", { job, trial }));
554
+ };
555
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-layout" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-list" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-trial-tools" }, /* @__PURE__ */ import_react.default.createElement("input", { className: "hse-input", value: query, placeholder: t("search"), onChange: (event) => {
556
+ setQuery(event.target.value);
557
+ setOffset(0);
558
+ } }), /* @__PURE__ */ import_react.default.createElement("select", { className: "hse-select", value: status, onChange: (event) => {
559
+ setStatus(event.target.value);
560
+ setOffset(0);
561
+ } }, /* @__PURE__ */ import_react.default.createElement("option", { value: "" }, t("all")), /* @__PURE__ */ import_react.default.createElement("option", { value: "completed" }, "completed"), /* @__PURE__ */ import_react.default.createElement("option", { value: "candidate-quality-failed" }, "candidate-quality-failed"), /* @__PURE__ */ import_react.default.createElement("option", { value: "infrastructure-error" }, "infrastructure-error"), /* @__PURE__ */ import_react.default.createElement("option", { value: "evaluation-error" }, "evaluation-error"), /* @__PURE__ */ import_react.default.createElement("option", { value: "running-agent" }, "running-agent"), /* @__PURE__ */ import_react.default.createElement("option", { value: "evaluating" }, "evaluating")), /* @__PURE__ */ import_react.default.createElement("select", { className: "hse-select", value: validity, onChange: (event) => {
562
+ setValidity(event.target.value);
563
+ setOffset(0);
564
+ } }, /* @__PURE__ */ import_react.default.createElement("option", { value: "" }, t("validity")), /* @__PURE__ */ import_react.default.createElement("option", { value: "true" }, t("valid")), /* @__PURE__ */ import_react.default.createElement("option", { value: "false" }, t("invalid"))), /* @__PURE__ */ import_react.default.createElement("select", { className: "hse-select", value: sort, onChange: (event) => setSort(event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "dataset-order" }, t("datasetOrder")), /* @__PURE__ */ import_react.default.createElement("option", { value: "latest-completed" }, t("latest")), /* @__PURE__ */ import_react.default.createElement("option", { value: "lowest-score" }, t("lowest")), /* @__PURE__ */ import_react.default.createElement("option", { value: "errors" }, t("errorsFirst")))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, "#"), /* @__PURE__ */ import_react.default.createElement("th", null, t("queryTrial")), /* @__PURE__ */ import_react.default.createElement("th", null, t("statusLabel")), /* @__PURE__ */ import_react.default.createElement("th", null, t("score")), /* @__PURE__ */ import_react.default.createElement("th", null, t("attempt")))), /* @__PURE__ */ import_react.default.createElement("tbody", null, page?.items?.map((trial) => /* @__PURE__ */ import_react.default.createElement("tr", { key: `${trial.id}-${trial.attempt}`, "data-selected": String(selected) === String(trial.id) }, /* @__PURE__ */ import_react.default.createElement("td", null, trial.datasetOrder + 1), /* @__PURE__ */ import_react.default.createElement("td", null, /* @__PURE__ */ import_react.default.createElement("button", { onClick: () => void choose(trial.id ?? trial.datasetTrial) }, trial.displayName ?? trial.datasetTrial ?? trial.name)), /* @__PURE__ */ import_react.default.createElement("td", null, trial.status), /* @__PURE__ */ import_react.default.createElement("td", null, trial.score?.valid ? format(trial.score.value ?? trial.rewards?.reward) : "\u2014"), /* @__PURE__ */ import_react.default.createElement("td", null, trial.attempt)))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-pager" }, /* @__PURE__ */ import_react.default.createElement("span", null, page?.total ? `${offset + 1}\u2013${Math.min(offset + (page.items?.length ?? 0), page.total)} / ${page.total}` : "0 / 0"), /* @__PURE__ */ import_react.default.createElement("button", { disabled: !offset, onClick: () => setOffset(Math.max(0, offset - 100)) }, t("previous")), /* @__PURE__ */ import_react.default.createElement("button", { disabled: !page?.hasMore, onClick: () => setOffset(offset + 100) }, t("next")))), /* @__PURE__ */ import_react.default.createElement(TrialDetail, { detail, t }));
565
+ }
566
+ function DatasetPanel({ job, artifacts, t }) {
567
+ const [state, setState] = (0, import_react.useState)({ status: "loading" });
568
+ (0, import_react.useEffect)(() => {
569
+ let alive = true;
570
+ void api("dataset", { job }).then((value) => alive && setState({ status: "ready", value }), (error) => alive && setState({ status: "error", error: error.message }));
571
+ return () => {
572
+ alive = false;
573
+ };
574
+ }, [job]);
575
+ const dataset = state.value ?? artifacts.datasetPreview ?? artifacts.dataset;
576
+ const badcases = (dataset?.tasks ?? []).filter((task) => task.metadata?.badcase).length;
577
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, "ID / version"), /* @__PURE__ */ import_react.default.createElement("b", null, artifacts.dataset?.dataset_id ?? "\u2014", " \xB7 ", artifacts.dataset?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(artifacts.dataset?.source_digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("population")), /* @__PURE__ */ import_react.default.createElement("b", null, artifacts.dataset?.task_count ?? dataset?.task_count ?? 0), /* @__PURE__ */ import_react.default.createElement("code", null, badcases, " ", t("badcase"), " \xB7 ", dataset?.source === "job-snapshot" ? t("snapshot") : dataset?.source === "historical-source-fallback" ? t("historicalFallback") : "\u2014")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("datasetTasks")), state.status === "loading" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spin" }), t("loading")) : state.status === "error" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, state.error) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-task-list" }, (dataset?.tasks ?? []).map((task, index) => /* @__PURE__ */ import_react.default.createElement("details", { className: "hse-task", key: task.id ?? index, open: index === 0 }, /* @__PURE__ */ import_react.default.createElement("summary", null, index + 1, ". ", task.query || task.id || `task-${index + 1}`, /* @__PURE__ */ import_react.default.createElement("span", { className: task.metadata?.badcase ? "hse-badcase" : void 0 }, task.metadata?.badcase ? `${t("badcase")} \xB7 ${task.metadata?.case_type}` : task.metadata?.topic ?? task.id ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-task-body" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("taskInstruction")), task.instruction ? /* @__PURE__ */ import_react.default.createElement("pre", { className: "hse-instruction" }, task.instruction) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, task.instruction_error ?? t("noData")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-inline-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, "ID: ", task.id ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("span", null, t("instructionFile"), ": ", task.instruction_file ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("span", null, t("datasetSource"), ": ", dataset.source === "job-snapshot" ? t("snapshot") : t("historicalFallback")), task.instruction_truncated ? /* @__PURE__ */ import_react.default.createElement("span", null, t("attention")) : null)))))));
578
+ }
579
+ function metricLabelMap(artifacts) {
580
+ return Object.fromEntries((artifacts.contract?.metrics ?? []).map((metric) => [metric.id, metric.label ?? metric.id]));
581
+ }
582
+ function CandidatePanel({ artifacts, t }) {
583
+ const candidate = artifacts.candidate ?? {};
584
+ const context = artifacts.context ?? {};
585
+ const dataset = context.dataset ?? artifacts.dataset ?? {};
586
+ const stack = context.evaluation_stack ?? artifacts.stack ?? {};
587
+ const runtime = context.runtime ?? candidate.runtime ?? {};
588
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("experimentIdentity")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, t("experimentIdentityHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-identity-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("candidate")), /* @__PURE__ */ import_react.default.createElement("b", null, candidate.candidate_id ?? "\u2014", " \xB7 ", candidate.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(candidate.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("dataset")), /* @__PURE__ */ import_react.default.createElement("b", null, dataset.dataset_id ?? "\u2014", " \xB7 ", dataset.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, dataset.task_count ?? "\u2014", " Tasks \xB7 ", short(dataset.source_digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("evaluationStack")), /* @__PURE__ */ import_react.default.createElement("b", null, stack.stack_id ?? "\u2014", " \xB7 ", stack.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(stack.comparison_digest ?? stack.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("runtime")), /* @__PURE__ */ import_react.default.createElement("b", null, "Harbor ", runtime.harbor_version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, candidate.runtime?.kind ?? "\u2014", " \xB7 ", candidate.runtime?.version ?? "\u2014", " \xB7 ", context.mode ?? "\u2014")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("immutableCandidateFiles")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-evidence-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, t("file")), /* @__PURE__ */ import_react.default.createElement("th", null, t("size")), /* @__PURE__ */ import_react.default.createElement("th", null, t("digest")))), /* @__PURE__ */ import_react.default.createElement("tbody", null, (candidate.files ?? []).map((file) => /* @__PURE__ */ import_react.default.createElement("tr", { key: file.path }, /* @__PURE__ */ import_react.default.createElement("td", null, file.path), /* @__PURE__ */ import_react.default.createElement("td", null, file.size), /* @__PURE__ */ import_react.default.createElement("td", null, /* @__PURE__ */ import_react.default.createElement("code", null, short(file.sha256))))))))));
589
+ }
590
+ function ContractPanel({ artifacts, component, t }) {
591
+ const contract = artifacts.contract ?? {};
592
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("integrationBoundary")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("integration")), /* @__PURE__ */ import_react.default.createElement("b", null, component?.id ?? "\u2014", " \xB7 ", component?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(component?.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("scoringContract")), /* @__PURE__ */ import_react.default.createElement("b", null, contract.contract_id ?? "\u2014", " \xB7 ", contract.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, t("primaryMetric"), ": ", contract.primary_metric ?? "\u2014")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("hardRequirements")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-chip-list" }, (contract.hard_requirements ?? []).map((item) => /* @__PURE__ */ import_react.default.createElement("span", { key: item.id ?? item }, item.id ?? item)))));
593
+ }
594
+ function ArtifactPreview({ detail, t }) {
595
+ const preview = detail?.preview;
596
+ if (!preview) return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-preview" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-preview-empty" }, t("noRenderableOutput")));
597
+ const content = preview.content;
598
+ const provenance = preview.provenance ?? [];
599
+ let body;
600
+ if (preview.kind === "page" && preview.format === "url" && preview.url) body = /* @__PURE__ */ import_react.default.createElement("iframe", { className: "hse-page-frame", title: preview.title ?? t("pagePreview"), src: preview.url, sandbox: "", referrerPolicy: "no-referrer" });
601
+ else if (preview.kind === "page" && preview.format === "html" && typeof content === "string") body = /* @__PURE__ */ import_react.default.createElement("iframe", { className: "hse-page-frame", title: preview.title ?? t("pagePreview"), srcDoc: content, sandbox: "", referrerPolicy: "no-referrer" });
602
+ else if (preview.kind === "document") {
603
+ const primary = typeof content === "string" ? content : content?.answer ?? content?.report ?? content?.markdown ?? content?.content ?? content?.text;
604
+ const remainder = isRecord(content) ? Object.fromEntries(Object.entries(content).filter(([key]) => !["answer", "report", "markdown", "content", "text"].includes(key))) : void 0;
605
+ body = /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-document" }, /* @__PURE__ */ import_react.default.createElement("h4", null, t("documentPreview")), /* @__PURE__ */ import_react.default.createElement("pre", null, primary ?? pretty(content)), remainder && Object.keys(remainder).length ? /* @__PURE__ */ import_react.default.createElement("details", { className: "hse-source-details" }, /* @__PURE__ */ import_react.default.createElement("summary", null, t("rawOutput")), /* @__PURE__ */ import_react.default.createElement("pre", { className: "hse-output-structured" }, pretty(remainder))) : null);
606
+ } else body = /* @__PURE__ */ import_react.default.createElement("pre", { className: "hse-output-structured" }, pretty(content));
607
+ return /* @__PURE__ */ import_react.default.createElement("article", { className: "hse-preview" }, /* @__PURE__ */ import_react.default.createElement("header", { className: "hse-preview-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, preview.title ?? t("generatedOutput")), /* @__PURE__ */ import_react.default.createElement("span", null, preview.kind, " \xB7 ", preview.format)), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, t("previewSource")), /* @__PURE__ */ import_react.default.createElement("span", null, provenance.map((item) => item.label ?? item.kind).join(" \xB7 ") || preview.source || "\u2014"))), body);
608
+ }
609
+ function RendererPanel({ job, active, component, t }) {
610
+ const [page, setPage] = (0, import_react.useState)();
611
+ const [selected, setSelected] = (0, import_react.useState)();
612
+ const [detail, setDetail] = (0, import_react.useState)();
613
+ (0, import_react.useEffect)(() => {
614
+ let alive = true;
615
+ const load = () => api("trials", { job, offset: 0, limit: 100, sort: "dataset-order" }).then((value) => {
616
+ if (!alive) return;
617
+ setPage(value);
618
+ if (value.items?.length) setSelected((current) => current ?? value.items[0].id ?? value.items[0].datasetTrial);
619
+ });
620
+ void load();
621
+ const poll = active ? window.setInterval(() => void load(), 2500) : void 0;
622
+ return () => {
623
+ alive = false;
624
+ if (poll) window.clearInterval(poll);
625
+ };
626
+ }, [job, active]);
627
+ (0, import_react.useEffect)(() => {
628
+ if (!selected) return;
629
+ let alive = true;
630
+ void api("trial", { job, trial: selected }).then((value) => alive && setDetail(value));
631
+ return () => {
632
+ alive = false;
633
+ };
634
+ }, [job, selected]);
635
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("renderer")), /* @__PURE__ */ import_react.default.createElement("b", null, component?.id ?? "\u2014", " \xB7 ", component?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(component?.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("generatedOutput")), /* @__PURE__ */ import_react.default.createElement("b", null, page?.items?.length ?? 0, " Trials"), /* @__PURE__ */ import_react.default.createElement("code", null, t("previewSource"), ": ", detail?.preview?.provenance?.map((item) => item.label ?? item.kind).join(" \xB7 ") || "\u2014")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("generatedOutput")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-output-layout" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-output-list" }, (page?.items ?? []).map((trial, index) => /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "hse-output-item", "data-active": String(selected) === String(trial.id ?? trial.datasetTrial), key: `${trial.id}-${trial.attempt}`, onClick: () => setSelected(trial.id ?? trial.datasetTrial) }, /* @__PURE__ */ import_react.default.createElement("b", null, index + 1, ". ", trial.displayName ?? trial.datasetTrial ?? trial.name), /* @__PURE__ */ import_react.default.createElement("span", null, trial.status, " \xB7 attempt ", trial.attempt)))), /* @__PURE__ */ import_react.default.createElement(ArtifactPreview, { detail, t }))));
636
+ }
637
+ function TrialAssessmentReport({ job, active, artifacts, t }) {
638
+ const [offset, setOffset] = (0, import_react.useState)(0);
639
+ const [page, setPage] = (0, import_react.useState)();
640
+ const [selected, setSelected] = (0, import_react.useState)();
641
+ const [detailState, setDetailState] = (0, import_react.useState)({ status: "idle" });
642
+ (0, import_react.useEffect)(() => {
643
+ let alive = true;
644
+ const load = () => api("trials", { job, offset, limit: REPORT_PAGE_SIZE, sort: "dataset-order" }).then((value) => {
645
+ if (!alive) return;
646
+ setPage(value);
647
+ if (value.items?.length) setSelected((current) => value.items.some((item) => String(item.id ?? item.datasetTrial) === String(current)) ? current : value.items[0].id ?? value.items[0].datasetTrial);
648
+ else setSelected(void 0);
649
+ });
650
+ void load();
651
+ const poll = active ? window.setInterval(() => void load(), 2500) : void 0;
652
+ return () => {
653
+ alive = false;
654
+ if (poll) window.clearInterval(poll);
655
+ };
656
+ }, [job, active, offset]);
657
+ (0, import_react.useEffect)(() => {
658
+ setOffset(0);
659
+ }, [job]);
660
+ (0, import_react.useEffect)(() => {
661
+ if (!selected) return;
662
+ let alive = true;
663
+ setDetailState({ status: "loading" });
664
+ void api("trial", { job, trial: selected }).then((value) => alive && setDetailState({ status: "ready", value }), (error) => alive && setDetailState({ status: "error", error: error.message }));
665
+ return () => {
666
+ alive = false;
667
+ };
668
+ }, [job, selected]);
669
+ const labels = metricLabelMap(artifacts);
670
+ const primary = artifacts.contract?.primary_metric ?? "reward";
671
+ const declared = (artifacts.contract?.metrics ?? []).map((item) => item.id).filter((id) => id !== primary);
672
+ const metricIds = declared.length ? declared : Object.keys(page?.items?.[0]?.rewards ?? {}).filter((id) => id !== primary);
673
+ const selectedTrial = page?.items?.find((item) => String(item.id ?? item.datasetTrial) === String(selected));
674
+ const detail = detailState.value;
675
+ const assessment = detail?.assessment;
676
+ const score = assessment?.score;
677
+ const artifactTitle = assessment?.output?.title ?? detail?.preview?.title ?? "\u2014";
678
+ return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("trialAssessments")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, t("trialAssessmentsHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-evidence-table hse-report-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, "#"), /* @__PURE__ */ import_react.default.createElement("th", null, t("queryTrial")), /* @__PURE__ */ import_react.default.createElement("th", null, t("overallScore")), metricIds.map((id) => /* @__PURE__ */ import_react.default.createElement("th", { key: id }, labels[id] ?? id)))), /* @__PURE__ */ import_react.default.createElement("tbody", null, (page?.items ?? []).map((trial) => /* @__PURE__ */ import_react.default.createElement("tr", { key: `${trial.id}-${trial.attempt}`, "data-selected": String(selected) === String(trial.id ?? trial.datasetTrial) }, /* @__PURE__ */ import_react.default.createElement("td", null, trial.datasetOrder + 1), /* @__PURE__ */ import_react.default.createElement("td", null, /* @__PURE__ */ import_react.default.createElement("button", { type: "button", onClick: () => setSelected(trial.id ?? trial.datasetTrial) }, trial.displayName ?? trial.datasetTrial ?? trial.name)), /* @__PURE__ */ import_react.default.createElement("td", null, /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-report-score", "data-valid": trial.score?.valid }, trial.score?.valid ? format(trial.score.value ?? trial.rewards?.[primary]) : "\u2014")), metricIds.map((id) => /* @__PURE__ */ import_react.default.createElement("td", { key: id }, format(trial.rewards?.[id])))))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-pager" }, /* @__PURE__ */ import_react.default.createElement("span", null, page?.total ? `${offset + 1}\u2013${Math.min(offset + (page.items?.length ?? 0), page.total)} / ${page.total}` : "0 / 0"), /* @__PURE__ */ import_react.default.createElement("button", { disabled: !offset, onClick: () => setOffset(Math.max(0, offset - REPORT_PAGE_SIZE)) }, t("previous")), /* @__PURE__ */ import_react.default.createElement("button", { disabled: !page?.hasMore, onClick: () => setOffset(offset + REPORT_PAGE_SIZE) }, t("next"))), detailState.status === "loading" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spin" }), t("loading")) : detailState.status === "error" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-error" }, detailState.error) : assessment ? /* @__PURE__ */ import_react.default.createElement("article", { className: "hse-report-detail" }, /* @__PURE__ */ import_react.default.createElement("header", { className: "hse-report-detail-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h4", null, selectedTrial?.displayName ?? assessment.query ?? assessment.trial_name), /* @__PURE__ */ import_react.default.createElement("span", null, t("artifact"), ": ", artifactTitle), /* @__PURE__ */ import_react.default.createElement("code", null, assessment.dataset_trial ?? selectedTrial?.datasetTrial)), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("span", null, t("overallScore")), /* @__PURE__ */ import_react.default.createElement("b", { className: score?.valid ? "hse-valid" : "hse-invalid" }, score?.valid ? format(score.value) : "\u2014"))), !score?.valid ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, (score?.invalid_reasons ?? []).join(" \xB7 ")) : null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-report-compare" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-report-criteria" }, (assessment.criteria ?? []).map((criterion) => /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-report-criterion", key: criterion.id }, /* @__PURE__ */ import_react.default.createElement("header", null, /* @__PURE__ */ import_react.default.createElement("b", null, criterion.label ?? labels[criterion.id] ?? criterion.id), /* @__PURE__ */ import_react.default.createElement("b", null, format(criterion.score))), /* @__PURE__ */ import_react.default.createElement("dl", null, /* @__PURE__ */ import_react.default.createElement("dt", null, t("assessmentReason")), /* @__PURE__ */ import_react.default.createElement("dd", null, criterion.reason || t("noAssessmentReason")), /* @__PURE__ */ import_react.default.createElement("dt", null, t("assessmentRecommendation")), /* @__PURE__ */ import_react.default.createElement("dd", { className: "hse-report-recommendation" }, criterion.recommendation || t("noAssessmentRecommendation")))))), /* @__PURE__ */ import_react.default.createElement(ArtifactPreview, { detail, t }))) : null);
679
+ }
680
+ function ReporterPanel({ job, active, artifacts, t }) {
681
+ const summary = artifacts.summary ?? {};
682
+ const population = artifacts.population ?? {};
683
+ const metrics = population.metrics ?? summary.metrics ?? {};
684
+ const labels = metricLabelMap(artifacts);
685
+ const total = summary.n_trials ?? population.population_size ?? 0;
686
+ const valid = summary.n_valid_scores ?? population.valid_population_size;
687
+ const groups = Array.isArray(population.groups) ? population.groups : Object.entries(population.groups ?? {}).map(([id, count]) => ({ id, count }));
688
+ const configured = population.hook?.configured_component;
689
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("populationEvidence")), configured ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-hook-state", "data-executed": Boolean(configured.executed) }, /* @__PURE__ */ import_react.default.createElement("b", null, t("hookExecution"), ": ", configured.id ?? "\u2014", " \xB7 ", configured.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("br", null), configured.executed ? t("configuredHookRun") : t("configuredHookNotRun")) : null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpis" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("trials")), /* @__PURE__ */ import_react.default.createElement("b", null, total)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("valid")), /* @__PURE__ */ import_react.default.createElement("b", { className: "hse-valid" }, valid ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("invalid")), /* @__PURE__ */ import_react.default.createElement("b", { className: "hse-invalid" }, summary.n_invalid_scores ?? population.invalid_population_size ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("exceptions")), /* @__PURE__ */ import_react.default.createElement("b", null, summary.n_exceptions ?? 0)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("health")), /* @__PURE__ */ import_react.default.createElement("b", null, summary.artifact_validation?.valid ? "VALID" : "CHECK")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-evidence-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, t("metric")), /* @__PURE__ */ import_react.default.createElement("th", null, t("aggregate")), /* @__PURE__ */ import_react.default.createElement("th", null, t("coverage")))), /* @__PURE__ */ import_react.default.createElement("tbody", null, Object.entries(metrics).map(([id, value]) => /* @__PURE__ */ import_react.default.createElement("tr", { key: id }, /* @__PURE__ */ import_react.default.createElement("td", null, /* @__PURE__ */ import_react.default.createElement("b", null, labels[id] ?? id), /* @__PURE__ */ import_react.default.createElement("br", null), /* @__PURE__ */ import_react.default.createElement("code", null, id)), /* @__PURE__ */ import_react.default.createElement("td", null, format(value)), /* @__PURE__ */ import_react.default.createElement("td", null, valid ?? "\u2014", " / ", total))))))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("trialGroups")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-chip-list" }, groups.map((group) => /* @__PURE__ */ import_react.default.createElement("span", { key: group.id }, group.id, ": ", group.count)))), /* @__PURE__ */ import_react.default.createElement(TrialAssessmentReport, { job, active, artifacts, t }));
292
690
  }
293
- function formatValue(value) {
294
- if (typeof value !== "number") return String(value ?? "\u2014");
295
- if (Number.isInteger(value)) return String(value);
296
- return value.toFixed(4).replace(/0+$/, "").replace(/\.$/, "");
691
+ function TrialDeltaTable({ title, items }) {
692
+ return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, title, " \xB7 ", items?.length ?? 0), items?.length ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-evidence-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, "Trial"), /* @__PURE__ */ import_react.default.createElement("th", null, "Baseline"), /* @__PURE__ */ import_react.default.createElement("th", null, "Candidate"), /* @__PURE__ */ import_react.default.createElement("th", null, "Delta"))), /* @__PURE__ */ import_react.default.createElement("tbody", null, items.map((item) => /* @__PURE__ */ import_react.default.createElement("tr", { key: item.trial }, /* @__PURE__ */ import_react.default.createElement("td", null, item.trial), /* @__PURE__ */ import_react.default.createElement("td", null, format(item.baseline)), /* @__PURE__ */ import_react.default.createElement("td", null, format(item.candidate)), /* @__PURE__ */ import_react.default.createElement("td", { className: "hse-delta", "data-positive": (item.delta ?? 0) >= 0 }, item.delta >= 0 ? "+" : "", format(item.delta))))))) : /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-muted" }, "0"));
297
693
  }
298
- function shortDigest(value) {
299
- if (typeof value !== "string") return "\u2014";
300
- return value.length > 19 ? `${value.slice(0, 15)}\u2026${value.slice(-4)}` : value;
694
+ function ComparePanel({ job, jobs, artifacts, t }) {
695
+ const current = jobs.find((item) => item.name === job);
696
+ const all = jobs.filter((item) => item.name !== job);
697
+ const matched = all.filter((item) => item.candidate?.candidate_id === current?.candidate?.candidate_id && item.dataset?.dataset_id === current?.dataset?.dataset_id && item.dataset?.version === current?.dataset?.version && item.mode === current?.mode);
698
+ const candidates = matched.length ? matched : all;
699
+ const [baseline, setBaseline] = (0, import_react.useState)(candidates[0]?.name ?? "");
700
+ const [state, setState] = (0, import_react.useState)();
701
+ (0, import_react.useEffect)(() => {
702
+ if (!baseline) return;
703
+ let alive = true;
704
+ void api("compare", { baseline, candidate: job }).then((value) => alive && setState({ value }), (error) => alive && setState({ error: error.message }));
705
+ return () => {
706
+ alive = false;
707
+ };
708
+ }, [baseline, job]);
709
+ const labels = metricLabelMap(artifacts);
710
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("compare")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-compare-select" }, /* @__PURE__ */ import_react.default.createElement("select", { className: "hse-select", value: baseline, onChange: (event) => setBaseline(event.target.value) }, /* @__PURE__ */ import_react.default.createElement("option", { value: "" }, t("baseline")), candidates.map((item) => /* @__PURE__ */ import_react.default.createElement("option", { key: item.name, value: item.name }, item.name)))), state?.error ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-error" }, state.error) : state?.value ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: state.value.comparable ? "hse-valid" : "hse-invalid" }, state.value.comparable ? `\u2713 ${t("comparable")}` : `\xD7 ${t("notComparable")}`), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, state.value.note), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, Object.entries(state.value.metrics ?? {}).map(([metric, values]) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card", key: metric }, /* @__PURE__ */ import_react.default.createElement("span", null, labels[metric] ?? metric, " \xB7 ", values.direction), /* @__PURE__ */ import_react.default.createElement("b", null, format(values.baseline), " \u2192 ", format(values.candidate)), /* @__PURE__ */ import_react.default.createElement("code", { className: "hse-delta", "data-positive": (values.improvement ?? values.delta ?? 0) >= 0 }, typeof values.delta === "number" ? `${values.delta >= 0 ? "+" : ""}${format(values.delta)}` : "\u2014"))))) : /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-muted" }, t("noData"))), state?.value ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(TrialDeltaTable, { title: t("improved"), items: state.value.improvedTrials }), /* @__PURE__ */ import_react.default.createElement(TrialDeltaTable, { title: t("regressed"), items: state.value.regressedTrials })) : null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, t("explicitGate")));
301
711
  }
302
- function statusLabel(status, t) {
303
- return t(status in dictionaries.zh ? status : "pending");
712
+ function OptimizerPanel({ artifacts, t }) {
713
+ const diagnosis = artifacts.diagnosis ?? {};
714
+ const optimization = artifacts.optimization ?? {};
715
+ const hypotheses = optimization.hypotheses ?? [];
716
+ const diagnoses = diagnosis.diagnoses ?? [];
717
+ const configured = optimization.hook?.configured_component;
718
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("controlledHypotheses")), configured ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-hook-state", "data-executed": Boolean(configured.executed) }, /* @__PURE__ */ import_react.default.createElement("b", null, t("hookExecution"), ": ", configured.id ?? "\u2014", " \xB7 ", configured.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("br", null), configured.executed ? t("configuredHookRun") : t("configuredHookNotRun")) : null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Diagnoser"), /* @__PURE__ */ import_react.default.createElement("b", null, diagnosis.hook?.id ?? "\u2014", " \xB7 ", diagnosis.hook?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, diagnoses.length, " diagnoses \xB7 non-reward-affecting")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("pluginFallback")), /* @__PURE__ */ import_react.default.createElement("b", null, optimization.hook?.id ?? "\u2014", " \xB7 ", optimization.hook?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, hypotheses.length, " hypotheses \xB7 non-reward-affecting")))), diagnoses.length ? /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "Diagnoses"), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-findings" }, diagnoses.map((item, index) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-finding", key: item.id ?? index }, item.message ?? item.root_cause ?? pretty(item))))) : null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-hypotheses" }, hypotheses.length ? hypotheses.map((item) => /* @__PURE__ */ import_react.default.createElement("article", { className: "hse-hypothesis", key: item.id }, /* @__PURE__ */ import_react.default.createElement("h4", null, item.id), /* @__PURE__ */ import_react.default.createElement("dl", null, /* @__PURE__ */ import_react.default.createElement("dt", null, t("rootCause")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.root_cause ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("affectedTrials")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.affected_trials?.length ?? 0), /* @__PURE__ */ import_react.default.createElement("dt", null, t("expectedEffect")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.expected_metric_effect ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("mutationSurface")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.mutation_surface?.join(" \xB7 ") || "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("forbiddenSurface")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.forbidden_surface?.join(" \xB7 ") || "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("guardrails")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.guardrails?.join(" \xB7 ") || "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("rollback")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.rollback_condition ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("nextExperiment")), /* @__PURE__ */ import_react.default.createElement("dd", null, item.next_experiment ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("details", { className: "hse-source-details" }, /* @__PURE__ */ import_react.default.createElement("summary", null, t("provenance"), " \xB7 ", item.evidence_refs?.length ?? 0), /* @__PURE__ */ import_react.default.createElement("pre", { className: "hse-source" }, pretty(item.evidence_refs))))) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, t("noHypotheses")))));
304
719
  }
305
- function MetricPills({ metrics, t }) {
306
- const entries = Object.entries(isRecord(metrics) ? metrics : {});
307
- if (!entries.length) return /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-metric" }, t("noMetrics"));
308
- return entries.map(([name2, value]) => /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-metric", key: name2 }, name2, /* @__PURE__ */ import_react.default.createElement("b", null, formatValue(value))));
720
+ function GateEvidencePanel({ artifacts, t }) {
721
+ const report = artifacts.promotion;
722
+ if (!report) return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("gateEvidence")), /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-muted" }, t("noData")));
723
+ const labels = metricLabelMap(artifacts);
724
+ const pass = report.decision === "PROMOTE";
725
+ const population = report.population ?? {};
726
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-gate-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h3", null, t("gateEvidence")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, report.baseline_job ?? "\u2014", " \u2192 ", report.candidate_job ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-decision", "data-pass": pass }, report.decision ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("comparable")), /* @__PURE__ */ import_react.default.createElement("b", { className: report.comparable ? "hse-valid" : "hse-invalid" }, report.comparable ? "\u2713 TRUE" : "\xD7 FALSE"), /* @__PURE__ */ import_react.default.createElement("code", null, short(report.baseline_evaluation_context?.digest), " = ", short(report.candidate_evaluation_context?.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, report.gate_eligible ? t("eligible") : t("notEligible")), /* @__PURE__ */ import_react.default.createElement("b", { className: report.gate_eligible ? "hse-valid" : "hse-invalid" }, population.baseline_valid ?? "\u2014", " / ", population.baseline ?? "\u2014", " \u2192 ", population.candidate_valid ?? "\u2014", " / ", population.candidate ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, t("policy"), ": ", report.policy?.policy_id ?? "\u2014", " \xB7 ", report.policy?.version ?? "\u2014")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("metricDeltas")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-evidence-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, t("metric")), /* @__PURE__ */ import_react.default.createElement("th", null, "Baseline"), /* @__PURE__ */ import_react.default.createElement("th", null, "Candidate"), /* @__PURE__ */ import_react.default.createElement("th", null, "Delta"))), /* @__PURE__ */ import_react.default.createElement("tbody", null, Object.entries(report.metric_deltas ?? {}).map(([id, delta]) => /* @__PURE__ */ import_react.default.createElement("tr", { key: id }, /* @__PURE__ */ import_react.default.createElement("td", null, labels[id] ?? id), /* @__PURE__ */ import_react.default.createElement("td", null, format(report.baseline_metrics?.[id])), /* @__PURE__ */ import_react.default.createElement("td", null, format(report.candidate_metrics?.[id])), /* @__PURE__ */ import_react.default.createElement("td", { className: "hse-delta", "data-positive": delta >= 0 }, delta >= 0 ? "+" : "", format(delta)))))))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpis" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("improved")), /* @__PURE__ */ import_react.default.createElement("b", null, report.improved_trials?.length ?? 0)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("regressed")), /* @__PURE__ */ import_react.default.createElement("b", null, report.regressed_trials?.length ?? 0)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("newExceptions")), /* @__PURE__ */ import_react.default.createElement("b", null, report.new_exceptions?.length ?? 0)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("artifactRegressions")), /* @__PURE__ */ import_react.default.createElement("b", null, report.artifact_regressions?.length ?? 0)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("reasons")), /* @__PURE__ */ import_react.default.createElement("b", null, report.reasons?.length ?? 0))), report.reasons?.length ? /* @__PURE__ */ import_react.default.createElement("ul", null, report.reasons.map((reason, index) => /* @__PURE__ */ import_react.default.createElement("li", { key: `${gateReasonText(reason)}-${index}` }, gateReasonText(reason)))) : null));
309
727
  }
310
- function JobCard({ job, t }) {
311
- const candidate = isRecord(job.candidate) ? job.candidate : {};
312
- const context = isRecord(job.evaluationContext) ? job.evaluationContext : {};
313
- return /* @__PURE__ */ import_react.default.createElement("article", { className: "hse-job", "data-status": job.status }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-top" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-title" }, /* @__PURE__ */ import_react.default.createElement("strong", null, job.name), /* @__PURE__ */ import_react.default.createElement("small", null, new Date(job.updatedAt).toLocaleString())), /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-status", "data-status": job.status }, statusLabel(job.status, t))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-meta" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("candidate")), /* @__PURE__ */ import_react.default.createElement("strong", null, candidate.candidate_id ?? "\u2014", " \xB7 ", candidate.version ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("context")), /* @__PURE__ */ import_react.default.createElement("code", { title: context.digest }, shortDigest(context.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("trials")), /* @__PURE__ */ import_react.default.createElement("strong", null, job.nTrials)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("exceptions")), /* @__PURE__ */ import_react.default.createElement("strong", null, job.nExceptions))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-metrics" }, /* @__PURE__ */ import_react.default.createElement(MetricPills, { metrics: job.metrics, t })), job.promotion ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-promotion", "data-decision": job.promotion.decision }, /* @__PURE__ */ import_react.default.createElement("strong", null, job.promotion.decision === "PROMOTE" ? t("promote") : t("reject")), job.promotion.reasons?.[0] ?? "") : null);
728
+ function EvaluatorEditor({ value, reload, t }) {
729
+ const active = value.evaluatorInterface;
730
+ const evaluator = active?.evaluator;
731
+ const files = evaluator?.editable_files ?? [];
732
+ const [selectedPath, setSelectedPath] = (0, import_react.useState)(files[0]?.path ?? "");
733
+ const selected = files.find((item) => item.path === selectedPath) ?? files[0];
734
+ const [draft, setDraft] = (0, import_react.useState)(selected?.text ?? "");
735
+ const [evaluatorVersion, setEvaluatorVersion] = (0, import_react.useState)(nextVersion(evaluator?.version));
736
+ const [stackVersion, setStackVersion] = (0, import_react.useState)(nextVersion(active?.stack?.version));
737
+ const [saveState, setSaveState] = (0, import_react.useState)({ status: "idle" });
738
+ (0, import_react.useEffect)(() => {
739
+ const first = files[0];
740
+ setSelectedPath((current) => files.some((item) => item.path === current) ? current : first?.path ?? "");
741
+ setEvaluatorVersion(nextVersion(evaluator?.version));
742
+ setStackVersion(nextVersion(active?.stack?.version));
743
+ }, [evaluator?.digest]);
744
+ (0, import_react.useEffect)(() => {
745
+ setDraft(selected?.text ?? "");
746
+ setSaveState({ status: "idle" });
747
+ }, [selected?.path, selected?.digest]);
748
+ if (active?.error || !evaluator) return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("evaluatorImplementation")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, active?.error ?? t("noEvaluatorInterface")));
749
+ const changed = selected && draft !== selected.text;
750
+ const save = async () => {
751
+ setSaveState({ status: "saving" });
752
+ try {
753
+ await mutate("evaluator", {
754
+ stackPath: active.stack.path,
755
+ filePath: selected.path,
756
+ content: draft,
757
+ expectedDigest: selected.digest,
758
+ newEvaluatorVersion: evaluatorVersion,
759
+ newStackVersion: stackVersion
760
+ });
761
+ setSaveState({ status: "saved" });
762
+ await reload();
763
+ } catch (error) {
764
+ setSaveState({ status: "error", message: error.message });
765
+ }
766
+ };
767
+ return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-editor-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h3", null, t("evaluatorImplementation")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, evaluator.evaluator_id, " \xB7 ", evaluator.version)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("evaluatorKind")), /* @__PURE__ */ import_react.default.createElement("b", null, evaluator.kind), /* @__PURE__ */ import_react.default.createElement("code", null, evaluator.interface))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("evaluatorProtocol")), /* @__PURE__ */ import_react.default.createElement("b", null, evaluator.protocol?.input, " \u2192 ", evaluator.protocol?.output), /* @__PURE__ */ import_react.default.createElement("code", null, evaluator.implementation?.language, " \xB7 ", evaluator.implementation?.callable)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("criteria")), /* @__PURE__ */ import_react.default.createElement("b", null, (evaluator.criteria ?? []).map((item) => item.label).join(" \xB7 ")), /* @__PURE__ */ import_react.default.createElement("code", null, "0 \xB7 0.5 \xB7 1"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-editor-tabs", "aria-label": t("editableFiles") }, files.map((file) => /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "hse-editor-tab", "data-active": file.path === selected?.path, key: file.path, onClick: () => setSelectedPath(file.path) }, /* @__PURE__ */ import_react.default.createElement("b", null, t("openFile"), " ", file.path.split("/").at(-1)), /* @__PURE__ */ import_react.default.createElement("span", null, file.role, " \xB7 ", file.path)))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-editor-current" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("editingFile")), /* @__PURE__ */ import_react.default.createElement("b", null, selected?.path.split("/").at(-1)), /* @__PURE__ */ import_react.default.createElement("code", null, selected?.path)), /* @__PURE__ */ import_react.default.createElement("textarea", { className: "hse-editor", "aria-label": t("editSource"), spellCheck: "false", value: draft, onChange: (event) => setDraft(event.target.value) }), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-editor-versions" }, /* @__PURE__ */ import_react.default.createElement("label", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("evaluatorVersion")), /* @__PURE__ */ import_react.default.createElement("input", { className: "hse-input", value: evaluatorVersion, onChange: (event) => setEvaluatorVersion(event.target.value) })), /* @__PURE__ */ import_react.default.createElement("label", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("stackVersion")), /* @__PURE__ */ import_react.default.createElement("input", { className: "hse-input", value: stackVersion, onChange: (event) => setStackVersion(event.target.value) }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-editor-actions" }, /* @__PURE__ */ import_react.default.createElement("p", { className: saveState.status === "error" ? "hse-editor-error" : saveState.status === "saved" ? "hse-editor-success" : "hse-muted" }, saveState.status === "error" ? saveState.message : saveState.status === "saved" ? t("saved") : t("editWarning")), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "hse-button", disabled: !changed || !evaluatorVersion || !stackVersion || saveState.status === "saving", onClick: () => void save() }, saveState.status === "saving" ? t("saving") : t("saveEvaluator"))));
314
768
  }
315
- function EmptyState({ t }) {
316
- return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement(WhaleIcon, { size: 34 }), /* @__PURE__ */ import_react.default.createElement("h3", null, t("emptyTitle")), /* @__PURE__ */ import_react.default.createElement("p", null, t("emptyBody")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-steps" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("startStep1")), /* @__PURE__ */ import_react.default.createElement("span", null, t("startStep2")), /* @__PURE__ */ import_react.default.createElement("span", null, t("startStep3"))));
769
+ function GovernancePanel({ job, t }) {
770
+ const [state, setState] = (0, import_react.useState)({ status: "loading" });
771
+ const [copied, setCopied] = (0, import_react.useState)(false);
772
+ const load = (0, import_react.useCallback)(async () => {
773
+ try {
774
+ setState({ status: "ready", value: await api("governance", { job }) });
775
+ } catch (error) {
776
+ setState({ status: "error", error: error.message });
777
+ }
778
+ }, [job]);
779
+ (0, import_react.useEffect)(() => {
780
+ void load();
781
+ }, [load]);
782
+ if (state.status === "loading") return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spin" }), t("loading"));
783
+ if (state.status === "error") return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, state.error);
784
+ const value = state.value;
785
+ const evaluator = value.components?.evaluator;
786
+ const rubric = value.components?.rubric;
787
+ const workflow = value.upgradeWorkflow ?? {};
788
+ const prompt = t("evaluatorPrompt");
789
+ const copy = async () => {
790
+ try {
791
+ await navigator.clipboard.writeText(prompt);
792
+ setCopied(true);
793
+ window.setTimeout(() => setCopied(false), 1500);
794
+ } catch {
795
+ setCopied(false);
796
+ }
797
+ };
798
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("currentEvaluator")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, t("governanceHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-governance-id" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("evaluator")), /* @__PURE__ */ import_react.default.createElement("b", null, evaluator?.id ?? "\u2014", " \xB7 ", evaluator?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, evaluator?.entry ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("rubric")), /* @__PURE__ */ import_react.default.createElement("b", null, rubric?.id ?? "\u2014", " \xB7 ", rubric?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, rubric?.entry ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Judge"), /* @__PURE__ */ import_react.default.createElement("b", null, value.judge?.provider ?? "\u2014", " / ", value.judge?.model ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, value.judge?.version ?? "\u2014")))), /* @__PURE__ */ import_react.default.createElement(EvaluatorEditor, { value, reload: load, t }), [["evaluator", evaluator], ["rubric", rubric]].map(([role, component]) => /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section", key: role }, /* @__PURE__ */ import_react.default.createElement("h3", null, role === "evaluator" ? t("evaluator") : t("rubric"), " \xB7 ", component?.id ?? "\u2014", " \xB7 ", component?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("sourceCode")), /* @__PURE__ */ import_react.default.createElement("b", null, component?.entry ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(component?.digest))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, "Reward semantics"), /* @__PURE__ */ import_react.default.createElement("b", null, component?.reward_affecting ? "reward-affecting" : "non-reward"), /* @__PURE__ */ import_react.default.createElement("code", null, component?.source?.error ?? "read-only"))), component?.source?.text ? /* @__PURE__ */ import_react.default.createElement("details", { className: "hse-source-details" }, /* @__PURE__ */ import_react.default.createElement("summary", null, t("sourceCode")), /* @__PURE__ */ import_react.default.createElement("pre", { className: "hse-source" }, component.source.text)) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, component?.source?.error))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section hse-upgrade" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("upgradeEvaluator")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, t("upgradeHint")), /* @__PURE__ */ import_react.default.createElement("ol", null, [1, 2, 3, 4, 5].map((index) => /* @__PURE__ */ import_react.default.createElement("li", { key: index }, t(`upgradeStep${index}`)))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("freshBaseline")), /* @__PURE__ */ import_react.default.createElement("b", null, "Evaluator / Rubric / Judge identity"), /* @__PURE__ */ import_react.default.createElement("code", null, (workflow.freshBaselineRequiredWhen ?? []).join(" \xB7 "))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("metaEvaluation")), /* @__PURE__ */ import_react.default.createElement("b", null, "Independent GT \xB7 ESF \xB7 SCE \xB7 RCR"), /* @__PURE__ */ import_react.default.createElement("code", null, "No automatic evaluation or Gate"))), /* @__PURE__ */ import_react.default.createElement("pre", { className: "hse-prompt" }, prompt), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-prompt-actions" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "hse-button", type: "button", onClick: () => void copy() }, copied ? t("copied") : t("copyPrompt")))));
799
+ }
800
+ function MetaEvaluationPanel({ job, t }) {
801
+ const [state, setState] = (0, import_react.useState)({ status: "loading" });
802
+ (0, import_react.useEffect)(() => {
803
+ let alive = true;
804
+ void api("meta", { job }).then((value2) => alive && setState({ status: "ready", value: value2 }), (error) => alive && setState({ status: "error", error: error.message }));
805
+ return () => {
806
+ alive = false;
807
+ };
808
+ }, [job]);
809
+ if (state.status === "loading") return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spin" }), t("loading"));
810
+ if (state.status === "error") return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-error" }, state.error);
811
+ const value = state.value ?? {};
812
+ const groundTruth = value.groundTruth;
813
+ const report = value.report;
814
+ const metrics = report?.metrics ?? {};
815
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("metaWorkflow")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-muted" }, t("metaWorkflowHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-meta-flow" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, "1. Evaluator Candidate"), /* @__PURE__ */ import_react.default.createElement("br", null), value.workflow?.candidate), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, "2. Fixed artifacts + GT"), /* @__PURE__ */ import_react.default.createElement("br", null), value.workflow?.dataset), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, "3. Repeated observations"), /* @__PURE__ */ import_react.default.createElement("br", null), value.workflow?.output), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, "4. ESF / SCE / RCR"), /* @__PURE__ */ import_react.default.createElement("br", null), value.workflow?.verifier))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("groundTruth")), groundTruth ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-grid" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, "ID / version"), /* @__PURE__ */ import_react.default.createElement("b", null, groundTruth.id, " \xB7 ", groundTruth.version), /* @__PURE__ */ import_react.default.createElement("code", null, groundTruth.path)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("gtSource")), /* @__PURE__ */ import_react.default.createElement("b", null, groundTruth.source?.kind), /* @__PURE__ */ import_react.default.createElement("code", null, groundTruth.source?.description)), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("gtCases")), /* @__PURE__ */ import_react.default.createElement("b", null, groundTruth.caseCount), /* @__PURE__ */ import_react.default.createElement("code", null, groundTruth.criteria?.map((item) => item.label ?? item.id).join(" \xB7 "))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-card" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("gtBadcases")), /* @__PURE__ */ import_react.default.createElement("b", null, groundTruth.badcaseCount), /* @__PURE__ */ import_react.default.createElement("code", null, t("gtProvenance"), ": ", groundTruth.source?.provenance)))) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, /* @__PURE__ */ import_react.default.createElement("b", null, t("groundTruthRequired")), /* @__PURE__ */ import_react.default.createElement("br", null), t("gtKinds")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-hook-state", "data-executed": Boolean(report) }, /* @__PURE__ */ import_react.default.createElement("b", null, t("metaNext")), /* @__PURE__ */ import_react.default.createElement("br", null), value.workflow?.nextAction)), report ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, "Evaluator \xB7 ", report.evaluator?.id, " \xB7 ", report.evaluator?.version), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpis" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, "ESF \u2191"), /* @__PURE__ */ import_react.default.createElement("b", null, format(metrics.esf))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, "SCE \u2193"), /* @__PURE__ */ import_react.default.createElement("b", null, format(metrics.sce))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, "RCR \u2191"), /* @__PURE__ */ import_react.default.createElement("b", null, format(metrics.rcr))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("coverage")), /* @__PURE__ */ import_react.default.createElement("b", null, format(report.coverage?.rate))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-kpi" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("disagreements")), /* @__PURE__ */ import_react.default.createElement("b", null, report.disagreements?.length ?? 0)))), report.disagreements?.length ? /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("disagreements")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-table-wrap" }, /* @__PURE__ */ import_react.default.createElement("table", { className: "hse-evidence-table" }, /* @__PURE__ */ import_react.default.createElement("thead", null, /* @__PURE__ */ import_react.default.createElement("tr", null, /* @__PURE__ */ import_react.default.createElement("th", null, "Case"), /* @__PURE__ */ import_react.default.createElement("th", null, "Criterion"), /* @__PURE__ */ import_react.default.createElement("th", null, "GT"), /* @__PURE__ */ import_react.default.createElement("th", null, "Observed"))), /* @__PURE__ */ import_react.default.createElement("tbody", null, report.disagreements.slice(0, 20).map((item, index) => /* @__PURE__ */ import_react.default.createElement("tr", { key: `${item.case_id}-${item.repeat}-${item.criterion_id}-${index}` }, /* @__PURE__ */ import_react.default.createElement("td", null, item.case_id), /* @__PURE__ */ import_react.default.createElement("td", null, item.criterion_id), /* @__PURE__ */ import_react.default.createElement("td", null, format(item.ground_truth)), /* @__PURE__ */ import_react.default.createElement("td", null, format(item.observed)))))))) : null) : null);
317
816
  }
318
- function ErrorState({ error, retry, t }) {
319
- return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-error" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("loadError")), /* @__PURE__ */ import_react.default.createElement("p", null, error), /* @__PURE__ */ import_react.default.createElement("button", { className: "hse-button", type: "button", onClick: () => void retry() }, t("retry")));
817
+ function Workbench({ job, jobs, close, t }) {
818
+ const [state, setState] = (0, import_react.useState)({ status: "loading" });
819
+ const [stage, setStage] = (0, import_react.useState)("candidate");
820
+ const activeJob = jobs.find((item) => item.name === job);
821
+ const load = (0, import_react.useCallback)(async () => {
822
+ try {
823
+ setState({ status: "ready", value: await api("job", { job }) });
824
+ } catch (error) {
825
+ setState({ status: "error", error: error.message });
826
+ }
827
+ }, [job]);
828
+ (0, import_react.useEffect)(() => {
829
+ void load();
830
+ }, [load]);
831
+ (0, import_react.useEffect)(() => {
832
+ if (!activeJob?.progress?.active) return void 0;
833
+ const timer = window.setInterval(() => void load(), 2500);
834
+ return () => window.clearInterval(timer);
835
+ }, [activeJob?.progress?.active, load]);
836
+ (0, import_react.useEffect)(() => {
837
+ const escape = (event) => event.key === "Escape" && close();
838
+ window.addEventListener("keydown", escape);
839
+ return () => window.removeEventListener("keydown", escape);
840
+ }, [close]);
841
+ const detail = state.value;
842
+ const artifacts = detail?.artifacts ?? {};
843
+ const component = artifacts.stack?.components?.[stage];
844
+ let content;
845
+ if (stage === "candidate") content = /* @__PURE__ */ import_react.default.createElement(CandidatePanel, { artifacts, t });
846
+ else if (stage === "dataset") content = /* @__PURE__ */ import_react.default.createElement(DatasetPanel, { job, artifacts, t });
847
+ else if (stage === "renderer") content = /* @__PURE__ */ import_react.default.createElement(RendererPanel, { job, active: Boolean(activeJob?.progress?.active), component, t });
848
+ else if (stage === "judge") content = /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(GovernancePanel, { job, t }), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("trials"), " / ", t("evidence")), /* @__PURE__ */ import_react.default.createElement(TrialExplorer, { job, active: Boolean(activeJob?.progress?.active), t })));
849
+ else if (stage === "meta") content = /* @__PURE__ */ import_react.default.createElement(MetaEvaluationPanel, { job, t });
850
+ else if (stage === "reporter") content = /* @__PURE__ */ import_react.default.createElement(ReporterPanel, { job, active: Boolean(activeJob?.progress?.active), artifacts, t });
851
+ else if (stage === "optimizer") content = /* @__PURE__ */ import_react.default.createElement(OptimizerPanel, { artifacts, t });
852
+ else if (stage === "gate") content = /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(ComparePanel, { job, jobs, artifacts, t }), /* @__PURE__ */ import_react.default.createElement(GateEvidencePanel, { artifacts, t }));
853
+ else content = stage === "integration" ? /* @__PURE__ */ import_react.default.createElement(ContractPanel, { artifacts, component, t }) : /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-components" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-component" }, /* @__PURE__ */ import_react.default.createElement("span", null, stage, component?.reward_affecting ? " \xB7 reward-affecting" : ""), /* @__PURE__ */ import_react.default.createElement("b", null, component?.id ?? "\u2014", " \xB7 ", component?.version ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("code", null, short(component?.digest)))));
854
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && close() }, /* @__PURE__ */ import_react.default.createElement("aside", { className: "hse-drawer", role: "dialog", "aria-modal": "true", "aria-label": job }, /* @__PURE__ */ import_react.default.createElement("header", { className: "hse-drawer-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h2", null, job), /* @__PURE__ */ import_react.default.createElement("p", null, activeJob?.candidate?.candidate_id ?? "\u2014", " \xB7 ", activeJob?.candidate?.version ?? "\u2014", " \xB7 ", activeJob?.mode ?? "\u2014", " \xB7 ", activeJob?.progress?.completed ?? 0, "/", activeJob?.progress?.total ?? 0)), /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "hse-close", onClick: close }, t("close"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-workbench" }, /* @__PURE__ */ import_react.default.createElement("nav", { className: "hse-stage-nav", "aria-label": t("stageNav") }, STAGES.map((item) => /* @__PURE__ */ import_react.default.createElement("button", { type: "button", key: item, "data-active": stage === item, "aria-current": stage === item ? "step" : void 0, onClick: () => setStage(item) }, STAGES.indexOf(item) + 1, ". ", t(item)))), state.status === "loading" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spin" }), t("loading")) : state.status === "error" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-error" }, state.error, /* @__PURE__ */ import_react.default.createElement("br", null), /* @__PURE__ */ import_react.default.createElement("button", { className: "hse-button", onClick: () => void load() }, t("retry"))) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, !detail.capabilities?.contextV2 ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-capability" }, t("capabilityUnavailable")) : null, content, /* @__PURE__ */ import_react.default.createElement("details", { className: "hse-section hse-audit" }, /* @__PURE__ */ import_react.default.createElement("summary", null, t("audit"), " / ", t("artifacts")), /* @__PURE__ */ import_react.default.createElement("pre", null, pretty({ validation: detail.validation, registry: artifacts.registry, context: artifacts.context, doctor: artifacts.doctor })))))));
320
855
  }
321
856
  function DashboardView({ t }) {
322
857
  const state = useDashboard(true);
858
+ const [selected, setSelected] = (0, import_react.useState)();
323
859
  const snapshot = state.value;
324
- const stats = [
325
- ["totalJobs", snapshot?.overview?.totalJobs ?? "\u2014"],
326
- ["completedJobs", snapshot?.overview?.completedJobs ?? "\u2014"],
327
- ["activeJobs", snapshot?.overview?.activeJobs ?? "\u2014"],
328
- ["latestMetric", snapshot?.overview?.latestMetric ? `${snapshot.overview.latestMetric.name} ${formatValue(snapshot.overview.latestMetric.value)}` : "\u2014"]
329
- ];
330
- return /* @__PURE__ */ import_react.default.createElement("main", { className: "hse-root" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-page" }, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-hero", style: { "--hse-ocean": `url(${harbor_ocean_default})` } }, /* @__PURE__ */ import_react.default.createElement("button", { type: "button", className: "hse-refresh", disabled: state.status === "loading" || state.status === "refreshing", onClick: () => void state.load() }, /* @__PURE__ */ import_react.default.createElement("span", null, "\u21BB"), t("refresh")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-hero-copy" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-eyebrow" }, t("eyebrow")), /* @__PURE__ */ import_react.default.createElement("h1", null, t("heroTitle")), /* @__PURE__ */ import_react.default.createElement("p", null, t("heroBody"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-stats" }, stats.map(([label, value]) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-stat", key: label }, /* @__PURE__ */ import_react.default.createElement("span", null, t(label)), /* @__PURE__ */ import_react.default.createElement("strong", null, value))))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-section" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-section-head" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("h2", null, t("jobs")), /* @__PURE__ */ import_react.default.createElement("p", null, t("jobsHint"))), snapshot?.generatedAt ? /* @__PURE__ */ import_react.default.createElement("p", null, t("refreshed"), " ", new Date(snapshot.generatedAt).toLocaleTimeString()) : null), state.status === "loading" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spinner" }), /* @__PURE__ */ import_react.default.createElement("p", null, t("loading"))) : state.status === "error" && !snapshot ? /* @__PURE__ */ import_react.default.createElement(ErrorState, { error: state.error, retry: state.load, t }) : !snapshot?.jobs?.length ? /* @__PURE__ */ import_react.default.createElement(EmptyState, { t }) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-job-list" }, snapshot.jobs.map((job) => /* @__PURE__ */ import_react.default.createElement(JobCard, { job, t, key: job.name }))))));
860
+ const stats = [[t("jobs"), snapshot?.overview?.totalJobs ?? "\u2014"], [t("completed"), snapshot?.overview?.completedJobs ?? "\u2014"], [t("running"), snapshot?.overview?.activeJobs ?? "\u2014"], [snapshot?.overview?.latestMetric?.name ?? t("score"), format(snapshot?.overview?.latestMetric?.value)]];
861
+ return /* @__PURE__ */ import_react.default.createElement("main", { className: "hse-root" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-page" }, /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-hero", style: { "--ocean-image": `url(${harbor_ocean_default})` } }, /* @__PURE__ */ import_react.default.createElement("button", { className: "hse-refresh", onClick: () => void state.load() }, t("refresh")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-eyebrow" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-whale", "aria-hidden": "true" }, "\u{1F433}"), t("eyebrow")), /* @__PURE__ */ import_react.default.createElement("h1", null, t("heroTitle")), /* @__PURE__ */ import_react.default.createElement("p", null, t("heroBody")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-stats" }, stats.map(([label, value]) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-stat", key: label }, /* @__PURE__ */ import_react.default.createElement("span", null, label), /* @__PURE__ */ import_react.default.createElement("b", null, value))))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-head" }, /* @__PURE__ */ import_react.default.createElement("h2", null, t("jobs")), /* @__PURE__ */ import_react.default.createElement("p", null, t("jobsHint"))), state.status === "loading" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spin" }), t("loading")) : state.status === "error" && !snapshot ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-error" }, state.error, /* @__PURE__ */ import_react.default.createElement("br", null), /* @__PURE__ */ import_react.default.createElement("button", { className: "hse-button", onClick: () => void state.load() }, t("retry"))) : !snapshot?.jobs?.length ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty" }, t("empty")) : /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-list" }, snapshot.jobs.map((job) => /* @__PURE__ */ import_react.default.createElement(JobCard, { job, t, open: setSelected, key: job.name })))), selected ? /* @__PURE__ */ import_react.default.createElement(Workbench, { job: selected, jobs: snapshot.jobs, close: () => setSelected(void 0), t }) : null);
331
862
  }
332
863
  function DoctorView({ t }) {
333
864
  const state = useDashboard(false);
334
- const snapshot = state.value;
335
- const checks = snapshot?.checks ?? {};
336
- const allReady = Object.values(checks).every((check) => check?.status === "ok");
337
- const labels = { projectRoot: "projectRoot", jobsDir: "jobsDir", harbor: "harbor", harborDsh: "harborDsh" };
338
- return /* @__PURE__ */ import_react.default.createElement("main", { className: "hse-root" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-doctor" }, /* @__PURE__ */ import_react.default.createElement("h2", null, t("doctorTitle")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hse-doctor-intro" }, t("doctorBody")), state.status === "loading" ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-empty", style: { marginTop: 20 } }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-spinner" }), /* @__PURE__ */ import_react.default.createElement("p", null, t("loading"))) : state.status === "error" && !snapshot ? /* @__PURE__ */ import_react.default.createElement("div", { style: { marginTop: 20 } }, /* @__PURE__ */ import_react.default.createElement(ErrorState, { error: state.error, retry: state.load, t })) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-doctor-banner" }, /* @__PURE__ */ import_react.default.createElement("strong", null, allReady ? t("ready") : t("attention")), /* @__PURE__ */ import_react.default.createElement("span", null, "Plugin v", snapshot?.pluginVersion ?? "0.4.0")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-checks" }, Object.entries(labels).map(([key, label]) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-check", "data-status": checks[key]?.status ?? "error", key }, /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-check-dot" }), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("strong", null, t(label)), /* @__PURE__ */ import_react.default.createElement("small", { title: checks[key]?.detail }, checks[key]?.detail ?? "\u2014"))))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-contract" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("runtime")), /* @__PURE__ */ import_react.default.createElement("dl", null, /* @__PURE__ */ import_react.default.createElement("dt", null, t("projectRoot")), /* @__PURE__ */ import_react.default.createElement("dd", null, /* @__PURE__ */ import_react.default.createElement("code", null, snapshot?.config?.projectRoot ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("dt", null, t("jobsDir")), /* @__PURE__ */ import_react.default.createElement("dd", null, /* @__PURE__ */ import_react.default.createElement("code", null, snapshot?.config?.jobsDir ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("dt", null, t("dshVersion")), /* @__PURE__ */ import_react.default.createElement("dd", null, snapshot?.config?.dshVersion ?? "\u2014"), /* @__PURE__ */ import_react.default.createElement("dt", null, t("agentImport")), /* @__PURE__ */ import_react.default.createElement("dd", null, /* @__PURE__ */ import_react.default.createElement("code", null, snapshot?.config?.agentImportPath ?? "\u2014")), /* @__PURE__ */ import_react.default.createElement("dt", null, t("pluginImport")), /* @__PURE__ */ import_react.default.createElement("dd", null, /* @__PURE__ */ import_react.default.createElement("code", null, snapshot?.config?.pluginImportPath ?? "\u2014")))), /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-skill-guide" }, /* @__PURE__ */ import_react.default.createElement("h3", null, t("skillGuide")), /* @__PURE__ */ import_react.default.createElement("p", null, t("skillBody"))))));
865
+ return /* @__PURE__ */ import_react.default.createElement("main", { className: "hse-root" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-settings" }, /* @__PURE__ */ import_react.default.createElement("h2", null, t("setupDoctor")), /* @__PURE__ */ import_react.default.createElement("p", null, t("setupHint")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-checks" }, Object.entries(state.value?.checks ?? {}).map(([key, check]) => /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-check", key }, /* @__PURE__ */ import_react.default.createElement("b", { className: check.status === "ok" ? "hse-valid" : "hse-invalid" }, key, " \xB7 ", check.status), /* @__PURE__ */ import_react.default.createElement("small", null, check.detail))))));
339
866
  }
340
- function ToolField({ label, value, code = false }) {
341
- return /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-tool-field" }, /* @__PURE__ */ import_react.default.createElement("span", null, label), code ? /* @__PURE__ */ import_react.default.createElement("code", { title: String(value ?? "\u2014") }, String(value ?? "\u2014")) : /* @__PURE__ */ import_react.default.createElement("strong", null, String(value ?? "\u2014")));
867
+ function blockText(block) {
868
+ return isRecord(block) && Array.isArray(block.content) ? block.content.filter((item) => item?.type === "text").map((item) => item.text).join("\n") : "";
342
869
  }
343
- function toolPresentation(toolName, value, t) {
344
- if (toolName === "harbor_candidate_snapshot") {
345
- return { title: t("toolSnapshot"), summary: value ? `${value.candidate_id ?? "\u2014"} \xB7 ${value.version ?? "\u2014"}` : void 0, fields: [[t("candidate"), value?.candidate_id], [t("version"), value?.version], [t("digest"), shortDigest(value?.digest), true]] };
346
- }
347
- if (toolName === "harbor_eval_run") {
348
- const summary = value?.summary;
349
- return { title: t("toolRun"), summary: summary?.job ?? value?.jobDir, metrics: summary?.metrics, fields: [[t("job"), summary?.job ?? value?.jobDir, true], [t("trials"), summary?.n_trials], [t("exceptions"), summary?.n_exceptions], [t("digest"), shortDigest(value?.manifest?.digest), true]] };
350
- }
351
- if (toolName === "harbor_eval_result") {
352
- return { title: t("toolResult"), summary: value?.job, metrics: value?.metrics, fields: [[t("job"), value?.job, true], [t("trials"), value?.n_trials], [t("exceptions"), value?.n_exceptions], [t("context"), shortDigest(value?.evaluation_context?.digest), true]] };
870
+ function decodeToolResult(block) {
871
+ if (!isRecord(block) || block.isError) return void 0;
872
+ if (isRecord(block.meta)) return block.meta;
873
+ try {
874
+ const value = JSON.parse(blockText(block));
875
+ return isRecord(value) ? value : void 0;
876
+ } catch {
877
+ return void 0;
353
878
  }
354
- return { title: t("toolCompare"), summary: value?.decision, metrics: value?.candidate_metrics, fields: [[t("decision"), value?.decision], [t("candidate"), value?.candidate?.version ?? value?.candidate_job], [t("comparable"), value?.baseline_evaluation_context?.digest === value?.candidate_evaluation_context?.digest ? "\u2713" : "\u2014"], [t("changed"), value?.baseline_candidate?.digest !== value?.candidate?.digest ? "\u2713" : "\u2014"]], reasons: value?.reasons };
355
879
  }
356
- function HarborToolView({ block, toolName, t }) {
880
+ function HarborToolView({ block, toolName }) {
357
881
  const [open, setOpen] = (0, import_react.useState)(true);
358
- const running = !isRecord(block) || !("kind" in block);
359
- const failed = !running && block.isError;
360
882
  const value = decodeToolResult(block);
361
- const view = toolPresentation(toolName, value, t);
362
- return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-tool", "data-state": running ? "running" : failed ? "error" : "success" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "hse-tool-head", type: "button", "aria-expanded": open, onClick: () => setOpen((current) => !current) }, /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-tool-icon" }, /* @__PURE__ */ import_react.default.createElement(WhaleIcon, null)), /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-tool-title" }, view.title), view.summary ? /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-tool-summary" }, "\xB7 ", view.summary) : null, /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-tool-state" }, running ? t("running") : failed ? t("toolFailed") : "\u2713")), open ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-tool-body" }, failed ? /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-tool-summary" }, blockText(block) || t("toolFailed")) : !value ? /* @__PURE__ */ import_react.default.createElement("span", { className: "hse-tool-summary" }, running ? t("running") : t("noResult")) : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-tool-grid" }, view.fields?.map(([label, fieldValue, code], index) => /* @__PURE__ */ import_react.default.createElement(ToolField, { label, value: fieldValue, code, key: `${label}-${index}` }))), view.metrics ? /* @__PURE__ */ import_react.default.createElement("div", { className: "hse-metrics" }, /* @__PURE__ */ import_react.default.createElement(MetricPills, { metrics: view.metrics, t })) : null, Array.isArray(view.reasons) && view.reasons.length ? /* @__PURE__ */ import_react.default.createElement("ul", { className: "hse-reasons" }, view.reasons.map((reason, index) => /* @__PURE__ */ import_react.default.createElement("li", { key: index }, reason))) : null)) : null);
883
+ const running = !isRecord(block) || !("kind" in block);
884
+ return /* @__PURE__ */ import_react.default.createElement("section", { className: "hse-tool" }, /* @__PURE__ */ import_react.default.createElement("button", { type: "button", onClick: () => setOpen(!open) }, /* @__PURE__ */ import_react.default.createElement("strong", null, "\u{1F433} ", toolName), /* @__PURE__ */ import_react.default.createElement("small", null, running ? "running" : block.isError ? "error" : "\u2713")), open ? /* @__PURE__ */ import_react.default.createElement("pre", null, value ? pretty(value) : blockText(block) || "Running\u2026") : null);
363
885
  }
364
886
  var name = "dsh-harbor-evolution";
365
887
  var inject = ["slots", "locale"];
@@ -368,25 +890,10 @@ function apply(ctx) {
368
890
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "harbor-evolution: locale");
369
891
  const t = ctx.locale.bind(NS);
370
892
  const injected = () => ({ t });
371
- ctx.slots.inject("conversation.view", () => ctx.slots.register({
372
- name: "conversation.view",
373
- id: "harbor-evolution",
374
- order: 30,
375
- locale: NS,
376
- label: () => t("tab"),
377
- inject: injected
378
- }, DashboardView));
379
- ctx.slots.inject("settings.section", () => ctx.slots.register({
380
- name: "settings.section",
381
- id: "harbor-evolution",
382
- order: 35,
383
- label: () => t("settings"),
384
- inject: injected
385
- }, DoctorView));
893
+ ctx.slots.inject("conversation.view", () => ctx.slots.register({ name: "conversation.view", id: "harbor-evolution", order: 30, locale: NS, label: () => t("tab"), inject: injected }, DashboardView));
894
+ ctx.slots.inject("settings.section", () => ctx.slots.register({ name: "settings.section", id: "harbor-evolution", order: 35, label: () => t("settings"), inject: injected }, DoctorView));
386
895
  ctx.slots.inject("tool.call.toolview", function* registerTools() {
387
- for (const key of ["harbor_candidate_snapshot", "harbor_eval_run", "harbor_eval_result", "harbor_candidate_compare"]) {
388
- yield ctx.slots.register({ name: "tool.call.toolview", key, inject: injected }, HarborToolView);
389
- }
896
+ for (const key of ["harbor_candidate_snapshot", "harbor_evolution_init", "harbor_evolution_doctor", "harbor_dataset_validate", "harbor_context_preview", "harbor_eval_run", "harbor_eval_result", "harbor_evaluator_inspect", "harbor_evaluator_update", "harbor_ground_truth_init", "harbor_evaluator_meta_evaluate", "harbor_candidate_compare"]) yield ctx.slots.register({ name: "tool.call.toolview", key, inject: injected }, HarborToolView);
390
897
  });
391
898
  }
392
899
  module.exports = { name, inject, apply };