dsh-switchman 1.11.5 → 1.11.7

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/client.js CHANGED
@@ -190,15 +190,16 @@ window.__ModuleLoader__.load({
190
190
  { field: 'poolReview', manualField: 'poolReviewManual', effortsField: 'poolReviewEfforts', lane: 'review' },
191
191
  ];
192
192
 
193
- /** Numeric watermark fields: settings field, schema minimum, and the
194
- * Host-side default (also the fallback for malformed stored values). */
193
+ /** Numeric watermark fields: settings field, schema bounds, and the
194
+ * Host-side default (also the fallback for malformed stored values).
195
+ * Bounds MUST mirror host/routes.js WM_BOUNDED_NUMBER_FIELDS. */
195
196
  const WM_NUMBER_FIELDS = [
196
- { field: 'wmSoftTokens', min: 1000, def: 80000 },
197
- { field: 'wmHardTokens', min: 2000, def: 95000 },
198
- { field: 'wmForceTokens', min: 3000, def: 150000 },
199
- { field: 'wmReadBudgetTokens', min: 200, def: 3000 },
200
- { field: 'wmSubagentForceTokens', min: 0, def: 0 },
201
- { field: 'wmSubagentWindowRatio', min: 0.1, def: 0.75 },
197
+ { field: 'wmSoftTokens', min: 1000, max: 10000000, def: 80000 },
198
+ { field: 'wmHardTokens', min: 2000, max: 10000000, def: 100000 },
199
+ { field: 'wmForceTokens', min: 3000, max: 10000000, def: 200000 },
200
+ { field: 'wmReadBudgetTokens', min: 200, max: 10000000, def: 3500 },
201
+ { field: 'wmSubagentForceTokens', min: 0, max: 10000000, def: 0 },
202
+ { field: 'wmSubagentWindowRatio', min: 0.1, max: 1, def: 0.75 },
202
203
  ];
203
204
 
204
205
  /** The three thresholds that must keep a strict ascending order. */
@@ -234,7 +235,7 @@ window.__ModuleLoader__.load({
234
235
  { field: 'intentTimeoutMs', min: 200, max: Infinity, def: 60000 },
235
236
  { field: 'intentHistoryMessages', min: 1, max: 20, def: 6 },
236
237
  { field: 'intentHistoryMaxChars', min: 200, max: 20000, def: 2400 },
237
- { field: 'intentContextWindow', min: 1024, max: Infinity, def: 200000 },
238
+ { field: 'intentContextWindow', min: 1024, max: Infinity, def: 250000 },
238
239
  ];
239
240
 
240
241
  /** Dictionary keys per numeric intent row. */
@@ -276,11 +277,14 @@ window.__ModuleLoader__.load({
276
277
  * write (and vice versa). */
277
278
  const TRIM_NUMBER_FIELDS = [
278
279
  { field: 'trimGrowthTokens', min: 1000, def: 22500 },
279
- { field: 'trimIncrementTokens', min: 1000, def: 25000 },
280
- { field: 'trimPressurePercent', min: 5, max: 100, def: 65 },
281
- { field: 'trimEmergencyPercent', min: 5, max: 100, def: 95 },
280
+ { field: 'trimIncrementTokens', min: 1000, def: 45000 },
281
+ { field: 'trimPressurePercent', min: 5, max: 100, def: 45 },
282
+ { field: 'trimEmergencyPercent', min: 5, max: 100, def: 90 },
283
+ { field: 'trimAdvisoryPercent', min: 5, max: 100, def: 50 },
284
+ { field: 'trimAdvisoryCriticalPercent', min: 5, max: 100, def: 80 },
285
+ { field: 'trimAdvisoryRepeatMs', min: 5000, max: 3600000, def: 120000 },
282
286
  { field: 'trimWindowTokens', min: 0, def: 0 },
283
- { field: 'trimProtectedTail', min: 0, max: 100, def: 10 },
287
+ { field: 'trimProtectedTail', min: 0, max: 100, def: 6 },
284
288
  { field: 'trimMaxFoldsPerHour', min: 1, max: 60, def: 30 },
285
289
  { field: 'trimLadderT2Tokens', min: 1000, def: 8000 },
286
290
  { field: 'trimLadderT2MinBlocks', min: 2, max: 200, def: 3 },
@@ -303,6 +307,18 @@ window.__ModuleLoader__.load({
303
307
  label: 'trimEmergencyLabel',
304
308
  help: 'trimEmergencyHelp',
305
309
  },
310
+ trimAdvisoryPercent: {
311
+ label: 'trimAdvisoryLabel',
312
+ help: 'trimAdvisoryHelp',
313
+ },
314
+ trimAdvisoryCriticalPercent: {
315
+ label: 'trimAdvisoryCriticalLabel',
316
+ help: 'trimAdvisoryCriticalHelp',
317
+ },
318
+ trimAdvisoryRepeatMs: {
319
+ label: 'trimAdvisoryRepeatLabel',
320
+ help: 'trimAdvisoryRepeatHelp',
321
+ },
306
322
  trimWindowTokens: {
307
323
  label: 'trimWindowLabel',
308
324
  help: 'trimWindowHelp',
@@ -350,6 +366,8 @@ window.__ModuleLoader__.load({
350
366
  'trimMode',
351
367
  'trimEnabled',
352
368
  'trimLadderEnabled',
369
+ 'trimProtectTaskIntent',
370
+ 'trimCriticalRelief',
353
371
  'surfaceFold',
354
372
  'trimSideModel',
355
373
  'trimFoldFallbackModel',
@@ -529,6 +547,9 @@ window.__ModuleLoader__.load({
529
547
  : 'auto',
530
548
  trimEnabled: bool('trimEnabled', true),
531
549
  trimLadderEnabled: bool('trimLadderEnabled', true),
550
+ trimProtectTaskIntent: bool('trimProtectTaskIntent', true),
551
+ trimCriticalRelief: bool('trimCriticalRelief', true),
552
+ trimVerboseLog: bool('trimVerboseLog', false),
532
553
  surfaceFold: bool('surfaceFold', true),
533
554
  trimSideModel:
534
555
  sanitizeRoute(value?.trimSideModel, true) ??
@@ -617,6 +638,9 @@ window.__ModuleLoader__.load({
617
638
  trimMode: values.trimMode,
618
639
  trimEnabled: values.trimEnabled,
619
640
  trimLadderEnabled: values.trimLadderEnabled,
641
+ trimProtectTaskIntent: values.trimProtectTaskIntent,
642
+ trimCriticalRelief: values.trimCriticalRelief,
643
+ trimVerboseLog: values.trimVerboseLog,
620
644
  surfaceFold: values.surfaceFold,
621
645
  trimSideModel: `${routeKey(values.trimSideModel)}\0${values.trimSideModel.effort ?? ''}`,
622
646
  trimFoldFallbackModel: `${routeKey(values.trimFoldFallbackModel)}\0${values.trimFoldFallbackModel.effort ?? ''}`,
@@ -890,6 +914,7 @@ window.__ModuleLoader__.load({
890
914
  wmReadBudgetLabel: '单次读取预算',
891
915
  wmReadBudgetHelp: '每次读取的 token 预算;每轮上限为其两倍。',
892
916
  wmNumberInvalid: '请输入不小于 {min} 的整数。',
917
+ wmNumberInvalidMax: '请输入 {min} 到 {max} 之间的数。',
893
918
  wmOrderInvalid: '三档水位需严格递增:soft < hard < force。',
894
919
  wmDenyModeLabel: '硬档行为',
895
920
  wmDenyModeCap: '限流放行',
@@ -914,11 +939,23 @@ window.__ModuleLoader__.load({
914
939
  trimSectionTitle: '上下文裁剪',
915
940
  trimModeLabel: '自动裁剪模式',
916
941
  trimModeHelp:
917
- '空闲时何时把历史折叠为摘要:off = 从不折叠,advisory = 仅模型主动调用,auto = 自动折叠。',
942
+ '空闲时何时把历史折叠为摘要:off = 从不折叠,advisory = 模型自主折叠(压力达线时引擎在系统提示注入一次性提醒),auto = 自动折叠。',
943
+ trimCriticalReliefLabel: '临界救援折叠',
944
+ trimCriticalReliefHelp: '开启后(默认),advisory 模式压力到达临界线(trimAdvisoryCriticalPercent)时引擎自动执行一次机械折叠(90 秒冷却),不再只依赖提示。',
945
+ trimVerboseLogLabel: '调试模式(详细日志)',
946
+ trimVerboseLogHelp: '默认关闭。开启后引擎的每个执行步骤、闸门判定与决策路径都会写入 decisions.log(debug 行),便于问题追溯;关闭时只记录关键决策行。无论开关与否,异常始终记录完整细节。',
947
+ trimDockLabel: '折叠 {pressure}%(线 {line}%)',
948
+ trimDockTipDomain: '折叠引擎口径:最近一次实付 prompt(max(view, wire))÷ 有效窗口(含上限)——不是输入框旁上下文面板的预测口径,两者本就不同、不应收敛。',
949
+ trimDockTipMass: '实付 {mass} / 窗口 {window} tokens',
950
+ trimDockTipMode: '模式:{mode}(advisory=模型自行折叠;auto=引擎自动折叠)',
951
+ trimDockTipReady: '临界纾缓就绪:达到 80% 线即由引擎机械折叠一次',
952
+ trimDockTipCooldown: '临界纾缓冷却中,剩 {seconds}s',
918
953
  trimEnabledLabel: '启用自动裁剪',
919
954
  trimEnabledHelp: '上下文裁剪层的总开关。',
920
955
  trimLadderEnabledLabel: '阶梯折叠(T1/T2/T3)',
921
956
  trimLadderEnabledHelp: '把累积的 T1 摘要再蒸馏为 T2、T2 再凝聚为 T3,让长会话视图保持平稳。',
957
+ trimProtectTaskIntentLabel: '保护任务意图',
958
+ trimProtectTaskIntentHelp: '第一条 user 消息(任务意图)永不折叠。关闭后它可进入折叠范围。',
922
959
  surfaceFoldLabel: '把折叠写入会话表面',
923
960
  surfaceFoldHelp: '追加宿主风格的替换事件,让折叠在冻结派发下也能到达线上。建议保持开启。',
924
961
  trimSideModelLabel: '摘要模型',
@@ -950,6 +987,12 @@ window.__ModuleLoader__.load({
950
987
  trimPressureHelp: '出站视图达到上下文窗口的这一百分比时折叠。',
951
988
  trimEmergencyLabel: '紧急阈值(%)',
952
989
  trimEmergencyHelp: '达到窗口的这一百分比时立即机械折叠。',
990
+ trimAdvisoryLabel: 'Advisory 提醒线(%)',
991
+ trimAdvisoryHelp: '仅 advisory 模式:压力达到窗口的这一百分比时,提醒模型自行折叠。',
992
+ trimAdvisoryCriticalLabel: 'Advisory 升级线(%)',
993
+ trimAdvisoryCriticalHelp: '仅 advisory 模式:达到这一百分比时,提醒升级为本轮必须折叠的指令。',
994
+ trimAdvisoryRepeatLabel: 'Advisory 重贴间隔(ms)',
995
+ trimAdvisoryRepeatHelp: '仅 advisory 模式:提醒贴在会话尾部后,每隔该毫秒数在新尾部重贴一次(临界档取其一半,下限 45 秒);默认 120000。',
953
996
  trimModeOff: '关闭',
954
997
  trimWindowLabel: '窗口上限(token)',
955
998
  trimWindowHelp: '压力与紧急档按 min(模型窗口, 上限) 计算;0 = 跟随强制水位(wmForceTokens)。',
@@ -1159,6 +1202,7 @@ window.__ModuleLoader__.load({
1159
1202
  wmReadBudgetLabel: 'Read budget',
1160
1203
  wmReadBudgetHelp: 'Token budget per read; each round caps at twice this.',
1161
1204
  wmNumberInvalid: 'Enter a whole number of {min} or more.',
1205
+ wmNumberInvalidMax: 'Enter a number between {min} and {max}.',
1162
1206
  wmOrderInvalid: 'The three tiers must strictly ascend: soft < hard < force.',
1163
1207
  wmDenyModeLabel: 'Hard-tier behavior',
1164
1208
  wmDenyModeCap: 'Cap and warn',
@@ -1183,12 +1227,24 @@ window.__ModuleLoader__.load({
1183
1227
  trimSectionTitle: 'Context trim',
1184
1228
  trimModeLabel: 'Trim mode',
1185
1229
  trimModeHelp:
1186
- 'When to fold history into summaries at idle: off = never, advisory = model-invoked only, auto = automatic folds.',
1230
+ 'When to fold history into summaries at idle: off = never, advisory = the model folds itself (the engine appends a one-off nudge line at the pressure line), auto = automatic folds.',
1231
+ trimCriticalReliefLabel: 'Critical relief fold',
1232
+ trimCriticalReliefHelp: 'When on (default), advisory mode performs one mechanical fold itself at the critical line (trimAdvisoryCriticalPercent, 90 s cooldown) instead of only nudging.',
1233
+ trimVerboseLogLabel: 'Debug mode (verbose log)',
1234
+ trimVerboseLogHelp: 'Off by default. When on, every engine step, gate evaluation and decision path is written to decisions.log (debug rows) for issue tracing; when off, only the key decision rows are kept. Exceptions always log full detail regardless of this switch.',
1235
+ trimDockLabel: 'fold {pressure}% (line {line}%)',
1236
+ trimDockTipDomain: 'Fold-engine domain: last PAID prompt (max of view/wire) over the effective window (cap included) — not the composer context meter projection; the two answer different questions and are not meant to converge.',
1237
+ trimDockTipMass: 'paid {mass} / window {window} tokens',
1238
+ trimDockTipMode: 'mode: {mode} (advisory = the model folds itself; auto = the engine folds)',
1239
+ trimDockTipReady: 'critical relief ready: one mechanical engine fold fires at the critical line',
1240
+ trimDockTipCooldown: 'critical relief cooling down, {seconds}s left',
1187
1241
  trimEnabledLabel: 'Enable auto-trim',
1188
1242
  trimEnabledHelp: 'Master switch for the context-trim layer.',
1189
1243
  trimLadderEnabledLabel: 'Ladder folding (T1/T2/T3)',
1190
1244
  trimLadderEnabledHelp:
1191
1245
  'Distill accumulated T1 summaries into T2, and T2 into T3, keeping long sessions flat.',
1246
+ trimProtectTaskIntentLabel: 'Protect task intent',
1247
+ trimProtectTaskIntentHelp: 'When on (default), the first user message (task intent) stays out of the automatic fold range. Turn off to let it fold like any other content.',
1192
1248
  surfaceFoldLabel: 'Ship folds to the session surface',
1193
1249
  surfaceFoldHelp:
1194
1250
  'Append host-style replace events so folds reach the wire even on frozen dispatches. Leave on.',
@@ -1227,6 +1283,12 @@ window.__ModuleLoader__.load({
1227
1283
  trimEmergencyLabel: 'Emergency threshold (%)',
1228
1284
  trimEmergencyHelp:
1229
1285
  'Immediate mechanical fold at this percent of the window.',
1286
+ trimAdvisoryLabel: 'Advisory nudge line (%)',
1287
+ trimAdvisoryHelp: 'Advisory mode only: the model is nudged to fold itself at this percent of the window.',
1288
+ trimAdvisoryCriticalLabel: 'Advisory critical line (%)',
1289
+ trimAdvisoryCriticalHelp: 'Advisory mode only: at this percent the nudge escalates to a fold-down-this-turn order.',
1290
+ trimAdvisoryRepeatLabel: 'Advisory re-pin interval (ms)',
1291
+ trimAdvisoryRepeatHelp: 'Advisory mode only: after a nudge is pinned to the session tail, it re-pins at the new tail every this many ms (critical band halves it, 45 s floor). Default 120000.',
1230
1292
  trimWindowLabel: 'Window cap (tokens)',
1231
1293
  trimWindowHelp: 'Pressure and emergency tiers use min(model window, cap); 0 = follow wmForceTokens.',
1232
1294
  trimModeOff: 'Off',
@@ -1439,6 +1501,7 @@ window.__ModuleLoader__.load({
1439
1501
  wmReadBudgetLabel: '單次讀取預算',
1440
1502
  wmReadBudgetHelp: '每次讀取的 token 預算;每輪上限為其兩倍。',
1441
1503
  wmNumberInvalid: '請輸入不小於 {min} 的整數。',
1504
+ wmNumberInvalidMax: '請輸入 {min} 到 {max} 之間的數。',
1442
1505
  wmOrderInvalid: '三檔水位需嚴格遞增:soft < hard < force。',
1443
1506
  wmDenyModeLabel: '硬檔行為',
1444
1507
  wmDenyModeCap: '限流放行',
@@ -1460,11 +1523,23 @@ window.__ModuleLoader__.load({
1460
1523
  trimSectionTitle: '上下文裁剪',
1461
1524
  trimModeLabel: '自動裁剪模式',
1462
1525
  trimModeHelp:
1463
- '閒置時何時將歷史摺疊為摘要:off = 從不摺疊,advisory = 僅模型主動呼叫,auto = 自動摺疊。',
1526
+ '閒置時何時將歷史摺疊為摘要:off = 從不摺疊,advisory = 模型自主摺疊(達壓力線時引擎於系統提示注入一次性提醒),auto = 自動摺疊。',
1527
+ trimCriticalReliefLabel: '臨界救援摺疊',
1528
+ trimCriticalReliefHelp: '開啟後(預設),advisory 模式壓力到達臨界線(trimAdvisoryCriticalPercent)時引擎自動執行一次機械摺疊(90 秒冷卻),不再只依賴提示。',
1529
+ trimVerboseLogLabel: '調試模式(詳細日誌)',
1530
+ trimVerboseLogHelp: '預設關閉。開啟後引擎的每個執行步驟、閘門判定與決策路徑都會寫入 decisions.log(debug 行),便於問題追溯;關閉時只記錄關鍵決策行。無論開關與否,異常始終記錄完整細節。',
1531
+ trimDockLabel: '摺疊 {pressure}%(線 {line}%)',
1532
+ trimDockTipDomain: '摺疊引擎口徑:最近一次實付 prompt(max(view, wire))÷ 有效視窗(含上限)——不是輸入框旁上下文面板的預測口徑,兩者本就不同、不應收斂。',
1533
+ trimDockTipMass: '實付 {mass} / 視窗 {window} tokens',
1534
+ trimDockTipMode: '模式:{mode}(advisory=模型自行摺疊;auto=引擎自動摺疊)',
1535
+ trimDockTipReady: '臨界紓緩就緒:達到 80% 線即由引擎機械摺疊一次',
1536
+ trimDockTipCooldown: '臨界紓緩冷卻中,剩 {seconds}s',
1464
1537
  trimEnabledLabel: '啟用自動裁剪',
1465
1538
  trimEnabledHelp: '上下文裁剪層的總開關。',
1466
1539
  trimLadderEnabledLabel: '階梯摺疊(T1/T2/T3)',
1467
1540
  trimLadderEnabledHelp: '把累積的 T1 摘要再蒸餾為 T2、T2 再凝聚為 T3,讓長會話檢視保持平穩。',
1541
+ trimProtectTaskIntentLabel: '保護任務意圖',
1542
+ trimProtectTaskIntentHelp: '第一條 user 訊息(任務意圖)永不摺疊。關閉後它可進入摺疊範圍。',
1468
1543
  surfaceFoldLabel: '把摺疊寫入會話表面',
1469
1544
  surfaceFoldHelp: '追加宿主風格的替換事件,讓摺疊在凍結派發下也能到達線上。建議保持開啟。',
1470
1545
  trimSideModelLabel: '摘要模型',
@@ -1496,6 +1571,10 @@ window.__ModuleLoader__.load({
1496
1571
  trimPressureHelp: '出站檢視達到上下文視窗的這一百分比時摺疊。',
1497
1572
  trimEmergencyLabel: '緊急閾值(%)',
1498
1573
  trimEmergencyHelp: '達到視窗的這一百分比時立即機械摺疊。',
1574
+ trimAdvisoryLabel: 'Advisory 提醒線(%)',
1575
+ trimAdvisoryHelp: '僅 advisory 模式:壓力達到視窗的這一百分比時,提醒模型自行摺疊。',
1576
+ trimAdvisoryCriticalLabel: 'Advisory 升級線(%)',
1577
+ trimAdvisoryCriticalHelp: '僅 advisory 模式:達到這一百分比時,提醒升級為本輪必須摺疊的指令。',
1499
1578
  trimModeOff: '關閉',
1500
1579
  trimWindowLabel: '視窗上限(token)',
1501
1580
  trimWindowHelp: '壓力與緊急檔按 min(模型視窗, 上限) 計算;0 = 跟隨強制水位(wmForceTokens)。',
@@ -1687,6 +1766,7 @@ window.__ModuleLoader__.load({
1687
1766
  wmReadBudgetLabel: '読み取り予算',
1688
1767
  wmReadBudgetHelp: '1 回の読み取りあたりの token 予算です。各ラウンドの上限はその 2 倍です。',
1689
1768
  wmNumberInvalid: '{min} 以上の整数を入力してください。',
1769
+ wmNumberInvalidMax: '{min} から {max} の間の数値を入力してください。',
1690
1770
  wmOrderInvalid: '3 段階の水位は厳密に昇順にしてください:soft < hard < force。',
1691
1771
  wmDenyModeLabel: 'ハード段階の動作',
1692
1772
  wmDenyModeCap: '制限して警告',
@@ -1708,7 +1788,17 @@ window.__ModuleLoader__.load({
1708
1788
  trimSectionTitle: 'コンテキストトリム',
1709
1789
  trimModeLabel: 'トリムモード',
1710
1790
  trimModeHelp:
1711
- 'アイドル時に履歴を要約へ折りたたむタイミング:off = 折りたたまない、advisory = モデル呼び出しのみ、auto = 自動で折りたたむ。',
1791
+ 'アイドル時に履歴を要約へ折りたたむタイミング:off = 折りたたまない、advisory = モデルが自発的に折りたたむ(圧力しきい値でエンジンがシステムプロンプトに一度だけ注意喚起を追記)、auto = 自動で折りたたむ。',
1792
+ trimCriticalReliefLabel: 'クリティカル救済フォールド',
1793
+ trimCriticalReliefHelp: 'オン(既定)では、advisory モードで圧力が臨界線(trimAdvisoryCriticalPercent)に達した時点でエンジン自身が機械的フォールドを 1 回実行します(90 秒クールダウン)。',
1794
+ trimVerboseLogLabel: 'デバッグモード(詳細ログ)',
1795
+ trimVerboseLogHelp: '既定ではオフ。オンにすると、エンジンの各ステップ・ゲート判定・決定経路が decisions.log に(debug 行として)記録され、問題の追跡に役立ちます。オフ時は主要な決定行のみ記録。例外はこの設定に関係なく常に完全な詳細を記録します。',
1796
+ trimDockLabel: 'fold {pressure}%(線 {line}%)',
1797
+ trimDockTipDomain: 'fold エンジンの基準:最後に支払った prompt(max(view, wire))÷ 実効ウィンドウ(上限込み)——入力欄のコンテキストメーターの推定基準とは別物で、収束しないのが正常です。',
1798
+ trimDockTipMass: '支払い済み {mass} / ウィンドウ {window} トークン',
1799
+ trimDockTipMode: 'モード:{mode}(advisory=モデル自身が fold、auto=エンジンが fold)',
1800
+ trimDockTipReady: 'critical relief 待機中:critical 線に達するとエンジンが 1 回機械的に fold します',
1801
+ trimDockTipCooldown: 'critical relief クールダウン中、残り {seconds}秒',
1712
1802
  trimEnabledLabel: '自動トリムを有効化',
1713
1803
  trimEnabledHelp: 'コンテキストトリム層のマスタースイッチ。',
1714
1804
  trimGrowthLabel: '増加しきい値(token)',
@@ -1723,6 +1813,10 @@ window.__ModuleLoader__.load({
1723
1813
  trimEmergencyLabel: '緊急しきい値(%)',
1724
1814
  trimEmergencyHelp:
1725
1815
  'ウィンドウのこの割合に達したら即座に機械的に折りたたみます。',
1816
+ trimAdvisoryLabel: 'Advisory 提案しきい値(%)',
1817
+ trimAdvisoryHelp: 'advisory モード専用:圧力がウィンドウのこの割合に達すると、モデルに自己折り畳みを促します。',
1818
+ trimAdvisoryCriticalLabel: 'Advisory 深刻しきい値(%)',
1819
+ trimAdvisoryCriticalHelp: 'advisory モード専用:この割合に達すると、提案は「このターンで折り畳む」指示にエスカレートします。',
1726
1820
  trimWindowLabel: 'ウィンドウ上限(トークン)',
1727
1821
  trimWindowHelp: '圧力・緊急ティアは min(モデルウィンドウ, 上限) で計算。0 = wmForceTokens に追従。',
1728
1822
  trimModeOff: 'オフ',
@@ -1925,6 +2019,7 @@ window.__ModuleLoader__.load({
1925
2019
  wmReadBudgetLabel: '읽기 예산',
1926
2020
  wmReadBudgetHelp: '한 번 읽기당 토큰 예산입니다. 매 라운드 상한은 그 두 배입니다.',
1927
2021
  wmNumberInvalid: '{min} 이상의 정수를 입력하세요.',
2022
+ wmNumberInvalidMax: '{min}부터 {max}까지의 숫자를 입력하세요.',
1928
2023
  wmOrderInvalid: '세 수위는 엄격히 증가해야 합니다: soft < hard < force.',
1929
2024
  wmDenyModeLabel: '하드 단계 동작',
1930
2025
  wmDenyModeCap: '제한하고 경고',
@@ -1953,7 +2048,17 @@ window.__ModuleLoader__.load({
1953
2048
  trimSectionTitle: '컨텍스트 트림',
1954
2049
  trimModeLabel: '트림 모드',
1955
2050
  trimModeHelp:
1956
- '유휴 시 언제 기록을 요약으로 접을지: off = 접지 않음, advisory = 모델 호출 시에만, auto = 자동 접기.',
2051
+ '유휴 시 언제 기록을 요약으로 접을지: off = 접지 않음, advisory = 모델이 스스로 접음(압력 임계값에서 엔진이 시스템 프롬프트에 일회성 알림 추가), auto = 자동 접기.',
2052
+ trimCriticalReliefLabel: '임계 구제 폴드',
2053
+ trimCriticalReliefHelp: '켜면(기본) advisory 모드에서 압력이 임계선(trimAdvisoryCriticalPercent)에 닿을 때 엔진이 직접 기계 폴드를 한 번 실행합니다(90초 쿨다운).',
2054
+ trimVerboseLogLabel: '디버그 모드(상세 로그)',
2055
+ trimVerboseLogHelp: '기본값은 끔입니다. 켜면 엔진의 모든 실행 단계, 게이트 판정, 결정 경로가 decisions.log에(debug 행) 기록되어 문제 추적에 도움이 됩니다. 끄면 핵심 결정 행만 기록됩니다. 예외는 이 설정과 무관하게 항상 전체 세부 정보를 기록합니다.',
2056
+ trimDockLabel: 'fold {pressure}%(선 {line}%)',
2057
+ trimDockTipDomain: 'fold 엔진 기준: 마지막 실제 결제 prompt(max(view, wire)) ÷ 실효 윈도우(상한 포함) — 입력창 컨텍스트 미터의 추정 기준과 다르며 수렴하지 않는 것이 정상입니다.',
2058
+ trimDockTipMass: '결제 {mass} / 윈도우 {window} 토큰',
2059
+ trimDockTipMode: '모드: {mode} (advisory=모델이 직접 fold, auto=엔진이 fold)',
2060
+ trimDockTipReady: 'critical relief 대기 중: critical 선 도달 시 엔진이 한 번 기계적으로 fold합니다',
2061
+ trimDockTipCooldown: 'critical relief 쿨다운 중, {seconds}초 남음',
1957
2062
  trimEnabledLabel: '자동 트림 사용',
1958
2063
  trimEnabledHelp: '컨텍스트 트림 계층의 마스터 스위치.',
1959
2064
  trimGrowthLabel: '증가 임계값(token)',
@@ -1967,6 +2072,10 @@ window.__ModuleLoader__.load({
1967
2072
  trimEmergencyLabel: '긴급 임계값(%)',
1968
2073
  trimEmergencyHelp:
1969
2074
  '창의 이 백분율에 도달하면 즉시 기계적으로 접습니다.',
2075
+ trimAdvisoryLabel: 'Advisory 알림 임계값(%)',
2076
+ trimAdvisoryHelp: 'advisory 모드 전용: 압력이 창의 이 백분율에 도달하면 모델에 자체 폴드를 권고합니다.',
2077
+ trimAdvisoryCriticalLabel: 'Advisory 치명적 임계값(%)',
2078
+ trimAdvisoryCriticalHelp: 'advisory 모드 전용: 이 백분율에 도달하면 권고가 이번 턴 폴드 명령으로 격상됩니다.',
1970
2079
  trimWindowLabel: '윈도우 상한(토큰)',
1971
2080
  trimWindowHelp: '압력·긴급 티어는 min(모델 윈도우, 상한)으로 계산. 0 = wmForceTokens를 따름.',
1972
2081
  trimModeOff: '끄기',
@@ -2162,6 +2271,7 @@ window.__ModuleLoader__.load({
2162
2271
  wmReadBudgetLabel: 'Lese-Budget',
2163
2272
  wmReadBudgetHelp: 'Token-Budget pro Lesevorgang; jede Runde ist auf das Doppelte gedeckelt.',
2164
2273
  wmNumberInvalid: 'Geben Sie eine ganze Zahl von mindestens {min} ein.',
2274
+ wmNumberInvalidMax: 'Geben Sie eine Zahl zwischen {min} und {max} ein.',
2165
2275
  wmOrderInvalid: 'Die drei Stufen müssen strikt aufsteigen: soft < hard < force.',
2166
2276
  wmDenyModeLabel: 'Verhalten der Hard-Stufe',
2167
2277
  wmDenyModeCap: 'Deckeln und warnen',
@@ -2190,7 +2300,17 @@ window.__ModuleLoader__.load({
2190
2300
  trimSectionTitle: 'Kontext-Trim',
2191
2301
  trimModeLabel: 'Trim-Modus',
2192
2302
  trimModeHelp:
2193
- 'Wann der Verlauf im Leerlauf zu Zusammenfassungen gefaltet wird: off = nie, advisory = nur per Modellaufruf, auto = automatisches Falten.',
2303
+ 'Wann der Verlauf im Leerlauf zu Zusammenfassungen gefaltet wird: off = nie, advisory = das Modell faltet selbst (der Motor hängt eine einmalige Erinnerung an den Systemprompt an), auto = automatisches Falten.',
2304
+ trimCriticalReliefLabel: 'Kritische Notfaltung',
2305
+ trimCriticalReliefHelp: 'Ein (Standard): Erreicht der Druck im Advisory-Modus die kritische Linie (trimAdvisoryCriticalPercent), faltet die Engine selbst einmal mechanisch (90 s Abklingzeit).',
2306
+ trimVerboseLogLabel: 'Debugmodus (ausführliches Protokoll)',
2307
+ trimVerboseLogHelp: 'Standardmäßig aus. Bei Aktivierung werden jeder Engine-Schritt, jede Gate-Prüfung und jeder Entscheidungspfad in die decisions.log geschrieben (Debug-Zeilen) zur Fehlerverfolgung; bei Deaktivierung bleiben nur die wichtigsten Entscheidungszeilen. Ausnahmen werden unabhängig von dieser Einstellung immer mit vollständigen Details protokolliert.',
2308
+ trimDockLabel: 'Falten {pressure}% (Linie {line}%)',
2309
+ trimDockTipDomain: 'Fold-Engine-Domäne: zuletzt bezahlter Prompt (max aus view/wire) über das effektive Fenster (inkl. Limit) — nicht die Projektion des Kontextmessers; beide beantworten verschiedene Fragen und sollen nicht konvergieren.',
2310
+ trimDockTipMass: 'bezahlt {mass} / Fenster {window} Token',
2311
+ trimDockTipMode: 'Modus: {mode} (advisory = das Modell faltet selbst; auto = die Engine faltet)',
2312
+ trimDockTipReady: 'Critical Relief bereit: an der Critical-Linie faltet die Engine einmal mechanisch',
2313
+ trimDockTipCooldown: 'Critical-Relief-Cooldown, noch {seconds}s',
2194
2314
  trimEnabledLabel: 'Auto-Trim aktivieren',
2195
2315
  trimEnabledHelp: 'Hauptschalter für die Kontext-Trim-Schicht.',
2196
2316
  trimGrowthLabel: 'Wachstumsschwelle (Token)',
@@ -2205,6 +2325,10 @@ window.__ModuleLoader__.load({
2205
2325
  trimEmergencyLabel: 'Notfallschwelle (%)',
2206
2326
  trimEmergencyHelp:
2207
2327
  'Sofortiges mechanisches Falten bei diesem Prozentanteil des Fensters.',
2328
+ trimAdvisoryLabel: 'Advisory-Hinweisschwelle (%)',
2329
+ trimAdvisoryHelp: 'Nur im Advisory-Modus: Erreicht der Druck diesen Prozentsatz des Fensters, wird das Modell zum eigenen Falten angehalten.',
2330
+ trimAdvisoryCriticalLabel: 'Advisory-Kritischschwelle (%)',
2331
+ trimAdvisoryCriticalHelp: 'Nur im Advisory-Modus: Ab diesem Prozentsatz wird der Hinweis zu einem Falt-Befehl für diese Runde eskaliert.',
2208
2332
  trimWindowLabel: 'Fensterlimit (Token)',
2209
2333
  trimWindowHelp: 'Druck- und Notfallstufen rechnen mit min(Modellfenster, Limit); 0 = folgt wmForceTokens.',
2210
2334
  trimModeOff: 'Aus',
@@ -2402,6 +2526,7 @@ window.__ModuleLoader__.load({
2402
2526
  wmReadBudgetLabel: 'Presupuesto de lectura',
2403
2527
  wmReadBudgetHelp: 'Presupuesto de tokens por lectura; cada ronda se limita al doble.',
2404
2528
  wmNumberInvalid: 'Introduce un número entero de {min} o más.',
2529
+ wmNumberInvalidMax: 'Introduzca un número entre {min} y {max}.',
2405
2530
  wmOrderInvalid: 'Los tres niveles deben ascender estrictamente: soft < hard < force.',
2406
2531
  wmDenyModeLabel: 'Comportamiento del nivel duro',
2407
2532
  wmDenyModeCap: 'Limitar y avisar',
@@ -2430,7 +2555,17 @@ window.__ModuleLoader__.load({
2430
2555
  trimSectionTitle: 'Recorte de contexto',
2431
2556
  trimModeLabel: 'Modo de recorte',
2432
2557
  trimModeHelp:
2433
- 'Cuándo plegar el historial en resúmenes en reposo: off = nunca, advisory = solo por invocación del modelo, auto = plegado automático.',
2558
+ 'Cuándo plegar el historial en resúmenes en reposo: off = nunca, advisory = el modelo pliega por sí mismo (el motor añade un aviso puntual al system prompt), auto = plegado automático.',
2559
+ trimCriticalReliefLabel: 'Alivio crítico mecánico',
2560
+ trimCriticalReliefHelp: 'Activado (predeterminado): en modo advisory, al llegar a la línea crítica (trimAdvisoryCriticalPercent), el motor pliega mecánicamente una vez por sí mismo (enfriamiento de 90 s).',
2561
+ trimVerboseLogLabel: 'Modo de depuración (registro detallado)',
2562
+ trimVerboseLogHelp: 'Desactivado por defecto. Al activarlo, cada paso del motor, evaluación de compuerta y ruta de decisión se escribe en decisions.log (líneas debug) para rastrear problemas; al desactivarlo solo se guardan las líneas de decisión clave. Las excepciones siempre se registran con detalle completo, independientemente de esta opción.',
2563
+ trimDockLabel: 'plegar {pressure}% (línea {line}%)',
2564
+ trimDockTipDomain: 'Dominio del motor de plegado: último prompt pagado (máx de view/wire) sobre la ventana efectiva (límite incluido) — no la proyección del medidor de contexto; ambos responden preguntas distintas y no están hechos para converger.',
2565
+ trimDockTipMass: 'pagado {mass} / ventana {window} tokens',
2566
+ trimDockTipMode: 'modo: {mode} (advisory = el modelo pliega; auto = pliega el motor)',
2567
+ trimDockTipReady: 'alivio crítico listo: en la línea crítica el motor pliega una vez mecánicamente',
2568
+ trimDockTipCooldown: 'alivio crítico enfriando, faltan {seconds}s',
2434
2569
  trimEnabledLabel: 'Activar recorte automático',
2435
2570
  trimEnabledHelp:
2436
2571
  'Interruptor maestro de la capa de recorte de contexto.',
@@ -2446,6 +2581,10 @@ window.__ModuleLoader__.load({
2446
2581
  trimEmergencyLabel: 'Umbral de emergencia (%)',
2447
2582
  trimEmergencyHelp:
2448
2583
  'Plegado mecánico inmediato al alcanzar este porcentaje de la ventana.',
2584
+ trimAdvisoryLabel: 'Línea de aviso advisory (%)',
2585
+ trimAdvisoryHelp: 'Solo en modo advisory: al alcanzar este porcentaje de la ventana se incita al modelo a plegarse por sí mismo.',
2586
+ trimAdvisoryCriticalLabel: 'Línea crítica advisory (%)',
2587
+ trimAdvisoryCriticalHelp: 'Solo en modo advisory: a este porcentaje el aviso escala a una orden de plegado en este turno.',
2449
2588
  trimWindowLabel: 'Límite de ventana (tokens)',
2450
2589
  trimWindowHelp: 'Los niveles de presión y emergencia usan min(ventana del modelo, límite); 0 = sigue a wmForceTokens.',
2451
2590
  trimModeOff: 'Desactivado',
@@ -2643,6 +2782,7 @@ window.__ModuleLoader__.load({
2643
2782
  wmReadBudgetLabel: 'Budget de lecture',
2644
2783
  wmReadBudgetHelp: 'Budget de tokens par lecture ; chaque tour plafonne au double.',
2645
2784
  wmNumberInvalid: 'Saisissez un nombre entier d’au moins {min}.',
2785
+ wmNumberInvalidMax: 'Saisissez un nombre compris entre {min} et {max}.',
2646
2786
  wmOrderInvalid: 'Les trois paliers doivent strictement monter : soft < hard < force.',
2647
2787
  wmDenyModeLabel: 'Comportement au palier hard',
2648
2788
  wmDenyModeCap: 'Plafonner et avertir',
@@ -2671,7 +2811,17 @@ window.__ModuleLoader__.load({
2671
2811
  trimSectionTitle: 'Rognage du contexte',
2672
2812
  trimModeLabel: 'Mode de rognage',
2673
2813
  trimModeHelp:
2674
- 'Quand replier l’historique en résumés au repos : off = jamais, advisory = sur invocation du modèle uniquement, auto = repli automatique.',
2814
+ 'Quand replier l’historique en résumés au repos : off = jamais, advisory = le modèle replie lui-même (le moteur ajoute un rappel ponctuel au system prompt), auto = repli automatique.',
2815
+ trimCriticalReliefLabel: 'Secours mécanique critique',
2816
+ trimCriticalReliefHelp: 'Activé (par défaut) : en mode advisory, quand la pression atteint la ligne critique (trimAdvisoryCriticalPercent), le moteur plie lui-même une fois mécaniquement (délai de 90 s).',
2817
+ trimVerboseLogLabel: 'Mode débogage (journal détaillé)',
2818
+ trimVerboseLogHelp: 'Désactivé par défaut. Une fois activé, chaque étape du moteur, chaque évaluation de garde et chaque chemin de décision est consigné dans decisions.log (lignes debug) pour faciliter le traçage ; sinon, seules les lignes de décision clés sont conservées. Les exceptions sont toujours journalisées en détail, quoi qu’il arrive.',
2819
+ trimDockLabel: 'replier {pressure}% (ligne {line}%)',
2820
+ trimDockTipDomain: 'Domaine du moteur de repli : dernier prompt payé (max de view/wire) sur la fenêtre effective (plafond inclus) — pas la projection du compteur de contexte ; les deux répondent à des questions différentes et ne sont pas faits pour converger.',
2821
+ trimDockTipMass: 'payé {mass} / fenêtre {window} jetons',
2822
+ trimDockTipMode: 'mode : {mode} (advisory = le modèle replie lui-même ; auto = le moteur replie)',
2823
+ trimDockTipReady: 'soulagement critique prêt : à la ligne critique, le moteur replie une fois mécaniquement',
2824
+ trimDockTipCooldown: 'soulagement critique en refroidissement, {seconds}s restantes',
2675
2825
  trimEnabledLabel: 'Activer le rognage automatique',
2676
2826
  trimEnabledHelp:
2677
2827
  'Interrupteur principal de la couche de rognage de contexte.',
@@ -2687,6 +2837,10 @@ window.__ModuleLoader__.load({
2687
2837
  trimEmergencyLabel: 'Seuil d’urgence (%)',
2688
2838
  trimEmergencyHelp:
2689
2839
  'Repli mécanique immédiat à ce pourcentage de la fenêtre.',
2840
+ trimAdvisoryLabel: 'Seuil de rappel advisory (%)',
2841
+ trimAdvisoryHelp: 'Mode advisory uniquement : à ce pourcentage de la fenêtre, le modèle est invité à se plier lui-même.',
2842
+ trimAdvisoryCriticalLabel: 'Seuil critique advisory (%)',
2843
+ trimAdvisoryCriticalHelp: 'Mode advisory uniquement : à ce pourcentage, le rappel devient un ordre de pliage pour ce tour.',
2690
2844
  trimWindowLabel: 'Plafond de fenêtre (jetons)',
2691
2845
  trimWindowHelp: 'Les paliers pression/urgence utilisent min(fenêtre du modèle, plafond) ; 0 = suit wmForceTokens.',
2692
2846
  trimModeOff: 'Off',
@@ -2884,6 +3038,7 @@ window.__ModuleLoader__.load({
2884
3038
  wmReadBudgetLabel: 'Budget di lettura',
2885
3039
  wmReadBudgetHelp: 'Budget di token per lettura; ogni turno arriva al massimo al doppio.',
2886
3040
  wmNumberInvalid: 'Inserisci un numero intero di almeno {min}.',
3041
+ wmNumberInvalidMax: 'Inserisci un numero compreso tra {min} e {max}.',
2887
3042
  wmOrderInvalid: 'Le tre soglie devono salire rigorosamente: soft < hard < force.',
2888
3043
  wmDenyModeLabel: 'Comportamento alla soglia hard',
2889
3044
  wmDenyModeCap: 'Tetto e avviso',
@@ -2912,7 +3067,17 @@ window.__ModuleLoader__.load({
2912
3067
  trimSectionTitle: 'Riduzione del contesto',
2913
3068
  trimModeLabel: 'Modalità di riduzione',
2914
3069
  trimModeHelp:
2915
- 'Quando comprimere la cronologia in riepiloghi a riposo: off = mai, advisory = solo su invocazione del modello, auto = riduzione automatica.',
3070
+ 'Quando comprimere la cronologia in riepiloghi a riposo: off = mai, advisory = il modello comprime da solo (il motore aggiunge un promemoria una tantum al system prompt), auto = riduzione automatica.',
3071
+ trimCriticalReliefLabel: 'Soccorso critico meccanico',
3072
+ trimCriticalReliefHelp: 'Attivo (predefinito): in modalità advisory, al raggiungimento della linea critica (trimAdvisoryCriticalPercent), il motore esegue una piegatura meccanica da sé (cooldown di 90 s).',
3073
+ trimVerboseLogLabel: 'Modalità debug (log dettagliato)',
3074
+ trimVerboseLogHelp: 'Disattivato per impostazione predefinita. Se attivo, ogni passo del motore, ogni valutazione di gate e ogni percorso decisionale viene scritto in decisions.log (righe debug) per la tracciabilità dei problemi; se disattivo restano solo le righe decisionali chiave. Le eccezioni vengono sempre registrate per intero, indipendentemente da questa opzione.',
3075
+ trimDockLabel: 'ripiega {pressure}% (linea {line}%)',
3076
+ trimDockTipDomain: 'Dominio del motore di ripiegamento: ultimo prompt pagato (max di view/wire) sulla finestra effettiva (limite incluso) — non la proiezione del misuratore di contesto; i due rispondono a domande diverse e non sono fatti per convergere.',
3077
+ trimDockTipMass: 'pagato {mass} / finestra {window} token',
3078
+ trimDockTipMode: 'modalità: {mode} (advisory = il modello ripiega da solo; auto = ripiega il motore)',
3079
+ trimDockTipReady: 'sollievo critico pronto: alla linea critica il motore ripiega una volta meccanicamente',
3080
+ trimDockTipCooldown: 'sollievo critico in raffreddamento, {seconds}s rimanenti',
2916
3081
  trimEnabledLabel: 'Attiva riduzione automatica',
2917
3082
  trimEnabledHelp:
2918
3083
  'Interruttore principale del livello di riduzione del contesto.',
@@ -2928,6 +3093,10 @@ window.__ModuleLoader__.load({
2928
3093
  trimEmergencyLabel: 'Soglia di emergenza (%)',
2929
3094
  trimEmergencyHelp:
2930
3095
  'Riduzione meccanica immediata a questa percentuale della finestra.',
3096
+ trimAdvisoryLabel: 'Soglia di avviso advisory (%)',
3097
+ trimAdvisoryHelp: 'Solo in modalità advisory: al raggiungimento di questa percentuale della finestra il modello viene invitato a ripiegare da solo.',
3098
+ trimAdvisoryCriticalLabel: 'Soglia critica advisory (%)',
3099
+ trimAdvisoryCriticalHelp: 'Solo in modalità advisory: a questa percentuale l\'avviso scala a un ordine di ripiegamento in questo turno.',
2931
3100
  trimWindowLabel: 'Limite finestra (token)',
2932
3101
  trimWindowHelp: 'Le soglie di pressione/emergenza usano min(finestra del modello, limite); 0 = segue wmForceTokens.',
2933
3102
  trimModeOff: 'Off',
@@ -3125,6 +3294,7 @@ window.__ModuleLoader__.load({
3125
3294
  wmReadBudgetLabel: 'Orçamento de leitura',
3126
3295
  wmReadBudgetHelp: 'Orçamento de tokens por leitura; cada turno se limita ao dobro disso.',
3127
3296
  wmNumberInvalid: 'Informe um número inteiro de {min} ou mais.',
3297
+ wmNumberInvalidMax: 'Informe um número entre {min} e {max}.',
3128
3298
  wmOrderInvalid: 'Os três limiares devem subir estritamente: soft < hard < force.',
3129
3299
  wmDenyModeLabel: 'Comportamento no limiar hard',
3130
3300
  wmDenyModeCap: 'Limitar e avisar',
@@ -3153,7 +3323,17 @@ window.__ModuleLoader__.load({
3153
3323
  trimSectionTitle: 'Corte de contexto',
3154
3324
  trimModeLabel: 'Modo de corte',
3155
3325
  trimModeHelp:
3156
- 'Quando dobrar o histórico em resumos na ociosidade: off = nunca, advisory = apenas por invocação do modelo, auto = dobra automática.',
3326
+ 'Quando dobrar o histórico em resumos na ociosidade: off = nunca, advisory = o modelo dobra por si (o motor acrescenta um aviso pontual ao system prompt), auto = dobra automática.',
3327
+ trimCriticalReliefLabel: 'Alívio crítico mecânico',
3328
+ trimCriticalReliefHelp: 'Ligado (padrão): no modo advisory, ao atingir a linha crítica (trimAdvisoryCriticalPercent), o motor dobra mecanicamente uma vez por si (arrefecimento de 90 s).',
3329
+ trimVerboseLogLabel: 'Modo de depuração (registro detalhado)',
3330
+ trimVerboseLogHelp: 'Desligado por padrão. Ativado, cada passo do motor, avaliação de portão e caminho de decisão é gravado no decisions.log (linhas debug) para rastrear problemas; desligado, apenas as linhas-chave de decisão são mantidas. Exceções sempre registram detalhes completos, independentemente desta opção.',
3331
+ trimDockLabel: 'dobrar {pressure}% (linha {line}%)',
3332
+ trimDockTipDomain: 'Domínio do motor de dobra: último prompt pago (máx de view/wire) sobre a janela efetiva (limite incluído) — não a projeção do medidor de contexto; ambos respondem perguntas diferentes e não estão feitos para convergir.',
3333
+ trimDockTipMass: 'pago {mass} / janela {window} tokens',
3334
+ trimDockTipMode: 'modo: {mode} (advisory = o modelo dobra; auto = o motor dobra)',
3335
+ trimDockTipReady: 'alívio crítico pronto: na linha crítica o motor dobra uma vez mecanicamente',
3336
+ trimDockTipCooldown: 'alívio crítico em arrefecimento, faltam {seconds}s',
3157
3337
  trimEnabledLabel: 'Ativar corte automático',
3158
3338
  trimEnabledHelp:
3159
3339
  'Interruptor principal da camada de corte de contexto.',
@@ -3169,6 +3349,10 @@ window.__ModuleLoader__.load({
3169
3349
  trimEmergencyLabel: 'Limiar de emergência (%)',
3170
3350
  trimEmergencyHelp:
3171
3351
  'Dobra mecânica imediata nessa porcentagem da janela.',
3352
+ trimAdvisoryLabel: 'Limiar de aviso advisory (%)',
3353
+ trimAdvisoryHelp: 'Apenas no modo advisory: ao atingir esta percentagem da janela, o modelo é incentivado a dobrar-se por si.',
3354
+ trimAdvisoryCriticalLabel: 'Limiar crítico advisory (%)',
3355
+ trimAdvisoryCriticalHelp: 'Apenas no modo advisory: nesta percentagem o aviso escala para uma ordem de dobragem neste turno.',
3172
3356
  trimWindowLabel: 'Limite de janela (tokens)',
3173
3357
  trimWindowHelp: 'Os níveis de pressão e emergência usam min(janela do modelo, limite); 0 = segue wmForceTokens.',
3174
3358
  trimModeOff: 'Off',
@@ -3366,6 +3550,7 @@ window.__ModuleLoader__.load({
3366
3550
  wmReadBudgetLabel: 'Бюджет чтения',
3367
3551
  wmReadBudgetHelp: 'Бюджет токенов на одно чтение; каждый ход ограничен удвоенным значением.',
3368
3552
  wmNumberInvalid: 'Введите целое число не меньше {min}.',
3553
+ wmNumberInvalidMax: 'Введите число от {min} до {max}.',
3369
3554
  wmOrderInvalid: 'Три линии должны строго возрастать: soft < hard < force.',
3370
3555
  wmDenyModeLabel: 'Поведение на линии hard',
3371
3556
  wmDenyModeCap: 'Урезать и предупредить',
@@ -3394,7 +3579,17 @@ window.__ModuleLoader__.load({
3394
3579
  trimSectionTitle: 'Обрезка контекста',
3395
3580
  trimModeLabel: 'Режим обрезки',
3396
3581
  trimModeHelp:
3397
- 'Когда сворачивать историю в сводки в простое: off = никогда, advisory = только по вызову модели, auto = автоматически.',
3582
+ 'Когда сворачивать историю в сводки в простое: off = никогда, advisory = модель сворачивает сама (движок добавляет разовое напоминание в системный промпт), auto = автоматически.',
3583
+ trimCriticalReliefLabel: 'Критическое авто-сворачивание',
3584
+ trimCriticalReliefHelp: 'Включено (по умолчанию): в режиме advisory при достижении критической линии (trimAdvisoryCriticalPercent) движок сам один раз сворачивает механически (куладдаун 90 с).',
3585
+ trimVerboseLogLabel: 'Режим отладки (подробный журнал)',
3586
+ trimVerboseLogHelp: 'По умолчанию выключено. При включении каждый шаг движка, проверка шлюза и путь решения записываются в decisions.log (строки debug) для отслеживания проблем; при выключении сохраняются только ключевые строки решений. Исключения всегда записываются с полными деталями независимо от этого переключателя.',
3587
+ trimDockLabel: 'свернуть {pressure}% (линия {line}%)',
3588
+ trimDockTipDomain: 'Область движка сворачивания: последний оплаченный prompt (max от view/wire) делённый на эффективное окно (с лимитом) — не прогноз счётчика контекста; эти числа отвечают на разные вопросы и не должны сходиться.',
3589
+ trimDockTipMass: 'оплачено {mass} / окно {window} токенов',
3590
+ trimDockTipMode: 'режим: {mode} (advisory = модель сворачивает сама; auto = сворачивает движок)',
3591
+ trimDockTipReady: 'критическое relief готово: у критической линии движок один раз свернёт механически',
3592
+ trimDockTipCooldown: 'критическое relief на кулдауне, осталось {seconds}с',
3398
3593
  trimEnabledLabel: 'Включить автообрезку',
3399
3594
  trimEnabledHelp: 'Главный выключатель слоя обрезки контекста.',
3400
3595
  trimGrowthLabel: 'Порог роста (токенов)',
@@ -3409,6 +3604,10 @@ window.__ModuleLoader__.load({
3409
3604
  trimEmergencyLabel: 'Аварийный порог (%)',
3410
3605
  trimEmergencyHelp:
3411
3606
  'Немедленное механическое сворачивание при этом проценте окна.',
3607
+ trimAdvisoryLabel: 'Порог advisory-напоминания (%)',
3608
+ trimAdvisoryHelp: 'Только в режиме advisory: при достижении этой доли окна модели предлагается свернуть контекст самостоятельно.',
3609
+ trimAdvisoryCriticalLabel: 'Критический порог advisory (%)',
3610
+ trimAdvisoryCriticalHelp: 'Только в режиме advisory: на этой доле напоминание становится приказом свернуть в текущем ходе.',
3412
3611
  trimWindowLabel: 'Лимит окна (токены)',
3413
3612
  trimWindowHelp: 'Уровни давления и аварийный считают от min(окно модели, лимит); 0 = следует за wmForceTokens.',
3414
3613
  trimModeOff: 'Off',
@@ -3991,6 +4190,147 @@ window.__ModuleLoader__.load({
3991
4190
  );
3992
4191
  }
3993
4192
 
4193
+ /** Composer dock chip for trim pressure (conversation.input.dock,
4194
+ * order 88 — one slot below the intent chip's 89): shows the fold
4195
+ * engine's own pressure figure — the LAST PAID prompt (max of view/
4196
+ * wire) over the effective window (cap included) — next to the
4197
+ * composer. This is the number the trim nudges and tiers act on, and
4198
+ * it is deliberately NOT the composer context meter's projection:
4199
+ * different numerator (paid vs projected) and denominator (effective
4200
+ * window vs model window), so the two figures answer different
4201
+ * questions and legitimately diverge (the tooltip spells this out).
4202
+ * Polls the Host trim-pressure route every 15s; disabled trim, an
4203
+ * unknown window, or any fetch failure renders null (fail-silent).
4204
+ * Pure display — no interactive controls. */
4205
+ function TrimDockEntry({ t, sessionId, useProjection }) {
4206
+ const [snap, setSnap] = React.useState(null);
4207
+ // Realtime trigger ([2026-11-15] user report: after a fold ships the chip
4208
+ // kept the pre-fold percentage for up to one 15s poll — the Host snapshot
4209
+ // recomputes per request, so the lag was entirely client-side). The
4210
+ // contextPressure projection face folds EVERY surface event, including
4211
+ // the trim engine's fold-commit replacements, so its value changes the
4212
+ // moment a fold lands; it is also stable-primitive-safe to observe with
4213
+ // useSyncExternalStore (the shipped ContextMeter does exactly this).
4214
+ // Subscribing to that face makes the poll loop fetch immediately on
4215
+ // each pressure change (fold commit AND normal turn growth) and keeps
4216
+ // the 15s timer only as the drift fallback (cooldown countdown, model
4217
+ // window changes — inputs the projection does not see).
4218
+ const projectionHook =
4219
+ typeof useProjection === 'function' ? useProjection : () => undefined;
4220
+ const pressureFace = projectionHook('contextPressure');
4221
+ const pressureSignal =
4222
+ pressureFace == null
4223
+ ? null
4224
+ : `${pressureFace.projectedTokens ?? pressureFace.pressureTokens ?? ''}|${pressureFace.contextWindow ?? ''}`;
4225
+ const [pulse, setPulse] = React.useState(0);
4226
+ React.useEffect(() => {
4227
+ setPulse((n) => n + 1);
4228
+ }, [pressureSignal]);
4229
+ React.useEffect(() => {
4230
+ let stopped = false;
4231
+ let timer = null;
4232
+ const query =
4233
+ typeof sessionId === 'string' && sessionId !== ''
4234
+ ? `?session=${encodeURIComponent(sessionId)}`
4235
+ : '';
4236
+ const tick = async () => {
4237
+ let next = null;
4238
+ try {
4239
+ const reply = await api.get(`trim-pressure${query}`);
4240
+ const value = reply?.ok ? reply.value : null;
4241
+ if (
4242
+ value &&
4243
+ typeof value === 'object' &&
4244
+ value.available === true &&
4245
+ typeof value.pressure === 'number' &&
4246
+ typeof value.window === 'number' &&
4247
+ value.window > 0
4248
+ )
4249
+ next = {
4250
+ mode: value.mode === 'advisory' || value.mode === 'auto' ? value.mode : null,
4251
+ pressure: Math.round(value.pressure),
4252
+ mass: typeof value.mass === 'number' ? value.mass : null,
4253
+ window: value.window,
4254
+ advisoryLine:
4255
+ typeof value.advisoryLine === 'number' ? value.advisoryLine : null,
4256
+ criticalLine:
4257
+ typeof value.criticalLine === 'number' ? value.criticalLine : null,
4258
+ reliefCooldown:
4259
+ typeof value.reliefCooldownRemaining === 'number'
4260
+ ? Math.max(0, Math.round(value.reliefCooldownRemaining / 1000))
4261
+ : null,
4262
+ reliefReady: value.reliefReady === true,
4263
+ };
4264
+ } catch {
4265
+ next = null;
4266
+ }
4267
+ if (stopped) return;
4268
+ setSnap(next);
4269
+ timer = setTimeout(tick, 15_000);
4270
+ };
4271
+ void tick();
4272
+ return () => {
4273
+ stopped = true;
4274
+ if (timer !== null) clearTimeout(timer);
4275
+ };
4276
+ }, [sessionId, pulse]);
4277
+ if (snap === null) return null;
4278
+ // Same dock-column formula as the sibling chips: keep the chip's
4279
+ // left edge tracking the centered composer card.
4280
+ const tipLines = [
4281
+ t('trimDockTipDomain'),
4282
+ snap.mass !== null
4283
+ ? t('trimDockTipMass', { mass: snap.mass, window: snap.window })
4284
+ : null,
4285
+ snap.mode !== null ? t('trimDockTipMode', { mode: snap.mode }) : null,
4286
+ snap.reliefCooldown !== null && snap.reliefCooldown > 0
4287
+ ? t('trimDockTipCooldown', { seconds: snap.reliefCooldown })
4288
+ : null,
4289
+ snap.reliefReady ? t('trimDockTipReady') : null,
4290
+ ].filter((line) => line !== null);
4291
+ const nearCritical =
4292
+ snap.criticalLine !== null && snap.pressure >= snap.criticalLine;
4293
+ const nearLine =
4294
+ !nearCritical &&
4295
+ snap.advisoryLine !== null &&
4296
+ snap.pressure >= snap.advisoryLine;
4297
+ return h(
4298
+ 'div',
4299
+ {
4300
+ 'data-dsh-switchman': 'trim-dock-column',
4301
+ style: {
4302
+ boxSizing: 'border-box',
4303
+ width: 'calc(100% - var(--dsh-composer-side-clearance, 16px) - var(--dsh-composer-side-clearance, 16px))',
4304
+ maxWidth: 'var(--dsh-composer-card-max-width, 780px)',
4305
+ margin: '0 auto',
4306
+ flex: 'none',
4307
+ display: 'flex',
4308
+ flexDirection: 'column',
4309
+ gap: 'var(--dsh-composer-stack-gap, 6px)',
4310
+ },
4311
+ },
4312
+ h(
4313
+ 'p',
4314
+ {
4315
+ 'data-dsh-switchman': 'trim-dock-chip',
4316
+ title: tipLines.join(' · '),
4317
+ style: {
4318
+ margin: '0',
4319
+ padding: '2px 0',
4320
+ color: nearCritical
4321
+ ? 'var(--dsw-alias-state-error-primary, inherit)'
4322
+ : nearLine
4323
+ ? 'var(--dsw-alias-state-business-primary, inherit)'
4324
+ : 'var(--dsw-alias-label-tertiary, inherit)',
4325
+ fontSize: '12px',
4326
+ lineHeight: '1.6',
4327
+ },
4328
+ },
4329
+ '⚙ ',
4330
+ t('trimDockLabel', { pressure: snap.pressure, line: snap.advisoryLine }),
4331
+ ),
4332
+ );
4333
+ }
3994
4334
  /** Composer dock chip for intent routing (conversation.input.dock,
3995
4335
  * order 89 — one slot above the vision entry's 90): shows where the
3996
4336
  * session's auto-selected pseudo-model currently routes AND the
@@ -5206,7 +5546,7 @@ window.__ModuleLoader__.load({
5206
5546
  (values.langConversation !== '' &&
5207
5547
  !isCandidate(values.langConversation));
5208
5548
  /** Per-field numeric validity: raw text (when present) must be a
5209
- * whole number at or above the schema minimum. The trim and intent rows
5549
+ * plain number within the schema bounds. The trim and intent rows
5210
5550
  * share the same raw-text overlay and save gate. */
5211
5551
  const numberInvalid = Object.fromEntries(
5212
5552
  [
@@ -5219,7 +5559,7 @@ window.__ModuleLoader__.load({
5219
5559
  return [
5220
5560
  field,
5221
5561
  raw !== undefined &&
5222
- (!/^\d+$/.test(raw.trim()) ||
5562
+ (!/^\d+(?:\.\d+)?$/.test(raw.trim()) ||
5223
5563
  Number(raw.trim()) < min ||
5224
5564
  Number(raw.trim()) > (max ?? Infinity)),
5225
5565
  ];
@@ -5254,12 +5594,13 @@ window.__ModuleLoader__.load({
5254
5594
  setFailed(false);
5255
5595
  }
5256
5596
 
5257
- /** Number-input onChange: stage the raw text, commit only whole
5258
- * numbers (the draft always holds parseable values). */
5597
+ /** Number-input onChange: stage the raw text, commit only plain
5598
+ * numbers (integers or decimal fractions — the draft always holds
5599
+ * parseable values). */
5259
5600
  function editNumber(field, raw) {
5260
5601
  setNumText((previous) => ({ ...previous, [field]: raw }));
5261
5602
  const trimmed = raw.trim();
5262
- if (/^\d+$/.test(trimmed)) edit(field, Number(trimmed));
5603
+ if (/^\d+(?:\.\d+)?$/.test(trimmed)) edit(field, Number(trimmed));
5263
5604
  }
5264
5605
 
5265
5606
  /** Number-input onBlur: drop the overlay so the display falls back
@@ -5475,6 +5816,9 @@ window.__ModuleLoader__.load({
5475
5816
  trimMode: values.trimMode,
5476
5817
  trimEnabled: values.trimEnabled,
5477
5818
  trimLadderEnabled: values.trimLadderEnabled,
5819
+ trimProtectTaskIntent: values.trimProtectTaskIntent,
5820
+ trimCriticalRelief: values.trimCriticalRelief,
5821
+ trimVerboseLog: values.trimVerboseLog,
5478
5822
  surfaceFold: values.surfaceFold,
5479
5823
  trimSideModel: {
5480
5824
  provider: values.trimSideModel.provider,
@@ -5773,12 +6117,17 @@ window.__ModuleLoader__.load({
5773
6117
  });
5774
6118
  };
5775
6119
 
5776
- /** Status lines under one number row: minimum + order hints. */
6120
+ /** Shared invalid-number hint: a finite max gets the range text. */
6121
+ const numberInvalidText = (spec) =>
6122
+ spec.max !== undefined && Number.isFinite(spec.max)
6123
+ ? t('wmNumberInvalidMax', { min: spec.min, max: spec.max })
6124
+ : t('wmNumberInvalid', { min: spec.min });
6125
+ /** Status lines under one number row: bounds + order hints. */
5777
6126
  const wmNumberLines = (spec) => {
5778
6127
  const lines = [];
5779
6128
  if (numberInvalid[spec.field])
5780
6129
  lines.push({
5781
- text: t('wmNumberInvalid', { min: spec.min }),
6130
+ text: numberInvalidText(spec),
5782
6131
  invalid: true,
5783
6132
  });
5784
6133
  if (orderInvalid && WM_ORDER_FIELDS.includes(spec.field))
@@ -5814,10 +6163,10 @@ window.__ModuleLoader__.load({
5814
6163
  });
5815
6164
  };
5816
6165
 
5817
- /** Status lines under one intent number row: minimum hint. */
6166
+ /** Status lines under one intent number row: bounds hint. */
5818
6167
  const intentNumberLines = (spec) =>
5819
6168
  numberInvalid[spec.field]
5820
- ? [{ text: t('wmNumberInvalid', { min: spec.min }), invalid: true }]
6169
+ ? [{ text: numberInvalidText(spec), invalid: true }]
5821
6170
  : [];
5822
6171
  /** One trim number input: the watermark rows' raw-text overlay
5823
6172
  * pattern under the trim section id (invalid text shows the
@@ -5846,10 +6195,10 @@ window.__ModuleLoader__.load({
5846
6195
  });
5847
6196
  };
5848
6197
 
5849
- /** Status lines under one trim number row: minimum hint. */
6198
+ /** Status lines under one trim number row: bounds hint. */
5850
6199
  const trimNumberLines = (spec) =>
5851
6200
  numberInvalid[spec.field]
5852
- ? [{ text: t('wmNumberInvalid', { min: spec.min }), invalid: true }]
6201
+ ? [{ text: numberInvalidText(spec), invalid: true }]
5853
6202
  : [];
5854
6203
 
5855
6204
  /** Intent option sets fed by the DSH model catalog (the same
@@ -7050,6 +7399,54 @@ window.__ModuleLoader__.load({
7050
7399
  }),
7051
7400
  lines: [],
7052
7401
  }),
7402
+ h(SettingsRow, {
7403
+ key: 'trimProtectTaskIntent',
7404
+ id: `${trimId}-intent`,
7405
+ label: t('trimProtectTaskIntentLabel'),
7406
+ help: t('trimProtectTaskIntentHelp'),
7407
+ control: h('input', {
7408
+ type: 'checkbox',
7409
+ id: `${trimId}-intent`,
7410
+ checked: values.trimProtectTaskIntent,
7411
+ onChange: () => {
7412
+ edit('trimProtectTaskIntent', !values.trimProtectTaskIntent);
7413
+ },
7414
+ disabled: !editable,
7415
+ style: STYLE.checkbox,
7416
+ }),
7417
+ lines: [],
7418
+ }),
7419
+ h(SettingsRow, {
7420
+ key: 'trimCriticalRelief',
7421
+ id: `${trimId}-relief`,
7422
+ label: t('trimCriticalReliefLabel'),
7423
+ help: t('trimCriticalReliefHelp'),
7424
+ control: h('input', {
7425
+ type: 'checkbox',
7426
+ id: `${trimId}-relief`,
7427
+ checked: values.trimCriticalRelief,
7428
+ onChange: () => {
7429
+ edit('trimCriticalRelief', !values.trimCriticalRelief);
7430
+ },
7431
+ disabled: !editable,
7432
+ style: STYLE.checkbox,
7433
+ }),
7434
+ key: 'trimVerboseLog',
7435
+ id: `${trimId}-verbose`,
7436
+ label: t('trimVerboseLogLabel'),
7437
+ help: t('trimVerboseLogHelp'),
7438
+ control: h('input', {
7439
+ type: 'checkbox',
7440
+ id: `${trimId}-verbose`,
7441
+ checked: values.trimVerboseLog,
7442
+ onChange: () => {
7443
+ edit('trimVerboseLog', !values.trimVerboseLog);
7444
+ },
7445
+ disabled: !editable,
7446
+ style: STYLE.checkbox,
7447
+ }),
7448
+ lines: [],
7449
+ }),
7053
7450
  h(SettingsRow, {
7054
7451
  key: 'surfaceFold',
7055
7452
  id: `${trimId}-surface`,
@@ -7428,6 +7825,19 @@ window.__ModuleLoader__.load({
7428
7825
  },
7429
7826
  (kit) => h(IntentDockEntry, { ...kit, t }),
7430
7827
  ),
7828
+ ); // Trim-pressure chip (same dock list, order 88 — one slot below
7829
+ // the intent chip): the fold engine's paid-prompt pressure, the
7830
+ // number its nudges/tiers act on. Deliberately NOT the composer
7831
+ // context meter's projection — the tooltip explains the domains.
7832
+ ctx.slots.inject('conversation.input.dock', () =>
7833
+ ctx.slots.register(
7834
+ {
7835
+ name: 'conversation.input.dock',
7836
+ id: 'dsh-switchman-trim',
7837
+ order: 88,
7838
+ },
7839
+ (kit) => h(TrimDockEntry, { ...kit, t }),
7840
+ ),
7431
7841
  );
7432
7842
  // Composer model label (conversation.input.model.label): the
7433
7843
  // ui-model-selection shell dispatches EVERY model's label