dsh-switchman 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cordis.patch.yml CHANGED
@@ -28,11 +28,13 @@
28
28
  #
29
29
  # Provenance & maintenance: the four `plugins` lists below are copied verbatim
30
30
  # from @deepseek-ai/dsh-web-app presets/{standard,ptc,minimal,cordis}.patch.yml
31
- # (dsh 0.2.1-rc.1: time-context + tool-schedule + the disabled tool-plugin-market
32
- # row joined every list, the subagent rows lost `backgroundMode` under the
33
- # unified activation lifecycles, the ralph/codex/claude-code rows left the
34
- # presets, minimal gained image-only fs tools and a compaction group, and the
35
- # plan-mode text was reworded). A Loader override replaces the target row's
31
+ # (dsh 0.2.2-rc.1: tool-fs ships `applyPatch: false`, tool-fs-search ships
32
+ # `sampleOverCapGlobResults: false`, the subagent spawn row carries
33
+ # `modelSelection` + `modelDiscovery` (the 0.2.1 unified-activation shape),
34
+ # tool-plugin-manager/market disabled guards use `!!js "!ctx.get('profileContext')"`
35
+ # expression strings, and no list-agents row ships; dsh 0.2.1-rc.1 had added
36
+ # time-context + tool-schedule, dropped `backgroundMode`, and reworded the
37
+ # plan-mode text). A Loader override replaces the target row's
36
38
  # `config` wholesale, so every field is restated here. After a DSH upgrade that
37
39
  # changes the shipped presets, re-sync these lists from the new preset files,
38
40
  # then reinstall this bundle; scripts/validate.mjs compares this patch against
@@ -45,7 +47,7 @@
45
47
  # scope, and a second instance makes session composition throw
46
48
  # `tool "list_subagent_models" is already registered in this scope` — breaking
47
49
  # creation of ALL new sessions and the recomposition of old ones. The shipped
48
- # presets (verified against installed dsh-web-app 0.2.0-rc.2, the fork's
50
+ # presets (verified against installed dsh-web-app 0.2.2-rc.1, the fork's
49
51
  # 0.2.1-alpha.1, and 0.2.1-rc.1) enable it on the spawn row only; fork-side
50
52
  # explicit routing is not a factory capability.
51
53
  #
@@ -122,6 +124,8 @@
122
124
  disabled: !!js process.platform !== 'win32'
123
125
  - id: tool-fs
124
126
  name: '@deepseek-ai/dsh-tool-fs'
127
+ config:
128
+ applyPatch: false
125
129
  - id: tool-fs-search
126
130
  name: '@deepseek-ai/dsh-tool-fs-search'
127
131
  config:
@@ -192,14 +196,13 @@
192
196
  config:
193
197
  - id: tool-subagent-control
194
198
  name: '@deepseek-ai/dsh-tool-subagent-control'
195
- - id: tool-subagent-list-agents
196
- name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
197
199
  - id: tool-subagent
198
200
  name: '@deepseek-ai/dsh-tool-subagent'
199
201
  config:
200
202
  provider: spawn
201
203
  toolName: subagent
202
- modelSelectionSettings: true
204
+ modelSelection: true
205
+ modelDiscovery: true
203
206
  - id: tool-subagent-fork
204
207
  name: '@deepseek-ai/dsh-tool-subagent'
205
208
  config:
@@ -226,7 +229,7 @@
226
229
  name: '@deepseek-ai/dsh-tool-present'
227
230
  - id: tool-plugin-manager
228
231
  name: '@deepseek-ai/dsh-plugin-manager/tools'
229
- disabled: true
232
+ disabled: !!js "!ctx.get('profileContext')"
230
233
  - id: tool-plugin-market
231
234
  name: '@deepseek-ai/dsh-plugin-market/tools'
232
235
  disabled: true
@@ -260,6 +263,8 @@
260
263
  disabled: !!js process.platform !== 'win32'
261
264
  - id: tool-fs
262
265
  name: '@deepseek-ai/dsh-tool-fs'
266
+ config:
267
+ applyPatch: false
263
268
  - id: tool-fs-search
264
269
  name: '@deepseek-ai/dsh-tool-fs-search'
265
270
  config:
@@ -330,14 +335,13 @@
330
335
  config:
331
336
  - id: tool-subagent-control
332
337
  name: '@deepseek-ai/dsh-tool-subagent-control'
333
- - id: tool-subagent-list-agents
334
- name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
335
338
  - id: tool-subagent
336
339
  name: '@deepseek-ai/dsh-tool-subagent'
337
340
  config:
338
341
  provider: spawn
339
342
  toolName: subagent
340
- modelSelectionSettings: true
343
+ modelSelection: true
344
+ modelDiscovery: true
341
345
  - id: tool-subagent-fork
