dsh-llm-fallbacks 0.4.4 → 0.5.1

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.
@@ -413,7 +413,7 @@ window.__ModuleLoader__.load({
413
413
  * are the ordered walk before that last-resort fallback. An empty chain or
414
414
  * a chain whose tail is not an official model (including the retired V4
415
415
  * ids) keeps slot rows inert and refuses the virtual-row
416
- * override/delegate; the v0.2.2 failure walk over the raw chain stays
416
+ * delegate; the v0.2.2 failure walk over the raw chain stays
417
417
  * verbatim.
418
418
  */
419
419
  function isAllDayConforming(chain) {
@@ -610,48 +610,6 @@ window.__ModuleLoader__.load({
610
610
  return parseSubagentPolicyWire(value.subagentPolicy);
611
611
  }
612
612
  /**
613
- * Shape-guard one wire role record (`fallbacks/subagent-roles` readback).
614
- * A non-object, a blank/non-string `role`, or a non-number `at` fails the
615
- * WHOLE record (`undefined` → the badge renders nothing). A present-but-
616
- * malformed `model` drops the FIELD while the record still parses (the
617
- * `parseSeedsWire` `source` rule) — the badge then hovers the role alone
618
- * instead of disappearing. Records are NORMALIZED to the known keys, so a
619
- * wire record can never smuggle a non-string `model` past the guard's type.
620
- */
621
- function parseSubagentRoleRecord(value) {
622
- if (!isRecord(value)) return void 0;
623
- if (typeof value.role !== "string" || value.role.trim() === "") return void 0;
624
- if (typeof value.at !== "number") return void 0;
625
- const model = parsePolicyRoute(value.model);
626
- return {
627
- role: value.role,
628
- ...model === void 0 ? {} : { model },
629
- at: value.at
630
- };
631
- }
632
- /**
633
- * Read this session's dispatch-resolved role record through the plugin
634
- * gateway channel (plan subagent-role-badge T3): the batch-of-ids endpoint
635
- * called with the one id the badge cares about. NEVER throws — a channel
636
- * down, an old gateway without the endpoint (rpc failure), or a malformed
637
- * payload all resolve `undefined` (the badge renders nothing —
638
- * degrade-never-crash, the fail-closed shape of `parseSubagentPolicyWire`).
639
- * @param rpc - the connection's generic RPC caller (`/api` channel).
640
- * @param sessionId - the session whose record to read.
641
- * @returns the parsed record, or `undefined` when absent/failed.
642
- */
643
- async function fetchSubagentRoleRecord(rpc, sessionId) {
644
- try {
645
- const result = await rpc.call("/api", "fallbacks/subagent-roles", { args: { ids: [sessionId] } });
646
- if (!result.ok) return void 0;
647
- const value = result.value;
648
- if (!isRecord(value)) return void 0;
649
- return parseSubagentRoleRecord(value[sessionId]);
650
- } catch {
651
- return;
652
- }
653
- }
654
- /**
655
613
  * The provider dropdown's offer set (spec §2.5 D-4): catalog providers whose
656
614
  * settings profile resolves in the describe namespaces — the Models page's
657
615
  * `configured` predicate (`ui-models` store.ts): a provider is configured
@@ -1274,20 +1232,6 @@ window.__ModuleLoader__.load({
1274
1232
  this.fail(error);
1275
1233
  }
1276
1234
  }
1277
- /**
1278
- * Read one session's dispatch-resolved subagent role record through the
1279
- * gateway channel (plan subagent-role-badge T3 — the session-header badge's
1280
- * data face). Thin delegate over {@link fetchSubagentRoleRecord} on the
1281
- * SAME rpc caller the store rides: the batch-of-ids readback called with
1282
- * the one id the badge cares about. Never throws — a channel down, an old
1283
- * gateway without the endpoint, or a malformed payload all resolve
1284
- * `undefined` (the badge renders nothing).
1285
- * @param sessionId - the session whose record to read.
1286
- * @returns the parsed record, or `undefined` when absent/failed.
1287
- */
1288
- fetchSubagentRole(sessionId) {
1289
- return fetchSubagentRoleRecord(this.rpc, sessionId);
1290
- }
1291
1235
  /** Stop in-flight responses from publishing after plugin disposal. */
1292
1236
  dispose() {
1293
1237
  this.readGeneration += 1;
@@ -1492,6 +1436,7 @@ window.__ModuleLoader__.load({
1492
1436
  "roles.persona.collapse": "收起人格提示",
1493
1437
  "roles.persona.empty": "(未设置)",
1494
1438
  "roles.seedSource.bundled": "内置",
1439
+ "roles.seedSource.external": "外部",
1495
1440
  "roles.seedSource.user": "用户",
1496
1441
  "roles.seedChainOptional": "角色 \"{id}\" 为 seed 角色:链可留空,保存不会被拦截",
1497
1442
  "roles.fallback": "链拼接策略",
@@ -1561,7 +1506,7 @@ window.__ModuleLoader__.load({
1561
1506
  "chat.switch.summary": "{from} → {to}({reason})",
1562
1507
  "chat.switch.summary.roleInject": "({reason})",
1563
1508
  "chat.switch.roleMap": "{role} → {model}",
1564
- "subagentRole.hover": "{role} → {model}",
1509
+ "subagentRole.hover": "{role} → {model}(最近一次请求的路由)",
1565
1510
  "defaults.prefix": "默认值",
1566
1511
  "save": "保存",
1567
1512
  "save.saving": "保存中…",
@@ -1688,6 +1633,7 @@ window.__ModuleLoader__.load({
1688
1633
  "roles.persona.collapse": "Collapse persona",
1689
1634
  "roles.persona.empty": "(not set)",
1690
1635
  "roles.seedSource.bundled": "bundled",
1636
+ "roles.seedSource.external": "external",
1691
1637
  "roles.seedSource.user": "User",
1692
1638
  "roles.seedChainOptional": "Role \"{id}\" is a seed role: the chain may stay empty",
1693
1639
  "roles.fallback": "Chain append",
@@ -1757,7 +1703,7 @@ window.__ModuleLoader__.load({
1757
1703
  "chat.switch.summary": "{from} → {to} ({reason})",
1758
1704
  "chat.switch.summary.roleInject": "({reason})",
1759
1705
  "chat.switch.roleMap": "{role} → {model}",
1760
- "subagentRole.hover": "{role} → {model}",
1706
+ "subagentRole.hover": "{role} → {model} (latest request route)",
1761
1707
  "defaults.prefix": "Default",
1762
1708
  "save": "Save",
1763
1709
  "save.saving": "Saving…",
@@ -1805,7 +1751,7 @@ window.__ModuleLoader__.load({
1805
1751
  }
1806
1752
  //#endregion
1807
1753
  //#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/FallbacksCard.module.css.mjs
1808
- const css$3 = "\n\n\n._8827595f_card {\n list-style: none;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n\n._8827595f_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._06704203_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._e488d460_header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n\n._e488d460_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n\n._f5dfe084_headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n._8d39bde6_name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n\n._346f3b69_description {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._631094a0_chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n\n._44836ce8_chevronOpen {\n transform: rotate(180deg);\n}\n\n\n._dbaa7975_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n\n._4e39cf17_readOnly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._99bf7f3c_pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n\n\n._9860a5b1_notice {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n\n._5006d43e_legacyNotice {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n._21918751_error {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._7cea4b2f_noticeRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px 0 0;\n}\n\n._7cea4b2f_noticeRow ._21918751_error {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n\n\n._4058c747_form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 0 0;\n}\n\n\n._9998065c_checkboxRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._02c2f6df_checkLabel {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 14px;\n line-height: 22px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._f2d47237_checkLabelTitle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: 400;\n}\n\n._c1bed8ea_checkLabelDesc {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._06389b18_checkbox {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n\n._67826267_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._ba240d82_sectionHeading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n._ddbc1b49_sectionHeadingText {\n flex: 1;\n min-width: 0;\n}\n\n\n._c41f9db7_sectionActions {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n}\n\n\n._b116c758_sectionToggle {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n._b116c758_sectionToggle:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n\n._b116c758_sectionToggle:disabled {\n cursor: default;\n}\n\n._b116c758_sectionToggle:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n._a5313fdf_sectionToggleText {\n flex: 1;\n min-width: 0;\n text-align: left;\n}\n\n._4bc809b8_hint {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._579f813a_defaultNote {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._b1962759_slotPresetName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._a6244318_infoHint {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 14px;\n line-height: 1;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-interactive-bg-hover);\n cursor: help;\n user-select: none;\n}\n\n._a6244318_infoHint:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._e655c840_infoHintDisabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._a2521bb0_optionRow {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._a2521bb0_optionRow:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n\n._06389b18_checkbox,\n._a2521bb0_optionRow input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:focus-visible,\n._a2521bb0_optionRow input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._a2521bb0_optionRow input:disabled {\n cursor: default;\n}\n\n\n._c4ecbdf3_dayRow {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n._0330c1ed_dayCell {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n border-radius: 6px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n._0330c1ed_dayCell input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell input:disabled {\n cursor: default;\n}\n\n._0330c1ed_dayCell input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._f9d86f7b_input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 6px 10px;\n resize: vertical;\n line-height: 20px;\n}\n\n\n._1285c19b_personaBriefRow {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 0;\n}\n\n._4b8f7345_personaBrief {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._2686400e_personaBriefEmpty {\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._4e4a07be_personaFull {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n\n._7b60337a_inputInvalid,\n._7b60337a_inputInvalid:focus {\n border-color: var(--dsw-alias-state-error-primary);\n}\n\n\nselect._f9d86f7b_input {\n max-width: 240px;\n cursor: pointer;\n}\n\n\n._16eb7153_selectInput {\n appearance: none;\n padding-right: 32px;\n \n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n\n._3e95886d_numberFields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n\n._86bc52d2_collapseRow {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n._a73efcc6_collapseToggle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n font: inherit;\n text-align: left;\n}\n\n._a73efcc6_collapseToggle:disabled {\n cursor: default;\n}\n\n._af017718_collapseTitle {\n \n flex: none;\n max-width: 55%;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n._2cabe603_collapseMeta {\n \n flex: none;\n margin-left: auto;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n._52d6df87_seedBadge {\n flex: none;\n max-width: 40%;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._7b04f727_slotTag {\n flex: none;\n display: inline-flex;\n align-items: center;\n border-radius: 999px;\n padding: 0 6px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n border: 1px solid;\n}\n\n._c381e792_slotTagHighCost {\n color: var(--dsw-alias-state-error-primary);\n border-color: var(--dsw-alias-state-error-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n._23bdb6fc_slotTagMultiplier {\n color: var(--dsw-alias-state-warn-primary);\n border-color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 10%, transparent);\n}\n\n._f000eed9_slotTagActive {\n color: var(--dsw-alias-state-success-primary);\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent);\n}\n\n\n._cd905ce5_dragHandle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: grab;\n color: var(--dsw-alias-label-tertiary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n flex: none;\n}\n\n._cd905ce5_dragHandle:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._cd905ce5_dragHandle:active {\n cursor: grabbing;\n}\n\n._cd905ce5_dragHandle:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n._cd905ce5_dragHandle:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._49f0c4f0_dragHandleIcon {\n transform: rotate(90deg);\n}\n\n\n._fee63b7e_slotCardDragging {\n opacity: 0.45;\n}\n\n._6f108491_slotCardOver {\n outline: 1px dashed var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._15a12620_chainSelectors {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n._240cbbf8_selectorRow {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n\n._70effa64_iconButton {\n position: relative;\n box-sizing: border-box;\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 6px;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n._70effa64_iconButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._70effa64_iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._70effa64_iconButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._70effa64_iconButton::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .12s;\n}\n\n._70effa64_iconButton:hover::after,\n._70effa64_iconButton:focus-visible::after {\n opacity: 1;\n}\n\n\n._a0968257_iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._28202c90_addButton {\n align-self: flex-start;\n}\n\n\n._6a2bd54c_slotAddRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n flex-wrap: wrap;\n}\n\n\n._4e77523e_rowActions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n\n._747fd56d_primaryButton,\n._7e855445_secondaryButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n._747fd56d_primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n._747fd56d_primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._7e855445_secondaryButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n._7e855445_secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n._747fd56d_primaryButton:disabled,\n._7e855445_secondaryButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._747fd56d_primaryButton:focus-visible,\n._7e855445_secondaryButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._238d19be_sectionAction {\n height: 28px;\n padding: 0 12px;\n border-radius: 14px;\n font-size: 12px;\n line-height: 18px;\n}\n\n\n._fbd045e0_statusBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 14px;\n margin-top: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n}\n\n._d4f70367_statusTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._8ab300ed_statusLine {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._e8cedbf5_statusLineLabel {\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._b48dfcba_offNotice {\n margin: 0;\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n\n._700006c9_policyStatus {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n._d4b67a81_policyStatusLabel {\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n._278bb4b3_policyStatusLine {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n}\n\n._da6387e5_policyStatusWarn {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
1754
+ const css$3 = "\n\n\n._8827595f_card {\n list-style: none;\n min-width: 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n background: var(--dsw-alias-bg-layer-3);\n transition: border-color .16s, background .16s;\n}\n\n._8827595f_card:hover {\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._06704203_cardOpen {\n background: var(--dsw-alias-bg-layer-2);\n border-color: var(--dsw-alias-label-dimmed);\n}\n\n\n._e488d460_header {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n color: inherit;\n text-align: left;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 14px 16px;\n border-radius: 12px;\n}\n\n._e488d460_header:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n\n._f5dfe084_headText {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n._8d39bde6_name {\n font-size: 15px;\n font-weight: 600;\n line-height: 1.4;\n color: var(--dsw-alias-label-primary);\n}\n\n._346f3b69_description {\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._631094a0_chevron {\n flex: none;\n color: var(--dsw-alias-label-tertiary);\n transition: transform .16s;\n}\n\n._44836ce8_chevronOpen {\n transform: rotate(180deg);\n}\n\n\n._dbaa7975_body {\n border-top: 1px solid var(--dsw-alias-border-l2);\n margin: 0 16px;\n padding-bottom: 8px;\n}\n\n._4e39cf17_readOnly {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._99bf7f3c_pending {\n flex: none;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n\n\n._9860a5b1_notice {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n\n._5006d43e_legacyNotice {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-business-primary);\n}\n\n._21918751_error {\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._7cea4b2f_noticeRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin: 12px 0 0;\n}\n\n._7cea4b2f_noticeRow ._21918751_error {\n flex: 1;\n min-width: 0;\n margin: 0;\n}\n\n\n._4058c747_form {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 0 0;\n}\n\n\n._9998065c_checkboxRow {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n._02c2f6df_checkLabel {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: 14px;\n line-height: 22px;\n font-weight: 400;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._f2d47237_checkLabelTitle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-weight: 400;\n}\n\n._c1bed8ea_checkLabelDesc {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._06389b18_checkbox {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._94c91bfd_fieldset {\n margin: 0;\n padding: 0;\n border: none;\n display: flex;\n flex-direction: column;\n gap: 12px;\n min-width: 0;\n}\n\n\n._67826267_field {\n display: flex;\n flex-direction: column;\n gap: 6px;\n margin: 0;\n padding: 0;\n border: none;\n min-width: 0;\n}\n\n._13e68c3f_fieldLabel {\n \n display: inline-flex;\n align-items: center;\n gap: 10px;\n padding: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._ba240d82_sectionHeading {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n\n._ddbc1b49_sectionHeadingText {\n flex: 1;\n min-width: 0;\n}\n\n\n._c41f9db7_sectionActions {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n}\n\n\n._b116c758_sectionToggle {\n width: 100%;\n appearance: none;\n border: 0;\n background: none;\n font: inherit;\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 4px 0;\n cursor: pointer;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n._b116c758_sectionToggle:hover:not(:disabled) {\n color: var(--dsw-alias-label-primary);\n}\n\n._b116c758_sectionToggle:disabled {\n cursor: default;\n}\n\n._b116c758_sectionToggle:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n._a5313fdf_sectionToggleText {\n flex: 1;\n min-width: 0;\n text-align: left;\n}\n\n._4bc809b8_hint {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n}\n\n._579f813a_defaultNote {\n font-size: 12px;\n line-height: 18px;\n font-weight: 400;\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._b1962759_slotPresetName {\n font-size: 14px;\n line-height: 22px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._a6244318_infoHint {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n font-size: 14px;\n line-height: 1;\n color: var(--dsw-alias-label-tertiary);\n background: var(--dsw-alias-interactive-bg-hover);\n cursor: help;\n user-select: none;\n}\n\n._a6244318_infoHint:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._e655c840_infoHintDisabled {\n opacity: 0.4;\n cursor: default;\n}\n\n\n._a2521bb0_optionRow {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 8px;\n border-radius: 6px;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n}\n\n._a2521bb0_optionRow:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n\n._06389b18_checkbox,\n._a2521bb0_optionRow input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._06389b18_checkbox:focus-visible,\n._a2521bb0_optionRow input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._a2521bb0_optionRow input:disabled {\n cursor: default;\n}\n\n\n._c4ecbdf3_dayRow {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n._0330c1ed_dayCell {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 2px 6px;\n border-radius: 6px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell:hover:has(input:not(:disabled)) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n._0330c1ed_dayCell input {\n flex: none;\n width: 16px;\n height: 16px;\n margin: 0;\n accent-color: var(--dsw-alias-brand-primary);\n cursor: pointer;\n}\n\n._0330c1ed_dayCell input:disabled {\n cursor: default;\n}\n\n._0330c1ed_dayCell input:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._f9d86f7b_input {\n box-sizing: border-box;\n width: 100%;\n height: 32px;\n padding: 0 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 8px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n}\n\n._f9d86f7b_input:focus {\n outline: none;\n border-color: var(--dsw-alias-brand-primary);\n}\n\n._f9d86f7b_input::placeholder {\n color: var(--dsw-alias-label-dimmed);\n}\n\n._f9d86f7b_input:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n\n._3a9b42fd_inputTextarea {\n height: auto;\n min-height: 72px;\n padding: 6px 10px;\n resize: vertical;\n line-height: 20px;\n}\n\n\n._1285c19b_personaBriefRow {\n display: flex;\n align-items: center;\n gap: 4px;\n min-width: 0;\n}\n\n._4b8f7345_personaBrief {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-primary);\n}\n\n\n._2686400e_personaBriefEmpty {\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n._4e4a07be_personaFull {\n margin: 0;\n font-size: 14px;\n line-height: 22px;\n color: var(--dsw-alias-label-secondary);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n\n._7b60337a_inputInvalid,\n._7b60337a_inputInvalid:focus {\n border-color: var(--dsw-alias-state-error-primary);\n}\n\n\nselect._f9d86f7b_input {\n max-width: 240px;\n cursor: pointer;\n}\n\n\n._16eb7153_selectInput {\n appearance: none;\n padding-right: 32px;\n \n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 12px center;\n background-size: 12px 12px;\n}\n\n\n._3e95886d_numberFields {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));\n gap: 8px;\n}\n\n._0cfb5881_list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 4px;\n}\n\n\n._f5c620d6_editorCard {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding: 14px 16px;\n border-radius: 12px;\n background: var(--dsw-alias-bg-module-platform);\n}\n\n._224b1387_cardFoot {\n display: flex;\n justify-content: flex-end;\n}\n\n._8e220e07_ruleGrid {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n._24a12a2f_ruleCell {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 120px;\n flex: 1;\n}\n\n\n._86bc52d2_collapseRow {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n}\n\n._a73efcc6_collapseToggle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: pointer;\n color: var(--dsw-alias-label-secondary);\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n font: inherit;\n text-align: left;\n}\n\n._a73efcc6_collapseToggle:disabled {\n cursor: default;\n}\n\n._af017718_collapseTitle {\n \n flex: none;\n max-width: 55%;\n min-width: 0;\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n._2cabe603_collapseMeta {\n \n flex: none;\n margin-left: auto;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n\n._52d6df87_seedBadge {\n flex: none;\n max-width: 40%;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n border-radius: 999px;\n padding: 1px 8px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._7b04f727_slotTag {\n flex: none;\n display: inline-flex;\n align-items: center;\n border-radius: 999px;\n padding: 0 6px;\n font-size: 11px;\n line-height: 17px;\n font-weight: 500;\n white-space: nowrap;\n border: 1px solid;\n}\n\n._c381e792_slotTagHighCost {\n color: var(--dsw-alias-state-error-primary);\n border-color: var(--dsw-alias-state-error-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n._23bdb6fc_slotTagMultiplier {\n color: var(--dsw-alias-state-warn-primary);\n border-color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 10%, transparent);\n}\n\n._f000eed9_slotTagActive {\n color: var(--dsw-alias-state-success-primary);\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent);\n}\n\n\n._cd905ce5_dragHandle {\n appearance: none;\n border: 0;\n background: none;\n padding: 0;\n cursor: grab;\n color: var(--dsw-alias-label-tertiary);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n border-radius: 6px;\n flex: none;\n}\n\n._cd905ce5_dragHandle:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._cd905ce5_dragHandle:active {\n cursor: grabbing;\n}\n\n._cd905ce5_dragHandle:disabled {\n cursor: default;\n opacity: 0.4;\n}\n\n._cd905ce5_dragHandle:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._49f0c4f0_dragHandleIcon {\n transform: rotate(90deg);\n}\n\n\n._fee63b7e_slotCardDragging {\n opacity: 0.45;\n}\n\n._6f108491_slotCardOver {\n outline: 1px dashed var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n}\n\n._1014c097_ruleCellLabel {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._15a12620_chainSelectors {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n._240cbbf8_selectorRow {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n\n._70effa64_iconButton {\n position: relative;\n box-sizing: border-box;\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n padding: 0;\n border: 0;\n border-radius: 6px;\n background: none;\n color: var(--dsw-alias-label-tertiary);\n cursor: pointer;\n}\n\n._70effa64_iconButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._70effa64_iconButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n._70effa64_iconButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n._70effa64_iconButton::after {\n content: attr(data-tip);\n position: absolute;\n bottom: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%);\n padding: 3px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-bg-layer-3);\n font-size: 11px;\n line-height: 17px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity .12s;\n}\n\n._70effa64_iconButton:hover::after,\n._70effa64_iconButton:focus-visible::after {\n opacity: 1;\n}\n\n\n._a0968257_iconButtonDanger:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-danger);\n color: var(--dsw-alias-state-error-primary);\n}\n\n\n._28202c90_addButton {\n align-self: flex-start;\n}\n\n\n._6a2bd54c_slotAddRow {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-top: 4px;\n flex-wrap: wrap;\n}\n\n\n._4e77523e_rowActions {\n display: flex;\n align-items: center;\n gap: 4px;\n}\n\n\n._747fd56d_primaryButton,\n._7e855445_secondaryButton {\n box-sizing: border-box;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n height: 36px;\n padding: 0 14px;\n border: none;\n border-radius: 18px;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n._747fd56d_primaryButton {\n background: var(--dsw-alias-button-primary-fill);\n color: var(--dsw-alias-label-primary-foreground);\n}\n\n._747fd56d_primaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-button-primary-hover);\n}\n\n._7e855445_secondaryButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n}\n\n._7e855445_secondaryButton:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n\n._747fd56d_primaryButton:disabled,\n._7e855445_secondaryButton:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n._747fd56d_primaryButton:focus-visible,\n._7e855445_secondaryButton:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--dsw-alias-border-l3);\n}\n\n\n._238d19be_sectionAction {\n height: 28px;\n padding: 0 12px;\n border-radius: 14px;\n font-size: 12px;\n line-height: 18px;\n}\n\n\n._fbd045e0_statusBlock {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 12px 14px;\n margin-top: 12px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 12px;\n}\n\n._d4f70367_statusTitle {\n font-size: 12px;\n line-height: 18px;\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._8ab300ed_statusLine {\n margin: 0;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n._e8cedbf5_statusLineLabel {\n font-weight: 500;\n color: var(--dsw-alias-label-secondary);\n}\n\n\n._b48dfcba_offNotice {\n margin: 0;\n padding: 12px;\n border: 1px dashed var(--dsw-alias-border-l3);\n border-radius: 8px;\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n\n._700006c9_policyStatus {\n margin: 12px 0 0;\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--dsw-alias-bg-module-platform);\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n._d4b67a81_policyStatusLabel {\n font-size: 12px;\n font-weight: 600;\n line-height: 18px;\n color: var(--dsw-alias-label-secondary);\n}\n\n._278bb4b3_policyStatusLine {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-label-primary);\n}\n\n._da6387e5_policyStatusWarn {\n font-size: 12px;\n line-height: 18px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n@media (prefers-reduced-motion: reduce) {\n ._70effa64_iconButton::after {\n transition: none;\n }\n}\n";
1809
1755
  const tagId$3 = "dsh-llm-fallbacks/FallbacksCard.module.css";
1810
1756
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
1811
1757
  const tag = document.createElement("style");
@@ -2123,17 +2069,19 @@ window.__ModuleLoader__.load({
2123
2069
  }
2124
2070
  /**
2125
2071
  * Badge label for one row's provenance (plan role-card-seeded-ux): every
2126
- * row states where its seed state comes from. A live seed renders its
2127
- * declaring set's label VERBATIM (case-preserved — no case-folding; the
2128
- * unnamed case is the literal `external`), the bundled presets and the
2129
- * operator's own rows resolve to their localized labels. `null` = no
2130
- * badge: a currently-seeded row whose wire entry lacks `source` (gateway
2131
- * version skew) — the degradation path, never an error.
2072
+ * row states where its seed state comes from. The three reserved labels
2073
+ * localize — `bundled`, `external` (the shared unnamed-producer slice;
2074
+ * plan seeds-source-and-persona-width), and the operator's own rows —
2075
+ * while a live seed declared under a registered set name renders that
2076
+ * name VERBATIM (case-preserved — no case-folding). `null` = no badge: a
2077
+ * currently-seeded row whose wire entry lacks `source` (gateway version
2078
+ * skew) — the degradation path, never an error.
2132
2079
  */
2133
2080
  function seedBadgeLabel(seed, t) {
2134
2081
  if (seed === void 0) return t("roles.seedSource.user");
2135
2082
  if (seed.source === void 0) return null;
2136
2083
  if (seed.source === "bundled") return t("roles.seedSource.bundled");
2084
+ if (seed.source === "external") return t("roles.seedSource.external");
2137
2085
  if (seed.source === "user") return t("roles.seedSource.user");
2138
2086
  return seed.source;
2139
2087
  }
@@ -4527,6 +4475,40 @@ window.__ModuleLoader__.load({
4527
4475
  });
4528
4476
  }
4529
4477
  //#endregion
4478
+ //#region src/role-projection-key.ts
4479
+ /**
4480
+ * The session-projection contract of the subagent role pill (plan
4481
+ * role-based-subagent-adoption Task 3b): the ONE key the host fold
4482
+ * (`./role-projection.ts`) publishes and the session-header badge reads.
4483
+ *
4484
+ * PURE module — no `@deepseek-ai/*` import, no host-only dependency — because
4485
+ * BOTH halves import it: the host through the seam's install point, the client
4486
+ * through `SubagentRoleBadge`. Splitting the key (and the value guard) out of
4487
+ * the host module is what keeps the client half free of the fold's host
4488
+ * imports, and a single shared literal is what keeps the two halves from
4489
+ * drifting into a silent "no pill".
4490
+ *
4491
+ * @module dsh-llm-fallbacks/role-projection-key
4492
+ */
4493
+ /**
4494
+ * The projection key the role pill reads (`useProjection(ROLE_PROJECTION_KEY)`).
4495
+ * Lower-camel like the host's own session-scoped keys (`modelSelection`,
4496
+ * `sessionListMetadata`); the `fallbacks` prefix keeps a third-party key
4497
+ * unambiguous inside the shared `SessionProjectionMap`.
4498
+ */
4499
+ const ROLE_PROJECTION_KEY = "fallbacksSubagentRole";
4500
+ /**
4501
+ * Read a projection value defensively (degrade-never-crash): only a non-blank
4502
+ * string is a role. `undefined` — the key is not registered on this host, or no
4503
+ * baseline/frame has carried it yet — and every foreign value read as "no
4504
+ * role", so the pill collapses to nothing instead of naming something wrong.
4505
+ *
4506
+ * @param value - the raw `useProjection('<key>')` value.
4507
+ */
4508
+ function readRoleProjectionValue(value) {
4509
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
4510
+ }
4511
+ //#endregion
4530
4512
  //#region \0dsh-css:/home/runner/work/dsh-llm-fallbacks/dsh-llm-fallbacks/src/client/SubagentRoleBadge.module.css.mjs
4531
4513
  const css = "\n\n._35648278_badge {\n display: inline-block;\n max-width: 120px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 12px;\n line-height: 20px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n vertical-align: middle;\n background: var(--dsw-alias-bg-module-platform);\n color: var(--dsw-alias-label-primary);\n}\n";
4532
4514
  const tagId = "dsh-llm-fallbacks/SubagentRoleBadge.module.css";
@@ -4541,101 +4523,47 @@ window.__ModuleLoader__.load({
4541
4523
  //#endregion
4542
4524
  //#region src/client/SubagentRoleBadge.tsx
4543
4525
  /**
4544
- * Session-header subagent role badge (plan subagent-role-badge T3): a
4545
- * compact read-only pill in `conversation.session.header.utilities` showing
4546
- * which Subagent role the viewed session's dispatch resolved, hovering as
4547
- * `role → provider/model`.
4548
- *
4549
- * Contract notes (verified 2026-09-09 against the harness checkout):
4550
- * - The slot is `kind: 'list'`, `scope: 'session'`, owner props an empty
4551
- * marker (`ConversationHeaderActionOwnerProps`, `children?: never`) — the
4552
- * header renders occupants with `renderSlot(..., {})`, so ALL data flows
4553
- * through this component's inject face and the session standard kit.
4554
- * - Every `scope: 'session'` occupant receives the session standard kit
4555
- * (`sessionId` + `useSession` + `useProjection`; ui-session
4556
- * `src/client/index.ts:112-119`, merged into the runtime share by ui-slots'
4557
- * `PropsRuntime`) — the fetch keys off the `sessionId` prop directly (mount
4558
- * + whenever the prop changes; the slot machinery remounts the occupant per
4559
- * viewed session — no manual session subscription). The compiled peer types
4560
- * do not carry the ui-session standard-props merge into this plugin's
4561
- * typecheck program (that package is deliberately not a plugin peer), so
4562
- * the seat is read structurally and guarded — a version-skewed host without
4563
- * it renders nothing, never throws.
4564
- * - Data: `fallbacks/subagent-roles` gateway readbacks via the injected fetch
4565
- * face ({@link fetchSubagentRoleRecord} — never throws): one on mount +
4566
- * whenever the viewed session changes, then a BOUNDED delayed re-probe
4567
- * while no record has landed (the record is written at the subagent's first
4568
- * dispatch request, which can land after this header mounted).
4569
- * - Render-only discipline (C4 pattern, same as `ConversationFallbackSwitch`):
4570
- * the badge contributes a view; no message construction, no model-context
4571
- * injection. Degrade-never-crash: a missing record, an `inherit` role, or
4572
- * ANY readback error renders `null` — the utilities strip collapses cleanly.
4526
+ * The host's own durable model-selection projection key (`dsh-api-session-
4527
+ * controller`, merged into `SessionProjectionMap`): its client value carries
4528
+ * `lastUsed` — the route the LATEST recorded request ran on. Read through the
4529
+ * same structural seat as the role key.
4573
4530
  */
4531
+ const MODEL_SELECTION_PROJECTION_KEY = "modelSelection";
4574
4532
  /**
4575
- * Bounded delayed re-probe (QC fix wave F-001): while the viewed session has
4576
- * no record yet, re-fetch up to {@link ROLE_RECORD_PROBES} times
4577
- * {@link ROLE_RECORD_PROBE_DELAY_MS} apart (~10s window) and stop on the
4578
- * first record, a session switch, or unmount. The record is written once, at
4579
- * the subagent's FIRST dispatch request — a header opened before that moment
4580
- * would otherwise never see the badge until remount.
4533
+ * `provider/model` of the model-selection projection's `lastUsed`, or
4534
+ * `undefined` when the value/key/fields are absent or foreign — the badge then
4535
+ * hovers the role alone instead of rendering a wrong route.
4581
4536
  */
4582
- const ROLE_RECORD_PROBE_DELAY_MS = 2e3;
4583
- const ROLE_RECORD_PROBES = 5;
4537
+ function latestRequestRoute(value) {
4538
+ if (typeof value !== "object" || value === null) return void 0;
4539
+ const { lastUsed } = value;
4540
+ if (typeof lastUsed !== "object" || lastUsed === null) return void 0;
4541
+ const { provider, model } = lastUsed;
4542
+ if (typeof provider !== "string" || provider === "" || typeof model !== "string" || model === "") return void 0;
4543
+ return `${provider}/${model}`;
4544
+ }
4584
4545
  /**
4585
4546
  * Render the viewed session's dispatch-resolved role badge.
4586
- * @param props - composed slot props (the `sessionId` session-kit seat is
4547
+ * @param props - composed slot props (the session-kit `useProjection` seat is
4587
4548
  * read structurally — see the module docblock).
4588
4549
  * @returns the badge element, or `null` when there is nothing to show.
4589
4550
  */
4590
4551
  function SubagentRoleBadge(props) {
4591
- const { t, controller } = props;
4592
- const seatSessionId = props.sessionId;
4593
- const sessionId = typeof seatSessionId === "string" && seatSessionId !== "" ? seatSessionId : void 0;
4594
- const [stamped, setStamped] = (0, react.useState)({
4595
- sessionId,
4596
- record: void 0
4597
- });
4598
- if (stamped.sessionId !== sessionId) setStamped({
4599
- sessionId,
4600
- record: void 0
4601
- });
4602
- const record = stamped.sessionId === sessionId ? stamped.record : void 0;
4603
- (0, react.useEffect)(() => {
4604
- if (sessionId === void 0) return;
4605
- let cancelled = false;
4606
- let timer;
4607
- const probe = (attempt) => {
4608
- controller.fetchSubagentRole(sessionId).then((next) => {
4609
- if (cancelled) return;
4610
- if (next !== void 0) {
4611
- setStamped({
4612
- sessionId,
4613
- record: next
4614
- });
4615
- return;
4616
- }
4617
- if (attempt >= ROLE_RECORD_PROBES) return;
4618
- timer = setTimeout(() => {
4619
- timer = void 0;
4620
- probe(attempt + 1);
4621
- }, ROLE_RECORD_PROBE_DELAY_MS);
4622
- });
4623
- };
4624
- probe(0);
4625
- return () => {
4626
- cancelled = true;
4627
- if (timer !== void 0) clearTimeout(timer);
4628
- };
4629
- }, [controller, sessionId]);
4630
- if (record === void 0 || record.role === "inherit") return null;
4631
- const model = record.model === void 0 ? void 0 : `${record.model.provider}/${record.model.model}`;
4552
+ const { t } = props;
4553
+ const readProjection = props.useProjection;
4554
+ if (typeof readProjection !== "function") return null;
4555
+ const rawRole = readProjection(ROLE_PROJECTION_KEY);
4556
+ const rawModelSelection = readProjection(MODEL_SELECTION_PROJECTION_KEY);
4557
+ const role = readRoleProjectionValue(rawRole);
4558
+ if (role === void 0 || role === "inherit") return null;
4559
+ const model = latestRequestRoute(rawModelSelection);
4632
4560
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4633
4561
  className: SubagentRoleBadge_module_css_default.badge,
4634
- title: model === void 0 ? record.role : t("subagentRole.hover", {
4635
- role: record.role,
4562
+ title: model === void 0 ? role : t("subagentRole.hover", {
4563
+ role,
4636
4564
  model
4637
4565
  }),
4638
- children: record.role
4566
+ children: role
4639
4567
  });
4640
4568
  }
4641
4569
  //#endregion
@@ -4760,8 +4688,7 @@ window.__ModuleLoader__.load({
4760
4688
  name: "conversation.session.header.utilities",
4761
4689
  id: "fallbacks-subagent-role",
4762
4690
  order: -20,
4763
- locale: NS,
4764
- inject: () => ({ controller })
4691
+ locale: NS
4765
4692
  }, SubagentRoleBadge);
4766
4693
  });
4767
4694
  }
@@ -116,6 +116,7 @@ export declare const zh: {
116
116
  'roles.persona.collapse': string;
117
117
  'roles.persona.empty': string;
118
118
  'roles.seedSource.bundled': string;
119
+ 'roles.seedSource.external': string;
119
120
  'roles.seedSource.user': string;
120
121
  'roles.seedChainOptional': string;
121
122
  'roles.fallback': string;
@@ -314,6 +315,7 @@ export declare const en: {
314
315
  'roles.persona.collapse': string;
315
316
  'roles.persona.empty': string;
316
317
  'roles.seedSource.bundled': string;
318
+ 'roles.seedSource.external': string;
317
319
  'roles.seedSource.user': string;
318
320
  'roles.seedChainOptional': string;
319
321
  'roles.fallback': string;
package/dist/events.d.ts CHANGED
@@ -7,8 +7,8 @@
7
7
  * after a dsh restart. The event now exists only in history: old logs that
8
8
  * contain it cannot be repaired by an `ignorable` flag (the released
9
9
  * session-format chain refuses unknown event types even when marked
10
- * ignorable), so `scripts/repair-fallbacks-switch-logs.ts` is a detector
11
- * that reports such logs and never writes.
10
+ * ignorable), so `pnpm repair:session-logs` only reports such logs by
11
+ * default; its opt-in lossy `--drop-legacy-events` mode is the sole recovery.
12
12
  * The module is type-only — the augmentation is erased at runtime; the
13
13
  * plugin's runtime behavior lives in `src/index.ts`.
14
14
  *
package/dist/gateway.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * T1 (plan llm-fallbacks-settings-gateway) + T3 (plan fallbacks-role-seeds) —
3
3
  * host-side `fallbacks` config gateway: the `/api/fallbacks/get` +
4
4
  * `/api/fallbacks/set` + `/api/fallbacks/reset` + `/api/fallbacks/revert-seed`
5
- * + `/api/fallbacks/subagent-roles` endpoints.
5
+ * endpoints.
6
6
  *
7
7
  * Transport: the typertGateway `/api` interceptor is the single host-wide RPC
8
8
  * slot (a plugin must NOT `connection.rpc.intercept('/api')` again — it would
@@ -43,11 +43,6 @@
43
43
  * `revert-seed` exposes revert-to-current-seed-default for one id — both
44
44
  * delegate to the per-apply `FallbacksSeedManager` passed into the
45
45
  * constructor (single point of truth, no copied manager logic).
46
- * `subagent-roles` (plan subagent-role-badge T2) is the read-only badge
47
- * readback: it projects the per-apply dispatch-resolved role-record map
48
- * (same T1 map the inject block writes, via the optional snapshot fn) for a
49
- * batch of session ids — unknown ids are omitted, an unwired or throwing
50
- * snapshot degrades to `{}`, never an error.
51
46
  *
52
47
  * The settings service is OPTIONAL (no settings service → the bridge source
53
48
  * stays the entry, `get` still works; `set`/`reset` fail with a clear
@@ -131,29 +126,6 @@ export type SubagentPolicySnapshotFn = () => {
131
126
  reason: string;
132
127
  };
133
128
  };
134
- /**
135
- * One dispatch-resolved subagent role record on the wire (plan
136
- * subagent-role-badge T2): the role the subagent's dispatch resolved and the
137
- * route it actually runs after the inject decision. `model` is optional on
138
- * the WIRE type only — the writer (T1) always sets it, but a record without
139
- * one still reads back as `{ role, at }` instead of failing the readback.
140
- */
141
- export type SubagentRoleRecord = {
142
- role: string;
143
- model?: {
144
- provider: string;
145
- model: string;
146
- };
147
- at: number;
148
- };
149
- /**
150
- * Live role-record snapshot the gateway reads through (plan
151
- * subagent-role-badge T2) — the `SubagentPolicySnapshotFn` pattern: built in
152
- * `apply()` over the SAME T1 map the dispatch inject block writes, no second
153
- * record source. Optional: constructors that omit it make the
154
- * `/api/fallbacks/subagent-roles` endpoint return `{}`.
155
- */
156
- export type SubagentRolesSnapshotFn = () => ReadonlyMap<string, SubagentRoleRecord>;
157
129
  /**
158
130
  * The live configuration source for the gateway (guide §7 — the same bridge
159
131
  * shape the runtime reads through). `source()` returns the live composed
@@ -212,12 +184,6 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
212
184
  * used by gateway unit tests stays byte-identical to the pre-T5 payload.
213
185
  */
214
186
  private readonly subagentPolicy;
215
- /**
216
- * Optional role-record snapshot (plan subagent-role-badge T2). When omitted
217
- * the `subagentRoles` endpoint returns `{}` — every existing constructor
218
- * call site keeps its payload byte-identical.
219
- */
220
- private readonly subagentRolesSnapshot;
221
187
  /**
222
188
  * @param ctx - owning context (the plugin fiber's ctx inside `apply`).
223
189
  * @param bridge - the same `FallbacksSettingsBridge` the runtime reads, so
@@ -227,11 +193,8 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
227
193
  * copied manager logic), through the io seam built over this bridge.
228
194
  * @param subagentPolicy - live host-policy snapshot from `apply()`; omit
229
195
  * to leave the additive field off the wire.
230
- * @param subagentRoles - live dispatch-resolved role-record snapshot from
231
- * `apply()` (plan subagent-role-badge T2); omit to make the
232
- * `subagent-roles` endpoint return `{}`.
233
196
  */
234
- constructor(ctx: Context, bridge: FallbacksSettingsBridge, seeds: FallbacksSeedManager, subagentPolicy?: SubagentPolicySnapshotFn, subagentRoles?: SubagentRolesSnapshotFn);
197
+ constructor(ctx: Context, bridge: FallbacksSettingsBridge, seeds: FallbacksSeedManager, subagentPolicy?: SubagentPolicySnapshotFn);
235
198
  /**
236
199
  * Read the current composed config (schema defaults → entry base → settings
237
200
  * user layer). No hard-gate resolver (ADR-2): the raw composed config is
@@ -290,22 +253,6 @@ export declare class FallbacksConfigGateway extends TypertRemoteService {
290
253
  * write channel is unavailable (KD-G5).
291
254
  */
292
255
  revertSeed(id: string): Promise<FallbacksRevertResult>;
293
- /**
294
- * Batch readback of dispatch-resolved subagent role records (plan
295
- * subagent-role-badge T2) — the read side of the session-header role badge.
296
- * Ids are agent ids (≡ session ids: the same id space the dispatch inject
297
- * block records under). Unknown/absent ids are OMITTED from the result,
298
- * never an error — the badge renders nothing for them. No snapshot wired
299
- * (pre-T2 constructors) or a throwing snapshot ⇒ `{}` — degrade-never-crash,
300
- * the same fail-closed shape as `projectSubagentPolicy`.
301
- * @param ids - the session ids to read (at most
302
- * {@link SUBAGENT_ROLES_MAX_IDS} entries).
303
- * @returns a plain JSON object keyed by KNOWN id only, each carrying the
304
- * wire record (`role`, `at`, `model` when the record has one).
305
- * @throws TypeError when `ids` is not an array of strings or the batch
306
- * exceeds {@link SUBAGENT_ROLES_MAX_IDS} entries.
307
- */
308
- subagentRoles(ids: string[]): Record<string, SubagentRoleRecord>;
309
256
  /**
310
257
  * Read the live composed config and normalize it to the typertGateway JSON
311
258
  * wire boundary. Containment (guide §10): a malformed stored user layer
package/dist/index.d.ts CHANGED
@@ -19,10 +19,12 @@
19
19
  * (provider/model override; the inherited `reasoningEffort` follows the
20
20
  * upstream routeChanged rule — dropped on a route change unless explicitly
21
21
  * named, preserved on a same-route override; spec D3); a
22
- * root-origin `FallbacksChain/Auto` seed then overrides to the
23
- * effective chain's first exact head (select-is-primary, plan
24
- * fallbacks-virtual-chain Task 2); then the always-mode cap check (count
25
- * `llm/retry` events for the current turn/step/provider; ≥
22
+ * root-origin `FallbacksChain/Auto` seed is served UNCHANGED (plan
23
+ * model-change-notice-loop Task 1 — the route the loop serves and records
24
+ * must equal the session selection, otherwise the host `model-selection`
25
+ * notice is re-armed on every step; the virtual adapter's `stream()`
26
+ * delegate is what reaches the chain head); then the always-mode cap check
27
+ * (count `llm/retry` events for the current turn/step/provider; ≥
26
28
  * `alwaysModeRetryCap` → same decision path, reason `always-cap` —
27
29
  * ADR-2).
28
30
  * - Per-agent state (`FallbackStateStore`): `agent/disposed` removes it,
@@ -122,29 +124,6 @@ export declare function blockedAttempts(ctx: Context): ReadonlyMap<string, Block
122
124
  * plugin is applied.
123
125
  */
124
126
  export declare function chainHeads(ctx: Context): ReadonlyMap<string, EffectiveChainHead> | undefined;
125
- /**
126
- * One dispatch-resolved subagent role record (plan subagent-role-badge T1):
127
- * the role `resolveRoleAtDispatch` resolved at the subagent's first request
128
- * and the route the subagent will actually run after the inject decision
129
- * (the override target when it applies, else the host seed).
130
- */
131
- type SubagentRoleRecord = {
132
- role: string;
133
- model: {
134
- provider: string;
135
- model: string;
136
- };
137
- at: number;
138
- };
139
- /**
140
- * @internal Test seam (mirrors `chainHeads`): the per-agent dispatch-resolved
141
- * role records written by the role-inject block (plan subagent-role-badge T1)
142
- * for the plugin applied to `ctx`. Not part of the plugin's public surface;
143
- * lets tests read the badge record without reaching into the closure (the
144
- * gateway readback closes over the per-apply map directly). `undefined` when
145
- * no plugin is applied.
146
- */
147
- export declare function subagentRoleRecords(ctx: Context): ReadonlyMap<string, SubagentRoleRecord> | undefined;
148
127
  /**
149
128
  * Count durable `llm/retry` events for the current (turn, step, provider) in
150
129
  * **always mode** (ADR-2; spec §2 clause 5). Normal-mode retries belong to