dsh-mnemon-source-skills 0.5.3 → 0.5.4

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
@@ -63,6 +63,13 @@ window.__ModuleLoader__.load({
63
63
  confirmed: true
64
64
  }));
65
65
  };
66
+ const savedModel = async (slot, input) => {
67
+ if (input.provider !== void 0 || input.model !== void 0) return void 0;
68
+ const preferences = await read("draft-preferences");
69
+ const overrides = slot === "draft" ? preferences.suggestionModels : preferences.skillRunModels;
70
+ const key = slot === "draft" ? input.suggestionId : input.skillName;
71
+ return key !== void 0 && Object.hasOwn(overrides, key) ? overrides[key] : slot === "draft" ? preferences.model : preferences.runModel;
72
+ };
66
73
  return {
67
74
  overview: () => read("overview"),
68
75
  catalog: () => read("catalog"),
@@ -107,6 +114,8 @@ window.__ModuleLoader__.load({
107
114
  expectedHash
108
115
  }),
109
116
  dismissSuggestion: (id) => mutate("suggestion-dismiss", { id }),
117
+ deleteSuggestion: (id) => mutate("suggestion-delete", { id }),
118
+ deleteDraft: (id) => mutate("draft-delete", { id }),
110
119
  pinTrajectory: (id, pinned) => mutate("trajectory-pin", {
111
120
  id,
112
121
  pinned
@@ -127,6 +136,22 @@ window.__ModuleLoader__.load({
127
136
  draftId,
128
137
  runId
129
138
  }),
139
+ draftPreferences: () => read("draft-preferences"),
140
+ saveDraftModel: (model) => mutate("draft-preference", { model }),
141
+ saveSuggestionModel: (id, model) => mutate("draft-preference", {
142
+ suggestionId: id,
143
+ model
144
+ }),
145
+ saveRunModel: (model) => mutate("draft-preference", {
146
+ slot: "run",
147
+ model
148
+ }),
149
+ saveSkillRunModel: (skillName, model) => mutate("draft-preference", {
150
+ slot: "run",
151
+ skillName,
152
+ model
153
+ }),
154
+ models: () => management.models === void 0 ? Promise.reject(/* @__PURE__ */ new Error("model catalog is unavailable")) : management.models(),
130
155
  market: () => read("market"),
131
156
  marketPreview: (registryId, name) => read("market-preview", {
132
157
  registryId,
@@ -142,8 +167,14 @@ window.__ModuleLoader__.load({
142
167
  enabled
143
168
  }),
144
169
  canAssist: (operation) => management.assistance?.operations.includes(operation) === true,
145
- generateDraft: (input) => assist("skill-draft", input),
146
- backtest: (input) => assist("skill-backtest", input),
170
+ generateDraft: async (input) => assist("skill-draft", {
171
+ ...await savedModel("draft", input),
172
+ ...input
173
+ }),
174
+ backtest: async (input) => assist("skill-backtest", {
175
+ ...await savedModel("run", input),
176
+ ...input
177
+ }),
147
178
  deriveCases: (input) => assist("skill-derive-cases", input),
148
179
  reviewNow: () => assist("skill-review-now", {})
149
180
  };
@@ -486,7 +517,17 @@ window.__ModuleLoader__.load({
486
517
  "trash.original": "原位置",
487
518
  "trash.chooseHint": "可选择恢复位置或改名。同名替换需要明确确认,现有技能会保留在回收站。",
488
519
  "trash.replace": "替换同名技能,并将现有版本保留在回收站",
489
- "trash.confirmName": "输入 {name} 确认彻底删除"
520
+ "trash.confirmName": "输入 {name} 确认彻底删除",
521
+ "evolution.model": "全局模型",
522
+ "evolution.modelCard": "所选草案模型",
523
+ "evolution.modelAuto": "跟随默认",
524
+ "evolution.modelAutoHint": "使用当前任务 Agent 的模型",
525
+ "evolution.deleteTitle": "删除这条建议?",
526
+ "evolution.deleteBody": "它生成的草案和证据引用会一起删掉,无法恢复。",
527
+ "evolution.deleted": "已删除",
528
+ "tests.model": "全局模型",
529
+ "tests.modelCard": "所选回测模型",
530
+ "tests.modelAuto": "跟随默认"
490
531
  };
491
532
  var en = {
492
533
  "page.title": "Skills",
@@ -824,11 +865,21 @@ window.__ModuleLoader__.load({
824
865
  "trash.original": "Original location",
825
866
  "trash.chooseHint": "Choose a location or a different name. Replacing a skill requires confirmation and keeps its current version in the Trash.",
826
867
  "trash.replace": "Replace the existing skill and keep its current version in the Trash",
827
- "trash.confirmName": "Type {name} to confirm permanent deletion"
868
+ "trash.confirmName": "Type {name} to confirm permanent deletion",
869
+ "evolution.model": "Global model",
870
+ "evolution.modelCard": "Selected model",
871
+ "evolution.modelAuto": "Follow default",
872
+ "evolution.modelAutoHint": "Use the model of the current task Agent",
873
+ "evolution.deleteTitle": "Delete this suggestion?",
874
+ "evolution.deleteBody": "Its draft and the evidence references it cites go with it, and this cannot be undone.",
875
+ "evolution.deleted": "Deleted",
876
+ "tests.model": "Global model",
877
+ "tests.modelCard": "Selected model",
878
+ "tests.modelAuto": "Follow default"
828
879
  };
829
880
  //#endregion
830
881
  //#region \0source-css:/home/runner/work/dsh-mnemon/dsh-mnemon/plugins/dsh-mnemon-source-skills/presentation/page.module.css.mjs
831
- const css$1 = ".IIa07q_skPage{flex-direction:column;gap:12px;min-width:0;animation:.22s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:flex}@keyframes IIa07q_sk-arrive{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}@keyframes IIa07q_sk-pop{0%{opacity:0;transform:scale(.6)}70%{transform:scale(1.08)}to{opacity:1;transform:none}}@keyframes IIa07q_sk-spin{to{transform:rotate(360deg)}}@keyframes IIa07q_sk-breathe{50%{opacity:.35}}.IIa07q_skMuted{color:var(--mn-faint);margin:0;font-size:12px;line-height:18px}.IIa07q_skProse{color:var(--mn-muted);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:21px}.IIa07q_skBusy{color:var(--mn-muted);align-items:center;gap:8px;padding:6px 0;font-size:12px;line-height:18px;display:inline-flex}.IIa07q_skLink{border-radius:var(--dsw-radius-xs,4px);color:var(--dsw-alias-link,var(--mn-accent));font:inherit;cursor:pointer;background:0 0;border:0;padding:0 2px;font-size:12px;line-height:18px;text-decoration:none;transition:color .12s,background-color .12s}.IIa07q_skLink:hover{background:color-mix(in srgb, var(--mn-accent) 8%, transparent)}.IIa07q_skAlert,.IIa07q_skNotice{border-radius:var(--dsw-radius-md);color:var(--mn-text);align-items:center;gap:8px;margin-bottom:12px;padding:8px 10px 8px 12px;font-size:12px;line-height:18px;display:flex}.IIa07q_skAlert{background:color-mix(in srgb, var(--mn-danger) 9%, transparent)}.IIa07q_skNotice{background:color-mix(in srgb, var(--mn-success) 9%, transparent)}.IIa07q_skAlert>span,.IIa07q_skNotice>span{overflow-wrap:anywhere;flex:1;min-width:0}.IIa07q_skDismiss{border-radius:var(--dsw-radius-xs,4px);width:20px;height:20px;color:inherit;opacity:.55;cursor:pointer;background:0 0;border:0;flex:none;place-items:center;padding:0;font-size:15px;line-height:1;transition:opacity .12s,background-color .12s;display:grid}.IIa07q_skDismiss:hover{background:var(--mn-hover);opacity:1}.IIa07q_skWarn,.IIa07q_skSuccess{border-radius:var(--dsw-radius-md);color:var(--mn-text);margin:0;padding:8px 12px;font-size:12px;line-height:18px}.IIa07q_skWarn{background:color-mix(in srgb, var(--mn-warn) 11%, transparent)}.IIa07q_skSuccess{background:color-mix(in srgb, var(--mn-success) 9%, transparent)}.IIa07q_skDangerButton{background:var(--mn-danger)!important}.IIa07q_skClamp{justify-items:start;gap:2px;display:grid}.IIa07q_skClamp>.IIa07q_skProse[data-clamped]{-webkit-line-clamp:var(--sk-lines,3);-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.IIa07q_skClamp>.IIa07q_skChanges{width:100%}.IIa07q_skCaption{color:var(--mn-faint);letter-spacing:.02em;margin:4px 0 0;font-size:11px;font-weight:500;line-height:16px}.IIa07q_skCallout{border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:color-mix(in srgb, var(--mn-accent) 8%, transparent);font:inherit;text-align:left;cursor:pointer;border:0;justify-content:space-between;align-items:center;gap:12px;padding:8px 12px;font-size:12px;line-height:18px;transition:background-color .14s;display:flex}.IIa07q_skCallout:hover{background:color-mix(in srgb, var(--mn-accent) 13%, transparent)}.IIa07q_skCallout>b{color:var(--dsw-alias-link,var(--mn-accent));flex:none;font-weight:500;transition:transform .16s cubic-bezier(.2,0,0,1)}.IIa07q_skCallout:hover>b{transform:translate(2px)}.IIa07q_skTabBadge{min-width:16px;color:var(--dsw-alias-label-inverse,#fff);background:var(--mn-accent);text-align:center;font-variant-numeric:tabular-nums;border-radius:999px;margin-left:6px;padding:0 5px;font-size:11px;font-weight:500;line-height:16px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop;display:inline-block}.IIa07q_skIconButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--mn-muted);cursor:pointer;background:0 0;border:0;flex:none;place-items:center;padding:0;transition:color .12s,background-color .12s;display:grid}.IIa07q_skIconButton:hover:not(:disabled),.IIa07q_skIconButton[aria-expanded=true]{color:var(--mn-text);background:var(--mn-hover)}.IIa07q_skIconButton:disabled{cursor:default;opacity:.45}.IIa07q_skIconButton[data-busy]>svg{animation:.9s linear infinite IIa07q_sk-spin}.IIa07q_skIconButton[data-pulse]>svg{color:var(--mn-accent);animation:1.2s ease-in-out infinite IIa07q_sk-breathe}.IIa07q_skIconButton:focus-visible,.IIa07q_skCallout:focus-visible,.IIa07q_skLink:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));outline:none}.IIa07q_skEmpty{place-content:center;justify-items:center;gap:4px;min-height:280px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skEmptyActions{flex-wrap:wrap;justify-content:center;gap:8px;display:flex}.IIa07q_skSplit{grid-template-columns:minmax(268px,340px) minmax(0,1fr);gap:12px;min-height:560px;display:grid}.IIa07q_skList,.IIa07q_skPane{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);min-width:0}.IIa07q_skList{flex-direction:column;padding-bottom:6px;display:flex;overflow:hidden}.IIa07q_skPane{padding:clamp(16px,2vw,24px);overflow:hidden}.IIa07q_skListBar{border-bottom:.5px solid var(--mn-line);align-items:center;gap:8px;padding:10px;display:flex}.IIa07q_skListBar>:first-child{flex:1;min-width:0}.IIa07q_skListNote{color:var(--mn-faint);text-align:center;margin:0;padding:18px 16px;font-size:12px;line-height:18px}.IIa07q_skListFilter{padding:8px 10px 2px}.IIa07q_skListGroup h5{color:var(--mn-faint);letter-spacing:.02em;text-overflow:ellipsis;white-space:nowrap;margin:14px 16px 4px;font-size:11px;font-weight:500;line-height:16px;overflow:hidden}.IIa07q_skListItem{border-radius:var(--dsw-radius-md);width:calc(100% - 12px);color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;margin:4px 6px 0;padding:9px 10px;transition:background-color .14s;display:block}.IIa07q_skListItem:hover{background:var(--mn-hover)}.IIa07q_skListItem[data-selected]{background:var(--mn-fill)}.IIa07q_skListItem>div{align-items:center;gap:6px;min-width:0;display:flex}.IIa07q_skListItem>div strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.IIa07q_skListItem p{color:var(--mn-muted);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:3px 0 4px;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.IIa07q_skListItem footer{min-width:0;color:var(--mn-faint);align-items:center;gap:8px;font-size:11px;line-height:16px;display:flex}.IIa07q_skListItem footer time{font-variant-numeric:tabular-nums;flex:none}.IIa07q_skListItem footer span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.IIa07q_skIcon{border-radius:var(--dsw-radius-md);width:30px;height:30px;color:var(--mn-muted);background:var(--mn-fill);flex:none;place-items:center;font-size:13px;font-weight:600;line-height:1;transition:color .14s,background-color .14s;display:grid}.IIa07q_skRow{border-radius:var(--dsw-radius-md);align-items:center;gap:6px;margin:2px 6px 0;padding-right:8px;transition:background-color .14s;display:flex;position:relative}.IIa07q_skRow:hover{background:var(--mn-hover)}.IIa07q_skRow[data-selected]{background:var(--mn-fill)}.IIa07q_skRow[data-selected] .IIa07q_skIcon{color:var(--mn-text);background:var(--mn-layer-1,var(--mn-hover))}.IIa07q_skRow[data-off] .IIa07q_skRowText,.IIa07q_skRow[data-shadowed] .IIa07q_skRowText{opacity:.55}.IIa07q_skRowMain{min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:10px;padding:8px 0 8px 8px;display:flex}.IIa07q_skRowMain:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));border-radius:var(--dsw-radius-md);outline:none}.IIa07q_skRowText{gap:1px;min-width:0;transition:opacity .14s;display:grid}.IIa07q_skRowText strong{white-space:nowrap;align-items:center;gap:6px;min-width:0;font-size:13px;font-weight:500;line-height:20px;display:flex}.IIa07q_skRowText strong>span{text-overflow:ellipsis;min-width:0;overflow:hidden}.IIa07q_skRowText small{color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.IIa07q_skScore{min-width:24px;color:var(--mn-muted);font-variant-numeric:tabular-nums;text-align:right;flex:none;font-size:13px;font-weight:500;line-height:20px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop}.IIa07q_skScore[data-tone=good]{color:var(--mn-success)}.IIa07q_skScore[data-tone=bad]{color:var(--mn-danger)}.IIa07q_skDot{background:var(--mn-accent);border-radius:999px;flex:none;width:6px;height:6px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop}.IIa07q_skRowActions{flex:none;align-items:center;gap:8px;display:flex}.IIa07q_skUse{opacity:0;pointer-events:none;transition:opacity .14s,transform .18s cubic-bezier(.2,0,0,1);transform:translate(4px)}.IIa07q_skRow:hover .IIa07q_skUse,.IIa07q_skRow:focus-within .IIa07q_skUse{opacity:1;pointer-events:auto;transform:none}@media (hover:none){.IIa07q_skUse{opacity:1;pointer-events:auto;transform:none}}.IIa07q_skProblems{color:var(--mn-faint);margin:12px 12px 4px;font-size:12px;line-height:18px}.IIa07q_skProblems summary{border-radius:var(--dsw-radius-xs,4px);cursor:pointer;width:fit-content;padding:0 2px}.IIa07q_skProblems summary:hover{color:var(--mn-muted)}.IIa07q_skProblems ul{gap:6px;margin:8px 0 0;padding:0;list-style:none;display:grid}.IIa07q_skProblems li{gap:2px;display:grid}.IIa07q_skProblems code{color:var(--mn-muted);font:11px/16px var(--mn-code)}.IIa07q_skDetail{grid-template-columns:minmax(0,1fr);gap:14px;min-width:0;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skDetailHead{justify-content:space-between;align-items:flex-start;gap:16px;display:flex}.IIa07q_skDetailHead>div:first-child{gap:4px;min-width:0;display:grid}.IIa07q_skDetailHead h3{overflow-wrap:anywhere;margin:0;font-size:17px;font-weight:600;line-height:26px}.IIa07q_skDetailHead p{color:var(--mn-muted);margin:0;font-size:13px;line-height:20px}.IIa07q_skDetailActions{flex-wrap:wrap;flex:none;justify-content:flex-end;align-items:center;gap:6px;display:flex}.IIa07q_skKicker{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.IIa07q_skTitleLink{color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;padding:0}.IIa07q_skTitleLink:hover{color:var(--dsw-alias-link,var(--mn-accent))}.IIa07q_skMeta{min-width:0;color:var(--mn-faint);flex-wrap:wrap;align-items:center;gap:0 6px;font-size:12px;line-height:18px;display:flex}.IIa07q_skMeta>*+:before{content:\"·\";color:var(--mn-line-strong,var(--mn-faint));margin-right:6px}.IIa07q_skMeta code{min-width:0;max-width:100%;font:11px/18px var(--mn-code);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.IIa07q_skInvocation{align-items:center;gap:8px;display:flex}.IIa07q_skWhen{color:var(--mn-muted);margin:0;font-size:12px;line-height:18px}.IIa07q_skDoc{overflow-wrap:anywhere;min-width:0;color:var(--mn-text);font-size:13px;line-height:1.75}.IIa07q_skDoc>:first-child{margin-top:0}.IIa07q_skDoc>:last-child{margin-bottom:0}.IIa07q_skDoc h1,.IIa07q_skDoc h2,.IIa07q_skDoc h3,.IIa07q_skDoc h4{color:var(--mn-text);margin:1.4em 0 .5em;font-weight:600;line-height:1.4}.IIa07q_skDoc h1{font-size:1.25em}.IIa07q_skDoc h2{font-size:1.1em}.IIa07q_skDoc h3,.IIa07q_skDoc h4{font-size:1em}.IIa07q_skDoc p,.IIa07q_skDoc ul,.IIa07q_skDoc ol,.IIa07q_skDoc blockquote,.IIa07q_skDoc table,.IIa07q_skDoc pre{margin:.7em 0}.IIa07q_skDoc ul,.IIa07q_skDoc ol{padding-left:1.5em}.IIa07q_skDoc li+li{margin-top:.25em}.IIa07q_skDoc li::marker{color:var(--mn-faint)}.IIa07q_skDoc blockquote{border-left:2px solid var(--mn-line-strong,var(--mn-line));color:var(--mn-muted);margin-inline:0;padding:.1em 1em}.IIa07q_skDoc code{border-radius:var(--dsw-radius-xs,4px);color:var(--mn-text);background:var(--dsw-alias-markdown-inline-code,var(--mn-fill));font:.9em/1.55 var(--mn-code);padding:.12em .38em}.IIa07q_skDoc pre{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-markdown-code-block,var(--mn-fill));max-width:100%;padding:10px 14px;overflow:auto}.IIa07q_skDoc pre code{background:0 0;padding:0;font-size:12px}.IIa07q_skDoc a{color:var(--dsw-alias-link,var(--mn-accent));text-underline-offset:3px;text-decoration-thickness:1px}.IIa07q_skDoc hr{border:0;border-top:.5px solid var(--mn-line);margin:1.6em 0}.IIa07q_skDoc table{border-collapse:collapse;max-width:100%;font-size:12px;display:block;overflow-x:auto}.IIa07q_skDoc th,.IIa07q_skDoc td{border:.5px solid var(--mn-line);text-align:left;vertical-align:top;padding:6px 10px}.IIa07q_skDoc th{background:var(--mn-fill);font-weight:500}.IIa07q_skDoc img{border-radius:var(--dsw-radius-sm);max-width:100%;height:auto}.IIa07q_skFolds{border-top:.5px solid var(--mn-line);grid-template-columns:minmax(0,1fr);min-width:0;margin-top:4px;display:grid}.IIa07q_skFold{border-bottom:.5px solid var(--mn-line);min-width:0}.IIa07q_skFold>header{justify-content:space-between;align-items:center;gap:12px;min-height:40px;display:flex}.IIa07q_skFold>header>button{border-radius:var(--dsw-radius-sm);min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:8px;margin-left:-4px;padding:8px 4px;font-size:13px;font-weight:500;line-height:20px;display:flex}.IIa07q_skFold>header>button>svg{color:var(--mn-faint);flex:none;transition:transform .18s cubic-bezier(.2,0,0,1),color .12s;transform:rotate(-90deg)}.IIa07q_skFold[data-open]>header>button>svg{transform:none}.IIa07q_skFold>header>button:hover>svg{color:var(--mn-text)}.IIa07q_skFold>header>button>small{min-width:0;color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:400;overflow:hidden}.IIa07q_skFold>header>button:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));outline:none}.IIa07q_skFold>header>div{align-items:center;gap:6px;display:flex}.IIa07q_skFoldBody{grid-template-columns:minmax(0,1fr);gap:10px;min-width:0;padding:2px 0 14px;display:grid}.IIa07q_skFold[data-link]>header>button{padding-left:24px}.IIa07q_skFold[data-link]>header>button>b{color:var(--mn-faint);margin-left:auto;font-weight:400;transition:transform .16s cubic-bezier(.2,0,0,1),color .12s}.IIa07q_skFold[data-link]>header>button:hover>b{color:var(--dsw-alias-link,var(--mn-accent));transform:translate(2px)}.IIa07q_skVersions{grid-template-columns:minmax(0,1fr);gap:1px;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skVersions li{border-radius:var(--dsw-radius-md);align-items:center;gap:10px;min-height:34px;padding:3px 6px;transition:background-color .12s;display:flex}.IIa07q_skVersions li:hover{background:var(--mn-hover)}.IIa07q_skVersions time{color:var(--mn-muted);font-variant-numeric:tabular-nums;font-size:12px}.IIa07q_skVersions li>span{flex:1}.IIa07q_skTrashList li{flex-wrap:wrap;padding-block:10px}.IIa07q_skTrashList li>span{flex:none}.IIa07q_skTrashList li>.IIa07q_skRowText{flex:220px}.IIa07q_skTrashTags{flex-wrap:wrap;gap:6px;display:flex}.IIa07q_skTrashList li>.IIa07q_skTrashActions{flex:none;gap:6px;margin-left:auto;display:flex}.IIa07q_skResources{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skResources code{color:var(--mn-muted);background:var(--mn-fill);font:11px/17px var(--mn-code);border-radius:999px;padding:1px 8px}.IIa07q_skEditor{resize:vertical;border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;min-height:420px;color:var(--mn-text);background:var(--mn-input);font:12px/1.6 var(--mn-code);tab-size:2;outline:0;padding:10px 12px;transition:border-color .12s}.IIa07q_skEditor:focus{border-color:var(--mn-accent)}.IIa07q_skTimeline{grid-template-columns:minmax(0,1fr);gap:0;min-width:0;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skTimeline>li{min-width:0}.IIa07q_skTurn{color:var(--mn-faint);letter-spacing:.02em;margin:12px 0 4px;font-size:11px;font-weight:500;line-height:16px}.IIa07q_skTimeline>li:first-child>.IIa07q_skTurn{margin-top:0}.IIa07q_skStep{border-radius:0 var(--dsw-radius-sm) var(--dsw-radius-sm) 0;border-left:2px solid #0000;align-items:flex-start;gap:8px;padding:5px 8px;transition:background-color .14s;display:flex}.IIa07q_skTimeline>li[data-annotated] .IIa07q_skStep{border-left-color:color-mix(in srgb, var(--mn-warn) 70%, transparent);background:color-mix(in srgb, var(--mn-warn) 5%, transparent)}.IIa07q_skTimeline>li[data-highlight] .IIa07q_skStep{border-left-color:var(--mn-accent);background:color-mix(in srgb, var(--mn-accent) 6%, transparent)}.IIa07q_skStepIndex{width:22px;color:var(--mn-faint);text-align:right;font-variant-numeric:tabular-nums;flex:none;font-size:11px;line-height:20px}.IIa07q_skStepGlyph{width:14px;color:var(--mn-faint);text-align:center;flex:none;font-size:12px;line-height:20px}.IIa07q_skTimeline>li[data-kind=skill] .IIa07q_skStepGlyph{color:var(--mn-accent)}.IIa07q_skTimeline>li[data-failed] .IIa07q_skStepGlyph{color:var(--mn-danger)}.IIa07q_skStepBody{flex:1;min-width:0}.IIa07q_skStepHead{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.IIa07q_skStepHead strong{font-size:12px;font-weight:500;line-height:20px}.IIa07q_skStepHead code{min-width:0;max-width:100%;color:var(--mn-faint);font:11px/18px var(--mn-code);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.IIa07q_skStepBody>p{overflow-wrap:anywhere;color:var(--mn-muted);white-space:pre-wrap;margin:1px 0 0;font-size:12px;line-height:18px}.IIa07q_skTimeline[data-compact] .IIa07q_skStepBody>p{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.IIa07q_skAnnotation{color:var(--mn-text);align-items:flex-start;gap:6px;margin-top:6px;font-size:12px;line-height:18px;display:flex}.IIa07q_skEvidence+.IIa07q_skEvidence{margin-top:14px}.IIa07q_skEvidence>header{align-items:center;gap:8px;min-width:0;margin-bottom:6px;display:flex}.IIa07q_skEvidence>header strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;font-weight:500;overflow:hidden}.IIa07q_skEvidence>header span{color:var(--mn-faint);flex:none;font-size:11px}.IIa07q_skEvidence>header button{margin-left:auto}.IIa07q_skChips{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skDeriveBar{border-radius:var(--dsw-radius-md);background:var(--mn-fill);color:var(--mn-muted);flex-wrap:wrap;align-items:center;gap:8px;padding:8px 10px;font-size:12px;line-height:18px;display:flex}.IIa07q_skDeriveBar>span{min-width:0;margin-right:auto}.IIa07q_skDraft{border-top:.5px solid var(--mn-line);grid-template-columns:minmax(0,1fr);gap:12px;min-width:0;padding-top:14px;display:grid}.IIa07q_skSectionHead{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 12px;display:flex}.IIa07q_skSectionHead h4{align-items:baseline;gap:8px;margin:0;font-size:14px;font-weight:600;line-height:22px;display:flex}.IIa07q_skSectionHead h4 small{color:var(--mn-faint);font-size:12px;font-weight:400}.IIa07q_skSectionHead>div{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skChanges{color:var(--mn-muted);gap:3px;margin:0;padding-left:18px;font-size:12px;line-height:18px;display:grid}.IIa07q_skChanges li::marker{color:var(--mn-faint)}.IIa07q_skGuidance{color:var(--mn-faint);gap:2px;margin:0;padding-left:18px;font-size:12px;line-height:18px;display:grid}.IIa07q_skBacktest{border-radius:var(--dsw-radius-md);background:var(--mn-fill);flex-wrap:wrap;align-items:center;gap:6px 10px;min-height:36px;padding:4px 6px 4px 12px;display:flex}.IIa07q_skBacktestLine{min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:10px;padding:4px 0;font-size:12px;line-height:18px;display:flex}.IIa07q_skBacktestLine>span{color:var(--mn-faint);flex:none}.IIa07q_skBacktestLine>strong{text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;min-width:0;font-weight:500;overflow:hidden}.IIa07q_skBacktestLine>em{color:var(--mn-muted);background:var(--mn-hover);font-variant-numeric:tabular-nums;border-radius:999px;flex:none;padding:0 7px;font-style:normal;font-weight:600}.IIa07q_skBacktest[data-tone=good] .IIa07q_skBacktestLine>em{color:var(--mn-success);background:color-mix(in srgb, var(--mn-success) 12%, transparent)}.IIa07q_skBacktest[data-tone=bad] .IIa07q_skBacktestLine>em{color:var(--mn-danger);background:color-mix(in srgb, var(--mn-danger) 12%, transparent)}.IIa07q_skBacktestLine:hover>strong{text-underline-offset:3px;text-decoration:underline;text-decoration-color:var(--mn-line-strong,var(--mn-faint))}.IIa07q_skTable{border-collapse:collapse;width:100%;font-size:12px;line-height:18px;animation:.18s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive}.IIa07q_skTable th{border-bottom:.5px solid var(--mn-line);color:var(--mn-faint);text-align:left;padding:6px 8px;font-weight:500}.IIa07q_skTable td{border-bottom:.5px solid var(--mn-line);vertical-align:top;padding:7px 8px}.IIa07q_skTable td small{color:var(--mn-faint);margin-top:3px;display:block}.IIa07q_skComposer{border-radius:var(--dsw-radius-lg);background:var(--mn-fill);grid-template-columns:minmax(0,1fr);gap:8px;padding:12px;animation:.18s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skComposer label{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_skComposer textarea{resize:vertical;border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:var(--mn-input);font:inherit;outline:0;padding:6px 10px;font-size:13px;line-height:20px;transition:border-color .12s}.IIa07q_skComposer textarea:focus{border-color:var(--mn-accent)}.IIa07q_skComposer>footer{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.IIa07q_skTests{grid-template-columns:minmax(0,1fr);gap:10px;min-width:0;display:grid}.IIa07q_skTestsBar{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skCases{grid-template-columns:minmax(0,1fr);gap:1px;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skCases>li{border-radius:var(--dsw-radius-md);align-items:flex-start;gap:8px;padding:2px 4px 2px 0;transition:background-color .12s,opacity .14s;display:flex}.IIa07q_skCases>li:hover{background:var(--mn-hover)}.IIa07q_skCases>li[data-off]>details{opacity:.5}.IIa07q_skCases>li>details{flex:1;min-width:0}.IIa07q_skCases>li>:not(details){margin-top:6px}.IIa07q_skCases summary{border-radius:var(--dsw-radius-md);cursor:pointer;align-items:baseline;gap:8px;min-width:0;padding:7px 8px;list-style:none;display:flex}.IIa07q_skCases summary::-webkit-details-marker{display:none}.IIa07q_skCases summary strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.IIa07q_skCases summary small{color:var(--mn-faint);flex:none;font-size:11px}.IIa07q_skCases details[open] summary strong{white-space:normal}.IIa07q_skCases details>p{color:var(--mn-muted);white-space:pre-wrap;overflow-wrap:anywhere;margin:0 8px 8px;font-size:12px;line-height:18px}.IIa07q_skCases details>ul{gap:4px;margin:0 8px 8px;padding:0;list-style:none;display:grid}.IIa07q_skCases details>ul li{color:var(--mn-text);align-items:flex-start;gap:6px;font-size:12px;line-height:18px;display:flex}.IIa07q_skCases details>.IIa07q_skLink{margin:0 6px 8px}.IIa07q_skRuns{grid-template-columns:minmax(0,1fr);gap:1px;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skRuns>li>button{border-radius:var(--dsw-radius-md);width:100%;min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:7px 8px;font-size:12px;line-height:18px;transition:background-color .12s;display:flex}.IIa07q_skRuns>li>button:hover,.IIa07q_skRuns>li>button[aria-expanded=true]{background:var(--mn-hover)}.IIa07q_skRuns>li>button>:first-child{flex:none}.IIa07q_skRuns>li>button span{min-width:0;color:var(--mn-muted);text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;flex:1;overflow:hidden}.IIa07q_skRuns>li>button time{color:var(--mn-faint);flex:none;font-size:11px}.IIa07q_skRunDetail{border-left:.5px solid var(--mn-line);grid-template-columns:minmax(0,1fr);gap:2px;margin:4px 0 8px 12px;padding-left:10px;animation:.18s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skRunDetail details{padding:4px 0}.IIa07q_skRunDetail summary{cursor:pointer;align-items:center;gap:8px;min-width:0;font-size:12px;line-height:18px;display:flex}.IIa07q_skRunDetail summary strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-weight:500;overflow:hidden}.IIa07q_skRunDetail summary span{color:var(--mn-faint);font-variant-numeric:tabular-nums}.IIa07q_skRunDetail h6{color:var(--mn-faint);margin:8px 0 4px;font-size:11px;font-weight:500}.IIa07q_skVerdicts{grid-template-columns:minmax(0,1fr);gap:2px;margin:6px 0;padding:0;font-size:12px;line-height:18px;list-style:none;display:grid}.IIa07q_skVerdicts li{color:var(--mn-muted);gap:6px;display:flex}.IIa07q_skVerdicts li b{color:var(--mn-danger)}.IIa07q_skVerdicts li[data-pass] b{color:var(--mn-success)}.IIa07q_skRunSteps{color:var(--mn-muted);margin:0;padding-left:18px;font-size:12px;line-height:18px}.IIa07q_skAnswer{border-radius:var(--dsw-radius-md);max-height:240px;color:var(--mn-text);background:var(--mn-fill);font:12px/1.55 var(--mn-code);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;padding:8px 10px;overflow:auto}.IIa07q_skForm{gap:14px;display:grid}.IIa07q_skField{gap:6px;display:grid}.IIa07q_skField>label{color:var(--mn-muted);font-size:12px;font-weight:500;line-height:18px}.IIa07q_skForm input:not([type=checkbox]):not([type=radio]),.IIa07q_skForm textarea{border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:var(--mn-input);font:inherit;outline:0;padding:7px 10px;font-size:13px;line-height:20px;transition:border-color .12s}.IIa07q_skForm input:not([type=checkbox]):not([type=radio]):focus,.IIa07q_skForm textarea:focus{border-color:var(--mn-accent)}.IIa07q_skForm textarea{resize:vertical}.IIa07q_skForm small{color:var(--mn-faint);font-size:11px;line-height:16px}.IIa07q_skFormRow{display:flex}.IIa07q_skFormError{color:var(--mn-danger);margin-right:auto;font-size:12px}.IIa07q_skChecks{border:0;gap:6px;margin:0;padding:0;display:grid}.IIa07q_skChecks legend{color:var(--mn-muted);margin-bottom:6px;font-size:12px;font-weight:500}.IIa07q_skChecks>div{align-items:center;gap:10px;display:flex}.IIa07q_skChecks>div>input{flex:1;min-width:0}.IIa07q_skMust{color:var(--mn-muted);white-space:nowrap;flex:none;font-size:12px}.IIa07q_skChecks>button{justify-self:start}.IIa07q_skMarket{gap:14px;display:grid}.IIa07q_skMarketBar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.IIa07q_skMarketBar>:first-child{flex:1;min-width:220px}.IIa07q_skMarketGrid{grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:12px;display:grid}.IIa07q_skMarketCard{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);background:0 0;flex-direction:column;min-width:0;transition:border-color .16s,box-shadow .2s,transform .2s cubic-bezier(.2,0,0,1);animation:.24s cubic-bezier(.2,0,0,1) backwards IIa07q_sk-arrive;display:flex}.IIa07q_skMarketCard:hover{border-color:var(--mn-line-strong,var(--mn-card-line));box-shadow:var(--dsw-elevation-soft,0 4px 16px #0000000f);transform:translateY(-1px)}.IIa07q_skMarketCard:hover .IIa07q_skIcon{color:var(--mn-text)}.IIa07q_skMarketOpen{color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-content:start;gap:10px;padding:14px 14px 6px;display:grid}.IIa07q_skMarketOpen:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));border-radius:var(--dsw-radius-lg);outline:none}.IIa07q_skMarketOpen>header{align-items:center;gap:10px;min-width:0;display:flex}.IIa07q_skMarketOpen>header>div{min-width:0;display:grid}.IIa07q_skMarketOpen strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.IIa07q_skMarketOpen code{color:var(--mn-faint);font:11px/16px var(--mn-code);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.IIa07q_skMarketOpen p{color:var(--mn-muted);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:0;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.IIa07q_skMarketCard>footer{justify-content:space-between;align-items:center;gap:8px;min-height:42px;padding:0 12px 10px 14px;display:flex}.IIa07q_skMarketCard>footer>span{min-width:0;color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.IIa07q_skMarketDetail{gap:12px;display:grid}.IIa07q_skInline{align-items:center;gap:8px;display:flex}.IIa07q_skInline>:first-child{flex:1;min-width:0}.IIa07q_skMarketSection{gap:8px;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skMarketGrid{transition:opacity .16s}.IIa07q_skMarketGrid[data-busy]{opacity:.55}.IIa07q_skMarketAdd{border-radius:var(--dsw-radius-md);background:color-mix(in srgb, var(--mn-accent) 7%, transparent);align-items:center;gap:10px;min-width:0;padding:6px 6px 6px 8px;font-size:12px;line-height:18px;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:flex}.IIa07q_skMarketAdd>span:nth-child(2){min-width:0;color:var(--mn-text);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.IIa07q_skMarketAdd .IIa07q_skSourceIcon{background:var(--mn-layer-1,var(--mn-fill));width:26px;height:26px}.IIa07q_skMarketStat{font-variant-numeric:tabular-nums;align-items:center;gap:4px;display:inline-flex}.IIa07q_skMarketCard[data-indexed] .IIa07q_skMarketOpen{padding-bottom:4px}.IIa07q_skMarketMeta{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;display:flex}.IIa07q_skAudits{gap:6px;display:grid}.IIa07q_skAudits>div{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skAuditsLabel{color:var(--mn-faint);margin-right:2px;font-size:12px;line-height:18px}.IIa07q_skAudit{color:var(--mn-text);background:var(--mn-fill);border-radius:999px;align-items:center;gap:6px;padding:2px 9px 2px 8px;font-size:12px;line-height:18px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop;display:inline-flex}.IIa07q_skAudit:before{content:\"\";background:var(--mn-success);border-radius:999px;flex:none;width:6px;height:6px}.IIa07q_skAudit[data-status=warn]:before{background:var(--mn-warn)}.IIa07q_skAudit[data-status=fail]:before{background:var(--mn-danger)}.IIa07q_skAudit small{color:var(--mn-faint);font-size:11px}.IIa07q_skSources{gap:18px;display:grid}.IIa07q_skSourceList{gap:2px;margin:0 -6px;padding:0;list-style:none;display:grid}.IIa07q_skSourceList>li{border-radius:var(--dsw-radius-md);align-items:center;gap:12px;min-width:0;padding:8px 8px 8px 6px;transition:background-color .14s;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:flex}.IIa07q_skSourceList>li:hover{background:var(--mn-hover)}.IIa07q_skSourceIcon{border-radius:var(--dsw-radius-md);width:32px;height:32px;color:var(--mn-muted);background:var(--mn-fill);flex:none;place-items:center;transition:opacity .14s;display:grid}.IIa07q_skSourceText{flex:1;gap:1px;min-width:0;transition:opacity .14s;display:grid}.IIa07q_skSourceText>strong{align-items:center;gap:6px;min-width:0;font-size:13px;font-weight:500;line-height:20px;display:flex}.IIa07q_skSourceText>strong>span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.IIa07q_skSourceText>small,.IIa07q_skSourceText>em{text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-style:normal;line-height:18px;overflow:hidden}.IIa07q_skSourceText>small{color:var(--mn-faint)}.IIa07q_skSourceText>em{color:var(--mn-danger)}.IIa07q_skSourceList>li[data-off] .IIa07q_skSourceText,.IIa07q_skSourceList>li[data-off] .IIa07q_skSourceIcon{opacity:.5}.IIa07q_skSourceActions{flex:none;align-items:center;gap:6px;display:flex}.IIa07q_skSourceAdd{border-top:.5px solid var(--mn-line);gap:6px;padding-top:16px;display:grid}.IIa07q_skSourceAdd>label{font-size:13px;font-weight:500;line-height:20px}.IIa07q_skSourceHint{min-height:18px;color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;margin:0;font-size:12px;line-height:18px;transition:color .14s;overflow:hidden}.IIa07q_skSourceHint[data-state=ok]{color:var(--mn-muted)}.IIa07q_skSourceHint[data-state=warn]{color:var(--mn-warn)}.IIa07q_skFormat summary{border-radius:var(--dsw-radius-xs,4px);width:fit-content;color:var(--mn-muted);cursor:pointer;padding:0 2px;font-size:12px;line-height:18px}.IIa07q_skFormat summary:hover{color:var(--mn-text)}.IIa07q_skFormat ul{gap:12px;margin:12px 0 0;padding:0;list-style:none;display:grid}.IIa07q_skFormat li{align-items:flex-start;gap:10px;display:flex}.IIa07q_skFormat li .IIa07q_skSourceIcon{width:26px;height:26px}.IIa07q_skFormat li>div{gap:1px;font-size:12px;line-height:18px;display:grid}.IIa07q_skFormat li strong{font-weight:500}.IIa07q_skFormat li span{color:var(--mn-muted)}@media (width<=860px){.IIa07q_skSplit{grid-template-columns:minmax(0,1fr)}.IIa07q_skList{max-height:360px;overflow-y:auto}}@media (width<=560px){.IIa07q_skDetailHead{flex-direction:column}.IIa07q_skDetailActions{justify-content:flex-start}}@media (prefers-reduced-motion:reduce){.IIa07q_skPage,.IIa07q_skDetail,.IIa07q_skEmpty,.IIa07q_skTable,.IIa07q_skComposer,.IIa07q_skRunDetail,.IIa07q_skMarketCard,.IIa07q_skMarketSection,.IIa07q_skMarketAdd,.IIa07q_skAudit,.IIa07q_skSourceList>li,.IIa07q_skTabBadge,.IIa07q_skDot,.IIa07q_skScore{animation:none}.IIa07q_skUse,.IIa07q_skFold>header>button>svg,.IIa07q_skFold[data-link]>header>button>b,.IIa07q_skCallout>b,.IIa07q_skMarketCard{transition:none}.IIa07q_skIconButton[data-busy]>svg,.IIa07q_skIconButton[data-pulse]>svg{animation:none}}";
882
+ const css$1 = ".IIa07q_skPage{flex-direction:column;gap:12px;min-width:0;animation:.22s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:flex}@keyframes IIa07q_sk-arrive{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}@keyframes IIa07q_sk-pop{0%{opacity:0;transform:scale(.6)}70%{transform:scale(1.08)}to{opacity:1;transform:none}}@keyframes IIa07q_sk-spin{to{transform:rotate(360deg)}}@keyframes IIa07q_sk-breathe{50%{opacity:.35}}.IIa07q_skMuted{color:var(--mn-faint);margin:0;font-size:12px;line-height:18px}.IIa07q_skProse{color:var(--mn-muted);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;font-size:13px;line-height:21px}.IIa07q_skBusy{color:var(--mn-muted);align-items:center;gap:8px;padding:6px 0;font-size:12px;line-height:18px;display:inline-flex}.IIa07q_skLink{border-radius:var(--dsw-radius-xs,4px);color:var(--dsw-alias-link,var(--mn-accent));font:inherit;cursor:pointer;background:0 0;border:0;padding:0 2px;font-size:12px;line-height:18px;text-decoration:none;transition:color .12s,background-color .12s}.IIa07q_skLink:hover{background:color-mix(in srgb, var(--mn-accent) 8%, transparent)}.IIa07q_skAlert,.IIa07q_skNotice{border-radius:var(--dsw-radius-md);color:var(--mn-text);align-items:center;gap:8px;margin-bottom:12px;padding:8px 10px 8px 12px;font-size:12px;line-height:18px;display:flex}.IIa07q_skAlert{background:color-mix(in srgb, var(--mn-danger) 9%, transparent)}.IIa07q_skNotice{background:color-mix(in srgb, var(--mn-success) 9%, transparent)}.IIa07q_skAlert>span,.IIa07q_skNotice>span{overflow-wrap:anywhere;flex:1;min-width:0}.IIa07q_skDismiss{border-radius:var(--dsw-radius-xs,4px);width:20px;height:20px;color:inherit;opacity:.55;cursor:pointer;background:0 0;border:0;flex:none;place-items:center;padding:0;font-size:15px;line-height:1;transition:opacity .12s,background-color .12s;display:grid}.IIa07q_skDismiss:hover{background:var(--mn-hover);opacity:1}.IIa07q_skWarn,.IIa07q_skSuccess{border-radius:var(--dsw-radius-md);color:var(--mn-text);margin:0;padding:8px 12px;font-size:12px;line-height:18px}.IIa07q_skWarn{background:color-mix(in srgb, var(--mn-warn) 11%, transparent)}.IIa07q_skSuccess{background:color-mix(in srgb, var(--mn-success) 9%, transparent)}.IIa07q_skDangerButton{background:var(--mn-danger)!important}.IIa07q_skClamp{justify-items:start;gap:2px;display:grid}.IIa07q_skClamp>.IIa07q_skProse[data-clamped]{-webkit-line-clamp:var(--sk-lines,3);-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.IIa07q_skClamp>.IIa07q_skChanges{width:100%}.IIa07q_skCaption{color:var(--mn-faint);letter-spacing:.02em;margin:4px 0 0;font-size:11px;font-weight:500;line-height:16px}.IIa07q_skCallout{border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:color-mix(in srgb, var(--mn-accent) 8%, transparent);font:inherit;text-align:left;cursor:pointer;border:0;justify-content:space-between;align-items:center;gap:12px;padding:8px 12px;font-size:12px;line-height:18px;transition:background-color .14s;display:flex}.IIa07q_skCallout:hover{background:color-mix(in srgb, var(--mn-accent) 13%, transparent)}.IIa07q_skCallout>b{color:var(--dsw-alias-link,var(--mn-accent));flex:none;font-weight:500;transition:transform .16s cubic-bezier(.2,0,0,1)}.IIa07q_skCallout:hover>b{transform:translate(2px)}.IIa07q_skTabBadge{min-width:16px;color:var(--dsw-alias-label-inverse,#fff);background:var(--mn-accent);text-align:center;font-variant-numeric:tabular-nums;border-radius:999px;margin-left:6px;padding:0 5px;font-size:11px;font-weight:500;line-height:16px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop;display:inline-block}.IIa07q_skIconButton{border-radius:var(--dsw-radius-sm);width:28px;height:28px;color:var(--mn-muted);cursor:pointer;background:0 0;border:0;flex:none;place-items:center;padding:0;transition:color .12s,background-color .12s;display:grid}.IIa07q_skIconButton:hover:not(:disabled),.IIa07q_skIconButton[aria-expanded=true]{color:var(--mn-text);background:var(--mn-hover)}.IIa07q_skIconButton:disabled{cursor:default;opacity:.45}.IIa07q_skIconButton[data-busy]>svg{animation:.9s linear infinite IIa07q_sk-spin}.IIa07q_skIconButton[data-pulse]>svg{color:var(--mn-accent);animation:1.2s ease-in-out infinite IIa07q_sk-breathe}.IIa07q_skIconButton:focus-visible,.IIa07q_skCallout:focus-visible,.IIa07q_skLink:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));outline:none}.IIa07q_skEmpty{place-content:center;justify-items:center;gap:4px;min-height:280px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skEmptyActions{flex-wrap:wrap;justify-content:center;gap:8px;display:flex}.IIa07q_skSplit{grid-template-columns:minmax(268px,340px) minmax(0,1fr);gap:12px;min-height:560px;display:grid}.IIa07q_skList,.IIa07q_skPane{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);min-width:0}.IIa07q_skList{flex-direction:column;padding-bottom:6px;display:flex;overflow:hidden}.IIa07q_skPane{padding:clamp(16px,2vw,24px);overflow:hidden}.IIa07q_skEvolutionSplit{height:max(320px,100dvh - 320px);min-height:0}.IIa07q_skEvolutionSplit>.IIa07q_skList,.IIa07q_skEvolutionSplit>.IIa07q_skPane{overscroll-behavior-y:contain;min-height:0;overflow-y:auto}.IIa07q_skEvolutionSplit>.IIa07q_skList>*{flex-shrink:0}.IIa07q_skListBar{border-bottom:.5px solid var(--mn-line);align-items:center;gap:8px;padding:10px;display:flex}.IIa07q_skListBar>:first-child{flex:1;min-width:0}.IIa07q_skListNote{color:var(--mn-faint);text-align:center;margin:0;padding:18px 16px;font-size:12px;line-height:18px}.IIa07q_skListFilter{padding:8px 10px 2px}.IIa07q_skListGroup h5{color:var(--mn-faint);letter-spacing:.02em;text-overflow:ellipsis;white-space:nowrap;margin:14px 16px 4px;font-size:11px;font-weight:500;line-height:16px;overflow:hidden}.IIa07q_skListItem{border-radius:var(--dsw-radius-md);width:calc(100% - 12px);color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;margin:4px 6px 0;padding:9px 10px;transition:background-color .14s;display:block}.IIa07q_skListItem:hover{background:var(--mn-hover)}.IIa07q_skListItem[data-selected]{background:var(--mn-fill)}.IIa07q_skListItem>div{align-items:center;gap:6px;min-width:0;display:flex}.IIa07q_skListItem>div strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.IIa07q_skListItem p{color:var(--mn-muted);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:3px 0 4px;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.IIa07q_skListItem footer{min-width:0;color:var(--mn-faint);align-items:center;gap:8px;font-size:11px;line-height:16px;display:flex}.IIa07q_skListItem footer time{font-variant-numeric:tabular-nums;flex:none}.IIa07q_skListItem footer span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.IIa07q_skIcon{border-radius:var(--dsw-radius-md);width:30px;height:30px;color:var(--mn-muted);background:var(--mn-fill);flex:none;place-items:center;font-size:13px;font-weight:600;line-height:1;transition:color .14s,background-color .14s;display:grid}.IIa07q_skRow{border-radius:var(--dsw-radius-md);align-items:center;gap:6px;margin:2px 6px 0;padding-right:8px;transition:background-color .14s;display:flex;position:relative}.IIa07q_skRow:hover{background:var(--mn-hover)}.IIa07q_skRow[data-selected]{background:var(--mn-fill)}.IIa07q_skRow[data-selected] .IIa07q_skIcon{color:var(--mn-text);background:var(--mn-layer-1,var(--mn-hover))}.IIa07q_skRow[data-off] .IIa07q_skRowText,.IIa07q_skRow[data-shadowed] .IIa07q_skRowText{opacity:.55}.IIa07q_skRowMain{min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:10px;padding:8px 0 8px 8px;display:flex}.IIa07q_skRowMain:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));border-radius:var(--dsw-radius-md);outline:none}.IIa07q_skRowText{gap:1px;min-width:0;transition:opacity .14s;display:grid}.IIa07q_skRowText strong{white-space:nowrap;align-items:center;gap:6px;min-width:0;font-size:13px;font-weight:500;line-height:20px;display:flex}.IIa07q_skRowText strong>span{text-overflow:ellipsis;min-width:0;overflow:hidden}.IIa07q_skRowText small{color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.IIa07q_skScore{min-width:24px;color:var(--mn-muted);font-variant-numeric:tabular-nums;text-align:right;flex:none;font-size:13px;font-weight:500;line-height:20px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop}.IIa07q_skScore[data-tone=good]{color:var(--mn-success)}.IIa07q_skScore[data-tone=bad]{color:var(--mn-danger)}.IIa07q_skDot{background:var(--mn-accent);border-radius:999px;flex:none;width:6px;height:6px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop}.IIa07q_skRowActions{flex:none;align-items:center;gap:8px;display:flex}.IIa07q_skUse{opacity:0;pointer-events:none;transition:opacity .14s,transform .18s cubic-bezier(.2,0,0,1);transform:translate(4px)}.IIa07q_skRow:hover .IIa07q_skUse,.IIa07q_skRow:focus-within .IIa07q_skUse{opacity:1;pointer-events:auto;transform:none}@media (hover:none){.IIa07q_skUse{opacity:1;pointer-events:auto;transform:none}}.IIa07q_skProblems{color:var(--mn-faint);margin:12px 12px 4px;font-size:12px;line-height:18px}.IIa07q_skProblems summary{border-radius:var(--dsw-radius-xs,4px);cursor:pointer;width:fit-content;padding:0 2px}.IIa07q_skProblems summary:hover{color:var(--mn-muted)}.IIa07q_skProblems ul{gap:6px;margin:8px 0 0;padding:0;list-style:none;display:grid}.IIa07q_skProblems li{gap:2px;display:grid}.IIa07q_skProblems code{color:var(--mn-muted);font:11px/16px var(--mn-code)}.IIa07q_skDetail{grid-template-columns:minmax(0,1fr);gap:14px;min-width:0;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skDetailHead{justify-content:space-between;align-items:flex-start;gap:16px;display:flex}.IIa07q_skDetailHead>div:first-child{gap:4px;min-width:0;display:grid}.IIa07q_skDetailHead h3{overflow-wrap:anywhere;margin:0;font-size:17px;font-weight:600;line-height:26px}.IIa07q_skDetailHead p{color:var(--mn-muted);margin:0;font-size:13px;line-height:20px}.IIa07q_skDetailActions{flex-wrap:wrap;flex:none;justify-content:flex-end;align-items:center;gap:6px;display:flex}.IIa07q_skKicker{flex-wrap:wrap;align-items:center;gap:6px;display:inline-flex}.IIa07q_skTitleLink{color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;padding:0}.IIa07q_skTitleLink:hover{color:var(--dsw-alias-link,var(--mn-accent))}.IIa07q_skMeta{min-width:0;color:var(--mn-faint);flex-wrap:wrap;align-items:center;gap:0 6px;font-size:12px;line-height:18px;display:flex}.IIa07q_skMeta>*+:before{content:\"·\";color:var(--mn-line-strong,var(--mn-faint));margin-right:6px}.IIa07q_skMeta code{min-width:0;max-width:100%;font:11px/18px var(--mn-code);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.IIa07q_skInvocation{align-items:center;gap:8px;display:flex}.IIa07q_skWhen{color:var(--mn-muted);margin:0;font-size:12px;line-height:18px}.IIa07q_skDoc{overflow-wrap:anywhere;min-width:0;color:var(--mn-text);font-size:13px;line-height:1.75}.IIa07q_skDoc>:first-child{margin-top:0}.IIa07q_skDoc>:last-child{margin-bottom:0}.IIa07q_skDoc h1,.IIa07q_skDoc h2,.IIa07q_skDoc h3,.IIa07q_skDoc h4{color:var(--mn-text);margin:1.4em 0 .5em;font-weight:600;line-height:1.4}.IIa07q_skDoc h1{font-size:1.25em}.IIa07q_skDoc h2{font-size:1.1em}.IIa07q_skDoc h3,.IIa07q_skDoc h4{font-size:1em}.IIa07q_skDoc p,.IIa07q_skDoc ul,.IIa07q_skDoc ol,.IIa07q_skDoc blockquote,.IIa07q_skDoc table,.IIa07q_skDoc pre{margin:.7em 0}.IIa07q_skDoc ul,.IIa07q_skDoc ol{padding-left:1.5em}.IIa07q_skDoc li+li{margin-top:.25em}.IIa07q_skDoc li::marker{color:var(--mn-faint)}.IIa07q_skDoc blockquote{border-left:2px solid var(--mn-line-strong,var(--mn-line));color:var(--mn-muted);margin-inline:0;padding:.1em 1em}.IIa07q_skDoc code{border-radius:var(--dsw-radius-xs,4px);color:var(--mn-text);background:var(--dsw-alias-markdown-inline-code,var(--mn-fill));font:.9em/1.55 var(--mn-code);padding:.12em .38em}.IIa07q_skDoc pre{border-radius:var(--dsw-radius-md);background:var(--dsw-alias-markdown-code-block,var(--mn-fill));max-width:100%;padding:10px 14px;overflow:auto}.IIa07q_skDoc pre code{background:0 0;padding:0;font-size:12px}.IIa07q_skDoc a{color:var(--dsw-alias-link,var(--mn-accent));text-underline-offset:3px;text-decoration-thickness:1px}.IIa07q_skDoc hr{border:0;border-top:.5px solid var(--mn-line);margin:1.6em 0}.IIa07q_skDoc table{border-collapse:collapse;max-width:100%;font-size:12px;display:block;overflow-x:auto}.IIa07q_skDoc th,.IIa07q_skDoc td{border:.5px solid var(--mn-line);text-align:left;vertical-align:top;padding:6px 10px}.IIa07q_skDoc th{background:var(--mn-fill);font-weight:500}.IIa07q_skDoc img{border-radius:var(--dsw-radius-sm);max-width:100%;height:auto}.IIa07q_skFolds{border-top:.5px solid var(--mn-line);grid-template-columns:minmax(0,1fr);min-width:0;margin-top:4px;display:grid}.IIa07q_skFold{border-bottom:.5px solid var(--mn-line);min-width:0}.IIa07q_skFold>header{justify-content:space-between;align-items:center;gap:12px;min-height:40px;display:flex}.IIa07q_skFold>header>button{border-radius:var(--dsw-radius-sm);min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:8px;margin-left:-4px;padding:8px 4px;font-size:13px;font-weight:500;line-height:20px;display:flex}.IIa07q_skFold>header>button>svg{color:var(--mn-faint);flex:none;transition:transform .18s cubic-bezier(.2,0,0,1),color .12s;transform:rotate(-90deg)}.IIa07q_skFold[data-open]>header>button>svg{transform:none}.IIa07q_skFold>header>button:hover>svg{color:var(--mn-text)}.IIa07q_skFold>header>button>small{min-width:0;color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-weight:400;overflow:hidden}.IIa07q_skFold>header>button:focus-visible{box-shadow:0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));outline:none}.IIa07q_skFold>header>div{align-items:center;gap:6px;display:flex}.IIa07q_skFoldBody{grid-template-columns:minmax(0,1fr);gap:10px;min-width:0;padding:2px 0 14px;display:grid}.IIa07q_skFold[data-link]>header>button{padding-left:24px}.IIa07q_skFold[data-link]>header>button>b{color:var(--mn-faint);margin-left:auto;font-weight:400;transition:transform .16s cubic-bezier(.2,0,0,1),color .12s}.IIa07q_skFold[data-link]>header>button:hover>b{color:var(--dsw-alias-link,var(--mn-accent));transform:translate(2px)}.IIa07q_skVersions{grid-template-columns:minmax(0,1fr);gap:1px;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skVersions li{border-radius:var(--dsw-radius-md);align-items:center;gap:10px;min-height:34px;padding:3px 6px;transition:background-color .12s;display:flex}.IIa07q_skVersions li:hover{background:var(--mn-hover)}.IIa07q_skVersions time{color:var(--mn-muted);font-variant-numeric:tabular-nums;font-size:12px}.IIa07q_skVersions li>span{flex:1}.IIa07q_skTrashList li{flex-wrap:wrap;padding-block:10px}.IIa07q_skTrashList li>span{flex:none}.IIa07q_skTrashList li>.IIa07q_skRowText{flex:220px}.IIa07q_skTrashTags{flex-wrap:wrap;gap:6px;display:flex}.IIa07q_skTrashList li>.IIa07q_skTrashActions{flex:none;gap:6px;margin-left:auto;display:flex}.IIa07q_skResources{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skResources code{color:var(--mn-muted);background:var(--mn-fill);font:11px/17px var(--mn-code);border-radius:999px;padding:1px 8px}.IIa07q_skEditor{resize:vertical;border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;min-height:420px;color:var(--mn-text);background:var(--mn-input);font:12px/1.6 var(--mn-code);tab-size:2;outline:0;padding:10px 12px;transition:border-color .12s}.IIa07q_skEditor:focus{border-color:var(--mn-accent)}.IIa07q_skTimeline{grid-template-columns:minmax(0,1fr);gap:0;min-width:0;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skTimeline>li{min-width:0}.IIa07q_skTurn{color:var(--mn-faint);letter-spacing:.02em;margin:12px 0 4px;font-size:11px;font-weight:500;line-height:16px}.IIa07q_skTimeline>li:first-child>.IIa07q_skTurn{margin-top:0}.IIa07q_skStep{border-radius:0 var(--dsw-radius-sm) var(--dsw-radius-sm) 0;border-left:2px solid #0000;align-items:flex-start;gap:8px;padding:5px 8px;transition:background-color .14s;display:flex}.IIa07q_skTimeline>li[data-annotated] .IIa07q_skStep{border-left-color:color-mix(in srgb, var(--mn-warn) 70%, transparent);background:color-mix(in srgb, var(--mn-warn) 5%, transparent)}.IIa07q_skTimeline>li[data-highlight] .IIa07q_skStep{border-left-color:var(--mn-accent);background:color-mix(in srgb, var(--mn-accent) 6%, transparent)}.IIa07q_skStepIndex{width:22px;color:var(--mn-faint);text-align:right;font-variant-numeric:tabular-nums;flex:none;font-size:11px;line-height:20px}.IIa07q_skStepGlyph{width:14px;color:var(--mn-faint);text-align:center;flex:none;font-size:12px;line-height:20px}.IIa07q_skTimeline>li[data-kind=skill] .IIa07q_skStepGlyph{color:var(--mn-accent)}.IIa07q_skTimeline>li[data-failed] .IIa07q_skStepGlyph{color:var(--mn-danger)}.IIa07q_skStepBody{flex:1;min-width:0}.IIa07q_skStepHead{flex-wrap:wrap;align-items:center;gap:6px;min-width:0;display:flex}.IIa07q_skStepHead strong{font-size:12px;font-weight:500;line-height:20px}.IIa07q_skStepHead code{min-width:0;max-width:100%;color:var(--mn-faint);font:11px/18px var(--mn-code);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.IIa07q_skStepBody>p{overflow-wrap:anywhere;color:var(--mn-muted);white-space:pre-wrap;margin:1px 0 0;font-size:12px;line-height:18px}.IIa07q_skTimeline[data-compact] .IIa07q_skStepBody>p{-webkit-line-clamp:3;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.IIa07q_skAnnotation{color:var(--mn-text);align-items:flex-start;gap:6px;margin-top:6px;font-size:12px;line-height:18px;display:flex}.IIa07q_skEvidence+.IIa07q_skEvidence{margin-top:14px}.IIa07q_skEvidence>header{align-items:center;gap:8px;min-width:0;margin-bottom:6px;display:flex}.IIa07q_skEvidence>header strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:12px;font-weight:500;overflow:hidden}.IIa07q_skEvidence>header span{color:var(--mn-faint);flex:none;font-size:11px}.IIa07q_skEvidence>header button{margin-left:auto}.IIa07q_skChips{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skDeriveBar{border-radius:var(--dsw-radius-md);background:var(--mn-fill);color:var(--mn-muted);flex-wrap:wrap;align-items:center;gap:8px;padding:8px 10px;font-size:12px;line-height:18px;display:flex}.IIa07q_skDeriveBar>span{min-width:0;margin-right:auto}.IIa07q_skDraft{border-top:.5px solid var(--mn-line);grid-template-columns:minmax(0,1fr);gap:12px;min-width:0;padding-top:14px;display:grid}.IIa07q_skSectionHead{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 12px;display:flex}.IIa07q_skSectionHead h4{align-items:baseline;gap:8px;margin:0;font-size:14px;font-weight:600;line-height:22px;display:flex}.IIa07q_skSectionHead h4 small{color:var(--mn-faint);font-size:12px;font-weight:400}.IIa07q_skSectionHead>div{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skChanges{color:var(--mn-muted);gap:3px;margin:0;padding-left:18px;font-size:12px;line-height:18px;display:grid}.IIa07q_skChanges li::marker{color:var(--mn-faint)}.IIa07q_skGuidance{color:var(--mn-faint);gap:2px;margin:0;padding-left:18px;font-size:12px;line-height:18px;display:grid}.IIa07q_skBacktest{border-radius:var(--dsw-radius-md);background:var(--mn-fill);flex-wrap:wrap;align-items:center;gap:6px 10px;min-height:36px;padding:4px 6px 4px 12px;display:flex}.IIa07q_skBacktestLine{min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-items:center;gap:10px;padding:4px 0;font-size:12px;line-height:18px;display:flex}.IIa07q_skBacktestLine>span{color:var(--mn-faint);flex:none}.IIa07q_skBacktestLine>strong{text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;min-width:0;font-weight:500;overflow:hidden}.IIa07q_skBacktestLine>em{color:var(--mn-muted);background:var(--mn-hover);font-variant-numeric:tabular-nums;border-radius:999px;flex:none;padding:0 7px;font-style:normal;font-weight:600}.IIa07q_skBacktest[data-tone=good] .IIa07q_skBacktestLine>em{color:var(--mn-success);background:color-mix(in srgb, var(--mn-success) 12%, transparent)}.IIa07q_skBacktest[data-tone=bad] .IIa07q_skBacktestLine>em{color:var(--mn-danger);background:color-mix(in srgb, var(--mn-danger) 12%, transparent)}.IIa07q_skBacktestLine:hover>strong{text-underline-offset:3px;text-decoration:underline;text-decoration-color:var(--mn-line-strong,var(--mn-faint))}.IIa07q_skTable{border-collapse:collapse;width:100%;font-size:12px;line-height:18px;animation:.18s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive}.IIa07q_skTable th{border-bottom:.5px solid var(--mn-line);color:var(--mn-faint);text-align:left;padding:6px 8px;font-weight:500}.IIa07q_skTable td{border-bottom:.5px solid var(--mn-line);vertical-align:top;padding:7px 8px}.IIa07q_skTable td small{color:var(--mn-faint);margin-top:3px;display:block}.IIa07q_skComposer{border-radius:var(--dsw-radius-lg);background:var(--mn-fill);grid-template-columns:minmax(0,1fr);gap:8px;padding:12px;animation:.18s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skComposer label{color:var(--mn-muted);gap:6px;font-size:12px;font-weight:500;line-height:18px;display:grid}.IIa07q_skComposer textarea{resize:vertical;border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:var(--mn-input);font:inherit;outline:0;padding:6px 10px;font-size:13px;line-height:20px;transition:border-color .12s}.IIa07q_skComposer textarea:focus{border-color:var(--mn-accent)}.IIa07q_skComposer>footer{flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:8px;display:flex}.IIa07q_skTests{grid-template-columns:minmax(0,1fr);gap:10px;min-width:0;display:grid}.IIa07q_skTestsBar{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skCases{grid-template-columns:minmax(0,1fr);gap:1px;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skCases>li{border-radius:var(--dsw-radius-md);align-items:flex-start;gap:8px;padding:2px 4px 2px 0;transition:background-color .12s,opacity .14s;display:flex}.IIa07q_skCases>li:hover{background:var(--mn-hover)}.IIa07q_skCases>li[data-off]>details{opacity:.5}.IIa07q_skCases>li>details{flex:1;min-width:0}.IIa07q_skCases>li>:not(details){margin-top:6px}.IIa07q_skCases summary{border-radius:var(--dsw-radius-md);cursor:pointer;align-items:baseline;gap:8px;min-width:0;padding:7px 8px;list-style:none;display:flex}.IIa07q_skCases summary::-webkit-details-marker{display:none}.IIa07q_skCases summary strong{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.IIa07q_skCases summary small{color:var(--mn-faint);flex:none;font-size:11px}.IIa07q_skCases details[open] summary strong{white-space:normal}.IIa07q_skCases details>p{color:var(--mn-muted);white-space:pre-wrap;overflow-wrap:anywhere;margin:0 8px 8px;font-size:12px;line-height:18px}.IIa07q_skCases details>ul{gap:4px;margin:0 8px 8px;padding:0;list-style:none;display:grid}.IIa07q_skCases details>ul li{color:var(--mn-text);align-items:flex-start;gap:6px;font-size:12px;line-height:18px;display:flex}.IIa07q_skCases details>.IIa07q_skLink{margin:0 6px 8px}.IIa07q_skRuns{grid-template-columns:minmax(0,1fr);gap:1px;margin:0;padding:0;list-style:none;display:grid}.IIa07q_skRuns>li>button{border-radius:var(--dsw-radius-md);width:100%;min-width:0;color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;align-items:center;gap:8px;padding:7px 8px;font-size:12px;line-height:18px;transition:background-color .12s;display:flex}.IIa07q_skRuns>li>button:hover,.IIa07q_skRuns>li>button[aria-expanded=true]{background:var(--mn-hover)}.IIa07q_skRuns>li>button>:first-child{flex:none}.IIa07q_skRuns>li>button span{min-width:0;color:var(--mn-muted);text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums;flex:1;overflow:hidden}.IIa07q_skRuns>li>button time{color:var(--mn-faint);flex:none;font-size:11px}.IIa07q_skRunDetail{border-left:.5px solid var(--mn-line);grid-template-columns:minmax(0,1fr);gap:2px;margin:4px 0 8px 12px;padding-left:10px;animation:.18s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skRunDetail details{padding:4px 0}.IIa07q_skRunDetail summary{cursor:pointer;align-items:center;gap:8px;min-width:0;font-size:12px;line-height:18px;display:flex}.IIa07q_skRunDetail summary strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-weight:500;overflow:hidden}.IIa07q_skRunDetail summary span{color:var(--mn-faint);font-variant-numeric:tabular-nums}.IIa07q_skRunDetail h6{color:var(--mn-faint);margin:8px 0 4px;font-size:11px;font-weight:500}.IIa07q_skVerdicts{grid-template-columns:minmax(0,1fr);gap:2px;margin:6px 0;padding:0;font-size:12px;line-height:18px;list-style:none;display:grid}.IIa07q_skVerdicts li{color:var(--mn-muted);gap:6px;display:flex}.IIa07q_skVerdicts li b{color:var(--mn-danger)}.IIa07q_skVerdicts li[data-pass] b{color:var(--mn-success)}.IIa07q_skRunSteps{color:var(--mn-muted);margin:0;padding-left:18px;font-size:12px;line-height:18px}.IIa07q_skAnswer{border-radius:var(--dsw-radius-md);max-height:240px;color:var(--mn-text);background:var(--mn-fill);font:12px/1.55 var(--mn-code);white-space:pre-wrap;overflow-wrap:anywhere;margin:0;padding:8px 10px;overflow:auto}.IIa07q_skForm{gap:14px;display:grid}.IIa07q_skField{gap:6px;display:grid}.IIa07q_skField>label{color:var(--mn-muted);font-size:12px;font-weight:500;line-height:18px}.IIa07q_skForm input:not([type=checkbox]):not([type=radio]),.IIa07q_skForm textarea{border:.5px solid var(--mn-field-line);border-radius:var(--dsw-radius-md);width:100%;color:var(--mn-text);background:var(--mn-input);font:inherit;outline:0;padding:7px 10px;font-size:13px;line-height:20px;transition:border-color .12s}.IIa07q_skForm input:not([type=checkbox]):not([type=radio]):focus,.IIa07q_skForm textarea:focus{border-color:var(--mn-accent)}.IIa07q_skForm textarea{resize:vertical}.IIa07q_skForm small{color:var(--mn-faint);font-size:11px;line-height:16px}.IIa07q_skFormRow{display:flex}.IIa07q_skFormError{color:var(--mn-danger);margin-right:auto;font-size:12px}.IIa07q_skChecks{border:0;gap:6px;margin:0;padding:0;display:grid}.IIa07q_skChecks legend{color:var(--mn-muted);margin-bottom:6px;font-size:12px;font-weight:500}.IIa07q_skChecks>div{align-items:center;gap:10px;display:flex}.IIa07q_skChecks>div>input{flex:1;min-width:0}.IIa07q_skMust{color:var(--mn-muted);white-space:nowrap;flex:none;font-size:12px}.IIa07q_skChecks>button{justify-self:start}.IIa07q_skMarket{gap:14px;display:grid}.IIa07q_skMarketBar{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.IIa07q_skMarketBar>:first-child{flex:1;min-width:220px}.IIa07q_skMarketGrid{grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:12px;display:grid}.IIa07q_skMarketCard{border:.5px solid var(--mn-card-line);border-radius:var(--dsw-radius-lg);background:0 0;flex-direction:column;min-width:0;transition:border-color .16s,box-shadow .2s,transform .2s cubic-bezier(.2,0,0,1);animation:.24s cubic-bezier(.2,0,0,1) backwards IIa07q_sk-arrive;display:flex}.IIa07q_skMarketCard:hover{border-color:var(--mn-line-strong,var(--mn-card-line));box-shadow:var(--dsw-elevation-soft,0 4px 16px #0000000f);transform:translateY(-1px)}.IIa07q_skMarketCard:hover .IIa07q_skIcon{color:var(--mn-text)}.IIa07q_skMarketOpen{color:var(--mn-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;flex:1;align-content:start;gap:10px;padding:14px 14px 6px;display:grid}.IIa07q_skMarketOpen:focus-visible{box-shadow:inset 0 0 0 2px var(--dsw-focus-ring-color,var(--mn-accent));border-radius:var(--dsw-radius-lg);outline:none}.IIa07q_skMarketOpen>header{align-items:center;gap:10px;min-width:0;display:flex}.IIa07q_skMarketOpen>header>div{min-width:0;display:grid}.IIa07q_skMarketOpen strong{text-overflow:ellipsis;white-space:nowrap;font-size:13px;font-weight:500;line-height:20px;overflow:hidden}.IIa07q_skMarketOpen code{color:var(--mn-faint);font:11px/16px var(--mn-code);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.IIa07q_skMarketOpen p{color:var(--mn-muted);-webkit-line-clamp:2;-webkit-box-orient:vertical;margin:0;font-size:12px;line-height:18px;display:-webkit-box;overflow:hidden}.IIa07q_skMarketCard>footer{justify-content:space-between;align-items:center;gap:8px;min-height:42px;padding:0 12px 10px 14px;display:flex}.IIa07q_skMarketCard>footer>span{min-width:0;color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;font-size:11px;overflow:hidden}.IIa07q_skMarketDetail{gap:12px;display:grid}.IIa07q_skInline{align-items:center;gap:8px;display:flex}.IIa07q_skInline>:first-child{flex:1;min-width:0}.IIa07q_skMarketSection{gap:8px;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:grid}.IIa07q_skMarketGrid{transition:opacity .16s}.IIa07q_skMarketGrid[data-busy]{opacity:.55}.IIa07q_skMarketAdd{border-radius:var(--dsw-radius-md);background:color-mix(in srgb, var(--mn-accent) 7%, transparent);align-items:center;gap:10px;min-width:0;padding:6px 6px 6px 8px;font-size:12px;line-height:18px;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:flex}.IIa07q_skMarketAdd>span:nth-child(2){min-width:0;color:var(--mn-text);text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.IIa07q_skMarketAdd .IIa07q_skSourceIcon{background:var(--mn-layer-1,var(--mn-fill));width:26px;height:26px}.IIa07q_skMarketStat{font-variant-numeric:tabular-nums;align-items:center;gap:4px;display:inline-flex}.IIa07q_skMarketCard[data-indexed] .IIa07q_skMarketOpen{padding-bottom:4px}.IIa07q_skMarketMeta{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;display:flex}.IIa07q_skAudits{gap:6px;display:grid}.IIa07q_skAudits>div{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.IIa07q_skAuditsLabel{color:var(--mn-faint);margin-right:2px;font-size:12px;line-height:18px}.IIa07q_skAudit{color:var(--mn-text);background:var(--mn-fill);border-radius:999px;align-items:center;gap:6px;padding:2px 9px 2px 8px;font-size:12px;line-height:18px;animation:.26s cubic-bezier(.2,0,0,1) IIa07q_sk-pop;display:inline-flex}.IIa07q_skAudit:before{content:\"\";background:var(--mn-success);border-radius:999px;flex:none;width:6px;height:6px}.IIa07q_skAudit[data-status=warn]:before{background:var(--mn-warn)}.IIa07q_skAudit[data-status=fail]:before{background:var(--mn-danger)}.IIa07q_skAudit small{color:var(--mn-faint);font-size:11px}.IIa07q_skSources{gap:18px;display:grid}.IIa07q_skSourceList{gap:2px;margin:0 -6px;padding:0;list-style:none;display:grid}.IIa07q_skSourceList>li{border-radius:var(--dsw-radius-md);align-items:center;gap:12px;min-width:0;padding:8px 8px 8px 6px;transition:background-color .14s;animation:.2s cubic-bezier(.2,0,0,1) IIa07q_sk-arrive;display:flex}.IIa07q_skSourceList>li:hover{background:var(--mn-hover)}.IIa07q_skSourceIcon{border-radius:var(--dsw-radius-md);width:32px;height:32px;color:var(--mn-muted);background:var(--mn-fill);flex:none;place-items:center;transition:opacity .14s;display:grid}.IIa07q_skSourceText{flex:1;gap:1px;min-width:0;transition:opacity .14s;display:grid}.IIa07q_skSourceText>strong{align-items:center;gap:6px;min-width:0;font-size:13px;font-weight:500;line-height:20px;display:flex}.IIa07q_skSourceText>strong>span{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.IIa07q_skSourceText>small,.IIa07q_skSourceText>em{text-overflow:ellipsis;white-space:nowrap;font-size:12px;font-style:normal;line-height:18px;overflow:hidden}.IIa07q_skSourceText>small{color:var(--mn-faint)}.IIa07q_skSourceText>em{color:var(--mn-danger)}.IIa07q_skSourceList>li[data-off] .IIa07q_skSourceText,.IIa07q_skSourceList>li[data-off] .IIa07q_skSourceIcon{opacity:.5}.IIa07q_skSourceActions{flex:none;align-items:center;gap:6px;display:flex}.IIa07q_skSourceAdd{border-top:.5px solid var(--mn-line);gap:6px;padding-top:16px;display:grid}.IIa07q_skSourceAdd>label{font-size:13px;font-weight:500;line-height:20px}.IIa07q_skSourceHint{min-height:18px;color:var(--mn-faint);text-overflow:ellipsis;white-space:nowrap;margin:0;font-size:12px;line-height:18px;transition:color .14s;overflow:hidden}.IIa07q_skSourceHint[data-state=ok]{color:var(--mn-muted)}.IIa07q_skSourceHint[data-state=warn]{color:var(--mn-warn)}.IIa07q_skFormat summary{border-radius:var(--dsw-radius-xs,4px);width:fit-content;color:var(--mn-muted);cursor:pointer;padding:0 2px;font-size:12px;line-height:18px}.IIa07q_skFormat summary:hover{color:var(--mn-text)}.IIa07q_skFormat ul{gap:12px;margin:12px 0 0;padding:0;list-style:none;display:grid}.IIa07q_skFormat li{align-items:flex-start;gap:10px;display:flex}.IIa07q_skFormat li .IIa07q_skSourceIcon{width:26px;height:26px}.IIa07q_skFormat li>div{gap:1px;font-size:12px;line-height:18px;display:grid}.IIa07q_skFormat li strong{font-weight:500}.IIa07q_skFormat li span{color:var(--mn-muted)}@media (width<=860px){.IIa07q_skSplit{grid-template-columns:minmax(0,1fr)}.IIa07q_skList{max-height:360px;overflow-y:auto}.IIa07q_skEvolutionSplit{height:auto}.IIa07q_skEvolutionSplit>.IIa07q_skPane{overscroll-behavior-y:auto;overflow:visible}}@media (width<=560px){.IIa07q_skDetailHead{flex-direction:column}.IIa07q_skDetailActions{justify-content:flex-start}}@media (prefers-reduced-motion:reduce){.IIa07q_skPage,.IIa07q_skDetail,.IIa07q_skEmpty,.IIa07q_skTable,.IIa07q_skComposer,.IIa07q_skRunDetail,.IIa07q_skMarketCard,.IIa07q_skMarketSection,.IIa07q_skMarketAdd,.IIa07q_skAudit,.IIa07q_skSourceList>li,.IIa07q_skTabBadge,.IIa07q_skDot,.IIa07q_skScore{animation:none}.IIa07q_skUse,.IIa07q_skFold>header>button>svg,.IIa07q_skFold[data-link]>header>button>b,.IIa07q_skCallout>b,.IIa07q_skMarketCard{transition:none}.IIa07q_skIconButton[data-busy]>svg,.IIa07q_skIconButton[data-pulse]>svg{animation:none}}";
832
883
  const id = "dsh-mnemon-source-skills/presentation/page.module.css";
833
884
  if (typeof document !== "undefined") {
834
885
  let tag = document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]");
@@ -874,6 +925,7 @@ window.__ModuleLoader__.load({
874
925
  "skEmpty": "IIa07q_skEmpty",
875
926
  "skEmptyActions": "IIa07q_skEmptyActions",
876
927
  "skEvidence": "IIa07q_skEvidence",
928
+ "skEvolutionSplit": "IIa07q_skEvolutionSplit",
877
929
  "skField": "IIa07q_skField",
878
930
  "skFold": "IIa07q_skFold",
879
931
  "skFoldBody": "IIa07q_skFoldBody",
@@ -1008,6 +1060,148 @@ window.__ModuleLoader__.load({
1008
1060
  return error instanceof Error ? error.message : String(error);
1009
1061
  }
1010
1062
  //#endregion
1063
+ //#region src/client/model-choice.tsx
1064
+ /**
1065
+ * The model pickers the Evolution and Evaluation pages share: which model
1066
+ * drafts and backtests run on, globally and per item, offered from the same
1067
+ * directory the task Agent resolves its own route against.
1068
+ *
1069
+ * A pick is stored as `provider|model`, so one menu value names one route, and
1070
+ * an absent pick is `auto`: the page follows the task Agent, as it did before
1071
+ * the user picked anything.
1072
+ */
1073
+ /** The menu value of a pick; `auto` asks for no pick at all. */
1074
+ function modelOptionValue(model) {
1075
+ if (model === null || model === void 0) return "auto";
1076
+ return `${model.provider}|${model.model}`;
1077
+ }
1078
+ /** The pick a menu value names; `auto` and a malformed value both pick nothing. */
1079
+ function modelOptionPick(value) {
1080
+ const at = value.indexOf("|");
1081
+ if (at <= 0) return null;
1082
+ return {
1083
+ provider: value.slice(0, at),
1084
+ model: value.slice(at + 1)
1085
+ };
1086
+ }
1087
+ /**
1088
+ * Follow-default first, then every Provider's models. The first entry exists
1089
+ * before the directory arrives, so the toolbar holds its place instead of
1090
+ * appearing a round trip later than the rest of the page.
1091
+ */
1092
+ function modelOptionsFrom(models, t, autoKey) {
1093
+ const options = [{
1094
+ value: "auto",
1095
+ label: models?.effective?.model ?? models?.inherited?.model ?? models?.defaultSelection?.model ?? t(autoKey),
1096
+ detail: t("evolution.modelAutoHint")
1097
+ }];
1098
+ if (models === null) return options;
1099
+ for (const group of models.groups) for (const entry of group.models) options.push({
1100
+ value: `${group.id}|${entry.id}`,
1101
+ label: entry.name,
1102
+ detail: group.name
1103
+ });
1104
+ return options;
1105
+ }
1106
+ /** The same list for one card: follow-default, then the directory without its own default entry. */
1107
+ function modelCardOptionsFrom(modelOptions, t, autoKey) {
1108
+ return [{
1109
+ value: "auto",
1110
+ label: t(autoKey)
1111
+ }, ...modelOptions.slice(1)];
1112
+ }
1113
+ const NO_PREFERENCES = {
1114
+ suggestionModels: {},
1115
+ skillRunModels: {}
1116
+ };
1117
+ /**
1118
+ * Read the directory and the stored picks alongside the page's own data, and
1119
+ * write one pick at a time. A write shows locally first so the menu answers at
1120
+ * once, then takes the Host's answer, which is also what a second window sees.
1121
+ */
1122
+ function useModelChoice(context, autoKey) {
1123
+ const t = useT();
1124
+ const [models, setModels] = (0, react.useState)(null);
1125
+ const [preferences, setPreferences] = (0, react.useState)(NO_PREFERENCES);
1126
+ (0, react.useEffect)(() => {
1127
+ let active = true;
1128
+ context.client.models().then((value) => {
1129
+ if (active) setModels(value);
1130
+ }).catch(() => void 0);
1131
+ return () => {
1132
+ active = false;
1133
+ };
1134
+ }, [context.client]);
1135
+ (0, react.useEffect)(() => {
1136
+ let active = true;
1137
+ context.client.draftPreferences().then((value) => {
1138
+ if (active) setPreferences(value);
1139
+ }).catch(() => void 0);
1140
+ return () => {
1141
+ active = false;
1142
+ };
1143
+ }, [context.client, context.revision]);
1144
+ /** Show the pick now, then let the Host's answer replace it; a failure shows through and reverts. */
1145
+ const write = (0, react.useCallback)((apply, operation) => {
1146
+ setPreferences((current) => apply(current));
1147
+ operation().then((next) => {
1148
+ setPreferences(next);
1149
+ context.refresh();
1150
+ }).catch((error) => {
1151
+ context.fail(error);
1152
+ context.refresh();
1153
+ });
1154
+ }, [context, context.client]);
1155
+ const options = (0, react.useMemo)(() => modelOptionsFrom(models, t, autoKey), [
1156
+ models,
1157
+ t,
1158
+ autoKey
1159
+ ]);
1160
+ return {
1161
+ models,
1162
+ preferences,
1163
+ options,
1164
+ cardOptions: (0, react.useMemo)(() => modelCardOptionsFrom(options, t, autoKey), [
1165
+ options,
1166
+ t,
1167
+ autoKey
1168
+ ]),
1169
+ saveDraftModel: (model) => write((current) => model === null ? omit(current, "model") : {
1170
+ ...current,
1171
+ model
1172
+ }, () => context.client.saveDraftModel(model)),
1173
+ saveSuggestionModel: (id, model) => write((current) => {
1174
+ const suggestionModels = { ...current.suggestionModels };
1175
+ if (model === null) delete suggestionModels[id];
1176
+ else suggestionModels[id] = model;
1177
+ return {
1178
+ ...current,
1179
+ suggestionModels
1180
+ };
1181
+ }, () => context.client.saveSuggestionModel(id, model)),
1182
+ saveRunModel: (model) => write((current) => model === null ? omit(current, "runModel") : {
1183
+ ...current,
1184
+ runModel: model
1185
+ }, () => context.client.saveRunModel(model)),
1186
+ saveSkillRunModel: (skillName, model) => write((current) => {
1187
+ const skillRunModels = { ...current.skillRunModels };
1188
+ if (model === null) delete skillRunModels[skillName];
1189
+ else skillRunModels[skillName] = model;
1190
+ return {
1191
+ ...current,
1192
+ skillRunModels
1193
+ };
1194
+ }, () => context.client.saveSkillRunModel(skillName, model))
1195
+ };
1196
+ }
1197
+ /** The preferences without one optional pick, for the case a pick was cleared. */
1198
+ function omit(preferences, key) {
1199
+ if (preferences[key] === void 0) return preferences;
1200
+ const next = { ...preferences };
1201
+ delete next[key];
1202
+ return next;
1203
+ }
1204
+ //#endregion
1011
1205
  //#region ../../node_modules/.pnpm/markdown-to-jsx@7.7.17_react@18.3.1/node_modules/markdown-to-jsx/dist/index.module.js
1012
1206
  function n() {
1013
1207
  return n = Object.assign ? Object.assign.bind() : function(r) {
@@ -2314,6 +2508,7 @@ window.__ModuleLoader__.load({
2314
2508
  function SkillTests(props) {
2315
2509
  const t = useT();
2316
2510
  const { context, skillName } = props;
2511
+ const runModel = props.runModel ?? null;
2317
2512
  const [cases, setCases] = (0, react.useState)(null);
2318
2513
  const [runs, setRuns] = (0, react.useState)([]);
2319
2514
  const [hasFile, setHasFile] = (0, react.useState)(true);
@@ -2349,7 +2544,11 @@ window.__ModuleLoader__.load({
2349
2544
  try {
2350
2545
  const started = await context.client.backtest({
2351
2546
  skillName,
2352
- target: { kind: hasFile ? "current" : "none" }
2547
+ target: { kind: hasFile ? "current" : "none" },
2548
+ ...runModel === null ? {} : {
2549
+ provider: runModel.provider,
2550
+ model: runModel.model
2551
+ }
2353
2552
  });
2354
2553
  setOpenRun(started.runId);
2355
2554
  context.refresh();
@@ -2716,6 +2915,7 @@ window.__ModuleLoader__.load({
2716
2915
  const [proposed, setProposed] = (0, react.useState)(/* @__PURE__ */ new Set());
2717
2916
  const [query, setQuery] = (0, react.useState)("");
2718
2917
  const [selected, setSelected] = (0, react.useState)(location.skillName);
2918
+ const choice = useModelChoice(context, "tests.modelAuto");
2719
2919
  (0, react.useEffect)(() => {
2720
2920
  if (location.skillName !== void 0) setSelected(location.skillName);
2721
2921
  }, [location.skillName, location.nonce]);
@@ -2775,7 +2975,45 @@ window.__ModuleLoader__.load({
2775
2975
  rows: visible.filter((row) => row.cases === 0)
2776
2976
  }].filter((group) => group.rows.length > 0);
2777
2977
  const current = rows.find((row) => row.name === selected) ?? groups[0]?.rows[0] ?? rows[0];
2778
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2978
+ const runOverride = Object.hasOwn(choice.preferences.skillRunModels, current.name) ? choice.preferences.skillRunModels[current.name] : null;
2979
+ const effectiveRunModel = runOverride ?? choice.preferences.runModel ?? null;
2980
+ const saveRun = (value) => choice.saveRunModel(modelOptionPick(value));
2981
+ const saveSkillRun = (value) => choice.saveSkillRunModel(current.name, modelOptionPick(value));
2982
+ const modelBar = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2983
+ className: css.skListBar,
2984
+ style: {
2985
+ borderBottom: "none",
2986
+ padding: "0 0 10px"
2987
+ },
2988
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2989
+ className: css.skSplit,
2990
+ style: {
2991
+ minHeight: 0,
2992
+ alignItems: "center",
2993
+ width: "100%"
2994
+ },
2995
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
2996
+ label: t("tests.model"),
2997
+ triggerDetail: true,
2998
+ inline: true,
2999
+ size: "sm",
3000
+ value: modelOptionValue(choice.preferences.runModel),
3001
+ disabled: !context.writable || choice.models === null,
3002
+ onChange: saveRun,
3003
+ options: choice.options
3004
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
3005
+ label: t("tests.modelCard"),
3006
+ triggerDetail: true,
3007
+ inline: true,
3008
+ size: "sm",
3009
+ value: modelOptionValue(runOverride),
3010
+ disabled: !context.writable || choice.models === null,
3011
+ onChange: saveSkillRun,
3012
+ options: choice.cardOptions
3013
+ })]
3014
+ })
3015
+ });
3016
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [modelBar, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2779
3017
  className: css.skSplit,
2780
3018
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
2781
3019
  className: css.skList,
@@ -2843,11 +3081,12 @@ window.__ModuleLoader__.load({
2843
3081
  })] })] })] })
2844
3082
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SkillTests, {
2845
3083
  context,
2846
- skillName: current.name
3084
+ skillName: current.name,
3085
+ runModel: effectiveRunModel
2847
3086
  })]
2848
3087
  }, current.name)
2849
3088
  })]
