dsh-switchman 1.9.0 → 1.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +13 -10
- package/README.es.md +13 -10
- package/README.fr.md +13 -10
- package/README.it.md +13 -10
- package/README.ja.md +13 -10
- package/README.ko.md +13 -10
- package/README.md +12 -9
- package/README.pt.md +13 -10
- package/README.ru.md +13 -10
- package/README.zh-TW.md +13 -10
- package/README.zh.md +13 -10
- package/client.js +56 -56
- package/host/config.js +8 -2
- package/host/context-trim/fork.js +16 -6
- package/host/context-trim/index.js +239 -15
- package/host/context-trim/metrics.js +32 -8
- package/host/context-trim/summarizer.js +1 -1
- package/host/context-trim/surface.js +920 -0
- package/host/context-trim/trigger.js +7 -0
- package/host/context-trim/view.js +81 -27
- package/host/context-watch.js +17 -67
- package/host/handover-state.js +2 -2
- package/host/routes.js +1 -1
- package/index.js +3 -3
- package/package.json +1 -1
package/README.de.md
CHANGED
|
@@ -14,7 +14,7 @@ Wer lange mit DSH arbeitet, ärgert sich über zwei Dinge. Erstens werden Sessio
|
|
|
14
14
|
|
|
15
15
|
dsh-switchman ist ein Plugin für [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH). Nach der Installation wandelt sich das Hauptmodell vom Selbermacher zum Disponenten: Wasserstand messen, Spur wählen, Aufgaben vergeben, Abnahme prüfen. Es ist kein neues Modell, sondern ein Dispositionsregelwerk an DSH plus eine Einstellungsseite — und es tut acht Dinge:
|
|
16
16
|
|
|
17
|
-
**1. Kontext-Wasserstand: lange Sessions platzen nicht.** Jede Runde zählt die Session-Tokens in Echtzeit; drei Stufen schrauben sich hoch: 80k (soft, einstellbar) mahnt „zeit zu delegieren“; 120k (hard) strafft das Einzellese-Budget und lenkt auf den Abschluss; 150k (force) übergibt automatisch —
|
|
17
|
+
**1. Kontext-Wasserstand: lange Sessions platzen nicht.** Jede Runde zählt die Session-Tokens in Echtzeit; drei Stufen schrauben sich hoch: 80k (soft, einstellbar) mahnt „zeit zu delegieren“; 120k (hard) strafft das Einzellese-Budget und lenkt auf den Abschluss; 150k (force) übergibt automatisch — das Übergabedokument wird geschrieben (das append-only Sitzungslog ist dabei die vollständige Sicherung), der Kontext komprimiert, die Session geweckt und läuft weiter, ohne dass die Aufgabe abreißt. Auch Hintergrund-Subagents, die im Moment der Übergabe noch laufen, gehen nicht verloren: id, Aufgabe und Report-Pfad landen im Übergabedokument; die fortgesetzte Session weiß, wo sie Reports abholt, und vergibt nichts doppelt. Jeder Subagent trägt eine eigene harte Obergrenze und verlässt nach seinem HANDOFF-Summary die Bühne. Passt dir die automatische Intervention nicht, übernimm jederzeit von Hand: `/ctx-pause` stoppt alle Wasserstands-Aktionen (die Messung läuft weiter, die Live-Wasserstandszeile am Ende springt auf paused — es wird nur nicht mehr gehandelt), `/ctx-resume` holt alles jederzeit zurück — nach einem DSH-Neustart greift die Intervention auch von selbst wieder, ein temporäres Loslassen, kein Dauer-Aus; `/ctx-handover` wartet nicht, bis der Wasserstand oben ist, und startet dieselbe Übergabe auf Zuruf: Übergabedokument schreiben, Kontext verdichten, Session zum Weiterlaufen wecken (die Session wird erst an eine Leerlauf-Grenze geführt, das Ergebnis kann daher ein paar Minuten dauern).
|
|
18
18
|
|
|
19
19
|
**2. Sechs Dispatch-Pools: das richtige Modell für jede Arbeit.** Economy (Massen-Kleinkram), Mechanical (Schablonen-Umformung), Main (tägliche Codearbeit), Hard (schwere Schlussfolgerungen und große Refactorings), Vision (Bilder), Review (unabhängige Prüfung). Auf der Einstellungsseite kreuzt man Kandidaten an, ordnet Prioritäten, vergibt Noten S/A/B/C und nagelt je Route einen Reasoning-Aufwand fest — das Aufwand-Dropdown führt die Stufen, die das Modell tatsächlich beherrscht, nicht generische drei. Im Prompt jeder Runde steckt eine `[SWITCHMAN:POOLS]`-Empfehlungstabelle; nach der wird vergeben. Drei Enforcement-Modi: aus / Empfehlung / Erzwingen (Erzwingen = Modelle außerhalb der Pools werden glatt abgelehnt).
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ dsh-switchman ist ein Plugin für [DeepSeek Harness](https://github.com/deepseek
|
|
|
23
23
|
- **Agent-Teams** — eingeschaltet injiziert das Team-Regelwerk (Delegation als Standard + gestufte Verifikation + Disziplin fürs gemeinsame Task-Board) und aktiviert die Agent-Teams-Funktion von DSH automatisch: das Hauptmodell rekrutiert Dauerteammates (`spawn_teammate`), legt Aufgaben auf das gemeinsame Task-Board (`team_task_*`) und tauscht Nachrichten mit Teammates aus. Wann ein Team fällig ist, ist klar geregelt: parallelisierbare unabhängige Subtasks, große in sich abgeschlossene Mengen, hoher Wasserstand im Hauptkontext, nötige Rollentrennung; einmalige Punktuntersuchungen bleiben beim Subagent. Wieder ausgeschaltet verschwinden die Team-Klauseln restlos, und laufenden Sessions werden die Team-Werkzeuge nie entrissen.
|
|
24
24
|
- **Whitelist-Sync für Subagent-Modelle** — DSH führt eine Autorisierungs-Whitelist „Agenten dürfen Modelle für Subagents wählen“: in einem Pool gewählte, aber nicht autorisierte Routen werden bei namentlicher Vergabe abgelehnt (im Teams-Modus mit ⚠ markiert). Dieser Schalter schreibt die Vereinigung aller sechs Pools en bloc in ebendiese Whitelist — switchman ist die einzige Quelle der Wahrheit, doppelte Konfiguration entfällt. Die Whitelist gilt als Snapshot je neuer Session; der Sync wirkt nur auf danach gestartete Sessions.
|
|
25
25
|
|
|
26
|
-
Die Session-Kopfzeile zeigt sofort, was los ist: das ⚡-Abzeichen „autonomes Team“ und ◇ mit dem tatsächlich genutzten Modell der Session; während einer laufenden Auto-Übergabe erscheint live „Übergabe läuft ·
|
|
26
|
+
Die Session-Kopfzeile zeigt sofort, was los ist: das ⚡-Abzeichen „autonomes Team“ und ◇ mit dem tatsächlich genutzten Modell der Session; während einer laufenden Auto-Übergabe erscheint live „Übergabe läuft · Übergabedokument schreiben / Kontext komprimieren / Nachfolger wecken“.
|
|
27
27
|
|
|
28
28
|
**4. Sprachpräferenzen: einmal fragen, für immer merken.** Je ein Dropdown für Antworten, Code-Kommentare und Dokumente; Geltungsbereich global oder je Projekt (`.switchman/lang.json`). Leer lassen geht auch — beim ersten Einsatz wird einmal in der Sprache deiner DSH-Oberfläche gefragt, danach hält sich jede Session daran.
|
|
29
29
|
|
|
@@ -75,7 +75,7 @@ Auch mit nur einem Modell lohnt sich die Installation — Wasserstandskontrolle
|
|
|
75
75
|
- **Dispatch-Pools** — sechs Karten in zwei Reihen zu drei: oben Economy / Mechanical / Main, unten Hard / Vision / Review. Kandidaten je Provider ankreuzen; ein Haken bei „manuelle Reihenfolge“ macht daraus eine nummerierte Prioritätsliste, sortiert mit ↑ ↓ ×; je Route lässt sich der Reasoning-Aufwand festnageln (Standard „wie Spur“). Die Zusammenfassungszeile oben aktualisiert live — im Screenshot: „4/6 Pools konfiguriert · 2 gerankt · Modus Empfehlung“.
|
|
76
76
|
- **Fähigkeits-Ranking + Enforcement-Modus** — die Vereinigung der gewählten Modelle über alle sechs Pools, nach Fähigkeit sortiert, das stärkste zuerst (im Screenshot glm-5.3 auf S und glm-5.3-flash auf A verankert), umsortier- und kürzbar; Enforcement-Modus Empfehlung / Erzwingen (Erzwingen = Modelle außerhalb der Pools werden glatt abgelehnt).
|
|
77
77
|
- **Agent-Teams** — die zwei Schalter für Team-Modus und Whitelist-Sync, beide standardmäßig aus; im Screenshot an, mit Sync-Statuszeile unter dem Schalter.
|
|
78
|
-
- **Kontext-Wasserstand** — die drei Schwellen (im Screenshot 80000 / 120000 / 150000), das Einzellese-Budget (3000), das Verhalten der Hard-Stufe (drosselnd durchlassen / blockieren), der Schalter für die Auto-Übergabe und die eigenen Obergrenzen der Subagents — alles in diesem Bereich. Unten die Befehlszeile: `/ctx-pause` Eingriffe pausieren · `/ctx-resume` fortsetzen · `/ctx-handover`
|
|
78
|
+
- **Kontext-Wasserstand** — die drei Schwellen (im Screenshot 80000 / 120000 / 150000), das Einzellese-Budget (3000), das Verhalten der Hard-Stufe (drosselnd durchlassen / blockieren), der Schalter für die Auto-Übergabe und die eigenen Obergrenzen der Subagents — alles in diesem Bereich. Unten die Befehlszeile: `/ctx-pause` Eingriffe pausieren · `/ctx-resume` fortsetzen · `/ctx-handover` Übergabedokument schreiben und sofort übergeben (die Session wird erst an eine Leerlauf-Grenze geführt und dann komprimiert — das Ergebnis kann ein paar Minuten dauern).
|
|
79
79
|
- **Intent-Routing** — der Hauptschalter, die Small-Model-Route des Klassifikators, der Klassifikatortyp (auto / decision / chat), die eigene Kandidatenliste (je Eintrag eine Zeile Fähigkeitsbeschreibung), Cache-Fenster / Vertrauensschwelle / Klassifikations-Timeout / Verlaufsbudget und ein optionales Fallback-Modell. Eingeschaltet erscheint in der Modellauswahl der lokalisierte Eintrag „Automatisch (Intent-Routing)“, und der Status-Chip über dem Eingabefeld zeigt Routing-Modell und Vertrauen.
|
|
80
80
|
|
|
81
81
|
4. **Prüfen** — in der Session-Kopfzeile erscheint das ⚡-Abzeichen „autonomes Team“ (daneben ◇ mit dem Modell der Session); oder das Modell einfach fragen: „Wie lautet die Überschrift des letzten Abschnitts deines System-Prompts?“ — die Antwort sollte das dsh-switchman-Regelwerk nennen.
|
|
@@ -96,7 +96,7 @@ Alles Folgende sind die vollständigen Werte direkt nach der Neuinstallation (ma
|
|
|
96
96
|
|
|
97
97
|
**Dispatch-Pools**: alle sechs Spuren (economy/mechanical/main/hard/vision/review) starten ohne Kandidaten (= die Standardmodelle des Systems, keine Einwirkung); manuelle Reihenfolge und gepinnter Aufwand sind aus/leer; `dispatchEnforce` = `advice` (nur Empfehlung, nichts wird erzwungen).
|
|
98
98
|
|
|
99
|
-
**Kontext-Wasserstand**: soft `80000` / hard `120000` / force `150000` Token; Einzellese-Budget `3000`; Verhalten bei Budgetüberschreitung `cap` (kürzen mit Warnung); `wmAutoHandover` = an (bei force
|
|
99
|
+
**Kontext-Wasserstand**: soft `80000` / hard `120000` / force `150000` Token; Einzellese-Budget `3000`; Verhalten bei Budgetüberschreitung `cap` (kürzen mit Warnung); `wmAutoHandover` = an (bei force Übergabedokument schreiben + Komprimierung, automatisch); die harte Obergrenze für Subagents = an (gemeinsame 150k).
|
|
100
100
|
|
|
101
101
|
**Agent Teams**: `teamsMode` = aus; `syncWhitelist` = aus (die beiden Schalter sind unabhängig voneinander).
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Alles Folgende sind die vollständigen Werte direkt nach der Neuinstallation (ma
|
|
|
104
104
|
|
|
105
105
|
**Kontext-Trimming**: `trimEnabled` = an; `trimMode` = `auto` (vollautomatisch); Wachstumsschwelle `22500` + Zuwachs `50000` Tokens; Druck `60%` / Notfall `95%`; geschütztes Ende `6` Nachrichten; Fold-Takt-Obergrenze `6` pro Stunde; Nebenmodell nicht gesetzt (erbt das Session-Modell) — Details im Abschnitt „Automatisches Kontext-Trimming“ unten.
|
|
106
106
|
|
|
107
|
-
**Out-of-the-Box-Anmerkungen**: ① dass Intent-Routing ab Werk unbrauchbar ist, ist Absicht — drei Schritte zum Einschalten (Klassifikator, Kandidaten, Schalter); ② das wirksame Auto-Fenster steht ab Werk auf 200000 — die Leitplanke garantiert 0.8×Fenster ≥ force (150000), die Kern-Komprimierlinie (160000) liegt also stets hinter der Linie der weichen Übergabe (150000); ③ am spürbarsten ab Werk ist das Wasserstands-Trio: 80k mahnt zur Delegation / 120k strafft das Lesen / 150k
|
|
107
|
+
**Out-of-the-Box-Anmerkungen**: ① dass Intent-Routing ab Werk unbrauchbar ist, ist Absicht — drei Schritte zum Einschalten (Klassifikator, Kandidaten, Schalter); ② das wirksame Auto-Fenster steht ab Werk auf 200000 — die Leitplanke garantiert 0.8×Fenster ≥ force (150000), die Kern-Komprimierlinie (160000) liegt also stets hinter der Linie der weichen Übergabe (150000); ③ am spürbarsten ab Werk ist das Wasserstands-Trio: 80k mahnt zur Delegation / 120k strafft das Lesen / 150k übergibt automatisch (Dokument schreiben + Komprimierung) — ganz ohne Einstellungen.
|
|
108
108
|
|
|
109
109
|
## Automatisches Kontext-Trimming
|
|
110
110
|
|
|
@@ -114,7 +114,7 @@ Automatisierungsstufen (`trimMode`):
|
|
|
114
114
|
|
|
115
115
|
- **`off`** — nur messen: Usage- und Cache-Hit-Sampling läuft weiter; kein Banner, keine Folds.
|
|
116
116
|
- **`advisory`** — das Session-Modell faltet selbst: die Tools `ctx_trim_fold` und `ctx_trim_status` plus der Protokollkopf werden dafür freigegeben.
|
|
117
|
-
- **`auto`** (Standard) — alles darüber hinaus plus automatische Folds an der Leerlauf-Grenze, in drei Stufen: eine Wachstumsschwelle (Zuwachs
|
|
117
|
+
- **`auto`** (Standard) — alles darüber hinaus plus automatische Folds an der Leerlauf-Grenze, in drei Stufen: eine Wachstumsschwelle (Zuwachs > `trimGrowthTokens`, gemessen ab dem Tiefpunkt nach dem letzten Fold — der Anker, der die Schwelle nach Folds auf hohem View-Stand scharf hält — UND ein zusammenhängender komprimierbarer Zuwachs ≥ `trimIncrementTokens`), eine Druckstufe (`trimPressurePercent` des Kontextfensters) und eine Notfallstufe (`trimEmergencyPercent` — ein mechanischer Fold mit eigener Abklingzeit).
|
|
118
118
|
|
|
119
119
|
Alle Schlüssel liegen unter Einstellungen → dsh-switchman; Defaults aus `host/config.js`:
|
|
120
120
|
|
|
@@ -131,16 +131,19 @@ Alle Schlüssel liegen unter Einstellungen → dsh-switchman; Defaults aus `host
|
|
|
131
131
|
| `trimMaxFoldsPerHour` | `6` | Fold-Takt-Obergrenze pro rollierender Stunde für Nebenmodell-Folds (Notfall-Folds ausgenommen). |
|
|
132
132
|
| `trimSideModel` | nicht gesetzt | Route des zusammenfassenden Nebenmodells. Leer = das aktuelle Session-Modell erben. |
|
|
133
133
|
| `trimStateDir` | nicht gesetzt | Überschreibt das Fold-Zustandsverzeichnis. Leer = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
| `surfaceFold` | `true` | Liefert committete Folds auf die Session-Oberfläche aus (Shadow-Price-Messereignis + `surfaceOp`-Replace-Ereignispaar). OFF behält die rein gesplicte View. |
|
|
134
135
|
|
|
135
|
-
**Trigger-Pfade.** Stufenprüfungen laufen an der Leerlauf-Grenze und — als Fallback für Hosts, auf denen Leerlauf-Status-Ereignisse nicht erreichbar sind — nach jedem Modell-Stream-Abschluss (auf eine Auswertung pro 60 s und Session gedrosselt). Jede Entscheidung — Folds wie No-ops gleichermaßen — wird als eine
|
|
136
|
+
**Trigger-Pfade.** Stufenprüfungen laufen an der Leerlauf-Grenze und — als Fallback für Hosts, auf denen Leerlauf-Status-Ereignisse nicht erreichbar sind — nach jedem Modell-Stream-Abschluss (auf eine Auswertung pro 60 s und Session gedrosselt). Jede Entscheidung — Folds wie No-ops gleichermaßen — wird als eine zeitgestempelte `key=value`-Zeile an `decisions.log` im Fold-Zustandsverzeichnis (siehe `trimStateDir`) angehängt und gibt Folds so eine Offline-Prüfspur; das Zeilenvokabular (`view-applied`, Fold-Entscheidungs-/Ergebniszeilen, `surface-replace`, `surface-replace skipped reason=…`) ist in [docs/context-trim.md](./docs/context-trim.md) katalogisiert.
|
|
136
137
|
|
|
138
|
+
**Leitungs-Wahrheit und stabiler Zustand.** Entscheidungszeilen tragen `view=<n>` und, sobald eine Antwort eingetroffen ist, `wire=<n>` — den echten Anbieter-Prompt (ungecachter Input + Cache-Read + Cache-Write, entnommen aus dem Usage-Event des Streams). Die View-Schätzung zählt nur das Messages-Array und liest immer um den festen Overhead kleiner als die Leitung (gemessen ≈ 17.3k: System-Prompt + Tool-Schemas + Persona); Druck- und Notfallstufe werten daher auf `max(view, wire)` aus, und nur `wire` ist eine Prompt-Größenmessung. In einem 150k-Fenster läuft der gesunde Sägezahn direkt nach einem Fold auf Leitung ≈ 40k ↔ 88–90k beim nächsten (≈27%–60% des Fensters), ein Fold pro ~50k Rohwachstum, wobei die Obergrenze eher von der Druckstufe als vom Fenster nahe 90k festgehalten wird. Steigt `view`, ohne dass je eine `surface-replace`-Zeile erscheint, lies die Skip-Zeilen (`incomplete-seqs`, `no-service`, `compaction-lock`).
|
|
139
|
+
|
|
140
|
+
**Host-Kompaktions-Epochen.** Fold-Verweise sind an Nachrichten-IDs und Inhalts-Hashes verankert; ersetzt der Host selbst den erneut gesendeten Verlauf, veralten sämtliche Blöcke auf einmal: keiner findet mehr seine Position, die View fällt still auf den Rohverlauf zurück (fail-open — das Entscheidungsprotokoll vermerkt `view-applied applied=0`), und das Plugin verankert seine Wachstumsbaseline bei der nächsten Anfrage auf der Sicht nach der Kompaktion. Die Host-Kompaktion ist damit die Backstop-Trimschicht; die Plugin-Folds leisten die feingranulare Arbeit innerhalb einer Host-Epoche. Manche Dispatches übergeben vollständig eingefrorene Anfrage-Arrays oder Optionsobjekte (die aktuelle Agent-Loop friert die zusammengesetzten Anfragen tief ein); für sie meldet `injectView` das Ergebnis im Entscheidungsprotokoll: `nothing-to-apply` (keine lokalisierbaren Fold-Blöcke — der Rohverlauf IST die View), `in-place`/`swapped` (der Fold-View wurde ausgeliefert) oder `none` (ein Fold existierte, aber der eingefrorene Dispatch konnte ihn nicht tragen — auf die Leitung geht der Rohverlauf). **Surface Replace ist der Auslieferungsweg, wann immer er verfügbar ist** (`surfaceFold`, standardmäßig an): an der seriellen `agent/turn-stopping`-Grenze plus einem Idle-Sweep hängt das Plugin das host-typische Shadow-Price-Messereignis und EIN `user/message`-Ersatzereignis an, das `surfaceOp {op:'replace', startSeq, endSeq}` trägt und mit `sourceEventSeqs` jeden überdeckten Oberflächen-Knoten abdeckt — derselbe Mechanismus, den die Host-Kompaktion selbst nutzt —, sodass ein committeter Fold aus der Quellschicht auf die Leitung gelangt, eingefrorene Dispatches eingeschlossen. Solange die letzten Dispatches einer Session `none` vermerken, behandelt das Plugin die View als reines Messobjekt: Der Wasserstand liest stattdessen die vom Anbieter gemeldete Zählung (force-Stufe und Auto-Übergabe arbeiten weiter), Fold-Zyklen pausieren, statt Summarizer-Aufrufe zu verbrennen, und das Trim-Banner markiert die Zeile mit `wire=raw` (folds not shipping; watermark reads the tally); Hosts ohne den Surface-Mechanismus (oder mit ausgeschaltetem Flag) behalten genau dieses alte Verhalten.
|
|
137
141
|
|
|
138
|
-
**Host-Kompaktions-Epochen.** Fold-Verweise sind an Nachrichten-IDs und Inhalts-Hashes verankert; ersetzt der Host selbst den erneut gesendeten Verlauf, veralten sämtliche Blöcke auf einmal: keiner findet mehr seine Position, die View fällt still auf den Rohverlauf zurück (fail-open — das Entscheidungsprotokoll vermerkt `view-applied applied=0`), und das Plugin verankert seine Wachstumsbaseline bei der nächsten Anfrage auf der Sicht nach der Kompaktion. Die Host-Kompaktion ist damit die Backstop-Trimschicht; die Plugin-Folds leisten die feingranulare Arbeit innerhalb einer Host-Epoche. Manche Dispatches übergeben vollständig eingefrorene Anfrage-Arrays oder Optionsobjekte; für sie fällt das Plugin fail-open (`injected=none` im Entscheidungsprotokoll), während der veränderliche Dispatch, der die Modellantwort erzeugt, den gefalteten View weiterhin erhält.
|
|
139
142
|
**Wie Folds Cache-Hits bewahren.** Jeder Fold zahlt das Präfix einmal zurück; das Ziel sind amortisierte Kosten, keine perfekte Hit-Rate. Die Engine erzwingt den Cache-Vertrag: Folds sind append-only — die Frontier bewegt sich nur vorwärts, die eingefrorene Zone wird nie wieder angetastet; die View wird deterministisch aus (Historie, Fold-Zustand) neu aufgebaut, sodass das serialisierte Präfix zwischen Folds byte-identisch bleibt und der Anbieter-Cache weiter trifft; Fold-Grenzen trennen nie einen Assistant-Tool-Call von seinem Tool-Ergebnis; die letzten `trimProtectedTail` Nachrichten sind ausgenommen; und alles failt offen — ein interner Fehler wird zum Durchreichen, nie zur kaputten Anfrage.
|
|
140
143
|
|
|
141
144
|
**Komprimierungs-Arbitrage.** Zwei automatische Trimmer über einer Historie würden doppelt zusammenfassen und einander die Frontier zerstören, deshalb setzt `cordis.patch.yml` bei den `dsh-compaction-basic`-Zeilen des Hosts `auto: false`: context-trim wird zum einzigen semantischen Trimmer. Manuelles `/compact` funktioniert weiter, und die Force-Stufen-Übergabe (sie leiht sich genau diesen manuellen Pfad) bleibt unberührt. Overflow-Recovery wandert zum Trim: Der Versuch über dem Fenster scheitert einmal, dann faltet die Notfallstufe die View, sodass der nächste Versuch passt.
|
|
142
145
|
|
|
143
|
-
**Fork-Vererbung.** Eine geforkte Session (Subagent-Fork
|
|
146
|
+
**Fork-Vererbung.** Eine geforkte Session (Subagent-Fork) erbt den Fold-Zustand des Elternteils per Copy-on-Fork — aber nur, wenn der Elter-Zustand existiert und die Historie des Kindes die Frontier des Elternteils tatsächlich auflöst; andernfalls startet das Kind sauber. Eine Vererbung pro Kind, idempotent über Neustarts.
|
|
144
147
|
|
|
145
148
|
**Der Wasserstand liest die View.** Das Wasserstand-Banner meldet die Token-Zahl der ausgehenden View (das, was das Modell nach dem Falten tatsächlich sieht) statt der gespeicherten Zählung — eine stark gefaltete Session pinnt den Wasserstand damit nicht mehr auf der harten Stufe fest.
|
|
146
149
|
|
|
@@ -155,7 +158,7 @@ Alle Schlüssel liegen unter Einstellungen → dsh-switchman; Defaults aus `host
|
|
|
155
158
|
|
|
156
159
|
- Ändert ein DSH-Upgrade die Werks-Preset-Pluginliste, `cordis.patch.yml` aus dem neuen `presets/*.patch.yml` neu synchronisieren (Doctrine-Suffix und die Komprimierungs-Arbitrage — `auto: false` auf den `compaction-basic`-Zeilen — behalten) und neu installieren.
|
|
157
160
|
- Die Protokollzeilen (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) sind bewusst englisch und byte-stabil — nicht lokalisieren.
|
|
158
|
-
- `npm pack --dry-run` muss die auditierte Form mit
|
|
161
|
+
- `npm pack --dry-run` muss die auditierte Form mit 60 Dateien / ~380 kB behalten (~1,26 MB entpackt; `docs/` ist ausgeschlossen).
|
|
159
162
|
|
|
160
163
|
## License
|
|
161
164
|
|
package/README.es.md
CHANGED
|
@@ -14,7 +14,7 @@ Trabajando con DSH, tarde o temprano te topas con dos cosas: la sesión pesa cad
|
|
|
14
14
|
|
|
15
15
|
dsh-switchman es un plugin para [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH). Una vez instalado, el modelo principal deja de «hacerlo todo él solo» y pasa a ser el guardagujas: medir el nivel de agua, elegir el carril, repartir tareas y aceptar el trabajo. No es un modelo nuevo: es un reglamento de despacho enganchado a DSH, más una página de configuración. En concreto hace ocho cosas:
|
|
16
16
|
|
|
17
|
-
**1. Nivel de agua del contexto: la sesión larga no se desborda.** Cada turno contabiliza los tokens de la sesión en vivo, y tres líneas de nivel aprietan por etapas: 80k (soft, ajustable) avisa «toca delegar»; 120k (hard) recorta el presupuesto de lectura por llamada y empuja al cierre; 150k (force) lanza la entrega automática —
|
|
17
|
+
**1. Nivel de agua del contexto: la sesión larga no se desborda.** Cada turno contabiliza los tokens de la sesión en vivo, y tres líneas de nivel aprietan por etapas: 80k (soft, ajustable) avisa «toca delegar»; 120k (hard) recorta el presupuesto de lectura por llamada y empuja al cierre; 150k (force) lanza la entrega automática — escribe el documento de entrega (el registro de sesión de solo añadido es la copia completa), compacta el contexto y despierta la sesión para continuar, sin que el trabajo se corte. Los subagentes en segundo plano que sigan corriendo en el momento de la entrega tampoco se pierden: id, descripción de la tarea y ruta del informe quedan escritos en el documento de entrega, y la sesión que continúa sabe dónde recoger los informes en vez de volver a despachar el trabajo. Cada subagente despachado lleva su propio techo duro independiente: al alcanzarlo, termina con un resumen HANDOFF. Si la intervención automática no te encaja, toma el mando manualmente en cualquier momento: `/ctx-pause` detiene todas las acciones del nivel (la medición sigue corriendo, la línea de nivel en vivo del final pasa a paused — solo deja de actuar), `/ctx-resume` lo devuelve en cualquier momento — tras reiniciar DSH la intervención también vuelve sola, lo sueltas por un rato, no lo apagas para siempre; `/ctx-handover` no espera a que el nivel llegue arriba y lanza esa misma entrega a demanda: escribe el documento de entrega, compacta el contexto, despierta la sesión para continuar (la sesión se conduce primero a la frontera de inactividad, así que el resultado puede tardar unos minutos).
|
|
18
18
|
|
|
19
19
|
**2. Seis pools de despacho: a cada trabajo, su modelo.** Pool ligero (economy, tareas pequeñas en lote), mecánico (mechanical, reescrituras con plantilla), principal (main, código del día a día), de alta dificultad (hard, razonamiento difícil y refactorizaciones a gran escala), multimodal (vision, leer imágenes) y de revisión (review, verificación independiente). En la página de ajustes marcas candidatos, ordenas prioridades (con anclaje opcional a las categorías S/A/B/C) y fijas un effort de razonamiento por ruta — el desplegable de categorías sale de los niveles que ese modelo soporta de verdad, no de tres genéricos. Cada turno, el prompt del modelo principal lleva consigo una tabla de recomendaciones `[SWITCHMAN:POOLS]`, y el trabajo se despacha siguiéndola. El modo de ejecución tiene tres estados: off / advice / enforce (enforce = los modelos fuera del pool se rechazan sin más).
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ dsh-switchman es un plugin para [DeepSeek Harness](https://github.com/deepseek-a
|
|
|
23
23
|
- **Modo de equipo de agentes** — al activarlo se inyecta el reglamento de equipo (delegación por defecto + verificación por niveles + disciplina del tablero de tareas compartido) y se habilitan automáticamente los Agent Teams de DSH: el modelo principal puede reclutar compañeros residentes (`spawn_teammate`), asignarles trabajo en el tablero compartido (`team_task_*`) e intercambiar mensajes con ellos. Hay una disciplina clara sobre cuándo formar equipo: subtareas independientes que puedan ir en paralelo, trabajo abundante y autocontenido, nivel de agua del contexto principal ya alto o necesidad de separar roles; una investigación puntual de un solo uso sigue yendo por subagent. Si vuelves a apagar el interruptor, de las cláusulas de equipo no queda rastro, y las herramientas de equipo no se retiran de las sesiones en marcha.
|
|
24
24
|
- **Sincronizar la lista blanca de modelos de subagentes** — DSH tiene una lista blanca de autorización «permitir que los agentes elijan modelos para subagentes»: una ruta elegida en un pool pero no autorizada hace que el despacho explícito del modelo principal sea rechazado (en modo equipo, se marca con ⚠). Al encender este interruptor, la unión de los seis pools se escribe entera en esa lista blanca — switchman es la única fuente de verdad, sin configurar dos veces. La lista blanca entra en vigor según la instantánea de «nueva sesión»: la sincronización solo afecta a las sesiones abiertas a partir de entonces.
|
|
25
25
|
|
|
26
|
-
La cabecera de la sesión da un feedback visual claro: la insignia ⚡ «equipo autónomo» y ◇ con el modelo real de la sesión actual; mientras hay una entrega automática en marcha, aparece un aviso en vivo: «entrega en curso ·
|
|
26
|
+
La cabecera de la sesión da un feedback visual claro: la insignia ⚡ «equipo autónomo» y ◇ con el modelo real de la sesión actual; mientras hay una entrega automática en marcha, aparece un aviso en vivo: «entrega en curso · escribiendo el documento de entrega / compactación del contexto / continuación despertada».
|
|
27
27
|
|
|
28
28
|
**4. Preferencias de idioma: pregunta una vez, lo recuerda para siempre.** Un desplegable para cada una de las tres: respuestas, comentarios de código y documentos; el ámbito puede ser global o por proyecto (`.switchman/lang.json`). No hace falta configurarlo: la primera vez que se necesite pregunta una sola vez, en el idioma de la interfaz de tu DSH, y una vez recordado, cada sesión lo respeta automáticamente.
|
|
29
29
|
|
|
@@ -75,7 +75,7 @@ La cabecera de la sesión da un feedback visual claro: la insignia ⚡ «equipo
|
|
|
75
75
|
- **Pools de despacho** — seis tarjetas en dos filas de tres: arriba ligero / mecánico / principal; abajo alta dificultad / multimodal / revisión. Cada tarjeta agrupa los modelos candidatos por proveedor; marca «orden manual» y se convierte en una lista de prioridades numerada que se reordena con ↑ ↓ ×; junto a cada ruta puedes fijar el effort de razonamiento (por defecto «seguir el carril»). La línea de resumen superior se actualiza en vivo; en la captura: «pools configurados: 4/6 · posiciones en el ranking: 2 · modo advice».
|
|
76
76
|
- **Orden por capacidad + modo de ejecución** — la unión de los modelos elegidos en los seis pools, ordenada por capacidad y con los más fuertes delante (en la captura glm-5.3 anclado en S y glm-5.3-flash anclado en A); se puede reordenar y recortar; el modo de ejecución va de advice / enforce (enforce = los modelos fuera del pool se rechazan sin más).
|
|
77
77
|
- **Equipo de agentes** — los dos interruptores, modo de equipo y sincronización de la lista blanca, vienen apagados; en la captura están encendidos, y debajo de cada uno hay una línea de estado de sincronización.
|
|
78
|
-
- **Nivel de agua del contexto** — los tres umbrales (en la captura 80000 / 120000 / 150000), el presupuesto de lectura por llamada (3000), el comportamiento del umbral duro (dejar pasar limitando / bloquear), el interruptor de entrega automática y el techo independiente para subagentes: todo en esta zona. Abajo, una línea de comandos: `/ctx-pause` pausa la intervención · `/ctx-resume` la reanuda · `/ctx-handover`
|
|
78
|
+
- **Nivel de agua del contexto** — los tres umbrales (en la captura 80000 / 120000 / 150000), el presupuesto de lectura por llamada (3000), el comportamiento del umbral duro (dejar pasar limitando / bloquear), el interruptor de entrega automática y el techo independiente para subagentes: todo en esta zona. Abajo, una línea de comandos: `/ctx-pause` pausa la intervención · `/ctx-resume` la reanuda · `/ctx-handover` escribe el documento y entrega ahora mismo (conduce la sesión a la frontera de inactividad antes de compactar; el resultado puede tardar unos minutos).
|
|
79
79
|
- **Enrutado por intención** — el interruptor maestro, la ruta de modelo pequeño del clasificador, el tipo de clasificador (auto / decision / chat), la lista de candidatos independiente (cada uno con su nota de capacidades), la ventana de caché / umbral de confianza / timeout / presupuesto de historial y un modelo de respaldo opcional. Al activarlo, el selector de modelos gana la entrada localizada «Automático (enrutado por intención)» y sobre el cuadro de entrada aparece el chip con el modelo en ruta y la confianza.
|
|
80
80
|
|
|
81
81
|
4. **Verificar** — en la cabecera de la sesión aparece la insignia ⚡ «equipo autónomo» (al lado, ◇ muestra el modelo de la sesión actual); o pregúntale directamente al modelo «¿cómo se titula la última sección de tu system prompt?» — debería mencionar el reglamento de dsh-switchman.
|
|
@@ -96,7 +96,7 @@ Esto es todo el conjunto de valores tras una instalación nueva (fuente autorita
|
|
|
96
96
|
|
|
97
97
|
**Pools de despacho**: los seis carriles (economy/mechanical/main/hard/vision/review) arrancan sin candidatos (= los modelos por defecto del sistema, sin intervenir); el orden manual y el effort fijado, apagados/vacíos; `dispatchEnforce` = `advice` (solo aconseja, no obliga).
|
|
98
98
|
|
|
99
|
-
**Nivel de agua del contexto**: soft `80000` / hard `120000` / force `150000` tokens; presupuesto de lectura por llamada `3000`; conducta al pasarse del presupuesto `cap` (recorta y avisa); `wmAutoHandover` = encendido (en force,
|
|
99
|
+
**Nivel de agua del contexto**: soft `80000` / hard `120000` / force `150000` tokens; presupuesto de lectura por llamada `3000`; conducta al pasarse del presupuesto `cap` (recorta y avisa); `wmAutoHandover` = encendido (en force, escritura del documento de entrega + compactación automáticas); el techo duro de subagentes = encendido (150k compartidas).
|
|
100
100
|
|
|
101
101
|
**Agent Teams**: `teamsMode` = apagado; `syncWhitelist` = apagado (los dos interruptores son independientes entre sí).
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Esto es todo el conjunto de valores tras una instalación nueva (fuente autorita
|
|
|
104
104
|
|
|
105
105
|
**Recorte de contexto**: `trimEnabled` = encendido; `trimMode` = `auto` (totalmente automático); compuerta de crecimiento `22500` + incremento `50000` tokens; presión `60%` / emergencia `95%`; cola protegida `6` mensajes; tope de cadencia de folds `6` por hora; modelo secundario sin definir (hereda el modelo de la sesión) — detalles en la sección «Recorte automático del contexto» más abajo.
|
|
106
106
|
|
|
107
|
-
**Notas de serie**: ① que el enrutado por intención no venga disponible de serie es intencionado: tres pasos para activarlo (clasificador, candidatos, interruptor); ② la ventana efectiva de Auto vale 200000 de serie — la barrera de seguridad garantiza 0.8×ventana ≥ force (150000), así que la línea de compactación del núcleo (160000) queda siempre por detrás de la línea de entrega suave (150000); ③ lo más perceptible de serie es el trío de niveles: 80k avisa de delegar / 120k aprieta la lectura / 150k
|
|
107
|
+
**Notas de serie**: ① que el enrutado por intención no venga disponible de serie es intencionado: tres pasos para activarlo (clasificador, candidatos, interruptor); ② la ventana efectiva de Auto vale 200000 de serie — la barrera de seguridad garantiza 0.8×ventana ≥ force (150000), así que la línea de compactación del núcleo (160000) queda siempre por detrás de la línea de entrega suave (150000); ③ lo más perceptible de serie es el trío de niveles: 80k avisa de delegar / 120k aprieta la lectura / 150k entrega automáticamente (documento + compactación) — sin tocar ningún ajuste.
|
|
108
108
|
|
|
109
109
|
## Recorte automático del contexto
|
|
110
110
|
|
|
@@ -114,7 +114,7 @@ Niveles de automatización (`trimMode`):
|
|
|
114
114
|
|
|
115
115
|
- **`off`** — solo medir: el muestreo de uso y de aciertos de caché sigue funcionando; sin banner ni folds.
|
|
116
116
|
- **`advisory`** — el modelo de la sesión se pliega a sí mismo: se exponen las herramientas `ctx_trim_fold` y `ctx_trim_status` más la cabecera de protocolo.
|
|
117
|
-
- **`auto`** (predeterminado) — todo lo anterior más folds automáticos en el límite de inactividad, en tres escalones: una compuerta de crecimiento (crecimiento
|
|
117
|
+
- **`auto`** (predeterminado) — todo lo anterior más folds automáticos en el límite de inactividad, en tres escalones: una compuerta de crecimiento (crecimiento > `trimGrowthTokens` medido desde el mínimo tras el último plegado — el ancla que mantiene la compuerta activa tras plegados que confirman en puntos altos de la view — Y un incremento comprimible contiguo ≥ `trimIncrementTokens`), un escalón de presión (`trimPressurePercent` de la ventana de contexto) y un escalón de emergencia (`trimEmergencyPercent` — un fold mecánico con su propio enfriamiento).
|
|
118
118
|
|
|
119
119
|
Todas las claves viven en Ajustes → dsh-switchman; los valores por defecto salen de `host/config.js`:
|
|
120
120
|
|
|
@@ -131,16 +131,19 @@ Todas las claves viven en Ajustes → dsh-switchman; los valores por defecto sal
|
|
|
131
131
|
| `trimMaxFoldsPerHour` | `6` | Tope de cadencia de folds por hora móvil para el modelo secundario (los de emergencia quedan exentos). |
|
|
132
132
|
| `trimSideModel` | sin definir | Ruta del modelo secundario que escribe los resúmenes. Vacía = heredar el modelo actual de la sesión. |
|
|
133
133
|
| `trimStateDir` | sin definir | Anula el directorio del estado de folds. Vacía = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
| `surfaceFold` | `true` | Envía los folds confirmados a la superficie de la sesión (par de eventos de medición shadow-price + replace con `surfaceOp`). Apagado conserva la vista de solo empalme. |
|
|
134
135
|
|
|
135
|
-
**Rutas de activación.** Las comprobaciones de escalones se ejecutan en el límite de inactividad y, como respaldo para hosts donde los eventos de estado de inactividad son inalcanzables, tras cada finalización del flujo del modelo (limitadas a una evaluación cada 60 s por sesión). Cada decisión — folds y no-ops por igual — se añade como una línea
|
|
136
|
+
**Rutas de activación.** Las comprobaciones de escalones se ejecutan en el límite de inactividad y, como respaldo para hosts donde los eventos de estado de inactividad son inalcanzables, tras cada finalización del flujo del modelo (limitadas a una evaluación cada 60 s por sesión). Cada decisión — folds y no-ops por igual — se añade como una línea `key=value` con marca de tiempo a `decisions.log` en el directorio del estado de folds (véase `trimStateDir`), dando a los folds una pista de auditoría fuera de línea; el vocabulario de filas (`view-applied`, filas de decisión/resultado de folds, `surface-replace`, `surface-replace skipped reason=…`) está catalogado en [docs/context-trim.md](./docs/context-trim.md).
|
|
136
137
|
|
|
138
|
+
**Verdad del cable y estado estacionario.** Las filas de decisión llevan `view=<n>` y, una vez que una respuesta ha llegado, `wire=<n>` — el prompt real del proveedor (entrada sin caché + lectura de caché + escritura de caché, muestreado del evento de uso del stream). La estimación de la view cuenta solo el array de mensajes y siempre lee menos que el cable por la sobrecarga fija (medida ≈ 17.3k: system prompt + esquemas de herramientas + persona), así que los escalones de presión y emergencia evalúan sobre `max(view, wire)`, y solo `wire` es una lectura del tamaño del prompt. En una ventana de 150k, el diente de sierra sano marca el cable en ≈ 40k justo después de un fold ↔ 88–90k en el siguiente (≈27%–60% de la ventana), un fold por cada ~50k de crecimiento bruto, con el techo fijado cerca de 90k por el escalón de presión y no por la ventana. Si `view` sube sin que aparezca nunca una fila `surface-replace`, lee las filas de omisión (`incomplete-seqs`, `no-service`, `compaction-lock`).
|
|
139
|
+
|
|
140
|
+
**Épocas de compactación del host.** Las referencias de fold se anclan en ids de mensaje y hashes de contenido, de modo que una compactación del propio host que reemplace el historial reenviado hace envejecer el libro entero de golpe: ningún bloque localiza su posición, la vista retrocede silenciosamente al historial sin plegar (fail-open — el registro de decisiones anota `view-applied applied=0`) y el plugin reancla su línea base de crecimiento en la vista posterior a la compactación en la siguiente petición. La compactación del host es así la capa de recorte de último recurso; los folds del plugin hacen el trabajo fino dentro de una época del host. Algunos despachos entregan matrices de solicitud u objetos de opciones totalmente congelados (el bucle de agente actual congela en profundidad las peticiones ya montadas); para ellos, `injectView` informa del resultado en el registro de decisiones: `nothing-to-apply` (no hay bloques de fold localizados — el historial sin plegar ES la vista), `in-place`/`swapped` (la vista plegada viajó con la petición) o `none` (había un fold, pero el despacho congelado no podía llevarlo — por el cable va el historial sin plegar). **El reemplazo de superficie es la ruta de envío cuando está disponible** (`surfaceFold`, activado por defecto): en el límite serial `agent/turn-stopping` más un barrido de inactividad, el plugin añade el evento de medición shadow-price al estilo del host y UN reemplazo `user/message` que lleva `surfaceOp {op:'replace', startSeq, endSeq}` con `sourceEventSeqs` cubriendo cada nodo de superficie sombreado — el mismo mecanismo que usa la propia compactación del host —, de modo que un fold confirmado llega al cable desde el nivel de origen, despachos congelados incluidos. Mientras los despachos recientes de una sesión registran `none`, el plugin trata la vista como solo-medición: el nivel de agua mide en su lugar la cuenta que reporta el proveedor (el escalón force y la entrega automática siguen funcionando), los ciclos de fold se pausan en vez de quemar llamadas al resumidor, y el banner de recorte marca la línea con `wire=raw` (folds not shipping; watermark reads the tally); los hosts sin el mecanismo de superficie (o con la opción apagada) se quedan exactamente con ese comportamiento antiguo.
|
|
137
141
|
|
|
138
|
-
**Épocas de compactación del host.** Las referencias de fold se anclan en ids de mensaje y hashes de contenido, de modo que una compactación del propio host que reemplace el historial reenviado hace envejecer el libro entero de golpe: ningún bloque localiza su posición, la vista retrocede silenciosamente al historial sin plegar (fail-open — el registro de decisiones anota `view-applied applied=0`) y el plugin reancla su línea base de crecimiento en la vista posterior a la compactación en la siguiente petición. La compactación del host es así la capa de recorte de último recurso; los folds del plugin hacen el trabajo fino dentro de una época del host. Algunos despachos entregan matrices de solicitud u objetos de opciones totalmente congelados; para ellos el plugin falla abiertamente (`injected=none` en el registro de decisiones), mientras que el despacho mutable que produce la respuesta del modelo sigue recibiendo la vista plegada.
|
|
139
142
|
**Cómo los folds conservan los aciertos de caché.** Cada fold repaga el prefijo una vez; el objetivo es el coste amortizado, no una tasa de aciertos perfecta. El motor hace cumplir el contrato de caché: los folds son de solo añadir — la frontier solo avanza y la zona congelada no se vuelve a editar; la view se reconstruye de forma determinista a partir de (historial, estado de folds), de modo que el prefijo serializado queda idéntico byte a byte entre folds y la caché del proveedor sigue acertando; los límites de fold jamás separan una tool-call del assistant de su resultado; los últimos `trimProtectedTail` mensajes quedan exentos; y todo falla abierto — un error interno degenera en paso a través, nunca en una petición rota.
|
|
140
143
|
|
|
141
144
|
**Arbitraje de compactación.** Dos recortadores automáticos sobre un mismo historial se resumirían dos veces y destruirían la frontier mutuamente, así que `cordis.patch.yml` pone `auto: false` en las filas de `dsh-compaction-basic` del host: context-trim pasa a ser el único recortador semántico. El `/compact` manual sigue funcionando, y la entrega del escalón force (que toma prestado justamente ese camino manual) queda intacta. La recuperación de desbordamiento pasa al trim: el intento que excede la ventana falla una vez, luego el escalón de emergencia pliega la view para que el siguiente intento quepa.
|
|
142
145
|
|
|
143
|
-
**Herencia en forks.** Una sesión forkeada (fork de subagente
|
|
146
|
+
**Herencia en forks.** Una sesión forkeada (fork de subagente) hereda el estado de folds del padre por copia al forkear — pero solo si el estado del padre existe y el historial del hijo realmente resuelve la frontier del padre; si no, el hijo arranca limpio. Una herencia por hijo, idempotente entre reinicios.
|
|
144
147
|
|
|
145
148
|
**El banner de niveles lee la view.** El banner de niveles informa del recuento de tokens de la view saliente (lo que el modelo ve de verdad tras el plegado) en lugar del recuento almacenado, así una sesión muy plegada ya no clava el nivel de agua en el escalón hard.
|
|
146
149
|
|
|
@@ -155,7 +158,7 @@ Todas las claves viven en Ajustes → dsh-switchman; los valores por defecto sal
|
|
|
155
158
|
|
|
156
159
|
- Si tras una actualización de DSH cambia la lista de plugins de los presets de fábrica, resincroniza `cordis.patch.yml` desde los nuevos `presets/*.patch.yml` (conserva el doctrine suffix y el arbitraje de compactación — `auto: false` en las filas de `compaction-basic`) y reinstala.
|
|
157
160
|
- Las líneas de protocolo (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) están deliberadamente en inglés y son estables byte a byte — no las localices.
|
|
158
|
-
- `npm pack --dry-run` debe mantenerse en la forma auditada de
|
|
161
|
+
- `npm pack --dry-run` debe mantenerse en la forma auditada de 60 archivos / ~380 kB (~1,26 MB descomprimido; `docs/` queda excluido).
|
|
159
162
|
|
|
160
163
|
## License
|
|
161
164
|
|
package/README.fr.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
dsh-switchman est un plugin pour [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH). Une fois installé, le modèle principal passe de « tout faire lui-même » au rôle de répartiteur : mesurer le niveau d'eau, choisir le couloir, distribuer les tâches, contrôler le résultat. Ce n'est pas un nouveau modèle — c'est une doctrine d'orchestration accrochée à DSH, accompagnée d'une page de réglages. Concrètement, il fait huit choses :
|
|
16
16
|
|
|
17
|
-
**1. Niveau d'eau du contexte : les longues sessions ne débordent jamais.** Chaque tour compte en direct les tokens de la session et les confronte à trois lignes d'eau qui durcissent par paliers : 80k (soft, réglable) rappelle qu'« il est temps de déléguer » ; 120k (hard) resserre le budget de lecture par appel et pousse à conclure ; 150k (force) déclenche la remise automatique —
|
|
17
|
+
**1. Niveau d'eau du contexte : les longues sessions ne débordent jamais.** Chaque tour compte en direct les tokens de la session et les confronte à trois lignes d'eau qui durcissent par paliers : 80k (soft, réglable) rappelle qu'« il est temps de déléguer » ; 120k (hard) resserre le budget de lecture par appel et pousse à conclure ; 150k (force) déclenche la remise automatique — le document de remise est écrit (le journal de session à ajout seul constitue la sauvegarde complète), le contexte compacté, la session réveillée pour continuer, et la tâche ne s'interrompt jamais. Les subagents d'arrière-plan encore en course à cet instant ne sont pas perdus pour autant : leurs id, descriptions de tâche et chemins de rapport sont consignés dans le document de remise, et la session relancée sait où récupérer les rapports au lieu de redéspatcher en double. Chaque subagent dispatché embarque son propre plafond strict ; une fois atteint, il écrit son résumé HANDOFF et se retire. Quand l'intervention automatique ne vous convient pas, reprenez la main à tout moment : `/ctx-pause` arrête toutes les actions de niveau (la mesure continue, la ligne d'eau en direct de la fin passe en paused — il n'agit plus, c'est tout), `/ctx-resume` rétablit à tout moment — après un redémarrage de DSH, l'intervention revient aussi d'elle-même, un lâcher-prise temporaire, pas une extinction définitive ; `/ctx-handover` n'attend pas que le niveau touche le plafond et déclenche à la demande la même remise : écrire le document de remise, compacter le contexte, réveiller la session pour continuer (la session est d'abord conduite jusqu'à la limite d'inactivité, le résultat peut donc prendre quelques minutes).
|
|
18
18
|
|
|
19
19
|
**2. Six pools de dispatch : le bon modèle pour chaque tâche.** Un pool léger (economy, les petites tâches en série), un pool mécanique (mechanical, les réécritures sur gabarit), un pool principal (main, le code au quotidien), un pool haute difficulté (hard, raisonnement corsé et refontes à grande échelle), un pool multimodal (vision, lire les images) et un pool de relecture (review, vérification indépendante). Dans la page de réglages, vous cochez les candidats, les classez par priorité (avec tiers S/A/B/C en option) et épinglez un effort de raisonnement pour chaque route — le menu déroulant des niveaux reflète ce que ce modèle supporte réellement, pas trois niveaux génériques. Chaque prompt du modèle principal embarque une table de recommandations `[SWITCHMAN:POOLS]`, et le dispatch suit cette table. Le mode d'exécution a trois états : off / advice / enforce (enforce = tout modèle hors pool est refusé sans appel).
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ dsh-switchman est un plugin pour [DeepSeek Harness](https://github.com/deepseek-
|
|
|
23
23
|
- **Mode équipe d'agents** — l'activer injecte la doctrine d'équipe (délégation par défaut + vérification par paliers + discipline du tableau de tâches partagé) et active automatiquement les Agent Teams de DSH : le modèle principal peut recruter des coéquipiers permanents (`spawn_teammate`), confier du travail au tableau de tâches partagé (`team_task_*`) et échanger des messages avec eux. Le moment de constituer une équipe obéit à une discipline explicite : sous-tâches indépendantes parallélisables, gros lots autoportants, contexte principal déjà bien chargé, besoin de séparer les rôles ; les enquêtes ponctuelles restent du ressort du subagent. Refermer l'interrupteur ne laisse aucun résidu des clauses d'équipe, et ne retire jamais les outils d'équipe aux sessions déjà en cours.
|
|
24
24
|
- **Synchronisation de la liste blanche des modèles de subagents** — DSH tient une liste d'autorisation « modèles qu'un agent peut choisir pour ses subagents » : une route cochée dans un pool mais jamais autorisée se voit refuser le dispatch quand le modèle principal la désigne nommément (en mode équipe, elle est marquée d'un ⚠). Activez cet interrupteur et l'union des six pools est d'un coup écrite dans cette liste — switchman reste l'unique source de vérité, fini la double configuration. La liste blanche s'applique par instantané à chaque nouvelle session : la synchronisation ne concerne que les sessions ouvertes ensuite.
|
|
25
25
|
|
|
26
|
-
L'en-tête de session donne un retour immédiat : un badge ⚡ « équipe autonome » et une puce ◇ indiquant le modèle réellement utilisé par la session ; pendant une remise automatique, une bannière en direct annonce « remise en cours ·
|
|
26
|
+
L'en-tête de session donne un retour immédiat : un badge ⚡ « équipe autonome » et une puce ◇ indiquant le modèle réellement utilisé par la session ; pendant une remise automatique, une bannière en direct annonce « remise en cours · écriture du document de remise / compactage du contexte / réveil de la continuation ».
|
|
27
27
|
|
|
28
28
|
**4. Préférences de langue : une question posée une fois, retenue pour toujours.** Un menu déroulant chacun pour les réponses, les commentaires de code et la documentation, avec un scope global ou par projet (`.switchman/lang.json`). Ne rien régler est permis — au premier besoin, on vous pose la question une fois dans la langue de votre interface DSH, la réponse est retenue, et chaque session suivante s'y conforme automatiquement.
|
|
29
29
|
|
|
@@ -75,7 +75,7 @@ Un seul modèle ? Ça vaut quand même l'installation — le contrôle du niveau
|
|
|
75
75
|
- **Pools de dispatch** — six cartes sur deux rangées de trois : en haut léger / mécanique / principal ; en bas haute difficulté / multimodal / révision. Chaque carte coche les modèles candidats groupés par fournisseur ; cochez « ordre manuel » et elle devient une liste de priorités numérotée, à réordonner avec ↑ ↓ × ; chaque route peut épingler un effort de raisonnement (par défaut « suivre le couloir »). La ligne de résumé en haut se met à jour en direct ; sur la capture : « 4/6 pools configurés · 2 classés · mode advice ».
|
|
76
76
|
- **Classement des capacités + mode d'exécution** — l'union des modèles cochés dans les six pools, classée par capacité, les plus forts devant (sur la capture glm-5.3 ancré S et glm-5.3-flash ancré A) ; on peut réordonner et retirer ; le mode d'exécution va de advice / enforce (enforce = tout modèle hors pool est refusé sans appel).
|
|
77
77
|
- **Équipe d'agents** — les deux interrupteurs, mode équipe et synchronisation de la liste blanche, arrivent désactivés ; sur la capture ils sont activés, avec sous chacun une ligne d'état de synchronisation.
|
|
78
|
-
- **Niveau d'eau du contexte** — les trois seuils (sur la capture 80000 / 120000 / 150000), le budget de lecture par appel (3000), le comportement du palier hard (passage à débit limité / blocage), l'interrupteur de remise automatique et le plafond indépendant des subagents : tout tient dans cette zone. La ligne du bas porte les commandes : `/ctx-pause` suspend les interventions · `/ctx-resume` reprend · `/ctx-handover`
|
|
78
|
+
- **Niveau d'eau du contexte** — les trois seuils (sur la capture 80000 / 120000 / 150000), le budget de lecture par appel (3000), le comportement du palier hard (passage à débit limité / blocage), l'interrupteur de remise automatique et le plafond indépendant des subagents : tout tient dans cette zone. La ligne du bas porte les commandes : `/ctx-pause` suspend les interventions · `/ctx-resume` reprend · `/ctx-handover` écrit le document et remet immédiatement (il conduit la session jusqu'à une limite d'inactivité avant de compacter — le résultat peut prendre quelques minutes).
|
|
79
79
|
- **Routage par intention** — l'interrupteur général, la route du petit modèle classifieur, le type de classifieur (auto / decision / chat), la liste de candidats indépendante (chacun avec sa note de capacité), la fenêtre de cache / seuil de confiance / timeout / budget d'historique et un modèle de repli facultatif. Une fois activé, le sélecteur de modèles gagne l'entrée localisée « Automatique (routage par intention) », et une pastille au-dessus du champ de saisie affiche le modèle routé et la confiance.
|
|
80
80
|
|
|
81
81
|
4. **Vérifier** — un badge ⚡ « équipe autonome » apparaît dans l'en-tête de session (avec à côté une puce ◇ montrant le modèle de la session en cours) ; ou demandez simplement au modèle « quel est le titre du dernier paragraphe de ton prompt système » — la réponse doit mentionner la doctrine dsh-switchman.
|
|
@@ -96,7 +96,7 @@ Voici l'ensemble complet des valeurs juste après une installation neuve (source
|
|
|
96
96
|
|
|
97
97
|
**Pools de dispatch** : les six couloirs (economy/mechanical/main/hard/vision/review) démarrent sans candidats (= les modèles par défaut du système, aucune intervention) ; l'ordre manuel et l'effort épinglé sont désactivés/vides ; `dispatchEnforce` = `advice` (simple recommandation, rien n'est forcé).
|
|
98
98
|
|
|
99
|
-
**Niveau d'eau du contexte** : soft `80000` / hard `120000` / force `150000` tokens ; budget de lecture par appel `3000` ; comportement en cas de dépassement `cap` (tronquer avec avertissement) ; `wmAutoHandover` = activé (à force,
|
|
99
|
+
**Niveau d'eau du contexte** : soft `80000` / hard `120000` / force `150000` tokens ; budget de lecture par appel `3000` ; comportement en cas de dépassement `cap` (tronquer avec avertissement) ; `wmAutoHandover` = activé (à force, écriture du document de remise + compactage automatiques) ; le plafond strict des subagents = activé (150k partagées).
|
|
100
100
|
|
|
101
101
|
**Agent Teams** : `teamsMode` = désactivé ; `syncWhitelist` = désactivé (les deux interrupteurs sont indépendants l'un de l'autre).
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Voici l'ensemble complet des valeurs juste après une installation neuve (source
|
|
|
104
104
|
|
|
105
105
|
**Trim de contexte** : `trimEnabled` = activé ; `trimMode` = `auto` (entièrement automatique) ; porte de croissance `22500` + incrément `50000` tokens ; pression `60%` / urgence `95%` ; queue protégée `6` messages ; plafond de cadence des folds `6` par heure ; modèle annexe non défini (hérite du modèle de la session) — détails dans la section « Trim automatique du contexte » ci-dessous.
|
|
106
106
|
|
|
107
|
-
**À savoir dès l'installation** : ① l'indisponibilité du routage par intention en sortie d'usine est un choix délibéré — trois étapes pour l'activer (classifieur, candidats, interrupteur) ; ② la fenêtre effective d'Auto vaut 200000 dès l'usine — le garde-fou garantit 0.8×fenêtre ≥ force (150000), si bien que la ligne de compactage cœur (160000) se situe toujours après la ligne de remise en douceur (150000) ; ③ l'effet le plus tangible dès l'usine est le trio de niveaux : 80k rappelle de déléguer / 120k resserre la lecture / 150k
|
|
107
|
+
**À savoir dès l'installation** : ① l'indisponibilité du routage par intention en sortie d'usine est un choix délibéré — trois étapes pour l'activer (classifieur, candidats, interrupteur) ; ② la fenêtre effective d'Auto vaut 200000 dès l'usine — le garde-fou garantit 0.8×fenêtre ≥ force (150000), si bien que la ligne de compactage cœur (160000) se situe toujours après la ligne de remise en douceur (150000) ; ③ l'effet le plus tangible dès l'usine est le trio de niveaux : 80k rappelle de déléguer / 120k resserre la lecture / 150k remet automatiquement (document + compactage) — sans aucun réglage.
|
|
108
108
|
|
|
109
109
|
## Trim automatique du contexte
|
|
110
110
|
|
|
@@ -114,7 +114,7 @@ Niveaux d'automatisation (`trimMode`) :
|
|
|
114
114
|
|
|
115
115
|
- **`off`** — mesure seule : l'échantillonnage de l'usage et des hits de cache tourne toujours ; pas de bannière, pas de folds.
|
|
116
116
|
- **`advisory`** — le modèle de session se replie lui-même : les outils `ctx_trim_fold` et `ctx_trim_status` plus l'en-tête de protocole sont exposés.
|
|
117
|
-
- **`auto`** (par défaut) — tout ce qui précède, plus des folds automatiques à la frontière d'inactivité, en trois paliers : une porte de croissance (croissance
|
|
117
|
+
- **`auto`** (par défaut) — tout ce qui précède, plus des folds automatiques à la frontière d'inactivité, en trois paliers : une porte de croissance (croissance > `trimGrowthTokens` mesurée depuis le point bas après le dernier pli — l'ancre qui garde la porte armée après des plis confirmés à des points hauts de la view — ET un incrément compressible contigu ≥ `trimIncrementTokens`), un palier de pression (`trimPressurePercent` de la fenêtre de contexte) et un palier d'urgence (`trimEmergencyPercent` — un fold mécanique avec son propre refroidissement).
|
|
118
118
|
|
|
119
119
|
Toutes les clés vivent dans Réglages → dsh-switchman ; les valeurs par défaut viennent de `host/config.js` :
|
|
120
120
|
|
|
@@ -131,16 +131,19 @@ Toutes les clés vivent dans Réglages → dsh-switchman ; les valeurs par défa
|
|
|
131
131
|
| `trimMaxFoldsPerHour` | `6` | Plafond de cadence des folds par heure glissante pour le modèle annexe (les folds d'urgence en sont exemptés). |
|
|
132
132
|
| `trimSideModel` | non définie | Route du modèle annexe qui écrit les résumés. Vide = hériter du modèle courant de la session. |
|
|
133
133
|
| `trimStateDir` | non défini | Redéfinit le répertoire d'état des folds. Vide = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
| `surfaceFold` | `true` | Expédie les folds validés sur la surface de session (paire d'événements : mesure shadow-price + remplacement `surfaceOp`). Désactivé, la vue reste en splice seul. |
|
|
134
135
|
|
|
135
|
-
**Chemins de déclenchement.** Les vérifications de paliers s'exécutent à la frontière d'inactivité et, en repli pour les hôtes où les événements d'état d'inactivité sont inaccessibles, après chaque fin de flux du modèle (limitées à une évaluation par 60 s et par session). Chaque décision — folds comme no-ops — est ajoutée comme une ligne
|
|
136
|
+
**Chemins de déclenchement.** Les vérifications de paliers s'exécutent à la frontière d'inactivité et, en repli pour les hôtes où les événements d'état d'inactivité sont inaccessibles, après chaque fin de flux du modèle (limitées à une évaluation par 60 s et par session). Chaque décision — folds comme no-ops — est ajoutée comme une ligne `key=value` horodatée à `decisions.log` dans le répertoire d'état des folds (voir `trimStateDir`), donnant aux folds une piste d'audit hors ligne; le vocabulaire des lignes (`view-applied`, lignes de décision/résultat de fold, `surface-replace`, `surface-replace skipped reason=…`) est catalogué dans [docs/context-trim.md](./docs/context-trim.md).
|
|
136
137
|
|
|
138
|
+
**Vérité du fil et régime stationnaire.** Les lignes de décision portent `view=<n>` et, une fois qu'une réponse est arrivée, `wire=<n>` — le prompt réel du fournisseur (entrée non cachée + lecture de cache + écriture de cache, échantillonné depuis l'événement d'usage du stream). L'estimation de la view ne compte que le tableau de messages et lit toujours moins que le fil, du surcoût fixe (mesuré ≈ 17.3k : system prompt + schémas d'outils + persona), donc les paliers de pression et d'urgence évaluent sur `max(view, wire)`, et seul `wire` est une lecture de la taille du prompt. Sur une fenêtre de 150k, la dent de scie saine fait tourner le fil à ≈ 40k juste après un fold ↔ 88–90k au suivant (≈27%–60% de la fenêtre), un fold par ~50k de croissance brute, le plafond étant arrimé près de 90k par le palier de pression plutôt que par la fenêtre. Si `view` monte sans qu'aucune ligne `surface-replace` n'apparaisse jamais, lisez les lignes d'omission (`incomplete-seqs`, `no-service`, `compaction-lock`).
|
|
139
|
+
|
|
140
|
+
**Époques de compactage de l'hôte.** Les références de fold sont ancrées dans les identifiants de messages et les hachages de contenu ; quand l'hôte compacte lui-même l'historique renvoyé, tout le registre vieillit d'un coup : plus aucun bloc ne se localise, la vue retombe silencieusement sur l'historique brut (fail-open — le journal des décisions note `view-applied applied=0`), et le plugin ré-ancre sa base de croissance sur la vue post-compaction à la requête suivante. La compaction de l'hôte est donc la couche de rognage de dernier recours ; les folds du plugin font le travail fin au sein d'une époque de l'hôte. Certains dispatches remettent des tableaux de requête ou des objets d'options entièrement gelés (la boucle d'agent actuelle gèle en profondeur les requêtes assemblées) ; pour eux, `injectView` rapporte l'issue dans le journal des décisions : `nothing-to-apply` (aucun bloc de fold localisé — l'historique brut EST la vue), `in-place`/`swapped` (la vue pliée est partie avec la requête) ou `none` (un fold existait mais le dispatch gelé ne pouvait pas le transporter — l'historique brut part sur le fil). **Le remplacement de surface est le chemin d'expédition quand il est disponible** (`surfaceFold`, activé par défaut) : à la frontière sérielle `agent/turn-stopping` plus un balayage d'inactivité, le plugin ajoute l'événement de mesure shadow-price à la manière de l'hôte et UN remplacement `user/message` portant `surfaceOp {op:'replace', startSeq, endSeq}` avec des `sourceEventSeqs` couvrant chaque nœud de surface masqué — le même mécanisme que celui de la compaction de l'hôte elle-même —, de sorte qu'un fold validé rejoint le fil depuis le niveau source, dispatches gelés compris. Tant que les dispatches récents d'une session consignent `none`, le plugin traite la vue comme une simple mesure : le niveau d'eau lit à la place le total rapporté par le fournisseur (le palier force et la remise automatique continuent de fonctionner), les cycles de fold se mettent en pause au lieu de brûler des appels au résumeur, et la bannière de rognage marque la ligne avec `wire=raw` (folds not shipping; watermark reads the tally) ; les hôtes sans le mécanisme de surface (ou avec l'option désactivée) gardent exactement cet ancien comportement.
|
|
137
141
|
|
|
138
|
-
**Époques de compactage de l'hôte.** Les références de fold sont ancrées dans les identifiants de messages et les hachages de contenu ; quand l'hôte compacte lui-même l'historique renvoyé, tout le registre vieillit d'un coup : plus aucun bloc ne se localise, la vue retombe silencieusement sur l'historique brut (fail-open — le journal des décisions note `view-applied applied=0`), et le plugin ré-ancre sa base de croissance sur la vue post-compaction à la requête suivante. La compaction de l'hôte est donc la couche de rognage de dernier recours ; les folds du plugin font le travail fin au sein d'une époque de l'hôte. Certains dispatches remettent des tableaux de requête ou des objets d'options entièrement gelés ; pour eux le plugin échoue ouvert (`injected=none` dans le journal des décisions), tandis que le dispatch mutable qui produit la réponse du modèle reçoit toujours la vue pliée.
|
|
139
142
|
**Comment les folds préservent les hits de cache.** Chaque fold repaye le préfixe une fois ; l'objectif est le coût amorti, pas un taux de hits parfait. Le moteur fait respecter le contrat de cache : les folds sont en ajout seul — la frontier n'avance que vers l'avant et la zone gelée n'est plus jamais éditée ; la view est reconstruite de façon déterministe depuis (historique, état des folds), donc le préfixe sérialisé reste identique à l'octet entre les folds et le cache du fournisseur continue de toucher ; les frontières de fold ne séparent jamais un tool-call d'assistant de son résultat ; les `trimProtectedTail` derniers messages sont exemptés ; et tout échoue ouvert — une erreur interne se dégrade en passage à travers, jamais en requête cassée.
|
|
140
143
|
|
|
141
144
|
**Arbitrage du compactage.** Deux mécanismes de trim automatiques sur un même historique résumeraient tout deux fois et détruiraient mutuellement leur frontier, donc `cordis.patch.yml` met `auto: false` sur les lignes `dsh-compaction-basic` de l'hôte : context-trim devient l'unique trimmer sémantique. Le `/compact` manuel continue de marcher, et la remise du palier force (qui emprunte justement ce chemin manuel) reste intacte. La récupération de débordement passe au trim : la tentative au-dessus de la fenêtre échoue une fois, puis le palier d'urgence plie la view pour que la tentative suivante tienne.
|
|
142
145
|
|
|
143
|
-
**Héritage des forks.** Une session forkée (fork de sous-agent
|
|
146
|
+
**Héritage des forks.** Une session forkée (fork de sous-agent) hérite de l'état de folds du parent par copie-au-fork — mais seulement si l'état parent existe et si l'historique de l'enfant résout réellement la frontier du parent ; sinon l'enfant démarre propre. Un héritage par enfant, idempotent entre redémarrages.
|
|
144
147
|
|
|
145
148
|
**La bannière de niveaux lit la view.** La bannière de niveaux rapporte le nombre de tokens de la view sortante (ce que le modèle voit réellement après repli) au lieu du décompte stocké — une session fortement repliée n'épingle donc plus le niveau d'eau au palier hard.
|
|
146
149
|
|
|
@@ -155,7 +158,7 @@ Toutes les clés vivent dans Réglages → dsh-switchman ; les valeurs par défa
|
|
|
155
158
|
|
|
156
159
|
- Si une mise à niveau de DSH change la liste de plugins des presets d'usine, resynchronisez `cordis.patch.yml` depuis les nouveaux `presets/*.patch.yml` (conservez le doctrine suffix et l'arbitrage du compactage — `auto: false` sur les lignes `compaction-basic`), puis réinstallez.
|
|
157
160
|
- Les lignes de protocole (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) restent volontairement en anglais et stables à l'octet — ne les localisez pas.
|
|
158
|
-
- `npm pack --dry-run` doit conserver la forme auditée de
|
|
161
|
+
- `npm pack --dry-run` doit conserver la forme auditée de 60 fichiers / ~380 kB (~1,26 Mo décompressés ; `docs/` est exclu).
|
|
159
162
|
|
|
160
163
|
## License
|
|
161
164
|
|
package/README.it.md
CHANGED
|
@@ -14,7 +14,7 @@ Se lavori con DSH, col passare del tempo ti imbatti in due cose: la sessione pes
|
|
|
14
14
|
|
|
15
15
|
dsh-switchman è un plugin per [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (DSH). Una volta installato, il modello principale smette di «fare tutto da solo» e diventa un dispatcher: misura il livello dell'acqua, sceglie la corsia, assegna i task, verifica il risultato. Non è un nuovo modello: è un regolamento di orchestrazione agganciato a DSH più un'interfaccia di configurazione. In concreto fa otto cose:
|
|
16
16
|
|
|
17
|
-
**1. Livello dell'acqua del contesto: le sessioni lunghe non esplodono.** A ogni turno conta i token della sessione in tempo reale, e tre soglie inaspriscono a gradini: 80k (soft, regolabile) ricorda che «è ora di delegare»; 120k (hard) stringe il budget di lettura per singola chiamata e spinge verso la chiusura; 150k (force) avvia l'handover automatico —
|
|
17
|
+
**1. Livello dell'acqua del contesto: le sessioni lunghe non esplodono.** A ogni turno conta i token della sessione in tempo reale, e tre soglie inaspriscono a gradini: 80k (soft, regolabile) ricorda che «è ora di delegare»; 120k (hard) stringe il budget di lettura per singola chiamata e spinge verso la chiusura; 150k (force) avvia l'handover automatico — scrittura del documento di handover (il log di sessione append-only è la copia completa), contesto compattato, sessione risvegliata per continuare: il task non si interrompe. Nemmeno i subagent in background ancora in corsa al momento del passaggio si perdono: id, descrizione del task e percorso del report finiscono nel documento di handover, così la sessione ripresa sa dove raccogliere i report invece di ri-assegnare lo stesso lavoro. Ogni subagent inviato porta con sé un tetto massimo indipendente e, raggiunto il limite, esce dopo aver scritto il riepilogo HANDOFF. Se l'intervento automatico non ti torna, prendi tu il comando in qualsiasi momento: `/ctx-pause` ferma tutte le azioni della soglia (la misurazione continua, la riga del livello dell'acqua in tempo reale in coda passa a paused — smette solo di agire), `/ctx-resume` ripristina in qualsiasi momento — dopo un riavvio di DSH l'intervento torna anche da solo, un mollare la presa temporaneo, non uno spegnimento definitivo; `/ctx-handover` non aspetta che la soglia tocchi il limite e avvia su richiesta lo stesso handover: scrittura del documento di handover, compattazione del contesto, risveglio della sessione per continuare (la sessione viene prima guidata fino al confine di inattività, quindi il risultato può richiedere qualche minuto).
|
|
18
18
|
|
|
19
19
|
**2. Sei pool di dispatch: a ogni lavoro il suo modello.** Pool leggero (economy, piccoli lavori in serie), pool meccanico (mechanical, riscritture modellate), pool principale (main, coding di tutti i giorni), pool ad alta difficoltà (hard, ragionamento complesso e refactoring su larga scala), pool multimodale (vision, lettura delle immagini), pool di revisione (review, verifica indipendente). Nella pagina delle impostazioni spunti i candidati, ordini le priorità (con fasce opzionali S/A/B/C) e fichi un reasoning effort per ogni route — il menu a tendina elenca i livelli che quel modello supporta davvero, non tre livelli generici. A ogni turno il prompt del modello principale viaggia con una tabella di raccomandazioni `[SWITCHMAN:POOLS]`: si assegna il lavoro seguendo la tabella. La modalità di esecuzione ha tre stati: off / advice / enforce (enforce = i modelli fuori pool vengono rifiutati sul posto).
|
|
20
20
|
|
|
@@ -23,7 +23,7 @@ dsh-switchman è un plugin per [DeepSeek Harness](https://github.com/deepseek-ai
|
|
|
23
23
|
- **Modalità Agent Teams** — una volta attivata, inietta la dottrina di squadra (delega per default + verifica a livelli + disciplina del task board condiviso) e abilita automaticamente gli Agent Teams di DSH: il modello principale può arruolare compagni permanenti (`spawn_teammate`), assegnare lavori al task board condiviso (`team_task_*`) e scambiarsi messaggi con loro. Quando formare la squadra segue una disciplina precisa: sotto-task indipendenti parallelizzabili, lavori voluminosi e autosufficienti, livello dell'acqua del contesto principale già alto, necessità di separare i ruoli; le indagini una-tantum restano al subagent. Ri-spegnendo l'interruttore, le clausole di squadra spariscono senza residui, e gli strumenti di squadra nelle sessioni in corso non vengono ritirati.
|
|
24
24
|
- **Sincronizzazione della whitelist dei modelli per i subagent** — DSH ha una whitelist di autorizzazione «Consenti agli agenti di scegliere i modelli per i subagent»: le route scelte nei pool ma non autorizzate vengono rifiutate se il modello principale le nomina esplicitamente (in modalità squadra, vengono marcate con ⚠). Con questo interruttore attivo, l'unione dei sei pool viene scritta in un colpo solo in quella whitelist — niente configurazione doppia: switchman è l'unica fonte di verità. La whitelist scatta come snapshot alla «nuova sessione»: la sincronizzazione vale solo per le sessioni aperte dopo.
|
|
25
25
|
|
|
26
|
-
L'intestazione della sessione dà un riscontro immediato: badge ⚡ «Squadra autonoma», ◇ modello effettivo della sessione in corso; durante un handover automatico compare un avviso in tempo reale del tipo «Handover in corso ·
|
|
26
|
+
L'intestazione della sessione dà un riscontro immediato: badge ⚡ «Squadra autonoma», ◇ modello effettivo della sessione in corso; durante un handover automatico compare un avviso in tempo reale del tipo «Handover in corso · scrittura del documento di handover / compattazione del contesto / risveglio della continuazione».
|
|
27
27
|
|
|
28
28
|
**4. Preferenze linguistiche: chiede una volta, ricorda per sempre.** Un menu a tendina per ciascuna delle tre lingue — risposte, commenti nel codice, documenti — con ambito a scelta globale o per progetto (`.switchman/lang.json`). Puoi anche non impostarlo: al primo utilizzo ti viene chiesto una volta, nella lingua dell'interfaccia DSH, e da lì in poi ogni sessione lo rispetta da sé.
|
|
29
29
|
|
|
@@ -75,7 +75,7 @@ Un solo modello? Vale comunque la pena installarlo — il controllo del livello
|
|
|
75
75
|
- **Pool di dispatch** — sei schede su due righe da tre: in alto leggero / meccanico / principale; in basso alta difficoltà / multimodale / revisione. In ogni scheda si spuntano i candidati raggruppati per provider; spunta «ordine manuale» e diventa una lista di priorità numerata da riordinare con ↑ ↓ ×; accanto a ogni route puoi fichare il reasoning effort (predefinito «segui la corsia»). La riga di riepilogo in alto si aggiorna in tempo reale; nella schermata: «4/6 pool configurati · 2 in classifica · modalità advice».
|
|
76
76
|
- **Classifica di capacità + modalità di esecuzione** — l'unione dei modelli scelti nei sei pool, ordinata per capacità con i più forti davanti (nella schermata glm-5.3 ancorato in S e glm-5.3-flash ancorato in A); si può riordinare e ridurre; la modalità di esecuzione va da advice / enforce (enforce = i modelli fuori pool vengono rifiutati sul posto).
|
|
77
77
|
- **Squadra di agenti** — i due interruttori, modalità squadra e sincronizzazione della whitelist, partono spenti; nella schermata sono accesi, con sotto una riga di stato della sincronizzazione.
|
|
78
|
-
- **Livello dell'acqua del contesto** — le tre soglie (nella schermata 80000 / 120000 / 150000), il budget di lettura per singola chiamata (3000), il comportamento della soglia hard (passa con limitazione / blocca), l'interruttore dell'handover automatico e il tetto indipendente dei subagent: tutto in quest'area. Una riga di comandi in fondo: `/ctx-pause` sospende gli interventi · `/ctx-resume` li riprende · `/ctx-handover`
|
|
78
|
+
- **Livello dell'acqua del contesto** — le tre soglie (nella schermata 80000 / 120000 / 150000), il budget di lettura per singola chiamata (3000), il comportamento della soglia hard (passa con limitazione / blocca), l'interruttore dell'handover automatico e il tetto indipendente dei subagent: tutto in quest'area. Una riga di comandi in fondo: `/ctx-pause` sospende gli interventi · `/ctx-resume` li riprende · `/ctx-handover` scrive il documento e passa le consegne subito (guida la sessione fino al confine di inattività prima di compattare: il risultato può richiedere alcuni minuti).
|
|
79
79
|
- **Instradamento per intent** — l'interruttore principale, la route del piccolo modello classificatore, il tipo di classificatore (auto / decision / chat), la lista di candidati indipendente (ciascuno con la sua nota di capacità), finestra di cache / soglia di confidenza / timeout / budget di cronologia e un modello di fallback facoltativo. Attivandolo, il selettore dei modelli guadagna la voce localizzata «Automatico (instradamento per intent)» e sopra la casella di input compare la chip con il modello di instradamento e la confidenza.
|
|
80
80
|
|
|
81
81
|
4. **Verifica** — nell'intestazione della sessione compare il badge ⚡ «Squadra autonoma» (accanto, il ◇ mostra il modello della sessione in corso); oppure chiedi direttamente al modello «qual è il titolo dell'ultima sezione del tuo system prompt?» — la risposta dovrebbe menzionare la dottrina dsh-switchman.
|
|
@@ -96,7 +96,7 @@ Questi sono tutti i valori così come si presentano dopo una nuova installazione
|
|
|
96
96
|
|
|
97
97
|
**Pool di dispatch**: le sei corsie (economy/mechanical/main/hard/vision/review) partono senza candidati (= i modelli predefiniti del sistema, nessuna interferenza); ordine manuale ed effort fissato spenti/vuoti; `dispatchEnforce` = `advice` (solo consiglio, niente di imposto).
|
|
98
98
|
|
|
99
|
-
**Livello dell'acqua del contesto**: soft `80000` / hard `120000` / force `150000` token; budget di lettura per singola chiamata `3000`; comportamento oltre budget `cap` (tronca con avviso); `wmAutoHandover` = attivo (a force,
|
|
99
|
+
**Livello dell'acqua del contesto**: soft `80000` / hard `120000` / force `150000` token; budget di lettura per singola chiamata `3000`; comportamento oltre budget `cap` (tronca con avviso); `wmAutoHandover` = attivo (a force, scrittura del documento di handover + compattazione automatiche); il tetto massimo dei subagent = attivo (150k condivisi).
|
|
100
100
|
|
|
101
101
|
**Agent Teams**: `teamsMode` = spento; `syncWhitelist` = spento (i due interruttori sono indipendenti tra loro).
|
|
102
102
|
|
|
@@ -104,7 +104,7 @@ Questi sono tutti i valori così come si presentano dopo una nuova installazione
|
|
|
104
104
|
|
|
105
105
|
**Trim del contesto**: `trimEnabled` = acceso; `trimMode` = `auto` (del tutto automatico); cancello di crescita `22500` + incremento `50000` token; pressione `60%` / emergenza `95%`; coda protetta `6` messaggi; tetto di cadenza dei fold `6` all'ora; modello secondario non impostato (eredita il modello della sessione) — dettagli nella sezione «Trim automatico del contesto» più sotto.
|
|
106
106
|
|
|
107
|
-
**Note di serie**: ① l'instradamento per intent non disponibile di serie è una scelta voluta — tre passi per attivarlo (classificatore, candidati, interruttore); ② la finestra effettiva di Auto vale di serie 200000 — la barriera di sicurezza garantisce 0.8×finestra ≥ force (150000), così la linea di compattazione del cuore (160000) resta sempre dopo la linea di consegna morbida (150000); ③ di serie la cosa più percettibile è il terzetto di soglie: 80k ricorda di delegare / 120k stringe la lettura / 150k
|
|
107
|
+
**Note di serie**: ① l'instradamento per intent non disponibile di serie è una scelta voluta — tre passi per attivarlo (classificatore, candidati, interruttore); ② la finestra effettiva di Auto vale di serie 200000 — la barriera di sicurezza garantisce 0.8×finestra ≥ force (150000), così la linea di compattazione del cuore (160000) resta sempre dopo la linea di consegna morbida (150000); ③ di serie la cosa più percettibile è il terzetto di soglie: 80k ricorda di delegare / 120k stringe la lettura / 150k consegna da sola (documento + compattazione) — senza alcuna impostazione.
|
|
108
108
|
|
|
109
109
|
## Trim automatico del contesto
|
|
110
110
|
|
|
@@ -114,7 +114,7 @@ Livelli di automazione (`trimMode`):
|
|
|
114
114
|
|
|
115
115
|
- **`off`** — solo misura: il campionamento di uso e hit di cache continua; niente banner, niente fold.
|
|
116
116
|
- **`advisory`** — il modello della sessione si ripiega da sé: vengono esposti gli strumenti `ctx_trim_fold` e `ctx_trim_status` più l'intestazione di protocollo.
|
|
117
|
-
- **`auto`** (predefinito) — tutto quanto sopra più fold automatici al confine di inattività, su tre scalini: un cancello di crescita (crescita
|
|
117
|
+
- **`auto`** (predefinito) — tutto quanto sopra più fold automatici al confine di inattività, su tre scalini: un cancello di crescita (crescita > `trimGrowthTokens` misurata dal minimo post-ripiegamento dell'ultimo fold — l'ancora che mantiene il cancello armato dopo ripiegamenti confermati su punti alti della view — E un incremento comprimibile contiguo ≥ `trimIncrementTokens`), uno scalino di pressione (`trimPressurePercent` della finestra di contesto) e uno scalino di emergenza (`trimEmergencyPercent` — un fold meccanico con il proprio raffreddamento).
|
|
118
118
|
|
|
119
119
|
Tutte le chiavi stanno in Impostazioni → dsh-switchman; i valori predefiniti vengono da `host/config.js`:
|
|
120
120
|
|
|
@@ -131,16 +131,19 @@ Tutte le chiavi stanno in Impostazioni → dsh-switchman; i valori predefiniti v
|
|
|
131
131
|
| `trimMaxFoldsPerHour` | `6` | Tetto di cadenza dei fold per ora mobile per il modello secondario (quelli di emergenza ne sono esenti). |
|
|
132
132
|
| `trimSideModel` | non impostata | Route del modello secondario che scrive i riassunti. Vuota = eredita il modello attuale della sessione. |
|
|
133
133
|
| `trimStateDir` | non impostata | Sostituisce la directory dello stato dei fold. Vuota = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
| `surfaceFold` | `true` | Spedisce i fold confermati sulla superficie della sessione (coppia di eventi: misurazione shadow-price + replace `surfaceOp`). OFF mantiene la vista a solo splice. |
|
|
134
135
|
|
|
135
|
-
**Percorsi di attivazione.** I controlli degli scalini girano al confine di inattività e, come ripiego per gli host dove gli eventi di stato di inattività non sono raggiungibili, dopo ogni completamento del flusso del modello (limitati a una valutazione ogni 60 s per sessione). Ogni decisione — fold e no-op allo stesso modo — viene aggiunta come una riga
|
|
136
|
+
**Percorsi di attivazione.** I controlli degli scalini girano al confine di inattività e, come ripiego per gli host dove gli eventi di stato di inattività non sono raggiungibili, dopo ogni completamento del flusso del modello (limitati a una valutazione ogni 60 s per sessione). Ogni decisione — fold e no-op allo stesso modo — viene aggiunta come una riga `key=value` con timestamp a `decisions.log` nella directory dello stato dei fold (vedi `trimStateDir`), dando ai fold una traccia di audit offline; il vocabolario delle righe (`view-applied`, righe di decisione/esito dei fold, `surface-replace`, `surface-replace skipped reason=…`) è catalogato in [docs/context-trim.md](./docs/context-trim.md).
|
|
136
137
|
|
|
138
|
+
**Verità del filo e stato stazionario.** Le righe di decisione portano `view=<n>` e, una volta arrivata una risposta, `wire=<n>` — il prompt reale del provider (input non in cache + lettura cache + scrittura cache, campionato dall'evento di utilizzo dello stream). La stima della view conta solo l'array di messaggi e legge sempre meno del filo, della misura dell'overhead fisso (misurato ≈ 17.3k: system prompt + schemi degli strumenti + persona), quindi gli scalini di pressione e di emergenza valutano su `max(view, wire)`, e solo `wire` è una lettura della dimensione del prompt. Su una finestra da 150k l'andamento a dente di sega sano porta il filo a ≈ 40k subito dopo un fold ↔ 88–90k al successivo (≈27%–60% della finestra), un fold ogni ~50k di crescita grezza, con il tetto fissato vicino a 90k dallo scalino di pressione anziché dalla finestra. Se `view` sale senza che compaia mai una riga `surface-replace`, leggi le righe di salto (`incomplete-seqs`, `no-service`, `compaction-lock`).
|
|
139
|
+
|
|
140
|
+
**Epoche di compattazione dell'host.** I riferimenti dei fold sono ancorati a id dei messaggi e hash dei contenuti; quando l'host compatta esso stesso la cronologia reinviata, l'intero registro invecchia in un colpo: nessun blocco si localizza, la vista retrocede silenziosamente alla cronologia grezza (fail-open — il registro delle decisioni annota `view-applied applied=0`) e il plugin re-ancora la sua baseline di crescita sulla vista post-compattazione alla richiesta successiva. La compattazione dell'host è quindi lo strato di taglio di ultima istanza; i fold del plugin fanno il lavoro fine all'interno di un'epoca dell'host. Alcuni dispatch consegnano array di richiesta o oggetti opzioni completamente congelati (l'attuale loop d'agente congela in profondità le richieste assemblate); per essi `injectView` riporta l'esito nel registro delle decisioni: `nothing-to-apply` (nessun blocco di fold localizzato — la cronologia grezza È la vista), `in-place`/`swapped` (la vista piegata è partita con la richiesta) oppure `none` (esisteva un fold ma il dispatch congelato non poteva portarlo — sul filo va la cronologia grezza). **La sostituzione di superficie è la via di spedizione quando disponibile** (`surfaceFold`, attivo per impostazione predefinita): al confine seriale `agent/turn-stopping` più una spazzata di inattività, il plugin aggiunge l'evento di misurazione shadow-price in stile host e UNA sostituzione `user/message` che porta `surfaceOp {op:'replace', startSeq, endSeq}` con `sourceEventSeqs` che copre ogni nodo di superficie in ombra — lo stesso meccanismo usato dalla compattazione dell'host stessa — cosicché un fold confermato raggiunge il filo dal livello sorgente, dispatch congelati compresi. Finché i dispatch recenti di una sessione registrano `none`, il plugin tratta la vista come sola misurazione: il livello dell'acqua misura invece il conteggio riportato dal provider (lo scalino force e la consegna automatica continuano a funzionare), i cicli di fold si mettono in pausa invece di bruciare chiamate al riassuntore, e il banner di taglio contrassegna la riga con `wire=raw` (folds not shipping; watermark reads the tally); gli host senza il meccanismo di superficie (o con il flag spento) mantengono esattamente quel comportamento legacy.
|
|
137
141
|
|
|
138
|
-
**Epoche di compattazione dell'host.** I riferimenti dei fold sono ancorati a id dei messaggi e hash dei contenuti; quando l'host compatta esso stesso la cronologia reinviata, l'intero registro invecchia in un colpo: nessun blocco si localizza, la vista retrocede silenziosamente alla cronologia grezza (fail-open — il registro delle decisioni annota `view-applied applied=0`) e il plugin re-ancora la sua baseline di crescita sulla vista post-compattazione alla richiesta successiva. La compattazione dell'host è quindi lo strato di taglio di ultima istanza; i fold del plugin fanno il lavoro fine all'interno di un'epoca dell'host. Alcuni dispatch consegnano array di richiesta o oggetti opzioni completamente congelati; per essi il plugin fallisce apertamente (`injected=none` nel registro delle decisioni), mentre il dispatch mutabile che produce la risposta del modello riceve comunque la vista piegata.
|
|
139
142
|
**Come i fold preservano gli hit di cache.** Ogni fold ripaga il prefisso una volta; l'obiettivo è il costo ammortizzato, non un tasso di hit perfetto. Il motore fa rispettare il contratto di cache: i fold sono solo in aggiunta — la frontier avanza soltanto e la zona congelata non viene più modificata; la view è ricostruita in modo deterministico da (cronologia, stato dei fold), quindi il prefisso serializzato resta identico al byte tra un fold e l'altro e la cache del fornitore continua a colpire; i confini di fold non separano mai una tool-call dell'assistant dal suo risultato; gli ultimi `trimProtectedTail` messaggi sono esenti; e tutto fallisce aperto — un errore interno degrada a pass-through, mai a una richiesta rotta.
|
|
140
143
|
|
|
141
144
|
**Arbitrato della compattazione.** Due trimmer automatici sulla stessa cronologia si riassumerebbero due volte e distruggerebbero a vicenda la frontier, quindi `cordis.patch.yml` mette `auto: false` sulle righe `dsh-compaction-basic` dell'host: context-trim diventa l'unico trimmer semantico. La `/compact` manuale continua a funzionare, e la consegna dello scalino force (che prende in prestito proprio quel percorso manuale) resta intatta. Il recupero da overflow passa al trim: il tentativo oltre la finestra fallisce una volta, poi lo scalino di emergenza ripiega la view così il tentativo successivo entra.
|
|
142
145
|
|
|
143
|
-
**Eredità dei fork.** Una sessione forkata (fork di subagente
|
|
146
|
+
**Eredità dei fork.** Una sessione forkata (fork di subagente) eredita lo stato dei fold del genitore per copia-al-fork — ma solo se lo stato del genitore esiste e la cronologia del figlio risolve davvero la frontier del genitore; altrimenti il figlio parte pulito. Un'eredità per figlio, idempotente tra riavvii.
|
|
144
147
|
|
|
145
148
|
**Il banner delle soglie legge la view.** Il banner delle soglie riporta il conteggio di token della view in uscita (ciò che il modello vede davvero dopo il ripiegamento) invece del totale memorizzato, così una sessione molto ripiegata non inchioda più il livello al — anzi — allo scalino hard.
|
|
146
149
|
|
|
@@ -155,7 +158,7 @@ Tutte le chiavi stanno in Impostazioni → dsh-switchman; i valori predefiniti v
|
|
|
155
158
|
|
|
156
159
|
- Dopo un upgrade di DSH che cambia la lista di plugin dei preset di serie, risincronizza `cordis.patch.yml` dai nuovi `presets/*.patch.yml` (mantieni il doctrine suffix e l'arbitrato della compattazione — `auto: false` sulle righe `compaction-basic`), poi reinstalla.
|
|
157
160
|
- Le righe di protocollo (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) restano deliberatamente in inglese e stabili al byte — non localizzarle.
|
|
158
|
-
- `npm pack --dry-run` deve restare alla forma auditata di
|
|
161
|
+
- `npm pack --dry-run` deve restare alla forma auditata di 60 file / ~380 kB (~1,26 MB scompattati; `docs/` è escluso).
|
|
159
162
|
|
|
160
163
|
## License
|
|
161
164
|
|