ozali 0.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/LICENSE +21 -0
- package/README.md +94 -0
- package/cli/bin/ozali.mjs +77 -0
- package/cli/lib/commands.mjs +235 -0
- package/cli/lib/detect.mjs +103 -0
- package/cli/lib/prompt.mjs +51 -0
- package/cli/lib/util.mjs +131 -0
- package/cli/test/smoke.test.mjs +88 -0
- package/docs/intended-usage.md +43 -0
- package/docs/security.md +47 -0
- package/docs/team-history.md +66 -0
- package/package.json +39 -0
- package/skill/SKILL.md +396 -0
- package/skill/references/agents-blueprint.md +138 -0
- package/skill/references/calibration-blueprint.md +113 -0
- package/skill/references/doc-templates.md +301 -0
- package/skill/references/engram-convention.md +186 -0
- package/skill/references/harness-template.md +214 -0
- package/skill/references/knowledge-blueprint.md +143 -0
- package/skill/references/permissions-bypass.md +232 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Plantillas de documentación
|
|
2
|
+
|
|
3
|
+
Hay **dos** conjuntos de documentación, con propósito y ruta distintos:
|
|
4
|
+
|
|
5
|
+
| Conjunto | Quién lo genera | Cuándo | Ruta |
|
|
6
|
+
|----------|-----------------|--------|------|
|
|
7
|
+
| **Corrida de ozali** | `ozali` | cada corrida de diagnóstico | `.ai/ozali/logs/ozali.log_{{yy-mm-dd}}/` |
|
|
8
|
+
| **Hito de cdk** | `cdk` (`project-documenter`) | cada solicitud/hito del usuario | `.ozali/docs/cdk/<hito>/` |
|
|
9
|
+
|
|
10
|
+
Ambos comparten el mismo **encabezado de identidad**.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## A) Documentación de corrida (ozali)
|
|
15
|
+
|
|
16
|
+
Cada corrida de `ozali` produce **3 documentos** en:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
.ai/ozali/logs/ozali.log_{{yy-mm-dd}}/
|
|
20
|
+
01-analisis.md
|
|
21
|
+
02-plan.md
|
|
22
|
+
03-mejoras.md
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- `{{yy-mm-dd}}` = fecha local de la corrida (ej. `26-06-10`).
|
|
26
|
+
- Si ya existe una carpeta del mismo día, agrega sufijo: `ozali.log_26-06-10-2/`.
|
|
27
|
+
- La **fecha** va en el nombre de la carpeta; la **fecha + hora** va dentro de cada documento.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Encabezado obligatorio (todos los documentos)
|
|
32
|
+
|
|
33
|
+
Va al inicio de cada `.md`. Toma los datos de la **Fase 0** de `ozali` (identidad/git/sesión).
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
---
|
|
37
|
+
ozali.log: {{yy-mm-dd}}
|
|
38
|
+
documento: 01-analisis | 02-plan | 03-mejoras
|
|
39
|
+
Autor: <git user.name> <<git user.email>>
|
|
40
|
+
Sesión: <correo de sesión si está disponible>
|
|
41
|
+
Rama: <branch actual>
|
|
42
|
+
Creado: <yyyy-mm-dd HH:MM:SS> (local)
|
|
43
|
+
---
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 01-analisis.md — Análisis e hitos de importancia
|
|
49
|
+
|
|
50
|
+
```markdown
|
|
51
|
+
# Análisis — <título corto de la solicitud>
|
|
52
|
+
|
|
53
|
+
## Contexto
|
|
54
|
+
<qué se pidió y por qué>
|
|
55
|
+
|
|
56
|
+
## Fuente de verdad usada
|
|
57
|
+
- Variante: AI.md/.ai | IA.md/.ia
|
|
58
|
+
- Discrepancias detectadas vs. estructura real:
|
|
59
|
+
- <lista>
|
|
60
|
+
|
|
61
|
+
## Hitos de importancia
|
|
62
|
+
1. <hito> — <por qué importa> — Riesgo: Alto/Medio/Bajo
|
|
63
|
+
2. ...
|
|
64
|
+
|
|
65
|
+
## Superficie de impacto
|
|
66
|
+
- Archivos/módulos afectados: <lista>
|
|
67
|
+
- Dependencias: <lista>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 02-plan.md — Plan ejecutado
|
|
73
|
+
|
|
74
|
+
```markdown
|
|
75
|
+
# Plan ejecutado — <título corto>
|
|
76
|
+
|
|
77
|
+
## Decisión
|
|
78
|
+
<enfoque elegido y alternativas descartadas>
|
|
79
|
+
|
|
80
|
+
## Tareas (con estado final)
|
|
81
|
+
- [x] <tarea 1>
|
|
82
|
+
- [x] <tarea 2>
|
|
83
|
+
- [ ] <pendiente, si aplica>
|
|
84
|
+
|
|
85
|
+
## Cambios realizados
|
|
86
|
+
- <archivo>: <qué cambió>
|
|
87
|
+
|
|
88
|
+
## Validación
|
|
89
|
+
- Pruebas ejecutadas: <comando / resultado>
|
|
90
|
+
- Criterios de aceptación: cumplidos/parciales
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 03-mejoras.md — Mejoras posibles (explicativo, breve)
|
|
96
|
+
|
|
97
|
+
```markdown
|
|
98
|
+
# Mejoras posibles — <título corto>
|
|
99
|
+
|
|
100
|
+
> Solo propuestas explicativas, sin profundizar. Cada una con su grado de relevancia.
|
|
101
|
+
|
|
102
|
+
## A la skill (ozali/cdk)
|
|
103
|
+
- **[Alta]** <mejora> — <por qué>
|
|
104
|
+
- **[Media]** <mejora> — <por qué>
|
|
105
|
+
|
|
106
|
+
## Al proyecto
|
|
107
|
+
- **[Alta]** <mejora> — <por qué>
|
|
108
|
+
- **[Baja]** <mejora> — <por qué>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Grados de relevancia: **Alta** (impacto/urgencia clara), **Media** (conviene pronto),
|
|
112
|
+
**Baja** (nice-to-have).
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## B) Documentación por hito (cdk)
|
|
117
|
+
|
|
118
|
+
La genera `cdk` (subagente `project-documenter`) **una vez por cada solicitud/hito** del
|
|
119
|
+
usuario, en:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
.ozali/docs/cdk/<hito>/
|
|
123
|
+
01-prompt-entrada.md ← al inicio del hito
|
|
124
|
+
02-plan-aprobado.md ← se congela al aprobar el GATE (inmutable)
|
|
125
|
+
03-resumen-tecnico.md ← al cierre
|
|
126
|
+
04-resumen-usuario.md ← al cierre
|
|
127
|
+
05-bitacora-ejecucion.md ← append-only, DURANTE el ciclo
|
|
128
|
+
06-uso-tokens.md ← al cierre
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
- `<hito>` = slug corto y descriptivo de la solicitud (ej. `alta-componente-cobranza`,
|
|
132
|
+
`fix-calculo-prima-poliza`). Si ya existe, agrega sufijo `-2`, `-3`, …
|
|
133
|
+
- Cada documento usa el **mismo encabezado de identidad** de arriba (con `hito:` en lugar de
|
|
134
|
+
`ozali.log:`).
|
|
135
|
+
|
|
136
|
+
### 01-prompt-entrada.md — Prompt de entrada
|
|
137
|
+
|
|
138
|
+
```markdown
|
|
139
|
+
# Prompt de entrada — <hito>
|
|
140
|
+
|
|
141
|
+
> Captura textual de la solicitud del usuario, para evaluar el progreso de las solicitudes.
|
|
142
|
+
|
|
143
|
+
## Prompt (textual)
|
|
144
|
+
<pega aquí, sin editar, el prompt/solicitud exacta del usuario>
|
|
145
|
+
|
|
146
|
+
## Contexto de la sesión
|
|
147
|
+
- Fecha/Hora de la solicitud: <yyyy-mm-dd HH:MM:SS>
|
|
148
|
+
- Hito asignado: <slug>
|
|
149
|
+
- Modo de ejecución: normal | --auto
|
|
150
|
+
- Solicitudes previas relacionadas: <links a otros hitos, si aplica>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 02-plan-aprobado.md — Plan aprobado (snapshot congelado en el GATE)
|
|
154
|
+
|
|
155
|
+
> Se escribe **al aprobarse el GATE, antes de tocar código**, y es **inmutable**: deja
|
|
156
|
+
> constancia de qué se acordó y quién lo aprobó. Cualquier desvío posterior se registra en
|
|
157
|
+
> `05-bitacora-ejecucion.md`, nunca editando este documento. Es el mismo Plan de Acción que
|
|
158
|
+
> vio el usuario, ya con su decisión.
|
|
159
|
+
|
|
160
|
+
```markdown
|
|
161
|
+
# Plan aprobado — <hito>
|
|
162
|
+
|
|
163
|
+
**Tipo:** feature | bugfix | hotfix | refactor **Tamaño:** S | M | L
|
|
164
|
+
**Workflow:** .ai/workflows/<archivo>.md
|
|
165
|
+
**Modo:** normal | --auto
|
|
166
|
+
**Aprobado por:** <usuario> — <yyyy-mm-dd HH:MM:SS>
|
|
167
|
+
|
|
168
|
+
## Solicitud del usuario
|
|
169
|
+
<qué pidió, en sus palabras>
|
|
170
|
+
|
|
171
|
+
## Alcance aprobado
|
|
172
|
+
<lo que SÍ se hará>
|
|
173
|
+
|
|
174
|
+
## Hallazgos del análisis
|
|
175
|
+
- Reutilización detectada: <clases/archivos existentes que se aprovechan>
|
|
176
|
+
- Riesgos: ⚠ <riesgo> → <mitigación> / 🔴 <bloqueante resuelto y cómo>
|
|
177
|
+
|
|
178
|
+
## Cambios aprobados (archivo por archivo)
|
|
179
|
+
| Acción | Archivo / Clase | Capa | Detalle |
|
|
180
|
+
| :-- | :-- | :-- | :-- |
|
|
181
|
+
| crear | <X> | <capa> | <detalle> |
|
|
182
|
+
| modificar | <Y> | <capa> | <detalle> |
|
|
183
|
+
|
|
184
|
+
## Tareas
|
|
185
|
+
- [ ] <tarea 1>
|
|
186
|
+
- [ ] <tarea 2>
|
|
187
|
+
|
|
188
|
+
## Plan de pruebas
|
|
189
|
+
- Caso feliz: <...>
|
|
190
|
+
- Casos negativos: <...>
|
|
191
|
+
|
|
192
|
+
## Criterios de aceptación (definition of done)
|
|
193
|
+
- <p. ej. mvn test verde + criterios del owner>
|
|
194
|
+
|
|
195
|
+
## Fuera de alcance (explícito)
|
|
196
|
+
- <lo que NO se hará en este hito>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### 03-resumen-tecnico.md — Resumen técnico
|
|
200
|
+
|
|
201
|
+
```markdown
|
|
202
|
+
# Resumen técnico — <hito>
|
|
203
|
+
|
|
204
|
+
## Decisiones de implementación
|
|
205
|
+
<enfoque, patrones, por qué>
|
|
206
|
+
|
|
207
|
+
## Archivos tocados
|
|
208
|
+
- <archivo>: <qué cambió>
|
|
209
|
+
|
|
210
|
+
## Impacto y riesgos
|
|
211
|
+
- Módulos afectados: <lista>
|
|
212
|
+
- Riesgo en módulos sensibles (core/guard/services/poliza/siniestros/cobranza/models/...): <sí/no, detalle>
|
|
213
|
+
|
|
214
|
+
## Validación
|
|
215
|
+
- Pruebas: <comando / resultado>
|
|
216
|
+
- walkthrough.md: <ruta / evidencia>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### 04-resumen-usuario.md — Resumen para el usuario
|
|
220
|
+
|
|
221
|
+
```markdown
|
|
222
|
+
# Resumen para usuario — <hito>
|
|
223
|
+
|
|
224
|
+
> Lenguaje claro, sin jerga técnica.
|
|
225
|
+
|
|
226
|
+
## ¿Qué se hizo y para qué sirve?
|
|
227
|
+
<explicación sencilla en 2-3 frases>
|
|
228
|
+
|
|
229
|
+
## ¿Cómo se usa? (casos de uso)
|
|
230
|
+
1. **<caso de uso 1>** — <pasos sencillos explicados>
|
|
231
|
+
2. **<caso de uso 2>** — <pasos sencillos explicados>
|
|
232
|
+
|
|
233
|
+
## Qué cambia para ti
|
|
234
|
+
<beneficio concreto / qué notará el usuario>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 05-bitacora-ejecucion.md — Bitácora de ejecución (append-only)
|
|
238
|
+
|
|
239
|
+
> Registro **cronológico y append-only** de lo que ocurre DESPUÉS de aprobar el plan y
|
|
240
|
+
> DURANTE el ciclo de ejecución: dudas, decisiones, actualizaciones y desvíos respecto al
|
|
241
|
+
> `02-plan-aprobado.md` (que permanece inmutable), preguntas al usuario y sus respuestas.
|
|
242
|
+
> **No se reescribe**: solo se agregan entradas, en orden cronológico. Aquí vive toda la
|
|
243
|
+
> diferencia entre lo planeado y lo realmente ejecutado.
|
|
244
|
+
|
|
245
|
+
```markdown
|
|
246
|
+
# Bitácora de ejecución — <hito>
|
|
247
|
+
|
|
248
|
+
**Modo de ejecución:** normal | --auto
|
|
249
|
+
**Inicio del ciclo:** <yyyy-mm-dd HH:MM:SS>
|
|
250
|
+
|
|
251
|
+
## Entradas
|
|
252
|
+
|
|
253
|
+
### <yyyy-mm-dd HH:MM:SS> — [duda | decisión | actualización | desvío | pregunta]
|
|
254
|
+
- **Qué surgió:** <descripción concreta>
|
|
255
|
+
- **Contexto:** <archivo / tarea / iteración donde apareció>
|
|
256
|
+
- **Resolución:** <qué se decidió y por qué; si fue pregunta al usuario, pega su respuesta textual>
|
|
257
|
+
- **Impacto en el plan:** ninguno | ajuste dentro de alcance | requirió ampliar alcance (se detuvo y preguntó)
|
|
258
|
+
|
|
259
|
+
### <yyyy-mm-dd HH:MM:SS> — [tipo]
|
|
260
|
+
- ...
|
|
261
|
+
|
|
262
|
+
## Cierre del ciclo
|
|
263
|
+
- **Fin:** <yyyy-mm-dd HH:MM:SS>
|
|
264
|
+
- **Iteraciones executioner⇄tester:** <n>
|
|
265
|
+
- **Desvíos relevantes vs. plan aprobado:** <resumen / "ninguno">
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 06-uso-tokens.md — Uso de tokens (al cierre)
|
|
269
|
+
|
|
270
|
+
> Se captura **al terminar el plan**. Las métricas se rellenan en caso de que el proveedor sea
|
|
271
|
+
> **Claude/Anthropic** (fuente: comando `/cost` de Claude Code). Con cualquier otro
|
|
272
|
+
> proveedor verifica si puedes obtener la información y si no puedes, deja la estructura con el **nombre del proveedor** y las métricas en `N/A`
|
|
273
|
+
> (data presente, sin inventar cifras).
|
|
274
|
+
|
|
275
|
+
```markdown
|
|
276
|
+
# Uso de tokens — <hito>
|
|
277
|
+
|
|
278
|
+
**Proveedor:** Claude (Anthropic) | <otro proveedor>
|
|
279
|
+
**Modelo:** <p. ej. claude-opus-4-8 / N/A>
|
|
280
|
+
**Fuente de la medición:** /cost (Claude Code) | N/A
|
|
281
|
+
**Capturado:** <yyyy-mm-dd HH:MM:SS>
|
|
282
|
+
|
|
283
|
+
## Métricas de la sesión
|
|
284
|
+
| Métrica | Valor |
|
|
285
|
+
| :-- | :-- |
|
|
286
|
+
| Tokens de entrada (input) | <n / N/A> |
|
|
287
|
+
| Tokens de salida (output) | <n / N/A> |
|
|
288
|
+
| Tokens de caché (lectura) | <n / N/A> |
|
|
289
|
+
| Tokens de caché (escritura) | <n / N/A> |
|
|
290
|
+
| Total de tokens | <n / N/A> |
|
|
291
|
+
| Total de tiempo de sesión | <n / N/A> |
|
|
292
|
+
| Costo estimado | <$ / N/A> |
|
|
293
|
+
|
|
294
|
+
## Notas
|
|
295
|
+
- <observaciones sobre el consumo del hito; deja vacío o "N/A" si no puedes encontrar información del proveedor>
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
> **Regla del proveedor:** si el proveedor **no** cuenta con estos datos, **no** intentes
|
|
299
|
+
> derivar ni inventar cifras de otro sistema: solo registra el nombre del proveedor y deja
|
|
300
|
+
> el resto en `N/A`. El objetivo es **mantener la estructura presente** para no perder la
|
|
301
|
+
> trazabilidad del hito.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Convención de memoria híbrida (docs + Engram)
|
|
2
|
+
|
|
3
|
+
Contrato de persistencia que `ozali` cablea dentro del `SKILL.md` de `cdk` (Fase 6). Define
|
|
4
|
+
**qué se guarda, dónde, cuándo y con qué nombre** para que la herramienta **aprenda de lo que el
|
|
5
|
+
equipo va haciendo** sin sobrecargar el repo principal.
|
|
6
|
+
|
|
7
|
+
> **Principio híbrido:** cada artefacto clave vive en **dos** lugares — un **documento legible**
|
|
8
|
+
> (para humanos, auditable, versionable en el repo de conocimiento) **y** un **espejo en Engram**
|
|
9
|
+
> (buscable, recuperable tras compactación, base de la memoria acumulativa del equipo).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Modo de persistencia y degradación
|
|
14
|
+
|
|
15
|
+
`cdk` resuelve el modo **al iniciar cada hito**:
|
|
16
|
+
|
|
17
|
+
| Modo | Lee de | Escribe en | Cuándo |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| **`hybrid`** (default) | Engram primero, docs como fallback | docs **y** Engram | Engram disponible |
|
|
20
|
+
| **`docs`** | docs | docs | Engram **no** instalado/alcanzable |
|
|
21
|
+
| **`none`** | contexto del prompt | nada | el usuario lo pide explícito (efímero) |
|
|
22
|
+
|
|
23
|
+
**Detección de Engram:** el MCP de Engram expone `mem_*`. Si las herramientas no están disponibles
|
|
24
|
+
(o `mem_context` falla), `cdk` **degrada a `docs`** sin romper: escribe los 6 documentos por hito
|
|
25
|
+
igual y anota en la bitácora que el espejo Engram quedó pendiente. `ozali init` (CLI) **verifica/
|
|
26
|
+
guía la instalación de Engram**; mientras no esté, todo funciona en modo `docs`.
|
|
27
|
+
|
|
28
|
+
> Regla: la **ausencia de Engram nunca bloquea** un hito. Solo se pierde la capa buscable, que se
|
|
29
|
+
> rellena al sincronizar cuando Engram esté disponible.
|
|
30
|
+
|
|
31
|
+
**Nombre de proyecto:** usa el que Engram autodetecta del remoto git (normalizado a minúsculas).
|
|
32
|
+
Sin remoto, el nombre de carpeta. Mantén UN nombre por proyecto (evita drift `my-app` vs `My-App`).
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 2. Naming determinista
|
|
37
|
+
|
|
38
|
+
Todos los artefactos de `cdk` en Engram siguen:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
title: cdk/{hito}/{artifact-type}
|
|
42
|
+
topic_key: cdk/{hito}/{artifact-type}
|
|
43
|
+
type: architecture
|
|
44
|
+
project: {nombre del proyecto detectado}
|
|
45
|
+
scope: project
|
|
46
|
+
capture_prompt: false # artefactos automáticos: NO capturan el prompt del usuario
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Para artefactos a nivel de proyecto (no de hito): `cdk/_project/{artifact-type}`.
|
|
50
|
+
|
|
51
|
+
> `capture_prompt: false` es **explícito y obligatorio** para artefactos automáticos cuando el
|
|
52
|
+
> esquema lo soporta (Engram v1.15.3+ lo pone `true` por defecto en saves humanos). Si un esquema
|
|
53
|
+
> viejo no expone el campo, **omítelo** en lugar de fallar. El **prompt del usuario** se captura
|
|
54
|
+
> aparte, una sola vez, con `mem_save_prompt` al inicio del hito (artefacto `01`).
|
|
55
|
+
|
|
56
|
+
### Mapa doc ↔ Engram
|
|
57
|
+
|
|
58
|
+
| Doc por hito (archivo) | artifact-type (Engram) | Momento | Operación |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| `01-prompt-entrada.md` | — (usa `mem_save_prompt`) | inicio del hito | `mem_save_prompt` |
|
|
61
|
+
| (análisis del analyzer) | `analisis` | tras el análisis | `mem_save` |
|
|
62
|
+
| `02-plan-aprobado.md` | `plan-aprobado` | al aprobar el GATE | `mem_save` **una vez** (inmutable) |
|
|
63
|
+
| `05-bitacora-ejecucion.md` | `bitacora` | checkpoints del ciclo | `mem_update` (upsert) |
|
|
64
|
+
| `03-resumen-tecnico.md` | `resumen-tecnico` | al cierre | `mem_save` |
|
|
65
|
+
| (estado del orchestrator) | `state` | tras cada transición de fase | `mem_update` (upsert) |
|
|
66
|
+
| calibración (Fase 3.5 de ozali) | `_project/testing-capabilities` | en el bootstrap | `mem_save` |
|
|
67
|
+
|
|
68
|
+
> `04-resumen-usuario.md` y `06-uso-tokens.md` se quedan como **docs legibles** (no necesitan
|
|
69
|
+
> espejo buscable); opcional mirror si el equipo lo quiere.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 3. Llamadas inline (lo que cdk debe ejecutar)
|
|
74
|
+
|
|
75
|
+
### Al INICIAR un hito (contrato de arranque — así aprende del equipo)
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
# 1) Capturar el prompt real, una vez:
|
|
79
|
+
mem_save_prompt(prompt: "{prompt textual del usuario}", project: "{project}")
|
|
80
|
+
|
|
81
|
+
# 2) Traer contexto previo (búsquedas primero, luego recuperar full):
|
|
82
|
+
mem_search(query: "cdk/{hito}/state", project: "{project}") → ¿hito en curso? (reanudar)
|
|
83
|
+
mem_search(query: "cdk/_project/testing-capabilities", project: "{project}") → strict_tdd + comando verde
|
|
84
|
+
mem_search(query: "cdk/{hito}", project: "{project}") → artefactos relacionados
|
|
85
|
+
mem_context(project: "{project}") → historia reciente de sesión
|
|
86
|
+
|
|
87
|
+
# 3) Recuperar contenido completo de lo relevante (search devuelve preview truncado):
|
|
88
|
+
mem_get_observation(id: {state_id}) → restaurar fase + tareas done/pending
|
|
89
|
+
mem_get_observation(id: {testing_capabilities_id}) → resolver modo TDD
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Si `state` existe con tareas pendientes → **reanuda** desde la primera pendiente (no rehagas lo
|
|
93
|
+
hecho). Si `testing-capabilities` da `strict_tdd: true` → ciclo **test-first** (RED→GREEN→REFACTOR).
|
|
94
|
+
|
|
95
|
+
### Al CONGELAR el plan (GATE aprobado)
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
mem_save(
|
|
99
|
+
title: "cdk/{hito}/plan-aprobado", topic_key: "cdk/{hito}/plan-aprobado",
|
|
100
|
+
type: "architecture", project: "{project}", capture_prompt: false,
|
|
101
|
+
content: "{markdown completo del plan aprobado}"
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
Inmutable: **no** se vuelve a guardar este topic_key. Los desvíos van a `bitacora`.
|
|
105
|
+
|
|
106
|
+
### DURANTE el ciclo (bitácora + estado, append-only en archivo, upsert en Engram)
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
# bitácora: el archivo 05 es append-only (fuente de verdad); el espejo se upserta con el full actual
|
|
110
|
+
mem_update(id: {bitacora_id}, content: "{contenido completo y actualizado de la bitácora}")
|
|
111
|
+
# (si aún no existe: mem_save con topic_key cdk/{hito}/bitacora)
|
|
112
|
+
|
|
113
|
+
# estado recuperable: upsert tras CADA transición de fase
|
|
114
|
+
mem_update(id: {state_id}, content: "{ver §4}")
|
|
115
|
+
# (si aún no existe: mem_save con topic_key cdk/{hito}/state)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Al CERRAR el hito
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
mem_save(title: "cdk/{hito}/resumen-tecnico", topic_key: "cdk/{hito}/resumen-tecnico",
|
|
122
|
+
type: "architecture", project: "{project}", capture_prompt: false,
|
|
123
|
+
content: "{resumen técnico}")
|
|
124
|
+
# y un cierre de sesión (solo el agente top-level, NUNCA un subagente):
|
|
125
|
+
mem_session_summary(project: "{project}", content: "{qué se logró en el hito}")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## 4. Artefacto `state` (recuperable tras compactación)
|
|
131
|
+
|
|
132
|
+
Lo mantiene el `project-orchestrator`. Permite que un hito sobreviva a una compactación de
|
|
133
|
+
contexto o a cerrar/abrir la sesión.
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
title: cdk/{hito}/state
|
|
137
|
+
topic_key: cdk/{hito}/state
|
|
138
|
+
content: |
|
|
139
|
+
hito: {hito}
|
|
140
|
+
fase: {analisis | plan-aprobado | ejecucion | cierre}
|
|
141
|
+
strict_tdd: {true|false}
|
|
142
|
+
modo: {normal | --auto}
|
|
143
|
+
tareas:
|
|
144
|
+
completadas: [t1, t2]
|
|
145
|
+
pendientes: [t3, t4]
|
|
146
|
+
ultimo_commit: {short SHA}
|
|
147
|
+
last_updated: {ISO-8601}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**Recuperación (2 pasos):** `mem_search("cdk/{hito}/state")` → `mem_get_observation(id)` → parsear
|
|
151
|
+
YAML → restaurar. Si no hay `state`, es un hito nuevo.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## 5. Reglas duras
|
|
156
|
+
|
|
157
|
+
- **Persistir ANTES de responder:** cuando un subagente guarda en Engram o escribe docs, la llamada
|
|
158
|
+
va **antes** de su texto final. La última salida del subagente debe ser **texto**, nunca un
|
|
159
|
+
tool-call (si no, el orquestador solo recibe `"Observation saved"` y se pierde el análisis).
|
|
160
|
+
- **Subagentes NO llaman `mem_session_summary`** — reservado para el agente top-level.
|
|
161
|
+
- **Modo `hybrid`: ambas escrituras deben tener éxito.** Si Engram falla a media operación, el doc
|
|
162
|
+
ya quedó (fuente de verdad) y se anota el espejo pendiente en la bitácora; no se aborta el hito.
|
|
163
|
+
- **Lectura `hybrid`: Engram primero, docs como fallback.** Si `mem_search` no devuelve, lee el
|
|
164
|
+
archivo correspondiente en `.ozali/docs/cdk/{hito}/`.
|
|
165
|
+
- **Nunca inventes el prompt:** si no hay contexto de prompt, `mem_save` no fabrica texto.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 6. Sincronización al repo de conocimiento (`ozali sync`)
|
|
170
|
+
|
|
171
|
+
Engram guarda en su **store local**; el histórico (docs + export Engram) se aísla en el repo de
|
|
172
|
+
conocimiento de equipo (ver [team-history](../../docs/team-history.md)). El CLI lo orquesta:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
ozali sync # export del proyecto → repo de conocimiento, commit + push
|
|
176
|
+
ozali sync --import # pull del repo de conocimiento → import a Engram local (onboarding)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Internamente (Fase C lo implementa):
|
|
180
|
+
1. `engram sync` exporta las memorias del proyecto a `.engram/` (chunks + manifest).
|
|
181
|
+
2. Copia `.engram/` y `.ozali/docs/cdk/` a `ozali-knowledge/{engram,projects/<project>/...}`.
|
|
182
|
+
3. Commit + push del repo de conocimiento (no del repo principal, que los tiene gitignored).
|
|
183
|
+
4. `--import` hace lo inverso: clona/pull del repo de conocimiento y `engram sync --import`.
|
|
184
|
+
|
|
185
|
+
> Trazabilidad: cada doc lleva `ultimo_commit`/`Commit:` del repo principal en su encabezado, así
|
|
186
|
+
> el histórico aislado siempre apunta al código exacto que documenta.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Plantilla del harness `verify-structure.mjs`
|
|
2
|
+
|
|
3
|
+
Esqueleto parametrizado del **harness del analista** que `ozali` genera en la Fase 6
|
|
4
|
+
(punto 3) como `.claude/skills/cdk/verify-structure.mjs`. El script es el paso 1
|
|
5
|
+
obligatorio del `project-analyzer`: verifica la estructura REAL del repo contra la
|
|
6
|
+
arquitectura documentada — no confía en la doc.
|
|
7
|
+
|
|
8
|
+
> **Regla:** los valores de los parámetros salen de la **fuente de verdad validada en la
|
|
9
|
+
> Fase 3** (`.ai/context/architecture.md`) y de la inspección real del repo — nunca de
|
|
10
|
+
> supuestos. Cero dependencias, Node 16+.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 1. Parámetros a sustituir
|
|
15
|
+
|
|
16
|
+
| Parámetro | Qué es | Ejemplo backend (Java) | Ejemplo frontend (Angular) |
|
|
17
|
+
|---|---|---|---|
|
|
18
|
+
| `{{PROJECT_NAME}}` | Nombre real del repo | `quattro-auto-mtto` | `biibiic` |
|
|
19
|
+
| `{{ROOT_MARKER}}` | Archivo que identifica la raíz (para subir buscándolo) | `pom.xml` | `angular.json` (o `package.json`) |
|
|
20
|
+
| `{{BASE_PATH}}` | Carpeta base del código, como array de segmentos | `["src","main","java","com","acme"]` | `["src","app"]` |
|
|
21
|
+
| `{{EXT}}` | Extensión de archivos a contar | `.java` | `.ts` |
|
|
22
|
+
| `{{EXPECTED}}` | Capas/carpetas esperadas + rol de una línea (de `architecture.md`) | `controllers`, `services/strategies/impl`, … | `components`, `services`, `guards`, `pages`, … |
|
|
23
|
+
| `{{KEY_CLASSES}}` | Clases/archivos clave que los agentes referencian (sin extensión) | `ApiResponse`, `ErrorCode` | `auth.guard`, `api.service` |
|
|
24
|
+
| `{{CONSISTENCY_CHECKS}}` | Gotchas verificados del repo (ver §3) | context-path, typos de nombres | rutas lazy, config de entornos |
|
|
25
|
+
| `{{TEST_DIR}}` | Carpeta(s) de pruebas a contar | `src/test` | `src` con sufijo `.spec.ts` |
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Esqueleto del script
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
#!/usr/bin/env node
|
|
33
|
+
// CDK — {{PROJECT_NAME}}
|
|
34
|
+
// Harness del analista: verifica la estructura real del proyecto contra la
|
|
35
|
+
// arquitectura documentada (.ai/context/architecture.md), localiza archivos clave
|
|
36
|
+
// y reporta discrepancias + candidatos a reutilizacion.
|
|
37
|
+
//
|
|
38
|
+
// Uso (desde cualquier carpeta dentro del repo):
|
|
39
|
+
// node .claude/skills/cdk/verify-structure.mjs # reporte completo
|
|
40
|
+
// node .claude/skills/cdk/verify-structure.mjs --grep <palabra>
|
|
41
|
+
//
|
|
42
|
+
// Cero dependencias. Node 16+.
|
|
43
|
+
|
|
44
|
+
import fs from "node:fs";
|
|
45
|
+
import path from "node:path";
|
|
46
|
+
|
|
47
|
+
// ---- localizar la raiz del proyecto (sube buscando {{ROOT_MARKER}}) ---------
|
|
48
|
+
function findRoot(start) {
|
|
49
|
+
let dir = start;
|
|
50
|
+
for (let i = 0; i < 30; i++) {
|
|
51
|
+
if (fs.existsSync(path.join(dir, "{{ROOT_MARKER}}"))) return dir;
|
|
52
|
+
const parent = path.dirname(dir);
|
|
53
|
+
if (parent === dir) break;
|
|
54
|
+
dir = parent;
|
|
55
|
+
}
|
|
56
|
+
return start;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const ROOT = findRoot(process.cwd());
|
|
60
|
+
const BASE = path.join(ROOT, ...{{BASE_PATH}});
|
|
61
|
+
const EXT = "{{EXT}}";
|
|
62
|
+
|
|
63
|
+
// ---- capas esperadas (lo que promete .ai/context/architecture.md) -----------
|
|
64
|
+
const EXPECTED = [
|
|
65
|
+
// { pkg: "<carpeta relativa a BASE>", role: "<rol de una linea>" },
|
|
66
|
+
{{EXPECTED}}
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
// ---- archivos clave que referencian los agentes -----------------------------
|
|
70
|
+
const KEY_CLASSES = [
|
|
71
|
+
{{KEY_CLASSES}}
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
function countFiles(dir) {
|
|
75
|
+
let n = 0;
|
|
76
|
+
if (!fs.existsSync(dir)) return -1;
|
|
77
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
78
|
+
if (e.isDirectory()) {
|
|
79
|
+
const c = countFiles(path.join(dir, e.name));
|
|
80
|
+
if (c > 0) n += c;
|
|
81
|
+
} else if (e.name.endsWith(EXT)) {
|
|
82
|
+
n++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return n;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function findFile(dir, name) {
|
|
89
|
+
if (!fs.existsSync(dir)) return null;
|
|
90
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
91
|
+
const full = path.join(dir, e.name);
|
|
92
|
+
if (e.isDirectory()) {
|
|
93
|
+
const hit = findFile(full, name);
|
|
94
|
+
if (hit) return hit;
|
|
95
|
+
} else if (e.name === name + EXT) {
|
|
96
|
+
return path.relative(ROOT, full);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function grepFiles(dir, term, out, limit = 40) {
|
|
103
|
+
if (out.length >= limit || !fs.existsSync(dir)) return;
|
|
104
|
+
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
105
|
+
if (out.length >= limit) return;
|
|
106
|
+
const full = path.join(dir, e.name);
|
|
107
|
+
if (e.isDirectory()) {
|
|
108
|
+
grepFiles(full, term, out, limit);
|
|
109
|
+
} else if (e.name.endsWith(EXT) && e.name.toLowerCase().includes(term.toLowerCase())) {
|
|
110
|
+
out.push(path.relative(ROOT, full));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
console.log("============================================================");
|
|
117
|
+
console.log(" CDK · {{PROJECT_NAME}} — Verificacion de estructura");
|
|
118
|
+
console.log("============================================================");
|
|
119
|
+
console.log("Root:", ROOT);
|
|
120
|
+
console.log("Base:", fs.existsSync(BASE) ? path.relative(ROOT, BASE) : "(!) NO ENCONTRADO");
|
|
121
|
+
console.log("");
|
|
122
|
+
|
|
123
|
+
const risks = [];
|
|
124
|
+
|
|
125
|
+
console.log("-- Capas / carpetas ---------------------------------------");
|
|
126
|
+
for (const { pkg, role } of EXPECTED) {
|
|
127
|
+
const dir = path.join(BASE, ...pkg.split("/"));
|
|
128
|
+
const c = countFiles(dir);
|
|
129
|
+
const status = c < 0 ? "FALTA " : String(c).padStart(4) + " ";
|
|
130
|
+
console.log(` [${c < 0 ? "X" : "ok"}] ${pkg.padEnd(26)} ${status}files — ${role}`);
|
|
131
|
+
if (c < 0) risks.push(`Carpeta esperada ausente: ${pkg}`);
|
|
132
|
+
}
|
|
133
|
+
console.log("");
|
|
134
|
+
|
|
135
|
+
console.log("-- Archivos clave -----------------------------------------");
|
|
136
|
+
for (const cls of KEY_CLASSES) {
|
|
137
|
+
const loc = findFile(BASE, cls);
|
|
138
|
+
console.log(` [${loc ? "ok" : "X"}] ${cls.padEnd(28)} ${loc || "(!) NO ENCONTRADO"}`);
|
|
139
|
+
if (!loc) risks.push(`Archivo clave no encontrado: ${cls}`);
|
|
140
|
+
}
|
|
141
|
+
console.log("");
|
|
142
|
+
|
|
143
|
+
console.log("-- Chequeos de consistencia doc<->codigo -----------------");
|
|
144
|
+
// {{CONSISTENCY_CHECKS}}: gotchas VERIFICADOS del repo. Cada uno imprime [i] con el
|
|
145
|
+
// hallazgo y la regla practica. Si dejan de aparecer, actualizar tambien la seccion
|
|
146
|
+
// Gotchas del SKILL.md de cdk y .ai/knowledge/learning-notes.md. Ejemplos:
|
|
147
|
+
// - typos en nombres reales de clases (no "corregirlos" sin refactor aprobado)
|
|
148
|
+
// - prefijos globales (context-path / baseHref) que no van en el codigo
|
|
149
|
+
// - donde vive cada propiedad de configuracion por entorno
|
|
150
|
+
// - conteo de pruebas reales ({{TEST_DIR}}) → advertir si la cobertura es minima
|
|
151
|
+
{{CONSISTENCY_CHECKS}}
|
|
152
|
+
console.log("");
|
|
153
|
+
|
|
154
|
+
// ---- busqueda opcional de reutilizacion (busca antes de crear) --------------
|
|
155
|
+
const gi = process.argv.indexOf("--grep");
|
|
156
|
+
if (gi !== -1 && process.argv[gi + 1]) {
|
|
157
|
+
const term = process.argv[gi + 1];
|
|
158
|
+
console.log(`-- Reutilizacion: archivos que ya mencionan "${term}" ----`);
|
|
159
|
+
const hits = [];
|
|
160
|
+
grepFiles(BASE, term, hits);
|
|
161
|
+
if (hits.length === 0) console.log(" (sin coincidencias por nombre de archivo)");
|
|
162
|
+
for (const h of hits) console.log(" •", h);
|
|
163
|
+
console.log("");
|
|
164
|
+
console.log(` >> Antes de crear codigo nuevo, revisa estos ${hits.length} archivo(s).`);
|
|
165
|
+
console.log("");
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.log("============================================================");
|
|
169
|
+
if (risks.length) {
|
|
170
|
+
console.log(` RIESGOS / HALLAZGOS (${risks.length}):`);
|
|
171
|
+
for (const r of risks) console.log(" ⚠ " + r);
|
|
172
|
+
} else {
|
|
173
|
+
console.log(" Estructura coherente con la arquitectura documentada.");
|
|
174
|
+
}
|
|
175
|
+
console.log("============================================================");
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 3. Secciones específicas por tipo de proyecto
|
|
181
|
+
|
|
182
|
+
Además del esqueleto, agrega los chequeos que apliquen:
|
|
183
|
+
|
|
184
|
+
**Backend (Java/Spring)**
|
|
185
|
+
- Sección extra de **dominio** si hay un patrón central (p. ej. en quattro-auto-mtto:
|
|
186
|
+
listar carpetas bajo `services/strategies/impl/` y verificar que cada aseguradora tenga
|
|
187
|
+
su `*Strategy`). Replica la idea para el patrón central del proyecto.
|
|
188
|
+
- Leer `context-path` de `application.properties`/`application.yml` y advertir que no se
|
|
189
|
+
incluye en `@RequestMapping`.
|
|
190
|
+
- Contar `.java` en `src/test`.
|
|
191
|
+
|
|
192
|
+
**Frontend (Angular/React/Vue)**
|
|
193
|
+
- Verificar módulos/rutas declarados vs carpetas reales (lazy loading roto = riesgo).
|
|
194
|
+
- Leer `baseHref`/`deploy` de `angular.json` o equivalente.
|
|
195
|
+
- Contar `*.spec.ts` (o `*.test.tsx`) para reportar cobertura real.
|
|
196
|
+
|
|
197
|
+
**Ambos**
|
|
198
|
+
- El bloque de consistencia **siembra** `learning-notes.md`: todo gotcha que el harness
|
|
199
|
+
detecte en su primera corrida debe quedar registrado ahí y en el SKILL.md de `cdk`.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 4. Validación obligatoria al generarlo
|
|
204
|
+
|
|
205
|
+
Tras escribir el script, `ozali` **debe ejecutarlo** y verificar:
|
|
206
|
+
1. Corre sin errores con Node 16+ (`node .claude/skills/cdk/verify-structure.mjs`).
|
|
207
|
+
2. Todas las capas de `EXPECTED` reportan `[ok]` (si algo reporta `FALTA`, o la doc está
|
|
208
|
+
mal o el parámetro está mal — corrígelo antes de cerrar la Fase 6).
|
|
209
|
+
3. Todos los `KEY_CLASSES` se localizan.
|
|
210
|
+
4. `--grep <término-conocido>` devuelve hits razonables.
|
|
211
|
+
|
|
212
|
+
La salida real de esta corrida se cita en el `02-plan.md` de la corrida de ozali como
|
|
213
|
+
evidencia. Ejemplo de referencia ya funcionando: el `verify-structure.mjs` de este repo
|
|
214
|
+
(`.claude/skills/cdk/verify-structure.mjs`).
|