ostacky 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -17
- package/assets/agents/ostacky.md +3 -3
- package/assets/commands/install-stack.md +15 -115
- package/assets/docs/ostacky-reference.md +0 -2
- package/assets/mcp/ostacky-controller/index.js +2 -2
- package/assets/mcp/ostacky-controller/package.json +1 -1
- package/assets/plugins/ostacky-plugin.ts +48 -0
- package/assets/skills/brainstorming/SKILL.md +1 -1
- package/assets/skills/graceful-degradation/SKILL.md +0 -9
- package/dist/cli.js +251 -85
- package/manifest.json +30 -30
- package/package.json +1 -1
- package/assets/plugins/ostacky-guard.ts +0 -18
package/README.md
CHANGED
|
@@ -116,7 +116,10 @@ npx ostacky install --scope global # ~/.config/opencode (XDG/APPDATA en Windows
|
|
|
116
116
|
npx ostacky install --scope auto # local si existe .opencode/.git, si no global
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
Descarga todos los agentes y commands definidos en el manifest y los escribe en `.opencode/` (scope `local`) o en `~/.config/opencode` (`global`).
|
|
119
|
+
Descarga todos los agentes y commands definidos en el manifest y los escribe en `.opencode/` (scope `local`) o en `~/.config/opencode` (`global`). Además copia los plugins **Ostacky-owned** `ostacky-plugin.ts` + `engram.ts` en `.opencode/plugins/` (el legacy `ostacky-guard.ts` fue fusionado en `ostacky-plugin.ts` y ya no se instala; `ostacky-controller.ts` legacy se limpia automáticamente si quedó de una instalación previa).
|
|
120
|
+
|
|
121
|
+
> **Coherencia local/global:** aunque elijas `global`, los plugins y herramientas (`tools/` con CodeGraph/Engram) permanecen siempre en `<proyecto>/.opencode` local para el hard-gate por worktree. En global solo se escribe el scope global + un espejo local de plugins. Para stack completo por proyecto ejecutá `npx ostacky install --scope local` dentro de cada repo.
|
|
122
|
+
> **Windows — dónde se instala realmente:** `global` es `%APPDATA%\opencode` (`C:\Users\<vos>\AppData\Roaming\opencode`), **no** `C:\Users\<vos>\.opencode`. Si ves `C:\Users\...\ .opencode\tools\codegraph` y esperabas `D:\mi-proyecto\.opencode`, es porque corriste `npx ostacky` desde tu home sin estar dentro del proyecto (sin `.git`). Hacé `cd` al proyecto y re-ejecutá con `--scope local`; el log ahora muestra `projectRoot` y `toolsDir` explícitos para evitar confusión.
|
|
120
123
|
|
|
121
124
|
### Agregar agentes o commands individualmente
|
|
122
125
|
|
|
@@ -148,15 +151,21 @@ Solo descarga los items que cambiaron de versión.
|
|
|
148
151
|
### Desinstalar
|
|
149
152
|
|
|
150
153
|
```bash
|
|
151
|
-
npx ostacky uninstall
|
|
154
|
+
npx ostacky uninstall # pregunta local vs global, luego qué borrar
|
|
155
|
+
npx ostacky uninstall --scope local # fuerza scope local
|
|
156
|
+
npx ostacky uninstall --scope global # fuerza scope global
|
|
157
|
+
npx ostacky uninstall --scope auto # auto
|
|
152
158
|
```
|
|
153
159
|
|
|
154
|
-
|
|
160
|
+
**Safe-delete:** solo borra lo trackeado en `.opencode/ostacky-lock.json` (agentes, commands, skills, MCPs) — nunca toca componentes previos del usuario que no estén en el lockfile. Antes de borrar muestra preview con `Scope: <ruta>` + lista de paths y pide confirmación. Los plugins Ostacky-owned (`ostacky-plugin.ts`, `engram.ts` + legacy `ostacky-guard.ts`/`ostacky-controller.ts` si quedaron) se limpian automáticamente via allowlist, nunca se borran plugins custom.
|
|
161
|
+
|
|
162
|
+
> Si el lockfile no existe o está vacío → `No hay nada instalado.` y no borra nada.
|
|
155
163
|
|
|
156
164
|
#### Desinstalar un agente puntual
|
|
157
165
|
|
|
158
166
|
```bash
|
|
159
|
-
npx ostacky uninstall agent <nombre>
|
|
167
|
+
npx ostacky uninstall agent <nombre> # también admite --scope local|global|auto
|
|
168
|
+
npx ostacky uninstall agent # sin nombre → selector de instalados
|
|
160
169
|
```
|
|
161
170
|
|
|
162
171
|
Por ejemplo:
|
|
@@ -168,7 +177,8 @@ npx ostacky uninstall agent ostacky
|
|
|
168
177
|
#### Desinstalar un command puntual
|
|
169
178
|
|
|
170
179
|
```bash
|
|
171
|
-
npx ostacky uninstall command <nombre>
|
|
180
|
+
npx ostacky uninstall command <nombre> # también admite --scope
|
|
181
|
+
npx ostacky uninstall command # sin nombre → selector
|
|
172
182
|
```
|
|
173
183
|
|
|
174
184
|
Por ejemplo:
|
|
@@ -179,6 +189,15 @@ npx ostacky uninstall command install-stack
|
|
|
179
189
|
|
|
180
190
|
Si no especificás el nombre, el CLI te muestra un selector con los items instalados para que elijas cuáles desinstalar (puede ser uno o varios).
|
|
181
191
|
|
|
192
|
+
#### Desinstalar todo el stack (tools + config)
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
npx ostacky uninstall-stack # pregunta scope, limpia mcp.codegraph/engram de opencode.json + .codegraph/ + .opencode/tools/
|
|
196
|
+
npx ostacky uninstall-stack --scope local
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
No toca binarios globales ni datos de Engram, solo la configuración del proyecto.
|
|
200
|
+
|
|
182
201
|
### Otros
|
|
183
202
|
|
|
184
203
|
```bash
|
|
@@ -188,7 +207,7 @@ npx ostacky --help # muestra la ayuda
|
|
|
188
207
|
|
|
189
208
|
## Estructura generada
|
|
190
209
|
|
|
191
|
-
Tras instalar, el proyecto queda así:
|
|
210
|
+
Tras instalar (`--scope local`), el proyecto queda así:
|
|
192
211
|
|
|
193
212
|
```
|
|
194
213
|
.opencode/
|
|
@@ -212,44 +231,63 @@ Tras instalar, el proyecto queda así:
|
|
|
212
231
|
│ ├── using-superpowers/
|
|
213
232
|
│ ├── writing-skills/
|
|
214
233
|
│ └── graceful-degradation/
|
|
215
|
-
|
|
234
|
+
├── plugins/
|
|
235
|
+
│ ├── ostacky-plugin.ts ← controller hard-gate (fusiona guard legacy)
|
|
236
|
+
│ └── engram.ts ← plugin Engram
|
|
237
|
+
├── mcp/
|
|
238
|
+
│ ├── ostacky-controller/ ← MCP thin (observabilidad)
|
|
239
|
+
│ └── openspec/
|
|
240
|
+
├── tools/
|
|
241
|
+
│ ├── codegraph/bin/codegraph
|
|
242
|
+
│ └── engram/bin/engram
|
|
243
|
+
├── cache/codegraph/ ← cache local CodeGraph/Discovery
|
|
244
|
+
├── ostacky-state.json ← estado por worktree (aislado)
|
|
245
|
+
└── ostacky-lock.json ← versiones instaladas (agentes, commands, skills, mcpServers)
|
|
216
246
|
```
|
|
217
247
|
|
|
248
|
+
> `assets/plugins/ostacky-guard.ts` fue **fusionado en `ostacky-plugin.ts` y eliminado** (re-export legacy). Fresh install solo escribe `ostacky-plugin.ts` + `engram.ts`; si venís de una versión previa con `ostacky-guard.ts` o `ostacky-controller.ts` legacy, el installer los elimina automáticamente.
|
|
249
|
+
|
|
218
250
|
### ostacky-lock.json
|
|
219
251
|
|
|
220
252
|
```json
|
|
221
253
|
{
|
|
222
|
-
"version": "0.8.
|
|
254
|
+
"version": "0.8.2",
|
|
223
255
|
"lockedAt": "2025-01-01T00:00:00.000Z",
|
|
224
256
|
"repo": "JaimeHoracio/Ostacky",
|
|
225
|
-
"tag": "v0.8.
|
|
257
|
+
"tag": "v0.8.2",
|
|
226
258
|
"agents": {
|
|
227
259
|
"ostacky": {
|
|
228
|
-
"version": "0.8.
|
|
260
|
+
"version": "0.8.2",
|
|
229
261
|
"installedAt": "2025-01-01T00:00:00.000Z",
|
|
230
262
|
"sha256": "abc123..."
|
|
231
263
|
}
|
|
232
264
|
},
|
|
233
265
|
"commands": {
|
|
234
266
|
"install-stack": {
|
|
235
|
-
"version": "0.8.
|
|
267
|
+
"version": "0.8.2",
|
|
236
268
|
"installedAt": "2025-01-01T00:00:00.000Z",
|
|
237
269
|
"sha256": "def456..."
|
|
238
270
|
},
|
|
239
271
|
"opsx-sync": {
|
|
240
|
-
"version": "0.8.
|
|
272
|
+
"version": "0.8.2",
|
|
241
273
|
"installedAt": "2025-01-01T00:00:00.000Z",
|
|
242
274
|
"sha256": "ghi789..."
|
|
243
275
|
}
|
|
244
276
|
},
|
|
245
277
|
"skills": {
|
|
246
|
-
"brainstorming": { "version": "0.8.
|
|
247
|
-
"execution-mode-evaluation": { "version": "0.8.
|
|
248
|
-
"openspec-propose": { "version": "0.8.
|
|
278
|
+
"brainstorming": { "version": "0.8.2", ... },
|
|
279
|
+
"execution-mode-evaluation": { "version": "0.8.2", ... },
|
|
280
|
+
"openspec-propose": { "version": "0.8.2", ... }
|
|
281
|
+
},
|
|
282
|
+
"mcpServers": {
|
|
283
|
+
"ostacky-controller": { "version": "0.8.2", ... },
|
|
284
|
+
"openspec": { "version": "0.8.2", ... }
|
|
249
285
|
}
|
|
250
286
|
}
|
|
251
287
|
```
|
|
252
288
|
|
|
289
|
+
`plugins/` (`ostacky-plugin.ts`, `engram.ts`) y `tools/` **no** se trackean en el lockfile — son allowlist Ostacky-owned y se gestionan via `uninstall` (allowlist) y `uninstall-stack`.
|
|
290
|
+
|
|
253
291
|
Se recomienda agregar `ostacky-lock.json` al control de versiones para que el equipo instale exactamente las mismas versiones.
|
|
254
292
|
|
|
255
293
|
## Después de la instalación
|
|
@@ -275,7 +313,7 @@ Es opcional y solo necesario si algo falló durante la instalación o si querés
|
|
|
275
313
|
## Seguridad
|
|
276
314
|
|
|
277
315
|
- `opencode.jsonc` se versiona en el repo para compartir permisos y MCP de forma reproducible.
|
|
278
|
-
- Las URLs de descarga usan **tags de GitHub** (ej. `v0.8.
|
|
316
|
+
- Las URLs de descarga usan **tags de GitHub** (ej. `v0.8.2`), nunca `main` — instalaciones reproducibles
|
|
279
317
|
- Cada path de archivo descargado es validado para prevenir **path traversal**
|
|
280
318
|
- Los archivos incluyen **checksum SHA-256** opcional; si el manifest lo define, el contenido se verifica antes de escribir
|
|
281
319
|
- El cache local (`.opencode/cache/`) también valida integridad al servir archivos cacheados
|
|
@@ -291,7 +329,7 @@ Es opcional y solo necesario si algo falló durante la instalación o si querés
|
|
|
291
329
|
- Variable `OSTACKY_SENSITIVE_PATTERNS` overridea los patrones por defecto (`**/.env*`, `**/.secrets/**`, `**/*.pem`, `**/*.key`, `**/.aws/**`, `**/.ssh/**`, `**/credentials.json`, `**/.npmrc`).
|
|
292
330
|
- Ejemplo: `OSTACKY_SENSITIVE_PATTERNS="**/.env*,**/.secrets/**" bunx ostacky doctor` — `doctor` imprime el patrón efectivo.
|
|
293
331
|
- Allowlist: `.env.example`, `.env.template`, `.env.sample` nunca se bloquean.
|
|
294
|
-
- Fuente única: `src/security.ts` (`SENSITIVE_DEFAULT`, `isSensitive`, `BASH_SENSITIVE_RE`) — guard
|
|
332
|
+
- Fuente única: `src/security.ts` (`SENSITIVE_DEFAULT`, `isSensitive`, `BASH_SENSITIVE_RE`) — `ostacky-plugin.ts` importa de ahí (legacy `ostacky-guard.ts` eliminado, fusionado en el plugin). Ver `doctor` para verificar.
|
|
295
333
|
|
|
296
334
|
#### Aislamiento de worktrees (harness-prod-hardening)
|
|
297
335
|
|
|
@@ -332,6 +370,8 @@ CodeGraph está instalado en `.opencode/tools/codegraph/bin/codegraph` y se conf
|
|
|
332
370
|
| `.opencode/tools/codegraph/bin/codegraph status` | Muestra estado del index y archivos pendientes |
|
|
333
371
|
| `.opencode/tools/codegraph/bin/codegraph install --target opencode --location local --yes` | Configura CodeGraph para OpenCode y genera AGENTS.md |
|
|
334
372
|
|
|
373
|
+
> **Windows:** si ves `Command failed: cmd.exe /d /c call ... codegraph.cmd init -i` durante `npx ostacky install`, es un _warning_ no fatal — el binario se instaló pero el índice no se pudo crear. Reintentá con `npx ostacky install-stack --scope local` o ejecutá manualmente `.opencode\tools\codegraph\bin\codegraph.exe init -i` (o `codegraph.cmd` si no hay `.exe`) dentro del proyecto. Desde v0.8.2 el instalador usa el patrón resiliente de Engram (strip 0 + búsqueda recursiva) y loguea `projectRoot|toolsDir` para diagnosticar scope.
|
|
374
|
+
|
|
335
375
|
## Licencia
|
|
336
376
|
|
|
337
377
|
MIT
|
package/assets/agents/ostacky.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Orquestador principal — rutea por nivel, orquesta CodeGraph + OpenSpec + Superpowers.
|
|
3
3
|
mode: primary
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Sos **Ostacky v0.8.
|
|
7
|
+
Sos **Ostacky v0.8.2**, orquestás, no implementás. Interpretás, clasificás (0/0+1/1+), ruteás y coordinás.
|
|
8
8
|
|
|
9
|
-
> **Versión:** `0.8.
|
|
9
|
+
> **Versión:** `0.8.2` (sincronizada desde `package.json` vía `scripts/sync-version.ts`). Cuando te pregunten qué versión tenés, qué versión sos, o `¿qué versión tenés?` / `version` / `¿en qué versión estás?`, respondé exactamente: **"Ostacky v0.8.2"** (o `v0.8.2` si te piden solo el número). No inventes otra versión.
|
|
10
10
|
|
|
11
11
|
## Reglas innegociables
|
|
12
12
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Instala CodeGraph, skills curadas, OpenSpec
|
|
2
|
+
description: Instala CodeGraph, skills curadas, OpenSpec y Engram localmente para OpenCode únicamente
|
|
3
3
|
agent: build
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
Instala el stack tecnológico de desarrollo para OpenCode. **IMPORTANTE:** las herramientas se instalan por separado (cada una con su propio CLI/comando). `npx ostacky install` solo instala el agente y commands de Ostacky en `.opencode/`. Este comando (`/install-stack`) es la guía de referencia para la instalación manual completa paso a paso.
|
|
7
7
|
|
|
8
|
-
**Nota:** A partir de v0.8.
|
|
8
|
+
**Nota:** A partir de v0.8.2, `npx ostacky install` ya instala automáticamente el stack completo (CodeGraph, OpenSpec, Engram, MCPs bundleados) además del agente y skills. Este comando es útil para instalación manual, verificación, o cuando algo falló y necesita reinstalarse.
|
|
9
9
|
|
|
10
10
|
**RESTRICCIÓN ABSOLUTA:** instalar ÚNICAMENTE para OpenCode. Está terminantemente prohibido crear o modificar archivos en `.claude/`, `.kiro/`, `.cursor/`, `.gemini/`, `.codex/`, `.antigravity/`, `.windsurf/` o cualquier otro directorio de plataformas externas.
|
|
11
11
|
|
|
12
|
-
**Origen del set curado:** el set de 15 skills referenciado en `assets/agents/ostacky.md` está bundleado en `assets/skills/` dentro del paquete npm.
|
|
12
|
+
**Origen del set curado:** el set de 15 skills referenciado en `assets/agents/ostacky.md` está bundleado en `assets/skills/` dentro del paquete npm. La definición del set y su trazabilidad viven en `manifest.json` y `.opencode/ostacky-lock.json`.
|
|
13
13
|
|
|
14
|
-
## Scope de instalación — local vs global (desde v0.8.
|
|
14
|
+
## Scope de instalación — local vs global (desde v0.8.2)
|
|
15
15
|
|
|
16
16
|
`npx ostacky install` soporta `--scope local|global|auto` (también `--scope=...`):
|
|
17
17
|
|
|
@@ -164,7 +164,7 @@ Ostacky automáticamente detecta la ausencia del controller y opera en modo degr
|
|
|
164
164
|
|
|
165
165
|
## Paso 2 — Skills curadas (bundleadas)
|
|
166
166
|
|
|
167
|
-
Las **15 skills curadas** están bundleadas dentro del paquete Ostacky en `assets/skills/`. No se descargan ni clonan; ya vienen en el paquete npm.
|
|
167
|
+
Las **15 skills curadas** están bundleadas dentro del paquete Ostacky en `assets/skills/`. No se descargan ni clonan; ya vienen en el paquete npm.
|
|
168
168
|
|
|
169
169
|
Copiá cada skill bundleada a `.opencode/skills/<nombre>/` preservando la estructura interna (incluyendo `SKILL.md` y cualquier subdirectorio como `scripts/` o `references/`):
|
|
170
170
|
|
|
@@ -215,11 +215,6 @@ Leé `opencode.json` (o `opencode.jsonc`) en la raíz del proyecto.
|
|
|
215
215
|
"command": [".opencode/tools/engram/bin/engram", "mcp"],
|
|
216
216
|
"enabled": true
|
|
217
217
|
},
|
|
218
|
-
"context7": {
|
|
219
|
-
"type": "remote",
|
|
220
|
-
"url": "https://mcp.context7.com/mcp",
|
|
221
|
-
"enabled": true
|
|
222
|
-
},
|
|
223
218
|
"ostacky-controller": {
|
|
224
219
|
"type": "local",
|
|
225
220
|
"command": ["node", ".opencode/mcp/ostacky-controller/index.js"],
|
|
@@ -353,99 +348,6 @@ rm -rf ~/.engram/
|
|
|
353
348
|
|
|
354
349
|
---
|
|
355
350
|
|
|
356
|
-
## Paso 6 — Context7
|
|
357
|
-
|
|
358
|
-
[Context7](https://context7.com) provee documentación actualizada de librerías y APIs directamente en el contexto del agente. Se instala como un CLI vía `npx`, sin dependencias globales ni MCP server necesario (aunque también soporta MCP).
|
|
359
|
-
|
|
360
|
-
**RESTRICCIÓN:** configurar ÚNICAMENTE para OpenCode. Está terminantemente prohibido crear archivos en `.claude/`, `.kiro/`, `.cursor/`, `.gemini/`, `.codex/`, `.antigravity/`, `.windsurf/` o cualquier otro directorio de plataformas externas.
|
|
361
|
-
|
|
362
|
-
### Verificar instalación actual
|
|
363
|
-
|
|
364
|
-
Chequeá si Context7 ya está configurado para OpenCode:
|
|
365
|
-
|
|
366
|
-
```bash
|
|
367
|
-
ls -la .opencode/skills/context7/ 2>/dev/null || echo "no-instalado"
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
También podés verificar si el MCP server de Context7 está en `opencode.json`:
|
|
371
|
-
|
|
372
|
-
```bash
|
|
373
|
-
grep -c "context7" opencode.json 2>/dev/null || echo "no-configurado"
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Instalar
|
|
377
|
-
|
|
378
|
-
**Opción recomendada — setup automático (CLI + skills):**
|
|
379
|
-
|
|
380
|
-
```bash
|
|
381
|
-
npx ctx7 setup --opencode
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
Este comando:
|
|
385
|
-
|
|
386
|
-
- Autentica vía OAuth y genera una API key
|
|
387
|
-
- Instala un skill en `.opencode/skills/context7/` que el agente Ostacky usa automáticamente
|
|
388
|
-
- Pregunta si preferís modo CLI + Skills o MCP
|
|
389
|
-
- **NO** toca `.claude/`, `.cursor/`, `.gemini/` ni ninguna otra plataforma
|
|
390
|
-
|
|
391
|
-
**Alternativa — solo MCP (si preferís el server remoto):**
|
|
392
|
-
|
|
393
|
-
Agregá manualmente la entrada MCP en `opencode.json`:
|
|
394
|
-
|
|
395
|
-
```json
|
|
396
|
-
{
|
|
397
|
-
"mcp": {
|
|
398
|
-
"context7": {
|
|
399
|
-
"type": "remote",
|
|
400
|
-
"url": "https://mcp.context7.com/mcp"
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
Si tenés una API key de Context7 (recomendado para mejores rate limits):
|
|
407
|
-
|
|
408
|
-
```json
|
|
409
|
-
{
|
|
410
|
-
"mcp": {
|
|
411
|
-
"context7": {
|
|
412
|
-
"type": "remote",
|
|
413
|
-
"url": "https://mcp.context7.com/mcp",
|
|
414
|
-
"headers": {
|
|
415
|
-
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
### Desinstalar
|
|
423
|
-
|
|
424
|
-
Para remover la configuración generada por `npx ctx7 setup`:
|
|
425
|
-
|
|
426
|
-
```bash
|
|
427
|
-
npx ctx7 remove
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
Esto elimina el skill y la configuración de Context7. Si instalaste el CLI globalmente con `npm install -g ctx7`, también necesitás:
|
|
431
|
-
|
|
432
|
-
```bash
|
|
433
|
-
npm uninstall -g ctx7
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
Para remover la entrada MCP manual, editá `opencode.json` y eliminá el bloque `mcp.context7`.
|
|
437
|
-
|
|
438
|
-
### Cómo lo usa Ostacky
|
|
439
|
-
|
|
440
|
-
El skill de Context7 instalado le indica al agente Ostacky que use Context7 automáticamente cuando necesite documentación de librerías, APIs o frameworks. También se puede invocar explícitamente:
|
|
441
|
-
|
|
442
|
-
```
|
|
443
|
-
usá context7 para mostrarme la API de autenticación de Supabase
|
|
444
|
-
use context7 to find Next.js 15 app router examples
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
---
|
|
448
|
-
|
|
449
351
|
## Estructura de herramientas
|
|
450
352
|
|
|
451
353
|
Cada herramienta se instala en su propia carpeta dentro de `.opencode/` para mantener una instalación limpia y aislada. El installer crea automáticamente `.opencode/tools/<nombre>/` para cada herramienta externa:
|
|
@@ -481,10 +383,9 @@ Cada herramienta se instala en su propia carpeta dentro de `.opencode/` para man
|
|
|
481
383
|
│ ├── using-superpowers/
|
|
482
384
|
│ ├── writing-skills/
|
|
483
385
|
│ └── graceful-degradation/
|
|
484
|
-
├── tools/ #
|
|
485
|
-
│ ├── codegraph/ #
|
|
486
|
-
│
|
|
487
|
-
│ └── context7/ # Config de Context7
|
|
386
|
+
├── tools/ # Binarios locales de herramientas externas
|
|
387
|
+
│ ├── codegraph/ # Binario local de CodeGraph
|
|
388
|
+
│ └── engram/ # Binario local de Engram
|
|
488
389
|
└── plugins/ # Plugins de OpenCode
|
|
489
390
|
```
|
|
490
391
|
|
|
@@ -493,24 +394,23 @@ Cada herramienta se instala en su propia carpeta dentro de `.opencode/` para man
|
|
|
493
394
|
- `.codegraph/` (índice de CodeGraph) vive en la raíz del proyecto — CodeGraph lo espera ahí.
|
|
494
395
|
- El binario de CodeGraph es **local al proyecto** en `.opencode/tools/codegraph/bin/`; en Windows puede ser `codegraph.cmd`. No se instala globalmente.
|
|
495
396
|
- El binario de Engram es **local al proyecto** en `.opencode/tools/engram/bin/engram` (o `engram.exe` en Windows). No se instala globalmente.
|
|
496
|
-
-
|
|
397
|
+
- El binary de CodeGraph y Engram vive siempre en `<proyecto>/.opencode/tools/` por reproducibilidad, nunca global.
|
|
497
398
|
- El controller publicado se bundlea como un único `index.js`; durante desarrollo el installer instala sus dependencias en staging y valida el servidor antes de activarlo.
|
|
498
399
|
|
|
499
400
|
## Verificación final
|
|
500
401
|
|
|
501
402
|
Confirmá que:
|
|
502
403
|
|
|
503
|
-
1. `.opencode/skills/` contiene las 15 skills curadas
|
|
404
|
+
1. `.opencode/skills/` contiene las 15 skills curadas
|
|
504
405
|
2. `.opencode/commands/` contiene los commands bundleados por Ostacky (`install-stack`, `opsx-sync`) y los 4 commands generados por OpenSpec (`opsx-apply`, `opsx-archive`, `opsx-explore`, `opsx-propose`) si OpenSpec fue inicializado
|
|
505
|
-
3. `opencode.json` (o `.jsonc`) tiene los bloques MCP: `codegraph`, `engram`, `
|
|
406
|
+
3. `opencode.json` (o `.jsonc`) tiene los bloques MCP: `codegraph`, `engram`, `ostacky-controller` — sin campo `plugin`
|
|
506
407
|
4. `.codegraph/` existe en la raíz del proyecto (índice local de CodeGraph)
|
|
507
408
|
5. El launcher local de CodeGraph funciona (`codegraph.cmd --version` en Windows o `codegraph --version` en Unix)
|
|
508
409
|
6. El binario local de Engram funciona (`engram.exe --version` en Windows o `engram --version` en Unix)
|
|
509
|
-
7.
|
|
510
|
-
8.
|
|
511
|
-
9.
|
|
512
|
-
10.
|
|
513
|
-
11. Un `AGENTS.md` preexistente en la raíz del proyecto se preserva sin cambios
|
|
410
|
+
7. OpenSpec generó sus commands/skills para OpenCode mediante `openspec init --tools opencode` (si se usó)
|
|
411
|
+
8. `.opencode/tools/` contiene subdirectorios para `codegraph/` y `engram/`
|
|
412
|
+
9. **NO existen** archivos generados en `.claude/`, `.kiro/`, `.cursor/`, `.gemini/`, `.codex/` ni ningún directorio de otra plataforma
|
|
413
|
+
10. Un `AGENTS.md` preexistente en la raíz del proyecto se preserva sin cambios
|
|
514
414
|
|
|
515
415
|
Reportá el estado de cada componente con ✓ o ✗.
|
|
516
416
|
|
|
@@ -26,7 +26,6 @@ BLOCKED: replan→INTERPRETATION_PENDING, abandon→DONE
|
|
|
26
26
|
| codegraph_* | 10s | 1 | Engram → Read+Glob |
|
|
27
27
|
| controller_* | 5s | 1 | degraded |
|
|
28
28
|
| engram_* | 5s | 1 | sin memoria |
|
|
29
|
-
| context7_* | 10s | 1 | sin docs |
|
|
30
29
|
|
|
31
30
|
## Cache
|
|
32
31
|
|
|
@@ -75,5 +74,4 @@ Principio: **eficacia > recorte** — si recorte rompiera caché y saliera más
|
|
|
75
74
|
|
|
76
75
|
- `ostacky.md` 109→72 líneas (diet estable cacheable). Tiered vía suffix, no reemplazo `system[0]`.
|
|
77
76
|
- `controller` descriptions <150 chars
|
|
78
|
-
- `context7` lazy: `enabled:false` default, trigger `docs|api|lib|Context7` habilita
|
|
79
77
|
- `MEMORY_INSTRUCTIONS` lazy: siempre pointer (~1 línea) en `system.transform`; full vive en `assets/docs/engram-protocol.md` on-demand via `Read` (ahorro ~1.2k en FULL, trivial ya era pointer)
|
|
@@ -2371,7 +2371,7 @@ function safeHandler(fn, options = {}) {
|
|
|
2371
2371
|
|
|
2372
2372
|
const server = new McpServer({
|
|
2373
2373
|
name: 'ostacky-controller',
|
|
2374
|
-
version: '0.8.
|
|
2374
|
+
version: '0.8.2',
|
|
2375
2375
|
});
|
|
2376
2376
|
|
|
2377
2377
|
server.registerTool(
|
|
@@ -2971,7 +2971,7 @@ function setupGracefulShutdown(ctrl) {
|
|
|
2971
2971
|
}
|
|
2972
2972
|
|
|
2973
2973
|
async function main() {
|
|
2974
|
-
log('Starting ostacky-controller MCP v0.8.
|
|
2974
|
+
log('Starting ostacky-controller MCP v0.8.2...');
|
|
2975
2975
|
log('State path:', { path: statePath });
|
|
2976
2976
|
// Clean up stale tmp/lock files from previous runs
|
|
2977
2977
|
cleanupTmpFiles(statePath);
|
|
@@ -20,6 +20,10 @@ import { isTrivial } from "../../src/tiered.ts"
|
|
|
20
20
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
21
21
|
|
|
22
22
|
const MAX_STATE_FILE_SIZE = 2 * 1024 * 1024
|
|
23
|
+
const PING_INTERVAL_MS = 60_000
|
|
24
|
+
const IDLE_THRESHOLD_MS = 45_000
|
|
25
|
+
const PURPLE_TENUE = "\x1b[38;5;183m"
|
|
26
|
+
const PURPLE_RESET = "\x1b[0m"
|
|
23
27
|
|
|
24
28
|
const STATES = Object.freeze({
|
|
25
29
|
INTERPRETATION_PENDING: "INTERPRETATION_PENDING",
|
|
@@ -254,6 +258,9 @@ function isCodegraphAvailable(directory: string): boolean {
|
|
|
254
258
|
const trivialBySession = new Map<string, boolean>()
|
|
255
259
|
// Track discovery hit per requestId to avoid blocking after hit
|
|
256
260
|
const discoveryHitByRequest = new Map<string, boolean>()
|
|
261
|
+
// ─── Heartbeat ping — evita sensación de trancado en tareas largas ──
|
|
262
|
+
let lastPingTs = 0
|
|
263
|
+
let pingInterval: ReturnType<typeof setInterval> | null = null
|
|
257
264
|
|
|
258
265
|
// ─── Plugin ──────────────────────────────────────────────────────────────────
|
|
259
266
|
|
|
@@ -267,6 +274,30 @@ export const OstackyController: Plugin = async (ctx) => {
|
|
|
267
274
|
let lastCheck: { revision: number; result: string } | null = null
|
|
268
275
|
let checkCount = 0
|
|
269
276
|
|
|
277
|
+
// Heartbeat ping — purple tenue, evita sensación de trancado en tareas largas
|
|
278
|
+
if (!pingInterval) {
|
|
279
|
+
pingInterval = setInterval(async () => {
|
|
280
|
+
try {
|
|
281
|
+
const s = readState(ctx.directory)
|
|
282
|
+
if (!s || !["EXECUTING_INLINE", "EXECUTING_SUBAGENTS", "SYNC"].includes(s.state)) return
|
|
283
|
+
const now = Date.now()
|
|
284
|
+
const lastHeartbeat = s.lastHeartbeat || s.ts || now
|
|
285
|
+
const idle = now - lastHeartbeat
|
|
286
|
+
if (idle < IDLE_THRESHOLD_MS) return
|
|
287
|
+
if (now - lastPingTs < PING_INTERVAL_MS) return
|
|
288
|
+
lastPingTs = now
|
|
289
|
+
const completed = Object.values(s.tasks || {}).filter((t: any) => t.status === "COMPLETED").length
|
|
290
|
+
const total = s.expectedTaskCount ?? s.expectedTasks?.length ?? "?"
|
|
291
|
+
const pending = Array.isArray(s.expectedTasks) ? s.expectedTasks.filter((id: string) => !s.tasks?.[id] || s.tasks[id].status !== "COMPLETED").length : "?"
|
|
292
|
+
const msg = `🟣 ${PURPLE_TENUE}[OSTACKY]${PURPLE_RESET} ⏳ Sigo trabajando — ${s.state} • ${completed}/${total} (${pending} pendientes) • hace ${Math.round(idle/1000)}s sin output`
|
|
293
|
+
try { await (ctx as any).client?.tui?.showToast?.({ body: { message: msg, variant: "info" } } as any) } catch {}
|
|
294
|
+
try { await (ctx as any).client?.app?.log?.({ body: { service: "ostacky-ping", level: "info", message: msg } } as any) } catch {}
|
|
295
|
+
try { const st = readState(ctx.directory); if (st) { (st as any).lastPingTs = now; persistState(ctx.directory, st) } } catch {}
|
|
296
|
+
} catch {}
|
|
297
|
+
}, 30_000)
|
|
298
|
+
if (pingInterval && typeof (pingInterval as any).unref === 'function') (pingInterval as any).unref()
|
|
299
|
+
}
|
|
300
|
+
|
|
270
301
|
return {
|
|
271
302
|
// ── Tiered: suffix hint on user message (cache-friendly, no system replace) ──
|
|
272
303
|
"chat.message": async (input: any, output: any) => {
|
|
@@ -527,6 +558,18 @@ export const OstackyController: Plugin = async (ctx) => {
|
|
|
527
558
|
const s = readState((input as any).ctx?.directory ?? "")
|
|
528
559
|
} catch {}
|
|
529
560
|
}
|
|
561
|
+
// Heartbeat + color purple tenue: Ostacky vs modelo (fácil)
|
|
562
|
+
try {
|
|
563
|
+
const dir = ctx.directory
|
|
564
|
+
const s = readState(dir)
|
|
565
|
+
if (s) {
|
|
566
|
+
s.lastHeartbeat = Date.now()
|
|
567
|
+
try { persistState(dir, s) } catch {}
|
|
568
|
+
if (["EXECUTING_INLINE", "EXECUTING_SUBAGENTS", "SYNC"].includes(s.state) && output && typeof output.title === "string" && output.title && !output.title.includes("🟣")) {
|
|
569
|
+
output.title = `🟣 ${PURPLE_TENUE}[OSTACKY]${PURPLE_RESET} ${output.title}`
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
} catch {}
|
|
530
573
|
},
|
|
531
574
|
|
|
532
575
|
// ── Observable tools (MCP thin replacement) ──
|
|
@@ -622,6 +665,11 @@ export const OstackyController: Plugin = async (ctx) => {
|
|
|
622
665
|
}
|
|
623
666
|
},
|
|
624
667
|
|
|
668
|
+
dispose: async () => {
|
|
669
|
+
try { if (pingInterval) clearInterval(pingInterval) } catch {}
|
|
670
|
+
pingInterval = null
|
|
671
|
+
},
|
|
672
|
+
|
|
625
673
|
"experimental.session.compacting": async (input: any, output: any) => {
|
|
626
674
|
try {
|
|
627
675
|
const statePath = getStatePath(ctx.directory)
|
|
@@ -38,7 +38,7 @@ Do NOT invoke any implementation skill, write any code, or scaffold any project
|
|
|
38
38
|
|
|
39
39
|
1. **Check discovery-cache first** — `src/discovery-cache.ts` `getDiscoverySnapshot(query)` + `getEngramDedup(query, requestId)`. Si hit válido (TTL+gitDiffHash), **reusar** sin llamar tools. Solo si miss → `engram_mem_search` + `codegraph_codegraph_explore` y **SHALL `putDiscoverySnapshot`** antes de avanzar. No re-llamar si área difiere <30% del snapshot.
|
|
40
40
|
2. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria
|
|
41
|
-
4. **Propose 2-3 approaches (hardening-v2 — SHALL)** — con tabla trade-offs (coste|riesgo|complejidad) + evidencia CodeGraph+Engram
|
|
41
|
+
4. **Propose 2-3 approaches (hardening-v2 — SHALL)** — con tabla trade-offs (coste|riesgo|complejidad) + evidencia CodeGraph+Engram sin alucinar, YAGNI, y recomendación con razón; cada approach cita symbols existentes y mem_search hits verificables
|
|
42
42
|
5. **Present design** — in sections scaled to complexity, get user approval after each section. **Gate post-brainstorming (hardening-v2):** tras presentar diseño, preguntar "¿Procedo con este diseño o querés ajustar algo?" y esperar confirmación explícita antes de `record_discovery`, `openspec-propose` o implementación directa
|
|
43
43
|
6. **Write design doc (output path condicional — router exclusivo):**
|
|
44
44
|
- Si trigger + `level 1+` no-downgradeable (`estLines>30` o `fileCount>2` o API pública) y change activo → escribir `openspec/changes/<id>/design.md` sección `## Alternatives Considered` con 2-3 approaches (tabla coste|riesgo|complejidad + evidencia CodeGraph+Engram), no `docs/`. No invocar `openspec-propose` separado — este es el diseño.
|
|
@@ -20,7 +20,6 @@ When critical tools are unavailable, this skill provides a systematic approach t
|
|
|
20
20
|
| CodeGraph | MCP server | Engram → Read + Glob | No structural analysis, manual exploration |
|
|
21
21
|
| Engram | MCP server | Continue without memory | No persistence across sessions |
|
|
22
22
|
| Controller | MCP server | Inline validation + manual state | No state machine, no edit validation |
|
|
23
|
-
| Context7 | MCP server (remote) | Skip documentation | No external API docs |
|
|
24
23
|
|
|
25
24
|
## Detection
|
|
26
25
|
|
|
@@ -108,12 +107,6 @@ Incluso en degraded, el guard de credenciales sigue activo (hard gate incluso en
|
|
|
108
107
|
- No state persistence across crashes
|
|
109
108
|
- No pending state enforcement (check_pending_state unavailable)
|
|
110
109
|
|
|
111
|
-
### Without Context7
|
|
112
|
-
|
|
113
|
-
**Impact:** Minimal — only affects external API documentation lookups.
|
|
114
|
-
|
|
115
|
-
**Workflow:** Proceed normally. Use existing knowledge.
|
|
116
|
-
|
|
117
110
|
## Communication Protocol
|
|
118
111
|
|
|
119
112
|
### Status Report Format
|
|
@@ -141,7 +134,6 @@ Herramientas disponibles:
|
|
|
141
134
|
✅ Controller — ping OK
|
|
142
135
|
❌ CodeGraph — timeout 10s
|
|
143
136
|
✅ Engram — disponible
|
|
144
|
-
✅ Context7 — disponible
|
|
145
137
|
|
|
146
138
|
¿Continuar con lectura manual de archivos?
|
|
147
139
|
```
|
|
@@ -154,7 +146,6 @@ Herramientas disponibles:
|
|
|
154
146
|
❌ Controller — no responde
|
|
155
147
|
❌ CodeGraph — no instalado
|
|
156
148
|
❌ Engram — timeout 5s
|
|
157
|
-
✅ Context7 — disponible (pero sin docs relevantes)
|
|
158
149
|
|
|
159
150
|
Modo básico: sin validación de edits, sin memoria persistente, sin análisis estructural.
|
|
160
151
|
¿Continuar o cancelar?
|