2850
- });
3089
+ })] });
2851
3090
  }
2852
3091
  //#endregion
2853
3092
  //#region src/client/evidence-page.tsx
@@ -3132,6 +3371,8 @@ window.__ModuleLoader__.load({
3132
3371
  const [drafts, setDrafts] = (0, react.useState)([]);
3133
3372
  const [selected, setSelected] = (0, react.useState)(location.suggestionId ?? location.draftId);
3134
3373
  const [reviewing, setReviewing] = (0, react.useState)(false);
3374
+ const [deleting, setDeleting] = (0, react.useState)(void 0);
3375
+ const choice = useModelChoice(context, "evolution.modelAuto");
3135
3376
  (0, react.useEffect)(() => {
3136
3377
  let active = true;
3137
3378
  context.client.suggestions().then((list) => {
@@ -3242,8 +3483,62 @@ window.__ModuleLoader__.load({
3242
3483
  location,
3243
3484
  bar
3244
3485
  });
3245
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3246
- className: css.skSplit,
3486
+ const currentId = current?.kind === "suggestion" ? current.id : void 0;
3487
+ const canOverride = currentId !== void 0 && current?.kind === "suggestion" && PENDING.includes(current.suggestion.status);
3488
+ const currentOverride = currentId === void 0 ? null : Object.hasOwn(choice.preferences.suggestionModels, currentId) ? choice.preferences.suggestionModels[currentId] : null;
3489
+ const currentModel = currentOverride ?? choice.preferences.model ?? null;
3490
+ const saveDraftModel = (value) => choice.saveDraftModel(modelOptionPick(value));
3491
+ const saveSuggestionModel = (value) => {
3492
+ if (canOverride && currentId !== void 0) choice.saveSuggestionModel(currentId, modelOptionPick(value));
3493
+ };
3494
+ const removeItem = async (item) => {
3495
+ try {
3496
+ if (item.kind === "draft") await context.client.deleteDraft(item.id);
3497
+ else await context.client.deleteSuggestion(item.id);
3498
+ setDeleting(void 0);
3499
+ if (selected === item.id) setSelected(void 0);
3500
+ context.notice(t("evolution.deleted"));
3501
+ context.refresh();
3502
+ } catch (error) {
3503
+ context.fail(error);
3504
+ }
3505
+ };
3506
+ const modelBar = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3507
+ className: css.skListBar,
3508
+ style: {
3509
+ borderBottom: "none",
3510
+ padding: "0 0 10px"
3511
+ },
3512
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3513
+ className: css.skSplit,
3514
+ style: {
3515
+ minHeight: 0,
3516
+ alignItems: "center",
3517
+ width: "100%"
3518
+ },
3519
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
3520
+ label: t("evolution.model"),
3521
+ triggerDetail: true,
3522
+ inline: true,
3523
+ size: "sm",
3524
+ value: modelOptionValue(choice.preferences.model),
3525
+ disabled: !context.writable || choice.models === null,
3526
+ onChange: saveDraftModel,
3527
+ options: choice.options
3528
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(dsh_mnemon_client.SelectField, {
3529
+ label: t("evolution.modelCard"),
3530
+ triggerDetail: true,
3531
+ inline: true,
3532
+ size: "sm",
3533
+ value: modelOptionValue(currentOverride),
3534
+ disabled: !context.writable || !canOverride || choice.models === null,
3535
+ onChange: saveSuggestionModel,
3536
+ options: choice.cardOptions
3537
+ })]
3538
+ })
3539
+ });
3540
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [modelBar, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3541
+ className: (0, dsh_mnemon_client.appearanceClass)(css.skSplit, css.skEvolutionSplit),
3247
3542
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("aside", {
3248
3543
  className: css.skList,
3249
3544
  children: [bar, items.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ListItem, {
@@ -3275,22 +3570,44 @@ window.__ModuleLoader__.load({
3275
3570
  children: t(`evolution.emptyBody.${filter}`)
3276
3571
  }) : current.kind === "suggestion" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SuggestionDetail, {
3277
3572
  context,
3278
- id: current.id
3573
+ id: current.id,
3574
+ model: currentModel
3279
3575
  }, current.id) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
3280
3576
  className: css.skDetail,
3281
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
3282
- className: css.skDetailHead,
3283
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3284
- className: css.skKicker,
3285
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionTag, { action: "update" })
3286
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: current.draft.skillName })] })
3287
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftReview, {
3288
- context,
3289
- draftId: current.id
3290
- }, current.id)]
3577
+ children: [
3578
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
3579
+ className: css.skDetailHead,
3580
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3581
+ className: css.skKicker,
3582
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionTag, { action: "update" })
3583
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: current.draft.skillName })] }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3584
+ className: css.skDetailActions,
3585
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3586
+ variant: "ghost",
3587
+ size: "sm",
3588
+ disabled: !context.writable,
3589
+ onClick: () => setDeleting(current.id),
3590
+ children: t("common.delete")
3591
+ })
3592
+ })]
3593
+ }),
3594
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftReview, {
3595
+ context,
3596
+ draftId: current.id,
3597
+ model: currentModel
3598
+ }, current.id),
3599
+ deleting === current.id && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Confirm, {
3600
+ danger: true,
3601
+ title: t("evolution.deleteTitle"),
3602
+ body: t("evolution.deleteBody"),
3603
+ confirmLabel: t("common.delete"),
3604
+ onClose: () => setDeleting(void 0),
3605
+ onConfirm: () => void removeItem(current)
3606
+ })
3607
+ ]
3291
3608
  })