342
346
  name: '@deepseek-ai/dsh-tool-subagent'
343
347
  config:
@@ -362,10 +366,8 @@
362
366
  config:
363
367
  fetch: true
364
368
  searchTimeoutMs: 60000
365
- - id: tool-presentation
366
- name: '@deepseek-ai/dsh-agent-tool-presentation'
367
- config:
368
- mode: ptc
369
+ - id: tool-executor-ptc
370
+ name: '@deepseek-ai/dsh-tool-executor-ptc'
369
371
  - id: present
370
372
  name: '@deepseek-ai/dsh-tool-present'
371
373
  - id: tool-plugin-manager
@@ -502,6 +504,8 @@
502
504
  disabled: !!js process.platform !== 'win32'
503
505
  - id: tool-fs
504
506
  name: '@deepseek-ai/dsh-tool-fs'
507
+ config:
508
+ applyPatch: false
505
509
  - id: tool-fs-search
506
510
  name: '@deepseek-ai/dsh-tool-fs-search'
507
511
  config:
@@ -568,14 +572,13 @@
568
572
  config:
569
573
  - id: tool-subagent-control
570
574
  name: '@deepseek-ai/dsh-tool-subagent-control'
571
- - id: tool-subagent-list-agents
572
- name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
573
575
  - id: tool-subagent
574
576
  name: '@deepseek-ai/dsh-tool-subagent'
575
577
  config:
576
578
  provider: spawn
577
579
  toolName: subagent
578
- modelSelectionSettings: true
580
+ modelSelection: true
581
+ modelDiscovery: true
579
582
  - id: tool-subagent-fork
580
583
  name: '@deepseek-ai/dsh-tool-subagent'
581
584
  config:
