dsh-switchman 1.8.0 → 1.9.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/README.de.md +41 -1
- package/README.es.md +41 -1
- package/README.fr.md +41 -1
- package/README.it.md +41 -1
- package/README.ja.md +41 -1
- package/README.ko.md +41 -1
- package/README.md +41 -1
- package/README.pt.md +41 -1
- package/README.ru.md +41 -1
- package/README.zh-TW.md +41 -1
- package/README.zh.md +41 -1
- package/client.js +399 -2
- package/cordis.patch.yml +32 -0
- package/host/config.js +40 -0
- package/host/context-trim/fork.js +168 -0
- package/host/context-trim/index.js +830 -0
- package/host/context-trim/metrics.js +104 -0
- package/host/context-trim/state.js +241 -0
- package/host/context-trim/summarizer.js +179 -0
- package/host/context-trim/trigger.js +122 -0
- package/host/context-trim/view.js +316 -0
- package/host/context-watch.js +22 -2
- package/host/dispatch.js +132 -20
- package/host/subagent-model.js +1 -1
- package/index.js +15 -1
- package/package.json +4 -1
package/README.de.md
CHANGED
|
@@ -102,8 +102,48 @@ Alles Folgende sind die vollständigen Werte direkt nach der Neuinstallation (ma
|
|
|
102
102
|
|
|
103
103
|
**Intent-Routing** (ab Werk unbrauchbar; nötig sind Klassifikator + mindestens ein Kandidat + der Hauptschalter): `intentEnabled` = aus (ist er aus, bleibt der Auto-Eintrag verborgen, und Sessions, die bereits Auto gewählt hatten, laufen über die Fallback-Kette); Klassifikator-Route nicht gesetzt; Klassifikatortyp `chat`; Kandidatenliste leer (die mitgelieferten Kategorien nehmen erst mit eingetragenem Modell am Routing teil); Cache-Fenster `300` s / Umschalt-Vertrauensschwelle `80` / Klassifikations-Timeout `60000` ms; Verlauf `6` Nachrichten / `2400` Zeichen; `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
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
|
+
|
|
105
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 sichert automatisch ab und übergibt — ganz ohne Einstellungen.
|
|
106
108
|
|
|
109
|
+
## Automatisches Kontext-Trimming
|
|
110
|
+
|
|
111
|
+
Lange Sessions bleiben günstig: verarbeitete Gesprächsbereiche werden zu kompakten deterministischen Zusammenfassungen gefaltet — vollautomatisch und ohne den Prompt-Cache des Anbieters zu brechen. An einer Leerlauf-Grenze wählt die Trim-Engine (`host/context-trim/`) die faltenswerten Bereiche, ein Nebenmodell schreibt die Zusammenfassung (nur unter Notfall-Druck greift stattdessen ein mechanischer Fold ohne Nebenmodell-Aufruf), und der Fold wird in den Fold-Zustand der Session committet. Von da an wird jede ausgehende Anfrage aus diesem Zustand neu aufgebaut — Zusammenfassungsblöcke ersetzen die gefalteten Bereiche, der lebende Tail bleibt unangetastet. Die gespeicherte Session wird nie umgeschrieben, und mitten im Stream passiert niemals etwas.
|
|
112
|
+
|
|
113
|
+
Automatisierungsstufen (`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`** — nur messen: Usage- und Cache-Hit-Sampling läuft weiter; kein Banner, keine Folds.
|
|
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 ≥ `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
|
+
|
|
119
|
+
Alle Schlüssel liegen unter Einstellungen → dsh-switchman; Defaults aus `host/config.js`:
|
|
120
|
+
|
|
121
|
+
| Schlüssel | Standard | Bedeutung |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | Hauptschalter. AUS deaktiviert Folds und Metriken komplett (der Listener wird zum reinen Durchreichen). |
|
|
124
|
+
| `trimMode` | `auto` | `off` nur messen / `advisory` modellgetriebene Folds / `auto` systemgetriebene Folds. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | Wachstumsschwelle: falte, wenn die ausgehende View seit dem letzten Fold so viel gewachsen ist. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | Schwellen-Begleiter: der zusammenhängende komprimierbare Zuwachs muss ebenfalls diese Größe erreichen. |
|
|
127
|
+
| `trimPressurePercent` | `60` | Druckstufe: falte, wenn die View-Nutzung diesen Prozentsatz des Kontextfensters erreicht. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | Notfallstufe: erzwungener mechanischer Fold (kein Nebenmodell-Aufruf) bei diesem Prozentsatz. |
|
|
129
|
+
| `trimWindowTokens` | `0` | Effektives Fensterlimit für die Stufenberechnung: gerechnet gegen min(Modellfenster, Limit). `0` = folgt `wmForceTokens`. |
|
|
130
|
+
| `trimProtectedTail` | `6` | Die letzten N Nachrichten werden nie gefaltet. |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | Fold-Takt-Obergrenze pro rollierender Stunde für Nebenmodell-Folds (Notfall-Folds ausgenommen). |
|
|
132
|
+
| `trimSideModel` | nicht gesetzt | Route des zusammenfassenden Nebenmodells. Leer = das aktuelle Session-Modell erben. |
|
|
133
|
+
| `trimStateDir` | nicht gesetzt | Überschreibt das Fold-Zustandsverzeichnis. Leer = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
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 JSON-Zeile an `decisions.log` im Fold-Zustandsverzeichnis (siehe `trimStateDir`) angehängt und gibt Folds so eine Offline-Prüfspur.
|
|
136
|
+
|
|
137
|
+
|
|
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
|
+
**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
|
+
|
|
141
|
+
**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
|
+
|
|
143
|
+
**Fork-Vererbung.** Eine geforkte Session (Subagent-Fork oder Übergabe-Backup) 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
|
+
|
|
145
|
+
**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
|
+
|
|
107
147
|
## Funktionsweise
|
|
108
148
|
|
|
109
149
|
- Die Host-Hälfte (`index.js` + `host/`) injiziert die byte-stabilen System-Prompt-Abschnitte (Sprache / Spuren / Wasserstands-Protokoll / Teams) plus die Live-Wasserstandszeile über den Runtime-Context-Snapshot am Ende (ein Kanal, der nur anhängt, statt den Prompt-Kopf umzuschreiben — der Prompt-Cache des Providers bleibt intakt), dazu das Lese-Budget samt Enforcement-Doppeltor und vier Slash-Befehle (das ctx-Trio + `/vision`). Gespeicherte Einstellungen wirken ab der nächsten Prompt-Montage — kein Neustart.
|
|
@@ -113,7 +153,7 @@ Alles Folgende sind die vollständigen Werte direkt nach der Neuinstallation (ma
|
|
|
113
153
|
|
|
114
154
|
## Hinweise zur Wartung
|
|
115
155
|
|
|
116
|
-
- Ändert ein DSH-Upgrade die Werks-Preset-Pluginliste, `cordis.patch.yml` aus dem neuen `presets/*.patch.yml` neu synchronisieren (Doctrine-Suffix behalten) und neu installieren.
|
|
156
|
+
- Ä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.
|
|
117
157
|
- Die Protokollzeilen (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) sind bewusst englisch und byte-stabil — nicht lokalisieren.
|
|
118
158
|
- `npm pack --dry-run` muss die auditierte Form mit 50 Dateien / ~205 kB behalten (`docs/`-Screenshots kommen nicht ins Paket).
|
|
119
159
|
|
package/README.es.md
CHANGED
|
@@ -102,8 +102,48 @@ Esto es todo el conjunto de valores tras una instalación nueva (fuente autorita
|
|
|
102
102
|
|
|
103
103
|
**Enrutado por intención** (no disponible de fábrica; hacen falta clasificador + al menos un candidato + encender el interruptor maestro): `intentEnabled` = apagado (apagado, la entrada Auto queda oculta y las sesiones que ya la tenían elegida caen en la cadena de respaldo); ruta del clasificador sin configurar; tipo de clasificador `chat`; lista de candidatos vacía (las categorías preinstaladas solo entran en el enrutado cuando se les asigna un modelo); ventana de caché `300` s / umbral de confianza para el cambio `80` / timeout de clasificación `60000` ms; historial de `6` mensajes / `2400` caracteres; `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
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
|
+
|
|
105
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 respalda y entrega automáticamente — sin tocar ningún ajuste.
|
|
106
108
|
|
|
109
|
+
## Recorte automático del contexto
|
|
110
|
+
|
|
111
|
+
Las sesiones largas salen baratas: los tramos de conversación ya consumidos se pliegan en resúmenes deterministas compactos — de forma totalmente automática y sin romper la caché de prompts del proveedor. En un límite de inactividad, el motor de trim (`host/context-trim/`) elige los tramos que vale la pena plegar, un modelo secundario escribe el resumen (solo bajo presión de emergencia se recurre a un fold mecánico sin llamada al modelo secundario) y el fold se confirma en el estado de folds de la sesión. A partir de ahí, cada petición saliente se reconstruye desde ese estado — los bloques de resumen sustituyen a los tramos plegados y la cola viva queda intacta. La sesión almacenada jamás se reescribe, y nada ocurre en mitad de un stream.
|
|
112
|
+
|
|
113
|
+
Niveles de automatización (`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`** — solo medir: el muestreo de uso y de aciertos de caché sigue funcionando; sin banner ni folds.
|
|
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 ≥ `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
|
+
|
|
119
|
+
Todas las claves viven en Ajustes → dsh-switchman; los valores por defecto salen de `host/config.js`:
|
|
120
|
+
|
|
121
|
+
| Clave | Por defecto | Significado |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | Interruptor maestro. Apagado desactiva folds y métricas por completo (el listener degenera en puro paso a través). |
|
|
124
|
+
| `trimMode` | `auto` | `off` solo medir / `advisory` folds dictados por el modelo / `auto` folds dictados por el sistema. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | Compuerta de crecimiento: pliega cuando la view saliente crezca esto desde el último fold. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | Compañera de la compuerta: el incremento comprimible contiguo también debe alcanzar este tamaño. |
|
|
127
|
+
| `trimPressurePercent` | `60` | Escalón de presión: pliega cuando el uso de la view alcance este porcentaje de la ventana de contexto. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | Escalón de emergencia: fold mecánico forzado (sin llamada al modelo secundario) a este porcentaje. |
|
|
129
|
+
| `trimWindowTokens` | `0` | Límite de ventana efectivo para el cálculo de niveles: se calcula sobre min(ventana del modelo, límite). `0` = sigue a `wmForceTokens`. |
|
|
130
|
+
| `trimProtectedTail` | `6` | Los últimos N mensajes nunca se pliegan. |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | Tope de cadencia de folds por hora móvil para el modelo secundario (los de emergencia quedan exentos). |
|
|
132
|
+
| `trimSideModel` | sin definir | Ruta del modelo secundario que escribe los resúmenes. Vacía = heredar el modelo actual de la sesión. |
|
|
133
|
+
| `trimStateDir` | sin definir | Anula el directorio del estado de folds. Vacía = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
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 JSON 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.
|
|
136
|
+
|
|
137
|
+
|
|
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
|
+
**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
|
+
|
|
141
|
+
**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
|
+
|
|
143
|
+
**Herencia en forks.** Una sesión forkeada (fork de subagente o respaldo de entrega) 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
|
+
|
|
145
|
+
**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
|
+
|
|
107
147
|
## Cómo funciona
|
|
108
148
|
|
|
109
149
|
- La mitad Host (`index.js` + `host/`) inyecta las secciones estables a nivel de bytes del system prompt (idioma / carriles / protocolo de nivel de agua / equipo) más la línea de nivel en vivo a través de la instantánea de runtime-context del final (un canal que añade en lugar de reescribir la cabecera del prompt, de modo que la caché de prompt del proveedor queda intacta), además de la doble compuerta de presupuesto de lectura y enforce, y cuatro comandos slash (el trío ctx + `/vision`). Todos los ajustes, una vez guardados, surten efecto en el siguiente ensamblado del prompt, sin reinicio.
|
|
@@ -113,7 +153,7 @@ Esto es todo el conjunto de valores tras una instalación nueva (fuente autorita
|
|
|
113
153
|
|
|
114
154
|
## Mantenimiento
|
|
115
155
|
|
|
116
|
-
- 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 reinstala.
|
|
156
|
+
- 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.
|
|
117
157
|
- 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.
|
|
118
158
|
- `npm pack --dry-run` debe mantenerse en la forma auditada de 50 archivos / ~205 kB (las capturas de `docs/` no entran en el paquete).
|
|
119
159
|
|
package/README.fr.md
CHANGED
|
@@ -102,8 +102,48 @@ Voici l'ensemble complet des valeurs juste après une installation neuve (source
|
|
|
102
102
|
|
|
103
103
|
**Routage par intention** (indisponible par défaut ; il exige un classifieur + au moins un candidat + l'interrupteur général) : `intentEnabled` = désactivé (désactivé, l'entrée Auto reste cachée et les sessions déjà passées en Auto empruntent la chaîne de repli) ; route du classifieur non définie ; type de classifieur `chat` ; liste de candidats vide (les catégories préinstallées ne participent au routage qu'une fois un modèle renseigné) ; fenêtre de cache `300` s / seuil de confiance du basculement `80` / timeout de classification `60000` ms ; historique de `6` messages / `2400` caractères ; `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
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
|
+
|
|
105
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 sauvegarde et remet automatiquement — sans aucun réglage.
|
|
106
108
|
|
|
109
|
+
## Trim automatique du contexte
|
|
110
|
+
|
|
111
|
+
Les longues sessions restent bon marché : les plages de conversation consommées sont repliées en résumés déterministes compacts — entièrement automatiquement, sans casser le cache de prompts du fournisseur. À une frontière d'inactivité, le moteur de trim (`host/context-trim/`) choisit les plages qui valent un repli, un modèle annexe écrit le résumé (sous pression d'urgence seulement, c'est un fold mécanique sans appel de modèle annexe), et le fold est validé dans l'état de folds de la session. Dès lors, chaque requête sortante est reconstruite depuis cet état — des blocs de résumé remplacent les plages repliées, la queue vive reste intacte. La session stockée n'est jamais réécrite, et rien ne se passe en plein stream.
|
|
112
|
+
|
|
113
|
+
Niveaux d'automatisation (`trimMode`) :
|
|
114
|
+
|
|
115
|
+
- **`off`** — mesure seule : l'échantillonnage de l'usage et des hits de cache tourne toujours ; pas de bannière, pas de folds.
|
|
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 ≥ `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
|
+
|
|
119
|
+
Toutes les clés vivent dans Réglages → dsh-switchman ; les valeurs par défaut viennent de `host/config.js` :
|
|
120
|
+
|
|
121
|
+
| Clé | Par défaut | Signification |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | Interrupteur maître. Désactivé, folding et métriques s'arrêtent totalement (le listener se dégrade en simple passage). |
|
|
124
|
+
| `trimMode` | `auto` | `off` mesure seule / `advisory` folds pilotés par le modèle / `auto` folds pilotés par le système. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | Porte de croissance : on plie quand la view sortante a grandi d'autant depuis le dernier fold. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | Compagnon de la porte : l'incrément compressible contigu doit aussi atteindre cette taille. |
|
|
127
|
+
| `trimPressurePercent` | `60` | Palier de pression : on plie quand l'usage de la view atteint ce pourcentage de la fenêtre de contexte. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | Palier d'urgence : fold mécanique forcé (sans appel de modèle annexe) à ce pourcentage. |
|
|
129
|
+
| `trimWindowTokens` | `0` | Plafond de fenêtre effectif pour le calcul des paliers : calculé sur min(fenêtre du modèle, plafond). `0` = suit `wmForceTokens`. |
|
|
130
|
+
| `trimProtectedTail` | `6` | Les N derniers messages ne sont jamais repliés. |
|
|
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
|
+
| `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
|
+
| `trimStateDir` | non défini | Redéfinit le répertoire d'état des folds. Vide = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
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 JSON à `decisions.log` dans le répertoire d'état des folds (voir `trimStateDir`), donnant aux folds une piste d'audit hors ligne.
|
|
136
|
+
|
|
137
|
+
|
|
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
|
+
**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
|
+
|
|
141
|
+
**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
|
+
|
|
143
|
+
**Héritage des forks.** Une session forkée (fork de sous-agent ou sauvegarde de remise) 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
|
+
|
|
145
|
+
**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
|
+
|
|
107
147
|
## Fonctionnement
|
|
108
148
|
|
|
109
149
|
- La partie Host (`index.js` + `host/`) injecte les sections stables à l'octet près du prompt système (langue / couloirs / protocole de niveau d'eau / équipes) plus la ligne d'eau en direct via l'instantané de runtime-context de fin (un canal qui ajoute au lieu de réécrire la tête du prompt, si bien que le cache de prompt du fournisseur reste intact), ainsi que les deux verrous budget de lecture et enforce, et les quatre commandes slash (le trio ctx + `/vision`). Tout réglage enregistré prend effet au prochain assemblage de prompt — sans redémarrage.
|
|
@@ -113,7 +153,7 @@ Voici l'ensemble complet des valeurs juste après une installation neuve (source
|
|
|
113
153
|
|
|
114
154
|
## Maintenance
|
|
115
155
|
|
|
116
|
-
- 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), puis réinstallez.
|
|
156
|
+
- 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.
|
|
117
157
|
- Les lignes de protocole (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) restent volontairement en anglais et stables à l'octet — ne les localisez pas.
|
|
118
158
|
- `npm pack --dry-run` doit conserver la forme auditée de 50 fichiers / ~205 kB (les captures d'écran de `docs/` ne partent pas dans le paquet).
|
|
119
159
|
|
package/README.it.md
CHANGED
|
@@ -102,8 +102,48 @@ Questi sono tutti i valori così come si presentano dopo una nuova installazione
|
|
|
102
102
|
|
|
103
103
|
**Instradamento per intent** (non disponibile per predefinito; servono classificatore + almeno un candidato + l'interruttore principale): `intentEnabled` = spento (spento, la voce Auto resta nascosta e le sessioni che l'avevano già scelta percorrono la catena di fallback); route del classificatore non impostata; tipo di classificatore `chat`; lista dei candidati vuota (le categorie preinstallate entrano nell'instradamento solo con un modello assegnato); finestra di cache `300` s / soglia di confidenza del cambio `80` / timeout di classificazione `60000` ms; cronologia di `6` messaggi / `2400` caratteri; `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
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
|
+
|
|
105
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 fa da solo backup e consegna — senza alcuna impostazione.
|
|
106
108
|
|
|
109
|
+
## Trim automatico del contesto
|
|
110
|
+
|
|
111
|
+
Le sessioni lunghe restano economiche: le porzioni di conversazione già consumate vengono ripiegate in riassunti deterministici compatti — in modo del tutto automatico e senza rompere la cache dei prompt del fornitore. A un confine di inattività, il motore di trim (`host/context-trim/`) sceglie le porzioni che valgono un fold, un modello secondario scrive il riassunto (solo sotto pressione di emergenza si ricorre a un fold meccanico senza chiamata al modello secondario) e il fold viene registrato nello stato dei fold della sessione. Da lì in poi ogni richiesta in uscita viene ricostruita da quello stato — i blocchi di riassunto sostituiscono le porzioni ripiegate, la coda viva resta intatta. La sessione memorizzata non viene mai riscritta, e nulla accade a metà stream.
|
|
112
|
+
|
|
113
|
+
Livelli di automazione (`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`** — solo misura: il campionamento di uso e hit di cache continua; niente banner, niente fold.
|
|
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 ≥ `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
|
+
|
|
119
|
+
Tutte le chiavi stanno in Impostazioni → dsh-switchman; i valori predefiniti vengono da `host/config.js`:
|
|
120
|
+
|
|
121
|
+
| Chiave | Predefinito | Significato |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | Interruttore principale. Spento disattiva fold e metriche del tutto (il listener degrada a puro pass-through). |
|
|
124
|
+
| `trimMode` | `auto` | `off` solo misura / `advisory` fold guidati dal modello / `auto` fold guidati dal sistema. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | Cancello di crescita: ripiega quando la view in uscita è cresciuta di tanto dall'ultimo fold. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | Compagno del cancello: anche l'incremento comprimibile contiguo deve raggiungere questa taglia. |
|
|
127
|
+
| `trimPressurePercent` | `60` | Scalino di pressione: ripiega quando l'uso della view raggiunge questa percentuale della finestra di contesto. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | Scalino di emergenza: fold meccanico forzato (nessuna chiamata al modello secondario) a questa percentuale. |
|
|
129
|
+
| `trimWindowTokens` | `0` | Limite di finestra effettivo per il calcolo delle soglie: calcolato su min(finestra del modello, limite). `0` = segue `wmForceTokens`. |
|
|
130
|
+
| `trimProtectedTail` | `6` | Gli ultimi N messaggi non vengono mai ripiegati. |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | Tetto di cadenza dei fold per ora mobile per il modello secondario (quelli di emergenza ne sono esenti). |
|
|
132
|
+
| `trimSideModel` | non impostata | Route del modello secondario che scrive i riassunti. Vuota = eredita il modello attuale della sessione. |
|
|
133
|
+
| `trimStateDir` | non impostata | Sostituisce la directory dello stato dei fold. Vuota = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
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 JSON a `decisions.log` nella directory dello stato dei fold (vedi `trimStateDir`), dando ai fold una traccia di audit offline.
|
|
136
|
+
|
|
137
|
+
|
|
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
|
+
**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
|
+
|
|
141
|
+
**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
|
+
|
|
143
|
+
**Eredità dei fork.** Una sessione forkata (fork di subagente o backup di consegna) 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
|
+
|
|
145
|
+
**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
|
+
|
|
107
147
|
## Come funziona
|
|
108
148
|
|
|
109
149
|
- La parte Host (`index.js` + `host/`) inietta le sezioni byte-stabili del system prompt (lingue / corsie / protocollo del livello dell'acqua / squadra) più la riga del livello dell'acqua in tempo reale tramite lo snapshot di runtime-context in coda (un canale che accoda invece di riscrivere la testa del prompt, quindi la cache di prompt del provider resta intatta), oltre al doppio cancello budget di lettura + enforce e i quattro comandi slash (il trio ctx più `/vision`). Ogni impostazione salvata vale già dall'assemblaggio del prompt successivo, senza riavvio.
|
|
@@ -113,7 +153,7 @@ Questi sono tutti i valori così come si presentano dopo una nuova installazione
|
|
|
113
153
|
|
|
114
154
|
## Manutenzione
|
|
115
155
|
|
|
116
|
-
- 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), poi reinstalla.
|
|
156
|
+
- 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.
|
|
117
157
|
- Le righe di protocollo (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) restano deliberatamente in inglese e stabili al byte — non localizzarle.
|
|
118
158
|
- `npm pack --dry-run` deve restare alla forma auditata di 50 file / ~205 kB (gli screenshot in `docs/` non viaggiano nel pacchetto).
|
|
119
159
|
|
package/README.ja.md
CHANGED
|
@@ -102,8 +102,48 @@ bash <インストールディレクトリ>/skills/db-query/scripts/setup.sh
|
|
|
102
102
|
|
|
103
103
|
**意図認識**(既定では利用不可。分類器+候補最低1つ+マスタートグルのオンが必要):`intentEnabled` = オフ(オフの間は Auto エントリが隠れ、Auto を選んでいたセッションはフォールバックチェーンへ流れる)。分類器ルートは未設定。分類器タイプは `chat`。候補リストは空(プリセット分類はモデルを埋めないとルーティングに参加しない)。キャッシュウィンドウ `300` 秒 / 切替信頼度 `80` / 分類タイムアウト `60000` ms。履歴 `6` 件 / `2400` 文字。`intentContextWindow` = `200000`。
|
|
104
104
|
|
|
105
|
+
**コンテキストトリム**:`trimEnabled` = オン;`trimMode` = `auto`(完全自動);成長ゲート `22500` + インクリメント `50000` トークン;圧力 `60%` / 緊急 `95%`;保護テール `6` 件;fold ペース上限は毎時 `6` 回;サイドモデルは未設定(セッションモデルを継承)——詳細は下の「自動コンテキストトリム」節で。
|
|
106
|
+
|
|
105
107
|
**初期状態のポイント**:① 意図認識が既定で使えないのは意図的な設計で、有効化は3ステップ(分類器、候補、トグル)。② Auto の実効ウィンドウは既定で 200000——ガードレールにより 0.8×ウィンドウ ≥ force 段(150000)が保証され、コア圧縮線(160000)は常にスムーズ引き継ぎ線(150000)より後ろにある。③ 既定でいちばん体感できるのは水位の3点セット:80k で委譲を促し、120k で読み取りを収束させ、150k で自動バックアップ引き継ぎ。設定は一切不要。
|
|
106
108
|
|
|
109
|
+
## 自動コンテキストトリム
|
|
110
|
+
|
|
111
|
+
長いセッションを安く保つ:消化済みの会話レンジはコンパクトな決定論的サマリへ fold される——完全自動で、プロバイダのプロンプトキャッシュも壊さない。アイドル境界でトリムエンジン(`host/context-trim/`)が fold する価値のあるレンジを選び、サイドモデルがサマリを書き(緊急圧力時のみ、サイドモデル呼び出しなしの機械 fold に切り替わる)、fold をセッションの fold 状態へコミットする。以降のアウトバウンドリクエストはすべてその状態から再構築される——サマリブロックが fold 済みレンジを置き換え、ライブテールはそのまま。保存されたセッションは決して書き換えられず、ストリーム途中で何かが起きることもない。
|
|
112
|
+
|
|
113
|
+
自動化レベル(`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`**——計測のみ:使用量とキャッシュヒットのサンプリングは動作;バナーなし、fold なし。
|
|
116
|
+
- **`advisory`**——セッションモデルが自ら fold する:`ctx_trim_fold` と `ctx_trim_status` のツールとプロトコルヘッドを公開。
|
|
117
|
+
- **`auto`**(既定)——advisory のすべてに加え、アイドル境界での自動 fold が3段階で動く:成長ゲート(前回の折り返し後の低点から測定した成長 ≥ `trimGrowthTokens`——高位で折り返してもゲートが有効であり続けるためのアンカー——かつ連続圧縮可能インクリメントが `trimIncrementTokens` 以上)、圧力段(コンテキストウィンドウの `trimPressurePercent`)、緊急段(`trimEmergencyPercent`——独自クールダウン付きの機械 fold)。
|
|
118
|
+
|
|
119
|
+
すべてのキーは「設定 → dsh-switchman」にあり、既定値は `host/config.js` 由来:
|
|
120
|
+
|
|
121
|
+
| キー | 既定値 | 意味 |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | マスタースイッチ。OFF で fold とメトリクスを完全停止(リスナーは純パススルーに退化)。 |
|
|
124
|
+
| `trimMode` | `auto` | `off` 計測のみ / `advisory` モデル駆動 fold / `auto` システム駆動 fold。 |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | 成長ゲート:前回の fold 以降にアウトバウンド view がこれだけ増えたら fold。 |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | ゲートの同伴条件:連続圧縮可能インクリメントもこの規模に達する必要あり。 |
|
|
127
|
+
| `trimPressurePercent` | `60` | 圧力段:view 使用量がコンテキストウィンドウのこの割合に達したら fold。 |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | 緊急段:この割合で機械 fold を強制(サイドモデル呼び出しなし)。 |
|
|
129
|
+
| `trimWindowTokens` | `0` | ティア計算の実効ウィンドウ上限:min(モデルウィンドウ, 上限) で計算。`0` = `wmForceTokens` に追従。 |
|
|
130
|
+
| `trimProtectedTail` | `6` | 最後の N メッセージは決して fold されない。 |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | ローリング1時間あたりのサイドモデル fold ペース上限(緊急段は対象外)。 |
|
|
132
|
+
| `trimSideModel` | 未設定 | サマリを書くサイドモデルのルート。空欄 = セッションの現在モデルを継承。 |
|
|
133
|
+
| `trimStateDir` | 未設定 | fold 状態ディレクトリの上書き。空欄 = `<dshHome>/.dsh-switchman/state/trim/`。 |
|
|
134
|
+
|
|
135
|
+
**トリガーパス。** 段階チェックはアイドル境界で走り、アイドル状態イベントが届かないホストへのフォールバックとして、各モデルストリーム完了後にも走る(セッションごとに 60 秒につき 1 回の評価へスロットル)。すべての決定——fold も no-op も同様に——は、fold 状態ディレクトリ(`trimStateDir` を参照)内の `decisions.log` へ 1 行の JSON として追記され、fold にオフラインの監査証跡を与える。
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
**ホスト圧縮エポック。** fold の参照はメッセージ id と内容ハッシュにアンカーされるため、ホスト側の圧縮が再送履歴を置き換えると帳簿全体が一度に老化します。すべてのブロックが位置を特定できなくなり、view は元の履歴へ静かにフォールバックし(fail-open —— 決定ログには `view-applied applied=0` が記録されます)、プラグインは次のリクエストで成長ベースラインを圧縮後のビューに再アンカーします。ホスト圧縮は最後のバックストップとなるトリム層であり、プラグインの fold は単一ホストエポック内のきめ細かい作業を担います。 一部のディスパッチはリクエスト配列やオプションオブジェクトがホストによって凍結されています。その場合プラグインは fail-open し(決定ログに `injected=none` を記録)、モデル応答を実際に生成する可変ディスパッチには折り畳み済みビューが届きます。
|
|
139
|
+
**fold がキャッシュヒットを守る仕組み。** fold は毎回プレフィックスを一度払い戻す。目指すのは償却コストであり、満点のヒット率ではない。エンジンはキャッシュ契約を守る:fold は追記専用——frontier は前進するだけで、凍結ゾーンは二度と編集されない。view は(履歴, fold 状態)から決定論的に再構築されるため、fold 間でシリアライズ済みプレフィックスはバイト同一のまま立ち、プロバイダキャッシュはヒットを続ける。fold 境界が assistant の tool-call をその tool 結果から切り離すことは決してなく、最後の `trimProtectedTail` メッセージは免除、そしてすべてが fail-open——内部エラーはパススルーに退化し、壊れたリクエストは生まれない。
|
|
140
|
+
|
|
141
|
+
**コンパクション仲裁。** 同じ履歴を巡る2つの自動トリマーは互いに二重要約し合い、frontier を破壊し合う。そこで `cordis.patch.yml` はホストの `dsh-compaction-basic` 行に `auto: false` を設定:context-trim が唯一のセマンティックトリマーになる。手動 `/compact` はそのまま使え、force 段の引き継ぎ(同じ手動パスを借用している)も無傷。オーバーフロー回復はトリムに移る:ウィンドウ超過の試行は一度失敗し、その後緊急段が view を fold して次の試行が収まる。
|
|
142
|
+
|
|
143
|
+
**fork 継承。** fork されたセッション(サブエージェント fork または引き継ぎバックアップ)は copy-on-fork で親の fold 状態を継承——ただし親の状態が存在し、子の履歴が実際に親の frontier を解決する場合のみ。さもなければ子はクリーンに開始する。子ごとに継承は一度きりで、再起動を跨いで冪等。
|
|
144
|
+
|
|
145
|
+
**水位は view を読む。** 水位バナーは保存側の集計ではなくアウトバウンド view のトークン数(fold 後にモデルが実際に見るもの)を報告するので、fold が進んだセッションが水位を hard 段に釘付けにすることはもうない。
|
|
146
|
+
|
|
107
147
|
## 仕組み
|
|
108
148
|
|
|
109
149
|
- ホスト側(`index.js` + `host/`)がバイト単位で不変のシステムプロンプト段(言語 / レーン / 水位プロトコル / チーム)と、末尾 runtime-context スナップショット経由で届くリアルタイム水位線(追記のみでプロンプト先頭を書き換えないため、プロバイダーの prompt cache は影響を受けない)、読み取り予算と enforce の二重ゲート、4つのスラッシュコマンド(ctx 3点セット + `/vision`)を注入する。保存した設定は次のターンのプロンプト組み立てで即効き、再起動は不要。
|
|
@@ -113,7 +153,7 @@ bash <インストールディレクトリ>/skills/db-query/scripts/setup.sh
|
|
|
113
153
|
|
|
114
154
|
## メンテナンスの注意
|
|
115
155
|
|
|
116
|
-
- DSH のアップグレードで出荷プリセットのプラグイン一覧が変わったら、新しい `presets/*.patch.yml` から `cordis.patch.yml` を再同期(doctrine suffix
|
|
156
|
+
- DSH のアップグレードで出荷プリセットのプラグイン一覧が変わったら、新しい `presets/*.patch.yml` から `cordis.patch.yml` を再同期(doctrine suffix と、`compaction-basic` 行への `auto: false` によるコンパクション仲裁も保持)し、入れ直す。
|
|
117
157
|
- プロトコル行(`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`)は意図的に英語のままバイト安定——ローカライズしない。
|
|
118
158
|
- `npm pack --dry-run` は監査済みの 50 ファイル / ~205 kB の形状を保つこと(`docs/` のスクリーンショットはパッケージに入らない)。
|
|
119
159
|
|
package/README.ko.md
CHANGED
|
@@ -102,8 +102,48 @@ bash <설치-디렉터리>/skills/db-query/scripts/setup.sh
|
|
|
102
102
|
|
|
103
103
|
**의도 인식**(기본은 사용 불가. 분류기 + 후보 최소 1개 + 마스터 토글 켜기가 필요): `intentEnabled` = 끔(꺼져 있으면 Auto 항목은 숨겨지고, Auto를 선택해 둔 세션은 폴백 체인으로 흐른다). 분류기 라우트 미설정. 분류기 유형 `chat`. 후보 목록은 빈 상태(프리셋 분류는 모델을 채워야 라우팅에 참여). 캐시 창 `300`초 / 전환 신뢰도 `80` / 분류 타임아웃 `60000`ms. 히스토리 `6`건 / `2400`자. `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
105
|
+
**컨텍스트 트림**: `trimEnabled` = 켬; `trimMode` = `auto`(완전 자동); 성장 게이트 `22500` + 증분 `50000` 토큰; 압력 `60%` / 비상 `95%`; 보호 테일 `6`건; fold 케이던스 상한 시간당 `6`회; 사이드 모델 미설정(세션 모델 상속) — 자세한 내용은 아래 "자동 컨텍스트 트림" 절에서.
|
|
106
|
+
|
|
105
107
|
**기본 상태에서 알아둘 점**: ① 의도 인식이 기본으로 불가능한 것은 의도된 설계고, 세 단계로 켠다(분류기, 후보, 토글). ② Auto의 실효 창은 기본값이 200000이다 — 가드레일이 0.8×창 ≥ force 단계(150000)를 보장하므로, 코어 압축선(160000)은 언제나 부드러운 인계선(150000)보다 뒤에 있다. ③ 기본 상태에서 가장 체감되는 건 수위 3종 세트다: 80k에 위임 알림 / 120k에 읽기 수렴 / 150k에 자동 백업 인계 — 설정은 아무것도 필요 없다.
|
|
106
108
|
|
|
109
|
+
## 자동 컨텍스트 트림
|
|
110
|
+
|
|
111
|
+
긴 세션도 저렴하게 유지한다: 소모된 대화 구간은 간결한 결정론적 요약으로 fold 된다 — 완전 자동, 프로바이더 프롬프트 캐시도 깨지 않는다. 유휴 경계에서 트림 엔진(`host/context-trim/`)이 fold 할 가치가 있는 구간을 고르고, 사이드 모델이 요약을 쓰며(비상 압력에서만 사이드 모델 호출 없는 기계 fold로 전환), fold를 세션의 fold 상태에 커밋한다. 이후 모든 아웃바운드 요청은 그 상태에서 재구성된다 — 요약 블록이 fold된 구간을 대체하고, 라이브 테일은 그대로 남는다. 저장된 세션은 절대 다시 쓰이지 않고, 스트리밍 도중에 뭔가 일어나는 일도 없다.
|
|
112
|
+
|
|
113
|
+
자동화 수준(`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`** — 측정만: 사용량과 캐시 히트 샘플링은 계속 돌아간다; 배너 없음, fold 없음.
|
|
116
|
+
- **`advisory`** — 세션 모델이 스스로 fold 한다: `ctx_trim_fold`와 `ctx_trim_status` 도구와 프로토콜 헤드를 노출.
|
|
117
|
+
- **`auto`**(기본값) — 위의 모든 것에 더해 유휴 경계에서 자동 fold가 세 단계로 동작한다: 성장 게이트(지난 접기 후 저점부터 측정한 성장 ≥ `trimGrowthTokens` — 높은 지점에서 접은 후에도 게이트가 계속 작동하도록 유지하는 앵커 — + 연속 압축 가능 증분이 `trimIncrementTokens` 이상), 압력 단계(컨텍스트 창의 `trimPressurePercent`), 비상 단계(`trimEmergencyPercent` — 독립 쿨다운을 가진 기계 fold).
|
|
118
|
+
|
|
119
|
+
모든 키는 설정 → dsh-switchman에 있고, 기본값은 `host/config.js` 기준이다:
|
|
120
|
+
|
|
121
|
+
| 키 | 기본값 | 의미 |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | 마스터 스위치. 끄면 fold와 메트릭이 완전히 정지한다(리스너는 순수 패스스루로 퇴화). |
|
|
124
|
+
| `trimMode` | `auto` | `off` 측정만 / `advisory` 모델 주도 fold / `auto` 시스템 주도 fold. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | 성장 게이트: 지난 fold 이후 아웃바운드 view가 이만큼 자라면 fold. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | 게이트 동반 조건: 연속 압축 가능 증분도 이 규모에 달해야 한다. |
|
|
127
|
+
| `trimPressurePercent` | `60` | 압력 단계: view 사용량이 컨텍스트 창의 이 백분율에 달하면 fold. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | 비상 단계: 이 백분율에서 기계 fold 강제(사이드 모델 호출 없음). |
|
|
129
|
+
| `trimWindowTokens` | `0` | 티어 계산의 유효 윈도우 상한: min(모델 윈도우, 상한)으로 계산. `0` = `wmForceTokens`를 따름. |
|
|
130
|
+
| `trimProtectedTail` | `6` | 마지막 N개 메시지는 절대 fold되지 않는다. |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | 롤링 1시간당 사이드 모델 fold 케이던스 상한(비상 단계는 제외). |
|
|
132
|
+
| `trimSideModel` | 미설정 | 요약을 쓰는 사이드 모델 라우트. 비어 있으면 세션의 현재 모델을 상속. |
|
|
133
|
+
| `trimStateDir` | 미설정 | fold 상태 디렉터리 재정의. 비어 있으면 `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
135
|
+
**트리거 경로.** 단계 검사는 유휴 경계에서 돌아가고, 유휴 상태 이벤트가 도달하지 않는 호스트를 위한 폴백으로 각 모델 스트림 완료 후에도 돌아간다(세션당 60초에 한 번 평가로 스로틀링). 모든 결정 — fold든 no-op든 마찬가지 — 는 fold 상태 디렉터리(`trimStateDir` 참조) 안의 `decisions.log`에 한 줄의 JSON으로 추가되어 fold에 오프라인 감사 추적을 제공한다.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
**호스트 압축 에포크.** fold 참조는 메시지 id와 내용 해시에 고정되므로, 호스트 자체의 압축이 재전송 기록을 대체하면 장부 전체가 한꺼번에 노후됩니다. 모든 블록이 위치를 찾지 못하고, view는 조용히 원본 기록으로 폴백하며(fail-open — 결정 로그에 `view-applied applied=0`가 기록됨), 플러그인은 다음 요청에서 성장 기준선을 압축 후 뷰에 다시 고정합니다. 호스트 압축이 최후의 트림 계층이고, 플러그인 fold는 하나의 호스트 에포크 안에서 세밀한 작업을 담당합니다. 일부 디스패치는 요청 배열이나 옵션 객체가 호스트에 의해 동결되어 있습니다. 이 경우 플러그인은 fail-open 하고(결정 로그에 `injected=none` 기록), 모델 응답을 실제로 생성하는 가변 디스패치에는 폴드된 뷰가 전달됩니다.
|
|
139
|
+
**fold가 캐시 히트를 지키는 방식.** fold는 매번 프리픽스를 한 번 재지불한다; 목표는 완벽한 히트율이 아니라 상각 비용이다. 엔진은 캐시 계약을 지킨다: fold는 append-only — frontier는 앞으로만 가고 동결 구역은 다시 편집되지 않는다. view는 (히스토리, fold 상태)에서 결정론적으로 재구성되므로 fold 사이에 직렬화된 프리픽스는 바이트 동일을 유지하고 프로바이더 캐시는 계속 히트한다. fold 경계는 assistant의 tool-call과 그 tool 결과를 절대 분리하지 않고, 마지막 `trimProtectedTail`개 메시지는 면제되며, 모든 것은 fail-open — 내부 오류는 패스스루로 퇴화하고 깨진 요청은 생기지 않는다.
|
|
140
|
+
|
|
141
|
+
**컴팩션 중재.** 하나의 히스토리 위에 자동 트리머가 둘이면 서로 이중 요약하고 서로의 frontier를 부수므로, `cordis.patch.yml`은 호스트의 `dsh-compaction-basic` 행에 `auto: false`를 설정한다: context-trim이 유일한 시맨틱 트리머가 된다. 수동 `/compact`은 그대로 동작하고, force 단계 인계(같은 수동 경로를 빌려 쓴다)도 무사하다. 오버플로 복구는 트림으로 이동한다: 창을 넘은 시도는 한 번 실패하고, 그다음 비상 단계가 view를 fold해 다음 시도는 들어간다.
|
|
142
|
+
|
|
143
|
+
**fork 상속.** fork된 세션(서브에이전트 fork 또는 인계 백업)은 copy-on-fork로 부모의 fold 상태를 상속한다 — 단, 부모 상태가 존재하고 자식 히스토리가 실제로 부모 frontier를 해석할 때만. 그렇지 않으면 자식은 깨끗하게 시작한다. 자식당 상속은 한 번뿐이며 재시작을 넘어 멱등이다.
|
|
144
|
+
|
|
145
|
+
**수위는 view를 읽는다.** 수위 배너는 저장 측 집계가 아니라 아웃바운드 view의 토큰 수(fold 후 모델이 실제로 보는 것)를 보고하므로, fold가 많이 진행된 세션이 수위를 hard 단계에 못 박는 일은 이제 없다.
|
|
146
|
+
|
|
107
147
|
## 작동 원리
|
|
108
148
|
|
|
109
149
|
- 호스트 쪽(`index.js` + `host/`)이 바이트 단위로 불변인 시스템 프롬프트 단(언어 / 레인 / 수위 프로토콜 / 팀)과, 뒤에 오는 runtime-context 스냅샷 채널로 전달되는 실시간 수위선(추가만 하고 프롬프트 앞부분을 재작성하지 않으므로 공급자 prompt cache는 영향받지 않는다), 읽기 예산과 enforce 이중 게이트, 슬래시 명령 4개(ctx 3종 + `/vision`)를 주입한다. 설정을 저장하면 다음 턴 프롬프트 조립 때 바로 반영되고 재시작은 필요 없다.
|
|
@@ -113,7 +153,7 @@ bash <설치-디렉터리>/skills/db-query/scripts/setup.sh
|
|
|
113
153
|
|
|
114
154
|
## 유지보수 주의사항
|
|
115
155
|
|
|
116
|
-
- DSH 업그레이드 후 출고 프리셋 플러그인 목록이 바뀌면 새 `presets/*.patch.yml`에서 `cordis.patch.yml`을 다시 동기화하고(doctrine suffix 유지) 재설치한다.
|
|
156
|
+
- DSH 업그레이드 후 출고 프리셋 플러그인 목록이 바뀌면 새 `presets/*.patch.yml`에서 `cordis.patch.yml`을 다시 동기화하고(doctrine suffix와 `compaction-basic` 행의 `auto: false` 압축 중재도 유지) 재설치한다.
|
|
117
157
|
- 프로토콜 행(`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`)은 의도적으로 영어 그대로 바이트 안정으로 둔다 — 현지화하지 않는다.
|
|
118
158
|
- `npm pack --dry-run`은 감사된 50 파일 / ~205 kB 형태를 유지해야 한다(`docs/` 스크린샷은 패키지에 들어가지 않는다).
|
|
119
159
|
|
package/README.md
CHANGED
|
@@ -102,8 +102,48 @@ Everything below is the full set of defaults after a fresh install (authoritativ
|
|
|
102
102
|
|
|
103
103
|
**Intent routing** (unavailable by default; needs a classifier + at least one candidate + the master switch on): `intentEnabled` = off (while off, the Auto entry stays hidden and sessions already on Auto fall through the fallback chain); the classifier route is unset; the classifier type is `chat`; the candidate list is empty (the preset categories join routing only once given a model); cache window `300` s / switch confidence threshold `80` / classification timeout `60000` ms; history `6` messages / `2400` characters; `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
105
|
+
**Context trim**: `trimEnabled` = on; `trimMode` = `auto` (fully automatic); growth gate `22500` tokens + increment `50000` tokens; pressure `60%` / emergency `95%`; protected tail `6` messages; fold cadence cap `6` per hour; side model unset (inherits the session model) — details in the "Automatic context trim" section below.
|
|
106
|
+
|
|
105
107
|
**Out-of-the-box notes**: ① intent routing being unavailable out of the box is by design — three steps to switch it on (classifier, candidates, the master switch); ② Auto's effective window is 200000 out of the box — the guardrail guarantees 0.8×window ≥ force (150000), so the core compaction line (160000) always sits after the smooth-handover line (150000); ③ the most tangible out-of-the-box effect is the watermark trio: 80k nudges delegation / 120k tightens reading / 150k backs up and hands over automatically — no configuration needed.
|
|
106
108
|
|
|
109
|
+
## Automatic context trim
|
|
110
|
+
|
|
111
|
+
Long sessions stay cheap: consumed conversation ranges are folded into compact deterministic summaries — fully automatically, without breaking the provider prompt cache. At an idle boundary the trim engine (`host/context-trim/`) picks the ranges worth folding, a side model writes the summary (only under emergency pressure does a mechanical fold run instead — no side-model call), and the fold is committed to the session's fold state. From then on every outbound request is rebuilt from that state — summary blocks replace the folded ranges, the live tail stays untouched. The stored session is never rewritten, and nothing ever happens mid-stream.
|
|
112
|
+
|
|
113
|
+
Automation levels (`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`** — measure only: usage and cache-hit sampling still runs; no banner, no folds.
|
|
116
|
+
- **`advisory`** — the session model folds itself: the `ctx_trim_fold` and `ctx_trim_status` tools plus the protocol head are exposed for it.
|
|
117
|
+
- **`auto`** (default) — everything above plus automatic folds at the idle boundary, in three tiers: a growth gate (growth ≥ `trimGrowthTokens` measured from the last fold's post-fold low — the anchor that keeps the gate armed after folds committing at high view points — AND a contiguous compressible increment ≥ `trimIncrementTokens`), a pressure tier (`trimPressurePercent` of the context window), and an emergency tier (`trimEmergencyPercent` — a mechanical fold with its own cooldown).
|
|
118
|
+
|
|
119
|
+
All keys live in Settings → dsh-switchman; defaults from `host/config.js`:
|
|
120
|
+
|
|
121
|
+
| Key | Default | Meaning |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | Master switch. OFF disables folding and metrics entirely (the listener degrades to a pure pass-through). |
|
|
124
|
+
| `trimMode` | `auto` | `off` measure only / `advisory` model-driven folds / `auto` system-driven folds. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | Growth gate: fold when the outbound view grew this much since the last fold. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | Gate companion: the contiguous compressible increment must also reach this size. |
|
|
127
|
+
| `trimPressurePercent` | `60` | Pressure tier: fold when view usage reaches this percent of the context window. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | Emergency tier: forced mechanical fold (no side-model call) at this percent. |
|
|
129
|
+
| `trimWindowTokens` | `0` | Effective-window cap for tier math: tiers are computed against min(model window, cap). `0` = follow `wmForceTokens`. |
|
|
130
|
+
| `trimProtectedTail` | `6` | The last N messages are never folded. |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | Side-model fold cadence cap per rolling hour (emergency folds are exempt). |
|
|
132
|
+
| `trimSideModel` | unset | Route for the summary side model. Empty = inherit the session's current model. |
|
|
133
|
+
| `trimStateDir` | unset | Fold-state directory override. Empty = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
135
|
+
**Trigger paths.** Tier checks run at the idle boundary and, as a fallback for hosts where idle status events are unreachable, after each model-stream completion (throttled to one evaluation per 60 s per session). Every decision — folds and no-ops alike — is appended as one JSON line to `decisions.log` in the trim state directory (see `trimStateDir`), giving folds an offline audit trail.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
**Host-compaction epochs.** Fold refs are anchored in message ids and content hashes, so a host-side compaction that replaces the re-send history ages the whole ledger out at once: no block locates, the view silently falls back to raw history (fail-open — the decision log records `view-applied applied=0`), and the plugin re-anchors its growth baseline at the post-compaction view on the next request. The host compaction is thus the backstop trim layer, and plugin folds do the fine-grained work within one host epoch. Some dispatches hand out fully frozen request arrays or option objects; for those the plugin fails open (`injected=none` in the decision log) while the mutable dispatch that produces the model response still receives the folded view.
|
|
139
|
+
**How folds preserve cache hits.** Every fold re-pays the prefix once; the goal is amortized cost, not a perfect hit rate. The engine enforces the cache contract: folds are append-only — the frontier only moves forward and the frozen zone is never edited again; the view is rebuilt deterministically from (history, fold state), so the serialized prefix stays byte-identical between folds and the provider cache keeps hitting; fold boundaries never split an assistant tool-call from its tool result; the last `trimProtectedTail` messages are exempt; and everything fails open — an internal error degrades to a pass-through, never a broken request.
|
|
140
|
+
|
|
141
|
+
**Compaction arbitration.** Two automatic trimmers over one history would double-summarize and destroy each other's frontier, so `cordis.patch.yml` sets `auto: false` on the host's `dsh-compaction-basic` rows: context-trim becomes the single semantic trimmer. Manual `/compact` keeps working, and the force-tier handover (which borrows that same manual path) is untouched. Overflow recovery moves to trim: an over-window attempt fails once, then the emergency tier folds the view so the next attempt fits.
|
|
142
|
+
|
|
143
|
+
**Fork inheritance.** A forked session (a subagent fork or the handover backup) inherits the parent's fold state copy-on-fork — but only when the parent state exists and the child's history actually resolves the parent's frontier; otherwise the child starts clean. One inheritance per child, idempotent across restarts.
|
|
144
|
+
|
|
145
|
+
**The watermark reads the view.** The watermark banner reports the outbound view's token count (what the model actually sees after folding) instead of the stored tally, so a heavily folded session no longer pins the watermark at the hard tier.
|
|
146
|
+
|
|
107
147
|
## How it works
|
|
108
148
|
|
|
109
149
|
- The host half (`index.js` + `host/`) injects the byte-stable system-prompt sections (language / lanes / watermark protocol / teams) plus the live watermark line through the tail runtime-context snapshot (a channel that appends instead of rewriting the prompt head, so the provider prompt cache stays intact), the read-budget plus enforce double gate, and four slash commands (the ctx trio + `/vision`). A saved setting takes effect at the very next prompt assembly — no restart.
|
|
@@ -113,7 +153,7 @@ Everything below is the full set of defaults after a fresh install (authoritativ
|
|
|
113
153
|
|
|
114
154
|
## Maintenance notes
|
|
115
155
|
|
|
116
|
-
- After a DSH upgrade, if the factory preset plugin list changed, re-sync `cordis.patch.yml` from the new `presets/*.patch.yml` (keeping the doctrine suffix), then reinstall.
|
|
156
|
+
- After a DSH upgrade, if the factory preset plugin list changed, re-sync `cordis.patch.yml` from the new `presets/*.patch.yml` (keeping the doctrine suffix and the compaction arbitration — `auto: false` on the `compaction-basic` rows), then reinstall.
|
|
117
157
|
- Protocol lines (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) are deliberately English and byte-stable — don't localize them.
|
|
118
158
|
- `npm pack --dry-run` should keep the audited 50-file / ~205 kB shape (`docs/` screenshots stay out of the package).
|
|
119
159
|
- **Zero runtime dependencies — a hard invariant.** Host-plane packages (`@deepseek-ai/schemastery`, cordis, …) are declared as `peerDependencies` only, and the running DSH satisfies them from its own copy. An ordinary `dependencies` entry is physically installed into the profile workspace (`<profile>/node_modules/…`), where it shadows the host's copy for every other profile-resident plugin — this is exactly what crashed the dshmarket plugin market while 1.7.0 carried schemastery as a dependency (two schemastery instances in one process; the market's schemas no longer matched the host's). `scripts/validate.mjs` fails if a `dependencies` entry ever reappears, so installing, updating, or removing dsh-switchman can never touch what dshmarket or any other community bundle resolves at runtime.
|
package/README.pt.md
CHANGED
|
@@ -102,8 +102,48 @@ Estes são todos os valores logo depois de uma instalação nova (fonte autorita
|
|
|
102
102
|
|
|
103
103
|
**Roteamento por intenção** (indisponível por padrão; são precisos classificador + pelo menos um candidato + ligar a chave mestra): `intentEnabled` = desligado (desligado, a entrada Auto fica oculta e as sessões que já a tinham escolhido caem na cadeia de fallback); rota do classificador sem definir; tipo de classificador `chat`; lista de candidatos vazia (as categorias pré-instaladas só entram no roteamento com um modelo preenchido); janela de cache `300` s / limiar de confiança da troca `80` / timeout de classificação `60000` ms; histórico de `6` mensagens / `2400` caracteres; `intentContextWindow` = `200000`.
|
|
104
104
|
|
|
105
|
+
**Trim de contexto**: `trimEnabled` = ligado; `trimMode` = `auto` (totalmente automático); portão de crescimento `22500` + incremento `50000` tokens; pressão `60%` / emergência `95%`; cauda protegida `6` mensagens; teto de cadência de folds `6` por hora; modelo secundário não definido (herda o modelo da sessão) — detalhes na seção «Trim automático do contexto» abaixo.
|
|
106
|
+
|
|
105
107
|
**Observações de fábrica**: ① o roteamento por intenção vir indisponível de fábrica é proposital — três passos para ligar (classificador, candidatos, chave); ② a janela efetiva do Auto já nasce em 200000 — o guard-rail garante 0.8×janela ≥ force (150000), então a linha de compactação do núcleo (160000) fica sempre depois da linha de entrega suave (150000); ③ o que mais se sente de fábrica é o trio de níveis: 80k lembra de delegar / 120k aperta a leitura / 150k faz backup e entrega sozinho — sem nenhuma configuração.
|
|
106
108
|
|
|
109
|
+
## Trim automático do contexto
|
|
110
|
+
|
|
111
|
+
Sessões longas ficam baratas: os trechos já consumidos da conversa viram resumos determinísticos compactos — de forma totalmente automática e sem quebrar o cache de prompt do provedor. Numa fronteira de ociosidade, o motor de trim (`host/context-trim/`) escolhe os trechos que valem um fold, um modelo secundário escreve o resumo (só sob pressão de emergência rola um fold mecânico sem chamada ao modelo secundário) e o fold é gravado no estado de folds da sessão. A partir daí, toda requisição de saída é reconstruída desse estado — blocos de resumo substituem os trechos dobrados e a cauda viva fica intacta. A sessão armazenada nunca é reescrita, e nada acontece no meio de um stream.
|
|
112
|
+
|
|
113
|
+
Níveis de automação (`trimMode`):
|
|
114
|
+
|
|
115
|
+
- **`off`** — só medição: a amostragem de uso e de acertos de cache continua rodando; sem banner, sem folds.
|
|
116
|
+
- **`advisory`** — o modelo da sessão dobra sozinho: as ferramentas `ctx_trim_fold` e `ctx_trim_status` mais o cabeçalho de protocolo ficam expostas.
|
|
117
|
+
- **`auto`** (padrão) — tudo isso mais folds automáticos na fronteira de ociosidade, em três degraus: um portão de crescimento (crescimento ≥ `trimGrowthTokens` medido a partir da mínima pós-dobra do último fold — a âncora que mantém o portão armado após dobras confirmadas em pontos altos da view — E um incremento comprimível contíguo ≥ `trimIncrementTokens`), um degrau de pressão (`trimPressurePercent` da janela de contexto) e um degrau de emergência (`trimEmergencyPercent` — um fold mecânico com cooldown próprio).
|
|
118
|
+
|
|
119
|
+
Todas as chaves ficam em Configurações → dsh-switchman; os padrões vêm de `host/config.js`:
|
|
120
|
+
|
|
121
|
+
| Chave | Padrão | Significado |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| `trimEnabled` | `true` | Chave mestra. Desligado desativa folds e métricas por completo (o listener degrada a puro pass-through). |
|
|
124
|
+
| `trimMode` | `auto` | `off` só medição / `advisory` folds conduzidos pelo modelo / `auto` folds conduzidos pelo sistema. |
|
|
125
|
+
| `trimGrowthTokens` | `22500` | Portão de crescimento: dobra quando a view de saída crescer isso desde o último fold. |
|
|
126
|
+
| `trimIncrementTokens` | `50000` | Companheiro do portão: o incremento comprimível contíguo também precisa alcançar esse tamanho. |
|
|
127
|
+
| `trimPressurePercent` | `60` | Degrau de pressão: dobra quando o uso da view alcança essa porcentagem da janela de contexto. |
|
|
128
|
+
| `trimEmergencyPercent` | `95` | Degrau de emergência: fold mecânico forçado (sem chamada ao modelo secundário) nessa porcentagem. |
|
|
129
|
+
| `trimWindowTokens` | `0` | Limite de janela efetivo para o cálculo dos níveis: calculado sobre min(janela do modelo, limite). `0` = segue `wmForceTokens`. |
|
|
130
|
+
| `trimProtectedTail` | `6` | As últimas N mensagens nunca são dobradas. |
|
|
131
|
+
| `trimMaxFoldsPerHour` | `6` | Teto de cadência de folds por hora rolante para o modelo secundário (os de emergência ficam fora). |
|
|
132
|
+
| `trimSideModel` | não definida | Rota do modelo secundário que escreve os resumos. Vazia = herdar o modelo atual da sessão. |
|
|
133
|
+
| `trimStateDir` | não definido | Sobrepõe o diretório do estado de folds. Vazio = `<dshHome>/.dsh-switchman/state/trim/`. |
|
|
134
|
+
|
|
135
|
+
**Caminhos do gatilho.** As verificações de degraus rodam na fronteira de ociosidade e, como fallback para hosts onde os eventos de estado de ociosidade são inalcançáveis, após cada conclusão do fluxo do modelo (limitadas a uma avaliação a cada 60 s por sessão). Cada decisão — folds e no-ops igualmente — é anexada como uma linha JSON a `decisions.log` no diretório do estado de folds (veja `trimStateDir`), dando aos folds uma trilha de auditoria offline.
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
**Épocas de compactação do host.** As referências de fold são ancoradas em ids de mensagens e hashes de conteúdo; quando o próprio host compacta o histórico reenviado, o livro inteiro envelhece de uma vez: nenhum bloco se localiza, a view retrocede silenciosamente ao histórico bruto (fail-open — o registro de decisões anota `view-applied applied=0`) e o plugin reancora sua linha de base de crescimento na view pós-compactação na requisição seguinte. A compactação do host é, assim, a camada de aparo de último recurso; os folds do plugin fazem o trabalho fino dentro de uma época do host. Alguns despachos entregam arrays de solicitação ou objetos de opções totalmente congelados; para eles o plugin falha abertamente (`injected=none` no registro de decisões), enquanto o despacho mutável que produz a resposta do modelo ainda recebe a visão dobrada.
|
|
139
|
+
**Como os folds preservam acertos de cache.** Cada fold repaga o prefixo uma vez; a meta é custo amortizado, não taxa de acerto perfeita. O motor faz valer o contrato de cache: folds são somente-acréscimo — a frontier só avança e a zona congelada nunca é editada de novo; a view é reconstruída de forma determinística a partir de (histórico, estado de folds), então o prefixo serializado fica idêntico byte a byte entre folds e o cache do provedor continua acertando; as fronteiras de fold jamais separam uma tool-call do assistant do seu resultado; as últimas `trimProtectedTail` mensagens ficam isentas; e tudo falha aberto — um erro interno degrada a pass-through, nunca a uma requisição quebrada.
|
|
140
|
+
|
|
141
|
+
**Arbitragem da compactação.** Dois trimmers automáticos sobre o mesmo histórico resumiriam duas vezes e destruiriam a frontier um do outro, então o `cordis.patch.yml` põe `auto: false` nas linhas do `dsh-compaction-basic` do host: o context-trim vira o único trimmer semântico. O `/compact` manual continua funcionando, e a entrega do degrau force (que empresta justamente esse caminho manual) fica intacta. A recuperação de overflow passa para o trim: a tentativa acima da janela falha uma vez, depois o degrau de emergência dobra a view para a próxima tentativa caber.
|
|
142
|
+
|
|
143
|
+
**Herança de fork.** Uma sessão forkada (fork de subagente ou backup de entrega) herda o estado de folds do pai por cópia-no-fork — mas só quando o estado do pai existe e o histórico do filho realmente resolve a frontier do pai; senão o filho começa limpo. Uma herança por filho, idempotente entre reinícios.
|
|
144
|
+
|
|
145
|
+
**O banner de níveis lê a view.** O banner de níveis informa a contagem de tokens da view de saída (o que o modelo de fato vê depois da dobra) em vez da soma armazenada — uma sessão muito dobrada não crava mais o nível no degrau hard.
|
|
146
|
+
|
|
107
147
|
## Como funciona
|
|
108
148
|
|
|
109
149
|
- A metade Host (`index.js` + `host/`) injeta as seções byte-estáveis do system prompt (idiomas / faixas / protocolo do nível de água / equipe) mais a linha de nível de água ao vivo pelo snapshot de runtime-context do final (um canal que acrescenta em vez de reescrever o cabeçalho do prompt, então o cache de prompt do provedor fica intacto), além da dupla trava de orçamento de leitura + enforce e os quatro comandos slash (o trio ctx mais `/vision`). Toda configuração salva já vale na montagem do prompt seguinte, sem reinício.
|
|
@@ -113,7 +153,7 @@ Estes são todos os valores logo depois de uma instalação nova (fonte autorita
|
|
|
113
153
|
|
|
114
154
|
## Manutenção
|
|
115
155
|
|
|
116
|
-
- Depois de um upgrade do DSH que mude a lista de plugins dos presets de fábrica, ressincronize `cordis.patch.yml` a partir dos novos `presets/*.patch.yml` (mantenha o doctrine suffix) e reinstale.
|
|
156
|
+
- Depois de um upgrade do DSH que mude a lista de plugins dos presets de fábrica, ressincronize `cordis.patch.yml` a partir dos novos `presets/*.patch.yml` (mantenha o doctrine suffix e a arbitragem da compactação — `auto: false` nas linhas do `compaction-basic`) e reinstale.
|
|
117
157
|
- As linhas de protocolo (`[SWITCHMAN:LANG|POOLS|WATERMARK|TEAMS]`) ficam deliberadamente em inglês e estáveis a byte — não as localize.
|
|
118
158
|
- `npm pack --dry-run` deve continuar na forma auditada de 50 arquivos / ~205 kB (os screenshots de `docs/` não vão no pacote).
|
|
119
159
|
|