@jmanuelcorral/openteam 0.18.1 → 0.20.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.
Files changed (162) hide show
  1. package/.opencode/openteam.example.json +23 -14
  2. package/AGENTS.md +16 -2
  3. package/README.es.md +300 -209
  4. package/README.md +300 -139
  5. package/dist/capabilities/classify.d.ts.map +1 -1
  6. package/dist/capabilities/normalize.d.ts.map +1 -1
  7. package/dist/certificates/graph-release-certificate.json +2 -2
  8. package/dist/certificates/graph-shadow-certificate.json +2 -2
  9. package/dist/cli/consoleServe.d.ts +16 -0
  10. package/dist/cli/consoleServe.d.ts.map +1 -1
  11. package/dist/cli/graphOperator.d.ts +10 -1
  12. package/dist/cli/graphOperator.d.ts.map +1 -1
  13. package/dist/cli/lifecycleHistoryProvider.d.ts +21 -0
  14. package/dist/cli/lifecycleHistoryProvider.d.ts.map +1 -0
  15. package/dist/cli.d.ts +3 -1
  16. package/dist/cli.d.ts.map +1 -1
  17. package/dist/cli.js +6841 -1555
  18. package/dist/commands/agents.d.ts +16 -4
  19. package/dist/commands/agents.d.ts.map +1 -1
  20. package/dist/commands/dispatch.d.ts.map +1 -1
  21. package/dist/commands/doctor.d.ts.map +1 -1
  22. package/dist/commands/local.d.ts +4 -5
  23. package/dist/commands/local.d.ts.map +1 -1
  24. package/dist/commands/report.d.ts +6 -6
  25. package/dist/commands/report.d.ts.map +1 -1
  26. package/dist/commands/rolesInit.d.ts +10 -12
  27. package/dist/commands/rolesInit.d.ts.map +1 -1
  28. package/dist/commands/setup.d.ts +5 -13
  29. package/dist/commands/setup.d.ts.map +1 -1
  30. package/dist/commands/yolo.d.ts +2 -4
  31. package/dist/commands/yolo.d.ts.map +1 -1
  32. package/dist/config/errors.d.ts.map +1 -1
  33. package/dist/config/executionPolicyDomains.d.ts +18 -0
  34. package/dist/config/executionPolicyDomains.d.ts.map +1 -0
  35. package/dist/config/migrations.d.ts +9 -2
  36. package/dist/config/migrations.d.ts.map +1 -1
  37. package/dist/config/persist.d.ts.map +1 -1
  38. package/dist/config/runtime.d.ts +2 -0
  39. package/dist/config/runtime.d.ts.map +1 -1
  40. package/dist/config/schema.d.ts +128 -13
  41. package/dist/config/schema.d.ts.map +1 -1
  42. package/dist/console/assets.d.ts +22 -1
  43. package/dist/console/assets.d.ts.map +1 -1
  44. package/dist/console/configView.d.ts +2 -7
  45. package/dist/console/configView.d.ts.map +1 -1
  46. package/dist/console/render.d.ts +12 -0
  47. package/dist/console/render.d.ts.map +1 -1
  48. package/dist/console/types.d.ts +2 -2
  49. package/dist/console/types.d.ts.map +1 -1
  50. package/dist/context/schema.d.ts +13 -7
  51. package/dist/context/schema.d.ts.map +1 -1
  52. package/dist/graph/certificate.d.ts.map +1 -1
  53. package/dist/graph/langgraph/adapter.d.ts +7 -8
  54. package/dist/graph/langgraph/adapter.d.ts.map +1 -1
  55. package/dist/graph/langgraph/certification.d.ts +5 -0
  56. package/dist/graph/langgraph/certification.d.ts.map +1 -1
  57. package/dist/graph/langgraph/checkpointReplay.d.ts.map +1 -1
  58. package/dist/graph/langgraph/engine.d.ts +2 -2
  59. package/dist/graph/langgraph/engine.d.ts.map +1 -1
  60. package/dist/graph/langgraph/types.d.ts +11 -6
  61. package/dist/graph/langgraph/types.d.ts.map +1 -1
  62. package/dist/graph/privacyPolicy.d.ts +6 -30
  63. package/dist/graph/privacyPolicy.d.ts.map +1 -1
  64. package/dist/index.d.ts +1 -9
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +5992 -1390
  67. package/dist/lifecycle/contracts.d.ts +618 -0
  68. package/dist/lifecycle/contracts.d.ts.map +1 -0
  69. package/dist/lifecycle/historyReader.d.ts +11 -0
  70. package/dist/lifecycle/historyReader.d.ts.map +1 -0
  71. package/dist/lifecycle/historySourceError.d.ts +7 -0
  72. package/dist/lifecycle/historySourceError.d.ts.map +1 -0
  73. package/dist/lifecycle/project.d.ts +3 -0
  74. package/dist/lifecycle/project.d.ts.map +1 -0
  75. package/dist/lifecycle/root.d.ts +3 -0
  76. package/dist/lifecycle/root.d.ts.map +1 -0
  77. package/dist/lifecycle/runtimeRecorder.d.ts +6 -0
  78. package/dist/lifecycle/runtimeRecorder.d.ts.map +1 -0
  79. package/dist/lifecycle/schema.d.ts +487 -0
  80. package/dist/lifecycle/schema.d.ts.map +1 -0
  81. package/dist/mcp/teamMemory.d.ts +2 -2
  82. package/dist/mcp/teamMemory.d.ts.map +1 -1
  83. package/dist/messages/commands.d.ts +22 -35
  84. package/dist/messages/commands.d.ts.map +1 -1
  85. package/dist/messages/executionSetup.d.ts +116 -0
  86. package/dist/messages/executionSetup.d.ts.map +1 -0
  87. package/dist/messages/index.d.ts +2 -0
  88. package/dist/messages/index.d.ts.map +1 -1
  89. package/dist/messages/lifecycle.d.ts +95 -0
  90. package/dist/messages/lifecycle.d.ts.map +1 -0
  91. package/dist/messages/lifecycleRuntime.d.ts +4 -0
  92. package/dist/messages/lifecycleRuntime.d.ts.map +1 -0
  93. package/dist/messages/lifecycleStorage.d.ts +4 -0
  94. package/dist/messages/lifecycleStorage.d.ts.map +1 -0
  95. package/dist/messages/memoryTool.d.ts +17 -0
  96. package/dist/messages/memoryTool.d.ts.map +1 -0
  97. package/dist/messages/orchestration.d.ts +16 -0
  98. package/dist/messages/orchestration.d.ts.map +1 -0
  99. package/dist/messages/routing.d.ts +9 -0
  100. package/dist/messages/routing.d.ts.map +1 -0
  101. package/dist/opencodeArtifacts/orchestratorAgent.d.ts +3 -5
  102. package/dist/opencodeArtifacts/orchestratorAgent.d.ts.map +1 -1
  103. package/dist/orchestrator/coordinator.d.ts +30 -13
  104. package/dist/orchestrator/coordinator.d.ts.map +1 -1
  105. package/dist/orchestrator/graphEffects.d.ts +10 -11
  106. package/dist/orchestrator/graphEffects.d.ts.map +1 -1
  107. package/dist/orchestrator/graphIngress.d.ts +5 -0
  108. package/dist/orchestrator/graphIngress.d.ts.map +1 -1
  109. package/dist/orchestrator/graphRuntime.d.ts +13 -1
  110. package/dist/orchestrator/graphRuntime.d.ts.map +1 -1
  111. package/dist/orchestrator/outputContract.d.ts +5 -6
  112. package/dist/orchestrator/outputContract.d.ts.map +1 -1
  113. package/dist/orchestrator/roles.d.ts +25 -2
  114. package/dist/orchestrator/roles.d.ts.map +1 -1
  115. package/dist/orchestrator/runtimeSelection.d.ts.map +1 -1
  116. package/dist/orchestrator/subsessions.d.ts +52 -1
  117. package/dist/orchestrator/subsessions.d.ts.map +1 -1
  118. package/dist/plugin/availability.d.ts +15 -2
  119. package/dist/plugin/availability.d.ts.map +1 -1
  120. package/dist/plugin/diagnostics.d.ts +1 -0
  121. package/dist/plugin/diagnostics.d.ts.map +1 -1
  122. package/dist/plugin/hooks.d.ts +21 -2
  123. package/dist/plugin/hooks.d.ts.map +1 -1
  124. package/dist/plugin/memoryTool.d.ts +3 -3
  125. package/dist/plugin/memoryTool.d.ts.map +1 -1
  126. package/dist/plugin/modelOwnership.d.ts +15 -0
  127. package/dist/plugin/modelOwnership.d.ts.map +1 -0
  128. package/dist/plugin/orchestrateTool.d.ts +53 -3
  129. package/dist/plugin/orchestrateTool.d.ts.map +1 -1
  130. package/dist/router/chooseModel.d.ts.map +1 -1
  131. package/dist/router/cost.d.ts +1 -1
  132. package/dist/router/cost.d.ts.map +1 -1
  133. package/dist/router/executionPolicy.d.ts +44 -0
  134. package/dist/router/executionPolicy.d.ts.map +1 -0
  135. package/dist/router/frontierBaseline.d.ts.map +1 -1
  136. package/dist/router/types.d.ts +10 -4
  137. package/dist/router/types.d.ts.map +1 -1
  138. package/dist/storage/lifecycle/codec.d.ts +19 -0
  139. package/dist/storage/lifecycle/codec.d.ts.map +1 -0
  140. package/dist/storage/lifecycle/fsLifecycleJournal.d.ts +3 -0
  141. package/dist/storage/lifecycle/fsLifecycleJournal.d.ts.map +1 -0
  142. package/dist/storage/lifecycle/fsLifecycleSupport.d.ts +17 -0
  143. package/dist/storage/lifecycle/fsLifecycleSupport.d.ts.map +1 -0
  144. package/dist/storage/lifecycle/fsLifecycleWriterLivenessProbe.d.ts +3 -0
  145. package/dist/storage/lifecycle/fsLifecycleWriterLivenessProbe.d.ts.map +1 -0
  146. package/dist/telemetry/aggregate.d.ts +4 -4
  147. package/dist/telemetry/aggregate.d.ts.map +1 -1
  148. package/dist/telemetry/diagnostics.d.ts.map +1 -1
  149. package/dist/telemetry/events.d.ts +6 -6
  150. package/dist/telemetry/otel.d.ts.map +1 -1
  151. package/dist/telemetry/types.d.ts +3 -3
  152. package/dist/web/configApi.d.ts +3 -1
  153. package/dist/web/configApi.d.ts.map +1 -1
  154. package/dist/web/graphRoute.d.ts +39 -1
  155. package/dist/web/graphRoute.d.ts.map +1 -1
  156. package/dist/web/server.d.ts +19 -0
  157. package/dist/web/server.d.ts.map +1 -1
  158. package/dist/web/start.d.ts +11 -0
  159. package/dist/web/start.d.ts.map +1 -1
  160. package/dist/web/watch.d.ts +17 -2
  161. package/dist/web/watch.d.ts.map +1 -1
  162. package/package.json +1 -1