3292
- })]
3293
- });
3609
+ }, current?.id ?? filter)]
3610
+ })] });
3294
3611
  }
3295
3612
  function ListItem(props) {
3296
3613
  const t = useT();
@@ -3336,9 +3653,14 @@ window.__ModuleLoader__.load({
3336
3653
  function SuggestionDetail(props) {
3337
3654
  const t = useT();
3338
3655
  const { context } = props;
3656
+ const route = props.model === null || props.model === void 0 ? {} : {
3657
+ provider: props.model.provider,
3658
+ model: props.model.model
3659
+ };
3339
3660
  const [view, setView] = (0, react.useState)(null);
3340
3661
  const [trajectories, setTrajectories] = (0, react.useState)(/* @__PURE__ */ new Map());
3341
3662
  const [busy, setBusy] = (0, react.useState)(false);
3663
+ const [deleting, setDeleting] = (0, react.useState)(false);
3342
3664
  (0, react.useEffect)(() => {
3343
3665
  let active = true;
3344
3666
  context.client.suggestion(props.id).then(async (value) => {
@@ -3406,25 +3728,50 @@ window.__ModuleLoader__.load({
3406
3728
  })
3407
3729
  ] }), suggestion.status === "pending" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3408
3730
  className: css.skDetailActions,
3409
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3410
- variant: "primary",
3411
- size: "sm",
3412
- disabled: !context.writable || busy || !canDraft,
3413
- title: canDraft ? void 0 : t("evolution.noAgent"),
3414
- onClick: () => void act(() => context.client.generateDraft({ suggestionId: suggestion.id })),
3415
- children: t("evolution.draft")
3416
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3417
- variant: "ghost",
3418
- size: "sm",
3419
- disabled: !context.writable || busy,
3420
- onClick: () => void act(async () => {
3421
- await context.client.dismissSuggestion(suggestion.id);
3422
- context.notice(t("evolution.dismissed"));
3731
+ children: [
3732
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3733
+ variant: "primary",
3734
+ size: "sm",
3735
+ disabled: !context.writable || busy || !canDraft,
3736
+ title: canDraft ? void 0 : t("evolution.noAgent"),
3737
+ onClick: () => void act(() => context.client.generateDraft({
3738
+ suggestionId: suggestion.id,
3739
+ ...route
3740
+ })),
3741
+ children: t("evolution.draft")
3423
3742
  }),
3424
- children: t("evolution.dismiss")
3425
- })]
3743
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3744
+ variant: "ghost",
3745
+ size: "sm",
3746
+ disabled: !context.writable || busy,
3747
+ onClick: () => void act(async () => {
3748
+ await context.client.dismissSuggestion(suggestion.id);
3749
+ context.notice(t("evolution.dismissed"));
3750
+ }),
3751
+ children: t("evolution.dismiss")
3752
+ }),
3753
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3754
+ variant: "ghost",
3755
+ size: "sm",
3756
+ disabled: !context.writable || busy,
3757
+ onClick: () => setDeleting(true),
3758
+ children: t("common.delete")
3759
+ })
3760
+ ]
3426
3761
  })]
