ostacky 0.10.0 → 0.10.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 +15 -22
- package/assets/agents/ostacky.md +10 -9
- package/assets/commands/install-stack.md +1 -1
- package/assets/docs/ostacky-reference.md +41 -6
- package/assets/mcp/ostacky-controller/index.js +183 -31
- package/assets/plugins/ostacky-controller/index.ts +362 -45
- package/assets/skills/brainstorming/SKILL.md +2 -2
- package/assets/skills/execution-mode-evaluation/SKILL.md +11 -12
- package/assets/skills/openspec-propose/SKILL.md +2 -2
- package/assets/skills/tdd/SKILL.md +1 -1
- package/dist/cli.js +83 -72
- package/manifest.json +32 -32
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@ Ostacky es un **agent harness** para [OpenCode](https://opencode.ai): el orquest
|
|
|
9
9
|
| [Superpowers](https://github.com/obra/superpowers) | Ejecución | CÓMO se implementa, prueba y revisa |
|
|
10
10
|
| [Engram](https://github.com/Gentleman-Programming/engram) | Memoria persistente | QUÉ aprendimos en sesiones anteriores |
|
|
11
11
|
|
|
12
|
-
Ostacky las rutea según el **nivel de impacto del cambio
|
|
12
|
+
Ostacky las rutea según el **nivel de impacto del cambio** y **te pregunta antes de actuar**:
|
|
13
13
|
|
|
14
14
|
| Nivel | Cuándo aplica | Flujo |
|
|
15
15
|
| ------- | ---------------------------------------- | ---------------------------------------------------------------------- |
|
|
@@ -17,12 +17,12 @@ Ostacky las rutea según el **nivel de impacto del cambio**, preguntándote ante
|
|
|
17
17
|
| **0+1** | 5-10 líneas, 1-2 archivos, sin API nueva | CodeGraph → vos elegís: spec o directo |
|
|
18
18
|
| **1+** | >10 líneas, API pública, refactors | CodeGraph → OpenSpec → execution-mode-evaluation → subagentes o inline |
|
|
19
19
|
|
|
20
|
-
Antes de ejecutar
|
|
20
|
+
Antes de ejecutar te muestra qué tasks comparten archivos, así elegís el modo de ejecución con información en mano.
|
|
21
21
|
|
|
22
22
|
## Requisitos
|
|
23
23
|
|
|
24
24
|
- [Node.js](https://nodejs.org/) >= 20 (para `npx`) o [Bun](https://bun.sh/) >= 1.x (para `bunx` o desarrollo)
|
|
25
|
-
- [OpenCode](https://opencode.ai) instalado: `
|
|
25
|
+
- [OpenCode](https://opencode.ai) instalado ([docs](https://opencode.ai/v2/docs)): `bun install -g --trust @opencode/cli` o `npm install -g @opencode/cli` (el `--trust` de Bun habilita el postinstall que elige tu binario nativo)
|
|
26
26
|
- Git recomendado: con git hay aislamiento por worktree; sin git Ostacky instala en el directorio actual con un aviso
|
|
27
27
|
- **WSL:** seguí las instrucciones de **Linux** — WSL corre un kernel Linux real, no uses los comandos de PowerShell aunque estés en Windows
|
|
28
28
|
|
|
@@ -31,7 +31,7 @@ Antes de ejecutar, Ostacky muestra qué tasks tocan los mismos archivos para que
|
|
|
31
31
|
No requiere instalación global ni clonar el repositorio:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
npx ostacky # menú interactivo
|
|
34
|
+
npx ostacky # menú interactivo (te pregunta el scope)
|
|
35
35
|
bunx ostacky # lo mismo con Bun
|
|
36
36
|
```
|
|
37
37
|
|
|
@@ -44,13 +44,11 @@ npx ostacky install --scope local # explícito
|
|
|
44
44
|
|
|
45
45
|
Instala el núcleo (agente, commands, skills, MCPs, plugins) más el stack de herramientas (CodeGraph, Engram) en `<proyecto>/.opencode`, y asegura `.gitignore` con `.opencode/tools/`, `.codegraph/`, `.opencode/cache/` y `ostacky-state.json*`.
|
|
46
46
|
|
|
47
|
-
> Si el log muestra `toolsDir` en tu home (ej. `C:\Users\...\.opencode\tools\codegraph`) y esperabas tu proyecto, es porque corriste el comando fuera de un repo git. Hacé `cd` al proyecto y re-ejecutá.
|
|
48
|
-
|
|
49
47
|
### Global (opt-in)
|
|
50
48
|
|
|
51
49
|
```bash
|
|
52
50
|
npx ostacky --scope global # menú interactivo global
|
|
53
|
-
npx ostacky install --scope global #
|
|
51
|
+
npx ostacky install --scope global # el mismo núcleo, sin el stack
|
|
54
52
|
```
|
|
55
53
|
|
|
56
54
|
Escribe el núcleo en el config dir global de OpenCode, sin tocar ningún proyecto:
|
|
@@ -81,8 +79,6 @@ Con `--scope global` el stack (CodeGraph, Engram) **se omite** — se instala po
|
|
|
81
79
|
|
|
82
80
|
> Por defecto la web corre en `http://127.0.0.1:49374` solo en localhost. Docs: https://opencode.ai/v2/docs/cli/web
|
|
83
81
|
|
|
84
|
-
Si algo del stack falló durante la instalación, regeneralo sin salir de la sesión: seleccioná `ostacky` y ejecutá `/install-stack` en el chat.
|
|
85
|
-
|
|
86
82
|
## Uso diario
|
|
87
83
|
|
|
88
84
|
```bash
|
|
@@ -102,7 +98,7 @@ npx ostacky uninstall-stack # limpia config del stack del pro
|
|
|
102
98
|
npx ostacky --version | npx ostacky --help
|
|
103
99
|
```
|
|
104
100
|
|
|
105
|
-
**Safe-delete:** solo borra lo trackeado en `ostacky-lock.json` — nunca toca componentes tuyos. Muestra preview con `Scope: <ruta>` y pide confirmación. Los plugins Ostacky
|
|
101
|
+
**Safe-delete:** solo borra lo trackeado en `ostacky-lock.json` — nunca toca componentes tuyos. Muestra preview con `Scope: <ruta>` y pide confirmación. Los plugins que instaló Ostacky no están en el lockfile: se limpian por allowlist; los tuyos no se tocan.
|
|
106
102
|
|
|
107
103
|
## Qué se instala
|
|
108
104
|
|
|
@@ -129,20 +125,20 @@ Local (`<proyecto>/.opencode`) o global (mismo árbol bajo el dir global, sin st
|
|
|
129
125
|
└── ostacky-lock.json ← versiones instaladas (agents, commands, skills, mcpServers)
|
|
130
126
|
```
|
|
131
127
|
|
|
132
|
-
`plugins/` y `tools/` **no** se trackean en el lockfile
|
|
128
|
+
`plugins/` y `tools/` **no** se trackean en el lockfile. Instalaciones viejas con archivos legacy sueltos (`ostacky-plugin.ts`, `ostacky-guard.ts`, `ostacky-controller.ts`) se limpian automáticamente.
|
|
133
129
|
|
|
134
130
|
```json
|
|
135
131
|
{
|
|
136
|
-
"version": "0.10.
|
|
137
|
-
"tag": "v0.10.
|
|
138
|
-
"agents": { "ostacky": { "version": "0.10.
|
|
132
|
+
"version": "0.10.2",
|
|
133
|
+
"tag": "v0.10.2",
|
|
134
|
+
"agents": { "ostacky": { "version": "0.10.2", "sha256": "…" } },
|
|
139
135
|
"commands": { "install-stack": { … }, "opsx-sync": { … } },
|
|
140
136
|
"skills": { "brainstorming": { … }, "…" : {} },
|
|
141
137
|
"mcpServers": { "ostacky-controller": { … }, "openspec": { … } }
|
|
142
138
|
}
|
|
143
139
|
```
|
|
144
140
|
|
|
145
|
-
Versionado con checksums: sumá `ostacky-lock.json` a git para que el equipo instale exactamente las mismas versiones
|
|
141
|
+
Versionado con checksums: sumá `ostacky-lock.json` a git para que el equipo instale exactamente las mismas versiones (mismo tag y mismos checksums).
|
|
146
142
|
|
|
147
143
|
## Comandos útiles
|
|
148
144
|
|
|
@@ -159,22 +155,19 @@ Engram y CodeGraph viven en `.opencode/tools/<herramienta>/bin/` y se exponen co
|
|
|
159
155
|
|
|
160
156
|
## Troubleshooting
|
|
161
157
|
|
|
162
|
-
- **Instalé fuera del proyecto / sin git:**
|
|
158
|
+
- **Instalé fuera del proyecto / sin git:** el log muestra `projectRoot` y `toolsDir` explícitos; si `toolsDir` apunta a tu home (ej. `C:\Users\...\.opencode\tools\codegraph`) y esperabas tu proyecto, corriste el comando fuera de un repo git. Hacé `cd` al proyecto y re-ejecutá.
|
|
163
159
|
- **El install global creó `.opencode/` local:** actualizá (`npx ostacky@latest`) y reinstalá — el menú interactivo ya propaga el scope y el stack se omite en global.
|
|
164
160
|
- **Windows `cmd.exe ... codegraph.cmd init -i` durante el install:** warning no fatal — el binario quedó, solo falta el índice. Reintentá con `npx ostacky install-stack --scope local` o corré `.opencode\tools\codegraph\bin\codegraph.exe init -i` dentro del proyecto.
|
|
165
|
-
- **¿Errores en el stack?**
|
|
161
|
+
- **¿Errores en el stack?** Elegí el agente `ostacky` y ejecutá `/install-stack` en el chat: regenera el stack sin salir de la sesión.
|
|
166
162
|
|
|
167
163
|
## Seguridad
|
|
168
164
|
|
|
169
165
|
- `opencode.jsonc` puede versionarse para compartir permisos y MCP de forma reproducible.
|
|
170
|
-
- Descargas por tags de GitHub
|
|
166
|
+
- Descargas por tags de GitHub (nunca `main`), validación anti path-traversal y checksums SHA-256 del manifest.
|
|
167
|
+
- Cache local en `.opencode/cache/<repo>/<tag>/<ruta>` con validación de integridad: si el hash cacheado coincide, no hay petición de red.
|
|
171
168
|
- Lectura/escritura de `*.env` y `.secret/**` bloqueadas con `deny` (la sesión sigue por `experimental.continue_loop_on_deny`).
|
|
172
169
|
- Patrones sensibles configurables: `OSTACKY_SENSITIVE_PATTERNS="**/.env*,**/.secrets/**" bunx ostacky doctor` (allowlist: `.env.example/.template/.sample`). Fuente única en `src/security.ts`; verificá con `npx ostacky doctor`.
|
|
173
170
|
|
|
174
|
-
## Cache
|
|
175
|
-
|
|
176
|
-
Descargas en `.opencode/cache/<repo>/<tag>/<ruta>`. Si el archivo cacheado tiene el hash correcto, no hay petición de red.
|
|
177
|
-
|
|
178
171
|
## Licencia
|
|
179
172
|
|
|
180
173
|
MIT
|
package/assets/agents/ostacky.md
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Orquestador principal — rutea por nivel, orquesta CodeGraph + OpenSpec + Superpowers.
|
|
3
3
|
mode: primary
|
|
4
|
-
version: 0.10.
|
|
4
|
+
version: 0.10.2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Sos **Ostacky v0.10.
|
|
7
|
+
Sos **Ostacky v0.10.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.10.
|
|
9
|
+
> **Versión:** `0.10.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.10.2"** (o `v0.10.2` si te piden solo el número). No inventes otra versión.
|
|
10
10
|
|
|
11
11
|
## Reglas innegociables
|
|
12
12
|
|
|
13
13
|
1. **NUNCA te congeles.** Plan B antes de tool, no reintentes fallida.
|
|
14
|
-
2. **CodeGraph primero
|
|
14
|
+
2. **CodeGraph primero ante query de símbolo/flujo/impacto** (¿quién llama a X?, blast radius, dónde vive un símbolo). Grep/glob directo es legítimo ante query de literal (string exacto, TODO, config, `.md`/`.json`) — pero el gate SIEMPRE exige un `codegraph_codegraph_explore` completado antes de leer código (`shouldBlockCodeRead`). Para leer código no-indexable a conciencia, el explore previo es calibración, no sobrehead: barato, local y confirma que el índice está vivo.
|
|
15
15
|
3. **El plugin hace cumplir PENDING.** Hard gate en `ctx.tool.hook("execute.before")`; no llames `check_*` manual.
|
|
16
16
|
4. **No edites sin Read fresco.** Nunca cache de turno anterior.
|
|
17
17
|
5. **Una pregunta por turno.** Natural, sin tool, STOP y esperar. Respuesta vinculante.
|
|
@@ -45,7 +45,7 @@ Sos **Ostacky v0.10.0**, orquestás, no implementás. Interpretás, clasificás
|
|
|
45
45
|
|
|
46
46
|
**CodeGraph:** `codegraph_codegraph_explore` antes de búsqueda manual. Si ya llamaste para área, reusar. Timeout 10s → Engram → Read.
|
|
47
47
|
|
|
48
|
-
**Discovery
|
|
48
|
+
**Discovery:** `codegraph_explore` + `mem_search`. Si ya llamaste para el área en este request, reusar ese output. No hay cache de archivo.
|
|
49
49
|
|
|
50
50
|
**Engram:** `mem_context` inicio, `mem_search` antes de decidir, `mem_save` tras gate.
|
|
51
51
|
|
|
@@ -59,7 +59,7 @@ Si vago → preguntar. Si claro → `start_request`.
|
|
|
59
59
|
|
|
60
60
|
1. `engram_mem_context` (lazy si `isTrivial && DONE` solo pointer)
|
|
61
61
|
2. Change activo → `proposal.md`/`design.md`/`tasks.md`
|
|
62
|
-
3. `
|
|
62
|
+
3. `codegraph_explore` + `mem_search`; reusar si ya lo hiciste para el área en este request
|
|
63
63
|
4. `codegraph_impact` solo si no cubierto
|
|
64
64
|
5. `Read` solo lo no cubierto
|
|
65
65
|
|
|
@@ -79,14 +79,14 @@ Router `brainstorming`↔`OpenSpec` por `level`/`estLines`/`fileCount`/`hasAPI`
|
|
|
79
79
|
|
|
80
80
|
**SHALL sin ambigüedad (spec iterativo + sync proactiva):**
|
|
81
81
|
|
|
82
|
-
- Antes de crear/editar `openspec/changes/<id>/{proposal.md,design.md,tasks.md}` **O** `docs/superpowers/specs/*.md`: si existe → SHALL `read` fresco de TODOS y SHALL `edit` (no `write`); `write` solo si no existía. Para `open-explore` sin archivo → SHALL `mem_save topic_key:brainstorm/<hash>` por iteración.
|
|
82
|
+
- Antes de crear/editar `openspec/changes/<id>/{proposal.md,design.md,tasks.md}` **O** `docs/superpowers/specs/*.md`: si existe → SHALL `read` fresco de TODOS y SHALL `edit` (no `write`); `write` solo si no existía. Para `open-explore` sin archivo → SHALL `mem_save topic_key:brainstorm/<hash>` por iteración. El discovery no aplica a specs/docs.
|
|
83
83
|
- Al final de cada turno de brainstorming/spec con decisiones nuevas no reflejadas en disco: SHALL listar cálido `Noté que lo que acordamos (X por Z) aún no está en <archivo>: 1) ...` (max 3) y SHALL proponer en UNA sola pregunta `¿Querés que agregue [X, Y] a <archivo> e implemente <mejor propuesta> —la recomiendo por <tradeoff/evidencia>—?` (respetando Regla 5). Si no hay delta, no proponer. Eximido si `isTrivial`.
|
|
84
84
|
|
|
85
85
|
### 4. Execution
|
|
86
86
|
|
|
87
87
|
1. `skill(execution-mode-evaluation)` en memoria, reusa discovery.
|
|
88
88
|
2. Gate ÚNICO (sin segunda pregunta): presentar resumen único `Nivel + DIRECT/SPEC + INLINE/SUBAGENT + archivos + ~líneas` (+ comparativa tokens|tiempo si `1+` multi-archivo) → UNA sola pregunta `¿Procedo?` (el usuario puede modificar). Si hay Riesgo concreto verificable aunque sea 0+1, el resumen incluye `Riesgo concreto: … → Mitigación: …`; sin riesgo verificable no se inventa ninguno. Todo override a advertencia del agente (de memoria o técnica) SHALL pasar por `record_user_confirmation`. Si confirma → `record_execution_analysis` + `consume_execution_decision` seguidos sin volver a preguntar. `Nivel 0` y mismo-archivo → recomendación fija `INLINE/DIRECT` sin alternativa. `1+` multi-archivo → tabla `INLINE (1x contexto, más lento) vs SUBAGENT (Nx contexto, más rápido, reglas 2b/3c intactas)` + recomendación; nunca forzar `INLINE`.
|
|
89
|
-
3. Por task: `Read` fresco → plugin valida edición in-process → `edit` → `
|
|
89
|
+
3. Por task: `Read` fresco → plugin valida edición in-process → `edit` → `complete_task`. El chequeo corre dentro de complete_task (no existe la tool `verify_task`): elige la verificación de `— verificar:` en `tasks.md` y devuelve el motivo si falla. **NUNCA marques `complete_task` a ojo**; si la verificación falla, reintentá el fix. Vale para SPEC y DIRECT, INLINE y SUBAGENTS.
|
|
90
90
|
|
|
91
91
|
### 5. Sync y cierre
|
|
92
92
|
|
|
@@ -97,7 +97,8 @@ Router `brainstorming`↔`OpenSpec` por `level`/`estLines`/`fileCount`/`hasAPI`
|
|
|
97
97
|
## Guardrails
|
|
98
98
|
|
|
99
99
|
- Decisión en OpenSpec/CodeGraph/controller → no re-resolver
|
|
100
|
+
- **Multi-sesión (un state file por proyecto):** si `start_request` devuelve `conflict:true` o un tool devuelve `BLOCKED: … pertenece a otra sesión`, NO re-presentes el resumen de ejecución ni consumas/bloquees esa decisión. Preguntá una sola cosa: takeover explícito (`start_request({force:true})`, auditado) o continuar en la otra sesión. Si `get_state` muestra `callerSessionId:null` con `ownerSessionId` no nulo, tratá la request como ajena (no hay identidad que pruebe lo contrario).
|
|
100
101
|
- Una pregunta por turno, sin deadlock
|
|
101
102
|
- Fase gate: en EXECUTING/SYNC no volver a DISCOVERY
|
|
102
103
|
- Audit: log antes de gate + `mem_save` solo en gates
|
|
103
|
-
- **Tasks son verificables, no instruccionales (genérico):** `tasks.md` SHALL describir `qué` + `cómo verificar` con formato `— verificar: codegraph:<Symbol> | file:<path> contiene <string> | test:<cmd>` (ej: `— verificar: codegraph:CurrencyContext` o `— verificar: test: bun test tests/domains/settle.test.ts`). El controller parsea `taskVerifications` y `
|
|
104
|
+
- **Tasks son verificables, no instruccionales (genérico):** `tasks.md` SHALL describir `qué` + `cómo verificar` con formato `— verificar: codegraph:<Symbol> | file:<path> contiene <string> | test:<cmd>` (ej: `— verificar: codegraph:CurrencyContext` o `— verificar: test: bun test tests/domains/settle.test.ts`). El controller parsea `taskVerifications` al registrar el análisis de ejecución. `file:<path> contiene <str>` exige el string en el archivo; `codegraph:<Symbol>` exige que el símbolo aparezca en el archivo (proxy textual, NO consulta al grafo); `test:<cmd>` exige evidencia: el agente corre el test, el plugin registra cada `shell` con su `exit` real, y `complete_task` sólo acepta una corrida con el comando exacto, `exit 0` y posterior a la última edición (sin evidencia, falla). `complete_task` corre el chequeo y sólo marca COMPLETED si pasa. Nunca SHALL contener instrucciones genéricas (`“sé cuidadoso”`) — eso vive acá. Para `Level 0` trivial, tasks SHALL ser de 1 línea sin overhead.
|
|
@@ -6,7 +6,7 @@ subagent: false
|
|
|
6
6
|
|
|
7
7
|
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.
|
|
8
8
|
|
|
9
|
-
**Nota:** A partir de v0.10.
|
|
9
|
+
**Nota:** A partir de v0.10.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.
|
|
10
10
|
|
|
11
11
|
**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.
|
|
12
12
|
|
|
@@ -27,12 +27,11 @@ BLOCKED: replan→INTERPRETATION_PENDING, abandon→DONE
|
|
|
27
27
|
| controller_* | 5s | 1 | degraded |
|
|
28
28
|
| engram_* | 5s | 1 | sin memoria |
|
|
29
29
|
|
|
30
|
-
##
|
|
31
|
-
|
|
32
|
-
- `src/cache-codegraph.ts`: `.opencode/cache/codegraph/<sha256(query)>.json` con `{ts, result, gitHead, gitDiffHash}`, TTL 1h, `OSTACKY_CACHE_DISABLE=1` bypass, LRU 50MB, invalidación `git diff --name-only` + `git status --porcelain --untracked-files=all` (hash combinado).
|
|
33
|
-
- `src/discovery-cache.ts`: `.opencode/cache/codegraph/discovery-<sha256>.json` con `{codegraph, engramHits, gitDiffHash, gitHead, ts, query}`, mismo TTL/LRU. `getDiscoverySnapshot` → hit reusar sin llamar tools; miss → SHALL `putDiscoverySnapshot` antes de `record_discovery` (auditable `WARN:cache_miss_without_put`).
|
|
34
|
-
- `record_cache_hit/miss` internos: `cache-codegraph.ts` hace write directo a `ostacky-state.json` incrementando `cacheHitCount/tokenSavingEstimate` sin tool LLM.
|
|
30
|
+
## Discovery
|
|
35
31
|
|
|
32
|
+
- Sin cache de archivo: discovery = `codegraph_explore` + `mem_search`; el reuso es del output ya presente en el contexto del request. `src/discovery-cache.ts` y `src/cache-codegraph.ts` se retiraron (change `remove-discovery-cache-phantom`).
|
|
33
|
+
- `OSTACKY_CACHE_DISABLE` ya no existe: no hay cache filesystem que desactivar.
|
|
34
|
+
- Los contadores `cacheHitCount`/`tokenSavingEstimate` quedan en `get_metrics` por compatibilidad, en 0: nada los incrementa.
|
|
36
35
|
## Metrics (get_metrics)
|
|
37
36
|
|
|
38
37
|
`revision, state, degraded, taskCounts{completed,pending,total,expected}, expectedTaskCount, auditSize, stateFileSize, diskFreeMB, uptimeMs, stateOversizedCount, codegraphBypassCount, degradedEditsCount, cacheHitCount, cacheMissCount, tokenSavingEstimate, sensitiveAccess, subagentFailedCount, discoveryCacheHitCount, redundantCallCount, cacheMissWithoutPutCount, stateCheckCount, toolCallCount`
|
|
@@ -56,6 +55,34 @@ Tras refino post-complete (archivo ya correcto, sin edición pendiente): `refres
|
|
|
56
55
|
|
|
57
56
|
El plugin hace cumplir `PENDING` en `ctx.tool.hook("execute.before")`; `lastCheck={revision, result}` cachea ALLOW por revisión, revalida si cambia o >5 tools; `BLOCKED` nunca cacheado. Métricas `stateCheckCount` cuentan checks del plugin (no del LLM).
|
|
58
57
|
|
|
58
|
+
## Gate de CodeGraph (alcance real)
|
|
59
|
+
|
|
60
|
+
Cubre `read`/`grep`/`glob`/`read_mcp_resource` y **`shell`** cuando el comando revela contenido (`cat`, `head`, `tail`, `sed` sin `-i`, `grep`, `rg`, `awk`, `diff`…). Predicado puro: `shellReadTargets(command)` devuelve los paths de código **revelados**, no los mencionados — `bun test x.ts`, `tsc src/x.ts` y `git diff` pasan.
|
|
61
|
+
|
|
62
|
+
**Fail-open:** redirección a archivo (`>`/`>>` a path), `sed -i` y verbo fuera de la allowlist → se permite. `read` falla cerrado porque es inequívoco; `shell` no, y un falso positivo rompe tests/builds sin escape hatch. Los redirects de stderr (`2>&1`, `1>&2`, `2>/dev/null`) NO cuentan como escritura (mismo criterio que `isShellMutation`): `cat src/x.ts 2>&1` sigue gateado.
|
|
63
|
+
|
|
64
|
+
**Exenciones `isShellPathExempt(p, directory, freshState)`:** paths FUERA del projectRoot (fixtures temporales, reportes generados — `cat /tmp/out.ts` nunca bloquea), specs/docs (openspec, `assets/docs`, `.md`, `.json`) y archivos ya trackeados en tasks/fileFingerprints/lastValidated.
|
|
65
|
+
|
|
66
|
+
**No es un sandbox.** Bypass residual por diseño: `git show`, `python -c`, `node -e`, `find -exec`, `xargs`, `base64`. El objetivo es quitar el bypass casual (`cat src/x.ts`, incluida su variante `cat src/x.ts 2>&1`), no probar imposibilidad.
|
|
67
|
+
|
|
68
|
+
`execute` (Code Mode) **no** se gatea: su catálogo no expone `read`/`grep`/`shell` ni filesystem. Si una versión futura lo expone, el gate debe extenderse.
|
|
69
|
+
|
|
70
|
+
**Evidencia válida de discovery:** únicamente un `codegraph_codegraph_explore` COMPLETADO en esta sesión (`discoveryHitByRequest`, memo limpiado con `session.deleted`). No hay fallback a cache en disco (el legado `getDiscoveryCacheHit` se retiró con discovery-cache).
|
|
71
|
+
|
|
72
|
+
## Evidencia de ejecución (`test:`)
|
|
73
|
+
|
|
74
|
+
`test:<cmd>` no se puede verificar sin ejecutar. El plugin observa cada `shell` pero **sólo persiste** `{cmd, exit, ts}` cuando el comando matchea un `test:` declarado en `taskVerifications` (D10: `git`/`ls`/`builds` no son evidencia; cada persist cuesta lock + re-read + write + backups). `complete_task` exige comando exacto (trim), `exit 0` y `ts` posterior a `lastMutationTs` (que avanza en cada `edit`/`write`/`patch` completado y en cada `shell` que escribe con exit 0: `cp`, `mv`, `rm`, `sed -i`, `tee`, redirección). `verifyIntegrity` re-verifica en el cierre: una edición posterior vence la evidencia y bloquea.
|
|
75
|
+
|
|
76
|
+
**Fail-closed en orden de operaciones:** si el test corre antes de `record_execution_analysis` (que carga `taskVerifications` en el state), el plugin no lo registra como evidencia → `complete_task` pide re-correr con razón explícita. El orden correcto es analysis → tests → complete.
|
|
77
|
+
|
|
78
|
+
**No se usa `status`:** en OpenCode 2.0.32, `sh -c 'exit 3'` llega con `status: "completed"` y `result.metadata.status: "completed"`. El único campo veraz es `result.metadata.exit`.
|
|
79
|
+
|
|
80
|
+
**Límites declarados:** un test débil pasa (semántica, no mecánica); sin el plugin no hay `shellRuns` y `test:` falla cerrado.
|
|
81
|
+
|
|
82
|
+
## Force gate (human confirmation, D4)
|
|
83
|
+
|
|
84
|
+
`implementation_complete({force:true})` exige una frase del USUARIO (`/forzar|confirmo|force/i`) en `lastUserPrompts` — no en el audit, que redacta el agente. El plugin registra cada prompt con `{text, ts}` antes de inyectar hints. Cada rechazo del gate setea `lastForceAttemptTs`: sólo cuenta una frase con `ts` POSTERIOR al último intento (un "¿qué hace force:true?" previo no habilita). Prompts legacy sin `ts` (formato viejo en disco) pasan sólo si nunca hubo intento registrado.
|
|
85
|
+
|
|
59
86
|
## Tiered Behaviour
|
|
60
87
|
|
|
61
88
|
`isTrivial(msg,state) = state==DONE && msg.trim().length<30 && /^(hola|hey|gracias|buenas|hi|hello)\b/i.test(msg) && !/(necesito|quiero|agregá|fix|bug|feature|auth|spec|implementar)/i.test(msg)`
|
|
@@ -86,4 +113,12 @@ Principio: **eficacia > recorte** — si recorte rompiera caché y saliera más
|
|
|
86
113
|
|
|
87
114
|
## Propose Flow (1+)
|
|
88
115
|
|
|
89
|
-
`openspec-propose` SHALL Paso 0: `
|
|
116
|
+
`openspec-propose` SHALL Paso 0: `codegraph_codegraph_explore` + `engram_mem_search` sobre el área (si no se hicieron ya en el request) **antes** de `openspec new`. Citá símbolos existentes en `proposal/design`; sin esto dispara `WARN:codegraphBypass` y `design.md` alucina API. Ver `assets/skills/openspec-propose/SKILL.md: Paso 0` y `brainstorming` (router por nivel: `brainstorming` decide 0/0+1/1+, `openspec-explore` es stance sin nivel).
|
|
117
|
+
|
|
118
|
+
## CI — openspec validate (remediación)
|
|
119
|
+
|
|
120
|
+
El job `test` de `.github/workflows/ci.yml` corre `bunx openspec validate --all --strict` (dep pinneada en `package.json`). Si falla en `main`: un delta/spec inválido entró — NO archivearlo roto ni hacer workaround. Protocolo:
|
|
121
|
+
1. El output lista el item roto (`✗ change/<id>` / `✗ spec/<name>`) + `Details: openspec validate <id> --type change|spec` — ese comando da la causa exacta y los next steps (el CLI es autoexplicativo: headers `## ADDED/MODIFIED/REMOVED/RENAMED Requirements`, cada requirement con al menos un `#### Scenario:`).
|
|
122
|
+
2. Debug de deltas parseados: `openspec show <id> --json --deltas-only`.
|
|
123
|
+
3. Change WIP incompleto en `main` → completarlo o removerlo del repo; specs de `openspec/specs/` rotos → fixear el formato in-place.
|
|
124
|
+
4. Si tocás `assets/` regenerá hashes (`bun run scripts/update-manifest-hashes.ts`) y usá `bun run test:safe` (nunca `bun test` full: se cuelga).
|