oficina-opencode 3.0.4 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +240 -208
- package/dist/cli.js +124 -26
- package/dist/cli.js.map +1 -1
- package/dist/core/bus.js +3 -3
- package/dist/core/bus.js.map +1 -1
- package/dist/core/catalog.d.ts +9 -1
- package/dist/core/catalog.d.ts.map +1 -1
- package/dist/core/catalog.js +77 -2
- package/dist/core/catalog.js.map +1 -1
- package/dist/core/dispatch.d.ts +1 -1
- package/dist/core/dispatch.d.ts.map +1 -1
- package/dist/core/dispatch.js +73 -12
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/docsync.d.ts +0 -9
- package/dist/core/docsync.d.ts.map +1 -1
- package/dist/core/docsync.js +12 -15
- package/dist/core/docsync.js.map +1 -1
- package/dist/core/factory.d.ts +16 -0
- package/dist/core/factory.d.ts.map +1 -1
- package/dist/core/factory.js +143 -0
- package/dist/core/factory.js.map +1 -1
- package/dist/core/fsx.d.ts +20 -2
- package/dist/core/fsx.d.ts.map +1 -1
- package/dist/core/fsx.js +10 -6
- package/dist/core/fsx.js.map +1 -1
- package/dist/core/gates.d.ts +23 -1
- package/dist/core/gates.d.ts.map +1 -1
- package/dist/core/gates.js +83 -8
- package/dist/core/gates.js.map +1 -1
- package/dist/core/leases.d.ts.map +1 -1
- package/dist/core/leases.js +4 -1
- package/dist/core/leases.js.map +1 -1
- package/dist/core/mesa.d.ts +1 -6
- package/dist/core/mesa.d.ts.map +1 -1
- package/dist/core/mesa.js +1 -6
- package/dist/core/mesa.js.map +1 -1
- package/dist/core/office.d.ts +3 -29
- package/dist/core/office.d.ts.map +1 -1
- package/dist/core/office.js +77 -90
- package/dist/core/office.js.map +1 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +6 -1
- package/dist/core/paths.js.map +1 -1
- package/dist/core/retry.d.ts +2 -8
- package/dist/core/retry.d.ts.map +1 -1
- package/dist/core/retry.js +3 -34
- package/dist/core/retry.js.map +1 -1
- package/dist/core/roster.js +3 -3
- package/dist/core/roster.js.map +1 -1
- package/dist/core/sandbox.d.ts +38 -1
- package/dist/core/sandbox.d.ts.map +1 -1
- package/dist/core/sandbox.js +119 -15
- package/dist/core/sandbox.js.map +1 -1
- package/dist/core/state.d.ts +2 -2
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +5 -33
- package/dist/core/state.js.map +1 -1
- package/dist/core/stores.d.ts +3 -13
- package/dist/core/stores.d.ts.map +1 -1
- package/dist/core/stores.js +8 -32
- package/dist/core/stores.js.map +1 -1
- package/dist/core/systemPrompt.js +1 -1
- package/dist/core/systemPrompt.js.map +1 -1
- package/dist/core/tripwire.d.ts +22 -8
- package/dist/core/tripwire.d.ts.map +1 -1
- package/dist/core/tripwire.js +71 -26
- package/dist/core/tripwire.js.map +1 -1
- package/dist/core/types.d.ts +6 -14
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +11 -3
- package/dist/core/types.js.map +1 -1
- package/dist/hooks/scopeGuard.d.ts +15 -1
- package/dist/hooks/scopeGuard.d.ts.map +1 -1
- package/dist/hooks/scopeGuard.js +88 -73
- package/dist/hooks/scopeGuard.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -59
- package/dist/tools/index.js.map +1 -1
- package/dist/v1.d.ts.map +1 -1
- package/dist/v1.js +30 -36
- package/dist/v1.js.map +1 -1
- package/dist/v2.d.ts.map +1 -1
- package/dist/v2.js +22 -41
- package/dist/v2.js.map +1 -1
- package/docs/GARANTIAS.md +2 -2
- package/docs/PRUEBA-E2E.md +479 -0
- package/docs/QUE-ES.md +4 -5
- package/docs/SEGURIDAD-REPO.md +83 -0
- package/docs/assets/banner.svg +42 -0
- package/docs/catalog-facts.json +3 -3
- package/docs/superpowers/specs/2026-10-29-factory-skill-creator-and-remove-budget.md +182 -0
- package/package.json +11 -6
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
# Prueba end-to-end de AI-OFFICE
|
|
2
|
+
|
|
3
|
+
Runbook ejecutable. Cada nivel dice **qué hacer**, **qué escribir**, **qué esperás** y
|
|
4
|
+
**cómo lo verificás**.
|
|
5
|
+
|
|
6
|
+
Podés parar en cualquier nivel: cada uno es independiente. El veredicto final sale del
|
|
7
|
+
Nivel 7, que corre un solo comando.
|
|
8
|
+
|
|
9
|
+
**Tiempo total estimado:** 45-70 minutos (la mayor parte es la corrida real, Nivel 3).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Antes de empezar
|
|
14
|
+
|
|
15
|
+
### La regla que más importa
|
|
16
|
+
|
|
17
|
+
> **Abrí OpenCode en `C:\prueba-oficina`.**
|
|
18
|
+
|
|
19
|
+
No en la **carpeta personal del usuario** (p. ej. `%USERPROFILE%`). El motivo es concreto y no es obvio:
|
|
20
|
+
|
|
21
|
+
La carpeta personal **no** es un proyecto (no tiene `package.json` ni `.git`), pero tiene
|
|
22
|
+
**14 subdirectorios que sí lo son**. `resolveProjectRoot` busca en los subdirectorios y,
|
|
23
|
+
como hay varios candidatos, elige por peso de fuentes. El resultado es aleatorio: podés
|
|
24
|
+
terminar escribiendo la corrida en un checkout cualquiera del plugin.
|
|
25
|
+
|
|
26
|
+
Verificá dónde estás antes de abrir OpenCode:
|
|
27
|
+
|
|
28
|
+
```powershell
|
|
29
|
+
cd C:\prueba-oficina
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Variables para las sesiones de PowerShell
|
|
33
|
+
|
|
34
|
+
Copiá esto en la terminal y dejalo abierto:
|
|
35
|
+
|
|
36
|
+
```powershell
|
|
37
|
+
$OFICINA = "$env:USERPROFILE\.config\opencode\node_modules\.bin\oficina.cmd"
|
|
38
|
+
$REPO = "<checkout local del plugin AI-OFFICE>"
|
|
39
|
+
$PROY = "C:\prueba-oficina"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
> `oficina` **no está en el PATH**. Por eso la variable `$OFICINA`. Si lo querés en el
|
|
43
|
+
> PATH: `setx PATH "$env:PATH;$env:USERPROFILE\.config\opencode\node_modules\.bin"`.
|
|
44
|
+
|
|
45
|
+
### Reinstalar el plugin
|
|
46
|
+
|
|
47
|
+
```powershell
|
|
48
|
+
$cfg = "$env:USERPROFILE\.config\opencode"
|
|
49
|
+
Set-Location $cfg
|
|
50
|
+
npm install oficina-opencode@3.0.4 --no-audit --no-fund --prefer-online
|
|
51
|
+
node ".\node_modules\oficina-opencode\dist\cli.js" install --target $cfg --json
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Cerrá OpenCode y volvé a abrirlo.** El plugin se carga al arrancar la sesión: si lo
|
|
55
|
+
reinstalás con OpenCode abierto, la sesión actual sigue con la versión vieja.
|
|
56
|
+
|
|
57
|
+
### El proyecto de prueba ya está armado
|
|
58
|
+
|
|
59
|
+
`C:\prueba-oficina` contiene:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
package.json → "test": "node test/run.js"
|
|
63
|
+
src/ → vacío
|
|
64
|
+
test/run.js → runner que falla si no corrió ningún test
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Por qué el runner y no `node --test` directo:** `node --test` sale con **exit 0**
|
|
68
|
+
aunque no encuentre un solo archivo de test:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
$ node --test "test/**/*.test.js"
|
|
72
|
+
# tests 0
|
|
73
|
+
exit code: 0
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Un gate así está **verde antes de que exista el trabajo**. `test/run.js` corrige eso:
|
|
77
|
+
|
|
78
|
+
| Escenario | Exit |
|
|
79
|
+
|---|---|
|
|
80
|
+
| sin ningún test | **1** (gate rojo) |
|
|
81
|
+
| test que pasa | 0 |
|
|
82
|
+
| test que falla | 1 |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Nivel 0 — Salud del repo (3 min, no necesita OpenCode)
|
|
87
|
+
|
|
88
|
+
```powershell
|
|
89
|
+
Set-Location $REPO
|
|
90
|
+
npm run typecheck
|
|
91
|
+
npm test
|
|
92
|
+
npm run build
|
|
93
|
+
npm run docs:check
|
|
94
|
+
npm run bench:selection
|
|
95
|
+
npm pack --dry-run
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
| Comando | Esperado |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `typecheck` | 0 errores |
|
|
101
|
+
| `test` | `Test Files 26 passed (26)` · `Tests 419 passed (419)` |
|
|
102
|
+
| `build` | sin errores |
|
|
103
|
+
| `docs:check` | `README.md: al dia` · `docs/QUE-ES.md: al dia` |
|
|
104
|
+
| `bench:selection` | `completo 71%` y le gana a `keywords 48%` y `solo-nombre 52%` |
|
|
105
|
+
| `pack --dry-run` | 173 archivos, ~328 KB |
|
|
106
|
+
|
|
107
|
+
> **El `docs:check` es una trampa real.** Si bumpeás la versión y no corrés
|
|
108
|
+
> `npm run docs:sync`, falla. Es el mecanismo de doc autogenerada funcionando.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Nivel 1 — ¿Cargó el plugin? (2 min)
|
|
113
|
+
|
|
114
|
+
Abrí OpenCode **en `C:\prueba-oficina`** y escribí:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
Usá la tool `oficina_board` y mostrame el tablero de la oficina.
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
| Respuesta | Significado |
|
|
121
|
+
|---|---|
|
|
122
|
+
| Devuelve un tablero | ✅ el plugin cargó |
|
|
123
|
+
| "No tengo la tool `oficina_board`" | ❌ el plugin no cargó |
|
|
124
|
+
|
|
125
|
+
Verificación en el log:
|
|
126
|
+
|
|
127
|
+
```powershell
|
|
128
|
+
Get-Content "$env:USERPROFILE\.local\share\opencode\log\opencode.log" -Tail 400 |
|
|
129
|
+
Select-String "oficina" | Select-Object -Last 5
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Buscá esta línea:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
INFO oficina:v2: plugin inicializado {"directory":"C:\\prueba-oficina",...,"tools":16}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Si aparece `failed to load plugin target=oficina`, el problema es la versión: OpenCode
|
|
139
|
+
v2 necesita `@opencode/plugin`, no `@opencode-ai/plugin`.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Nivel 2 — El CLI (3 min, en un directorio aparte)
|
|
144
|
+
|
|
145
|
+
```powershell
|
|
146
|
+
$scratch = "C:\scratch-oficina"
|
|
147
|
+
Remove-Item $scratch -Recurse -Force -ErrorAction SilentlyContinue
|
|
148
|
+
mkdir $scratch -Force
|
|
149
|
+
Set-Content "$scratch\package.json" '{ "name": "scratch" }'
|
|
150
|
+
|
|
151
|
+
& $OFICINA init "Prueba del CLI" --directory $scratch
|
|
152
|
+
& $OFICINA status --directory $scratch
|
|
153
|
+
& $OFICINA board --directory $scratch
|
|
154
|
+
& $OFICINA bus --directory $scratch
|
|
155
|
+
& $OFICINA catalog --agency-root "$env:USERPROFILE\agency-agents" | Select-Object -First 10
|
|
156
|
+
& $OFICINA audit T-99 --directory $scratch
|
|
157
|
+
& $OFICINA verify --directory $scratch
|
|
158
|
+
& $OFICINA reset --directory $scratch
|
|
159
|
+
& $OFICINA reset --directory $scratch --force
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
| Comando | Esperado |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `init` | JSON con `"ok": true`, `officeDir`, `projectRoot`, `runId` |
|
|
165
|
+
| `status` | `Estado: planning` · `Presupuesto: 0/20 cards` |
|
|
166
|
+
| `board` | tabla vacía, sin error |
|
|
167
|
+
| `bus` | 4 canales en 0 mensajes |
|
|
168
|
+
| `catalog` | lista los agentes. **Necesita `--agency-root`** (si no, "Falta --agency-root.") |
|
|
169
|
+
| `audit T-99` | sale con error: `No existe la card T-99.` (exit 1) |
|
|
170
|
+
| `verify` | sección de gates vacía, sin error |
|
|
171
|
+
| `reset` | **pide confirmación**: "Re-ejecutá con --force para confirmar." |
|
|
172
|
+
| `reset --force` | borra |
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Nivel 3 — La corrida real (el evento principal)
|
|
177
|
+
|
|
178
|
+
### 3.1 Abrí la sesión
|
|
179
|
+
|
|
180
|
+
```powershell
|
|
181
|
+
cd C:\prueba-oficina
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Abrí OpenCode **ahí**. En una segunda terminal dejá `$OFICINA` y `$PROY` definidos, para
|
|
185
|
+
poder mirar la mesa mientras corre.
|
|
186
|
+
|
|
187
|
+
### 3.2 El objetivo — copiá esto tal cual
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
/oficina Crear un modulo de utilidades de texto en src/texto.js con dos funciones: slugify(texto), que convierte un titulo en un slug (minusculas, sin acentos, con guiones), y contarPalabras(texto), que cuenta las palabras separadas por espacios. Los tests van en test/texto.test.js y la documentacion de la API en docs/API.md.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 3.3 Qué mirar en los primeros 60 segundos
|
|
194
|
+
|
|
195
|
+
**a) El plan.** Tiene que ser un desglose de **3 cards**: implementación, tests,
|
|
196
|
+
documentación. Cada una con criteria de aceptación verificables, scope y gate. Si el
|
|
197
|
+
plan sale con una sola card gigante, no es un error — pero anotá que el plan fue de 1.
|
|
198
|
+
|
|
199
|
+
**b) El rol que eligió el dispatch.** Este es **el chequeo clave**.
|
|
200
|
+
|
|
201
|
+
Mirá la salida del dispatch. El rol tiene que ser coherente con las capabilities de la
|
|
202
|
+
card. Un rol de otro dominio es exactamente el bug que arreglé en 3.0.3 (a una card de
|
|
203
|
+
"utilidades de texto" le tocaba un *ServiceNow Developer Mentor*).
|
|
204
|
+
|
|
205
|
+
Si ves un rol absurdo:
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
/oficina-stop
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
o pedí que frene: `oficina_stop` con `action="halt"`.
|
|
212
|
+
|
|
213
|
+
Un rol **fabricado** (que no viene del catálogo) también es válido — siempre que el
|
|
214
|
+
despacho lo diga explícitamente. Un rol del catálogo con cobertura baja **también**,
|
|
215
|
+
mientras lo diga.
|
|
216
|
+
|
|
217
|
+
### 3.4 Mientras corre — mirá la mesa
|
|
218
|
+
|
|
219
|
+
```powershell
|
|
220
|
+
& $OFICINA board --directory $PROY
|
|
221
|
+
& $OFICINA status --directory $PROY
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Los estados de card posibles: `todo`, `in_progress`, `review`, `done`, `blocked`,
|
|
225
|
+
`escalated`.
|
|
226
|
+
|
|
227
|
+
### 3.5 Cuando termine — el checklist
|
|
228
|
+
|
|
229
|
+
La corrida dejó esto:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
C:\prueba-oficina\.oficina\
|
|
233
|
+
state.json
|
|
234
|
+
roster.json
|
|
235
|
+
cost.json
|
|
236
|
+
artifacts\T-00\handoff.md
|
|
237
|
+
artifacts\T-00\gates.md
|
|
238
|
+
artifacts\T-00\evidence.md
|
|
239
|
+
evidence\T-00.json
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Y los entregables:
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
C:\prueba-oficina\src\texto.js
|
|
246
|
+
C:\prueba-oficina\test\texto.test.js
|
|
247
|
+
C:\prueba-oficina\docs\API.md
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**Los 5 criterios que tiene que cumplir:**
|
|
251
|
+
|
|
252
|
+
| # | Criterio | Cómo lo verificás |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| 1 | `src/texto.js` existe y exporta las dos funciones | `node -e "console.log(Object.keys(require('C:/prueba-oficina/src/texto.js')))"` |
|
|
255
|
+
| 2 | `slugify` saca acentos, pasa a minúsculas y une con guiones | `node -e "const {slugify}=require('C:/prueba-oficina/src/texto.js'); console.log(slugify('Hola Mundo Ávil'))"` → `hola-mundo-avil` |
|
|
256
|
+
| 3 | `contarPalabras` cuenta palabras separadas por espacios | `node -e "const {contarPalabras}=require('C:/prueba-oficina/src/texto.js'); console.log(contarPalabras('uno dos tres'))"` → `3` |
|
|
257
|
+
| 4 | `npm test` corre la suite y sale con exit 0 | `cd C:\prueba-oficina; npm test; echo $LASTEXITCODE` → `0` |
|
|
258
|
+
| 5 | La evidencia incluye la **verificación negativa** | abrir `.oficina\artifacts\T-00\evidence.md` |
|
|
259
|
+
|
|
260
|
+
El punto 5 es el que más dice: la oficina tiene que **romper el código a propósito** y
|
|
261
|
+
comprobar que el test lo detecta. Si la evidencia solo dice "npm test pasó", la card
|
|
262
|
+
cerró sin probar que el test sirva.
|
|
263
|
+
|
|
264
|
+
### 3.6 El veredicto automático
|
|
265
|
+
|
|
266
|
+
```powershell
|
|
267
|
+
Set-Location $REPO
|
|
268
|
+
npx tsx scripts\diagnose-run.ts C:\prueba-oficina
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Esperado: **0 fallas**. Si hay fallas, son invariantes rotos (mirá abajo).
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Nivel 4 — Adversarial (10 min, mismo proyecto)
|
|
276
|
+
|
|
277
|
+
Cada prueba es un mensaje para OpenCode. Todas tienen una respuesta **correcta** clara.
|
|
278
|
+
|
|
279
|
+
### 4.1 El scope se respeta de verdad
|
|
280
|
+
|
|
281
|
+
En la misma sesión (o una nueva abierta en `C:\prueba-oficina`), escribí:
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
Toma la card T-00 con oficina_assign y despues intentá escribir un archivo nuevo README.md en la raiz del proyecto, que esta fuera del scope de la card. Decime exactamente que responde el motor.
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
| Correcto | Incorrecto |
|
|
288
|
+
|---|---|
|
|
289
|
+
| La escritura se **rechaza** con un error de scope | El archivo `README.md` aparece en el proyecto |
|
|
290
|
+
|
|
291
|
+
Verificalo en disco:
|
|
292
|
+
|
|
293
|
+
```powershell
|
|
294
|
+
Test-Path C:\prueba-oficina\README.md # tiene que dar False
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### 4.2 Nadie se auto-aprueba
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
Intentá registrar el review de la card T-00 con tu propio agentId, o sea revisarte a vos mismo. Decime que responde el motor.
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
| Correcto | Incorrecto |
|
|
304
|
+
|---|---|
|
|
305
|
+
| El motor **rechaza**: el owner no puede ser su propio reviewer | El review queda registrado con owner == reviewer |
|
|
306
|
+
|
|
307
|
+
### 4.3 El gate es real (rompé el código)
|
|
308
|
+
|
|
309
|
+
```
|
|
310
|
+
Rompe src/texto.js a proposito, de modo que slugify devuelva siempre la cadena vacia, y corré el gate de esa card. Decime que paso.
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
| Correcto | Incorrecto |
|
|
314
|
+
|---|---|
|
|
315
|
+
| El gate **falla** y la card vuelve a trabajo | El gate pasa en verde |
|
|
316
|
+
|
|
317
|
+
**Restaurá el código después** (o volvé a correr `/oficina` para que la oficina lo arregle).
|
|
318
|
+
|
|
319
|
+
### 4.4 El freno de emergencia
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
Frená la corrida con oficina_stop, y despues reanudala con action resume.
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
| Correcto | Incorrecto |
|
|
326
|
+
|---|---|
|
|
327
|
+
| `state.json` muestra `halt` con motivo, y después queda en `null` | El freno no hace nada |
|
|
328
|
+
|
|
329
|
+
### 4.5 El costo se lleva
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
Mostrame el costo de la corrida con oficina_cost.
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Esperado: el total en USD, las llamadas y los tokens. Con tu modelo (MiniMax M3.1 Flash
|
|
336
|
+
Free) el USD va a ser **$0.0000** — eso es correcto, no un bug. Lo que tiene que estar
|
|
337
|
+
bien es el conteo de llamadas y tokens.
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Nivel 5 — Recuperación (5 min, proyecto aparte)
|
|
342
|
+
|
|
343
|
+
Esta es la prueba de **durabilidad**: que la oficina sobreviva a una muerte.
|
|
344
|
+
|
|
345
|
+
### 5.1 Preparar y arrancar
|
|
346
|
+
|
|
347
|
+
```powershell
|
|
348
|
+
$adv = "C:\prueba-oficina-adv"
|
|
349
|
+
Remove-Item $adv -Recurse -Force -ErrorAction SilentlyContinue
|
|
350
|
+
mkdir "$adv\src" -Force
|
|
351
|
+
mkdir "$adv\test" -Force
|
|
352
|
+
Copy-Item "C:\prueba-oficina\package.json" $adv
|
|
353
|
+
Copy-Item "C:\prueba-oficina\test\run.js" "$adv\test\run.js" -Force
|
|
354
|
+
cd $adv
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Abrí OpenCode en `C:\prueba-oficina-adv` y:
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
/oficina Crear un archivo src/saludo.js que exporte una funcion saludo(nombre) que devuelva "Hola, <nombre>!". Con su test en test/saludo.test.js.
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### 5.2 Matarla en caliente
|
|
364
|
+
|
|
365
|
+
Cuando veas que empezó a trabajar (**mientras la card está `in_progress`**), cerrá la
|
|
366
|
+
ventana de OpenCode de golpe. No dejes que termine.
|
|
367
|
+
|
|
368
|
+
### 5.3 Reanimarla
|
|
369
|
+
|
|
370
|
+
Abrí OpenCode de nuevo **en el mismo directorio** y escribí:
|
|
371
|
+
|
|
372
|
+
```
|
|
373
|
+
Revisá el estado de la oficina y decime si la corrida quedó consistente o hay algo roto.
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
| Correcto | Incorrecto |
|
|
377
|
+
|---|---|
|
|
378
|
+
| La oficina detecta la inconsistencia y la reporta | Dice "todo bien" con una card colgada |
|
|
379
|
+
|
|
380
|
+
Y desde la terminal:
|
|
381
|
+
|
|
382
|
+
```powershell
|
|
383
|
+
& $OFICINA board --directory $adv
|
|
384
|
+
& $OFICINA status --directory $adv
|
|
385
|
+
Set-Location $REPO
|
|
386
|
+
npx tsx scripts\diagnose-run.ts C:\prueba-oficina-adv
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Lo que tiene que aparecer: la card con su estado real, y el diagnóstico reportando
|
|
390
|
+
inconsistencias (por ejemplo, el owner fantasma) en vez de un "todo bien" falso.
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Nivel 6 — Cerrar y limpiar
|
|
395
|
+
|
|
396
|
+
```powershell
|
|
397
|
+
& $OFICINA reset --directory $PROY --force
|
|
398
|
+
& $OFICINA reset --directory $adv --force
|
|
399
|
+
Remove-Item C:\scratch-oficina -Recurse -Force -ErrorAction SilentlyContinue
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Los artefactos de la corrida se borran con `reset`. Si querés conservarlos para
|
|
403
|
+
analizarlos, **no corras `reset` todavía**: el Nivel 7 los necesita.
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Nivel 7 — Veredicto final (1 min)
|
|
408
|
+
|
|
409
|
+
```powershell
|
|
410
|
+
Set-Location $REPO
|
|
411
|
+
npx tsx scripts\diagnose-run.ts C:\prueba-oficina
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Salida con exit code **0** = todos los invariantes se sostienen. Exit 1 = hay al menos
|
|
415
|
+
uno roto.
|
|
416
|
+
|
|
417
|
+
Los 7 invariantes que verifica:
|
|
418
|
+
|
|
419
|
+
| # | Invariante | Cómo se viola |
|
|
420
|
+
|---|---|---|
|
|
421
|
+
| 1 | Ninguna card cerrada sin gates en PASS | El gate estaba en FAIL pero la card se cerró |
|
|
422
|
+
| 2 | Ninguna card cerrada sin evidencia para **cada** criterio | Falta evidencia para un criterio de aceptación |
|
|
423
|
+
| 3 | Nadie se auto-aprueba | `owner == reviewer` |
|
|
424
|
+
| 4 | Ninguna card sin owner | Cardcolgada sin nadie que la tome |
|
|
425
|
+
| 5 | Todo owner existe en el roster | El agente murió o el roster se perdió |
|
|
426
|
+
| 6 | Presupuesto respetado | Más cards / llamadas / spawns que los permitidos |
|
|
427
|
+
| 7 | Todo gate `NA` explica por qué | Una fase que nadie corrió, sin motivo |
|
|
428
|
+
|
|
429
|
+
Las secciones del diagnóstico:
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
1. ESTADO objetivo, run, presupuesto, freno
|
|
433
|
+
2. CARDS cada card con su scope, gate, acceptance, owner, reviewer
|
|
434
|
+
3. EL EQUIPO qué rol se eligió y si es coherente con la card
|
|
435
|
+
4. ARTEFACTOS gates, handoff, evidencia por card
|
|
436
|
+
5. EL BUS mensajes entre agentes
|
|
437
|
+
6. COSTO USD, llamadas, tokens
|
|
438
|
+
7. RECONCILIACIÓN estado vs artefactos vs filesystem
|
|
439
|
+
8. INVARIANTES ← el veredicto
|
|
440
|
+
9. VEREDICTO
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## Tarjeta de resultados
|
|
446
|
+
|
|
447
|
+
| Nivel | Qué verificaba | Resultado |
|
|
448
|
+
|---|---|---|
|
|
449
|
+
| 0 | Repo sano | ☐ |
|
|
450
|
+
| 1 | El plugin carga | ☐ |
|
|
451
|
+
| 2 | El CLI responde | ☐ |
|
|
452
|
+
| 3 | La corrida real completa | ☐ |
|
|
453
|
+
| 3.5 | Los 5 criterios del entregable | ☐ |
|
|
454
|
+
| 4.1 | El scope bloquea | ☐ |
|
|
455
|
+
| 4.2 | Nadie se auto-aprueba | ☐ |
|
|
456
|
+
| 4.3 | El gate falla si el código está roto | ☐ |
|
|
457
|
+
| 4.4 | El freno funciona | ☐ |
|
|
458
|
+
| 4.5 | El costo se lleva | ☐ |
|
|
459
|
+
| 5 | La oficina sobrevive a una muerte | ☐ |
|
|
460
|
+
| 7 | 0 fallas en los invariantes | ☐ |
|
|
461
|
+
|
|
462
|
+
**Si algo falla**, el lugar exacto para mirar es
|
|
463
|
+
`C:\prueba-oficina\.oficina\artifacts\<card>\gates.md` (la salida real de cada comando)
|
|
464
|
+
y `C:\prueba-oficina\.oficina\evidence\<card>.json` (el grafo de evidencia).
|
|
465
|
+
|
|
466
|
+
---
|
|
467
|
+
|
|
468
|
+
## Lo que NO se testea acá
|
|
469
|
+
|
|
470
|
+
- **La suite automatizada** (419 tests) ya cubre: sandbox, guard de scope, herencia de
|
|
471
|
+
scope en subagentes, concurrencia, atomicidad, evidencia, gates, costo, recovery,
|
|
472
|
+
matcher, dispatch, router, state machine, CLI, docsync.
|
|
473
|
+
Corré `npm test` para eso.
|
|
474
|
+
- **El catálogo de 258 agentes**: `oficina catalog --agency-root ...` los lista, y el
|
|
475
|
+
benchmark mide la calidad del matching (71% hit@1).
|
|
476
|
+
- **La carga bajo OpenCode v1**: el entry `./v1` existe y tiene sus tests, pero tu
|
|
477
|
+
OpenCode es v2. No es una prioridad.
|
|
478
|
+
- **Multi-proyecto / concurrencia real entre corridas**: el motor lo soporta
|
|
479
|
+
(`withLock`, leases), pero probarlo requiere dos sesiones simultáneas.
|
package/docs/QUE-ES.md
CHANGED
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
<!-- BEGIN GENERATED: facts -->
|
|
4
4
|
| | |
|
|
5
5
|
|---|---|
|
|
6
|
-
| **Paquete** | `oficina-opencode` v3.0
|
|
7
|
-
| **Tools** |
|
|
6
|
+
| **Paquete** | `oficina-opencode` v3.1.0 |
|
|
7
|
+
| **Tools** | 15 |
|
|
8
8
|
| **Hooks** | 7 |
|
|
9
9
|
| **API de plugin** | `@opencode/plugin@2.1.2` |
|
|
10
|
-
| **Node** | >=
|
|
10
|
+
| **Node** | >=22 |
|
|
11
11
|
| **Catálogo** | 258 agentes resolubles en 18 divisiones |
|
|
12
12
|
| **Divisiones** | academic, design, engineering, finance, game-development, gis, healthcare, marketing, paid-media, product, project-management, research, sales, spatial-computing, specialized, strategy, support, testing |
|
|
13
|
-
|
|
14
|
-
| **Cobertura mínima** | 60% |
|
|
13
|
+
<!-- Catalog source: agency-agents @ 4e3ac3c -->
|
|
15
14
|
<!-- END GENERATED: facts -->
|
|
16
15
|
|
|
17
16
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Hardening del repo y de npm — cierre a maldades
|
|
2
|
+
|
|
3
|
+
Checklist operativa para que **nadie que no sea el mantenedor** pueda pushear,
|
|
4
|
+
publicar o borrar nada. Divide las medidas en lo que ya vive en el repo
|
|
5
|
+
(aplicado en archivos) y lo que se activa una vez en la web de GitHub y de npm.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Parte A — Ya aplicado en el repo
|
|
10
|
+
|
|
11
|
+
| Medida | Archivo | Qué cierra |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Revisión del owner obligatoria en todo el árbol | `.github/CODEOWNERS` | PRs que tocan código sin el visto bueno del owner |
|
|
14
|
+
| Superficie CI/seguridad/empaquetado con protección explícita | `.github/CODEOWNERS` | Manipulación de workflows, policy de seguridad o manifest |
|
|
15
|
+
| Dependabot semanal (npm + Actions) | `.github/dependabot.yml` | Dependencias y actions que quedan viejas; majors manuales a propósito |
|
|
16
|
+
| Publicación OIDC con provenance, environment protegido, sin token de larga vida | `.github/workflows/publish.yml` | Spoofing de publicación, robo de token, publicar algo que no pasó el suite |
|
|
17
|
+
| Corredor de verificación previa en el publish | `prepublishOnly` + workflow | Publicar typecheck/test/docs en rojo |
|
|
18
|
+
| Política de seguridad sin datos de contacto inventados | `SECURITY.md` | Reportes por canales no verificados |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Parte B — Activar una vez en GitHub (UI del repositorio)
|
|
23
|
+
|
|
24
|
+
Settings → Saltar al punto → clícalo y listo:
|
|
25
|
+
|
|
26
|
+
1. **Branch protection de `main`** (Settings → Branches → Add branch ruleset):
|
|
27
|
+
- ✅ *Require a pull request before merging* (1 revisión mínima).
|
|
28
|
+
- ✅ *Require review from Code Owners* — activa la CODEOWNERS de arriba.
|
|
29
|
+
- ✅ *Require status checks to pass before merging* con estos jobs:
|
|
30
|
+
`verify (ubuntu-latest, 24) · verify (ubuntu-latest, 22) · verify (windows-latest, 24) · verify (windows-latest, 22) · docs · smoke · install-verify`.
|
|
31
|
+
- ✅ *Require branches to be up to date before merging*.
|
|
32
|
+
- ✅ *Do not allow bypassing the above settings* (ni apps ni admins).
|
|
33
|
+
- ❌ **Nunca**: *Allow force pushes* · *Allow deletions*.
|
|
34
|
+
|
|
35
|
+
2. **Ruleset de tags** (Settings → Rules → Rulesets → New → Tag ruleset):
|
|
36
|
+
- Protege `v*`: solo el owner crea tags. Evita que un tag spurio dispare
|
|
37
|
+
publicidad falsa de versiones.
|
|
38
|
+
|
|
39
|
+
3. **Permisos de Actions** (Settings → Actions → General):
|
|
40
|
+
- ⛔ *Read and write permissions* → cambiar a **Read repository contents** por defecto.
|
|
41
|
+
- ✅ Requiere aprobación de colaboradores para workflows de PRs de primera vez.
|
|
42
|
+
- ✅ Alta del *GitHub Actions* no admite escalación: el token ahora no puede
|
|
43
|
+
pushear ni publicar aunque un agente se piratee.
|
|
44
|
+
|
|
45
|
+
4. **Secretos** (Settings → Secrets and variables):
|
|
46
|
+
- No necesitas `NPM_TOKEN` si configuras *Trusted Publishing* (punto C.3).
|
|
47
|
+
- Si igual la almacenas: granular (`oficina-opencode` únicamente), con 2FA
|
|
48
|
+
obligatoria y vencido corto mejor que eterno.
|
|
49
|
+
|
|
50
|
+
5. **Dependabot alerts + security notifications** (Settings → Security):
|
|
51
|
+
- ✅ Dependabot alerts · Code scanning (si se suma CodeQL luego) · Secret scanning.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Parte C — Activar una vez en npm (npmjs.com)
|
|
56
|
+
|
|
57
|
+
1. **2FA en la cuenta** (Account settings → Security): siempre, obligatoria.
|
|
58
|
+
2. **Package settings de `oficina-opencode`**:
|
|
59
|
+
- ✅ *Require two-factor authentication to publish or change settings* (ON — es el default ahora).
|
|
60
|
+
- Mantenedores: **solo el owner**. Cualquier colaboración va por PR, no por copropiedad del paquete.
|
|
61
|
+
3. **Trusted Publishing** (Package settings → Publishing access):
|
|
62
|
+
- Vincula el repo `SOCRAMbt/AI-OFFICE` con el workflow `.github/workflows/publish.yml`.
|
|
63
|
+
- Con esto la publicación usa OIDC: **no existe token que filtrar** y npm
|
|
64
|
+
firma la provenance (SLSA 3) del artefacto.
|
|
65
|
+
4. **Publicar siempre con provenance**:
|
|
66
|
+
```bash
|
|
67
|
+
npm publish --provenance
|
|
68
|
+
```
|
|
69
|
+
El workflow ya lo hace. Instaladores verosificables con
|
|
70
|
+
`npm view oficina-opencode dist.attestations`.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Verificación rápida del cierre
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# ¿Quién puede tocar main? → nadie sin PR del owner (Parte B.1)
|
|
78
|
+
# ¿Quién puede publicar? → solo el workflow OIDC del repo (Parte C.3)
|
|
79
|
+
# ¿Un PR de un extraño tocará CODEOWNERS? → GitHub lo exige en aprobación automática
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Si algo de la Parte B/C no está activado, el cierre técnico queda a medias:
|
|
83
|
+
los archivos del repo son la mitad grosera; los toggles de la web son la otra.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<svg width="1000" height="240" viewBox="0 0 1000 240" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="AI-OFFICE — una oficina de agentes para OpenCode">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="accent" x1="0" y1="0" x2="1000" y2="0" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop offset="0" stop-color="#7c3aed"/>
|
|
5
|
+
<stop offset="0.55" stop-color="#22a06b"/>
|
|
6
|
+
<stop offset="1" stop-color="#f59e0b"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
<linearGradient id="heroText" x1="120" y1="60" x2="880" y2="160" gradientUnits="userSpaceOnUse">
|
|
9
|
+
<stop offset="0" stop-color="#f8fafc"/>
|
|
10
|
+
<stop offset="1" stop-color="#cbd5f5"/>
|
|
11
|
+
</linearGradient>
|
|
12
|
+
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
|
|
13
|
+
<path d="M 40 0 L 0 0 0 40" stroke="#1c2333" stroke-width="1"/>
|
|
14
|
+
</pattern>
|
|
15
|
+
</defs>
|
|
16
|
+
|
|
17
|
+
<rect width="1000" height="240" rx="18" fill="#0b0f19"/>
|
|
18
|
+
<rect width="1000" height="240" rx="18" fill="url(#grid)" opacity="0.55"/>
|
|
19
|
+
<rect x="0.5" y="0.5" width="999" height="239" rx="17.5" stroke="#232b3e"/>
|
|
20
|
+
|
|
21
|
+
<!-- desk motif: a minimal "office" abstract -->
|
|
22
|
+
<g opacity="0.9">
|
|
23
|
+
<rect x="856" y="150" width="7" height="62" rx="3" fill="#22a06b"/>
|
|
24
|
+
<rect x="869" y="132" width="7" height="80" rx="3" fill="#7c3aed"/>
|
|
25
|
+
<rect x="882" y="164" width="7" height="48" rx="3" fill="#f59e0b"/>
|
|
26
|
+
<rect x="808" y="204" width="170" height="8" rx="4" fill="#1c2333"/>
|
|
27
|
+
<circle cx="823" cy="132" r="9" stroke="#3b4664" stroke-width="2"/>
|
|
28
|
+
<rect x="808" y="146" width="30" height="4" rx="2" fill="#2a3350"/>
|
|
29
|
+
</g>
|
|
30
|
+
|
|
31
|
+
<g opacity="0.65">
|
|
32
|
+
<circle cx="92" cy="196" r="3" fill="#7c3aed"/>
|
|
33
|
+
<circle cx="110" cy="196" r="3" fill="#22a06b"/>
|
|
34
|
+
<circle cx="128" cy="196" r="3" fill="#f59e0b"/>
|
|
35
|
+
</g>
|
|
36
|
+
|
|
37
|
+
<text x="72" y="104" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="76" font-weight="800" letter-spacing="4" fill="url(#heroText)">AI-OFFICE</text>
|
|
38
|
+
<rect x="74" y="126" width="212" height="4" rx="2" fill="url(#accent)"/>
|
|
39
|
+
|
|
40
|
+
<text x="74" y="168" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="23" fill="#9aa4b2">Una oficina de agentes para OpenCode donde el trabajo</text>
|
|
41
|
+
<text x="74" y="198" font-family="'Segoe UI', Roboto, Helvetica, Arial, sans-serif" font-size="23" fill="#9aa4b2">no se detiene cuando el modelo dice «terminé».</text>
|
|
42
|
+
</svg>
|
package/docs/catalog-facts.json
CHANGED