dsh-harbor-evolution 0.9.2 → 0.9.3

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
@@ -44,6 +44,7 @@ __export(index_exports, {
44
44
  clearStructuredHarborReferences: () => clearStructuredHarborReferences,
45
45
  commitIssuedDraft: () => commitIssuedDraft,
46
46
  comparisonCandidates: () => comparisonCandidates,
47
+ createHarborActionHandlers: () => createHarborActionHandlers,
47
48
  dashboardFailureState: () => dashboardFailureState,
48
49
  decodeToolResult: () => decodeToolResult,
49
50
  effectiveHarborSubmissionReference: () => effectiveHarborSubmissionReference,
@@ -132,22 +133,10 @@ function jobAttention(job) {
132
133
  }
133
134
 
134
135
  // src/client/workbench-journey.js
135
- function harborQuestionKeys(context) {
136
- const focus = context?.selection?.at(-1);
137
- if (focus?.kind === "evaluator-source") return ["askSource", "askSourceChange"];
138
- if (focus?.kind === "trial-set") return ["askSelectedTrials", "suggestedQuestion3"];
139
- if (focus?.kind === "metric") return ["askMetric", "suggestedQuestion3"];
140
- if (focus?.kind === "hypothesis") return ["askHypothesis", "suggestedQuestion3"];
141
- if (focus?.kind === "gate-reason") return ["askGateReason", "suggestedQuestion3"];
142
- if (context?.object?.trial || focus?.trial) return ["suggestedQuestion1", "suggestedQuestion3", "askCandidateChange"];
143
- if (context?.object?.job) return ["askHealth", "suggestedQuestion4"];
144
- return ["askGettingStarted"];
145
- }
146
- function harborQuestionLabelKey(key) {
147
- return ["askSource", "askSourceChange", "askSelectedTrials", "askMetric", "askHypothesis", "askGateReason", "askCandidateChange", "askHealth", "askGettingStarted"].includes(key) ? `${key}Label` : key;
148
- }
149
136
  var JOURNEY_MESSAGES = {
150
137
  zh: {
138
+ preparedInHarbor: "\u5DF2\u51C6\u5907\u597D\uFF0C\u8BF7\u6253\u5F00 Harbor \u6807\u7B7E\u67E5\u770B\u3002",
139
+ navigationPending: "\u8BF7\u6253\u5F00 Harbor \u6807\u7B7E\u67E5\u770B\u5DF2\u8BF7\u6C42\u7684\u5BF9\u8C61\uFF1B\u82E5\u672A\u5B9A\u4F4D\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u5BF9\u8C61\u3002",
151
140
  replyReady: "AI \u5DF2\u56DE\u590D \xB7 \u70B9 + \u67E5\u770B",
152
141
  historyOnly: "\u5EF6\u7EED\u4F1A\u8BDD\u5386\u53F2\uFF0C\u672A\u91CD\u65B0\u8BFB\u53D6\u9875\u9762",
153
142
  draftRecoveryReselect: "\u5DF2\u8FD4\u56DE\u539F\u5BF9\u8C61\u9875\u9762\u3002\u5176\u5185\u5BB9\u6216\u9009\u4E2D\u96C6\u5408\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u5177\u4F53\u5185\u5BB9\u540E\u63D0\u95EE\uFF1B\u65E7\u5EFA\u8BAE\u548C\u7F16\u8F91\u5DF2\u4FDD\u7559\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u6269\u5927\u8303\u56F4\u3002",
@@ -210,6 +199,8 @@ var JOURNEY_MESSAGES = {
210
199
  repreparePrompt: "\u8BF7\u91CD\u65B0\u8BFB\u53D6\u8FD9\u4E2A\u5BF9\u8C61\u7684\u6700\u65B0\u8BC1\u636E\uFF0C\u66F4\u65B0\u4E4B\u524D\u7684\u4FEE\u6539\u5EFA\u8BAE\u5E76\u751F\u6210\u65B0\u7684\u8349\u7A3F\u4F9B\u6211\u5BA1\u9605\u3002\u4E0D\u8981\u5199\u5165\u6587\u4EF6\u3001\u8FD0\u884C\u8BC4\u6D4B\u6216\u53D1\u5E03\u3002\u4E4B\u524D\u7684\u5EFA\u8BAE\uFF08\u4EC5\u4F5C\u5F85\u6838\u5B9E\u53C2\u8003\uFF09\uFF1A"
211
200
  },
212
201
  en: {
202
+ preparedInHarbor: "Ready. Open the Harbor tab to view it.",
203
+ navigationPending: "Open the Harbor tab to inspect the requested object; select it again if it was not located.",
213
204
  replyReady: "AI replied \xB7 expand to read",
214
205
  historyOnly: "Conversation history; page not re-read",
215
206
  draftRecoveryReselect: "Returned to the original object page. Its content or selection changed; explicitly select it again before asking. Suggestions and edits remain intact; scope is never expanded automatically.",
@@ -273,6 +264,111 @@ var JOURNEY_MESSAGES = {
273
264
  }
274
265
  };
275
266
 
267
+ // src/client/historical-launcher-state.js
268
+ var HISTORICAL_MESSAGES = {
269
+ zh: {
270
+ historicalLaunch: "\u8BC4\u6D4B\u6700\u8FD1\u4F1A\u8BDD",
271
+ historicalLaunchShort: "\u5F00\u59CB\u8BC4\u6D4B",
272
+ historicalLaunchHint: "\u6700\u591A 3 \u6761 \xB7 \u786E\u8BA4\u540E\u5F00\u59CB",
273
+ historicalLaunchBody: "\u81EA\u52A8\u67E5\u627E\u5F53\u524D DSH \u53EF\u8BBF\u95EE\u7684\u5386\u53F2\u4F1A\u8BDD\uFF0C\u770B\u770B\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u6709\u54EA\u4E9B\u53EF\u4EE5\u6539\u8FDB\u3002",
274
+ historicalPreparing: "\u6B63\u5728\u67E5\u627E\u6700\u8FD1\u53EF\u8BC4\u6D4B\u7684\u4F1A\u8BDD\u2026",
275
+ historicalPreparingShort: "\u8BFB\u53D6\u4E2D\u2026",
276
+ historicalPreviewTitle: "\u8BC4\u6D4B\u8FD9\u4E9B\u4F1A\u8BDD\uFF1F",
277
+ historicalPreviewHint: "\u5DF2\u81EA\u52A8\u67E5\u627E DSH \u5386\u53F2\u8BB0\u5F55\u3002\u786E\u8BA4\u524D\u53EA\u8BFB\u53D6\uFF0C\u4E0D\u542F\u52A8\u8BC4\u6D4B\u3002",
278
+ historicalPrivacyHint: "\u786E\u8BA4\u540E\uFF0C\u6240\u9009\u4F1A\u8BDD\u7684\u8131\u654F\u5BF9\u8BDD\u5C06\u53D1\u9001\u7ED9\u4E0B\u65B9\u8BC4\u5BA1\u6A21\u578B\uFF0C\u53EF\u80FD\u4EA7\u751F\u6A21\u578B\u8D39\u7528\uFF1B\u4E0D\u4F1A\u91CD\u65B0\u6267\u884C\u539F\u4EFB\u52A1\u3002",
279
+ historicalPartialHint: "\u672C\u6B21\u4ECE\u6700\u8FD1\u4E00\u6279\u8BB0\u5F55\u4E2D\u9009\u53D6\uFF0C\u672A\u904D\u5386\u5168\u90E8\u5386\u53F2\u3002",
280
+ historicalUnreadableHint: "\u90E8\u5206\u5386\u53F2\u8BB0\u5F55\u672A\u80FD\u8BFB\u53D6\uFF0C\u672A\u7EB3\u5165\u672C\u6B21\u8BC4\u6D4B\u3002",
281
+ historicalConfirm: "\u786E\u8BA4\u5E76\u5F00\u59CB\u8BC4\u6D4B",
282
+ historicalStarting: "\u6B63\u5728\u542F\u52A8\u8BC4\u6D4B\u2026",
283
+ historicalRunning: "\u6B63\u5728\u8BC4\u6D4B\u5386\u53F2\u4F1A\u8BDD",
284
+ historicalStartingHint: "\u6B63\u5728\u63D0\u4EA4\u5DF2\u786E\u8BA4\u7684\u8BC4\u6D4B\uFF0C\u8BF7\u7A0D\u5019\u3002\u5173\u95ED\u7A97\u53E3\u4E0D\u4F1A\u64A4\u56DE\u786E\u8BA4\u3002",
285
+ historicalErrorTitle: "\u8BC4\u6D4B\u6682\u65F6\u65E0\u6CD5\u7EE7\u7EED",
286
+ historicalErrorBody: "\u8BF7\u67E5\u770B\u4E0B\u65B9\u539F\u56E0\u3002\u91CD\u8BD5\u4F1A\u5148\u91CD\u65B0\u67E5\u627E\u4F1A\u8BDD\uFF0C\u4E0D\u4F1A\u76F4\u63A5\u91CD\u8DD1\u8BC4\u6D4B\u3002",
287
+ historicalErrorDetails: "\u6280\u672F\u8BE6\u60C5",
288
+ historicalRunningHint: "\u53EF\u4EE5\u5173\u95ED\u7A97\u53E3\u7EE7\u7EED\u5DE5\u4F5C\u3002\u8BC4\u6D4B\u5728\u540E\u53F0\u7EE7\u7EED\uFF0C\u5B8C\u6210\u540E\u6253\u5F00\u7ED3\u679C\u3002",
289
+ historicalActive: "\u67E5\u770B\u8BC4\u6D4B\u72B6\u6001",
290
+ historicalActiveShort: "\u67E5\u770B\u72B6\u6001",
291
+ historicalCompleted: "\u8BC4\u6D4B\u5B8C\u6210\uFF0C\u6B63\u5728\u6253\u5F00\u7ED3\u679C\u2026",
292
+ recentSessions: "\u672C\u6B21\u8BC4\u6D4B\u7684\u4F1A\u8BDD",
293
+ selectedSessions: "\u4F1A\u8BDD\u6570\u91CF",
294
+ historicalSessionUnit: "\u6761\u4F1A\u8BDD",
295
+ requestEstimate: "\u9884\u8BA1\u8BC4\u5BA1\u8BF7\u6C42",
296
+ tokenExpiry: "\u9884\u89C8\u6709\u6548\u671F",
297
+ generatorRole: "\u751F\u6210\u5668",
298
+ generatorRoleValue: "\u4EA7\u751F\u8FD9\u4E9B\u4F1A\u8BDD\u7684 DSH Agent",
299
+ evaluatorIdentity: "\u8BC4\u6D4B\u5668\u8EAB\u4EFD",
300
+ judgeIdentity: "\u8BC4\u5BA1\u6A21\u578B",
301
+ coupling: "\u6A21\u578B\u8026\u5408",
302
+ evidenceRetention: "\u8BC1\u636E\u4FDD\u7559",
303
+ historicalBoundaries: "\u8BC4\u6D4B\u8BF4\u660E",
304
+ historicalBoundaryDetail: "\u53EA\u8BCA\u65AD\u5DF2\u6709\u5BF9\u8BDD\uFF0C\u4E0D\u91CD\u8DD1\u539F\u4EFB\u52A1\uFF0C\u4E0D\u81EA\u52A8\u4FEE\u6539\u3001\u90E8\u7F72\u6216\u664B\u7EA7 Agent\uFF1B\u7ED3\u679C\u4E0D\u4EE3\u8868\u8BC4\u6D4B\u5668\u672C\u8EAB\u5DF2\u7ECF\u9A8C\u8BC1\u53EF\u9760\u3002",
305
+ feedbackCounts: "\u53CD\u9988",
306
+ turnCounts: "\u8F6E\u6B21",
307
+ toolCounts: "\u5DE5\u5177\u8C03\u7528",
308
+ previewAgain: "\u91CD\u65B0\u67E5\u627E",
309
+ noEligibleHint: "\u5F53\u524D DSH \u53EF\u8BBF\u95EE\u7684\u5386\u53F2\u8BB0\u5F55\u4E2D\uFF0C\u6682\u672A\u627E\u5230\u5DF2\u5B8C\u6210\u4E14\u53EF\u8BC4\u6D4B\u7684\u4F1A\u8BDD\u3002\u53EF\u4EE5\u7A0D\u540E\u91CD\u8BD5\u3002",
310
+ historyReadFailedHint: "\u90E8\u5206\u5386\u53F2\u4F1A\u8BDD\u672A\u80FD\u8BFB\u53D6\uFF0C\u6682\u65F6\u65E0\u6CD5\u51C6\u5907\u8BC4\u6D4B\u3002\u8BF7\u91CD\u8BD5\uFF1B\u8FD9\u4E0D\u8868\u793A\u5386\u53F2\u8BB0\u5F55\u4E0D\u5B58\u5728\u3002",
311
+ historyWindowExhaustedHint: "\u672C\u6B21\u5DF2\u68C0\u67E5\u7684\u6700\u8FD1\u8BB0\u5F55\u4E2D\uFF0C\u6682\u672A\u627E\u5230\u53EF\u8BC4\u6D4B\u4F1A\u8BDD\u3002\u66F4\u65E9\u7684\u8BB0\u5F55\u5C1A\u672A\u68C0\u67E5\uFF0C\u53EF\u4EE5\u7A0D\u540E\u91CD\u8BD5\u3002",
312
+ changedSessionHint: "\u4F1A\u8BDD\u6216\u8BC4\u6D4B\u8BBE\u7F6E\u5DF2\u53D8\u5316\uFF0C\u6216\u9884\u89C8\u5DF2\u8FC7\u671F\u3002\u8BF7\u91CD\u65B0\u67E5\u627E\u5E76\u786E\u8BA4\u3002",
313
+ historicalGenericError: "\u672C\u6B21\u64CD\u4F5C\u672A\u5B8C\u6210\u3002\u8BF7\u91CD\u8BD5\uFF1B\u5982\u4ECD\u5931\u8D25\uFF0C\u8BF7\u4FDD\u7559\u9519\u8BEF\u4FE1\u606F\u4EE5\u4FBF\u6392\u67E5\u3002",
314
+ cancel: "\u53D6\u6D88"
315
+ },
316
+ en: {
317
+ historicalLaunch: "Evaluate recent Sessions",
318
+ historicalLaunchShort: "Start evaluation",
319
+ historicalLaunchHint: "Up to 3 \xB7 confirm before starting",
320
+ historicalLaunchBody: "Automatically find history available to this DSH and see how completed tasks could improve.",
321
+ historicalPreparing: "Finding recent Sessions to evaluate\u2026",
322
+ historicalPreparingShort: "Loading\u2026",
323
+ historicalPreviewTitle: "Evaluate these Sessions?",
324
+ historicalPreviewHint: "DSH history was found automatically. Nothing is evaluated until you confirm.",
325
+ historicalPrivacyHint: "After confirmation, redacted conversations from the selected Sessions will be sent to the review model below and may incur model charges. The original tasks will not rerun.",
326
+ historicalPartialHint: "This sample comes from a recent set of records, not a full scan of all history.",
327
+ historicalUnreadableHint: "Some historical records could not be read and are not included in this evaluation.",
328
+ historicalConfirm: "Confirm and start evaluation",
329
+ historicalStarting: "Starting evaluation\u2026",
330
+ historicalRunning: "Evaluating historical Sessions",
331
+ historicalStartingHint: "Submitting the evaluation you confirmed. Closing this window will not withdraw that confirmation.",
332
+ historicalErrorTitle: "Evaluation could not continue",
333
+ historicalErrorBody: "Review the reason below. Retrying finds Sessions again; it does not rerun an evaluation without confirmation.",
334
+ historicalErrorDetails: "Technical details",
335
+ historicalRunningHint: "You can close this window and keep working. Evaluation continues in the background and opens the results when complete.",
336
+ historicalActive: "View evaluation status",
337
+ historicalActiveShort: "View status",
338
+ historicalCompleted: "Evaluation complete. Opening results\u2026",
339
+ recentSessions: "Sessions to evaluate",
340
+ selectedSessions: "Session count",
341
+ historicalSessionUnit: "Sessions",
342
+ requestEstimate: "Estimated review requests",
343
+ tokenExpiry: "Preview expires",
344
+ generatorRole: "Generator",
345
+ generatorRoleValue: "The DSH Agent that produced these Sessions",
346
+ evaluatorIdentity: "Evaluator identity",
347
+ judgeIdentity: "Review model",
348
+ coupling: "Model coupling",
349
+ evidenceRetention: "Evidence retention",
350
+ historicalBoundaries: "About this evaluation",
351
+ historicalBoundaryDetail: "Diagnoses existing conversations only. No task rerun, automatic Agent changes, deployment, or promotion. These results do not establish evaluator reliability.",
352
+ feedbackCounts: "Feedback",
353
+ turnCounts: "Turns",
354
+ toolCounts: "Tool calls",
355
+ previewAgain: "Find Sessions again",
356
+ noEligibleHint: "No completed, eligible Sessions were found in the history currently available to this DSH. Try again later.",
357
+ historyReadFailedHint: "Some historical Sessions could not be read, so evaluation cannot be prepared yet. Retry; this does not mean the history is missing.",
358
+ historyWindowExhaustedHint: "No eligible Sessions were found among the recent records checked in this attempt. Older records have not been checked. Try again later.",
359
+ changedSessionHint: "The Sessions or evaluation settings changed, or the preview expired. Find Sessions again and confirm the new preview.",
360
+ historicalGenericError: "This operation did not complete. Retry; if it keeps failing, retain the error details for troubleshooting.",
361
+ cancel: "Cancel"
362
+ }
363
+ };
364
+ function historicalErrorHint(code, t) {
365
+ if (code === "NO_ELIGIBLE_SESSIONS") return t("noEligibleHint");
366
+ if (code === "SESSION_HISTORY_READ_FAILED") return t("historyReadFailedHint");
367
+ if (code === "SESSION_HISTORY_WINDOW_EXHAUSTED" || code === "SESSION_SELECTION_TOO_EXPENSIVE") return t("historyWindowExhaustedHint");
368
+ if (/SESSION_(?:SAMPLE|FEEDBACK)_CHANGED|WORKSPACE_MISMATCH|TOKEN_(?:INVALID|EXPIRED)|PREVIEW_(?:INVALID|WORKSPACE_MISMATCH)/.test(code)) return t("changedSessionHint");
369
+ return t("historicalGenericError");
370
+ }
371
+
276
372
  // src/client/action-draft-card.jsx
277
373
  var import_react = __toESM(require("react"), 1);
278
374
 
@@ -435,7 +531,7 @@ var ACTION_CARD_MESSAGES = {
435
531
  zh: {
436
532
  actionStateRecovered: "\u5DF2\u6838\u67E5\u5E76\u89E3\u9501\uFF1B\u672A\u91CD\u8BD5",
437
533
  actionRecoveryReleased: "\u8BCA\u65AD\u9501\u5DF2\u89E3\u9664\u3002\u539F\u8FD0\u884C\u72B6\u6001\u548C\u8BC1\u636E\u4FDD\u7559\uFF0C\u6CA1\u6709\u81EA\u52A8\u91CD\u8BD5\u3002",
438
- actionRecoveryTaskCenter: "\u6253\u5F00\u4E0A\u65B9\u300C\u540E\u53F0\u4EFB\u52A1\u300D\uFF0C\u6838\u67E5\u8FDB\u7A0B\u4E0E\u8D44\u6E90\u540E\u53EF\u786E\u8BA4\u89E3\u9501\u3002",
534
+ actionRecoveryTaskCenter: "\u6253\u5F00 Harbor \u6807\u7B7E\u4E2D\u7684\u300C\u540E\u53F0\u4EFB\u52A1\u300D\uFF0C\u6838\u67E5\u8FDB\u7A0B\u4E0E\u8D44\u6E90\u540E\u53EF\u786E\u8BA4\u89E3\u9501\u3002",
439
535
  actionDiagnosticPartialView: "\u67E5\u770B\u8FD0\u884C\uFF0F\u90E8\u5206\u8BC1\u636E",
440
536
  actionSuggestion: "AI \u5EFA\u8BAE",
441
537
  actionReviewSource: "\u5BA1\u9605\u5E76\u4FEE\u6539",
@@ -552,7 +648,7 @@ var ACTION_CARD_MESSAGES = {
552
648
  en: {
553
649
  actionStateRecovered: "Inspected and unlocked; not retried",
554
650
  actionRecoveryReleased: "Diagnostic lock released. Original status and evidence retained; no automatic retry.",
555
- actionRecoveryTaskCenter: "Open Background tasks above to inspect the process and resources before confirming unlock.",
651
+ actionRecoveryTaskCenter: "Open Background tasks in the Harbor tab to inspect the process and resources before confirming unlock.",
556
652
  actionDiagnosticPartialView: "View run / partial evidence",
557
653
  actionSuggestion: "AI suggestion",
558
654
  actionReviewSource: "Review and edit",
@@ -987,7 +1083,7 @@ var OPERATION_TRAY_MESSAGES = {
987
1083
  }
988
1084
  };
989
1085
  for (const locale of ["zh", "en"]) Object.assign(OPERATION_TRAY_MESSAGES[locale], Object.fromEntries(Object.entries(PHASES[locale]).map(([key, value]) => [`phase_${key}`, value])));
990
- function OperationTray({ sessionId, scopeKey, request, update, onViewResult, t }) {
1086
+ function OperationTray({ sessionId, scopeKey, request, update, onViewResult, t, hideWhenEmpty = false }) {
991
1087
  const label = (key) => t?.(key) ?? OPERATION_TRAY_MESSAGES.zh[key] ?? key;
992
1088
  const ownerKey = `${sessionId}
993
1089
  ${scopeKey ?? ""}`;
@@ -1015,6 +1111,7 @@ ${scopeKey ?? ""}`;
1015
1111
  }, [sessionId, scopeKey, request, attempt, limit]);
1016
1112
  const active = state.items.filter(actionOperationActive).length;
1017
1113
  const attention = state.items.filter(operationNeedsRecovery).length;
1114
+ if (hideWhenEmpty && !state.loading && !state.error && state.items.length === 0) return null;
1018
1115
  return /* @__PURE__ */ import_react2.default.createElement("section", { className: "hse-operation-tray", "aria-label": label("tasks") }, /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", className: "hse-operation-toggle", "aria-expanded": expanded, onClick: () => setExpanded((value) => !value) }, label("tasks"), " \xB7 ", /* @__PURE__ */ import_react2.default.createElement("span", { role: "status" }, state.loading ? label("loading") : `${active} ${label("active")} \xB7 ${attention} ${label("attention")} \xB7 ${state.items.length} ${label("records")}`), expanded ? " \u2212" : " +"), state.error ? /* @__PURE__ */ import_react2.default.createElement("p", { role: "alert" }, label("stale"), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", onClick: () => setAttempt((value) => value + 1) }, label("refresh"))) : null, expanded ? /* @__PURE__ */ import_react2.default.createElement("div", { className: "hse-operation-list" }, /* @__PURE__ */ import_react2.default.createElement("p", null, label("taskHint")), !state.loading && !state.items.length && !state.error ? /* @__PURE__ */ import_react2.default.createElement("p", null, label("empty")) : null, state.items.map((operation) => /* @__PURE__ */ import_react2.default.createElement(OperationItem, { key: `${ownerKey}:${operation.operationId}`, ...{ operation, request, update, onViewResult, label }, stale: Boolean(state.error), onChanged: () => setAttempt((value) => value + 1) })), state.nextCursor && limit < 100 ? /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", onClick: () => setLimit((value) => Math.min(100, value + 20)) }, label("loadMore")) : state.truncated || state.nextCursor ? /* @__PURE__ */ import_react2.default.createElement("p", null, label("more")) : null) : null);
1019
1116
  }
1020
1117
  function OperationItem({ operation, request, update, onViewResult, onChanged, label, stale }) {
@@ -1079,78 +1176,6 @@ function OperationItem({ operation, request, update, onViewResult, onChanged, la
1079
1176
  }) }, label(operation.status === "CANCELLING" || pending === "cancel" ? "CANCELLING" : "cancel")) : null, needsRecovery ? /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", disabled: stale || Boolean(pending), onClick: () => void inspect() }, label(pending === "inspect" ? "checking" : "inspect")) : null), needsRecovery ? /* @__PURE__ */ import_react2.default.createElement("p", null, label("inspectHint")) : null, inspection ? /* @__PURE__ */ import_react2.default.createElement("section", { className: "hse-operation-inspection" }, /* @__PURE__ */ import_react2.default.createElement("p", null, label(inspection.canRecover ? "releaseReview" : "blocked")), /* @__PURE__ */ import_react2.default.createElement("p", null, label("process"), ": ", label(inspection.process?.state ?? "unknown"), " \xB7 ", label("resources"), ": ", label(inspection.resources?.state ?? "unknown")), inspection.process?.pid ? /* @__PURE__ */ import_react2.default.createElement("code", null, "PID ", inspection.process.pid, " \xB7 PGID ", inspection.process.groupId ?? "\u2014") : null, (inspection.resources?.items ?? []).map((resource) => /* @__PURE__ */ import_react2.default.createElement("p", { key: `${resource.kind}:${resource.id}` }, /* @__PURE__ */ import_react2.default.createElement("code", null, resource.kind, " \xB7 ", resource.id, /* @__PURE__ */ import_react2.default.createElement("br", null), "Compose: ", resource.project))), (inspection.blockers ?? []).map((check, index) => /* @__PURE__ */ import_react2.default.createElement("p", { key: index }, check.message ?? check.code)), inspection.canRecover ? /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, /* @__PURE__ */ import_react2.default.createElement("label", null, /* @__PURE__ */ import_react2.default.createElement("input", { type: "checkbox", checked: reviewed, onChange: (event) => setReviewed(event.target.checked) }), label("releaseReview")), /* @__PURE__ */ import_react2.default.createElement("button", { type: "button", disabled: stale || !reviewed || Boolean(pending), onClick: () => void release() }, label(pending === "release" ? "saving" : "release"))) : null) : null, error ? /* @__PURE__ */ import_react2.default.createElement("p", { role: "alert" }, String(error?.message ?? error)) : null, /* @__PURE__ */ import_react2.default.createElement("details", null, /* @__PURE__ */ import_react2.default.createElement("summary", null, label("detail")), /* @__PURE__ */ import_react2.default.createElement("code", null, operation.operationId), /* @__PURE__ */ import_react2.default.createElement("p", null, operation.createdAt)));
1080
1177
  }
1081
1178
 
1082
- // src/client/conversation-projection.js
1083
- var HUMAN_KINDS = /* @__PURE__ */ new Set(["user", "steering"]);
1084
- var HISTORY_LIMIT = 24;
1085
- function humanText(node) {
1086
- if (!HUMAN_KINDS.has(node?.kind) || !Array.isArray(node.content)) return "";
1087
- return node.content.filter((part) => part?.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n");
1088
- }
1089
- function humanReference(node) {
1090
- const tokens = [];
1091
- const question = humanText(node).replace(/<harbor-context-ref\b([^<>]*)>[\s\S]*?<\/harbor-context-ref\s*>/g, (reference, attributes) => {
1092
- const match = attributes.match(/(?:^|\s)context-snapshot-id\s*=\s*(?:"([^"]*)"|'([^']*)')/);
1093
- const token = match?.[1] ?? match?.[2];
1094
- if (!/^hctx_[A-Za-z0-9_-]+$/.test(token ?? "")) return reference;
1095
- tokens.push(token);
1096
- return "";
1097
- }).trim();
1098
- return { tokens, question };
1099
- }
1100
- function emptyProjection() {
1101
- return { nodes: [], originNodes: [], active: false, anchorSeq: void 0, turn: void 0, question: "", continuation: false, turns: [], selectedSeq: void 0, contextToken: void 0 };
1102
- }
1103
- function humanSegments(nodes) {
1104
- const segments = [];
1105
- let anchor;
1106
- let previous;
1107
- for (let index = 0; index < nodes.length; index += 1) {
1108
- const node = nodes[index];
1109
- if (!HUMAN_KINDS.has(node?.kind) || !Number.isFinite(node.seq)) continue;
1110
- if (previous) previous.endIndex = index;
1111
- const reference = humanReference(node);
1112
- const attached = reference.tokens.length > 0 && reference.tokens.every((value) => value === reference.tokens[0]);
1113
- if (attached) anchor = { index, seq: node.seq, contextToken: reference.tokens[0] };
1114
- else if (reference.tokens.length) anchor = void 0;
1115
- if (!anchor) {
1116
- previous = void 0;
1117
- continue;
1118
- }
1119
- const segment = { index, endIndex: nodes.length, seq: node.seq, question: reference.question, contextAttached: attached, contextToken: anchor.contextToken, anchor };
1120
- segments.push(segment);
1121
- previous = segment;
1122
- }
1123
- return segments;
1124
- }
1125
- function segmentNodes(nodes, segment) {
1126
- const candidates = nodes.slice(segment.index + 1, segment.endIndex).filter((node) => !Number.isFinite(node?.seq) || node.seq > segment.seq);
1127
- const turn = candidates.find((node) => node?.kind === "assistant" && Number.isFinite(node.turn))?.turn;
1128
- return { nodes: candidates.filter((node) => turn === void 0 || !Number.isFinite(node?.turn) || node.turn === turn), turn };
1129
- }
1130
- function harborConversationProjection(nodes, token, selectedSeq) {
1131
- if (!Array.isArray(nodes) || !/^hctx_[A-Za-z0-9_-]+$/.test(token ?? "")) return emptyProjection();
1132
- const requestedSeq = typeof selectedSeq === "object" && selectedSeq !== null ? selectedSeq.selectedSeq : selectedSeq;
1133
- const segments = humanSegments(nodes);
1134
- const history = segments.slice(-HISTORY_LIMIT);
1135
- const latestForToken = history.findLast((segment) => segment.contextToken === token);
1136
- if (!latestForToken) return emptyProjection();
1137
- const selected = history.find((segment) => segment.seq === requestedSeq) ?? latestForToken;
1138
- const projected = segmentNodes(nodes, selected);
1139
- const origin = segments.find((segment) => segment.index === selected.anchor.index);
1140
- return {
1141
- nodes: projected.nodes,
1142
- originNodes: origin ? segmentNodes(nodes, origin).nodes : [],
1143
- active: selected === latestForToken && selected.endIndex === nodes.length && selected.contextToken === token,
1144
- anchorSeq: selected.anchor.seq,
1145
- turn: projected.turn,
1146
- question: selected.question,
1147
- continuation: !selected.contextAttached,
1148
- turns: history.map(({ seq, question, contextAttached, contextToken }) => ({ seq, question, contextAttached, contextToken })),
1149
- selectedSeq: selected.seq,
1150
- contextToken: selected.contextToken
1151
- };
1152
- }
1153
-
1154
1179
  // src/client/evaluator-editor.jsx
1155
1180
  var import_react3 = __toESM(require("react"), 1);
1156
1181
 
@@ -1740,7 +1765,7 @@ var dictionaries = {
1740
1765
  jobsHint: "\u70B9\u51FB Job \u540E\uFF0C\u6700\u591A\u518D\u70B9\u4E00\u6B21\u5373\u53EF\u8FDB\u5165\u5BF9\u5E94 Trial \u7684\u8BC1\u636E\u3002",
1741
1766
  workspace: "\u5DE5\u4F5C\u7A7A\u95F4",
1742
1767
  workspaceSelect: "\u9009\u62E9 Harbor \u5DE5\u4F5C\u7A7A\u95F4",
1743
- empty: "\u8FD8\u6CA1\u6709 Harbor Job\u3002\u53EF\u4EE5\u5148\u8BC4\u6D4B\u8FD9\u4E2A\u5DE5\u4F5C\u7A7A\u95F4\u6700\u8FD1\u5B8C\u6210\u7684\u771F\u5B9E\u4F1A\u8BDD\u3002",
1768
+ empty: "\u8FD8\u6CA1\u6709\u8BC4\u6D4B\u7ED3\u679C\u3002\u53EF\u4EE5\u5148\u8BD5\u8BD5\u300C\u8BC4\u6D4B\u6700\u8FD1\u4F1A\u8BDD\u300D\uFF0C\u81EA\u52A8\u67E5\u627E\u5F53\u524D DSH \u7684\u8FD1\u671F\u771F\u5B9E\u4F1A\u8BDD\uFF0C\u786E\u8BA4\u540E\u5F00\u59CB\u3002",
1744
1769
  askAi: "Ask AI",
1745
1770
  askAboutThis: "\u5F15\u7528\u540E\u63D0\u95EE",
1746
1771
  currentPage: "\u5F53\u524D\u9875\u9762",
@@ -1801,43 +1826,7 @@ var dictionaries = {
1801
1826
  errorNextPermission: "\u68C0\u67E5\u5F53\u524D Session \u7684\u5DE5\u4F5C\u7A7A\u95F4\u4E0E\u8BBF\u95EE\u6743\u9650\u3002",
1802
1827
  errorNextMissing: "\u5237\u65B0\u5217\u8868\u5E76\u786E\u8BA4\u5BF9\u8C61\u4ECD\u7136\u5B58\u5728\u3002",
1803
1828
  errorNextArtifact: "\u68C0\u67E5 Job \u7684 Artifact / Audit\uFF0C\u4FEE\u590D\u4EA7\u7269\u540E\u91CD\u8BD5\u3002",
1804
- historicalLaunch: "\u8BC4\u6D4B\u6700\u8FD1\u4F1A\u8BDD",
1805
- historicalLaunchShort: "\u5F00\u59CB\u8BC4\u6D4B",
1806
- historicalLaunchHint: "\u6700\u591A 10 \u6761 \xB7 \u5148\u9884\u89C8\u518D\u8FD0\u884C",
1807
- historicalLaunchBody: "\u7528\u5F53\u524D DSH Agent \u5DF2\u5B8C\u6210\u7684\u771F\u5B9E\u4EFB\u52A1\u505A\u8BCA\u65AD\uFF0C\u4E0D\u91CD\u65B0\u8FD0\u884C Candidate\u3002",
1808
- historicalPreparing: "\u6B63\u5728\u67E5\u627E\u53EF\u8BC4\u6D4B\u4F1A\u8BDD\u2026",
1809
- historicalPreparingShort: "\u8BFB\u53D6\u4E2D\u2026",
1810
- historicalPreviewTitle: "\u786E\u8BA4\u5386\u53F2\u4F1A\u8BDD\u8BC4\u6D4B",
1811
- historicalPreviewHint: "\u8FD9\u91CC\u53EA\u5C55\u793A\u5B89\u5168\u5143\u6570\u636E\u3002\u786E\u8BA4\u524D\u4E0D\u4F1A\u5199\u5165 Batch\uFF0C\u4E5F\u4E0D\u4F1A\u542F\u52A8 Harbor Job\u3002",
1812
- historicalConfirm: "\u786E\u8BA4\u5E76\u5F00\u59CB\u8BC4\u6D4B",
1813
- historicalStarting: "\u6B63\u5728\u542F\u52A8\u2026",
1814
- historicalRunning: "\u5386\u53F2\u4F1A\u8BDD\u8BC4\u6D4B\u8FD0\u884C\u4E2D",
1815
- historicalRunningHint: "\u53EF\u4EE5\u5173\u95ED\u6B64\u7A97\u53E3\u7EE7\u7EED\u5DE5\u4F5C\u3002Harbor \u4F1A\u5728\u540E\u53F0\u8FD0\u884C\uFF0C\u5B8C\u6210\u540E\u81EA\u52A8\u6253\u5F00 Job\u3002",
1816
- historicalActive: "\u67E5\u770B\u8FD0\u884C\u72B6\u6001",
1817
- historicalActiveShort: "\u67E5\u770B\u72B6\u6001",
1818
- historicalCompleted: "\u8BC4\u6D4B\u5B8C\u6210\uFF0C\u6B63\u5728\u6253\u5F00 Job\u2026",
1819
- recentSessions: "\u672C\u6B21\u4F1A\u8BDD\u6837\u672C",
1820
- selectedSessions: "\u9009\u4E2D\u4F1A\u8BDD",
1821
- requestEstimate: "\u9884\u8BA1 Judge \u8BF7\u6C42",
1822
- tokenExpiry: "\u9884\u89C8\u6709\u6548\u671F",
1823
- generatorRole: "\u751F\u6210\u5668",
1824
- generatorRoleValue: "\u4EA7\u751F\u8FD9\u4E9B\u4F1A\u8BDD\u7684 DSH Agent",
1825
- evaluatorIdentity: "\u8BC4\u6D4B\u5668\u8EAB\u4EFD",
1826
- judgeIdentity: "Judge \u8EAB\u4EFD",
1827
- coupling: "\u6A21\u578B\u8026\u5408",
1828
- evidenceRetention: "\u8BC1\u636E\u4FDD\u7559",
1829
- historicalBoundaries: "\u672C\u6B21\u8FD0\u884C\u8FB9\u754C",
1830
- historicalBoundaryDetail: "\u4E0D\u8FD0\u884C Candidate \xB7 \u4E0D\u505A\u8BC4\u6D4B\u5668\u5143\u8BC4\u6D4B \xB7 \u4E0D\u8FDB\u5165 Gate / \u664B\u7EA7",
1831
- feedbackCounts: "\u53CD\u9988",
1832
- turnCounts: "\u8F6E\u6B21",
1833
- toolCounts: "\u5DE5\u5177\u8C03\u7528",
1834
- previewAgain: "\u91CD\u65B0\u9884\u89C8",
1835
- recent30Days: "\u4EC5\u770B\u6700\u8FD1 30 \u5929",
1836
- noEligibleHint: "\u5F53\u524D\u5DE5\u4F5C\u7A7A\u95F4\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u5DF2\u5B8C\u6210\u9876\u5C42\u4F1A\u8BDD\u3002\u5148\u5728\u8FD9\u4E2A\u76EE\u5F55\u5B8C\u6210\u4E00\u4E2A\u6709\u7528\u6237\u8F93\u5165\u548C Agent \u8F93\u51FA\u7684\u771F\u5B9E\u4EFB\u52A1\uFF0C\u6216\u6539\u7528\u663E\u5F0F Dataset\u3002",
1837
- narrowScanHint: "\u8FD9\u4E2A\u5DE5\u4F5C\u7A7A\u95F4\u7684\u4F1A\u8BDD\u592A\u591A\u3002\u53EF\u4EE5\u628A\u626B\u63CF\u8303\u56F4\u7F29\u5230\u6700\u8FD1 30 \u5929\u540E\u91CD\u8BD5\u3002",
1838
- changedSessionHint: "\u9884\u89C8\u540E\u4F1A\u8BDD\u3001\u53CD\u9988\u6216\u5DE5\u4F5C\u7A7A\u95F4\u53D1\u751F\u4E86\u53D8\u5316\u3002\u4E3A\u4E86\u907F\u514D\u8BC4\u9519\u8BC1\u636E\uFF0C\u8BF7\u91CD\u65B0\u9884\u89C8\u3002",
1839
- historicalGenericError: "\u6CA1\u6709\u542F\u52A8 Job\u3002\u8BF7\u68C0\u67E5\u63D0\u793A\u540E\u91CD\u65B0\u9884\u89C8\u3002",
1840
- cancel: "\u53D6\u6D88",
1829
+ ...HISTORICAL_MESSAGES.zh,
1841
1830
  completed: "\u5DF2\u5B8C\u6210",
1842
1831
  partial: "\u5B8C\u6210\u4F46\u6709\u5F02\u5E38",
1843
1832
  failed: "\u8BFB\u53D6\u5931\u8D25",
@@ -2144,7 +2133,7 @@ var dictionaries = {
2144
2133
  jobsHint: "Open a Job, then reach Trial evidence in at most one more interaction.",
2145
2134
  workspace: "Workspace",
2146
2135
  workspaceSelect: "Select Harbor workspace",
2147
- empty: "No Harbor Jobs yet. Start by evaluating recent completed Sessions in this workspace.",
2136
+ empty: "No evaluation results yet. Try \u201CEvaluate recent Sessions\u201D to find recent real conversations in this DSH automatically, then confirm to begin.",
2148
2137
  askAi: "Ask AI",
2149
2138
  askAboutThis: "Ask about this",
2150
2139
  currentPage: "Current page",
@@ -2205,43 +2194,7 @@ var dictionaries = {
2205
2194
  errorNextPermission: "Check the active Session workspace and its access permissions.",
2206
2195
  errorNextMissing: "Refresh the list and confirm that the object still exists.",
2207
2196
  errorNextArtifact: "Inspect the Job Artifact / Audit, repair the artifact, and retry.",
2208
- historicalLaunch: "Evaluate recent Sessions",
2209
- historicalLaunchShort: "Start evaluation",
2210
- historicalLaunchHint: "Up to 10 \xB7 preview before running",
2211
- historicalLaunchBody: "Diagnose real tasks already completed by the current DSH Agent without rerunning a Candidate.",
2212
- historicalPreparing: "Finding eligible Sessions\u2026",
2213
- historicalPreparingShort: "Loading\u2026",
2214
- historicalPreviewTitle: "Confirm Historical Session evaluation",
2215
- historicalPreviewHint: "Only safe metadata is shown. No Batch is written and no Harbor Job starts until you confirm.",
2216
- historicalConfirm: "Confirm and start evaluation",
2217
- historicalStarting: "Starting\u2026",
2218
- historicalRunning: "Historical Session evaluation is running",
2219
- historicalRunningHint: "You can close this window and keep working. Harbor runs in the background and opens the Job when it completes.",
2220
- historicalActive: "View run status",
2221
- historicalActiveShort: "View status",
2222
- historicalCompleted: "Evaluation complete. Opening the Job\u2026",
2223
- recentSessions: "Session sample",
2224
- selectedSessions: "Selected Sessions",
2225
- requestEstimate: "Estimated Judge requests",
2226
- tokenExpiry: "Preview expires",
2227
- generatorRole: "Generator",
2228
- generatorRoleValue: "The DSH Agent that produced these Sessions",
2229
- evaluatorIdentity: "Evaluator identity",
2230
- judgeIdentity: "Judge identity",
2231
- coupling: "Model coupling",
2232
- evidenceRetention: "Evidence retention",
2233
- historicalBoundaries: "Run boundaries",
2234
- historicalBoundaryDetail: "No Candidate run \xB7 no Evaluator meta-evaluation \xB7 no Gate or promotion",
2235
- feedbackCounts: "Feedback",
2236
- turnCounts: "Turns",
2237
- toolCounts: "Tool calls",
2238
- previewAgain: "Preview again",
2239
- recent30Days: "Only last 30 days",
2240
- noEligibleHint: "No eligible completed top-level Sessions were found in this workspace. Complete a real task here with direct user input and Agent output, or use an explicit Dataset.",
2241
- narrowScanHint: "This workspace has too many Sessions to scan safely. Narrow the scan to the last 30 days and try again.",
2242
- changedSessionHint: "A Session, its feedback, or the workspace changed after Preview. Preview again so Harbor cannot evaluate stale evidence.",
2243
- historicalGenericError: "No Job was started. Review the message and preview again.",
2244
- cancel: "Cancel",
2197
+ ...HISTORICAL_MESSAGES.en,
2245
2198
  completed: "Completed",
2246
2199
  partial: "Completed with errors",
2247
2200
  failed: "Read failed",
@@ -2472,23 +2425,23 @@ for (const locale of ["zh", "en"]) Object.assign(dictionaries[locale], JOURNEY_M
2472
2425
  Object.assign(dictionaries.zh, { prepareDiagnostic: "\u89C4\u5212\u9009\u4E2D\u9879\u7684\u8BCA\u65AD\u5B9E\u9A8C", askDiagnostic: "\u57FA\u4E8E\u8FD9\u7EC4\u5DF2\u51BB\u7ED3\u7684 Trial\uFF0C\u5148\u8BFB\u53D6\u8BC1\u636E\u5E76\u8BF4\u660E\u5171\u540C\u539F\u56E0\u4E0E\u4E0D\u786E\u5B9A\u6027\uFF0C\u518D\u8C03\u7528 harbor_propose_action \u521B\u5EFA diagnostic-evaluation \u8349\u7A3F\u3002\u53EA\u4F7F\u7528\u6B64\u5F15\u7528\u7684\u9009\u4E2D\u4EFB\u52A1\uFF0C\u4E0D\u6269\u5927\u8303\u56F4\u3001\u4E0D\u6539 Candidate \u6216\u8BC4\u5206\u89C4\u5219\u3002\u5B9E\u9645\u6267\u884C\u7531\u6211\u68C0\u67E5\u53C2\u6570\u5E76\u786E\u8BA4\uFF1B\u73B0\u5728\u4E0D\u8981\u8FD0\u884C\u4EFB\u4F55\u8BC4\u6D4B\u3001\u91CD\u8BD5\u3001Gate \u6216\u53D1\u5E03\u3002" });
2473
2426
  Object.assign(dictionaries.en, { prepareDiagnostic: "Plan a diagnostic for this selection", askDiagnostic: "Read this frozen Trial selection and explain the common cause and uncertainty, then use harbor_propose_action to propose a diagnostic-evaluation. Use only these selected tasks, without changing Candidate or scoring rules. I will review the parameters and confirm execution. Do not run evaluations, retries, Gate, or deployment now." });
2474
2427
  var CSS = `
2475
- .hse-copilot .hse-operation-tray button{color:#dcecff;border-color:#70cfff77}
2428
+
2476
2429
  .hse-selection-bar .hse-local-actions button{color:inherit}
2477
- .hse-operation-tray{margin:10px 0;border:1px solid #70cfff55;border-radius:9px;font-size:11px;overflow-wrap:anywhere}.hse-operation-tray button{padding:7px 9px;background:transparent;color:inherit;border:1px solid #70cfff55;border-radius:7px;font:inherit;cursor:pointer}.hse-operation-tray button:disabled{opacity:.5;cursor:not-allowed}.hse-operation-tray .hse-operation-toggle{border:0;width:100%;text-align:left}.hse-operation-list{padding:0 9px 9px;max-height:45vh;overflow:auto}.hse-operation-item{border-top:1px solid #70cfff35;padding:10px 0;line-height:1.6}.hse-operation-item header{display:flex;justify-content:space-between;flex-wrap:wrap;gap:6px}.hse-operation-item p{margin:6px 0}.hse-operation-item code{font-size:9px}.hse-operation-inspection{padding:8px;border:1px solid #e4a23b55;border-radius:7px;margin:8px 0}.hse-operation-inspection label{display:block}.hse-operation-tray button:focus-visible{outline:2px solid #ffca68;outline-offset:2px}@container(max-width:1050px){.hse-layout>.hse-copilot[data-collapsed=true]:has(.hse-operation-tray){max-height:140px}.hse-layout>.hse-copilot[data-collapsed=true]:has(.hse-operation-toggle[aria-expanded=true]){max-height:45vh}}
2478
- .hse-journey{padding:18px;margin-bottom:18px;border:1px solid #2875ff35;border-radius:14px;background:#2875ff08}.hse-journey h2{margin:0;font-size:20px}.hse-journey p,.hse-journey li{font-size:13px;line-height:1.7}.hse-journey ol{padding:0;list-style:none}.hse-journey details summary{cursor:pointer}.hse-question{font-size:12px;line-height:1.6;white-space:pre-wrap;overflow-wrap:anywhere}.hse-discussion-history{margin:10px 0;font-size:12px}.hse-discussion-history button{display:block;width:100%;margin:5px 0;padding:7px;text-align:left;color:inherit;border:1px solid #70cfff55;background:transparent;border-radius:6px;cursor:pointer}.hse-draft-notice{padding:10px;border:1px solid #2875ff44;border-radius:8px;font-size:12px;line-height:1.6}.hse-editor-tab[data-dirty=true]:after{content:' \u2022';color:#c78312}.hse-local-actions{flex-wrap:wrap}.hse-answer-unverified>p{font-size:11px;color:#f3c779}.hse-copilot details>summary{cursor:pointer;font-size:11px}.hse-copilot-actions{flex-wrap:wrap}.hse-context-questions{max-height:70px;overflow:auto}.hse-job-identities>summary{cursor:pointer;font-size:12px}.hse-job-identities[open]>.hse-identity-tags{margin-top:12px}
2430
+ .hse-operation-tray{margin:10px 0;border:1px solid #70cfff55;border-radius:9px;font-size:11px;overflow-wrap:anywhere}.hse-operation-tray button{padding:7px 9px;background:transparent;color:inherit;border:1px solid #70cfff55;border-radius:7px;font:inherit;cursor:pointer}.hse-operation-tray button:disabled{opacity:.5;cursor:not-allowed}.hse-operation-tray .hse-operation-toggle{border:0;width:100%;text-align:left}.hse-operation-list{padding:0 9px 9px;max-height:45vh;overflow:auto}.hse-operation-item{border-top:1px solid #70cfff35;padding:10px 0;line-height:1.6}.hse-operation-item header{display:flex;justify-content:space-between;flex-wrap:wrap;gap:6px}.hse-operation-item p{margin:6px 0}.hse-operation-item code{font-size:9px}.hse-operation-inspection{padding:8px;border:1px solid #e4a23b55;border-radius:7px;margin:8px 0}.hse-operation-inspection label{display:block}.hse-operation-tray button:focus-visible{outline:2px solid #ffca68;outline-offset:2px}@container(max-width:1050px){}
2431
+ .hse-journey{padding:18px;margin-bottom:18px;border:1px solid #2875ff35;border-radius:14px;background:#2875ff08}.hse-journey h2{margin:0;font-size:20px}.hse-journey p,.hse-journey li{font-size:13px;line-height:1.7}.hse-journey ol{padding:0;list-style:none}.hse-journey details summary{cursor:pointer}.hse-question{font-size:12px;line-height:1.6;white-space:pre-wrap;overflow-wrap:anywhere}.hse-discussion-history{margin:10px 0;font-size:12px}.hse-discussion-history button{display:block;width:100%;margin:5px 0;padding:7px;text-align:left;color:inherit;border:1px solid #70cfff55;background:transparent;border-radius:6px;cursor:pointer}.hse-draft-notice{padding:10px;border:1px solid #2875ff44;border-radius:8px;font-size:12px;line-height:1.6}.hse-editor-tab[data-dirty=true]:after{content:' \u2022';color:#c78312}.hse-local-actions{flex-wrap:wrap}.hse-answer-unverified>p{font-size:11px;color:#f3c779}.hse-job-identities>summary{cursor:pointer;font-size:12px}.hse-job-identities[open]>.hse-identity-tags{margin-top:12px}
2479
2432
  .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}
2480
2433
  .hse-dashboard-back{margin-bottom:10px}
2481
- .hse-action-draft button{padding:7px 10px;border:1px solid #70cfff55;border-radius:7px;background:transparent;color:inherit;cursor:pointer;font:inherit}.hse-action-draft>.hse-primary{background:#2875ff;color:#fff;border-color:#2875ff}.hse-action-draft header{flex-wrap:wrap}.hse-action-draft header>span{font-size:10px;color:#a8d9ff}.hse-action-recovery,.hse-action-next-step{padding:8px;margin:8px 0;border:1px solid #e4a23b55;border-radius:8px}.hse-action-comparison{overflow:auto}.hse-action-comparison table{width:100%;border-collapse:collapse}.hse-action-comparison th,.hse-action-comparison td{padding:6px;border-bottom:1px solid #70cfff35;text-align:left}.hse-action-collapsed{display:flex;gap:10px;align-items:center}.hse-copilot-answer{font-size:12px}.hse-copilot-status{font-size:11px}.hse-editor-actions{flex-wrap:wrap}
2434
+ .hse-action-draft button{padding:7px 10px;border:1px solid #70cfff55;border-radius:7px;background:transparent;color:inherit;cursor:pointer;font:inherit}.hse-action-draft>.hse-primary{background:#2875ff;color:#fff;border-color:#2875ff}.hse-action-draft header{flex-wrap:wrap}.hse-action-draft header>span{font-size:10px;color:#a8d9ff}.hse-action-recovery,.hse-action-next-step{padding:8px;margin:8px 0;border:1px solid #e4a23b55;border-radius:8px}.hse-action-comparison{overflow:auto}.hse-action-comparison table{width:100%;border-collapse:collapse}.hse-action-comparison th,.hse-action-comparison td{padding:6px;border-bottom:1px solid #70cfff35;text-align:left}.hse-action-collapsed{display:flex;gap:10px;align-items:center}.hse-editor-actions{flex-wrap:wrap}
2482
2435
  .hse-root-switch{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px;margin:16px 0 8px;padding:14px;border:1px solid #2875ff42;border-radius:12px;background:#2875ff0b}.hse-root-switch label{grid-column:1/-1;font-size:11px;font-weight:700}.hse-root-switch input{min-width:0;padding:10px 12px;border:1px solid #c8d6e7;border-radius:8px;color:inherit;background:var(--dsw-alias-bg-layer-2,#fff);font:11px ui-monospace,SFMono-Regular,Menlo,monospace}.hse-root-switch button{padding:9px 13px;border:0;border-radius:8px;color:#fff;background:var(--ocean-600);cursor:pointer}.hse-root-switch small{grid-column:1/-1;color:var(--dsw-alias-label-secondary,#748096)}
2483
2436
  .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}
2484
2437
  .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)}
2485
2438
  .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,.hse-ask{border:0;border-radius:9px;padding:8px 11px;color:#fff;background:var(--whale-500);cursor:pointer}.hse-drawer{width:100%;min-height:0;background:var(--dsw-alias-bg-layer-1,#f2f7fc)}.hse-drawer-head{position:sticky;top:0;z-index:5;display:flex;justify-content:space-between;gap:15px;padding:14px 0;border-bottom:1px solid var(--dsw-alias-border-l1,#dce4f0);background:color-mix(in srgb,var(--dsw-alias-bg-layer-1,#f2f7fc) 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-drawer-actions{display:flex;align-items:flex-start;gap:7px}.hse-close{align-self:flex-start;background:var(--ocean-950)}.hse-workbench{padding:14px 0 48px}.hse-stage-nav{position:sticky;top:68px;z-index:4;display:grid;grid-template-columns:repeat(9,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}
2486
- .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}
2487
- .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-trial-list-state{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:9px;padding:9px 11px;border-left:3px solid var(--amber-500);border-radius:8px;background:#e4a23b14;font-size:10px}.hse-trial-list-state[data-stale=false]{border-color:var(--coral-500);background:#ee647812}.hse-trial-list-state div{min-width:0}.hse-trial-list-state b,.hse-trial-list-state small{display:block}.hse-trial-list-state small{margin-top:3px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary,#748096)}.hse-trial-list-state button{flex:none;padding:5px 9px;border:1px solid currentColor;border-radius:7px;color:var(--ocean-600);background:transparent;cursor:pointer;font:inherit}.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;align-items:center;justify-content:space-between;gap:8px;padding:7px;border-radius:6px;background:#ffffff0b;font-size:10px}.hse-criterion[data-highlight=true]{outline:2px solid #86e8ff;background:#1464c84a;animation:hse-focus-flash 2.2s ease-out}.hse-inline-ask{flex:none;padding:4px 7px;border:1px solid #70cfff66;border-radius:999px;color:#dcecff;background:transparent;cursor:pointer;font:inherit;font-size:8px}.hse-provenance{display:flex;gap:5px;flex-wrap:wrap}.hse-provenance button{padding:5px 7px;border:1px solid #70cfff4a;border-radius:999px;color:#dcecff;background:transparent;cursor:pointer;font:inherit;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}.hse-tool-action{border-top:1px solid #e3e9f1!important;color:var(--ocean-600)!important;font-weight:700}
2439
+ .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}
2440
+ .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-trial-list-state{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:9px;padding:9px 11px;border-left:3px solid var(--amber-500);border-radius:8px;background:#e4a23b14;font-size:10px}.hse-trial-list-state[data-stale=false]{border-color:var(--coral-500);background:#ee647812}.hse-trial-list-state div{min-width:0}.hse-trial-list-state b,.hse-trial-list-state small{display:block}.hse-trial-list-state small{margin-top:3px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary,#748096)}.hse-trial-list-state button{flex:none;padding:5px 9px;border:1px solid currentColor;border-radius:7px;color:var(--ocean-600);background:transparent;cursor:pointer;font:inherit}.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;align-items:center;justify-content:space-between;gap:8px;padding:7px;border-radius:6px;background:#ffffff0b;font-size:10px}.hse-criterion[data-highlight=true]{outline:2px solid #86e8ff;background:#1464c84a;animation:hse-focus-flash 2.2s ease-out}.hse-inline-ask{flex:none;padding:4px 7px;border:1px solid #70cfff66;border-radius:999px;color:#dcecff;background:transparent;cursor:pointer;font:inherit;font-size:8px}.hse-provenance{display:flex;gap:5px;flex-wrap:wrap}.hse-provenance button{padding:5px 7px;border:1px solid #70cfff4a;border-radius:999px;color:#dcecff;background:transparent;cursor:pointer;font:inherit;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}.hse-tool-action{border-top:1px solid #e3e9f1!important;color:var(--ocean-600)!important;font-weight:700}
2488
2441
  .hse-inline-ask[data-highlight=true],.hse-provenance button[data-highlight=true]{outline:2px solid #86e8ff;background:#1464c84a;animation:hse-focus-flash 2.2s ease-out}
2489
- .hse-context-dock{display:grid;gap:7px;width:100%;box-sizing:border-box;padding:10px 12px;border:1px solid #2875ff48;border-radius:12px;background:color-mix(in srgb,var(--dsw-alias-bg-layer-2,#fff) 95%,#2875ff 5%);box-shadow:0 6px 20px #17366014}.hse-context-line{display:flex;align-items:center;gap:7px;flex-wrap:wrap;font-size:10px}.hse-context-line>strong{min-width:78px}.hse-context-chip{display:inline-flex;align-items:center;gap:6px;max-width:min(520px,70vw);padding:5px 8px;border:1px solid #2875ff42;border-radius:999px;background:#2875ff10}.hse-context-chip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hse-context-chip button,.hse-context-link{padding:0;border:0;color:var(--ocean-600);background:transparent;cursor:pointer;font:inherit;font-size:9px}.hse-context-flags{display:flex;gap:5px}.hse-context-flags em{padding:3px 6px;border-radius:999px;color:#8e5b0c;background:#e4a23b1b;font-size:8px;font-style:normal}.hse-context-error{color:#bd3148}.hse-context-questions{display:flex;gap:5px;flex-wrap:wrap}.hse-context-questions button{padding:5px 8px;border:1px solid #c8d6e7;border-radius:999px;color:inherit;background:transparent;cursor:pointer;font:inherit;font-size:9px}
2490
- .hse-copilot{margin:14px 0;padding:14px;border:1px solid #2875ff45;border-radius:14px;background:linear-gradient(145deg,#03152f,#07366f);color:#dcecff}.hse-copilot-head,.hse-copilot-controls{display:flex;align-items:center;justify-content:space-between;gap:10px}.hse-copilot-head h3{margin:0;font-size:13px}.hse-copilot-head button{padding:5px 8px;border:1px solid #70cfff55;border-radius:7px;color:#dcecff;background:transparent;cursor:pointer}.hse-copilot-toggle{min-width:30px;font-weight:800}.hse-copilot-status{margin:9px 0;color:#a8d9ff;font-size:10px}.hse-copilot-tools{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:8px}.hse-copilot-tools span{padding:4px 7px;border:1px solid #70cfff42;border-radius:999px;font-size:8px}.hse-copilot-answer{max-height:360px;overflow:auto;margin:0;padding:12px;border-radius:9px;background:#ffffff0b;white-space:pre-wrap;word-break:break-word;font:inherit;font-size:11px;line-height:1.65}.hse-copilot-actions{display:flex;align-items:center;gap:8px;margin-top:9px}.hse-copilot-actions button{padding:6px 9px;border:0;border-radius:8px;color:#fff;background:var(--whale-500);cursor:pointer}.hse-copilot-actions small{color:#a8c7df}
2491
- .hse-copilot-basis{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;margin:8px 0;padding:9px;border:1px solid #70cfff36;border-radius:9px;background:#ffffff0a}.hse-copilot-basis>strong{grid-column:1/-1;color:#8fe8ff;font-size:9px;text-transform:uppercase;letter-spacing:.06em}.hse-copilot-basis span{min-width:0;font-size:9px}.hse-copilot-basis span b,.hse-copilot-basis span code,.hse-copilot-basis span time{display:block;margin-top:2px;overflow-wrap:anywhere;color:#dcecff;font:inherit}.hse-copilot-refs{display:grid;gap:6px;margin-top:9px}.hse-copilot-refs>strong{color:#a8d9ff;font-size:9px}.hse-copilot-ref{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:3px 10px;width:100%;padding:8px 10px;border:1px solid #70cfff45;border-radius:8px;color:#dcecff;background:#ffffff0a;text-align:left;cursor:pointer;font:inherit}.hse-copilot-ref b{font-size:10px}.hse-copilot-ref span{grid-row:1/3;grid-column:2;color:#8fe8ff;font-size:8px}.hse-copilot-ref code{overflow-wrap:anywhere;color:#a8c7df;font-size:8px}.hse-copilot-ref[data-available=false]{border-color:#e4a23b73}.hse-copilot-ref[data-available=false] span{color:#f3c779}
2442
+ .hse-context-flags{display:flex;gap:5px}.hse-context-flags em{padding:3px 6px;border-radius:999px;color:#8e5b0c;background:#e4a23b1b;font-size:8px;font-style:normal}.hse-context-error{color:#bd3148}
2443
+
2444
+
2492
2445
  .hse-error-state{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:13px;border-left:4px solid var(--coral-500);border-radius:10px;background:#ee647812;text-align:left}.hse-error-state>div{min-width:0}.hse-error-state b,.hse-error-state span,.hse-error-state small{display:block;overflow-wrap:anywhere}.hse-error-state b{color:#bd3148;font-size:11px}.hse-error-state span{margin-top:4px;font-size:10px}.hse-error-state small{margin-top:5px;color:var(--dsw-alias-label-secondary,#748096);font-size:9px;line-height:1.5}.hse-error-state button,.hse-filter-empty button{flex:none;padding:6px 9px;border:1px solid currentColor;border-radius:7px;color:var(--ocean-600);background:transparent;cursor:pointer;font:inherit;font-size:9px}.hse-error-state[data-category=permission]{border-color:var(--amber-500);background:#e4a23b14}.hse-error-state[data-category=permission] b{color:#8e5b0c}
2493
2446
  .hse-skeleton{display:grid;gap:9px;min-height:150px;padding:16px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:14px;background:var(--dsw-alias-bg-layer-2,#fff)}.hse-skeleton i{display:block;height:17px;border-radius:7px;background:linear-gradient(90deg,#dce6f2 20%,#eef4fa 45%,#dce6f2 70%);background-size:240% 100%;animation:hse-skeleton 1.3s ease-in-out infinite}.hse-skeleton i:first-child{height:30px;width:44%}.hse-skeleton i:nth-child(3n){width:72%}.hse-skeleton[data-kind=dashboard]{grid-template-columns:repeat(2,minmax(0,1fr));min-height:230px}.hse-skeleton[data-kind=dashboard] i:first-child{grid-column:1/-1;width:52%;height:38px}.hse-skeleton[data-kind=trial-detail]{min-height:420px;background:var(--ocean-950);border-color:#70cfff32}.hse-skeleton[data-kind=trial-detail] i{background:linear-gradient(90deg,#ffffff0d 20%,#ffffff20 45%,#ffffff0d 70%);background-size:240% 100%}.hse-filter-empty{display:grid;justify-items:center;gap:9px;min-height:120px;padding:24px;border:1px dashed #c4d3e5;border-radius:12px;color:var(--dsw-alias-label-secondary,#728097);background:var(--dsw-alias-bg-layer-2,#fff);text-align:center;font-size:10px}
2494
2447
  .hse-job{position:relative;cursor:default}.hse-job-open{display:block;width:100%;padding:0;border:0;color:inherit;background:transparent;text-align:left;cursor:pointer}.hse-job-open:focus-visible{outline:3px solid #2875ff20;outline-offset:-3px}.hse-job-body{padding-right:104px}.hse-job-ask{position:absolute;right:16px;bottom:14px;padding:7px 10px;border:0;border-radius:8px;color:#fff;background:var(--whale-500);cursor:pointer;font:inherit;font-size:9px;font-weight:800}.hse-trial-name{display:flex;align-items:center;gap:7px}.hse-trial-name .hse-trial-ask{padding:3px 6px;border:1px solid #2875ff42;border-radius:999px;font-size:8px}.hse-criterion{flex-wrap:wrap}.hse-criterion>span{margin-right:auto}.hse-context-link:disabled,.hse-job-ask:disabled{opacity:.5;cursor:wait}
@@ -2504,13 +2457,13 @@ var CSS = `
2504
2457
  @media(max-width:520px){.hse-hero{min-height:auto;padding:22px}.hse-hero h1{font-size:30px}.hse-stats{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));width:100%}.hse-stat{min-width:0}.hse-launch-card{display:grid;grid-template-columns:38px minmax(0,1fr) 108px;align-items:center;flex-wrap:nowrap}.hse-launch-copy span{display:none}.hse-launch-button{width:100%;margin:0;padding:9px;white-space:normal}.hse-launch-button-full{display:none}.hse-launch-button-short{display:inline}}
2505
2458
  @media(prefers-reduced-motion:reduce){.hse-spin,.hse-skeleton i,.hse-status:before,.hse-hero:after,.hse-criterion[data-highlight=true],.hse-inline-ask[data-highlight=true],.hse-provenance button[data-highlight=true]{animation:none}.hse-job{transition:none}.hse-job:hover{transform:none}}
2506
2459
  @media(max-width:900px){.hse-report-compare,.hse-meta-flow{grid-template-columns:1fr}.hse-meta-flow div:after{display:none}}
2507
- .hse-root{container-type:inline-size;overflow:visible}.hse-layout{display:grid;grid-template-columns:minmax(0,1fr) 320px;align-items:start;gap:18px;max-width:1600px}.hse-main-panel{grid-column:1;grid-row:1;min-width:0}.hse-layout>.hse-copilot{grid-column:2;grid-row:1;position:sticky;top:12px;margin:0;max-height:calc(100vh - 220px);overflow:auto}.hse-layout .hse-drawer{width:100%;max-width:none}.hse-layout .hse-drawer-head{position:static}.hse-copilot-basis{grid-template-columns:1fr}.hse-copilot-answer{max-height:45vh}
2460
+ .hse-root{container-type:inline-size;overflow:visible}.hse-layout{display:grid;grid-template-columns:minmax(0,1fr);align-items:start;gap:18px;max-width:1600px}.hse-main-panel{grid-column:1;grid-row:1;min-width:0}.hse-layout .hse-drawer{width:100%;max-width:none}.hse-layout .hse-drawer-head{position:static}
2508
2461
  .hse-health-summary{padding:20px;margin-bottom:16px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:16px;background:var(--dsw-alias-bg-layer-2,#fff)}.hse-health-summary h1{margin:6px 0;font-size:22px}.hse-health-summary small{letter-spacing:.07em;color:var(--ocean-600);font-size:10px}.hse-health-filters{display:flex;gap:8px;flex-wrap:wrap}.hse-health-filters button{display:grid;gap:7px;min-width:104px;flex:1;padding:12px;border:1px solid var(--dsw-alias-border-l1,#d7e2ef);border-radius:10px;background:transparent;color:inherit;cursor:pointer;text-align:left}.hse-health-filters button[aria-pressed=true]{border-color:var(--ocean-600);background:#2875ff12}.hse-health-filters span{font-size:11px}.hse-health-filters b{font-size:21px}.hse-attention-label{display:block;font-size:11px;color:var(--ocean-600);margin:5px 0}.hse-attention-label[data-kind=blocked],.hse-attention-label[data-kind=invalid]{color:var(--coral-500)}
2509
2462
  .hse-object-nav{display:flex;flex-wrap:wrap;gap:5px;padding:8px 0 14px;border-bottom:1px solid var(--dsw-alias-border-l1,#d7e2ef);margin-bottom:16px}.hse-object-nav button{padding:9px 12px;border:0;border-radius:8px;color:inherit;background:transparent;cursor:pointer;font:inherit;font-size:12px}.hse-object-nav button[aria-current=page]{color:#fff;background:var(--ocean-600);font-weight:700}.hse-job-identities{padding:12px 20px;border-bottom:1px solid var(--dsw-alias-border-l1,#d7e2ef)}.hse-identity-tags{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}.hse-identity-tags span{display:grid;gap:4px;min-width:0}.hse-identity-tags small{font-size:10px;color:var(--dsw-alias-label-secondary,#748096)}.hse-identity-tags b{font-size:11px;overflow-wrap:anywhere}.hse-identity-tags code{font-size:9px;overflow-wrap:anywhere}.hse-identity-flags{display:flex;flex-wrap:wrap;gap:10px;margin-top:10px;font-size:10px}.hse-summary-status{display:flex;justify-content:space-between;align-items:start;gap:12px}.hse-summary-status p{font-size:12px;line-height:1.6;color:var(--dsw-alias-label-secondary,#748096)}.hse-summary-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:10px;margin:15px 0}.hse-summary-metric{padding:14px;border-radius:10px;background:#2875ff0a}.hse-summary-metric>span{display:block;font-size:11px}.hse-summary-metric>strong{display:block;margin:8px 0;font-size:24px}.hse-summary-links{display:flex;gap:8px;flex-wrap:wrap}
2510
- .hse-local-actions{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:8px}.hse-local-actions button{border:1px solid #2875ff45;border-radius:6px;padding:5px 7px;background:transparent;color:var(--ocean-600);cursor:pointer;font-size:10px}.hse-local-actions code{font-size:9px;overflow-wrap:anywhere}.hse-root [data-highlight=true]{outline:2px solid #2896ff;outline-offset:3px;background:#2875ff14}.hse-capsule-parts{display:flex;gap:5px;flex-wrap:wrap;margin:8px 0}.hse-context-identity{max-width:100%;font-size:10px}.hse-context-identity pre{max-height:180px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere}.hse-source-fragment textarea{width:100%;min-height:180px;padding:12px;border:1px solid #2875ff45;border-radius:8px;background:var(--dsw-alias-bg-layer-1,#f3f7fb);color:inherit;font:11px/1.6 monospace}.hse-diff-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}.hse-diff-grid pre{max-height:280px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere}.hse-answer-unverified{padding:8px;border:1px solid #e4a23b73;border-radius:8px;font-size:11px}.hse-answer-unverified button{margin-top:8px;border:1px solid #70cfff55;border-radius:6px;background:transparent;color:inherit;padding:6px;cursor:pointer}
2511
- @container(max-width:1050px){.hse-layout{grid-template-columns:minmax(0,1fr)}.hse-layout>.hse-copilot{grid-column:1;grid-row:2;position:sticky;bottom:0;z-index:10;max-height:45vh}.hse-layout>.hse-copilot[data-collapsed=true]{max-height:60px}.hse-identity-tags{grid-template-columns:repeat(2,minmax(0,1fr))}.hse-trial-layout,.hse-output-layout,.hse-report-compare{grid-template-columns:1fr}.hse-trial-detail{position:static;max-height:none}.hse-meta-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.hse-diff-grid{grid-template-columns:1fr}}
2512
- .hse-input-dock{position:relative;width:100%;min-width:0}.hse-mobile-copilot{position:absolute;bottom:calc(100% + 6px);left:12px;right:12px;z-index:10}.hse-mobile-copilot>.hse-copilot{box-sizing:border-box;margin:0;max-height:min(40dvh,420px);overflow:auto}.hse-capsule-parts .hse-context-chip{max-width:42%;font-size:11px;display:inline-flex;align-items:center}.hse-capsule-parts .hse-context-chip>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hse-context-identity summary{font-size:10px;cursor:pointer}.hse-context-dock{padding:8px 12px}.hse-answer-text h4{margin:12px 0 6px;color:#a8d9ff;font-size:12px}.hse-answer-text p{margin:5px 0;white-space:pre-wrap}.hse-answer-text code{padding:1px 3px;border-radius:4px;background:#70cfff18;font-size:10px}.hse-answer-text pre{margin:0;font-size:10px;white-space:pre-wrap}.hse-answer-bullet{padding-left:8px}.hse-selection-bar{padding:10px;margin:8px 0;border:1px solid #2875ff25;border-radius:8px;font-size:11px}.hse-selection-bar code{font-size:9px;overflow-wrap:anywhere}.hse-saved-source textarea{min-height:180px}
2513
- .hse-action-draft{padding:12px;margin:10px 0;border:1px solid #70cfff55;border-radius:10px;font-size:11px}.hse-action-draft header{display:flex;justify-content:space-between;gap:8px}.hse-action-draft dl{display:grid;grid-template-columns:80px minmax(0,1fr);gap:5px;margin:10px 0}.hse-action-draft dd{margin:0;overflow-wrap:anywhere}.hse-action-draft code{font-size:9px;overflow-wrap:anywhere}.hse-action-draft pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:240px;overflow:auto}.hse-action-preview{padding:10px;margin:8px 0;border:1px solid #e4a23b55;border-radius:7px;font-size:11px}.hse-action-preview>code{display:block;overflow-wrap:anywhere;font-size:9px}.hse-copilot .hse-action-draft .hse-local-actions button{color:#a8d9ff;border-color:#70cfff55}.hse-action-draft button:disabled{opacity:.45;cursor:not-allowed}
2463
+ .hse-local-actions{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-top:8px}.hse-local-actions button{border:1px solid #2875ff45;border-radius:6px;padding:5px 7px;background:transparent;color:var(--ocean-600);cursor:pointer;font-size:10px}.hse-local-actions code{font-size:9px;overflow-wrap:anywhere}.hse-root [data-highlight=true]{outline:2px solid #2896ff;outline-offset:3px;background:#2875ff14}.hse-source-fragment textarea{width:100%;min-height:180px;padding:12px;border:1px solid #2875ff45;border-radius:8px;background:var(--dsw-alias-bg-layer-1,#f3f7fb);color:inherit;font:11px/1.6 monospace}.hse-diff-grid{display:grid;grid-template-columns:1fr 1fr;gap:10px}.hse-diff-grid pre{max-height:280px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere}.hse-answer-unverified{padding:8px;border:1px solid #e4a23b73;border-radius:8px;font-size:11px}.hse-answer-unverified button{margin-top:8px;border:1px solid #70cfff55;border-radius:6px;background:transparent;color:inherit;padding:6px;cursor:pointer}
2464
+ @container(max-width:1050px){.hse-layout{grid-template-columns:minmax(0,1fr)}.hse-identity-tags{grid-template-columns:repeat(2,minmax(0,1fr))}.hse-trial-layout,.hse-output-layout,.hse-report-compare{grid-template-columns:1fr}.hse-trial-detail{position:static;max-height:none}.hse-meta-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.hse-diff-grid{grid-template-columns:1fr}}
2465
+ .hse-selection-bar{padding:10px;margin:8px 0;border:1px solid #2875ff25;border-radius:8px;font-size:11px}.hse-selection-bar code{font-size:9px;overflow-wrap:anywhere}.hse-saved-source textarea{min-height:180px}
2466
+ .hse-action-draft{padding:12px;margin:10px 0;border:1px solid #70cfff55;border-radius:10px;font-size:11px}.hse-action-draft header{display:flex;justify-content:space-between;gap:8px}.hse-action-draft dl{display:grid;grid-template-columns:80px minmax(0,1fr);gap:5px;margin:10px 0}.hse-action-draft dd{margin:0;overflow-wrap:anywhere}.hse-action-draft code{font-size:9px;overflow-wrap:anywhere}.hse-action-draft pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:240px;overflow:auto}.hse-action-preview{padding:10px;margin:8px 0;border:1px solid #e4a23b55;border-radius:7px;font-size:11px}.hse-action-preview>code{display:block;overflow-wrap:anywhere;font-size:9px}.hse-action-draft button:disabled{opacity:.45;cursor:not-allowed}
2514
2467
  `;
2515
2468
  function installStyles() {
2516
2469
  const id = "dsh-harbor-evolution/client";
@@ -3063,9 +3016,6 @@ function harborTurnProjection(nodes, token) {
3063
3016
  const projected = candidates.filter((node) => turn === void 0 || !Number.isFinite(node?.turn) || node.turn === turn);
3064
3017
  return { nodes: projected, active: boundaryIndex === values.length, anchorSeq, turn };
3065
3018
  }
3066
- function assistantText(node) {
3067
- return Array.isArray(node?.blocks) ? node.blocks.filter((block) => block?.kind === "text").map((block) => block.text).join("\n") : "";
3068
- }
3069
3019
  function toolResultValue(node) {
3070
3020
  if (!node || node.kind !== "tool-result" || node.isError) return void 0;
3071
3021
  if (isRecord(node.value)) return node.value;
@@ -3154,12 +3104,6 @@ function ContextFlags({ context, t }) {
3154
3104
  ].filter(Boolean);
3155
3105
  return values.length ? /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-context-flags" }, values.map((value) => /* @__PURE__ */ import_react5.default.createElement("em", { key: value }, value))) : null;
3156
3106
  }
3157
- function harborReferenceIdentity(reference) {
3158
- const value = reference?.ref ?? reference?.action?.target ?? {};
3159
- const parts = [value.job, value.trial, value.criterion, value.evidenceRef].filter(Boolean);
3160
- if (parts.length) return parts.join(" / ");
3161
- return value.id ?? reference?.action?.target?.route ?? "\u2014";
3162
- }
3163
3107
  function harborSubmissionTransition(submitted, explicit, phase, hasReference) {
3164
3108
  let pending = submitted;
3165
3109
  if (explicit && hasReference && ["adjudicating", "submitting"].includes(phase)) pending = explicit;
@@ -3267,47 +3211,20 @@ function removeContextPart(context, part) {
3267
3211
  }
3268
3212
  return next;
3269
3213
  }
3270
- function ContextDock({ bridge, sessionId, useInput, useSession, stop, inputActions, replaceHarborReference, clearHarborReferences, t }) {
3214
+ function HarborInputSync({ bridge, sessionId, useInput, replaceHarborReference }) {
3271
3215
  const ui = useHarborUi(bridge, sessionId);
3272
- const dockNode = (0, import_react5.useRef)();
3273
3216
  const draft = useInput((state) => state?.draft ?? "");
3274
3217
  const phase = useInput((state) => state?.phase ?? "plain");
3275
- const phaseRef = (0, import_react5.useRef)(phase);
3276
- phaseRef.current = phase;
3277
3218
  const occurrences = useInput((state) => state?.occurrences ?? []);
3278
3219
  const submitted = (0, import_react5.useRef)();
3279
3220
  const observedTokens = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
3280
- const [clock, setClock] = (0, import_react5.useState)(Date.now);
3281
3221
  const explicit = ui.explicit;
3282
3222
  const token = explicit?.contextSnapshotId;
3283
3223
  const hasReference = hasHarborReference(draft, occurrences, token);
3284
- const expiry = Date.parse(explicit?.expiresAt ?? "");
3285
- const expired = isExplicitContextExpired(explicit?.expiresAt, clock);
3286
- (0, import_react5.useEffect)(() => {
3287
- const measure = () => {
3288
- const top = dockNode.current?.getBoundingClientRect().top;
3289
- if (Number.isFinite(top) && bridge.getSnapshot(sessionId).composerTop !== Math.floor(top)) bridge.update(sessionId, { composerTop: Math.floor(top) });
3290
- };
3291
- const frame = window.requestAnimationFrame(measure);
3292
- const observer = new ResizeObserver(measure);
3293
- if (dockNode.current) observer.observe(dockNode.current);
3294
- window.addEventListener("resize", measure);
3295
- return () => {
3296
- window.cancelAnimationFrame(frame);
3297
- observer.disconnect();
3298
- window.removeEventListener("resize", measure);
3299
- };
3300
- }, [bridge, sessionId, draft, phase, token]);
3301
3224
  (0, import_react5.useEffect)(() => {
3302
3225
  if (!explicit || isHarborInputBusy(phase) || !needsStructuredHarborNormalization(draft, occurrences, explicit, observedTokens.current.has(token))) return;
3303
3226
  replaceHarborReference?.(explicit, "");
3304
3227
  }, [draft, explicit, occurrences, phase, replaceHarborReference, token]);
3305
- (0, import_react5.useEffect)(() => {
3306
- setClock(Date.now());
3307
- if (!Number.isFinite(expiry) || expiry <= Date.now()) return void 0;
3308
- const timer = window.setTimeout(() => setClock(Date.now()), Math.min(expiry - Date.now() + 25, 2147483647));
3309
- return () => window.clearTimeout(timer);
3310
- }, [expiry]);
3311
3228
  (0, import_react5.useEffect)(() => {
3312
3229
  if (token && hasReference) observedTokens.current.add(token);
3313
3230
  const wasObserved = Boolean(token && observedTokens.current.has(token));
@@ -3322,63 +3239,7 @@ function ContextDock({ bridge, sessionId, useInput, useSession, stop, inputActio
3322
3239
  observedTokens.current.delete(token);
3323
3240
  }
3324
3241
  }, [bridge, explicit, hasReference, phase, sessionId, token]);
3325
- const bind = async (context) => {
3326
- if (!context || !inputActions) return void 0;
3327
- return bridge.issue(sessionId, context, { forceNew: true });
3328
- };
3329
- const update = async (context) => {
3330
- try {
3331
- const issued = await bind(context);
3332
- commitIssuedDraft(bridge, sessionId, issued, replaceHarborReference, "", phaseRef.current, true);
3333
- return issued;
3334
- } catch {
3335
- return void 0;
3336
- }
3337
- };
3338
- const clear = () => {
3339
- if (clearHarborReferences?.() !== true) return;
3340
- bridge.clearExplicit(sessionId, token);
3341
- };
3342
- const removePart = async (part) => {
3343
- const context = removeContextPart(explicit?.context, part);
3344
- if (!context) {
3345
- clear();
3346
- return;
3347
- }
3348
- await update(context);
3349
- };
3350
- const capsuleContext = explicit?.context;
3351
- const capsuleParts = capsuleContext ? [
3352
- { key: "job", label: capsuleContext.object?.job ? `Job ${capsuleContext.object.job}` : `Harbor ${capsuleContext.workspace}` },
3353
- ...capsuleContext.object?.trial ? [{ key: "trial", label: `Trial ${capsuleContext.object.trial}` }] : [],
3354
- ...(capsuleContext.selection ?? []).map((ref, index) => ({ key: `selection-${index}`, label: `${ref.kind}${ref.selectionCount ? ` (${ref.selectionCount})` : ""} \xB7 ${ref.criterion ?? ref.evidenceRef ?? short(ref.id)}${ref.startLine ? ` \xB7 L${ref.startLine}\u2013${ref.endLine}` : ""}` }))
3355
- ] : [];
3356
- const ask = async (prompt, context) => {
3357
- if (expired) return;
3358
- try {
3359
- const reusingExplicit = Boolean(explicit && !context);
3360
- const issued = reusingExplicit ? explicit : await bind(context ?? ui.current);
3361
- if (!issued) return;
3362
- commitIssuedDraft(bridge, sessionId, issued, replaceHarborReference, prompt, phaseRef.current, !reusingExplicit);
3363
- } catch {
3364
- }
3365
- };
3366
- return /* @__PURE__ */ import_react5.default.createElement(HarborSessionContext.Provider, { value: sessionId }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-input-dock", ref: dockNode }, ui.workbenchDock?.narrow ? /* @__PURE__ */ import_react5.default.createElement("aside", { className: "hse-mobile-copilot" }, /* @__PURE__ */ import_react5.default.createElement(CopilotDock, { bridge, sessionId, useSession, stop, resolveLatest: ui.workbenchDock.resolveLatest, reanalyzeLatest: ui.workbenchDock.reanalyzeLatest, prepareQuestion: ui.workbenchDock.prepareQuestion, t })) : null, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-context-dock", "aria-live": "polite" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-context-line" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, t("currentPage")), ui.current ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-context-chip" }, /* @__PURE__ */ import_react5.default.createElement("span", null, contextLabel(ui.current))), /* @__PURE__ */ import_react5.default.createElement(ContextFlags, { context: ui.current, t }), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-context-link", disabled: ui.status === "binding", onClick: () => void update(ui.current) }, explicit ? t("updateContext") : t("askAboutThis"))) : /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-muted" }, "Harbor \u2014")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-context-line" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, t("turnContext")), explicit ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-context-chip" }, /* @__PURE__ */ import_react5.default.createElement("span", null, explicit.context.route?.params?.stage ?? "Harbor"), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", "aria-label": t("clearContext"), disabled: isHarborInputBusy(phase), onClick: clear }, t("clearContext"), " \xD7")), /* @__PURE__ */ import_react5.default.createElement(ContextFlags, { context: explicit.context, t }), expired ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("em", { className: "hse-context-error" }, t("contextExpired")), /* @__PURE__ */ import_react5.default.createElement("small", null, t("contextExpiredHint")), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-context-link", disabled: !ui.current || ui.status === "binding", onClick: () => void update(ui.current) }, t("updateContext"))) : /* @__PURE__ */ import_react5.default.createElement("small", null, t("oneShot"))) : /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-muted" }, ui.status === "binding" ? t("bindingContext") : t("noTurnContext"))), explicit ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-capsule-parts" }, capsuleParts.map((part) => /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-context-chip", key: part.key }, /* @__PURE__ */ import_react5.default.createElement("span", null, part.label), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", "aria-label": `${t("clearContext")} ${part.label}`, disabled: isHarborInputBusy(phase) || ui.status === "binding", onClick: () => void removePart(part.key) }, "\xD7"))), /* @__PURE__ */ import_react5.default.createElement("details", { className: "hse-context-identity" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, t("contextIdentity")), /* @__PURE__ */ import_react5.default.createElement("pre", null, pretty2({ ...capsuleContext, contextSnapshotId: explicit.contextSnapshotId, expiresAt: explicit.expiresAt })))) : null, ui.error ? /* @__PURE__ */ import_react5.default.createElement(HarborErrorState, { error: ui.error, title: t("contextBindFailed"), t }) : null, ui.current ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-context-questions", "aria-label": t("questionSuggestions") }, harborQuestionKeys(explicit?.context ?? ui.current).map((key) => /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", key, disabled: expired || isHarborInputBusy(phase) || ui.status === "binding", onClick: () => void ask(t(key)) }, t(harborQuestionLabelKey(key)))), ui.lastSent?.context && !explicit ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", disabled: isHarborInputBusy(phase) || ui.status === "binding", title: t("followupHint"), onClick: () => void ask("", ui.lastSent.context) }, t("continueObject")) : null) : null)));
3367
- }
3368
- function AnswerText({ text }) {
3369
- const lines = String(text ?? "").split("\n");
3370
- let code = false;
3371
- const inline = (line) => line.split(/(`[^`]+`)/g).map((part, i) => part.startsWith("`") && part.endsWith("`") ? /* @__PURE__ */ import_react5.default.createElement("code", { key: i }, part.slice(1, -1)) : part);
3372
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-answer-text" }, lines.map((line, index) => {
3373
- if (line.startsWith("```")) {
3374
- code = !code;
3375
- return /* @__PURE__ */ import_react5.default.createElement("hr", { key: index });
3376
- }
3377
- if (code) return /* @__PURE__ */ import_react5.default.createElement("pre", { key: index }, line || " ");
3378
- if (/^#{1,4} /.test(line)) return /* @__PURE__ */ import_react5.default.createElement("h4", { key: index }, inline(line.replace(/^#{1,4} /, "")));
3379
- if (/^[-*] /.test(line)) return /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-answer-bullet", key: index }, "\u2022 ", inline(line.slice(2)));
3380
- return line.trim() ? /* @__PURE__ */ import_react5.default.createElement("p", { key: index }, inline(line)) : null;
3381
- }));
3242
+ return null;
3382
3243
  }
3383
3244
  function ActionDraftCard({ draft, onSourceDraft, onReprepare, onViewComparison, onViewResult, t }) {
3384
3245
  const update = useHarborMutation();
@@ -3436,40 +3297,19 @@ function actionDraftContext(draft, sessionId, pageSessionId) {
3436
3297
  }
3437
3298
  return context;
3438
3299
  }
3439
- function CopilotDock({ bridge, sessionId, useSession, stop, resolveLatest, reanalyzeLatest, prepareQuestion, t }) {
3440
- const request = useHarborApi();
3441
- const update = useHarborMutation();
3442
- const [expanded, setExpanded] = (0, import_react5.useState)(() => !bridge.getSnapshot(sessionId).workbenchDock?.narrow);
3443
- const [selectedSeq, setSelectedSeq] = (0, import_react5.useState)();
3444
- const [latest, setLatest] = (0, import_react5.useState)({ status: "idle" });
3445
- const latestSequence = (0, import_react5.useRef)(0);
3446
- const ui = useHarborUi(bridge, sessionId);
3447
- const nodes = useSession((state) => state?.nodes ?? []);
3448
- (0, import_react5.useEffect)(() => {
3449
- if (bridge.getSnapshot(sessionId).lastSent) return;
3450
- const recovered = recoverHarborTurn(nodes, sessionId);
3451
- if (recovered) bridge.update(sessionId, { lastSent: recovered });
3452
- }, [bridge, nodes, sessionId]);
3453
- const partial = useSession((state) => state?.partial ?? null);
3454
- const runningCalls = useSession((state) => state?.runningCalls ?? []);
3455
- const running = useSession((state) => Boolean(state?.running));
3456
- const lastAgentError = useSession((state) => state?.lastAgentError ?? null);
3457
- const projection = harborConversationProjection(nodes, ui.lastSent?.contextSnapshotId, selectedSeq);
3458
- const recent = projection.nodes;
3459
- const completed = [...recent].reverse().find((node) => node?.kind === "assistant");
3460
- const answer = projection.active && running && partial ? assistantText(partial) : assistantText(completed);
3461
- const settledTools = recent.filter((node) => node?.kind === "tool-result").map((node) => node.call?.name ?? node.callId).filter(Boolean);
3462
- const references = trustedHarborReferences(recent);
3463
- const action = toolUiAction(recent) ?? ui.pendingAction;
3464
- const resolved = trustedHarborResolvedContext(recent);
3465
- const actionDrafts = recent.filter((node) => node?.call?.name === "harbor_propose_action").map(toolResultValue).filter((value) => value?.schema === "harbor-action-draft/v1" && value?.draftId);
3300
+ function createHarborActionHandlers({ bridge, sessionId, prepareQuestion, onNavigate, t }) {
3301
+ const navigate = (action) => {
3302
+ const accepted = bridge.navigate(sessionId, action, { force: true });
3303
+ onNavigate?.(accepted);
3304
+ return accepted;
3305
+ };
3466
3306
  const openSourceDraft = (draft) => {
3467
3307
  bridge.update(sessionId, { evaluatorProposal: { ...draft, reviewRequestId: pageSessionIdentity() } });
3468
3308
  const ref = draft.proposal?.sourceRef;
3469
- if (ref) bridge.navigate(sessionId, { kind: "harbor.navigate", actionId: `draft-source-${draft.draftId}`, target: { route: "harbor.evaluator", workspace: draft.target.workspace, job: ref.job, stage: "judge" } }, { force: true });
3309
+ if (ref) navigate({ kind: "harbor.navigate", actionId: `draft-source-${draft.draftId}`, target: { route: "harbor.evaluator", workspace: draft.target.workspace, job: ref.job, stage: "judge" } });
3470
3310
  };
3471
3311
  const reprepare = async (draft) => {
3472
- const original = actionDraftContext(draft, sessionId, ui.current?.pageSessionId ?? ui.lastSent?.context?.pageSessionId);
3312
+ const original = actionDraftContext(draft, sessionId, bridge.getSnapshot(sessionId).current?.pageSessionId ?? bridge.getSnapshot(sessionId).lastSent?.context?.pageSessionId ?? pageSessionIdentity());
3473
3313
  if (!original) return false;
3474
3314
  const prepared = await prepareQuestion?.(original, `${t("repreparePrompt")}
3475
3315
  ${draft.proposal?.summary ?? ""}`);
@@ -3477,52 +3317,13 @@ ${draft.proposal?.summary ?? ""}`);
3477
3317
  if (!prepared && ["conflict", "expired"].includes(error?.category)) {
3478
3318
  const source = draft.proposal?.sourceRef;
3479
3319
  bridge.update(sessionId, { error: { ...error, nextStep: t("draftRecoveryReselect") } });
3480
- bridge.navigate(sessionId, { kind: "harbor.navigate", actionId: `reselect-${draft.draftId}`, target: { route: source ? "harbor.evaluator" : "harbor.job", workspace: draft.target.workspace, job: draft.target.job, stage: source || draft.selection?.some((ref) => /trial-set/.test(ref.kind)) ? "judge" : original.route.params.stage, ...draft.target.trial ? { trial: draft.target.trial } : {} } }, { force: true });
3320
+ navigate({ kind: "harbor.navigate", actionId: `reselect-${draft.draftId}`, target: { route: source ? "harbor.evaluator" : "harbor.job", workspace: draft.target.workspace, job: draft.target.job, stage: source || draft.selection?.some((ref) => /trial-set/.test(ref.kind)) ? "judge" : original.route.params.stage, ...draft.target.trial ? { trial: draft.target.trial } : {} } });
3481
3321
  }
3482
3322
  return prepared === true;
3483
3323
  };
3484
- const viewComparison = (draft) => bridge.navigate(sessionId, { kind: "harbor.navigate", actionId: `comparison-${draft.draftId}`, target: { route: "harbor.compare", workspace: draft.target.workspace, job: draft.target.job, stage: "gate", baseline: draft.target.baseline, candidate: draft.target.candidate } }, { force: true });
3485
- const viewDiagnostic = (draft, result) => bridge.navigate(sessionId, { kind: "harbor.navigate", actionId: `diagnostic-result-${draft.operationId}`, target: { route: "harbor.job", workspace: draft.target.workspace, job: result.jobName, stage: "judge" } }, { force: true });
3486
- const activeCalls = projection.active ? runningCalls : [];
3487
- const activeRunning = projection.active && running;
3488
- const relevantError = projection.active ? lastAgentError : null;
3489
- const turnId = projection.turn ?? projection.anchorSeq;
3490
- const token = resolved?.contextSnapshotId ?? projection.contextToken ?? ui.lastSent?.contextSnapshotId;
3491
- const completionId = completed?.messageId ?? completed?.seq;
3492
- const refreshLatest = (0, import_react5.useCallback)(async () => {
3493
- if (!token || !resolveLatest) return;
3494
- const sequence = ++latestSequence.current;
3495
- try {
3496
- const value = await resolveLatest(token, sessionId);
3497
- if (sequence === latestSequence.current) setLatest({ status: "ready", token, turnId, value });
3498
- } catch (error) {
3499
- if (sequence !== latestSequence.current) return;
3500
- const expired = /(?:^|_)EXPIRED\b|\bexpired\b/i.test(`${error?.code ?? ""} ${error?.message ?? ""}`);
3501
- setLatest({ status: "error", token, turnId, freshness: expired ? "EXPIRED" : "UNAVAILABLE", error: normalizeHarborUiError(error) });
3502
- }
3503
- }, [resolveLatest, sessionId, token, turnId]);
3504
- (0, import_react5.useEffect)(() => {
3505
- latestSequence.current += 1;
3506
- if (!token || !completionId || activeRunning || !resolveLatest || !resolved) {
3507
- setLatest({ status: "idle" });
3508
- return void 0;
3509
- }
3510
- void refreshLatest();
3511
- const timer = window.setInterval(() => void refreshLatest(), 15e3);
3512
- return () => {
3513
- window.clearInterval(timer);
3514
- latestSequence.current += 1;
3515
- };
3516
- }, [activeRunning, completionId, refreshLatest, resolveLatest, token, resolved?.contextSnapshotId]);
3517
- const currentLatest = latest.token === token ? latest : void 0;
3518
- const origin = trustedHarborResolvedContext(projection.originNodes ?? []);
3519
- const discussionContext = resolvedUiContext(resolved ?? origin, sessionId) ?? (token === ui.lastSent?.contextSnapshotId ? ui.lastSent?.context : void 0);
3520
- const freshness = resolved ? currentLatest?.value?.freshness ?? currentLatest?.freshness ?? resolved.freshness : "UNVERIFIED";
3521
- const contextSummary = resolved?.context ?? (projection.continuation ? void 0 : discussionContext);
3522
- const basis = harborDisplayedAnswerBasis(resolved, references, projection.continuation, currentLatest?.value, discussionContext);
3523
- const stale = freshness === "DRIFTED_READ_ONLY" || freshness === "DRIFTED" || freshness === "EXPIRED";
3524
- const status = relevantError ? t("copilotFailed") : activeCalls.length ? t("copilotReading") : activeRunning ? t("copilotAnalyzing") : ui.lastSent ? t("fullConversation") : t("copilotIdle");
3525
- return /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-copilot", style: !ui.workbenchDock?.narrow && ui.composerTop ? { maxHeight: Math.max(80, ui.composerTop - 120), boxSizing: "border-box" } : void 0, "data-collapsed": String(!expanded), "aria-live": "polite" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-head" }, /* @__PURE__ */ import_react5.default.createElement("h3", null, "\u{1F433} ", t("copilot")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-controls" }, activeRunning && stop ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => void stop() }, t("stopAgent")) : null, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-copilot-toggle", "aria-expanded": expanded, "aria-label": expanded ? t("collapse") : t("expand"), onClick: () => setExpanded((value) => !value) }, expanded ? "\u2212" : "+"))), !expanded ? /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-copilot-status" }, activeRunning ? status : answer ? t("replyReady") : t("copilotIdle")) : null, /* @__PURE__ */ import_react5.default.createElement(OperationTray, { ...{ sessionId, request, update }, scopeKey: ui.current?.workspace, t: (key) => t(`operationTray_${key}`), onViewResult: (operation, result) => viewDiagnostic(operation, result) }), expanded ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-copilot-status" }, status), projection.turns?.length > 1 ? /* @__PURE__ */ import_react5.default.createElement("details", { className: "hse-discussion-history" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, t("discussionHistory"), " \xB7 ", projection.turns.length), projection.turns.map((item) => /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", key: item.seq, "aria-current": item.seq === projection.selectedSeq ? "true" : void 0, onClick: () => setSelectedSeq(item.seq) }, item.question || t("aiQuestion"))), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => setSelectedSeq(void 0) }, t("latestReply"))) : null, projection.question ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-question" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, t("aiQuestion")), /* @__PURE__ */ import_react5.default.createElement("p", null, projection.question)) : null, projection.continuation ? /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-copilot-status" }, t("followupUnbound")) : null, token ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-hook-state" }, /* @__PURE__ */ import_react5.default.createElement("b", null, t("copilotTurn"), ": ", turnId ?? "\u2014"), /* @__PURE__ */ import_react5.default.createElement("br", null), contextSummary ? contextLabel(contextSummary) : basis?.job ? `Job ${basis.job}` : t("historyOnly"), stale ? /* @__PURE__ */ import_react5.default.createElement("p", null, t("contextStale")) : null) : null, answer ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-answer" }, /* @__PURE__ */ import_react5.default.createElement(AnswerText, { text: answer })) : null, answer && !activeRunning && !references.some((ref) => ref.kind === "evidence" && ref.available) ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-answer-unverified", role: "status" }, /* @__PURE__ */ import_react5.default.createElement("p", null, t("evidenceNotChecked"))) : null, references.length ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-refs" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, references.some((reference) => reference.kind === "evidence") ? t("evidenceRefs") : t("objectRefs")), references.map((reference) => /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-copilot-ref", "data-available": String(reference.available), key: reference.action.actionId, onClick: () => bridge.navigate(sessionId, reference.action, { force: true }) }, /* @__PURE__ */ import_react5.default.createElement("b", null, reference.label ?? t("viewInHarbor")), /* @__PURE__ */ import_react5.default.createElement("span", null, reference.kind === "evidence" ? t("evidence") : t("objectRefs")), /* @__PURE__ */ import_react5.default.createElement("code", null, harborReferenceIdentity(reference), reference.available ? "" : ` \xB7 ${t("evidenceUnavailable")}`)))) : null, actionDrafts.map((draft) => /* @__PURE__ */ import_react5.default.createElement(ActionDraftCard, { key: draft.draftId, draft, onSourceDraft: openSourceDraft, onReprepare: reprepare, onViewComparison: viewComparison, onViewResult: (result) => viewDiagnostic(draft, result), t })), discussionContext && prepareQuestion ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-actions" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", disabled: activeRunning || ui.status === "binding", onClick: () => void prepareQuestion(discussionContext, "") }, t("continueObject")), /* @__PURE__ */ import_react5.default.createElement("small", null, t("followupHint"))) : null, basis || activeCalls.length || settledTools.length ? /* @__PURE__ */ import_react5.default.createElement("details", { className: "hse-answer-details" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, t("answerDetails")), /* @__PURE__ */ import_react5.default.createElement("p", null, t("contextFreshness"), ": ", freshness ?? "\u2014"), activeCalls.length || settledTools.length ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-tools" }, [...activeCalls.map((call) => call.name ?? call.toolName ?? call.callId), ...settledTools].filter(Boolean).map((name2, index) => /* @__PURE__ */ import_react5.default.createElement("span", { key: `${name2}-${index}` }, name2))) : null, basis ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-basis" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, t("basedOn")), basis.job ? /* @__PURE__ */ import_react5.default.createElement("span", null, "Job", /* @__PURE__ */ import_react5.default.createElement("b", null, basis.job)) : null, basis.artifactRevision ? /* @__PURE__ */ import_react5.default.createElement("span", null, t("revision"), /* @__PURE__ */ import_react5.default.createElement("code", null, short(basis.artifactRevision))) : null, basis.currentRevision && basis.currentRevision !== basis.artifactRevision ? /* @__PURE__ */ import_react5.default.createElement("span", null, t("currentRevision"), /* @__PURE__ */ import_react5.default.createElement("code", null, short(basis.currentRevision))) : null, basis.observedAt ? /* @__PURE__ */ import_react5.default.createElement("span", null, t("observedAt"), /* @__PURE__ */ import_react5.default.createElement("time", { dateTime: basis.observedAt }, new Date(basis.observedAt).toLocaleString())) : null) : null) : null, relevantError ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-context-error" }, relevantError) : null, currentLatest?.status === "error" && freshness !== "EXPIRED" ? /* @__PURE__ */ import_react5.default.createElement(HarborErrorState, { error: currentLatest.error, t }) : null, stale && reanalyzeLatest ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-actions" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => void reanalyzeLatest(discussionContext) }, t("reanalyzeLatest"))) : null, !references.length && action ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-copilot-actions" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => bridge.navigate(sessionId, action, { force: true }) }, t("viewInHarbor"))) : null) : null);
3324
+ const viewComparison = (draft) => navigate({ kind: "harbor.navigate", actionId: `comparison-${draft.draftId}`, target: { route: "harbor.compare", workspace: draft.target.workspace, job: draft.target.job, stage: "gate", baseline: draft.target.baseline, candidate: draft.target.candidate } });
3325
+ const viewDiagnostic = (draft, result) => navigate({ kind: "harbor.navigate", actionId: `diagnostic-result-${draft.operationId}`, target: { route: "harbor.job", workspace: draft.target.workspace, job: result.jobName, stage: "judge" } });
3326
+ return { openSourceDraft, reprepare, viewComparison, viewDiagnostic };
3526
3327
  }
3527
3328
  function MetricPills({ metrics }) {
3528
3329
  return /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-metrics" }, Object.entries(metrics ?? {}).map(([key, value]) => /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-pill", key }, key, /* @__PURE__ */ import_react5.default.createElement("b", null, format2(value)))));
@@ -4717,25 +4518,24 @@ function historicalError(value) {
4717
4518
  const code = value?.code ?? message.match(/\b([A-Z][A-Z0-9_]{3,})\b/)?.[1] ?? "HISTORICAL_JOB_FAILED";
4718
4519
  return { code, message: message.replace(new RegExp(`^${code}:\\s*`), ""), observedAt: (/* @__PURE__ */ new Date()).toISOString() };
4719
4520
  }
4720
- function historicalErrorHint(code, t) {
4721
- if (code === "NO_ELIGIBLE_SESSIONS") return t("noEligibleHint");
4722
- if (code === "SESSION_SELECTION_TOO_EXPENSIVE") return t("narrowScanHint");
4723
- if (/SESSION_(?:SAMPLE|FEEDBACK)_CHANGED|WORKSPACE_MISMATCH|TOKEN_(?:INVALID|EXPIRED)|PREVIEW_(?:INVALID|WORKSPACE_MISMATCH)/.test(code)) return t("changedSessionHint");
4724
- return t("historicalGenericError");
4725
- }
4726
4521
  function HistoricalLauncher({ snapshot, reload, onCompleted, t }) {
4727
4522
  const request = useHarborApi();
4728
4523
  const update = useHarborMutation();
4729
4524
  const [state, setState] = (0, import_react5.useState)({ status: "idle" });
4730
4525
  const [open, setOpen] = (0, import_react5.useState)(false);
4526
+ const previewSequence = (0, import_react5.useRef)(0);
4527
+ const workspaceGeneration = (0, import_react5.useRef)(0);
4731
4528
  const workspace = snapshot?.workspace?.id;
4732
4529
  const operationId = state.operation?.operationId;
4733
4530
  (0, import_react5.useEffect)(() => {
4734
4531
  let alive = true;
4532
+ previewSequence.current += 1;
4533
+ workspaceGeneration.current += 1;
4735
4534
  setState({ status: "idle" });
4736
4535
  setOpen(false);
4737
4536
  if (!workspace) return () => {
4738
4537
  alive = false;
4538
+ workspaceGeneration.current += 1;
4739
4539
  };
4740
4540
  void request("historical-operation", { workspace }).then((operation) => {
4741
4541
  if (alive && ["queued", "running"].includes(operation?.status)) {
@@ -4745,6 +4545,8 @@ function HistoricalLauncher({ snapshot, reload, onCompleted, t }) {
4745
4545
  });
4746
4546
  return () => {
4747
4547
  alive = false;
4548
+ previewSequence.current += 1;
4549
+ workspaceGeneration.current += 1;
4748
4550
  };
4749
4551
  }, [request, workspace]);
4750
4552
  (0, import_react5.useEffect)(() => {
@@ -4756,10 +4558,12 @@ function HistoricalLauncher({ snapshot, reload, onCompleted, t }) {
4756
4558
  const operation = await request("historical-operation", { workspace, operationId });
4757
4559
  if (!alive) return;
4758
4560
  if (operation.status === "completed") {
4561
+ const generation = workspaceGeneration.current;
4562
+ const sequence = previewSequence.current;
4759
4563
  setState({ status: "completed", operation });
4760
4564
  setOpen(false);
4761
4565
  await reload(true);
4762
- if (alive) onCompleted(operation);
4566
+ if (generation === workspaceGeneration.current && sequence === previewSequence.current) onCompleted(operation);
4763
4567
  return;
4764
4568
  }
4765
4569
  if (operation.status === "failed") {
@@ -4782,38 +4586,45 @@ function HistoricalLauncher({ snapshot, reload, onCompleted, t }) {
4782
4586
  if (!open) return void 0;
4783
4587
  const escape = (event) => {
4784
4588
  if (event.key !== "Escape") return;
4589
+ previewSequence.current += 1;
4785
4590
  setOpen(false);
4786
4591
  if (!["running", "starting"].includes(state.status)) setState({ status: "idle" });
4787
4592
  };
4788
4593
  window.addEventListener("keydown", escape);
4789
4594
  return () => window.removeEventListener("keydown", escape);
4790
4595
  }, [open, state.status]);
4791
- const preview = async (days) => {
4596
+ const preview = async () => {
4597
+ const sequence = ++previewSequence.current;
4792
4598
  setOpen(true);
4793
4599
  setState({ status: "previewing" });
4794
4600
  try {
4795
4601
  const value = await update("historical-preview", {
4796
4602
  workspace,
4797
- limit: 10,
4798
- includeFeedback: true,
4799
- ...days ? { createdAfter: new Date(Date.now() - days * 864e5).toISOString() } : {}
4603
+ limit: 3,
4604
+ includeFeedback: true
4800
4605
  });
4606
+ if (sequence !== previewSequence.current) return;
4801
4607
  setState({ status: "ready", preview: value });
4802
4608
  } catch (error) {
4609
+ if (sequence !== previewSequence.current) return;
4803
4610
  setState({ status: "error", error: historicalError(error) });
4804
4611
  }
4805
4612
  };
4806
4613
  const confirm = async () => {
4807
4614
  if (!state.preview) return;
4615
+ const generation = workspaceGeneration.current;
4808
4616
  setState((current) => ({ ...current, status: "starting" }));
4809
4617
  try {
4810
4618
  const operation = await update("historical-run", { workspace, previewId: state.preview.previewId });
4619
+ if (generation !== workspaceGeneration.current) return;
4811
4620
  setState({ status: "running", operation });
4812
4621
  } catch (error) {
4622
+ if (generation !== workspaceGeneration.current) return;
4813
4623
  const normalized = historicalError(error);
4814
4624
  if (normalized.code === "HISTORICAL_JOB_ALREADY_RUNNING") {
4815
4625
  try {
4816
4626
  const operation = await request("historical-operation", { workspace });
4627
+ if (generation !== workspaceGeneration.current) return;
4817
4628
  if (["queued", "running"].includes(operation?.status)) {
4818
4629
  setState({ status: "running", operation });
4819
4630
  return;
@@ -4821,23 +4632,26 @@ function HistoricalLauncher({ snapshot, reload, onCompleted, t }) {
4821
4632
  } catch {
4822
4633
  }
4823
4634
  }
4635
+ if (generation !== workspaceGeneration.current) return;
4824
4636
  setState({ status: "error", error: normalized });
4825
4637
  }
4826
4638
  };
4827
4639
  const close = () => {
4640
+ previewSequence.current += 1;
4828
4641
  setOpen(false);
4829
4642
  if (!["running", "starting"].includes(state.status)) setState({ status: "idle" });
4830
4643
  };
4831
4644
  const previewValue = state.preview;
4832
- const evaluator = previewValue?.evaluation?.evaluator;
4833
4645
  const judge = previewValue?.evaluation?.judge;
4834
4646
  const active = ["running", "starting"].includes(state.status);
4835
4647
  const buttonLabel = active ? t("historicalActive") : state.status === "previewing" ? t("historicalPreparing") : t("historicalLaunch");
4836
4648
  const buttonShort = active ? t("historicalActiveShort") : state.status === "previewing" ? t("historicalPreparingShort") : t("historicalLaunchShort");
4837
- return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-card", "aria-live": "polite" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-mark", "aria-hidden": "true" }, "\u2726"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-copy" }, /* @__PURE__ */ import_react5.default.createElement("b", null, active ? t("historicalRunning") : t("historicalLaunch")), /* @__PURE__ */ import_react5.default.createElement("span", null, active ? t("historicalRunningHint") : t("historicalLaunchBody")), /* @__PURE__ */ import_react5.default.createElement("small", null, active ? `${state.operation?.selectedCount ?? "\u2014"} Trials` : t("historicalLaunchHint"))), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-launch-button", disabled: !workspace || state.status === "previewing", onClick: () => active ? setOpen(true) : void preview() }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-launch-button-full" }, buttonLabel), /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-launch-button-short" }, buttonShort))), open ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && close() }, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "hse-historical-title" }, /* @__PURE__ */ import_react5.default.createElement("header", { className: "hse-launch-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("historicalLaunchHint")), /* @__PURE__ */ import_react5.default.createElement("h2", { id: "hse-historical-title" }, state.status === "running" ? t("historicalRunning") : t("historicalPreviewTitle")), /* @__PURE__ */ import_react5.default.createElement("p", null, state.status === "running" ? t("historicalRunningHint") : t("historicalPreviewHint"))), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-dialog-close", "aria-label": t("close"), onClick: close }, "\xD7")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-body" }, state.status === "previewing" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-spin" }), t("historicalPreparing")) : null, state.status === "starting" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-spin" }), t("historicalStarting")) : null, state.status === "running" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-run-state" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-spin" }), /* @__PURE__ */ import_react5.default.createElement("b", null, t("historicalRunning")), /* @__PURE__ */ import_react5.default.createElement("span", null, state.operation?.selectedCount ?? "\u2014", " Trials \xB7 ", snapshot.workspace.label), /* @__PURE__ */ import_react5.default.createElement("p", null, t("historicalRunningHint"))) : null, state.status === "completed" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-run-state" }, /* @__PURE__ */ import_react5.default.createElement("b", null, "\u2713 ", t("historicalCompleted"))) : null, state.status === "error" ? /* @__PURE__ */ import_react5.default.createElement(HarborErrorState, { error: { ...state.error, nextStep: historicalErrorHint(state.error.code, t) }, t }) : null, state.status === "ready" && previewValue ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-summary" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("selectedSessions")), /* @__PURE__ */ import_react5.default.createElement("b", null, previewValue.selected.length)), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("requestEstimate")), /* @__PURE__ */ import_react5.default.createElement("b", null, previewValue.estimatedJudgeRequests)), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("tokenExpiry")), /* @__PURE__ */ import_react5.default.createElement("b", null, new Date(previewValue.expiresAt).toLocaleTimeString())), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("workspace")), /* @__PURE__ */ import_react5.default.createElement("b", null, snapshot.workspace.label))), /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-section" }, /* @__PURE__ */ import_react5.default.createElement("h3", null, t("recentSessions")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-session-list" }, previewValue.selected.map((session) => /* @__PURE__ */ import_react5.default.createElement("article", { key: session.trialId }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("b", null, session.title), /* @__PURE__ */ import_react5.default.createElement("span", null, session.lastActivityAt ? new Date(session.lastActivityAt).toLocaleString() : "\u2014")), /* @__PURE__ */ import_react5.default.createElement("p", null, t("turnCounts"), " ", session.turnCount ?? 0, " \xB7 ", t("toolCounts"), " ", session.toolCallCount ?? 0, " \xB7 ", t("feedbackCounts"), " +", session.feedback?.positive ?? 0, " / -", session.feedback?.negative ?? 0), /* @__PURE__ */ import_react5.default.createElement("code", null, (session.modelRoutes ?? []).map((route) => `${route.provider}/${route.model}`).join(" \xB7 ") || session.agentPreset || "\u2014"))))), /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-section" }, /* @__PURE__ */ import_react5.default.createElement("h3", null, t("historicalBoundaries")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-grid" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("generatorRole")), /* @__PURE__ */ import_react5.default.createElement("b", null, t("generatorRoleValue"))), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("evaluatorIdentity")), /* @__PURE__ */ import_react5.default.createElement("b", null, evaluator?.id ?? "\u2014", " \xB7 ", evaluator?.version ?? "\u2014")), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("judgeIdentity")), /* @__PURE__ */ import_react5.default.createElement("b", null, judge?.provider ?? "\u2014", " / ", judge?.model ?? "\u2014")), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("coupling")), /* @__PURE__ */ import_react5.default.createElement("b", null, previewValue.evaluation?.coupling ?? "\u2014")), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("evidenceRetention")), /* @__PURE__ */ import_react5.default.createElement("b", null, previewValue.retention?.privateEvidence, " \xB7 ", previewValue.retention?.jobEvidence))), /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-boundary-note" }, t("historicalBoundaryDetail")))) : null), /* @__PURE__ */ import_react5.default.createElement("footer", { className: "hse-launch-actions" }, state.status === "ready" ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: close }, t("cancel")), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-confirm", onClick: () => void confirm() }, t("historicalConfirm"))) : null, state.status === "error" ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: close }, t("close")), state.error.code === "SESSION_SELECTION_TOO_EXPENSIVE" ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => void preview(30) }, t("recent30Days")) : /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => void preview() }, t("previewAgain"))) : null, state.status === "running" ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: close }, t("close")) : null))) : null);
4649
+ const dialogTitle = state.status === "error" ? t("historicalErrorTitle") : state.status === "running" ? t("historicalRunning") : state.status === "starting" ? t("historicalStarting") : t("historicalPreviewTitle");
4650
+ const dialogHint = state.status === "error" ? t("historicalErrorBody") : state.status === "running" ? t("historicalRunningHint") : state.status === "starting" ? t("historicalStartingHint") : t("historicalPreviewHint");
4651
+ return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-card", "aria-live": "polite" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-mark", "aria-hidden": "true" }, "\u2726"), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-copy" }, /* @__PURE__ */ import_react5.default.createElement("b", null, active ? t("historicalRunning") : t("historicalLaunch")), /* @__PURE__ */ import_react5.default.createElement("span", null, active ? t("historicalRunningHint") : t("historicalLaunchBody")), /* @__PURE__ */ import_react5.default.createElement("small", null, active ? `${state.operation?.selectedCount ?? "\u2014"} ${t("historicalSessionUnit")}` : t("historicalLaunchHint"))), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-launch-button", disabled: !workspace || state.status === "previewing", onClick: () => active ? setOpen(true) : void preview() }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-launch-button-full" }, buttonLabel), /* @__PURE__ */ import_react5.default.createElement("span", { className: "hse-launch-button-short" }, buttonShort))), open ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-overlay", role: "presentation", onMouseDown: (event) => event.target === event.currentTarget && close() }, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-dialog", role: "dialog", "aria-modal": "true", "aria-labelledby": "hse-historical-title" }, /* @__PURE__ */ import_react5.default.createElement("header", { className: "hse-launch-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("historicalLaunchHint")), /* @__PURE__ */ import_react5.default.createElement("h2", { id: "hse-historical-title" }, dialogTitle), /* @__PURE__ */ import_react5.default.createElement("p", null, dialogHint)), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-dialog-close", "aria-label": t("close"), onClick: close }, "\xD7")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-body" }, state.status === "previewing" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-spin" }), t("historicalPreparing")) : null, state.status === "starting" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-empty" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-spin" }), t("historicalStarting")) : null, state.status === "running" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-run-state" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-spin" }), /* @__PURE__ */ import_react5.default.createElement("b", null, t("historicalRunning")), /* @__PURE__ */ import_react5.default.createElement("span", null, state.operation?.selectedCount ?? "\u2014", " ", t("historicalSessionUnit")), /* @__PURE__ */ import_react5.default.createElement("p", null, t("historicalRunningHint"))) : null, state.status === "completed" ? /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-run-state" }, /* @__PURE__ */ import_react5.default.createElement("b", null, "\u2713 ", t("historicalCompleted"))) : null, state.status === "error" ? /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-section" }, /* @__PURE__ */ import_react5.default.createElement("p", { role: "alert" }, historicalErrorHint(state.error.code, t)), /* @__PURE__ */ import_react5.default.createElement("details", null, /* @__PURE__ */ import_react5.default.createElement("summary", null, t("historicalErrorDetails")), /* @__PURE__ */ import_react5.default.createElement(HarborErrorState, { error: { ...state.error, nextStep: historicalErrorHint(state.error.code, t) }, t }))) : null, state.status === "ready" && previewValue ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-boundary-note" }, t("historicalPrivacyHint")), previewValue.scan?.partial ? /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-muted" }, t("historicalPartialHint")) : null, previewValue.excludedCounts?.unreadable > 0 ? /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-muted" }, t("historicalUnreadableHint")) : null, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-launch-summary" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("selectedSessions")), /* @__PURE__ */ import_react5.default.createElement("b", null, previewValue.selected.length)), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("span", null, t("judgeIdentity")), /* @__PURE__ */ import_react5.default.createElement("b", null, judge?.provider ?? "\u2014", " / ", judge?.model ?? "\u2014"))), /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-launch-section" }, /* @__PURE__ */ import_react5.default.createElement("h3", null, t("recentSessions")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-session-list" }, previewValue.selected.map((session) => /* @__PURE__ */ import_react5.default.createElement("article", { key: session.trialId }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("b", null, session.title), /* @__PURE__ */ import_react5.default.createElement("span", null, session.lastActivityAt ? new Date(session.lastActivityAt).toLocaleString() : "\u2014")), /* @__PURE__ */ import_react5.default.createElement("p", null, t("turnCounts"), " ", session.turnCount ?? 0, " \xB7 ", t("toolCounts"), " ", session.toolCallCount ?? 0))))), /* @__PURE__ */ import_react5.default.createElement("details", { className: "hse-launch-section" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, t("historicalBoundaries")), /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-boundary-note" }, t("historicalBoundaryDetail")))) : null), /* @__PURE__ */ import_react5.default.createElement("footer", { className: "hse-launch-actions" }, state.status === "ready" ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: close }, t("cancel")), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-confirm", onClick: () => void confirm() }, t("historicalConfirm"))) : null, state.status === "error" ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: close }, t("close")), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => void preview() }, t("previewAgain"))) : null, state.status === "running" ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: close }, t("close")) : null))) : null);
4838
4652
  }
4839
4653
  function DashboardView(props) {
4840
- return /* @__PURE__ */ import_react5.default.createElement(DashboardSessionView, { key: String(props.sessionId), ...props });
4654
+ return /* @__PURE__ */ import_react5.default.createElement(HarborSessionContext.Provider, { value: props.sessionId }, /* @__PURE__ */ import_react5.default.createElement(DashboardSessionView, { key: String(props.sessionId), ...props }));
4841
4655
  }
4842
4656
  function nearestScrollPort(element) {
4843
4657
  for (let node = element; node; node = node.parentElement) {
@@ -4848,7 +4662,7 @@ function nearestScrollPort(element) {
4848
4662
  function GettingStarted({ jobs, openJob, t }) {
4849
4663
  return /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-journey", "aria-label": t("journeyTitle") }, /* @__PURE__ */ import_react5.default.createElement("h2", null, t("journeyTitle")), /* @__PURE__ */ import_react5.default.createElement("p", null, t("journeyIntro")), /* @__PURE__ */ import_react5.default.createElement("ol", null, [1, 2, 3].map((step) => /* @__PURE__ */ import_react5.default.createElement("li", { key: step }, t(`journeyStep${step}`)))), jobs?.length ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-button", onClick: () => openJob(jobs[0].name) }, t("journeyOpen")) : /* @__PURE__ */ import_react5.default.createElement("p", null, t("journeyEmpty")));
4850
4664
  }
4851
- function DashboardSessionView({ t, bridge, stop, sessionId, useSession, useInput, inputActions, replaceHarborReference }) {
4665
+ function DashboardSessionView({ t, bridge, sessionId, useInput, inputActions, replaceHarborReference }) {
4852
4666
  const [workspace, setWorkspace] = (0, import_react5.useState)("");
4853
4667
  const [offset, setOffset] = (0, import_react5.useState)(0);
4854
4668
  const [attentionFilter, setAttentionFilter] = (0, import_react5.useState)("all");
@@ -4881,37 +4695,9 @@ function DashboardSessionView({ t, bridge, stop, sessionId, useSession, useInput
4881
4695
  return false;
4882
4696
  }
4883
4697
  }, [bridge, inputActions, replaceHarborReference, sessionId]);
4884
- const resolveLatest = (0, import_react5.useCallback)((token, requestedSessionId) => {
4885
- if (!token || String(requestedSessionId) !== String(sessionId)) throw new Error("Harbor context resolution requires the active Session");
4886
- return mutate("session-context-resolve", { sessionId, contextSnapshotId: token });
4887
- }, [sessionId]);
4888
- const reanalyzeLatest = (0, import_react5.useCallback)(async (context) => {
4889
- if (!context || !inputActions) return;
4890
- try {
4891
- const issued = await bridge.issue(sessionId, context, { forceNew: true });
4892
- commitIssuedDraft(bridge, sessionId, issued, replaceHarborReference, t("reanalyzeLatestPrompt"), phaseRef.current, true);
4893
- } catch {
4894
- }
4895
- }, [bridge, inputActions, replaceHarborReference, sessionId, t]);
4896
- const dockCallbacks = (0, import_react5.useRef)();
4897
- dockCallbacks.current = { resolveLatest, reanalyzeLatest, prepareQuestion: askContext };
4898
- (0, import_react5.useEffect)(() => {
4899
- let previous;
4900
- const callbacks = { resolveLatest: (...args) => dockCallbacks.current.resolveLatest(...args), reanalyzeLatest: (...args) => dockCallbacks.current.reanalyzeLatest(...args), prepareQuestion: (...args) => dockCallbacks.current.prepareQuestion(...args) };
4901
- const publish = (width) => {
4902
- const narrow = width <= 1050;
4903
- if (previous === narrow) return;
4904
- previous = narrow;
4905
- bridge.update(sessionId, { workbenchDock: { pageSessionId, narrow, ...callbacks } });
4906
- };
4907
- if (rootNode.current) publish(rootNode.current.getBoundingClientRect().width);
4908
- const observer = new ResizeObserver((entries) => publish(entries[0].contentRect.width));
4909
- if (rootNode.current) observer.observe(rootNode.current);
4910
- return () => {
4911
- observer.disconnect();
4912
- if (bridge.getSnapshot(sessionId).workbenchDock?.pageSessionId === pageSessionId) bridge.update(sessionId, { workbenchDock: void 0 });
4913
- };
4914
- }, [bridge, pageSessionId, sessionId]);
4698
+ const request = useHarborApi();
4699
+ const update = useHarborMutation();
4700
+ const viewDiagnostic = (operation, result) => bridge.navigate(sessionId, { kind: "harbor.navigate", actionId: `diagnostic-result-${operation.operationId}`, target: { route: "harbor.job", workspace: operation.target.workspace, job: result.jobName, stage: "judge" } }, { force: true });
4915
4701
  const switchWorkspace = (event) => {
4916
4702
  navigationHistory.current = [];
4917
4703
  setHistoryDepth(0);
@@ -5021,7 +4807,7 @@ function DashboardSessionView({ t, bridge, stop, sessionId, useSession, useInput
5021
4807
  bridge.acknowledgeNavigation(sessionId, action.actionId);
5022
4808
  }, [bridge, offset, selected, sessionId, snapshot?.workspace?.id, ui.navigation, workspace]);
5023
4809
  const askJob = (jobSummary) => askContext(buildUiContext({ sessionId, pageSessionId, workspace: snapshot.workspace.id, job: jobSummary.name, detail: void 0, jobSummary }), t("suggestedQuestion2"));
5024
- return /* @__PURE__ */ import_react5.default.createElement(HarborSessionContext.Provider, { value: sessionId }, /* @__PURE__ */ import_react5.default.createElement("main", { ref: rootNode, className: "hse-root" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-page hse-layout" }, !ui.workbenchDock?.narrow ? /* @__PURE__ */ import_react5.default.createElement(CopilotDock, { bridge, sessionId, useSession, stop, resolveLatest, reanalyzeLatest, prepareQuestion: askContext, t }) : null, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-main-panel" }, selected ? /* @__PURE__ */ import_react5.default.createElement(Workbench, { key: `${selected.workspace}\0${selected.job}`, job: selected.job, workspace: selected.workspace, jobs: snapshot?.jobs ?? [], close: closeWorkbench, navigation: selected.navigation, consumeNavigation, restoreView: selected.restoreView, hasHistory: selected.fromNavigation, scrollContainerRef: scrollNode, onViewStateChange: (value) => {
4810
+ return /* @__PURE__ */ import_react5.default.createElement(HarborSessionContext.Provider, { value: sessionId }, /* @__PURE__ */ import_react5.default.createElement("main", { ref: rootNode, className: "hse-root" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-page hse-layout" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-main-panel" }, ui.error ? /* @__PURE__ */ import_react5.default.createElement(HarborErrorState, { error: ui.error, title: t("contextBindFailed"), t }) : null, /* @__PURE__ */ import_react5.default.createElement(OperationTray, { hideWhenEmpty: true, ...{ sessionId, request, update }, scopeKey: snapshot?.workspace?.id ?? workspace, t: (key) => t(`operationTray_${key}`), onViewResult: viewDiagnostic }), selected ? /* @__PURE__ */ import_react5.default.createElement(Workbench, { key: `${selected.workspace}\0${selected.job}`, job: selected.job, workspace: selected.workspace, jobs: snapshot?.jobs ?? [], close: closeWorkbench, navigation: selected.navigation, consumeNavigation, restoreView: selected.restoreView, hasHistory: selected.fromNavigation, scrollContainerRef: scrollNode, onViewStateChange: (value) => {
5025
4811
  activeWorkbenchView.current = value;
5026
4812
  }, sessionId, pageSessionId, bridge, askContext, t }) : /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, historyDepth ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-button hse-dashboard-back", onClick: closeWorkbench }, t("back")) : null, snapshot ? /* @__PURE__ */ import_react5.default.createElement(GettingStarted, { jobs: snapshot.jobs, openJob, t }) : null, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-health-summary" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-head" }, /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("small", null, "Harbor \xB7 ", t("eyebrow")), /* @__PURE__ */ import_react5.default.createElement("h1", null, t("health"), ": ", t((snapshot?.overview?.attention?.blocked ?? 0) > 0 ? "health_blocked" : ["blocked", "stalled", "infrastructure", "invalid", "regressed", "gate", "fresh-baseline"].some((key) => (snapshot?.overview?.attention?.[key] ?? 0) > 0) ? "healthRisk" : "healthy")), /* @__PURE__ */ import_react5.default.createElement("p", null, t("attentionCountHint"))), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-button", onClick: () => void state.load() }, t("refresh"))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "hse-health-filters", "aria-label": t("attention") }, ATTENTION_FILTERS.map((filter) => /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", key: filter, "aria-pressed": attentionFilter === filter, onClick: () => {
5027
4813
  setAttentionFilter(filter);
@@ -5083,12 +4869,16 @@ function decodeToolResult(block) {
5083
4869
  return void 0;
5084
4870
  }
5085
4871
  }
5086
- function HarborToolView({ block, toolName, bridge, sessionId, t }) {
4872
+ function HarborToolView({ block, toolName, bridge, sessionId, prepareQuestion, t }) {
5087
4873
  const [open, setOpen] = (0, import_react5.useState)(false);
5088
- const value = decodeToolResult(block);
4874
+ const [navigationNotice, setNavigationNotice] = (0, import_react5.useState)("");
4875
+ const settled = block?.kind === "tool-result";
4876
+ const value = settled ? decodeToolResult(block) : void 0;
5089
4877
  const uiAction = trustedHarborUiAction(toolName, value);
5090
- const running = !isRecord(block) || !("kind" in block);
5091
- return /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-tool" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => setOpen(!open) }, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u{1F433} ", toolName), /* @__PURE__ */ import_react5.default.createElement("small", null, running ? "running" : block.isError ? "error" : "\u2713")), open ? /* @__PURE__ */ import_react5.default.createElement("pre", null, value ? pretty2(value) : blockText(block) || "Running\u2026") : null, uiAction ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-tool-action", onClick: () => bridge.navigate(sessionId, uiAction, { force: true }) }, t("viewInHarbor")) : null);
4878
+ const draft = toolName === "harbor_propose_action" && value?.schema === "harbor-action-draft/v1" && typeof value.draftId === "string" && value.draftId ? value : void 0;
4879
+ const onNavigate = (accepted) => setNavigationNotice(t(accepted === false ? "navigationPending" : "preparedInHarbor"));
4880
+ const actions = createHarborActionHandlers({ bridge, sessionId, prepareQuestion, onNavigate, t });
4881
+ return /* @__PURE__ */ import_react5.default.createElement(HarborSessionContext.Provider, { value: sessionId }, /* @__PURE__ */ import_react5.default.createElement("section", { className: "hse-tool" }, /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", onClick: () => setOpen(!open) }, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u{1F433} ", toolName), /* @__PURE__ */ import_react5.default.createElement("small", null, !settled ? "running" : block.isError ? "error" : "\u2713")), open ? /* @__PURE__ */ import_react5.default.createElement("pre", null, value ? pretty2(value) : blockText(block) || "Running\u2026") : null, uiAction ? /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", className: "hse-tool-action", onClick: () => onNavigate(bridge.navigate(sessionId, uiAction, { force: true })) }, t("viewInHarbor")) : null, draft ? /* @__PURE__ */ import_react5.default.createElement(ActionDraftCard, { draft, onSourceDraft: actions.openSourceDraft, onReprepare: actions.reprepare, onViewComparison: actions.viewComparison, onViewResult: (result) => actions.viewDiagnostic(draft, result), t }) : null, navigationNotice ? /* @__PURE__ */ import_react5.default.createElement("p", { className: "hse-draft-notice", role: "status" }, navigationNotice) : null));
5092
4882
  }
5093
4883
  var name = "dsh-harbor-evolution";
5094
4884
  var inject = ["slots", "locale", "inputTriggers", "sessions", "conversation"];
@@ -5107,6 +4897,21 @@ function apply(ctx) {
5107
4897
  const injected = (sessionId) => ({
5108
4898
  t,
5109
4899
  bridge,
4900
+ prepareQuestion: async (context, prompt = "") => {
4901
+ const { actx, conversation } = scopedConversation(sessionId);
4902
+ if (!actx || !conversation?.input?.for || !context) return false;
4903
+ let input;
4904
+ try {
4905
+ input = conversation.input.for(actx);
4906
+ const issued = await bridge.issue(sessionId, context, { forceNew: true });
4907
+ return commitIssuedDraft(bridge, sessionId, issued, (reference, text) => replaceStructuredHarborReference(input, reference, text), prompt, input.state.getSnapshot().phase, true);
4908
+ } catch (error) {
4909
+ const failure2 = normalizeHarborUiError(error);
4910
+ bridge.update(sessionId, { status: "error", error: failure2 });
4911
+ input?.notify?.("error", failure2.message);
4912
+ return false;
4913
+ }
4914
+ },
5110
4915
  replaceHarborReference: (issued, prompt) => {
5111
4916
  const { actx, conversation } = scopedConversation(sessionId);
5112
4917
  if (!actx || !conversation?.input?.for) return false;
@@ -5131,13 +4936,13 @@ function apply(ctx) {
5131
4936
  }
5132
4937
  });
5133
4938
  ctx.slots.inject("conversation.view", () => ctx.slots.register({ name: "conversation.view", id: "harbor-evolution", order: 30, locale: NS, label: () => t("tab"), inject: injected }, DashboardView));
5134
- ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({ name: "conversation.input.dock", id: "harbor-evolution-context", order: 10, locale: NS, inject: injected }, ContextDock));
4939
+ ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({ name: "conversation.input.dock", id: "harbor-evolution-input-sync", order: 10, locale: NS, inject: injected }, HarborInputSync));
5135
4940
  ctx.slots.inject("settings.section", () => ctx.slots.register({ name: "settings.section", id: "harbor-evolution", order: 35, label: () => t("settings"), inject: () => ({ t }) }, DoctorView));
5136
4941
  ctx.slots.inject("tool.call.toolview", function* registerTools() {
5137
4942
  for (const key of ["harbor_candidate_snapshot", "harbor_model_binding", "harbor_evolution_init", "harbor_evolution_doctor", "harbor_quick_diagnostic_init", "harbor_session_diagnostic_preview", "harbor_session_diagnostic_run", "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", "harbor_resolve_page_context", "harbor_get_evidence", "harbor_propose_action"]) yield ctx.slots.register({ name: "tool.call.toolview", key, inject: injected }, HarborToolView);
5138
4943
  });
5139
4944
  }
5140
- module.exports = { name, inject, apply, CopilotDock, actionDraftContext, resolvedUiContext, harborDisplayedAnswerBasis, recoverHarborTurn, applySourceProposal, removeContextPart, mergeHarborFocus, selectedSourceLines, sectionForNavigation, HarborUiBridge, buildUiContext, harborContextFilters, replaceStructuredHarborReference, clearStructuredHarborReferences, needsStructuredHarborNormalization, commitIssuedDraft, isHarborInputBusy, dashboardFailureState, workbenchSuccessState, workbenchFailureState, harborTurnProjection, harborSubmissionTransition, effectiveHarborSubmissionReference, shouldClearObservedExplicit, isExplicitContextExpired, evidenceCriterionOwners, evidenceFocusKey, isEvidenceFocused, trialNavigationView, trialRestoreView, navigationHistoryEntry, ownsNavigationHistoryEntry, restoreNavigationSelection, clearConsumedNavigation, ownsTrialRequest, trialListSuccessState, trialListFailureState, hasTrialFilters, trialDetailLoadingState, trialDetailErrorState, comparisonCandidates, governanceRequestKey, ownsGovernanceRequest, ownsGovernanceBinding, normalizeHarborUiError, harborApiError, trustedHarborUiAction, trustedHarborResolvedContext, trustedHarborReferences, harborAnswerBasis, toolUiAction };
4945
+ module.exports = { name, inject, apply, HarborInputSync, HarborToolView, createHarborActionHandlers, actionDraftContext, resolvedUiContext, harborDisplayedAnswerBasis, recoverHarborTurn, applySourceProposal, removeContextPart, mergeHarborFocus, selectedSourceLines, sectionForNavigation, HarborUiBridge, buildUiContext, harborContextFilters, replaceStructuredHarborReference, clearStructuredHarborReferences, needsStructuredHarborNormalization, commitIssuedDraft, isHarborInputBusy, dashboardFailureState, workbenchSuccessState, workbenchFailureState, harborTurnProjection, harborSubmissionTransition, effectiveHarborSubmissionReference, shouldClearObservedExplicit, isExplicitContextExpired, evidenceCriterionOwners, evidenceFocusKey, isEvidenceFocused, trialNavigationView, trialRestoreView, navigationHistoryEntry, ownsNavigationHistoryEntry, restoreNavigationSelection, clearConsumedNavigation, ownsTrialRequest, trialListSuccessState, trialListFailureState, hasTrialFilters, trialDetailLoadingState, trialDetailErrorState, comparisonCandidates, governanceRequestKey, ownsGovernanceRequest, ownsGovernanceBinding, normalizeHarborUiError, harborApiError, trustedHarborUiAction, trustedHarborResolvedContext, trustedHarborReferences, harborAnswerBasis, toolUiAction };
5141
4946
  return module.exports;
5142
4947
  },
5143
4948
  });