package/host/config.js CHANGED
@@ -129,11 +129,20 @@ export const Config = z.object({
129
129
  // --- Phase 3: context watermark control --------------------------------
130
130
  /** Soft watermark: advisory banner + delegation nudge (tokens). */
131
131
  wmSoftTokens: z.number().min(1000).default(80000).volatile(),
132
- /** Hard watermark: read budget tightens, wrap-up advised (tokens). */
133
- wmHardTokens: z.number().min(2000).default(120000).volatile(),
132
+ /** Hard watermark: read budget tightens, wrap-up advised (tokens). 95k
133
+ * aligns with the trim pressure line (60% of the 150k window): past
134
+ * this point the fold engine is already folding, so per-call read
135
+ * budgets must tighten at the SAME boundary — agent sessions grow in
136
+ * PULSES (one large file read = tens of thousands of tokens injected
137
+ * at once, faster than any fold can commit), and the read budget is
138
+ * the only preventive valve on the pulse source. */
139
+ wmHardTokens: z.number().min(2000).default(95000).volatile(),
134
140
  /** Force watermark: handover document + compaction (tokens). */
135
141
  wmForceTokens: z.number().min(3000).default(150000).volatile(),
136
- /** Per-call read budget for read/glob/grep (tokens). */
142
+ /** Per-TURN read budget (inspection C16 — the name predates the turn
143
+ * accounting): read/glob/grep/bash results accumulate against it within
144
+ * one turn; the account resets after 15 idle minutes and the pre/post
145
+ * gates act at 2.4× this value (CEILING_MULTIPLE in context-watch.js). */
137
146
  wmReadBudgetTokens: z.number().min(200).default(3000).volatile(),
138
147
  /** Hard-tier behavior: cap reads and advise, or deny outright. */
139
148
  wmDenyMode: z.union(["cap", "deny"]).default("cap").volatile(),
@@ -188,7 +197,7 @@ export const Config = z.object({
188
197
  * kind fails open to the fallback chain. */
189
198
  intentClassifierEndpoint: z.string().default("").volatile(),
190
199
  /** Model name sent to the decision endpoint for kind "systemone"
191
- * (free text, e.g. tev1:4b-mxfp8). Independent of the llm provider
200
+ * (free text, e.g. d3:4b-mxfp8). Independent of the llm provider
192
201
  * catalog — no provider registration needed. Empty = unset; that
193
202
  * kind fails open to the fallback chain. */
194
203
  intentClassifierSystemoneModel: z.string().default("").volatile(),
@@ -245,7 +254,14 @@ export const Config = z.object({
245
254
  /** Emergency tier (tier c): forced MECHANICAL fold (no side-model call)
246
255
  * at this percent of the window; cooldown-gated. */
247
256
  trimEmergencyPercent: z.number().min(1).max(100).default(95).volatile(),
248
- /** Effective-window cap for the tier math: tier points are computed
257
+ /** [2026-11-07]-[growth/increment constants are absolute tokens
258
+ * calibrated for the default 150k effective window]-[scaling
259
+ * trimWindowTokens down without scaling trimGrowthTokens /
260
+ * trimIncrementTokens proportionally makes the growth tier unreachable
261
+ * (a 30k window can never accumulate a 50k increment; observed live:
262
+ * growth fired once while emergency fired 17 times). Rule of thumb:
263
+ * increment ≈ window/3, growth ≈ increment × 0.45.]
264
+ * Effective-window cap for the tier math: tier points are computed
249
265
  * against min(model-resolved window, cap). 0 = auto (cap follows
250
266
  * wmForceTokens, so folds always fire ahead of the handover tier). */
251
267
  trimWindowTokens: z.number().min(0).default(0).volatile(),
@@ -253,11 +269,39 @@ export const Config = z.object({
253
269
  * next model call reasons over). */
254
270
  trimProtectedTail: z.number().min(0).max(100).default(6).volatile(),
255
271
  /** Side-model fold cadence cap per rolling hour (emergency mechanical
256
- * folds are exempt; they have their own cooldown). */
257
- trimMaxFoldsPerHour: z.number().min(1).max(60).default(6).volatile(),
272
+ * folds are exempt; they have their own cooldown). 16 covers continuous
273
+ * full-rate generation: at ~170 tok/s output a session grows ~612k
274
+ * raw tokens/hour ⇒ 12.2 folds/hour of pure T1 demand (one 50k
275
+ * increment fold every ~4.9 min), leaving 12 starved and zero ladder
276
+ * share; 16 fits the T1 demand plus 2-3 ladder folds plus headroom
277
+ * (observed live: at 12, growth consumed the whole budget). */
278
+ trimMaxFoldsPerHour: z.number().min(1).max(60).default(16).volatile(),
258
279
  /** Route for the side-model summarizer (L3). Empty = inherit the
259
280
  * session's current model. */
260
281
  trimSideModel: IntentRouteSchema.default({ provider: "", model: "" }).volatile(),
282
+ /** Route for the fold-fallback summarizer. When the primary side route
283
+ * (trimSideModel or the inherited session model) fails, raw folds retry
284
+ * on this route before degrading to a mechanical fold; ladder folds
285
+ * retry but never go mechanical. Pick a route with headroom on cooldown,
286
+ * risk-control, and concurrency limits. Empty = no fallback leg. */
287
+ trimFoldFallbackModel: IntentRouteSchema.default({ provider: "", model: "" }).volatile(),
288
+ /** T1/T2/T3 ladder folding (docs/ladder-fold.md): master switch for the
289
+ * T2/T3 distillation tiers. T1 raw-range folds are governed by
290
+ * trimMode; the ladder only adds the summary-maintenance tiers. */
291
+ trimLadderEnabled: z.boolean().default(true).volatile(),
292
+ /** Ladder T2 gate: minimum active-T1 summary token mass before a T2
293
+ * distillation fires (the need signal — bili #379: block count alone
294
+ * is not a need signal). */
295
+ trimLadderT2Tokens: z.number().min(1000).default(8000).volatile(),
296
+ /** Ladder T2 companion floor: a T2 distillation merges at least this
297
+ * many active T1 blocks (filters degenerate two-block rewrites). */
298
+ trimLadderT2MinBlocks: z.number().min(2).max(200).default(3).volatile(),
299
+ /** Ladder T3 gate: minimum active-T2 summary token mass before a T3
300
+ * condensation fires. */
301
+ trimLadderT3Tokens: z.number().min(1000).default(6000).volatile(),
302
+ /** Ladder T3 companion floor: a T3 condensation merges at least this
303
+ * many active T2 blocks. */
304
+ trimLadderT3MinBlocks: z.number().min(2).max(200).default(2).volatile(),
261
305
  /** Explicit ledger state directory. Empty = <dshHome>/.dsh-switchman/
262
306
  * state/trim/. */
263
307
  trimStateDir: z.string().default("").volatile(),
@@ -159,7 +159,11 @@ export function resolveInheritance(parentLedger, parentId, childId, childMessage
159
159
  version: LEDGER_VERSION,
160
160
  sessionId: childId,
161
161
  blocks: blocks.map((block) => {
162
- const clone = { ...block, refRange: { ...block.refRange } };
162
+ // [2026-11-07]-[v2 ladder blocks carry refRange: null]-[spreading
163
+ // null produced {} on the clone, which slipped past the view's
164
+ // `refRange !== null` T1 filter and inflated the unlocated count
165
+ // (a phantom epoch signal); ladder clones must keep null]
166
+ const clone = { ...block, refRange: block.refRange !== null && block.refRange !== undefined ? { ...block.refRange } : null };
163
167
  delete clone.surfaceSeqs;
164
168
  delete clone.surfaceReplaced;
165
169
  delete clone.surfaceSkip;