@jmanuelcorral/openteam 0.1.38 → 0.1.41

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/command/openteam.md +5 -5
  2. package/AGENTS.md +50 -35
  3. package/README.es.md +759 -0
  4. package/README.md +213 -480
  5. package/dist/capabilities/types.d.ts +1 -1
  6. package/dist/cli/consoleServe.d.ts.map +1 -1
  7. package/dist/cli.js +1123 -232
  8. package/dist/commands/frontierCatalog.d.ts +27 -0
  9. package/dist/commands/frontierCatalog.d.ts.map +1 -0
  10. package/dist/commands/graph.d.ts +65 -0
  11. package/dist/commands/graph.d.ts.map +1 -0
  12. package/dist/commands/orchestratorAgent.d.ts +2 -1
  13. package/dist/commands/orchestratorAgent.d.ts.map +1 -1
  14. package/dist/commands/setup.d.ts +3 -18
  15. package/dist/commands/setup.d.ts.map +1 -1
  16. package/dist/config/load.d.ts.map +1 -1
  17. package/dist/config/migrations.d.ts +27 -0
  18. package/dist/config/migrations.d.ts.map +1 -0
  19. package/dist/config/resolve.d.ts +34 -0
  20. package/dist/config/resolve.d.ts.map +1 -0
  21. package/dist/config/schema.d.ts +235 -0
  22. package/dist/config/schema.d.ts.map +1 -1
  23. package/dist/console/assets.d.ts +9 -0
  24. package/dist/console/assets.d.ts.map +1 -0
  25. package/dist/console/render.d.ts.map +1 -1
  26. package/dist/context/redaction.d.ts +48 -0
  27. package/dist/context/redaction.d.ts.map +1 -0
  28. package/dist/context/schema.d.ts +115 -0
  29. package/dist/context/schema.d.ts.map +1 -0
  30. package/dist/context/types.d.ts +8 -0
  31. package/dist/context/types.d.ts.map +1 -0
  32. package/dist/contract/opencode.d.ts +1 -1
  33. package/dist/contract/opencode.d.ts.map +1 -1
  34. package/dist/graph/events.d.ts +25 -0
  35. package/dist/graph/events.d.ts.map +1 -0
  36. package/dist/graph/ids.d.ts +5 -0
  37. package/dist/graph/ids.d.ts.map +1 -0
  38. package/dist/graph/planner.d.ts +15 -0
  39. package/dist/graph/planner.d.ts.map +1 -0
  40. package/dist/graph/policies.d.ts +34 -0
  41. package/dist/graph/policies.d.ts.map +1 -0
  42. package/dist/graph/privacyPolicy.d.ts +29 -0
  43. package/dist/graph/privacyPolicy.d.ts.map +1 -0
  44. package/dist/graph/reducer.d.ts +27 -0
  45. package/dist/graph/reducer.d.ts.map +1 -0
  46. package/dist/graph/replay.d.ts +20 -0
  47. package/dist/graph/replay.d.ts.map +1 -0
  48. package/dist/graph/reviewerPolicy.d.ts +27 -0
  49. package/dist/graph/reviewerPolicy.d.ts.map +1 -0
  50. package/dist/graph/schema.d.ts +220 -0
  51. package/dist/graph/schema.d.ts.map +1 -0
  52. package/dist/graph/types.d.ts +40 -0
  53. package/dist/graph/types.d.ts.map +1 -0
  54. package/dist/graph/validate.d.ts +19 -0
  55. package/dist/graph/validate.d.ts.map +1 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +873 -88
  58. package/dist/local/embeddings.d.ts +29 -0
  59. package/dist/local/embeddings.d.ts.map +1 -0
  60. package/dist/local/extractClient.d.ts +31 -0
  61. package/dist/local/extractClient.d.ts.map +1 -0
  62. package/dist/local/openai-compatible.d.ts +1 -0
  63. package/dist/local/openai-compatible.d.ts.map +1 -1
  64. package/dist/mcp/semanticRecall.d.ts +25 -0
  65. package/dist/mcp/semanticRecall.d.ts.map +1 -0
  66. package/dist/mcp/server.d.ts +22 -0
  67. package/dist/mcp/server.d.ts.map +1 -1
  68. package/dist/memory/consolidate.d.ts +21 -0
  69. package/dist/memory/consolidate.d.ts.map +1 -0
  70. package/dist/memory/extract.d.ts +68 -0
  71. package/dist/memory/extract.d.ts.map +1 -0
  72. package/dist/memory/fold.d.ts +24 -0
  73. package/dist/memory/fold.d.ts.map +1 -0
  74. package/dist/memory/index.d.ts +18 -0
  75. package/dist/memory/index.d.ts.map +1 -0
  76. package/dist/memory/inject.d.ts +29 -0
  77. package/dist/memory/inject.d.ts.map +1 -0
  78. package/dist/memory/log.d.ts +16 -0
  79. package/dist/memory/log.d.ts.map +1 -0
  80. package/dist/memory/merge.d.ts +38 -0
  81. package/dist/memory/merge.d.ts.map +1 -0
  82. package/dist/memory/rank.d.ts +32 -0
  83. package/dist/memory/rank.d.ts.map +1 -0
  84. package/dist/memory/recall.d.ts +30 -0
  85. package/dist/memory/recall.d.ts.map +1 -0
  86. package/dist/memory/temporal.d.ts +39 -0
  87. package/dist/memory/temporal.d.ts.map +1 -0
  88. package/dist/memory/types.d.ts +159 -0
  89. package/dist/memory/types.d.ts.map +1 -0
  90. package/dist/memory/vector.d.ts +18 -0
  91. package/dist/memory/vector.d.ts.map +1 -0
  92. package/dist/orchestrator/graphCancellation.d.ts +84 -0
  93. package/dist/orchestrator/graphCancellation.d.ts.map +1 -0
  94. package/dist/orchestrator/graphEffects.d.ts +63 -0
  95. package/dist/orchestrator/graphEffects.d.ts.map +1 -0
  96. package/dist/orchestrator/graphReview.d.ts +84 -0
  97. package/dist/orchestrator/graphReview.d.ts.map +1 -0
  98. package/dist/orchestrator/graphRuntime.d.ts +69 -0
  99. package/dist/orchestrator/graphRuntime.d.ts.map +1 -0
  100. package/dist/orchestrator/opencodeSessionAdapter.d.ts +117 -0
  101. package/dist/orchestrator/opencodeSessionAdapter.d.ts.map +1 -0
  102. package/dist/orchestrator/roles.d.ts +1 -1
  103. package/dist/orchestrator/roles.d.ts.map +1 -1
  104. package/dist/orchestrator/sdd.d.ts +38 -2
  105. package/dist/orchestrator/sdd.d.ts.map +1 -1
  106. package/dist/orchestrator/sddCompiler.d.ts +44 -0
  107. package/dist/orchestrator/sddCompiler.d.ts.map +1 -0
  108. package/dist/orchestrator/sessionReconciler.d.ts +74 -0
  109. package/dist/orchestrator/sessionReconciler.d.ts.map +1 -0
  110. package/dist/orchestrator/shadowComparator.d.ts +62 -0
  111. package/dist/orchestrator/shadowComparator.d.ts.map +1 -0
  112. package/dist/plugin/hooks.d.ts +13 -0
  113. package/dist/plugin/hooks.d.ts.map +1 -1
  114. package/dist/plugin/memoryInject.d.ts +25 -0
  115. package/dist/plugin/memoryInject.d.ts.map +1 -0
  116. package/dist/router/chooseModel.d.ts.map +1 -1
  117. package/dist/router/cost.d.ts +4 -0
  118. package/dist/router/cost.d.ts.map +1 -0
  119. package/dist/router/frontierBaseline.d.ts +13 -0
  120. package/dist/router/frontierBaseline.d.ts.map +1 -0
  121. package/dist/router/modelSelection.d.ts +18 -0
  122. package/dist/router/modelSelection.d.ts.map +1 -0
  123. package/dist/storage/graph/codec.d.ts +52 -0
  124. package/dist/storage/graph/codec.d.ts.map +1 -0
  125. package/dist/storage/graph/fsGraphJournal.d.ts +3 -0
  126. package/dist/storage/graph/fsGraphJournal.d.ts.map +1 -0
  127. package/dist/storage/graph/importLegacy.d.ts +62 -0
  128. package/dist/storage/graph/importLegacy.d.ts.map +1 -0
  129. package/dist/storage/graph/memoryGraphJournal.d.ts +11 -0
  130. package/dist/storage/graph/memoryGraphJournal.d.ts.map +1 -0
  131. package/dist/storage/graph/migrateLegacyBriefs.d.ts +32 -0
  132. package/dist/storage/graph/migrateLegacyBriefs.d.ts.map +1 -0
  133. package/dist/storage/graph/projections.d.ts +31 -0
  134. package/dist/storage/graph/projections.d.ts.map +1 -0
  135. package/dist/storage/graph/provider.d.ts +52 -0
  136. package/dist/storage/graph/provider.d.ts.map +1 -0
  137. package/dist/storage/graph/recovery.d.ts +38 -0
  138. package/dist/storage/graph/recovery.d.ts.map +1 -0
  139. package/dist/storage/graph/runRegistry.d.ts +17 -0
  140. package/dist/storage/graph/runRegistry.d.ts.map +1 -0
  141. package/dist/storage/graph/snapshot.d.ts +44 -0
  142. package/dist/storage/graph/snapshot.d.ts.map +1 -0
  143. package/dist/storage/graph/workspaceLease.d.ts +36 -0
  144. package/dist/storage/graph/workspaceLease.d.ts.map +1 -0
  145. package/dist/storage/graph/writer.d.ts +20 -0
  146. package/dist/storage/graph/writer.d.ts.map +1 -0
  147. package/dist/storage/index/memoryConsolidate.d.ts +24 -0
  148. package/dist/storage/index/memoryConsolidate.d.ts.map +1 -0
  149. package/dist/storage/index/memoryIndex.d.ts +52 -0
  150. package/dist/storage/index/memoryIndex.d.ts.map +1 -0
  151. package/dist/storage/index/memoryRecall.d.ts +23 -0
  152. package/dist/storage/index/memoryRecall.d.ts.map +1 -0
  153. package/dist/storage/index/memoryRuntime.d.ts +41 -0
  154. package/dist/storage/index/memoryRuntime.d.ts.map +1 -0
  155. package/dist/telemetry/events.d.ts +3 -1
  156. package/dist/telemetry/events.d.ts.map +1 -1
  157. package/dist/telemetry/graphProjection.d.ts +36 -0
  158. package/dist/telemetry/graphProjection.d.ts.map +1 -0
  159. package/dist/telemetry/hash.d.ts.map +1 -1
  160. package/dist/web/server.d.ts +4 -0
  161. package/dist/web/server.d.ts.map +1 -1
  162. package/package.json +14 -6