package/README.es.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 🌐 **Language / Idioma:** [English](README.md) · **Español** (este documento)
4
4
 
5
- **openteam — plugin de opencode con routing coste-consciente local-first, fallback FRONTIER cheapest-capable y orquestación multiagente a demanda.**
5
+ **openteam — ejecución de modelos local, frontier y mixed controlada por el operador para opencode, con selección automática cheapest-capable y orquestación multiagente a demanda.**
6
6
 
7
7
  > 📖 **Sitio de documentación:** <https://jmanuelcorral.github.io/openteam/es/> (también en [English](https://jmanuelcorral.github.io/openteam/))
8
8
 
@@ -13,6 +13,7 @@
13
13
  - [Requisitos](#requisitos)
14
14
  - [Instalación](#instalación)
15
15
  - [Quickstart: `openteam setup`](#quickstart-openteam-setup)
16
+ - [El agente `openteam`](#el-agente-openteam)
16
17
  - [Probar en otra máquina](#probar-en-otra-máquina)
17
18
  - [Actualizar openteam](#actualizar-openteam)
18
19
  - [Configuración](#configuración)
@@ -28,21 +29,29 @@
28
29
 
29
30
  ## Qué es y por qué existe
30
31
 
31
- openteam añade a opencode una capa de routing y orquestación para ahorrar tokens y coste frontier sin perder calidad ni privacidad. La estrategia por defecto es **local-first**: tareas triviales, resúmenes, documentación sencilla y diffs pequeños intentan usar runtimes locales; tareas de arquitectura, seguridad, refactors multiarchivo, tool calling crítico o debugging ambiguo escalan a **FRONTIER cheapest-capable**.
32
+ openteam añade a opencode una capa de routing y orquestación. El operador elige
33
+ un dominio global **local**, **frontier** o **mixed**; las políticas del
34
+ coordinador y de los workers pueden fijar un modelo exacto o usar selección
35
+ `"auto"` cheapest-capable dentro de ese dominio.
32
36
 
33
- El router mantiene una garantía de privacidad: con `privacyMode: "forceLocalOnSensitive"`, una tarea marcada como `privacySensitive` no escala a frontier.
37
+ openteam **no** inspecciona el contenido del prompt para inferir sensibilidad
38
+ antes de una llamada frontier. Para prohibir frontier, usa `local` globalmente o
39
+ estrecha un agente a `local` bajo el modo global `mixed`.
34
40
 
35
41
  ## Características
36
42
 
37
43
  - Routing por turno desde el hook `chat.message`, mutando `output.message.model` antes de que opencode persista el mensaje.
38
44
  - Registro de runtimes locales OpenAI-compatible: Ollama, LM Studio, Lemonade Server y Foundry Local.
39
- - Clasificador local JSON con fallback heurístico determinista.
40
45
  - Perfiles de capacidad desde Models.dev, con cache y fallback curado cuando el catálogo no está disponible.
41
- - Selección frontier **cheapest-capable** por coste blended `0.75 * inputUSD + 0.25 * outputUSD`.
46
+ - Selección automática **cheapest-capable** por coste, disponibilidad, soporte de tools y contexto dentro del dominio permitido.
42
47
  - Presupuestos por sesión, mes y tokens frontier por sesión.
43
48
  - Telemetría `CostRecord` JSONL hash-only: guarda `promptHash`, métricas de coste y decisión, nunca prompts crudos.
44
- - Orquestación multiagente con `runRoleTask` / `runRoleTasks`, subsesiones SDK y modelo explícito en `client.session.prompt({ body: { model } })`.
49
+ - Pines exactos o `"auto"` por agente, fallbacks ordenados opcionales y relevo acotado de modelo para nodos incompletos.
50
+ - Orquestación multiagente con subsesiones SDK y modelo explícito en `client.session.prompt({ body: { model } })`.
45
51
  - Refresh de disponibilidad local al arrancar y en eventos `session.created` / `session.idle`.
52
+ - Una [línea de tiempo de agentes](docs/es/guide/agent-timeline.md) solo de
53
+ metadatos, con historial duradero del coordinador y los intentos, cursor
54
+ histórico y avisos de actualización en vivo.
46
55
 
47
56
  ## Requisitos
48
57
 
@@ -78,99 +87,16 @@ Para la carga directa desde opencode, basta con referenciar el paquete:
78
87
  "$schema": "https://opencode.ai/config.json",
79
88
  "model": "anthropic/claude-sonnet-4-5",
80
89
  "small_model": "ollama/qwen3:8b",
81
- "plugin": [
82
- [
83
- "@jmanuelcorral/openteam",
84
- {
85
- "baseline": {
86
- "mode": "auto",
87
- "pinnedModel": null,
88
- "hardDefault": {
89
- "providerID": "anthropic",
90
- "modelID": "claude-sonnet-4-5"
91
- }
92
- },
93
- "router": {
94
- "mode": "balanced",
95
- "localDefault": {
96
- "providerID": "ollama",
97
- "modelID": "qwen3:8b"
98
- },
99
- "trivialPromptMaxChars": 280,
100
- "frontierPromptMinChars": 2000
101
- },
102
- "local": {
103
- "runtimes": [
104
- {
105
- "id": "ollama",
106
- "enabled": true,
107
- "baseURL": "http://localhost:11434/v1",
108
- "defaultModel": {
109
- "providerID": "ollama",
110
- "modelID": "qwen3:8b"
111
- }
112
- },
113
- {
114
- "id": "lmstudio",
115
- "enabled": true,
116
- "baseURL": "http://localhost:1234/v1",
117
- "defaultModel": {
118
- "providerID": "lmstudio",
119
- "modelID": "qwen2.5-coder-local"
120
- }
121
- }
122
- ]
123
- },
124
- "budgets": {
125
- "sessionUSD": 2,
126
- "monthlyUSD": 30,
127
- "frontierTokensPerSession": 250000,
128
- "hardStopOnBudgetExhaustion": false
129
- },
130
- "privacyMode": "forceLocalOnSensitive",
131
- "telemetry": {
132
- "enabled": true,
133
- "path": ".opencode/openteam-local/telemetry.jsonl"
134
- }
135
- }
136
- ]
137
- ],
138
- "provider": {
139
- "ollama": {
140
- "npm": "@ai-sdk/openai-compatible",
141
- "name": "Ollama (local)",
142
- "options": {
143
- "baseURL": "http://localhost:11434/v1",
144
- "apiKey": "ollama",
145
- "chunkTimeout": 60000
146
- },
147
- "models": {
148
- "qwen3:8b": {
149
- "name": "Qwen3 8B (Ollama)",
150
- "tool_call": true,
151
- "limit": { "context": 32768, "output": 8192 }
152
- }
153
- }
154
- },
155
- "lmstudio": {
156
- "npm": "@ai-sdk/openai-compatible",
157
- "name": "LM Studio (local)",
158
- "options": {
159
- "baseURL": "http://localhost:1234/v1",
160
- "apiKey": "lm-studio"
161
- },
162
- "models": {
163
- "qwen2.5-coder-local": {
164
- "name": "Qwen2.5 Coder Local",
165
- "tool_call": true,
166
- "limit": { "context": 32768, "output": 8192 }
167
- }
168
- }
169
- }
170
- }
90
+ "plugin": ["@jmanuelcorral/openteam"]
171
91
  }
172
92
  ```
173
93
 
94
+ Esos modelos deben existir en tus providers configurados en opencode;
95
+ sustitúyelos por equivalentes disponibles cuando sea necesario.
96
+
97
+ Mantén la política del operador en `.opencode/openteam.json`, no dentro de la
98
+ declaración del plugin. `openteam setup` crea ambos archivos.
99
+
174
100
  ### Opción B: ruta de desarrollo
175
101
 
176
102
  Durante desarrollo puedes cargar un plugin local desde `.opencode/plugins/openteam.ts`:
@@ -178,33 +104,29 @@ Durante desarrollo puedes cargar un plugin local desde `.opencode/plugins/opente
178
104
  ```jsonc
179
105
  {
180
106
  "$schema": "https://opencode.ai/config.json",
181
- "plugin": [
182
- [
183
- "./.opencode/plugins/openteam.ts",
184
- {
185
- "router": {
186
- "mode": "balanced",
187
- "localDefault": {
188
- "providerID": "ollama",
189
- "modelID": "qwen3:8b"
190
- }
191
- },
192
- "telemetry": {
193
- "path": ".opencode/openteam-local/telemetry.jsonl"
194
- }
195
- }
196
- ]
197
- ]
107
+ "plugin": ["./.opencode/plugins/openteam.ts"]
198
108
  }
199
109
  ```
200
110
 
201
- ## Quickstart: `openteam setup`
111
+ La carga por ruta de desarrollo no cambia el límite de configuración: conserva
112
+ la política del operador en `.opencode/openteam.json`.
202
113
 
203
- La forma más rápida de dejar un repositorio listo para opencode + openteam es el comando interactivo `openteam setup`. Detecta los runtimes locales instalados (Ollama, LM Studio, Lemonade Server, Foundry Local) —que son **opcionales**: puedes usar openteam **solo con frontier**, o apuntar a un Ollama/LM Studio/Lemonade Server que corra en **otra máquina de la red local**—, te deja elegir los modelos locales y el modelo **frontier baseline** (ordenados de más barato-capaz a más caro), y genera tres ficheros:
114
+ ## Quickstart: `openteam setup`
204
115
 
205
- - `opencode.json` en la raíz: declara el plugin `@jmanuelcorral/openteam`, los `provider` locales OpenAI-compatible, el `model` frontier y el `small_model` local.
206
- - `.opencode/openteam.json`: la configuración runtime validada de openteam (baseline, routing, runtimes locales, roles del orquestador y privacidad).
116
+ La forma más rápida de dejar un repositorio listo es `openteam setup`. Detecta
117
+ Ollama, LM Studio, Lemonade Server y Foundry Local —todos opcionales—, permite
118
+ elegir modelos locales y el **frontier baseline** (cheapest-capable primero), y
119
+ genera la configuración y los artefactos de agentes/comandos:
120
+
121
+ - `.opencode/opencode.json` en proyectos nuevos, o el
122
+ `.opencode/opencode.json` / `opencode.json` raíz ya existente: declara el
123
+ plugin, los providers locales, el `model` frontier y el `small_model` local.
124
+ - `.opencode/openteam.json`: la configuración runtime validada de openteam
125
+ (dominio, runtimes locales, políticas de modelo del primary/roles, presupuestos
126
+ y reintentos/relevos acotados).
207
127
  - `.opencode/agent/openteam.md`: el **agente primario `openteam`**, visible en el Tab-switcher.
128
+ - `.opencode/agent/<rol>.md` para los destinos estándar, además de entradas
129
+ `.opencode/command/*.md` y el `.opencode/.gitignore` local.
208
130
 
209
131
  ```powershell
210
132
  # Ejecución puntual, sin instalación global
@@ -217,25 +139,60 @@ openteam setup
217
139
 
218
140
  El asistente:
219
141
 
220
- 1. Sondea los runtimes locales y marca los detectados.
221
- 2. Te deja habilitar runtimes (o **ninguno**: puedes usar openteam **solo con modelos frontier**) y, por cada runtime que habilites, elegir si corre **en esta máquina** o **en otra máquina de la red local** (introduciendo su URL, p. ej. `http://192.168.1.50:11434/v1`); luego eliges el modelo por defecto de cada uno (o lo escribes si no se detectan modelos). Si tienes **más de una máquina del mismo tipo** (p. ej. dos hosts LM Studio), declara cada una como una instancia aparte con su propio id (`lmstudio-a`, `lmstudio-b`), URL y modelos. Para cada instancia también pregunta cuántos **slots de generación concurrente** tiene el runtime (por defecto `4`), para que puedas dejar un slot libre para el trabajo interactivo en vez de saturar el servidor.
222
- 3. Ofrece el modelo frontier baseline a partir del **catálogo completo de [Models.dev](https://models.dev)** que openteam ya integra: una lista rápida con los más **baratos-capaces primero** (incluidos los **gratuitos**, etiquetados como `gratis`), una opción **«Ver todos los modelos por proveedor…»** para navegar el catálogo completo, y **«Otro (custom)»** para escribir un `provider/model`. Si el catálogo no se puede cargar (offline), cae a la lista curada.
223
- 4. Pregunta el modo de routing (`balanced`/`economy`/`quality`), la política de privacidad y si quieres activar el **modo YOLO** (auto-aprobar permisos de opencode). Si no habilitas ningún runtime local, avisa de que estás en **modo solo frontier** y recomienda `consentBeforeFrontier` (porque `forceLocalOnSensitive` no tendría destino local).
224
- 5. Si ya existe `opencode.json` o `.opencode/openteam.json`, pide confirmación antes de sobrescribir.
225
-
226
- Tras `setup`, autentica el provider frontier (`opencode auth login`), asegúrate de que tu runtime local (en esta máquina o en la red) esté accesible si lo habilitaste, y abre opencode en el repositorio: openteam enruta local-first automáticamente. Puedes reajustar el baseline después con `openteam baseline set <provider/model>` o `openteam baseline auto`.
142
+ 1. Sondea runtimes locales y primero pregunta cuáles habilitar. Elegir
143
+ **Ninguno** selecciona global `frontier` directamente, sin una pregunta
144
+ redundante sobre los tres modos, y continúa con la selección frontier.
145
+ 2. Para cada runtime habilitado, configura esta máquina u otro host LAN,
146
+ modelos default/thinking/coder y concurrencia. Varias instancias conservan
147
+ identidades distintas de runtime y provider.
148
+ 3. Si hay algún runtime local, elige el modo del equipo (default `mixed`).
149
+ `local` fija el primario al modelo thinking o default del primer runtime;
150
+ `frontier` pide un modelo frontier; `mixed` pregunta si el primario usa ese
151
+ modelo local o el frontier elegido. Las opciones frontier usan el orden
152
+ cheapest-capable de Models.dev, exploración/custom y fallback curado offline.
153
+ 4. Setup escribe una política primaria exacta con `fallbacks: []`, persiste
154
+ cada worker como política parcial compacta `{ "model": "auto" }` y escribe
155
+ límites `2`/`2`. El schema/config manual permiten primary `"auto"` y
156
+ fallbacks primarios, pero setup no los pregunta.
157
+ 5. Elige si activar **YOLO**. Los archivos existentes requieren confirmación
158
+ antes de sobrescribir.
159
+
160
+ Tras `setup`, autentica un provider frontier si las políticas lo permiten,
161
+ comprueba cada runtime local configurado y abre opencode. Reajusta el baseline
162
+ con `openteam baseline set <provider/model>` o `openteam baseline auto`.
163
+
164
+ > **Nota de upgrade:** `privacyMode` es metadata obsoleta e ignorada y ya no impide ejecución
165
+ > frontier. Convierte cualquier restricción necesaria a
166
+ > `router.executionMode: "local"` o a un `executionMode: "local"` por agente
167
+ > bajo el modo global `mixed`.
227
168
 
228
169
  ## El agente `openteam`
229
170
 
230
- `openteam setup` genera un único **agente primario** llamado `openteam` (`.opencode/agent/openteam.md`). Pulsa **Tab** en opencode para seleccionarlo: así sabes explícitamente que estás en modo openteam, mientras el plugin sigue optimizando el modelo por debajo.
171
+ `openteam setup` genera un único **agente primario** llamado `openteam`
172
+ (`.opencode/agent/openteam.md`). Pulsa **Tab** en opencode para seleccionarlo:
173
+ así sabes explícitamente que estás en modo openteam. Su modelo sigue las
174
+ políticas global y del primario; el prompt no elige dominio por ser juzgado
175
+ sensible o complejo.
231
176
 
232
- Ese orquestador **no trae subagentes precreados**. En **cada petición** su primera acción es comprobar si ya existe equipo (`.opencode/openteam/roster.md` + subagentes en `.opencode/agent/`). Si **existe**, reparte el trabajo entre los especialistas adecuados; si **no existe**, entiende las tareas que implica tu petición, diseña el equipo mínimo y **lo crea a demanda** —sin que tengas que pedírselo explícitamente— antes de pasarle esas tareas (escribiendo `.opencode/agent/<nombre>.md` con `mode: subagent`), reutilizando los existentes antes de crear nuevos. Los roles mecánicos/bulk se dejan enrutar a modelos locales y solo se escala a frontier para arquitectura, seguridad o debugging ambiguo. (Este modelo de equipo temático creado a demanda está inspirado en [Squad](https://bradygaster.github.io/squad/); ver [Agradecimientos](#agradecimientos-e-inspiración).)
177
+ El frontmatter primario generado y `opencode.json.model` usan el mismo modelo
178
+ bootstrap exacto. Los workers generados omiten `model` en frontmatter: manda su
179
+ política en `.opencode/openteam.json`. Guardian, scribe y ralph no están
180
+ forzados a local por nombre.
181
+
182
+ Ese orquestador no trae subagentes específicos del proyecto precreados. En cada
183
+ petición comprueba el roster, reutiliza especialistas existentes y crea el equipo
184
+ mínimo a demanda cuando haga falta. La ubicación de modelos viene de las
185
+ políticas globales y por agente, no de clasificar sensibilidad. El router
186
+ unificado puede seguir derivando requisitos de capacidad y complejidad dentro
187
+ del dominio permitido.
233
188
 
234
189
  El equipo tiene **identidad temática**: el orquestador elige (o te pregunta) un **universo** y nombra a cada agente con un personaje de ese universo, registrando el reparto en `.opencode/openteam/roster.md` (fuera de `.opencode/agent/`, para que opencode no lo cargue como un agente fantasma) para que los nombres **persistan** entre sesiones. Además de los roles específicos del proyecto, contempla tres **roles estándar** creados a demanda:
235
190
 
236
- - **scribe** — memoria silenciosa: registra decisiones y aprendizajes en `.opencode/openteam/decisions.md` sin tocar el código (modelo local).
191
+ - **scribe** — memoria silenciosa: registra decisiones y aprendizajes en `.opencode/openteam/decisions.md` sin tocar el código.
237
192
  - **ralph** — automatización y triage: monitoriza el trabajo pendiente, lo prioriza, coordina la ejecución y **escala al humano** ante bloqueos o aprobaciones.
238
- - **guardian** — seguridad y privacidad: **detecta y enmascara datos sensibles** (PII, secretos, API keys, tokens) antes de que salgan a frontier y hace revisión de seguridad; corre siempre en local y respeta `forceLocalOnSensitive`.
193
+ - **guardian** — revisión de seguridad y consejo sobre política. No es un gate
194
+ automático previo a frontier y no tiene requisito local integrado. Configura
195
+ `executionMode: "local"` si debe quedarse local.
239
196
 
240
197
  Antes de delegar, el orquestador **planifica dependencias y paraleliza**: descompone la petición en tareas, y como opencode ejecuta en paralelo todas las llamadas `task` emitidas en un mismo turno (Vercel AI SDK), lanza a la vez las tareas independientes y secuencia por olas solo las que dependen de un resultado previo. El trabajo que colisiona sobre los mismos ficheros se separa en olas distintas para evitar conflictos.
241
198
 
@@ -273,7 +230,9 @@ Para instalar y probar openteam en otro equipo que ya tenga [opencode](https://o
273
230
 
274
231
  4. **Arranca tu runtime local** si lo habilitaste y no estaba activo (p. ej. `ollama serve`, o abre LM Studio / Foundry Local). Si apuntaste a un runtime en **otra máquina de la red**, asegúrate de que sea accesible desde este equipo (host expuesto y puerto abierto); para Ollama esto normalmente implica arrancarlo con `OLLAMA_HOST=0.0.0.0 ollama serve` en la máquina remota. Si configuraste **solo frontier**, sáltate este paso.
275
232
 
276
- 5. **Abre opencode en el repo**, pulsa **Tab** y elige el agente `openteam`. Dale el primer prompt: creará el equipo de subagentes a demanda y enrutará local-first automáticamente.
233
+ 5. **Abre opencode en el repo**, pulsa **Tab** y elige el agente `openteam`.
234
+ Dale el primer prompt: creará el equipo a demanda y ejecutará cada agente
235
+ dentro del dominio configurado.
277
236
 
278
237
  Comprueba el estado con `openteam doctor` (runtimes + config) y el ahorro con `openteam report`.
279
238
 
@@ -303,11 +262,19 @@ Notas al actualizar:
303
262
 
304
263
  ## Configuración
305
264
 
306
- La configuración runtime canónica vive en `.opencode/openteam.json`; este repositorio incluye `.opencode/openteam.example.json` como ejemplo completo. La forma validada por Zod es la de `src/config/schema.ts`. `telemetry` es una opción del plugin leída por `src/index.ts`, no parte del objeto `OpenTeamConfig` persistido.
265
+ La configuración runtime canónica vive en `.opencode/openteam.json`; este
266
+ repositorio incluye `.opencode/openteam.example.json` como ejemplo v2 mínimo y
267
+ completo, no como contrato byte-for-byte para todas las decisiones de setup.
268
+ La serialización canónica v2 es compacta: omite los valores default de las
269
+ heurísticas legacy, conserva overrides no-default para compatibilidad sin
270
+ política y compacta perfiles resueltos a políticas parciales respecto de su
271
+ baseline integrado o sintetizado. La forma validada por Zod es la de
272
+ `src/config/schema.ts`. `telemetry` es una opción del plugin leída por
273
+ `src/index.ts`, no parte del objeto `OpenTeamConfig` persistido.
307
274
 
308
275
  Los archivos de configuración son estrictos: las claves desconocidas fallan
309
276
  cerrado tanto en la CLI como en el plugin en vez de ignorarse en silencio. Los
310
- errores nombran cada ruta rechazada (por ejemplo `router.trivialPromptMxChars`)
277
+ errores nombran cada ruta rechazada (por ejemplo `router.executionMod`)
311
278
  e incluyen una sugerencia de la clave más cercana cuando existe.
312
279
  Esta validación estricta se aplica al archivo de configuración en ambas rutas;
313
280
  las opciones programáticas del plugin son una superficie separada y aún no se
@@ -358,13 +325,15 @@ ejecutas desde un subdirectorio verás "provider not configured" y debes hacer
358
325
 
359
326
  | Key | Tipo | Default | Descripción |
360
327
  | --- | --- | --- | --- |
328
+ | `configVersion` | `2`, input opcional | canónico `2` | Si falta, se trata como v1 y se migra. Un valor no entero o menor que `1` es desconocido; mayor que `2` no está soportado. |
361
329
  | `baseline.mode` | `"auto" \| "pinned"` | `"auto"` | En `auto`, usa perfiles frontier cheapest-capable cuando se pasan al router; en `pinned`, usa `baseline.pinnedModel` si existe. |
362
330
  | `baseline.pinnedModel` | `ModelRef \| null` | `null` | Modelo frontier fijado explícitamente. `ModelRef` usa `{ "providerID": string, "modelID": string }`. |
363
- | `baseline.hardDefault` | `ModelRef` | `{ "providerID": "anthropic", "modelID": "claude-sonnet-4-5" }` | Fallback frontier si no hay perfiles cheapest-capable o pin válido. |
364
- | `router.mode` | `"economy" \| "balanced" \| "quality"` | `"balanced"` | Modo de routing validado y reservado para política. |
331
+ | `baseline.hardDefault` | `ModelRef` | `{ "providerID": "google", "modelID": "gemini-3.5-flash" }` | Fallback offline/de lista curada configurable cuando ningún perfil live o de catálogo utilizable guía la selección automática. No prevalece sobre los perfiles suministrados; `setup` puede escribir el frontier elegido y siguen permitidos los pins explícitos por agente. |
332
+ | `router.executionMode` | `"local" \| "frontier" \| "mixed"`, opcional | efectivo `"mixed"` | Límite duro global. La serialización canónica escribe `"mixed"` si falta. La política de agente puede estrechar `mixed`, nunca ampliar `local` o `frontier`. |
333
+ | `router.mode` | `"economy" \| "balanced" \| "quality"` | `"balanced"` | Ajuste canónico de heurística legacy para callers sin política de agente v2. No selecciona modelos por agente ni sobreescribe `executionMode` ni añade routing por sensibilidad. |
334
+ | `router.trivialPromptMaxChars` | entero positivo | `280` | Umbral legacy de routing mixed sin política. Se conserva para callers compatibles sin política de agente v2; las políticas v2 generadas no dependen de él. |
335
+ | `router.frontierPromptMinChars` | entero positivo | `2000` | Umbral legacy de routing mixed sin política. Se conserva para callers compatibles sin política de agente v2; las políticas v2 generadas no dependen de él. |
365
336
  | `router.localDefault` | `ModelRef \| null` | `null` | Modelo local principal. No configurado por defecto — ningún modelo local se enruta hasta que configures uno con `openteam setup` o manualmente. |
366
- | `router.trivialPromptMaxChars` | `number` entero positivo | `280` | Prompts sin código hasta este tamaño prefieren local. |
367
- | `router.frontierPromptMinChars` | `number` entero positivo | `2000` | Prompts desde este tamaño se tratan como candidatos a frontier si no aplican guards. |
368
337
  | `local.runtimes` | `LocalRuntime[]` | `[]` | Runtimes locales a sondear. Vacío por defecto — ningún runtime está configurado hasta que ejecutes `openteam setup` o añadas una entrada manualmente. |
369
338
  | `local.runtimes[].id` | `string` | requerido | Identidad de instancia, única dentro del array. Libre (`lmstudio-a`, `lemonade-lan`) para que dos máquinas del mismo tipo sean distintas; si se omite `kind`, debe ser en sí mismo un tipo de runtime (retrocompatibilidad). |
370
339
  | `local.runtimes[].kind` | `"ollama" \| "lmstudio" \| "foundry-local" \| "lemonade"` opcional | migra desde `id` | Tipo de runtime que selecciona el adaptador. Opcional: si falta, se usa `id` como tipo, así toda config previa sigue funcionando sin cambios. |
@@ -377,57 +346,121 @@ ejecutas desde un subdirectorio verás "provider not configured" y debes hacer
377
346
  | `budgets.sessionUSD` | `number` positivo opcional | sin límite | Presupuesto frontier por sesión. |
378
347
  | `budgets.monthlyUSD` | `number` positivo opcional | sin límite | Presupuesto frontier mensual. |
379
348
  | `budgets.frontierTokensPerSession` | `number` entero positivo opcional | sin límite | Límite de tokens frontier por sesión. |
380
- | `budgets.hardStopOnBudgetExhaustion` | `boolean` | `false` | Si es `true`, agotar presupuesto devuelve `blockFrontier`; si es `false`, fuerza local. |
381
- | `privacyMode` | `"forceLocalOnSensitive" \| "consentBeforeFrontier" \| "off"` | `"forceLocalOnSensitive"` | Política de privacidad para tareas sensibles. |
382
- | `orchestrator.roles` | `Record<string, AgentRoleProfile>` | `{}` | Perfiles de rol personalizados o sobrescritos, indexados por role ID. Las entradas de config se validan con el mismo schema estricto que los roles integrados y tienen prioridad sobre `TEAM_ROLES`; si una entrada omite `roleID`, se usa la clave del mapa. Los roles desconocidos no declarados aquí siguen usando el fallback neutral y avisan una vez. |
349
+ | `budgets.hardStopOnBudgetExhaustion` | `boolean` | `false` | Controla la acción de presupuesto; nunca permite salir del dominio. |
350
+ | `orchestrator` | objeto opcional | ausente | Contiene políticas de primary/roles y límites de pasadas. |
351
+ | `orchestrator.maxRetries` | entero no negativo opcional | efectivo `2` | Límite superior de pasadas openteam extra por modelo autorizado; `2` efectivo permite hasta tres pasadas. El default se aplica en runtime, no se materializa en el schema. |
352
+ | `orchestrator.maxModelsPerNode` | entero positivo opcional | efectivo `2` | Total de candidatos por nodo: el seleccionado más como máximo un fallback por defecto. El default de runtime no se materializa; combinado con reintentos permite como máximo seis intentos. |
353
+ | `orchestrator.primary` | `ExecutionPolicy` parcial opcional | ausente | Política del coordinador primario; todos sus campos son opcionales. |
354
+ | `orchestrator.roles` | `Record<string, AgentRoleProfile parcial>` raw | `{}` si existe `orchestrator` | Las entradas raw pueden ser parciales. Las cargadas quedan totalmente fusionadas y validadas: primero perfil integrado o, si no existe, sintetizado; después prevalece el override raw. |
383
355
  | `orchestrator.roles.<role>.opencodeAgent` | `string` no vacío opcional | role ID | Nombre del agente opencode al que se despacha ese rol. |
384
- | `orchestrator.roles.<role>.defaultTier` | `"trivial" \| "simple" \| "moderate" \| "hard"` | requerido | Tier base de complejidad antes de aplicar heurística y elevación por permisos. |
385
- | `orchestrator.roles.<role>.minReasoningTier` | `1`–`5` | requerido | Capacidad mínima de razonamiento para candidatos frontier. |
386
- | `orchestrator.roles.<role>.minCodeQualityTier` | `1`–`5` | requerido | Capacidad mínima de calidad de código para candidatos frontier. |
387
- | `orchestrator.roles.<role>.needsToolCallingByDefault` | `boolean` | requerido | Si el rol requiere tool calling salvo que la tarea indique otra cosa. |
388
- | `orchestrator.roles.<role>.preferredFrontierModels` | `Array<ModelRef \| "auto">` | requerido | Modelos frontier preferidos; usa `[]` para un rol local-first sin preferencia frontier explícita. |
389
- | `orchestrator.roles.<role>.localFirst` | `boolean` | requerido | Si el rol conserva la postura local-first normal en vez de forzar frontier para tareas hard. |
356
+ | `orchestrator.primary.executionMode` / `orchestrator.roles.<role>.executionMode` | `"local" \| "frontier" \| "mixed"`, opcional | heredado | Puede estrechar global `mixed`; no contradecir global `local`/`frontier`. |
357
+ | `orchestrator.primary.model` / `orchestrator.roles.<role>.model` | `ModelRef \| "auto"`, opcional | omitir equivale a `"auto"` | Selección exacta o automática determinista entre modelos capaces, disponibles y dentro del dominio. `mixed` prioriza local si es capaz y después cheapest-capable cuando existe coste de catálogo. Pins estáticamente no configurados, fuera del dominio o incapaces conocidos fallan; candidatos temporalmente offline se omiten solo en runtime. Un coste ausente no se inventa como cero. |
358
+ | `orchestrator.primary.fallbacks` / `orchestrator.roles.<role>.fallbacks` | `ModelRef[]`, opcional | derivados para auto; ninguno para pin exacto | Una lista explícita sustituye fallbacks derivados y conserva orden tras deduplicar y omitir el seleccionado. Cada entrada recibe validación estática de identidad/dominio/capacidad antes del límite. Un backup temporalmente offline no invalida un primary sano: se omite para probar el siguiente candidato autorizado. |
359
+ | `privacyMode` | legacy/obsoleto | ninguno | Solo metadata compatible ignorada; se elimina al persistir canónicamente. Al cargarla emite una vez el aviso de migración `privacy-mode-ignored` con el riesgo de egress frontier y el remedio `executionMode: "local"`; el aviso nunca cambia el routing. |
390
360
  | `telemetry.enabled` | `boolean` plugin option | `true` | Activa/desactiva escritura JSONL. |
391
361
  | `telemetry.path` | `string` plugin option | `.opencode/openteam-local/telemetry.jsonl` | Ruta del log `CostRecord` JSONL. |
392
362
 
393
- Ejemplo de auditor de privacidad/seguridad personalizado:
363
+ `router.localOnly` y `router.frontierOnly` siguen como aliases opcionales de
364
+ parseo para cargar archivos antiguos; la migración y las escrituras canónicas
365
+ los sustituyen por `executionMode`. `TaskSignals.privacySensitive?` también
366
+ sigue como campo histórico opcional, pero clasificación, score, rationale y
367
+ routing lo ignoran.
368
+
369
+ Ejemplo de políticas explícitas para coordinador y workers:
370
+
371
+ Los modelos exactos de política siempre son objetos como
372
+ `{ "providerID": "anthropic", "modelID": "claude-sonnet-4-5" }`, nunca un
373
+ scalar `"provider/model"`. El comando baseline de slash/CLI y el campo `model`
374
+ propio de opencode sí usan la notación scalar. Cada modelo del ejemplo debe
375
+ existir en los providers configurados por el operador. Un ID de instancia como
376
+ `lmstudio-b` y un provider ID como `lmstudio` son conceptos distintos; usa la
377
+ identidad de provider configurada para opencode.
394
378
 
395
379
  ```jsonc
396
380
  {
381
+ "configVersion": 2,
382
+ "router": { "executionMode": "mixed" },
397
383
  "orchestrator": {
384
+ "maxRetries": 2,
385
+ "maxModelsPerNode": 2,
386
+ "primary": {
387
+ "executionMode": "frontier",
388
+ "model": "auto"
389
+ },
398
390
  "roles": {
399
- "galadriel": {
400
- "opencodeAgent": "galadriel",
401
- "defaultTier": "moderate",
402
- "minReasoningTier": 3,
403
- "minCodeQualityTier": 3,
404
- "needsToolCallingByDefault": true,
405
- "preferredFrontierModels": [],
406
- "localFirst": true
391
+ "scribe": {
392
+ "executionMode": "local",
393
+ "model": { "providerID": "ollama", "modelID": "qwen3:8b" }
394
+ },
395
+ "integration": {
396
+ "executionMode": "frontier",
397
+ "model": { "providerID": "anthropic", "modelID": "claude-sonnet-4-5" },
398
+ "fallbacks": [
399
+ { "providerID": "google", "modelID": "gemini-3.5-flash" }
400
+ ]
407
401
  }
408
402
  }
409
403
  }
410
404
  }
411
405
  ```
412
406
 
407
+ El `routeKind` resuelto siempre es `local`, `frontier` o `blocked`, nunca
408
+ `mixed`. Solo pueden ejecutarse el modelo seleccionado y la cadena de fallback
409
+ devuelta. Una decisión bloqueada no despacha; su identidad seleccionada es solo
410
+ un valor de coste/referencia. El estrechamiento por presupuesto no puede
411
+ sustituir un modelo local no aprobado: si no queda ningún candidato autorizado,
412
+ el routing bloquea.
413
+
413
414
  ## Uso
414
415
 
415
- En cada turno, openteam deriva señales del prompt (`promptChars`, `hasCode`, `privacySensitive`, `requiresTools` y override de modelo si existe), ejecuta `chooseModel` y asigna `output.message.model`.
416
+ En cada turno, openteam resuelve las políticas global y por agente, filtra por
417
+ dominio, tools y contexto, ordena los candidatos `"auto"` por coste según los
418
+ requisitos de capacidad/complejidad del router unificado y asigna
419
+ `output.message.model`. La sensibilidad del prompt y los metadatos de privacidad
420
+ de Graph no son entradas de routing.
416
421
 
417
422
  La orquestación multiagente usa roles estáticos y subsesiones opencode:
418
423
 
419
- | Rol | Agent opencode | Tier base | Política |
420
- | --- | --- | --- | --- |
421
- | `rusty` | `architect` | `hard` | Arquitectura y decisiones de alto riesgo; frontier auto. |
422
- | `livingston` | `integration` | `moderate` | Integración TS/opencode; tool calling por defecto. |
423
- | `yen` | `local-runtime` | `moderate` | Runtimes locales; local-first con fallback frontier. |
424
- | `basher` | `routing-cost` | `moderate` | Router, coste y presupuesto; local-first. |
425
- | `scribe` | `scribe` | `trivial` | Documentación y resúmenes; local-first. |
426
- | `linus` | `tester` | `simple` | Tests y contratos; local-first con tools. |
424
+ En el trabajo del coordinador, `defaultTier` y los mínimos de capacidad del rol
425
+ son suelos. La clasificación ordinaria de capacidad/complejidad de la tarea
426
+ puede elevar el requisito efectivo para trabajo más difícil, pero no debilitar
427
+ el requisito del rol. El tier efectivo guía routing y telemetría. El vocabulario
428
+ de sensibilidad y la metadata de privacidad de Graph no afectan al routing.
427
429
 
428
- `runRoleTask` ejecuta una subsesión; `runRoleTasks` ejecuta varias con `batchID`. Los roles con `destructive` o `multiFileEdit` elevan el tier antes de elegir modelo.
429
-
430
- Para ver ahorro y decisiones, revisa el JSONL de telemetría. Campos clave: `promptHash`, `promptChars`, `tier`, `routeKind`, `selected`, `rationale`, `estimatedCostUSD`, `baselineCostUSD`, `estimatedSavingsUSD`, `budgetAction`, `tokensIn` y `tokensOut`.
430
+ | Rol | Agent opencode | Política típica |
431
+ | --- | --- | --- |
432
+ | `rusty` | `architect` | Configura `"auto"` o un modelo exacto del dominio. |
433
+ | `livingston` | `integration` | Suele necesitar tools; el dominio es explícito. |
434
+ | `yen` | `local-runtime` | Puede estrecharse a `local` bajo `mixed`. |
435
+ | `basher` | `routing-cost` | Auto puede optimizar coste dentro del dominio. |
436
+ | `scribe` | `scribe` | Sin restricción local integrada; configúrala si procede. |
437
+ | `linus` | `tester` | Configura modelos con tools/contexto suficientes. |
438
+
439
+ `runRoleTask` ejecuta una subsesión; `runRoleTasks` ejecuta varias con
440
+ `batchID`. Los intentos directos y en batch usan la misma ruta lógica estable
441
+ de reporte y deben probar un reporte actual, cambiado cuando proceda,
442
+ sustantivo y duradero antes del éxito. La política de permisos/review está
443
+ separada de la ubicación de modelo.
444
+
445
+ El dispatch SDK de un hijo usa una autorización de modelo de un solo uso y
446
+ acotada a la instancia del plugin, identificada por la sesión hija, el alias de
447
+ agente y el modelo exactos. Cuando el prompt del SDK público vuelve a entrar por
448
+ `chat.message`, solo esa coincidencia conserva el modelo worker autorizado por
449
+ el coordinador; la autorización se libera al terminar el prompt. Los mensajes
450
+ sin coincidencia y los iniciados por el usuario siguen el routing normal. Este
451
+ mecanismo no amplía dominios ni autoriza modelos fuera de `selected` y
452
+ `fallbackChain`.
453
+
454
+ Para consultar el modelo realmente usado, las razones del relevo y las
455
+ estimaciones de coste/ahorro cuando estén disponibles, revisa el JSONL de
456
+ telemetría. Los campos clave incluyen `promptHash`, `promptChars`, `routeKind`,
457
+ `selected`, `rationale`, `estimatedCostUSD`, `baselineCostUSD`,
458
+ `estimatedSavingsUSD`, `budgetAction`, `tokensIn` y `tokensOut`. Un coste de
459
+ modelo desconocido permanece `null`/desconocido, no se convierte en gratis; el
460
+ ahorro es desconocido si falta alguna estimación necesaria. En auto del
461
+ coordinador, el requisito efectivo de capacidad —el suelo del rol más cualquier
462
+ elevación por clasificación de la tarea— determina tanto la capacidad de los
463
+ candidatos como el baseline frontier capaz usado para comparar costes.
431
464
 
432
465
  ## Comandos runtime
433
466
 
@@ -440,8 +473,9 @@ El plugin registra la herramienta `openteam`. Pídele al agente que la use, o in
440
473
  - `show` — muestra el baseline efectivo.
441
474
  - `set` (con `model` en formato `provider/model`) — fija el baseline (modo `pinned`).
442
475
  - `auto` — vuelve a cheapest-capable (modo `auto`).
443
- - `doctor` — diagnóstico de runtimes locales, privacidad y telemetría.
444
- - `report` — resumen de coste y ahorro desde la telemetría.
476
+ - `doctor` — diagnóstico de dominio, política de modelos, runtimes y telemetría.
477
+ - `report` — estimaciones disponibles de coste y ahorro desde la telemetría;
478
+ los valores desconocidos siguen siendo desconocidos.
445
479
 
446
480
  Los cambios de `set`/`auto` se persisten en `.opencode/openteam.json` y aplican en el siguiente arranque del plugin.
447
481
 
@@ -468,7 +502,7 @@ El paquete expone el binario `openteam`. Con instalación global:
468
502
  ```powershell
469
503
  bun add --global @jmanuelcorral/openteam@latest
470
504
  openteam baseline show
471
- openteam baseline set openai/gpt-5-mini
505
+ openteam baseline set anthropic/claude-sonnet-4-5
472
506
  openteam doctor --config .opencode/openteam.json
473
507
  openteam agents
474
508
  openteam console
@@ -487,25 +521,10 @@ Flags: `--config <path>` y `--telemetry <path>` sobrescriben las rutas por defec
487
521
 
488
522
  ### Ver el LLM de cada agente: `openteam agents`
489
523
 
490
- Lista los agentes de `.opencode/agent/` indicando **qué LLM usa cada uno**: si es **local** (Ollama/LM Studio/Lemonade/Foundry, sin coste de tokens) o **frontier** (consume tu suscripción), y el **proveedor** (Anthropic, OpenAI, GitHub Copilot, Google…). Los agentes sin `model` propio **heredan** el default de `opencode.json` (que openteam enruta local-first por mensaje).
491
-
492
- ```powershell
493
- openteam agents
494
- ```
495
-
496
- ```text
497
- openteam agents — LLM por agente:
498
-
499
- ● openteam [primary ] frontier · Anthropic (consume tu suscripción) (anthropic/claude-sonnet-4-5)
500
- ○ basher [subagent] local · Ollama (sin coste de tokens) (ollama/qwen3:8b)
501
- ○ scribe [subagent] hereda default → frontier · Anthropic (consume tu suscripción) · openteam enruta local-first por mensaje
502
-
503
- Default de opencode.json: anthropic/claude-sonnet-4-5 (frontier · Anthropic)
504
- Leyenda: ● primary · ○ subagent · local = sin coste de tokens · frontier = consume tu suscripción.
505
- ```
506
-
507
- También está disponible **dentro de opencode**: pídele a openteam la lista de agentes y ejecutará la acción `agents` de su herramienta de comandos.
508
-
524
+ Lista los agentes de `.opencode/agent/` con su modelo y proveedor configurados.
525
+ Los agentes sin `model` propio heredan el default de `opencode.json`. Ese
526
+ default no autoriza salir del dominio resuelto: prevalecen las políticas
527
+ efectivas de `.opencode/openteam.json`.
509
528
 
510
529
  ### Modo YOLO (auto-aprobar permisos)
511
530
 
@@ -521,20 +540,30 @@ También puedes activarlo durante `openteam setup` (te lo pregunta), o al vuelo
521
540
 
522
541
  > **Importante: el permiso del agente anula al global.** opencode fusiona el permiso del frontmatter de cada agente **después** del global y gana la última regla que casa; por eso `openteam yolo on/off` regenera `.opencode/agent/openteam.md` para que su `permission` coincida con el estado YOLO. Sin esto, un `bash: ask`/`external_directory: deny` en el agente seguiría pidiendo confirmación aunque el global fuese `"*": allow`. Tras cambiar el modo, **reinicia o recarga opencode** para que los agentes tomen los nuevos permisos, y crea los subagentes con el mismo comodín cuando YOLO esté activo (el orquestador ya lo hace).
523
542
 
524
- > **YOLO no desactiva la privacidad de openteam.** Solo afecta a las aprobaciones de permisos de opencode; con `privacyMode: "forceLocalOnSensitive"`, los prompts sensibles siguen sin salir a frontier. Úsalo solo en entornos de confianza: auto-aprueba también `bash`, escrituras y accesos fuera del workspace (salvo reglas `deny` explícitas).
543
+ > **YOLO no cambia el dominio de ejecución.** Solo afecta a las aprobaciones de
544
+ > opencode y no añade un filtro de sensibilidad. En `frontier` o `mixed`, el
545
+ > contenido del prompt puede enviarse a frontier. Úsalo solo en entornos de
546
+ > confianza.
525
547
 
526
548
  ### Modo de routing: `openteam local`
527
549
 
528
550
  Usa `openteam local` para alternar entre los tres modos globales de routing sin repetir el setup:
529
551
 
530
552
  ```powershell
531
- openteam local status # ¿local-first, solo local o solo frontier? + runtimes configurados
532
- openteam local off # solo frontier (desactiva el routing local-first)
553
+ openteam local status # ¿mixed, local o frontier? + runtimes configurados
554
+ openteam local off # frontier
533
555
  openteam local only # solo local (nunca escala a frontier)
534
- openteam local on # vuelve al routing local-first
556
+ openteam local on # mixed
535
557
  ```
536
558
 
537
- `local off` persiste `router.frontierOnly=true`: el router escoge el **frontier cheapest-capable**, pero respeta privacidad, presupuestos y overrides explícitos por tarea. Los prompts sensibles con `forceLocalOnSensitive` no salen a frontier; `local off` degrada esa política a `consentBeforeFrontier` (imposible forzar local sin runtime) e informa del cambio. `local only` persiste `router.localOnly=true` y limpia `frontierOnly`; se niega a escribir la config salvo que haya al menos un runtime local habilitado.
559
+ Los comandos persisten `router.executionMode`. `local only` es un límite duro:
560
+ ningún pin o fallback de agente puede llegar a frontier, y el comando se rechaza
561
+ sin runtime local habilitado. `local off` no necesita runtime local. `local on`
562
+ permite ambos dominios y cada agente puede estrechar el suyo. Toda escritura
563
+ valida primero las políticas exactas de primary, roles y fallbacks contra el
564
+ dominio propuesto; un conflicto rechaza el comando y deja la config sin cambios.
565
+ También elimina `localOnly`, `frontierOnly` y `privacyMode` raíz; `local status`
566
+ muestra el modo efectivo y las identidades de runtimes habilitados.
538
567
 
539
568
  ### Actualizar el plugin y limpiar la caché: `openteam clear-cache`
540
569
 
@@ -565,7 +594,47 @@ de actualización paso a paso.
565
594
 
566
595
  ### Trabajo iterativo bajo `openteam-orchestrate` 🎯
567
596
 
568
- El trabajo desatendido y de tipo backlog se gestiona **enteramente desde la orquestación** — la iteración es una propiedad del grafo, no un comando aparte. Cuando el coordinador despacha un rol, ese nodo del grafo sigue trabajando en pasadas sucesivas hasta que declara `openteam-status: done` en su artefacto de reporte (el **contrato de salida**) o alcanza su tope de reintentos. El tope es configurable vía `orchestrator.maxRetries` en `.opencode/openteam.json`: cuenta reintentos, así que el valor por defecto `2` significa **tres pasadas por nodo** y `0` desactiva la iteración (una sola pasada). Un nodo que nunca declara completitud se vuelve a despachar hasta el tope en lugar de asumirse terminado, y un **gate de durabilidad** verifica en código que cada rol persistió realmente un reporte no vacío — así ninguna pasada descarta trabajo en silencio. La concurrencia por oleada y la cancelación por dependencias no cambian. Consulta **[docs/es/guide/commands.md](docs/es/guide/commands.md)** para el contrato completo.
597
+ El trabajo desatendido se gestiona desde la orquestación. El modelo actual
598
+ recibe `orchestrator.maxRetries` pasadas extra (default efectivo de runtime `2`,
599
+ tres pasadas como máximo por modelo). La incompletitud persistente consume el
600
+ presupuesto de pasadas del modelo antes de entregar el **mismo nodo** al
601
+ siguiente modelo autorizado. Un fallo retry-safe reconocido de
602
+ transporte/capacidad del prompt (`prompt-timeout`, `prompt-rate-limited`,
603
+ `prompt-connection`, `prompt-server` o `prompt-context-length`) se reintenta en
604
+ ese mismo modelo dentro de su presupuesto de pasadas; en create se reconocen
605
+ las mismas clases salvo context length. `maxRetries` es un límite superior, no
606
+ un mínimo obligatorio de repeticiones: tras confirmar la parada, un fallo de
607
+ transporte elegible puede consumir el presupuesto restante del mismo modelo o
608
+ entregar antes el nodo al siguiente candidato autorizado. Auth,
609
+ content-filter, validation/modelo inválido, rechazo genérico, session ID ausente
610
+ y fallos sin clasificar son terminales. Un candidato detectado como no
611
+ disponible antes del dispatch puede omitirse porque no empezó ningún intento.
612
+ `maxModelsPerNode` tiene
613
+ default efectivo de runtime `2`; juntos, ambos defaults limitan el nodo a hasta
614
+ seis pasadas openteam. Ninguno se materializa en el schema. No es una cuenta
615
+ garantizada de pasadas/llamadas HTTP ni una afirmación sobre reintentos internos
616
+ del SDK/provider.
617
+
618
+ El relevo conserva batch, objetivo, ruta de reporte y estado duradero. Un pin
619
+ exacto sin `fallbacks` no autoriza un segundo modelo. Cada pasada, incluso con
620
+ `maxRetries: 0`, necesita una declaración independiente
621
+ `openteam-status: done` y un reporte duradero con al menos 40 caracteres
622
+ sustantivos tras retirar las líneas de declaración reales. Gana la última
623
+ declaración independiente fuera de bloques de código; los ejemplos citados o
624
+ dentro de fences siguen siendo cuerpo y no declaran completitud. El marcador
625
+ solo no basta. El coordinador lee el texto únicamente para parsear ese estado y
626
+ comprobar sustancia; no copia el cuerpo a resultados de rol, telemetría de
627
+ routing, diagnósticos ni a la proyección solo-referencia.
628
+
629
+ Tras un dispatch de prompt con timeout o excepción/incertidumbre, la petición
630
+ SDK anterior debe terminar y la parada del servidor debe confirmarse antes de
631
+ cualquier reintento o relevo. Tras un abort correcto, el polling acotado
632
+ confirma la parada si la sesión exacta está `idle` o no aparece en un snapshot
633
+ de estado disperso válido; un payload ausente/malformado o una sesión que sigue
634
+ `busy`/`retry` bloquean la continuación. La evidencia de estado no sustituye la
635
+ terminación de la petición. Agotar la cadena termina en fallo/incompleto y no
636
+ ejecuta dependientes. Consulta
637
+ **[docs/es/guide/commands.md](docs/es/guide/commands.md)**.
569
638
 
570
639
  ### Console web multi-sesión (se lanza desde la CLI)
571
640
 
@@ -576,12 +645,11 @@ de opencode abiertas y todas aparecen en la **misma** Console, con una pestaña
576
645
  sesión (más "Todas"), porque cada plugin **escribe eventos redactados** en logs
577
646
  JSONL por sesión y la Console los vigila (`fs.watch`) y **agrega**.
578
647
 
579
- Muestra en vivo: **coste y tokens reales por mensaje** (input/output/reasoning/
580
- cache), **toolcalls con duración** y ok/fallo, ruteo reciente (coste/ahorro y
581
- modelo elegido, **solo hashes de prompt, nunca el texto**), **decisiones** de los
582
- agentes (scribe) y **reuniones** (batches multi-agente del orquestador), progreso
583
- de orquestación e iteración, el equipo de agentes (LLM local/frontier de cada uno) y
584
- últimos commits. Se actualiza por **SSE** (con *polling* de respaldo).
648
+ Muestra en vivo: **uso de tokens registrado y estimaciones de coste por
649
+ mensaje** (input/output/reasoning/cache), toolcalls con duración, routing
650
+ reciente, decisiones, reuniones, progreso, equipo y commits. Solo muestra hashes
651
+ de prompt, nunca el texto. Los límites y estimaciones son finitos y auditables,
652
+ pero no sustituyen la factura del provider. Se actualiza por **SSE**.
585
653
 
586
654
  Cada pestaña de sesión incluye además una **vista "Sesión"**: una consola por la
587
655
  que puedes **ver la salida en vivo** (SSE) y **enviar prompts** o **responder
@@ -622,7 +690,12 @@ Puedes ajustar host/puerto y la terminal en `.opencode/openteam.json` (bloque
622
690
  }
623
691
  ```
624
692
 
625
- **Vista del grafo de agentes en vivo.** La Console también puede renderizar un **grafo de agentes** en vivo de una ejecución de Graph; está **activada por defecto en modo shadow** y se puede ocultar con `console.graphView.enabled: false` — consulta [Graph observability web](docs/es/guide/graph-observability-web.md) para la configuración y los requisitos completos.
693
+ **Árbol de agentes y línea de tiempo.**
694
+ `console.graphView.enabled` vale `true` por defecto. El historial nativo del
695
+ ciclo de vida se compone con independencia de la autoridad de ejecución de
696
+ Graph; el DAG separado de Graph sigue el `graph.mode` efectivo. Consulta
697
+ [Línea de tiempo de agentes](docs/es/guide/agent-timeline.md) y
698
+ [Web de observabilidad del grafo](docs/es/guide/graph-observability-web.md).
626
699
 
627
700
  > **Seguridad**: el servidor escucha **solo en loopback** (`127.0.0.1`/`localhost`, validado por Zod) y **nunca expone prompts** (solo `promptHash`), args de toolcall ni contenido de mensajes: solo contadores, costes y resúmenes redactados. La vista "Sesión"/"Terminal" exige el token efímero. Si el puerto está ocupado y `autoPortFallback` es `true`, prueba el siguiente libre. El acceso remoto mediante `openteam tunnel` se **eliminó del MVP** (2026-08-31) y se redefinirá más adelante; la Console no tiene camino de exposición remota integrado.
628
701
 
@@ -635,8 +708,10 @@ stdio, sin dependencias) que expone la memoria del equipo agregada desde los
635
708
  eventos por sesión para que agentes/herramientas la consulten. Se apoya en el
636
709
  mismo `StorageProvider` que la Console y **nunca** expone prompts crudos, solo el
637
710
  estado ya redactado. Tools disponibles: `list_decisions` (filtrable por
638
- `agent`/`tag`), `list_meetings`, `list_sessions` y `cost_summary` (coste/tokens
639
- reales + ahorro estimado vs baseline all-frontier).
711
+ `agent`/`tag`), `list_meetings`, `list_sessions` y `cost_summary` (uso
712
+ registrado y estimaciones disponibles de coste/ahorro frente al baseline
713
+ all-frontier; los costes desconocidos siguen siendo desconocidos y no es una
714
+ factura).
640
715
 
641
716
  Regístralo en `opencode.json` como cualquier MCP server local:
642
717
 
@@ -651,6 +726,13 @@ Regístralo en `opencode.json` como cualquier MCP server local:
651
726
  }
652
727
  ```
653
728
 
729
+ La **tool de escritura `openteam-memory`** del plugin está separada de este
730
+ servidor MCP de solo lectura y de la política de modelo del rol scribe general.
731
+ Su transporte de extracción es explícitamente solo-local y exige un runtime
732
+ local configurado y alcanzable. El modo global `frontier` rechaza la llamada al
733
+ modelo de memoria; la tool no añade memoria frontier ni hace fallback
734
+ silencioso a frontier.
735
+
654
736
  #### Recall semántico (opt-in): `recall_facts`, `recall_preferences`, `similar_tasks`
655
737
 
656
738
  Además de la memoria de equipo, `openteam mcp` puede exponer **recall semántico**
@@ -803,17 +885,24 @@ GitHub Actions.
803
885
 
804
886
  ## Privacidad
805
887
 
806
- Con `privacyMode: "forceLocalOnSensitive"`, si `TaskSignals.privacySensitive` es `true`, `chooseModel` usa local y no permite fallback frontier. Si no hay local utilizable, la decisión conserva la ruta local y registra la razón en `rationale`.
888
+ openteam **no** detecta sensibilidad ni promete interceptar contenido antes de
889
+ una llamada frontier. `privacyMode` está obsoleto y no tiene autoridad de
890
+ routing. `frontier` y `mixed` permiten egress según la política configurada.
891
+ Para prohibirlo, usa `router.executionMode: "local"` globalmente o estrecha el
892
+ agente a `local` bajo `mixed`.
807
893
 
808
- La telemetría usa `hashPrompt`, actualmente `fnv1a32:<hash>`, y no serializa el prompt completo.
894
+ La redacción de credenciales, la telemetría con hash, el almacenamiento
895
+ solo-referencia, los controles de acceso y los límites finitos de
896
+ presupuesto/modelos/pasadas siguen vigentes. La telemetría usa `hashPrompt`,
897
+ actualmente `fnv1a32:<hash>`, y no serializa el prompt completo.
809
898
 
810
899
  ## Calidad
811
900
 
812
901
  Gates no negociables:
813
902
 
814
903
  - `bun test`
815
- - Coverage global: líneas `>= 85%`, branches `>= 80%`.
816
- - Coverage de `src/router/**`: `100%` lines, branches, statements y functions.
904
+ - Coverage global: líneas/funciones `>= 85%`.
905
+ - Coverage de `src/router/**`: `100%` líneas y funciones.
817
906
  - `bun run typecheck`
818
907
  - `biome check .` o `bun run lint` + `bun run format:check`
819
908
  - Test de determinismo del router.
@@ -825,7 +914,7 @@ Consulta [docs/compatibility.md](docs/compatibility.md). Resumen verificado el `
825
914
 
826
915
  | Superficie | Versión / contrato |
827
916
  | --- | --- |
828
- | openteam | `0.18.1`; versión actual del paquete |
917
+ | openteam | `0.20.0`; versión actual del paquete |
829
918
  | `@opencode-ai/plugin` | `1.18.19` |
830
919
  | `@opencode-ai/sdk` | `1.18.19` |
831
920
  | Hook de routing | `chat.message`; no `chat.params` para cambiar modelo |
@@ -840,11 +929,13 @@ Las contribuciones son bienvenidas. Lee [CONTRIBUTING.md](CONTRIBUTING.md) para
840
929
  | Fase | Estado | Entregables |
841
930
  | --- | --- | --- |
842
931
  | 0. Scaffold/PoC | Hecha | TS/Bun, plugin mínimo, hook `chat.message`. |
843
- | 1. Local registry + router heurístico | Hecha | Ollama/LM Studio/Lemonade/Foundry, probes y `chooseModel` determinista. |
844
- | 2. Clasificador + perfiles + presupuesto + telemetría | Hecha | Clasificador local, `ModelCapabilityProfile`, budgets y `CostRecord`. |
932
+ | 1. Local registry + router | Hecha | Ollama/LM Studio/Lemonade/Foundry, probes y `chooseModel` determinista. |
933
+ | 2. Perfiles + presupuesto + telemetría | Hecha | `ModelCapabilityProfile`, budgets y `CostRecord`. |
845
934
  | 3. Orquestación multiagente | Hecha | Coordinator, roles, child sessions y permisos. |
846
935
  | 4. Empaquetado npm + docs | Hecha | Package exportable, README, ejemplos Windows y matriz de compatibilidad. |
847
936
  | 5. Comandos runtime | Hecha | `baseline show/set/auto`, `doctor` y `report` vía tool, `/openteam` y CLI `bin`. |
937
+ | 6. Console web + memoria MCP | Hecha | Console multi-sesión solo-loopback, MCP de solo lectura y recall semántico opt-in. |
938
+ | MVP del agent stack | En curso | Config v2 con dominios, políticas por agente, relevo acotado, retirada del routing por sensibilidad y eliminación de la resolución duplicada de política dentro de Graph. El routing unificado por capacidad/complejidad permanece. La migración LangGraph sigue pendiente por separado. |
848
939
 
849
940
  ## Licencia
850
941