3427
3762
  }),
3763
+ deleting && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Confirm, {
3764
+ danger: true,
3765
+ title: t("evolution.deleteTitle"),
3766
+ body: t("evolution.deleteBody"),
3767
+ confirmLabel: t("common.delete"),
3768
+ onClose: () => setDeleting(false),
3769
+ onConfirm: () => void act(async () => {
3770
+ await context.client.deleteSuggestion(suggestion.id);
3771
+ setDeleting(false);
3772
+ context.notice(t("evolution.deleted"));
3773
+ })
3774
+ }),
3428
3775
  suggestion.rationale !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Clamp, { text: suggestion.rationale }),
3429
3776
  suggestion.action === "update" && view.skill === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3430
3777
  className: css.skWarn,
@@ -3441,7 +3788,8 @@ window.__ModuleLoader__.load({
3441
3788
  }),
3442
3789
  suggestion.status === "review" && suggestion.draftId !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DraftReview, {
3443
3790
  context,
3444
- draftId: suggestion.draftId
3791
+ draftId: suggestion.draftId,
3792
+ model: props.model ?? null
3445
3793
  }),
3446
3794
  suggestion.status === "adopted" && view.skill !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
3447
3795
  className: css.skSuccess,
@@ -3534,6 +3882,10 @@ window.__ModuleLoader__.load({
3534
3882
  function DraftReview(props) {
3535
3883
  const t = useT();
3536
3884
  const { context } = props;
3885
+ const route = props.model === null || props.model === void 0 ? {} : {
3886
+ provider: props.model.provider,
3887
+ model: props.model.model
3888
+ };
3537
3889
  const [view, setView] = (0, react.useState)(null);
3538
3890
  const [cases, setCases] = (0, react.useState)(void 0);
3539
3891
  const [editing, setEditing] = (0, react.useState)(null);
@@ -3604,7 +3956,8 @@ window.__ModuleLoader__.load({
3604
3956
  });
3605
3957
  const redraft = (note) => act(() => context.client.generateDraft({
3606
3958
  ...draft.suggestionId === void 0 ? { skill: draft.skillName } : { suggestionId: draft.suggestionId },
3607
- guidance: note
3959
+ guidance: note,
3960
+ ...route
3608
3961
  }), () => setRedrafting(null));
3609
3962
  const ready = draft.status === "ready";
3610
3963
  const progress = (run) => run === void 0 ? 0 : run.progress.done;
@@ -239,6 +239,30 @@ interface RunTarget {
239
239
  draftId?: string;
240
240
  versionId?: string;
241
241
  }
242
+ /** One Provider and model, as a user picked it; never carries a reasoning effort. */
243
+ interface ModelRoute {
244
+ provider: string;
245
+ model: string;
246
+ }
247
+ /**
248
+ * The models the user picked for skill work, kept beside the ledger. Every
249
+ * entry is optional: absent means "follow the task Agent's own route".
250
+ * `suggestionModels` is keyed by suggestion id, `skillRunModels` by skill name.
251
+ */
252
+ interface DraftPreferences {
253
+ version: 1;
254
+ draftModel?: ModelRoute;
255
+ runModel?: ModelRoute;
256
+ suggestionModels: Record<string, ModelRoute>;
257
+ skillRunModels: Record<string, ModelRoute>;
258
+ }
259
+ /** What the pickers read: the stored picks, named the way the pages use them. */
260
+ interface DraftPreferencesView {
261
+ model?: ModelRoute;
262
+ runModel?: ModelRoute;
263
+ suggestionModels: Record<string, ModelRoute>;
264
+ skillRunModels: Record<string, ModelRoute>;
265
+ }
242
266
  interface CaseResult {
243
267
  caseId: string;
244
268
  title: string;
@@ -596,4 +620,4 @@ interface MarketInstall {
596
620
  installedAt: string;
597
621
  }
598
622
  //#endregion
599
- export { BacktestRun, CaseResult, CatalogView, DEFAULT_SKILLS_POLICY, type DetectedSource, DraftStatus, DraftView, EVOLUTION_SIGNALS, EvalCase, EvalCheck, EvidencePack, EvidenceReference, EvolutionSignal, LocalizedText, MarketAudit, MarketEntry, MarketInstall, MarketInstallState, MarketItem, MarketPreview, MarketRegistry, MarketRegistryFile, MarketSearchResult, MarketSource, type MarketSourceKind, MarketView, ReviewLogEntry, ReviewRecordInput, ReviewRecordResult, ReviewScore, RunStatus, RunTarget, RunTargetKind, SKILL_ROOT_KINDS, SKILL_ROOT_RANK, SUGGESTION_STATUSES, SkillCatalog, SkillDocument, SkillDraft, SkillInvocation, SkillProblem, SkillRoot, SkillRootKind, SkillSuggestion, SkillSummary, SkillVersion, SkillVersionReason, SkillsOverview, SkillsPolicy, SuggestionStatus, SuggestionView, Trajectory, TrajectoryAnnotation, TrajectoryStats, TrajectoryStep, TrajectoryStepKind, TrajectorySummary, TrashEntry, TrashRestoreInput, TrashRestorePreview };
623
+ export { BacktestRun, CaseResult, CatalogView, DEFAULT_SKILLS_POLICY, type DetectedSource, DraftPreferences, DraftPreferencesView, DraftStatus, DraftView, EVOLUTION_SIGNALS, EvalCase, EvalCheck, EvidencePack, EvidenceReference, EvolutionSignal, LocalizedText, MarketAudit, MarketEntry, MarketInstall, MarketInstallState, MarketItem, MarketPreview, MarketRegistry, MarketRegistryFile, MarketSearchResult, MarketSource, type MarketSourceKind, MarketView, ModelRoute, ReviewLogEntry, ReviewRecordInput, ReviewRecordResult, ReviewScore, RunStatus, RunTarget, RunTargetKind, SKILL_ROOT_KINDS, SKILL_ROOT_RANK, SUGGESTION_STATUSES, SkillCatalog, SkillDocument, SkillDraft, SkillInvocation, SkillProblem, SkillRoot, SkillRootKind, SkillSuggestion, SkillSummary, SkillVersion, SkillVersionReason, SkillsOverview, SkillsPolicy, SuggestionStatus, SuggestionView, Trajectory, TrajectoryAnnotation, TrajectoryStats, TrajectoryStep, TrajectoryStepKind, TrajectorySummary, TrashEntry, TrashRestoreInput, TrashRestorePreview };
package/lib/index.js CHANGED
@@ -489,6 +489,43 @@ var SkillsStore = class {
489
489
  installs: array(value.installs)
490
490
  };
491
491
  }
492
+ /**
493
+ * What the user picked for draft and backtest runs, kept out of `fingerprint()`
494
+ * on purpose: changing a picker must not invalidate an open page's revision.
495
+ */
496
+ preferences() {
497
+ const stored = object$1(this.readJson("preferences.json")) ?? {};
498
+ const route = (value) => {
499
+ const picked = object$1(value);
500
+ const provider = typeof picked?.provider === "string" ? picked.provider : void 0;
501
+ const model = typeof picked?.model === "string" ? picked.model : void 0;
502
+ return provider !== void 0 && model !== void 0 ? {
503
+ provider,
504
+ model
505
+ } : void 0;
506
+ };
507
+ const routes = (value) => {
508
+ const result = {};
509
+ const map = object$1(value);
510
+ if (map !== void 0) for (const [key, item] of Object.entries(map)) {
511
+ const picked = route(item);
512
+ if (picked !== void 0) result[key] = picked;
513
+ }
514
+ return result;
515
+ };
516
+ const draft = route(stored.draftModel);
517
+ const run = route(stored.runModel);
518
+ return {
519
+ version: 1,
520
+ ...draft === void 0 ? {} : { draftModel: draft },
521
+ ...run === void 0 ? {} : { runModel: run },
522
+ suggestionModels: routes(stored.suggestionModels),
523
+ skillRunModels: routes(stored.skillRunModels)
524
+ };
525
+ }
526
+ savePreferences(preferences) {
527
+ this.writeJson("preferences.json", preferences);
528
+ }
492
529
  saveLedger(ledger) {
493
530
  ledger.generation += 1;
494
531
  ledger.reviews = ledger.reviews.slice(0, 200);
@@ -732,13 +769,33 @@ function clip$1(value, maximum) {
732
769
  const text = value.trim();
733
770
  return text.length <= maximum ? text : text.slice(0, maximum - 1) + "…";
734
771
  }
735
- /** Move pending suggestions past their expiry to `expired`; true when anything changed. */
772
+ /**
773
+ * `drafting` was set before this process started, so no live writer owns it any
774
+ * more. A draft write is cancelled only by the Host going away, and the catch
775
+ * that would put the suggestion back never runs then, so the row would sit in
776
+ * "drafting" forever and refuse both a retry and a delete.
777
+ */
778
+ const PROCESS_STARTED_AT = Date.now() - Math.round(process.uptime() * 1e3);
779
+ const ORPHAN_DRAFT_ERROR = "the host restarted while this draft was being written";
780
+ function orphanedDraft(suggestion) {
781
+ const at = Date.parse(suggestion.updatedAt);
782
+ return !Number.isFinite(at) || at < PROCESS_STARTED_AT;
783
+ }
784
+ /**
785
+ * Move pending suggestions past their expiry to `expired`, and suggestions whose
786
+ * draft was abandoned by a dead process back to `pending`; true when anything changed.
787
+ */
736
788
  function expireSuggestions(ledger, now) {
737
789
  let changed = false;
738
790
  for (const suggestion of ledger.suggestions) if (suggestion.status === "pending" && Date.parse(suggestion.expiresAt) < now.getTime()) {
739
791
  suggestion.status = "expired";
740
792
  suggestion.updatedAt = now.toISOString();
741
793
  changed = true;
794
+ } else if (suggestion.status === "drafting" && orphanedDraft(suggestion)) {
795
+ suggestion.status = "pending";
796
+ suggestion.updatedAt = now.toISOString();
797
+ suggestion.lastError = ORPHAN_DRAFT_ERROR;
798
+ changed = true;
742
799
  }
743
800
  return changed;
744
801
  }
@@ -3410,6 +3467,39 @@ var SkillsService = class {
3410
3467
  return { purged: entries.length };
3411
3468
  });
3412
3469
  }
3470
+ /** The model the user picked for drafts and backtests, if any. */
3471
+ draftPreferences() {
3472
+ const stored = this.store.preferences();
3473
+ return {
3474
+ ...stored.draftModel === void 0 ? {} : { model: stored.draftModel },
3475
+ ...stored.runModel === void 0 ? {} : { runModel: stored.runModel },
3476
+ suggestionModels: stored.suggestionModels,
3477
+ skillRunModels: stored.skillRunModels
3478
+ };
3479
+ }
3480
+ /**
3481
+ * Record one picker change. `suggestionId` targets a single suggestion,
3482
+ * `skillName` with `slot: 'run'` a single skill, and a null model clears the
3483
+ * entry so the page falls back to following the task Agent again.
3484
+ */
3485
+ setDraftPreference(input) {
3486
+ return this.write(() => {
3487
+ const preferences = this.store.preferences();
3488
+ if (input.slot === "run") {
3489
+ if (input.skillName !== void 0) {
3490
+ if (input.model === null) delete preferences.skillRunModels[input.skillName];
3491
+ else preferences.skillRunModels[input.skillName] = input.model;
3492
+ } else if (input.model === null) delete preferences.runModel;
3493
+ else preferences.runModel = input.model;
3494
+ } else if (input.suggestionId !== void 0) {
3495
+ if (input.model === null) delete preferences.suggestionModels[input.suggestionId];
3496
+ else preferences.suggestionModels[input.suggestionId] = input.model;
3497
+ } else if (input.model === null) delete preferences.draftModel;
3498
+ else preferences.draftModel = input.model;
3499
+ this.store.savePreferences(preferences);
3500
+ return this.draftPreferences();
3501
+ });
3502
+ }
3413
3503
  restoreVersion(workspace, input) {
3414
3504
  return this.write(() => {
3415
3505
  const skill = findSkill(this.catalog(workspace), input.key);
@@ -3449,6 +3539,25 @@ var SkillsService = class {
3449
3539
  return suggestion;
3450
3540
  });
3451
3541
  }
3542
+ /** Remove a suggestion for good, together with any draft it produced and its model pick. */
3543
+ deleteSuggestion(id) {
3544
+ return this.write(() => {
3545
+ const ledger = this.store.ledger();
3546
+ expireSuggestions(ledger, this.clock());
3547
+ const index = ledger.suggestions.findIndex((candidate) => candidate.id === id);
3548
+ if (index < 0) throw new Error("suggestion not found: " + id);
3549
+ if (ledger.suggestions[index].status === "drafting") throw new Error("a draft is being written for this suggestion; wait for it to finish");
3550
+ ledger.suggestions.splice(index, 1);
3551
+ ledger.drafts = ledger.drafts.filter((draft) => draft.suggestionId !== id);
3552
+ const preferences = this.store.preferences();
3553
+ if (preferences.suggestionModels[id] !== void 0) {
3554
+ delete preferences.suggestionModels[id];
3555
+ this.store.savePreferences(preferences);
3556
+ }
3557
+ this.store.saveLedger(ledger);
3558
+ return { deleted: id };
3559
+ });
3560
+ }
3452
3561
  /** The Host marks a suggestion `drafting` before a task Agent writes, and back to `pending` if it fails. */
3453
3562
  suggestionStatus(input) {
3454
3563
  return this.withSuggestion(input.id, (suggestion) => {
@@ -3698,6 +3807,40 @@ var SkillsService = class {
3698
3807
  return draft;
3699
3808
  });
3700
3809
  }
3810
+ /** Remove a draft for good; its suggestion goes back to `pending` so it can be drafted again. */
3811
+ deleteDraft(id) {
3812
+ return this.write(() => {
3813
+ const ledger = this.store.ledger();
3814
+ const index = ledger.drafts.findIndex((candidate) => candidate.id === id);
3815
+ if (index < 0) throw new Error("draft not found: " + id);
3816
+ const draft = ledger.drafts[index];
3817
+ ledger.drafts.splice(index, 1);
3818
+ if (draft.suggestionId !== void 0) {
3819
+ const suggestion = ledger.suggestions.find((candidate) => candidate.id === draft.suggestionId);
3820
+ if (suggestion?.draftId === draft.id) {
3821
+ delete suggestion.draftId;
3822
+ if (suggestion.status === "review") suggestion.status = "pending";
3823
+ suggestion.updatedAt = this.clock().toISOString();
3824
+ }
3825
+ }
3826
+ this.store.saveLedger(ledger);
3827
+ return { deleted: id };
3828
+ });
3829
+ }
3830
+ /**
3831
+ * Put suggestions whose draft write died with the previous Host back to
3832
+ * `pending`, so the page stops showing them as "drafting" forever.
3833
+ */
3834
+ reclaimOrphanDrafts() {
3835
+ return this.write(() => {
3836
+ const ledger = this.store.ledger();
3837
+ const before = ledger.suggestions.filter((suggestion) => suggestion.status === "drafting").length;
3838
+ if (!expireSuggestions(ledger, this.clock())) return { reclaimed: 0 };
3839
+ this.store.saveLedger(ledger);
3840
+ const after = ledger.suggestions.filter((suggestion) => suggestion.status === "drafting").length;
3841
+ return { reclaimed: Math.max(0, before - after) };
3842
+ });
3843
+ }
3701
3844
  /** The content a run tests, resolved from its target. */
3702
3845
  targetContent(workspace, skillName, target) {
3703
3846
  if (target.kind === "none") return { target: { kind: "none" } };
@@ -4291,6 +4434,16 @@ function rootKind(value) {
4291
4434
  if (typeof value !== "string" || !SKILL_ROOT_KINDS.includes(value)) throw new Error("root must be one of " + SKILL_ROOT_KINDS.join(", "));
4292
4435
  return value;
4293
4436
  }
4437
+ /** A picked model, or null to clear the pick and follow the task Agent again. */
4438
+ function draftModelInput(value) {
4439
+ if (value === void 0 || value === null) return null;
4440
+ if (typeof value !== "object" || Array.isArray(value)) throw new Error("model must be an object or null");
4441
+ const picked = value;
4442
+ return {
4443
+ provider: memoryInputText(picked.provider, "model.provider", 100),
4444
+ model: memoryInputText(picked.model, "model.model", 200)
4445
+ };
4446
+ }
4294
4447
  function caseInput(value, skillName) {
4295
4448
  const input = memoryInputRecord(value, "case");
4296
4449
  const checks = input.checks;
@@ -4515,6 +4668,7 @@ function createSkillsMemorySource(config = {}) {
4515
4668
  ...effective.dshHome === void 0 ? {} : { dshHome: effective.dshHome },
4516
4669
  ...effective.agentsHome === void 0 ? {} : { agentsHome: effective.agentsHome }
4517
4670
  });
4671
+ service.reclaimOrphanDrafts().catch(() => void 0);
4518
4672
  const facts = (scope, management) => management ? {
4519
4673
  sourceInstanceKey: context.sourceInstanceKey,
4520
4674
  sourceTypeId: SKILLS_SOURCE_TYPE_ID,
@@ -4572,6 +4726,7 @@ function createSkillsMemorySource(config = {}) {
4572
4726
  ...optionalText(fields.skill, "skill", 64) === void 0 ? {} : { skill: optionalText(fields.skill, "skill", 64) }
4573
4727
  });
4574
4728
  case "draft": return service.draft(root, memoryInputText(fields.id, "id", 100));
4729
+ case "draft-preferences": return service.draftPreferences();
4575
4730
  case "reviews": return service.reviews({
4576
4731
  ...typeof fields.sessionId === "string" ? { sessionId: fields.sessionId } : {},
4577
4732
  ...typeof fields.limit === "number" ? { limit: fields.limit } : {}
@@ -4659,6 +4814,9 @@ function createSkillsMemorySource(config = {}) {
4659
4814
  case "suggestion-dismiss":
4660
4815
  value = await service.dismissSuggestion(memoryInputText(fields.id, "id", 100));
4661
4816
  break;
4817
+ case "suggestion-delete":
4818
+ value = await service.deleteSuggestion(memoryInputText(fields.id, "id", 100));
4819
+ break;
4662
4820
  case "suggestion-status": {
4663
4821
  const status = fields.status;
4664
4822
  if (status !== "drafting" && status !== "pending") throw new Error("status must be drafting or pending");
@@ -4715,6 +4873,22 @@ function createSkillsMemorySource(config = {}) {
4715
4873
  case "draft-discard":
4716
4874
  value = await service.discardDraft(memoryInputText(fields.id, "id", 100));
4717
4875
  break;
4876
+ case "draft-delete":
4877
+ value = await service.deleteDraft(memoryInputText(fields.id, "id", 100));
4878
+ break;
4879
+ case "draft-preference": {
4880
+ const slot = optionalText(fields.slot, "slot", 10);
4881
+ if (slot !== void 0 && slot !== "draft" && slot !== "run") throw new Error("slot must be draft or run");
4882
+ const suggestionId = optionalText(fields.suggestionId, "suggestionId", 100);
4883
+ if (suggestionId !== void 0 && slot === "run") throw new Error("a suggestion pick cannot be a backtest pick");
4884
+ value = await service.setDraftPreference({
4885
+ ...slot === void 0 ? {} : { slot },
4886
+ ...suggestionId === void 0 ? {} : { suggestionId },
4887
+ ...optionalText(fields.skillName, "skillName", 64) === void 0 ? {} : { skillName: optionalText(fields.skillName, "skillName", 64) },
4888
+ model: draftModelInput(fields.model)
4889
+ });
4890
+ break;
4891
+ }
4718
4892
  case "run-start":
4719
4893
  value = await service.startRun({
4720
4894
  skillName: memoryInputText(fields.skillName, "skillName", 64),
@@ -1,5 +1,5 @@
1
- import type { MnemonSourceManagementClient } from 'dsh-mnemon/client';
2
- import type { BacktestRun, CatalogView, DraftView, EvalCase, MarketPreview, MarketRegistry, MarketSearchResult, MarketView, EvidencePack, ReviewLogEntry, ReviewRecordResult, RunTarget, SkillDocument, SkillDraft, SkillRootKind, SkillSuggestion, SkillSummary, SkillVersion, SkillsOverview, SuggestionStatus, SuggestionView, Trajectory, TrajectorySummary, TrashEntry, TrashRestoreInput, TrashRestorePreview } from '../contracts.ts';
1
+ import type { MnemonSourceManagementClient, TaskAgentModelCatalog } from 'dsh-mnemon/client';
2
+ import type { BacktestRun, CatalogView, DraftPreferencesView, DraftView, EvalCase, MarketPreview, MarketRegistry, MarketSearchResult, MarketView, EvidencePack, ModelRoute, ReviewLogEntry, ReviewRecordResult, RunTarget, SkillDocument, SkillDraft, SkillRootKind, SkillSuggestion, SkillSummary, SkillVersion, SkillsOverview, SuggestionStatus, SuggestionView, Trajectory, TrajectorySummary, TrashEntry, TrashRestoreInput, TrashRestorePreview } from '../contracts.ts';
3
3
  export interface CaseDraft {
4
4
  id?: string;
5
5
  skillName: string;
@@ -75,6 +75,14 @@ export interface SkillsPageClient {
75
75
  }>;
76
76
  restoreVersion(key: string, versionId: string, expectedHash: string): Promise<SkillSummary>;
77
77
  dismissSuggestion(id: string): Promise<SkillSuggestion>;
78
+ /** Delete a waiting suggestion and any draft written for it. */
79
+ deleteSuggestion(id: string): Promise<{
80
+ deleted: string;
81
+ }>;
82
+ /** Delete a draft; its suggestion goes back to waiting. */
83
+ deleteDraft(id: string): Promise<{
84
+ deleted: string;
85
+ }>;
78
86
  pinTrajectory(id: string, pinned: boolean): Promise<TrajectorySummary>;
79
87
  deleteTrajectory(id: string): Promise<{
80
88
  deleted: string;
@@ -92,6 +100,18 @@ export interface SkillsPageClient {
92
100
  discardDraft(id: string): Promise<SkillDraft>;
93
101
  /** Attach a baseline run to the draft it is compared with. */
94
102
  linkRun(draftId: string, runId: string): Promise<void>;
103
+ /** The model each piece of model work follows: the two global picks and their per-item overrides. */
104
+ draftPreferences(): Promise<DraftPreferencesView>;
105
+ /** Pick the model for drafts, for backtests, or for one suggestion or skill; `null` follows the task Agent again. */
106
+ saveDraftModel(model: ModelRoute | null): Promise<DraftPreferencesView>;
107
+ saveSuggestionModel(id: string, model: ModelRoute | null): Promise<DraftPreferencesView>;
108
+ saveRunModel(model: ModelRoute | null): Promise<DraftPreferencesView>;
109
+ saveSkillRunModel(skillName: string, model: ModelRoute | null): Promise<DraftPreferencesView>;
110
+ /**
111
+ * The routes and model directory a page may offer. Rejects when the Host
112
+ * offers none, which is also when the page hides its pickers.
113
+ */
114
+ models(): Promise<TaskAgentModelCatalog>;
95
115
  market(): Promise<MarketView>;
96
116
  marketPreview(registryId: string, name: string): Promise<MarketPreview>;
97
117
  /** Search the search sources; the page filters the listed ones itself. */
@@ -118,6 +138,8 @@ export interface SkillsPageClient {
118
138
  skill?: string;
119
139
  guidance?: string;
120
140
  targetRoot?: SkillRootKind;
141
+ provider?: string;
142
+ model?: string;
121
143
  }): Promise<{
122
144
  started: true;
123
145
  }>;
@@ -125,6 +147,8 @@ export interface SkillsPageClient {
125
147
  skillName: string;
126
148
  target: RunTarget;
127
149
  caseIds?: string[];
150
+ provider?: string;
151
+ model?: string;
128
152
  }): Promise<{
129
153
  runId: string;
130
154
  }>;
@@ -0,0 +1,45 @@
1
+ import type { FieldOption, TaskAgentModelCatalog } from 'dsh-mnemon/client';
2
+ import type { DraftPreferencesView, ModelRoute } from '../contracts.ts';
3
+ import { type SkillsTranslate } from './presentation.ts';
4
+ import type { SkillsPageContext } from './ui.tsx';
5
+ /**
6
+ * The model pickers the Evolution and Evaluation pages share: which model
7
+ * drafts and backtests run on, globally and per item, offered from the same
8
+ * directory the task Agent resolves its own route against.
9
+ *
10
+ * A pick is stored as `provider|model`, so one menu value names one route, and
11
+ * an absent pick is `auto`: the page follows the task Agent, as it did before
12
+ * the user picked anything.
13
+ */
14
+ /** The menu value of a pick; `auto` asks for no pick at all. */
15
+ export declare function modelOptionValue(model: ModelRoute | null | undefined): string;
16
+ /** The pick a menu value names; `auto` and a malformed value both pick nothing. */
17
+ export declare function modelOptionPick(value: string): ModelRoute | null;
18
+ /**
19
+ * Follow-default first, then every Provider's models. The first entry exists
20
+ * before the directory arrives, so the toolbar holds its place instead of
21
+ * appearing a round trip later than the rest of the page.
22
+ */
23
+ export declare function modelOptionsFrom(models: TaskAgentModelCatalog | null, t: SkillsTranslate, autoKey: 'tests.modelAuto' | 'evolution.modelAuto'): FieldOption<string>[];
24
+ /** The same list for one card: follow-default, then the directory without its own default entry. */
25
+ export declare function modelCardOptionsFrom(modelOptions: readonly FieldOption<string>[], t: SkillsTranslate, autoKey: 'tests.modelAuto' | 'evolution.modelAuto'): FieldOption<string>[];
26
+ /** What the pickers read and write, and the directory behind them. */
27
+ export interface ModelChoice {
28
+ /** `null` until the directory arrives; the pickers are disabled meanwhile. */
29
+ models: TaskAgentModelCatalog | null;
30
+ preferences: DraftPreferencesView;
31
+ /** Every routable model, follow-default first. */
32
+ options: FieldOption<string>[];
33
+ /** The same for one card's own pick. */
34
+ cardOptions: FieldOption<string>[];
35
+ saveDraftModel(model: ModelRoute | null): void;
36
+ saveSuggestionModel(id: string, model: ModelRoute | null): void;
37
+ saveRunModel(model: ModelRoute | null): void;
38
+ saveSkillRunModel(skillName: string, model: ModelRoute | null): void;
39
+ }
40
+ /**
41
+ * Read the directory and the stored picks alongside the page's own data, and
42
+ * write one pick at a time. A write shows locally first so the menu answers at
43
+ * once, then takes the Host's answer, which is also what a second window sees.
44
+ */
45
+ export declare function useModelChoice(context: SkillsPageContext, autoKey: 'tests.modelAuto' | 'evolution.modelAuto'): ModelChoice;
@@ -1,5 +1,5 @@
1
1
  import { type JSX } from 'react';
2
- import type { BacktestRun } from '../contracts.ts';
2
+ import type { BacktestRun, ModelRoute } from '../contracts.ts';
3
3
  import type { SkillsPageContext } from './ui.tsx';
4
4
  /**
5
5
  * A skill's test cases and its backtests: the cases with a switch each, one
@@ -9,6 +9,7 @@ import type { SkillsPageContext } from './ui.tsx';
9
9
  export declare function SkillTests(props: {
10
10
  context: SkillsPageContext;
11
11
  skillName: string;
12
+ runModel?: ModelRoute | null;
12
13
  }): JSX.Element;
13
14
  /** One run's cases: the verdict, each check with the judge's note, and what the simulated run did and answered. */
14
15
  export declare function RunDetail(props: {
@@ -221,6 +221,30 @@ export interface RunTarget {
221
221
  draftId?: string;
222
222
  versionId?: string;
223
223
  }
224
+ /** One Provider and model, as a user picked it; never carries a reasoning effort. */
225
+ export interface ModelRoute {
226
+ provider: string;
227
+ model: string;
228
+ }
229
+ /**
230
+ * The models the user picked for skill work, kept beside the ledger. Every
231
+ * entry is optional: absent means "follow the task Agent's own route".
232
+ * `suggestionModels` is keyed by suggestion id, `skillRunModels` by skill name.
233
+ */
234
+ export interface DraftPreferences {
235
+ version: 1;
236
+ draftModel?: ModelRoute;
237
+ runModel?: ModelRoute;
238
+ suggestionModels: Record<string, ModelRoute>;
239
+ skillRunModels: Record<string, ModelRoute>;
240
+ }
241
+ /** What the pickers read: the stored picks, named the way the pages use them. */
242
+ export interface DraftPreferencesView {
243
+ model?: ModelRoute;
244
+ runModel?: ModelRoute;
245
+ suggestionModels: Record<string, ModelRoute>;
246
+ skillRunModels: Record<string, ModelRoute>;
247
+ }
224
248
  export interface CaseResult {
225
249
  caseId: string;
226
250
  title: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mnemon-source-skills",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Skills Source for Composable View Memory: DSH skill management, evolution suggestions, evidence trajectories and eval sets.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -53,7 +53,7 @@
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@deepseek-ai/cordis": "^4.0.1",
56
- "dsh-mnemon": "^0.5.33",
56
+ "dsh-mnemon": "^0.5.37",
57
57
  "react": "^18.2.0"
58
58
  },
59
59
  "devDependencies": {
@@ -62,7 +62,7 @@
62
62
  "@types/node": "^22.0.0",
63
63
  "@types/react": "^18.3.0",
64
64
  "@types/react-dom": "^18.3.0",
65
- "dsh-mnemon": "^0.5.36",
65
+ "dsh-mnemon": "^0.5.37",
66
66
  "jsdom": "^26.0.0",
67
67
  "react": "^18.2.0",
68
68
  "react-dom": "^18.2.0",
@@ -335,7 +335,17 @@
335
335
  "trash.original": "原位置",
336
336
  "trash.chooseHint": "可选择恢复位置或改名。同名替换需要明确确认,现有技能会保留在回收站。",
337
337
  "trash.replace": "替换同名技能,并将现有版本保留在回收站",
338
- "trash.confirmName": "输入 {name} 确认彻底删除"
338
+ "trash.confirmName": "输入 {name} 确认彻底删除",
339
+ "evolution.model": "全局模型",
340
+ "evolution.modelCard": "所选草案模型",
341
+ "evolution.modelAuto": "跟随默认",
342
+ "evolution.modelAutoHint": "使用当前任务 Agent 的模型",
343
+ "evolution.deleteTitle": "删除这条建议?",
344
+ "evolution.deleteBody": "它生成的草案和证据引用会一起删掉,无法恢复。",
345
+ "evolution.deleted": "已删除",
346
+ "tests.model": "全局模型",
347
+ "tests.modelCard": "所选回测模型",
348
+ "tests.modelAuto": "跟随默认"
339
349
  },
340
350
  "en": {
341
351
  "page.title": "Skills",
@@ -673,6 +683,16 @@
673
683
  "trash.original": "Original location",
674
684
  "trash.chooseHint": "Choose a location or a different name. Replacing a skill requires confirmation and keeps its current version in the Trash.",
675
685
  "trash.replace": "Replace the existing skill and keep its current version in the Trash",
676
- "trash.confirmName": "Type {name} to confirm permanent deletion"
686
+ "trash.confirmName": "Type {name} to confirm permanent deletion",
687
+ "evolution.model": "Global model",
688
+ "evolution.modelCard": "Selected model",
689
+ "evolution.modelAuto": "Follow default",
690
+ "evolution.modelAutoHint": "Use the model of the current task Agent",
691
+ "evolution.deleteTitle": "Delete this suggestion?",
692
+ "evolution.deleteBody": "Its draft and the evidence references it cites go with it, and this cannot be undone.",
693
+ "evolution.deleted": "Deleted",
694
+ "tests.model": "Global model",
695
+ "tests.modelCard": "Selected model",
696
+ "tests.modelAuto": "Follow default"
677
697
  }
678
698
  }
@@ -180,6 +180,12 @@
180
180
  .skList { display: flex; flex-direction: column; overflow: hidden; padding-bottom: 6px; }
181
181
  .skPane { padding: clamp(16px, 2vw, 24px); overflow: hidden; }
182
182
 
183
+ /* Keep the evolution inbox beside its detail while browsing long lists. */
184
+ .skEvolutionSplit { height: max(320px, calc(100dvh - 320px)); min-height: 0; }
185
+ .skEvolutionSplit > .skList,
186
+ .skEvolutionSplit > .skPane { min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; }
187
+ .skEvolutionSplit > .skList > * { flex-shrink: 0; }
188
+
183
189
  .skListBar { display: flex; align-items: center; gap: 8px; padding: 10px; border-bottom: .5px solid var(--mn-line); }
184
190
  .skListBar > :first-child { min-width: 0; flex: 1; }
185
191
  .skListNote { margin: 0; padding: 18px 16px; color: var(--mn-faint); font-size: 12px; line-height: 18px; text-align: center; }
@@ -574,6 +580,8 @@
574
580
  @media (max-width: 860px) {
575
581
  .skSplit { grid-template-columns: minmax(0, 1fr); }
576
582
  .skList { max-height: 360px; overflow-y: auto; }
583
+ .skEvolutionSplit { height: auto; }
584
+ .skEvolutionSplit > .skPane { overflow: visible; overscroll-behavior-y: auto; }
577
585
  }
578
586
 
579
587
  @media (max-width: 560px) {