package/README.es.md ADDED
@@ -0,0 +1,759 @@
1
+ # openteam
2
+
3
+ > 🌐 **Language / Idioma:** [English](README.md) · **Español** (este documento)
4
+
5
+ **openteam — plugin de opencode con routing coste-consciente local-first, fallback FRONTIER cheapest-capable y orquestación multiagente a demanda.**
6
+
7
+ > 📖 **Sitio de documentación:** <https://jmanuelcorral.github.io/openteam/es/> (también en [English](https://jmanuelcorral.github.io/openteam/))
8
+
9
+ ## Tabla de contenidos
10
+
11
+ - [Qué es y por qué existe](#qué-es-y-por-qué-existe)
12
+ - [Características](#características)
13
+ - [Requisitos](#requisitos)
14
+ - [Instalación](#instalación)
15
+ - [Quickstart: `openteam setup`](#quickstart-openteam-setup)
16
+ - [Probar en otra máquina](#probar-en-otra-máquina)
17
+ - [Actualizar openteam](#actualizar-openteam)
18
+ - [Configuración](#configuración)
19
+ - [Uso](#uso)
20
+ - [Ejemplos en Windows](#ejemplos-en-windows)
21
+ - [Publicación segura](#publicación-segura)
22
+ - [Privacidad](#privacidad)
23
+ - [Calidad](#calidad)
24
+ - [Compatibilidad](#compatibilidad)
25
+ - [Roadmap](#roadmap)
26
+ - [Licencia](#licencia)
27
+ - [Agradecimientos e inspiración](#agradecimientos-e-inspiración)
28
+
29
+ ## Qué es y por qué existe
30
+
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
+
33
+ El router mantiene una garantía de privacidad: con `privacyMode: "forceLocalOnSensitive"`, una tarea marcada como `privacySensitive` no escala a frontier.
34
+
35
+ ## Características
36
+
37
+ - Routing por turno desde el hook `chat.message`, mutando `output.message.model` antes de que opencode persista el mensaje.
38
+ - Registro de runtimes locales OpenAI-compatible: Ollama, LM Studio y Foundry Local.
39
+ - Clasificador local JSON con fallback heurístico determinista.
40
+ - 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`.
42
+ - Presupuestos por sesión, mes y tokens frontier por sesión.
43
+ - 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 } })`.
45
+ - Refresh de disponibilidad local al arrancar y en eventos `session.created` / `session.idle`.
46
+
47
+ ## Requisitos
48
+
49
+ - opencode compatible con `@opencode-ai/plugin` `1.17.13`.
50
+ - Bun `1.3.14` para instalaciones, desarrollo y tests reproducibles.
51
+ - Node.js `^22.22.2 || ^24.15.0 || >=26.0.0` para la CLI y el plugin publicados.
52
+ - Runtimes locales opcionales:
53
+ - Ollama en `http://localhost:11434/v1`.
54
+ - LM Studio en `http://localhost:1234/v1`.
55
+ - Foundry Local con puerto dinámico descubierto por CLI en Windows.
56
+
57
+ ## Instalación
58
+
59
+ ### Opción A: paquete npm
60
+
61
+ El paquete se publica como `@jmanuelcorral/openteam`. Estas son las rutas de instalación soportadas:
62
+
63
+ | Necesidad | Método soportado |
64
+ | --- | --- |
65
+ | Cargar el plugin en opencode | Añadir `@jmanuelcorral/openteam` al array `plugin` de `opencode.json`. opencode resuelve el paquete; no hace falta instalar la CLI globalmente. |
66
+ | Ejecutar setup una vez | `bunx --package @jmanuelcorral/openteam@latest openteam setup` |
67
+ | Mantener la CLI `openteam` en el `PATH` | `bun add --global @jmanuelcorral/openteam@latest` y después `openteam setup` |
68
+
69
+ La instalación global con npm **no está soportada**. Bun es el único instalador de paquetes soportado. Node.js ejecuta la CLI y el plugin publicados dentro del rango declarado de engines; npm se limita a operaciones de mantenedor: `pack`, Trusted Publishing y `link:local`.
70
+
71
+ Para la carga directa desde opencode, basta con referenciar el paquete:
72
+
73
+ ```jsonc
74
+ {
75
+ "$schema": "https://opencode.ai/config.json",
76
+ "model": "anthropic/claude-sonnet-4-5",
77
+ "small_model": "ollama/qwen3:8b",
78
+ "plugin": [
79
+ [
80
+ "@jmanuelcorral/openteam",
81
+ {
82
+ "baseline": {
83
+ "mode": "auto",
84
+ "pinnedModel": null,
85
+ "hardDefault": {
86
+ "providerID": "anthropic",
87
+ "modelID": "claude-sonnet-4-5"
88
+ }
89
+ },
90
+ "router": {
91
+ "mode": "balanced",
92
+ "localDefault": {
93
+ "providerID": "ollama",
94
+ "modelID": "qwen3:8b"
95
+ },
96
+ "trivialPromptMaxChars": 280,
97
+ "frontierPromptMinChars": 2000
98
+ },
99
+ "local": {
100
+ "runtimes": [
101
+ {
102
+ "id": "ollama",
103
+ "enabled": true,
104
+ "baseURL": "http://localhost:11434/v1",
105
+ "defaultModel": {
106
+ "providerID": "ollama",
107
+ "modelID": "qwen3:8b"
108
+ }
109
+ },
110
+ {
111
+ "id": "lmstudio",
112
+ "enabled": true,
113
+ "baseURL": "http://localhost:1234/v1",
114
+ "defaultModel": {
115
+ "providerID": "lmstudio",
116
+ "modelID": "qwen2.5-coder-local"
117
+ }
118
+ }
119
+ ]
120
+ },
121
+ "budgets": {
122
+ "sessionUSD": 2,
123
+ "monthlyUSD": 30,
124
+ "frontierTokensPerSession": 250000,
125
+ "hardStopOnBudgetExhaustion": false
126
+ },
127
+ "privacyMode": "forceLocalOnSensitive",
128
+ "telemetry": {
129
+ "enabled": true,
130
+ "path": ".opencode/openteam-telemetry.jsonl"
131
+ }
132
+ }
133
+ ]
134
+ ],
135
+ "provider": {
136
+ "ollama": {
137
+ "npm": "@ai-sdk/openai-compatible",
138
+ "name": "Ollama (local)",
139
+ "options": {
140
+ "baseURL": "http://localhost:11434/v1",
141
+ "apiKey": "ollama",
142
+ "chunkTimeout": 60000
143
+ },
144
+ "models": {
145
+ "qwen3:8b": {
146
+ "name": "Qwen3 8B (Ollama)",
147
+ "tool_call": true,
148
+ "limit": { "context": 32768, "output": 8192 }
149
+ }
150
+ }
151
+ },
152
+ "lmstudio": {
153
+ "npm": "@ai-sdk/openai-compatible",
154
+ "name": "LM Studio (local)",
155
+ "options": {
156
+ "baseURL": "http://localhost:1234/v1",
157
+ "apiKey": "lm-studio"
158
+ },
159
+ "models": {
160
+ "qwen2.5-coder-local": {
161
+ "name": "Qwen2.5 Coder Local",
162
+ "tool_call": true,
163
+ "limit": { "context": 32768, "output": 8192 }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ ```
170
+
171
+ ### Opción B: ruta de desarrollo
172
+
173
+ Durante desarrollo puedes cargar un plugin local desde `.opencode/plugins/openteam.ts`:
174
+
175
+ ```jsonc
176
+ {
177
+ "$schema": "https://opencode.ai/config.json",
178
+ "plugin": [
179
+ [
180
+ "./.opencode/plugins/openteam.ts",
181
+ {
182
+ "router": {
183
+ "mode": "balanced",
184
+ "localDefault": {
185
+ "providerID": "ollama",
186
+ "modelID": "qwen3:8b"
187
+ }
188
+ },
189
+ "telemetry": {
190
+ "path": ".opencode/openteam-telemetry.jsonl"
191
+ }
192
+ }
193
+ ]
194
+ ]
195
+ }
196
+ ```
197
+
198
+ ## Quickstart: `openteam setup`
199
+
200
+ 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, Foundry Local) —que son **opcionales**: puedes usar openteam **solo con frontier**, o apuntar a un Ollama/LM Studio 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:
201
+
202
+ - `opencode.json` en la raíz: declara el plugin `@jmanuelcorral/openteam`, los `provider` locales OpenAI-compatible, el `model` frontier y el `small_model` local.
203
+ - `.opencode/openteam.json`: la configuración runtime validada de openteam (baseline, routing, runtimes locales y privacidad).
204
+ - `.opencode/agent/openteam.md`: el **agente primario `openteam`**, visible en el Tab-switcher.
205
+
206
+ ```powershell
207
+ # Ejecución puntual, sin instalación global
208
+ bunx --package @jmanuelcorral/openteam@latest openteam setup
209
+ # O después de la instalación global soportada con Bun
210
+ openteam setup
211
+ ```
212
+
213
+ > El antiguo comando `openteam init` sigue funcionando como **alias obsoleto** de `openteam setup`.
214
+
215
+ El asistente:
216
+
217
+ 1. Sondea los runtimes locales y marca los detectados.
218
+ 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).
219
+ 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.
220
+ 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).
221
+ 5. Si ya existe `opencode.json` o `.opencode/openteam.json`, pide confirmación antes de sobrescribir.
222
+
223
+ 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`.
224
+
225
+ ### El agente `openteam`
226
+
227
+ `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.
228
+
229
+ 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).)
230
+
231
+ 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:
232
+
233
+ - **scribe** — memoria silenciosa: registra decisiones y aprendizajes en `.opencode/openteam-decisions.md` sin tocar el código (modelo local).
234
+ - **ralph** — automatización y triage: monitoriza el trabajo pendiente, lo prioriza, coordina la ejecución y **escala al humano** ante bloqueos o aprobaciones.
235
+ - **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`.
236
+
237
+ 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.
238
+
239
+ En la **lista de tareas** (`todowrite`, la que ves en el todo general de opencode) cada entrada lleva **visible el responsable**. opencode no tiene un campo de "agente" en sus todos (solo `content`/`status`/`priority`, y la lista es por sesión), así que el orquestador usa una convención en el texto: prefija cada tarea con el nombre del casting, p. ej. `[@Basher] Implementar el router` o `[@openteam] Sintetizar resultados`. Así, de un vistazo, sabes quién es responsable de cada tarea.
240
+
241
+ ## Probar en otra máquina
242
+
243
+ Para instalar y probar openteam en otro equipo que ya tenga [opencode](https://opencode.ai) y [Bun](https://bun.sh):
244
+
245
+ 1. **Ejecuta o instala la CLI.** Elige una de estas rutas soportadas:
246
+
247
+ ```powershell
248
+ # Opción global (deja el comando `openteam` en el PATH)
249
+ bun add --global @jmanuelcorral/openteam@latest
250
+
251
+ # Opción puntual (no instala globalmente)
252
+ bunx --package @jmanuelcorral/openteam@latest openteam setup
253
+ ```
254
+
255
+ 2. **Inicializa el repositorio** donde vayas a trabajar. Genera `opencode.json`, `.opencode/openteam.json` y `.opencode/agent/openteam.md`:
256
+
257
+ ```powershell
258
+ cd C:\ruta\a\tu\repo
259
+ openteam setup # global
260
+ # La opción puntual ya ejecutó setup en el paso anterior.
261
+ ```
262
+
263
+ El asistente detecta Ollama / LM Studio / Foundry Local, te deja elegir los modelos locales (locales o en otra máquina de la red) o **ninguno** para funcionar solo con frontier, y el frontier baseline, y escribe la configuración.
264
+
265
+ 3. **Autentica el provider frontier** que hayas elegido:
266
+
267
+ ```powershell
268
+ opencode auth login
269
+ ```
270
+
271
+ 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.
272
+
273
+ 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.
274
+
275
+ Comprueba el estado con `openteam doctor` (runtimes + config) y el ahorro con `openteam report`.
276
+
277
+ ## Actualizar openteam
278
+
279
+ openteam se publica en npm al publicar una GitHub Release. Para traer la última versión:
280
+
281
+ ```powershell
282
+ # Instalación global
283
+ bun add --global @jmanuelcorral/openteam@latest
284
+ ```
285
+
286
+ Comprobar versiones:
287
+
288
+ ```powershell
289
+ bun pm ls --global # paquetes globales instalados
290
+ ```
291
+
292
+ La versión publicada más reciente aparece en
293
+ <https://www.npmjs.com/package/@jmanuelcorral/openteam>.
294
+
295
+ Notas al actualizar:
296
+
297
+ - **No necesitas volver a ejecutar `openteam setup`** para actualizar el plugin: opencode resuelve el paquete `@jmanuelcorral/openteam` declarado en `opencode.json` a la versión instalada. Reinicia opencode para que recargue el plugin.
298
+ - Vuelve a ejecutar `openteam setup` **solo** si quieres regenerar la configuración (cambiar runtimes, modelos o baseline). Pedirá confirmación antes de sobrescribir `opencode.json`, `.opencode/openteam.json` o `.opencode/agent/openteam.md`; **no toca los subagentes** que el orquestador haya creado a demanda.
299
+ - Ajustes puntuales sin reinit: `openteam baseline set <provider/model>` o `openteam baseline auto`.
300
+
301
+ ## Configuración
302
+
303
+ 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.
304
+
305
+ | Key | Tipo | Default | Descripción |
306
+ | --- | --- | --- | --- |
307
+ | `baseline.mode` | `"auto" \| "pinned"` | `"auto"` | En `auto`, usa perfiles frontier cheapest-capable cuando se pasan al router; en `pinned`, usa `baseline.pinnedModel` si existe. |
308
+ | `baseline.pinnedModel` | `ModelRef \| null` | `null` | Modelo frontier fijado explícitamente. `ModelRef` usa `{ "providerID": string, "modelID": string }`. |
309
+ | `baseline.hardDefault` | `ModelRef` | `{ "providerID": "anthropic", "modelID": "claude-sonnet-4-5" }` | Fallback frontier si no hay perfiles cheapest-capable o pin válido. |
310
+ | `router.mode` | `"economy" \| "balanced" \| "quality"` | `"balanced"` | Modo de routing validado y reservado para política. |
311
+ | `router.localDefault` | `ModelRef` | `{ "providerID": "ollama", "modelID": "qwen3:8b" }` | Modelo local principal. |
312
+ | `router.trivialPromptMaxChars` | `number` entero positivo | `280` | Prompts sin código hasta este tamaño prefieren local. |
313
+ | `router.frontierPromptMinChars` | `number` entero positivo | `2000` | Prompts desde este tamaño se tratan como candidatos a frontier si no aplican guards. |
314
+ | `local.runtimes` | `LocalRuntime[]` | Ollama enabled en `http://localhost:11434/v1` con `qwen3:8b` | Lista mínima de un runtime local. |
315
+ | `local.runtimes[].id` | `"ollama" \| "lmstudio" \| "foundry-local"` | requerido | Runtime local. |
316
+ | `local.runtimes[].enabled` | `boolean` | `true` | Habilita o deshabilita ese runtime. |
317
+ | `local.runtimes[].baseURL` | URL opcional | según runtime/config | Endpoint OpenAI-compatible `/v1`; Foundry Local puede omitirlo si usa discovery. |
318
+ | `local.runtimes[].discovery` | `"cli" \| "sdk" \| "manual"` opcional | sin default por item | Discovery de Foundry Local; el registry usa CLI si está configurado y no es `manual`. |
319
+ | `local.runtimes[].defaultModel` | `ModelRef` | requerido | Modelo por defecto de ese runtime. |
320
+ | `budgets.sessionUSD` | `number` positivo opcional | sin límite | Presupuesto frontier por sesión. |
321
+ | `budgets.monthlyUSD` | `number` positivo opcional | sin límite | Presupuesto frontier mensual. |
322
+ | `budgets.frontierTokensPerSession` | `number` entero positivo opcional | sin límite | Límite de tokens frontier por sesión. |
323
+ | `budgets.hardStopOnBudgetExhaustion` | `boolean` | `false` | Si es `true`, agotar presupuesto devuelve `blockFrontier`; si es `false`, fuerza local. |
324
+ | `privacyMode` | `"forceLocalOnSensitive" \| "consentBeforeFrontier" \| "off"` | `"forceLocalOnSensitive"` | Política de privacidad para tareas sensibles. |
325
+ | `telemetry.enabled` | `boolean` plugin option | `true` | Activa/desactiva escritura JSONL. |
326
+ | `telemetry.path` | `string` plugin option | `.opencode/openteam-telemetry.jsonl` | Ruta del log `CostRecord` JSONL. |
327
+
328
+ ## Uso
329
+
330
+ 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`.
331
+
332
+ La orquestación multiagente usa roles estáticos y subsesiones opencode:
333
+
334
+ | Rol | Agent opencode | Tier base | Política |
335
+ | --- | --- | --- | --- |
336
+ | `rusty` | `architect` | `hard` | Arquitectura y decisiones de alto riesgo; frontier auto. |
337
+ | `livingston` | `integration` | `moderate` | Integración TS/opencode; tool calling por defecto. |
338
+ | `yen` | `local-runtime` | `moderate` | Runtimes locales; local-first con fallback frontier. |
339
+ | `basher` | `routing-cost` | `moderate` | Router, coste y presupuesto; local-first. |
340
+ | `scribe` | `scribe` | `trivial` | Documentación y resúmenes; local-first. |
341
+ | `linus` | `tester` | `simple` | Tests y contratos; local-first con tools. |
342
+
343
+ `runRoleTask` ejecuta una subsesión; `runRoleTasks` ejecuta varias con `batchID`. Los roles con `destructive` o `multiFileEdit` elevan el tier antes de elegir modelo.
344
+
345
+ 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`.
346
+
347
+ ## Comandos runtime
348
+
349
+ openteam expone comandos para inspeccionar y cambiar el routing sin editar JSON a mano. Hay tres superficies equivalentes:
350
+
351
+ ### 1. Tool en la conversación
352
+
353
+ El plugin registra la herramienta `openteam`. Pídele al agente que la use, o instala el comando `/openteam` (ver más abajo). Acciones:
354
+
355
+ - `show` — muestra el baseline efectivo.
356
+ - `set` (con `model` en formato `provider/model`) — fija el baseline (modo `pinned`).
357
+ - `auto` — vuelve a cheapest-capable (modo `auto`).
358
+ - `doctor` — diagnóstico de runtimes locales, privacidad y telemetría.
359
+ - `report` — resumen de coste y ahorro desde la telemetría.
360
+
361
+ Los cambios de `set`/`auto` se persisten en `.opencode/openteam.json` y aplican en el siguiente arranque del plugin.
362
+
363
+ ### 2. Slash command `/openteam`
364
+
365
+ `openteam setup` **genera automáticamente** `.opencode/command/openteam.md`, así que el comando `/openteam` aparece en opencode sin pasos manuales. (Si vienes de una versión anterior, vuelve a ejecutar `openteam setup` para crearlo, o cópialo a mano a tu proyecto o a `~/.config/opencode/command/`.) Después:
366
+
367
+ ```text
368
+ /openteam baseline show
369
+ /openteam baseline set anthropic/claude-sonnet-4-5
370
+ /openteam baseline auto
371
+ /openteam doctor
372
+ /openteam agents
373
+ /openteam console
374
+ /openteam report
375
+ ```
376
+
377
+ > ¿No ves `/openteam` en opencode? Asegúrate de que existe `.opencode/command/openteam.md` (lo crea `openteam setup`) y **reinicia/recarga opencode** para que descubra el comando.
378
+
379
+ ### 3. CLI (`bin`)
380
+
381
+ El paquete expone el binario `openteam`. Con instalación global:
382
+
383
+ ```powershell
384
+ bun add --global @jmanuelcorral/openteam@latest
385
+ openteam baseline show
386
+ openteam baseline set openai/gpt-5-mini
387
+ openteam doctor --config .opencode/openteam.json
388
+ openteam agents
389
+ openteam console
390
+ openteam report --telemetry .opencode/openteam-telemetry.jsonl
391
+ openteam yolo status
392
+ openteam yolo on
393
+ openteam local status
394
+ openteam local off
395
+ ```
396
+
397
+ Flags: `--config <path>` y `--telemetry <path>` sobrescriben las rutas por defecto; `--opencode <path>` apunta el comando `yolo` a un `opencode.json` concreto.
398
+
399
+ ### Ver el LLM de cada agente: `openteam agents`
400
+
401
+ Lista los agentes de `.opencode/agent/` indicando **qué LLM usa cada uno**: si es **local** (Ollama/LM Studio/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).
402
+
403
+ ```powershell
404
+ openteam agents
405
+ ```
406
+
407
+ ```text
408
+ openteam agents — LLM por agente:
409
+
410
+ ● openteam [primary ] frontier · Anthropic (consume tu suscripción) (anthropic/claude-sonnet-4-5)
411
+ ○ basher [subagent] local · Ollama (sin coste de tokens) (ollama/qwen3:8b)
412
+ ○ scribe [subagent] hereda default → frontier · Anthropic (consume tu suscripción) · openteam enruta local-first por mensaje
413
+
414
+ Default de opencode.json: anthropic/claude-sonnet-4-5 (frontier · Anthropic)
415
+ Leyenda: ● primary · ○ subagent · local = sin coste de tokens · frontier = consume tu suscripción.
416
+ ```
417
+
418
+ 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.
419
+
420
+
421
+ ### Modo YOLO (auto-aprobar permisos)
422
+
423
+ El **modo YOLO** hace que opencode auto-apruebe **todos** los permisos (equivale al flag nativo `opencode --auto`, pero persistente). Escribe la regla global `permission: { "*": "allow" }` en `opencode.json` y **regenera el agente `openteam`** (`.opencode/agent/openteam.md`) con el mismo comodín, conservando el resto de tu configuración:
424
+
425
+ ```powershell
426
+ openteam yolo status # ¿está activo?
427
+ openteam yolo on # activa YOLO
428
+ openteam yolo off # desactiva YOLO
429
+ ```
430
+
431
+ También puedes activarlo durante `openteam setup` (te lo pregunta), o al vuelo con `opencode --auto` sin tocar la config.
432
+
433
+ > **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).
434
+
435
+ > **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).
436
+
437
+ ### Solo frontier (sin runtime local): `openteam local`
438
+
439
+ Si **no tienes ningún runtime local** (Ollama/LM Studio/Foundry Local) o prefieres no usarlo, puedes forzar que openteam enrute **siempre a modelos frontier**. `openteam setup` ya activa este modo automáticamente cuando no habilitas ningún runtime, pero puedes alternarlo en cualquier momento sin repetir el setup:
440
+
441
+ ```powershell
442
+ openteam local status # ¿local-first o solo frontier? + runtimes configurados
443
+ openteam local off # solo frontier (desactiva el routing local-first)
444
+ openteam local on # vuelve al routing local-first
445
+ ```
446
+
447
+ Esto persiste el flag `router.frontierOnly` en `.opencode/openteam.json`. Con `frontierOnly` activo, el router escoge el **frontier cheapest-capable** en lugar de la heurística local-first, pero **respeta la privacidad, los presupuestos y los overrides explícitos por tarea**: los prompts sensibles con `forceLocalOnSensitive` no salen a frontier, y `local off` degrada esa política a `consentBeforeFrontier` (imposible forzar local sin runtime) informándote del cambio.
448
+
449
+ ### Modo desatendido: `openteam loop` (patrón Ralph) 🎯 *(diseño)*
450
+
451
+ Segundo modo de operación: un **bucle externo** que invoca `opencode run` contra un backlog persistente hasta vaciarlo, con contexto fresco por iteración y topes de seguridad (presupuesto, máx. iteraciones, sin-progreso). Complementa al orquestador interactivo, no lo sustituye. Consulta el diseño y los ejemplos en **[docs/loop.md](docs/loop.md)**.
452
+
453
+ ### Console web multi-sesión (se lanza desde la CLI) — alfa
454
+
455
+ > ⚠️ **Alfa — sin terminar.** La Console (y el comando `tunnel` de más abajo) es
456
+ > una funcionalidad **experimental** que todavía puede **rehacerse o
457
+ > reconstruirse**, con cambios incompatibles en su UI, endpoints, config (bloque
458
+ > `console`) y formato de eventos. El router, presupuestos, telemetría y el core
459
+ > de memoria son estables; la superficie web aún no. Úsala para observación
460
+ > local, no como API estable.
461
+
462
+ openteam expone una **Console web local** que **lanzas tú desde la CLI** con
463
+ `openteam console`.
464
+ Agrega **todas** las sesiones de opencode a la vez: puedes tener varias pestañas
465
+ de opencode abiertas y todas aparecen en la **misma** Console, con una pestaña por
466
+ sesión (más "Todas"), porque cada plugin **escribe eventos redactados** en logs
467
+ JSONL por sesión y la Console los vigila (`fs.watch`) y **agrega**.
468
+
469
+ Muestra en vivo: **coste y tokens reales por mensaje** (input/output/reasoning/
470
+ cache), **toolcalls con duración** y ok/fallo, ruteo reciente (coste/ahorro y
471
+ modelo elegido, **solo hashes de prompt, nunca el texto**), **decisiones** de los
472
+ agentes (scribe) y **reuniones** (batches multi-agente del orquestador), progreso
473
+ del backlog del loop, el equipo de agentes (LLM local/frontier de cada uno) y
474
+ últimos commits. Se actualiza por **SSE** (con *polling* de respaldo).
475
+
476
+ Cada pestaña de sesión incluye además una **vista "Sesión"**: una consola por la
477
+ que puedes **ver la salida en vivo** (SSE) y **enviar prompts** o **responder
478
+ permisos** a esa sesión de opencode, autenticada con un **token efímero** por
479
+ arranque. Opcionalmente, con el flag `terminal.pty`, una **vista "Terminal"** abre
480
+ una **shell real** en el workspace vía la API de PTY de opencode (sin `node-pty`).
481
+
482
+ Lánzala contra el repo actual; escucha en loopback y corre hasta **Ctrl+C**:
483
+
484
+ ```powershell
485
+ openteam console # imprime la URL y sirve la Console multi-sesión
486
+ openteam console --open # además abre el navegador
487
+ openteam console --status # solo imprime la config (no lanza el servidor)
488
+ ```
489
+
490
+ Las sesiones se leen de:
491
+
492
+ ```text
493
+ .opencode/openteam/sessions/*.jsonl
494
+ ```
495
+
496
+ Puedes ajustar host/puerto y la terminal en `.opencode/openteam.json` (bloque
497
+ `console`):
498
+
499
+ ```json
500
+ {
501
+ "console": {
502
+ "host": "127.0.0.1",
503
+ "port": 4599,
504
+ "autoPortFallback": true,
505
+ "refreshMs": 2000,
506
+ "recentRoutes": 50,
507
+ "openBrowser": false,
508
+ "terminal": { "enabled": true, "pty": false }
509
+ }
510
+ }
511
+ ```
512
+
513
+ > **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.
514
+
515
+ ### Acceso remoto seguro: `openteam tunnel` — alfa
516
+
517
+ > ⚠️ **Alfa — sin terminar.** Igual que la Console, `tunnel` es experimental y
518
+ > puede rehacerse o reconstruirse. Trata sus flags y comportamiento como
519
+ > inestables.
520
+
521
+ Para acceder a la Console (y, opcionalmente, operar la terminal) **desde fuera**,
522
+ `openteam tunnel` la expone vía **Microsoft Dev Tunnels** en lugar de bindear a
523
+ `0.0.0.0`. Comprueba que `devtunnel` esté instalado y con sesión iniciada,
524
+ hospeda el puerto de la Console e imprime la URL pública hasta **Ctrl+C**:
525
+
526
+ ```powershell
527
+ openteam tunnel # expone solo la Console (observación), autenticado
528
+ openteam tunnel --terminal # además expone opencode para la terminal remota
529
+ openteam tunnel --allow-anonymous --yes # túnel anónimo (requiere doble confirmación)
530
+ ```
531
+
532
+ > **Seguridad del túnel**: autenticado por defecto. La **terminal remota** exige
533
+ > `OPENCODE_SERVER_PASSWORD` definido; sin ella, `--terminal` se ignora y solo se
534
+ > expone la Console (observación). El túnel **anónimo** requiere `--yes` (doble
535
+ > confirmación) y avisa de que opencode puede ejecutar comandos y editar ficheros.
536
+ > Instala devtunnel con `winget install Microsoft.devtunnel` e inicia sesión con
537
+ > `devtunnel user login`.
538
+
539
+ ### Memoria del equipo por MCP (solo lectura): `openteam mcp`
540
+
541
+ `openteam mcp` arranca un **servidor MCP de solo lectura** (JSON-RPC 2.0 sobre
542
+ stdio, sin dependencias) que expone la memoria del equipo agregada desde los
543
+ eventos por sesión para que agentes/herramientas la consulten. Se apoya en el
544
+ mismo `StorageProvider` que la Console y **nunca** expone prompts crudos, solo el
545
+ estado ya redactado. Tools disponibles: `list_decisions` (filtrable por
546
+ `agent`/`tag`), `list_meetings`, `list_sessions` y `cost_summary` (coste/tokens
547
+ reales + ahorro estimado vs baseline all-frontier).
548
+
549
+ Regístralo en `opencode.json` como cualquier MCP server local:
550
+
551
+ ```json
552
+ {
553
+ "mcp": {
554
+ "openteam-memory": {
555
+ "type": "local",
556
+ "command": ["openteam", "mcp"]
557
+ }
558
+ }
559
+ }
560
+ ```
561
+
562
+ #### Recall semántico (opt-in): `recall_facts`, `recall_preferences`, `similar_tasks`
563
+
564
+ Además de la memoria de equipo, `openteam mcp` puede exponer **recall semántico**
565
+ de la memoria de conocimiento long-term (hechos, preferencias, tareas similares).
566
+ Está **desactivado por defecto**; se activa con el bloque `memory.semantic` en
567
+ `.opencode/openteam.json`:
568
+
569
+ ```json
570
+ {
571
+ "memory": {
572
+ "semantic": { "enabled": true }
573
+ }
574
+ }
575
+ ```
576
+
577
+ Al activarlo, y si hay un runtime local con `baseURL`, el servidor añade tres
578
+ tools: `recall_facts`, `recall_preferences` y `similar_tasks`. La query se embebe
579
+ **en local** (nunca sale a frontier) y los records están **redactados en origen**
580
+ (`storeContent=false` por defecto), por lo que las tools nunca devuelven prompts
581
+ crudos. Si falta `bun:sqlite` o el índice no puede abrirse, `openteam mcp`
582
+ **degrada con seguridad** y sigue exponiendo solo la memoria de equipo.
583
+
584
+ #### Consolidación / olvido: `openteam memory consolidate`
585
+
586
+ La memoria long-term **olvida** por decay: la confianza de cada record decae con
587
+ el tiempo y, al caer bajo el umbral, se marca como soft-invalidated (sin borrar:
588
+ el histórico se conserva para auditoría "as-of"). Ejecuta la pasada de olvido con:
589
+
590
+ ```powershell
591
+ openteam memory consolidate
592
+ ```
593
+
594
+ Anexa *tombstones* al log de memoria y reporta cuántos records se olvidaron. Es
595
+ idempotente y no destructivo.
596
+
597
+ #### Push automático a contexto (opt-in)
598
+
599
+ Con la inyección activada, openteam **prepende** memoria relevante al prompt en
600
+ cada turno (`chat.message`), respetando un presupuesto de tokens:
601
+
602
+ ```json
603
+ {
604
+ "memory": {
605
+ "semantic": {
606
+ "enabled": true,
607
+ "injection": { "enabled": true, "maxChars": 1200, "maxItems": 8 }
608
+ }
609
+ }
610
+ }
611
+ ```
612
+
613
+ Está **desactivado por defecto**. La inyección ocurre **después** de decidir el
614
+ modelo, así que no altera el routing ni la telemetría, y **nunca rompe el turno**
615
+ si el recall falla. Solo inyecta lo que ya está en los records (redactado en
616
+ origen si `storeContent=false`).
617
+
618
+
619
+
620
+ ### Ollama
621
+
622
+ ```powershell
623
+ ollama serve
624
+ ollama pull qwen3:8b
625
+ Invoke-RestMethod -Uri "http://localhost:11434/v1/models" -Method Get
626
+ ```
627
+
628
+ ### LM Studio
629
+
630
+ 1. Abre LM Studio.
631
+ 2. Carga un modelo compatible.
632
+ 3. Activa el servidor local OpenAI-compatible en el puerto `1234`.
633
+
634
+ ```powershell
635
+ Invoke-RestMethod -Uri "http://localhost:1234/v1/models" -Method Get
636
+ ```
637
+
638
+ ### Foundry Local
639
+
640
+ ```powershell
641
+ foundry service status
642
+ ```
643
+
644
+ openteam extrae el puerto de la salida del CLI y normaliza el endpoint a `http://localhost:<PORT>/v1`.
645
+
646
+ ### Telemetría
647
+
648
+ ```powershell
649
+ $telemetryPath = "C:\gitrepos\openteam\.opencode\openteam-telemetry.jsonl"
650
+ Get-Content -Path $telemetryPath -Tail 5
651
+ ```
652
+
653
+ ### Verificación local
654
+
655
+ ```powershell
656
+ Set-Location -Path "C:\gitrepos\openteam"
657
+ bun test
658
+ bun run typecheck
659
+ bun run lint
660
+ bun run format:check
661
+ # Cuando el empaquetado de Fase 4 exponga el script:
662
+ bun run build
663
+ ```
664
+
665
+ ### Desarrollo local en modo dev (sin registry)
666
+
667
+ Para que la CLI global `openteam` y opencode usen la build local de este repo en
668
+ lugar de la versión publicada (sin pasar por ningún registry), se enlaza el
669
+ paquete con un symlink global:
670
+
671
+ ```powershell
672
+ Set-Location -Path "C:\gitrepos\openteam"
673
+ bun run link:local # = bun run build && npm link
674
+ ```
675
+
676
+ `npm link` crea un enlace global (junction/symlink) hacia este repo, así que tras
677
+ cada `bun run build` la CLI global refleja el código local.
678
+
679
+ Un hook `pre-push` versionado (`.githooks/pre-push`) puede ejecutar
680
+ `bun run link:local` antes de cada `git push`, manteniendo la instalación local al
681
+ día. La instalación de dependencias **no** modifica Git. Activa el hook
682
+ explícitamente, una vez por clone:
683
+
684
+ ```powershell
685
+ bun run hooks:install
686
+ ```
687
+
688
+ El hook avisa si el build o el link fallan, pero **no bloquea** el push.
689
+
690
+ ## Publicación segura
691
+
692
+ El workflow de release construye y verifica un único tarball sin permisos de
693
+ escritura ni OIDC. Otro job publica exactamente ese artefacto, después de validar
694
+ su integridad, mediante npm Trusted Publishing; un último job con solo
695
+ `contents: write` lo adjunta a la GitHub Release. No existe fallback a credenciales
696
+ persistentes y el CI normal no necesita configuración de npm.
697
+
698
+ Antes de la primera release real, el propietario debe registrar en npm un Trusted
699
+ Publisher para `@jmanuelcorral/openteam` con owner `jmanuelcorral`, repositorio
700
+ `openteam`, workflow `release.yml`, acción permitida `npm publish` y sin
701
+ environment. Hasta completar ese alta única, la publicación falla de forma
702
+ cerrada. Tras la primera publicación OIDC correcta, hay que exigir 2FA sin tokens,
703
+ revocar el antiguo token de automatización y eliminar su secreto heredado de
704
+ GitHub Actions.
705
+
706
+ ## Privacidad
707
+
708
+ 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`.
709
+
710
+ La telemetría usa `hashPrompt`, actualmente `fnv1a32:<hash>`, y no serializa el prompt completo.
711
+
712
+ ## Calidad
713
+
714
+ Gates no negociables:
715
+
716
+ - `bun test`
717
+ - Coverage global: líneas `>= 85%`, branches `>= 80%`.
718
+ - Coverage de `src/router/**`: `100%` lines, branches, statements y functions.
719
+ - `bun run typecheck`
720
+ - `biome check .` o `bun run lint` + `bun run format:check`
721
+ - Test de determinismo del router.
722
+ - Tests de contrato si cambian hooks opencode, agents, comandos, providers o SDK.
723
+
724
+ ## Compatibilidad
725
+
726
+ Consulta [docs/compatibility.md](docs/compatibility.md). Resumen verificado el `2026-08-19`:
727
+
728
+ | Superficie | Versión / contrato |
729
+ | --- | --- |
730
+ | openteam | `0.1.41`; versión actual del paquete |
731
+ | `@opencode-ai/plugin` | `1.17.13` |
732
+ | `@opencode-ai/sdk` | `1.17.13` |
733
+ | Hook de routing | `chat.message`; no `chat.params` para cambiar modelo |
734
+ | Subsesiones | `client.session.create` + `client.session.prompt({ body: { model } })` |
735
+
736
+ ## Roadmap
737
+
738
+ | Fase | Estado | Entregables |
739
+ | --- | --- | --- |
740
+ | 0. Scaffold/PoC | Hecha | TS/Bun, plugin mínimo, hook `chat.message`. |
741
+ | 1. Local registry + router heurístico | Hecha | Ollama/LM Studio/Foundry, probes y `chooseModel` determinista. |
742
+ | 2. Clasificador + perfiles + presupuesto + telemetría | Hecha | Clasificador local, `ModelCapabilityProfile`, budgets y `CostRecord`. |
743
+ | 3. Orquestación multiagente | Hecha | Coordinator, roles, child sessions y permisos. |
744
+ | 4. Empaquetado npm + docs | Hecha | Package exportable, README, ejemplos Windows y matriz de compatibilidad. |
745
+ | 5. Comandos runtime | Hecha | `baseline show/set/auto`, `doctor` y `report` vía tool, `/openteam` y CLI `bin`. |
746
+
747
+ ## Licencia
748
+
749
+ MIT. Consulta [LICENSE](LICENSE).
750
+
751
+ ## Agradecimientos e inspiración
752
+
753
+ openteam se apoya en trabajo previo. Estos proyectos han inspirado su diseño: tomamos ideas de ellos, las adaptamos a opencode y las reimplementamos desde cero en TypeScript:
754
+
755
+ - **[Squad](https://bradygaster.github.io/squad/)** ([bradygaster/squad](https://github.com/bradygaster/squad)) — el modelo de equipo multiagente temático creado a demanda: un único orquestador que castea subagentes especialistas según lo pide el trabajo. Inspiró el agente orquestador `openteam` y la convención de equipo/roster.
756
+ - **[Superpowers](https://github.com/obra/superpowers)** de Jesse Vincent — una metodología componible basada en *skills* para agentes de código. Inspiró las convenciones de agentes basadas en skills y el flujo spec-first / subagent-driven.
757
+ - **[agent-memory-dotnet](https://github.com/joslat/agent-memory-dotnet)** de José Luis Latorre — un modelo de memoria semántica a largo plazo para agentes. Inspiró el subsistema de memoria (extraer → rankear → consolidar → recuperar) con almacenamiento local-first y hash-redactado.
758
+
759
+ Todas las marcas y nombres de proyecto pertenecen a sus respectivos dueños; los enlaces anteriores son atribución, no un aval.