@ingeniomaps/cauce 0.97.0 → 0.99.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/CHANGELOG.md +162 -0
- package/README.md +1 -0
- package/agents/roles/system/accounting-specialist/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/ai-governance-lead/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/ai-product-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/analytics-engineer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/backend-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/business-strategist/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/cloud-architect/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/community-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/content-specialist/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/customer-success-manager/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/customer-support-specialist/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/data-analyst/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/data-engineer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/data-governance-steward/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/data-scientist/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/database-administrator/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/developer-relations-engineer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/devops-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/engineering-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/financial-controller/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/finops-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/fraud-risk-analyst/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/frontend-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/growth-marketer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/implementation-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/integrations-engineer/learning/AUTOMATION.md +3 -3
- package/agents/roles/system/kyc-aml-specialist/learning/AUTOMATION.md +3 -3
- package/agents/roles/system/legal-counsel/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/logistics-operations-manager/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/machine-learning-engineer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/mlops-engineer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/mobile-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/partnerships-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/people-operations-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/privacy-compliance-specialist/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/procurement-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/product-manager/learning/AUTOMATION.md +3 -3
- package/agents/roles/system/product-marketing-manager/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/project-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/qa-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/release-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/sales-representative/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/security-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/site-reliability-engineer/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/software-architect/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/solutions-engineer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/tech-lead/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/technical-program-manager/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/technical-writer/learning/AUTOMATION.md +1 -1
- package/agents/roles/system/treasury-analyst/learning/AUTOMATION.md +2 -2
- package/agents/roles/system/ui-designer/learning/AUTOMATION.md +3 -3
- package/agents/roles/system/user-researcher/learning/AUTOMATION.md +3 -3
- package/agents/roles/system/ux-designer/learning/AUTOMATION.md +3 -3
- package/automatization/hooks/README.md +10 -5
- package/automatization/runners/antigravity/README.md +4 -1
- package/automatization/runners/antigravity/hook.js +84 -22
- package/automatization/runners/antigravity/manifest.json +1 -0
- package/automatization/shared/acceptance.js +26 -0
- package/automatization/workflows/agent-propose.js +2 -2
- package/automatization/workflows/autobuild.js +121 -38
- package/engine/agents/learning-files.js +18 -0
- package/engine/agents/learning-seal.js +24 -12
- package/engine/agents/learning-sources.js +12 -10
- package/engine/agents/learning.js +29 -7
- package/engine/automation/index.js +11 -2
- package/engine/automation/registration.js +89 -0
- package/engine/cli/args.js +2 -2
- package/engine/cli/catalog.js +12 -12
- package/engine/cli/ops.js +2 -1
- package/engine/cli/validate.js +3 -0
- package/engine/cli/wiring.js +1 -1
- package/engine/config/validate.js +30 -11
- package/engine/core/migrations.js +275 -0
- package/engine/core/repos.js +18 -4
- package/engine/hooks/approval.js +38 -7
- package/engine/hooks/chat.js +97 -27
- package/engine/hooks/files.js +6 -104
- package/engine/hooks/input.js +67 -11
- package/engine/hooks/migrations.js +93 -0
- package/engine/hooks/push.js +8 -5
- package/engine/hooks/run.js +10 -5
- package/engine/hooks/self-approval.js +2 -2
- package/engine/hooks/shell.js +34 -0
- package/engine/hooks/verify.js +79 -22
- package/engine/planning/acceptance.js +18 -0
- package/engine/planning/contracts.js +78 -45
- package/engine/schemas/ops-config.schema.json +9 -0
- package/package.json +1 -1
- package/template/AGENTS.md +8 -5
- package/template/Makefile +1 -1
- package/template/planning/PROTOCOL.md +6 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
3
|
```text
|
|
4
4
|
Investiga cambios recientes en ventas responsables y procesos comerciales para
|
|
@@ -15,4 +15,4 @@ no compres listas, envíes outreach, publiques, hagas commit ni push. Termina co
|
|
|
15
15
|
`make agent-evaluate AGENT=sales-representative`.
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Programar
|
|
18
|
+
Programar mensualmente en cada instalación.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
3
|
```text
|
|
4
4
|
Investiga cambios recientes en Security Engineering para mantener
|
|
@@ -16,4 +16,4 @@ hagas commit ni push. Termina con
|
|
|
16
16
|
`make agent-evaluate AGENT=security-engineer`.
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
Programar
|
|
19
|
+
Programar mensualmente en cada instalación.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
3
|
```text
|
|
4
4
|
Investiga cambios recientes en Site Reliability Engineering para mantener
|
|
@@ -15,4 +15,4 @@ no ejecutes carga, caos, failover, publiques, hagas commit ni push. Termina con
|
|
|
15
15
|
`make agent-evaluate AGENT=site-reliability-engineer`.
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Programar
|
|
18
|
+
Programar mensualmente en cada instalación.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
3
|
```text
|
|
4
4
|
Investiga cambios recientes en Software Architecture para mantener
|
|
@@ -15,4 +15,4 @@ no generes migraciones, publiques, hagas commit ni push. Termina con
|
|
|
15
15
|
`make agent-evaluate AGENT=software-architect`.
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
Programar
|
|
18
|
+
Programar mensualmente en cada instalación.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Automatización de aprendizaje
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Mensual con Codex
|
|
4
4
|
|
|
5
5
|
Ejecutar `make agent-learn AGENT=solutions-engineer`. Completar el informe generado con novedades relevantes, versiones, aplicabilidad, evidencia primaria, impacto y recomendación. Investigar no autoriza cambiar `SKILL.md`, materiales, producto ni sistemas.
|
|
6
6
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
3
|
```text
|
|
4
4
|
Investiga cambios recientes en la práctica de liderazgo técnico —revisión y aprobación
|
|
@@ -22,4 +22,4 @@ apruebes, despliegues, hagas commit ni push, y no autorices gasto. Termina con
|
|
|
22
22
|
`make agent-evaluate AGENT=tech-lead`.
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
Programar
|
|
25
|
+
Programar mensualmente en cada instalación.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Automatización de aprendizaje
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Mensual con Codex
|
|
4
4
|
|
|
5
5
|
Ejecutar `make agent-learn AGENT=technical-program-manager`. Registrar fuentes primarias, estándar/versión/estado, fit organizacional, evidencia de outcome y validación de owners. Investigar no autoriza cambiar planes, compromisos o sistemas.
|
|
6
6
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
3
|
```text
|
|
4
4
|
Investiga cambios recientes en tesorería corporativa, liquidez y pagos salientes para mantener
|
|
@@ -17,4 +17,4 @@ no actualices SKILL.md, código ni planificación; no publiques, hagas commit ni
|
|
|
17
17
|
con `make agent-evaluate AGENT=treasury-analyst`.
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Programar
|
|
20
|
+
Programar mensualmente en cada instalación.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
|
-
Configurar una automatización
|
|
3
|
+
Configurar una automatización mensual con este prompt:
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
6
|
Investiga cambios recientes en UI Design para mantener agents/roles/system/ui-designer.
|
|
@@ -16,4 +16,4 @@ permiso, publiques, hagas commit ni push. Termina ejecutando
|
|
|
16
16
|
`make agent-evaluate AGENT=ui-designer`.
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
La frecuencia recomendada es
|
|
19
|
+
La frecuencia recomendada es mensual; cada instalación define el horario.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
|
-
Configurar una automatización
|
|
3
|
+
Configurar una automatización mensual en la raíz del repositorio con este prompt:
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
6
|
Investiga cambios recientes en User Research para mantener el agente
|
|
@@ -19,4 +19,4 @@ contactes participantes, accedas a datos personales, publiques, hagas commit ni
|
|
|
19
19
|
push. Termina ejecutando `make agent-evaluate AGENT=user-researcher`.
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
La frecuencia recomendada es
|
|
22
|
+
La frecuencia recomendada es mensual; cada instalación elige día y hora.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Automatización
|
|
1
|
+
# Automatización mensual del aprendizaje
|
|
2
2
|
|
|
3
|
-
Configurar una automatización
|
|
3
|
+
Configurar una automatización mensual con este prompt:
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
6
|
Investiga cambios recientes en UX Design para mantener agents/roles/system/ux-designer.
|
|
@@ -15,4 +15,4 @@ referencias, evaluaciones, fuentes ni planificación; no publiques, hagas commit
|
|
|
15
15
|
ni push. Termina con `make agent-evaluate AGENT=ux-designer`.
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
La frecuencia recomendada es
|
|
18
|
+
La frecuencia recomendada es mensual; cada instalación define el horario.
|
|
@@ -12,7 +12,8 @@ Los hooks convierten invariantes comprobables en gates mecánicos. La base recom
|
|
|
12
12
|
- cierre de sesión con planning o integraciones inválidas;
|
|
13
13
|
- modificación del protocolo durante una tarea de producto.
|
|
14
14
|
- escrituras fuera de las raíces declaradas del workspace;
|
|
15
|
-
- reescritura de migraciones y SQL
|
|
15
|
+
- reescritura de migraciones y borrado destructivo —SQL o la API del ORM— en la parte que aplica, no en su
|
|
16
|
+
reversión; qué carpetas y extensiones son migraciones lo declara `migrations` en `ops.config.json`;
|
|
16
17
|
- publicación, instalaciones globales y drift entre manifests y lockfiles.
|
|
17
18
|
|
|
18
19
|
La lógica portable vive en `engine/hooks/run.js`; los `guard-*.sh` son entradas ejecutables comunes. Cada
|
|
@@ -74,16 +75,20 @@ guards lo leen:
|
|
|
74
75
|
|
|
75
76
|
- lo que la persona **pidió nombrándolo** pasa: «leé el `.env`» autoriza leer el `.env`; «no toques el
|
|
76
77
|
`.env`» no, y tampoco una pregunta o un comentario que sólo lo nombra —«¿qué tiene el `.env`?»—;
|
|
77
|
-
- lo que se frenó sin que lo nombrara queda anotado, y
|
|
78
|
-
exactamente eso;
|
|
78
|
+
- lo que se frenó sin que lo nombrara queda anotado, y su confirmación en el mensaje siguiente —con las
|
|
79
|
+
palabras que sea— aprueba exactamente eso. Si ese mensaje niega, frena o pregunta, no aprueba nada; y lo
|
|
80
|
+
que se frenó mientras ella decía que no, no queda esperando;
|
|
79
81
|
- lo que un guard dejó pasar porque ella lo pidió sigue valiendo mientras dure la sesión, **salvo en los
|
|
80
82
|
gates de un commit** —`governance`, `verify` y `dependencies`—, que preguntan cada vez: ahí vale lo que
|
|
81
|
-
pidió el mensaje en curso o
|
|
83
|
+
pidió el mensaje en curso o su confirmación al bloqueo, igual que para publicar;
|
|
82
84
|
- `plan-first` no aplica: el plan es del trabajo que va por tareas.
|
|
83
85
|
|
|
84
86
|
No cuenta cuando no hay persona —CI, o un aviso del runner como el de un subagente que terminó—, cuando lo
|
|
85
87
|
que pidió es un recorrido de Cauce (`/autobuild`, `$flow`…), ni en la llamada de un subagente, que Claude
|
|
86
|
-
marca con `agent_id
|
|
88
|
+
marca con `agent_id`: a un subagente no le llega lo que ella pidió ni lo que se le concedió antes. Sí le
|
|
89
|
+
llega su confirmación a un bloqueo, que nombra exactamente lo frenado: el bloqueo de un subagente le pide
|
|
90
|
+
devolverlo a quien lo lanzó para que se lo pregunte, y lo que ella confirme pasa aunque lo reintente otro
|
|
91
|
+
subagente. En Claude y Codex cada llamada trae el identificador del mensaje que la originó;
|
|
87
92
|
Gemini no lo manda, y ahí vale el último mensaje. El registro vive en el temporal del sistema, uno por
|
|
88
93
|
sesión, y los guards de límites lo cuidan junto con `planning/.ops-approval`: el registro no lo escribe
|
|
89
94
|
nunca una herramienta, y en la aprobación sólo entran las líneas que la persona nombró en ese mismo
|
|
@@ -19,7 +19,10 @@ usuario y no por workspace. De ahí salen tres consecuencias que conviene tener
|
|
|
19
19
|
- Registrar desde otro proyecto reemplaza el plugin del anterior.
|
|
20
20
|
|
|
21
21
|
Volvé a registrar cada vez que `automation install` cambie el wiring o el proyecto se mueva de lugar;
|
|
22
|
-
`agy plugin validate .agents/plugins/cauce` comprueba la copia del repo antes de registrarla.
|
|
22
|
+
`agy plugin validate .agents/plugins/cauce` comprueba la copia del repo antes de registrarla. Si te
|
|
23
|
+
olvidás, `automation doctor` lo dice: compara la copia registrada con la del workspace y la lanza como
|
|
24
|
+
la lanza `agy`, desde su carpeta, así que una copia de otro proyecto o de otra versión es un error con el
|
|
25
|
+
comando que lo corrige. Al instalar es una advertencia, porque registrar es justo el paso que sigue.
|
|
23
26
|
|
|
24
27
|
El plugin aporta hooks `PreToolUse` y `Stop`, reglas Cauce y los cinco recorridos —`/cauce:onboard`,
|
|
25
28
|
`/cauce:flow`, `/cauce:autobuild`, `/cauce:integration-sync` y `/cauce:integration-promote`— más el
|
|
@@ -4,13 +4,6 @@
|
|
|
4
4
|
const fs = require('node:fs')
|
|
5
5
|
const path = require('node:path')
|
|
6
6
|
|
|
7
|
-
function readInput() {
|
|
8
|
-
try {
|
|
9
|
-
const raw = fs.readFileSync(0, 'utf8')
|
|
10
|
-
return raw.trim() ? JSON.parse(raw) : {}
|
|
11
|
-
} catch { return {} }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
7
|
// Dónde quedó la raíz ops respecto de la carpeta que Antigravity abre. Lo completa
|
|
15
8
|
// `automation install`, que es el único momento en que se sabe: en modo sidecar la raíz ops es un
|
|
16
9
|
// hermano de los repos de producto, y ninguna búsqueda hacia arriba la encuentra. Sin esto el bridge
|
|
@@ -78,18 +71,39 @@ function findRoot(input, markers = MARKERS) {
|
|
|
78
71
|
throw new Error('No se encontró una raíz Cauce desde el workspace de Antigravity.')
|
|
79
72
|
}
|
|
80
73
|
|
|
81
|
-
function
|
|
74
|
+
function engineAt(root, file) {
|
|
82
75
|
const candidates = [
|
|
83
|
-
path.join(root, 'node_modules', '@ingeniomaps', 'cauce', 'engine', 'hooks',
|
|
84
|
-
path.join(root, 'engine', 'hooks',
|
|
85
|
-
path.join(root, '..', 'node_modules', '@ingeniomaps', 'cauce', 'engine', 'hooks',
|
|
76
|
+
path.join(root, 'node_modules', '@ingeniomaps', 'cauce', 'engine', 'hooks', file),
|
|
77
|
+
path.join(root, 'engine', 'hooks', file),
|
|
78
|
+
path.join(root, '..', 'node_modules', '@ingeniomaps', 'cauce', 'engine', 'hooks', file),
|
|
86
79
|
]
|
|
87
80
|
// Copia de `packagePath`; su porqué vive allá. Son tres los que la repiten y el motor los nombra.
|
|
88
|
-
|
|
81
|
+
return candidates.find(fs.existsSync) || ''
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function runtimeAt(root) {
|
|
85
|
+
const runtime = engineAt(root, 'run.js')
|
|
89
86
|
if (!runtime) throw new Error('No se encontró el runtime engine/hooks/run.js.')
|
|
90
87
|
return require(runtime)
|
|
91
88
|
}
|
|
92
89
|
|
|
90
|
+
// La entrada se lee con el lector del motor y no con uno propio: el puente tenía su copia, y la copia se
|
|
91
|
+
// colgaba con stdin abierto y convertía un JSON ilegible en `allow` (caso 198). Lo que no se puede usar para
|
|
92
|
+
// encontrarlo es la entrada misma, que todavía no se leyó: se busca como `findRoot` sin entrada —la raíz que
|
|
93
|
+
// `install` dejó escrita y, si no resuelve, desde donde corre el puente—. Sólo la declarada dejaba sin
|
|
94
|
+
// lector, negando cada llamada, a un proyecto movido que los guards sí encontraban. Sin ninguna, se niega.
|
|
95
|
+
function inputReader(markers = MARKERS) {
|
|
96
|
+
let root = ''
|
|
97
|
+
try { root = findRoot({}, markers) } catch { /* sin raíz no hay motor: lo dice el error de abajo */ }
|
|
98
|
+
const reader = root && engineAt(root, 'input.js')
|
|
99
|
+
if (!reader) {
|
|
100
|
+
throw new Error('No se encontró engine/hooks/input.js, con el que se lee la entrada, ni en la raíz que '
|
|
101
|
+
+ `automation install declaró (${declaredRoot(markers) || 'ninguna'}) ni desde ${process.cwd()}. `
|
|
102
|
+
+ 'Reinstalá el runner.')
|
|
103
|
+
}
|
|
104
|
+
return require(reader)
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
// La carpeta que el runner abrió, deducida de la raíz: en sidecar la raíz ops es su hija, y en modo
|
|
94
108
|
// embebido son la misma.
|
|
95
109
|
function workspaceOf(root, markers) {
|
|
@@ -134,6 +148,47 @@ function respond(value) {
|
|
|
134
148
|
process.stdout.write(`${JSON.stringify(value)}\n`)
|
|
135
149
|
}
|
|
136
150
|
|
|
151
|
+
function refusal(event, message, blocking) {
|
|
152
|
+
const reason = `Cauce: ${message}`
|
|
153
|
+
if (event !== 'stop') return { decision: 'deny', reason }
|
|
154
|
+
// Un guard que bloquea marca su error con `blocked` (engine/hooks/run.js); cualquier otro es que el
|
|
155
|
+
// puente no llegó a juzgar nada. En `stop` los dos devolvían `continue`, y eso ata al agente: la
|
|
156
|
+
// raíz que no resuelve no se arregla sola, así que cada intento de cerrar repite el mismo error.
|
|
157
|
+
// El bloqueo sigue dando `continue` —es el mecanismo funcionando—; la falla deja cerrar y avisa.
|
|
158
|
+
return blocking ? { decision: 'continue', reason } : { decision: 'stop', reason }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Lo que cada evento tiene que traer para que sus guards juzguen algo. `normalize` lee campos por nombre y
|
|
162
|
+
// convierte en `''` el que no encuentra, así que una llamada con otra forma —un campo renombrado en una
|
|
163
|
+
// actualización de Antigravity— llegaba vacía a los guards, ninguno frenaba y el puente respondía `allow`:
|
|
164
|
+
// todos los guards apagados sin rastro (caso 200). Cerrado por defecto: sin lo que el evento juzga, se niega
|
|
165
|
+
// y se dice qué llegó, que es lo que hace falta para enseñarle la forma nueva a `normalize`.
|
|
166
|
+
//
|
|
167
|
+
// Una entrada vacía no es una llamada con otra forma: no describe ninguna, y es como se invoca a mano, con
|
|
168
|
+
// `OPS_HOOK_COMMAND` u `OPS_HOOK_FILE` (caso 198).
|
|
169
|
+
const DESCRIBED_BY = {
|
|
170
|
+
'pre-shell': { field: 'command', names: 'CommandLine' },
|
|
171
|
+
'pre-files': { field: 'file_path', names: 'TargetFile ni AbsolutePath' },
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Un archivo sin su contenido tampoco se puede juzgar: los guards que miran qué se escribe —secretos,
|
|
175
|
+
// migraciones— verían un texto vacío. Basta que el campo esté; vacío es un archivo vacío.
|
|
176
|
+
const CONTENT_FIELDS = ['CodeContent', 'ReplacementContent', 'ReplacementChunks']
|
|
177
|
+
|
|
178
|
+
function undescribed(event, input, normalized) {
|
|
179
|
+
const need = DESCRIBED_BY[event]
|
|
180
|
+
if (!need || !Object.keys(input).length) return ''
|
|
181
|
+
const fields = (input.toolCall && input.toolCall.args) || {}
|
|
182
|
+
const args = Object.keys(fields)
|
|
183
|
+
const missing = !normalized.tool_input[need.field] ? need.names
|
|
184
|
+
: event === 'pre-files' && !CONTENT_FIELDS.some((field) => field in fields)
|
|
185
|
+
? 'CodeContent, ReplacementContent ni ReplacementChunks' : ''
|
|
186
|
+
if (!missing) return ''
|
|
187
|
+
const received = args.length ? `toolCall.args trae ${args.join(', ')}` : `llegó ${Object.keys(input).join(', ')}`
|
|
188
|
+
return `la llamada no trae ${missing}, así que no hay nada que juzgar y no se autoriza (${received}). Si `
|
|
189
|
+
+ 'Antigravity cambió el formato de sus llamadas, el puente tiene que aprenderlo en normalize().'
|
|
190
|
+
}
|
|
191
|
+
|
|
137
192
|
function evaluate(event, input) {
|
|
138
193
|
try {
|
|
139
194
|
const root = findRoot(input)
|
|
@@ -141,23 +196,30 @@ function evaluate(event, input) {
|
|
|
141
196
|
const hooks = runtimeAt(root)
|
|
142
197
|
const normalized = normalize(input, root)
|
|
143
198
|
if (!hooks.hookGroups[event]) throw new Error(`Evento Antigravity desconocido: ${event || '(vacío)'}`)
|
|
199
|
+
const missing = undescribed(event, input, normalized)
|
|
200
|
+
if (missing) throw new Error(missing)
|
|
144
201
|
hooks.executeAll([event], normalized)
|
|
145
202
|
return event === 'stop' ? { decision: 'stop' } : { decision: 'allow' }
|
|
146
203
|
} catch (error) {
|
|
147
|
-
|
|
148
|
-
if (event !== 'stop') return { decision: 'deny', reason }
|
|
149
|
-
// Un guard que bloquea marca su error con `blocked` (engine/hooks/run.js); cualquier otro es que el
|
|
150
|
-
// puente no llegó a juzgar nada. En `stop` los dos devolvían `continue`, y eso ata al agente: la
|
|
151
|
-
// raíz que no resuelve no se arregla sola, así que cada intento de cerrar repite el mismo error.
|
|
152
|
-
// El bloqueo sigue dando `continue` —es el mecanismo funcionando—; la falla deja cerrar y avisa.
|
|
153
|
-
return error.blocked ? { decision: 'continue', reason } : { decision: 'stop', reason }
|
|
204
|
+
return refusal(event, error.message, error.blocked)
|
|
154
205
|
}
|
|
155
206
|
}
|
|
156
207
|
|
|
157
|
-
function main() {
|
|
158
|
-
|
|
208
|
+
async function main(event = process.argv[2]) {
|
|
209
|
+
let input
|
|
210
|
+
try {
|
|
211
|
+
const engine = inputReader()
|
|
212
|
+
const usage = 'pasale el JSON de Antigravity —printf \'%s\' '
|
|
213
|
+
+ `'{"toolCall":{"args":{"CommandLine":"…"}}}' | node hook.js ${event || '<evento>'}—`
|
|
214
|
+
input = await engine.readInput(process.stdin, engine.FIRST_BYTE_MS, usage)
|
|
215
|
+
} catch (error) {
|
|
216
|
+
// El lector del motor marca `blocked` lo que no pudo leer, porque para un guard eso es bloquear. Acá
|
|
217
|
+
// es el puente sin nada que juzgar, y en `stop` eso deja cerrar: reintentar no arregla la entrada.
|
|
218
|
+
return respond(refusal(event, error.message, false))
|
|
219
|
+
}
|
|
220
|
+
respond(evaluate(event, input))
|
|
159
221
|
}
|
|
160
222
|
|
|
161
223
|
if (require.main === module) main()
|
|
162
224
|
|
|
163
|
-
module.exports = { evaluate, findRoot, normalize }
|
|
225
|
+
module.exports = { evaluate, findRoot, normalize, inputReader }
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Cómo se lee una aceptación, compartido por las dos puntas que la juzgan: `check`, que avisa sobre la
|
|
2
|
+
// cola, y `autobuild`, que la manda a Verify. Vive acá y no en el motor porque el recorrido no puede hacer
|
|
3
|
+
// `require` —se renderiza con `{{INCLUDE:}}`— y el motor sí puede leer este archivo: lo carga
|
|
4
|
+
// `engine/planning/acceptance.js`. Escrito dos veces, una copia dejaba de reconocer lo que la otra pedía
|
|
5
|
+
// escribir, que es exactamente el caso 195: `check` ofrecía una marca que el recorrido no conocía.
|
|
6
|
+
|
|
7
|
+
// Una condición por tramo separado con `;`, el grano con el que Verify contrasta —su `uncovered` enumera
|
|
8
|
+
// criterios— y con el que `check` avisa.
|
|
9
|
+
const acceptanceConditions = (acceptance) => String(acceptance || '').split(';')
|
|
10
|
+
.map((one) => one.trim()).filter(Boolean)
|
|
11
|
+
|
|
12
|
+
// La salida explícita, con la forma que el repositorio ya usa dos veces: `(sin partir: …)` para el umbral
|
|
13
|
+
// de R17 y `n/a — razón` para `tests:` y `commit:`. Acá vale lo mismo que allá —«como lleva su razón
|
|
14
|
+
// escrita se lee en el propio artefacto sin que nadie la cruce»— y por eso no se intenta adivinar si la
|
|
15
|
+
// prosa excluye a Verify. Adivinarlo es lo que no se puede: la única aceptación real que nombra el commit
|
|
16
|
+
// lo hace justamente para decir que no es condición de Verify, y cualquier lista de frases que la
|
|
17
|
+
// reconociera enseñaría a escribir esa frase exacta para silenciar el aviso.
|
|
18
|
+
const OUT_OF_VERIFY = /\(fuera de verify:\s*[^)]+\)/i
|
|
19
|
+
|
|
20
|
+
// Lo que no se ejecuta, y por eso lo único que un criterio `no-surface` puede haber producido (caso 189).
|
|
21
|
+
// Es la lista a favor y no la de lo ejecutable a propósito (R27): un `.sql` de migración, un workflow en
|
|
22
|
+
// YAML, un `Dockerfile`, un `Makefile` o un `.json` de configuración se ejecutan sin parecer código, y una
|
|
23
|
+
// lista de lo ejecutable dejaría afuera lo que venga después. Ampliarla es un cambio con su razón al lado.
|
|
24
|
+
// Las imágenes entraron porque un ADR suele traer su diagrama, y sin ellas ese commit contaba como código.
|
|
25
|
+
// Lo que no tiene extensión sigue contando como ejecutable: `Makefile` y `Dockerfile` no la tienen.
|
|
26
|
+
const NON_EXECUTABLE = ['.md', '.txt', '.adoc', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Convierte la recomendación de los informes en el cambio concreto que una persona puede aprobar.
|
|
2
2
|
//
|
|
3
|
-
// `learn --proposal` consolida qué recomendaron los informes de
|
|
3
|
+
// `learn --proposal` consolida qué recomendaron los informes de investigación, pero deja «Cambio
|
|
4
4
|
// propuesto: por definir». Eso no es aprobable: nadie firma una intención. Este recorrido escribe el
|
|
5
5
|
// texto exacto que habría que agregar, archivo por archivo, y lo contrasta contra los casos
|
|
6
6
|
// adversariales vigentes antes de proponerlo.
|
|
@@ -70,7 +70,7 @@ phase('Proponer')
|
|
|
70
70
|
|
|
71
71
|
const proposal = await agent(
|
|
72
72
|
`Sos quien mantiene el cargo ${AGENT}. La propuesta ${context.proposal} consolidó lo que ` +
|
|
73
|
-
`recomendaron los informes
|
|
73
|
+
`recomendaron los informes de investigación, pero le falta lo único que una persona puede aprobar: el ` +
|
|
74
74
|
`cambio concreto.\n\n` +
|
|
75
75
|
`Leé los informes citados en su sección «Hallazgos», el SKILL.md del cargo, ` +
|
|
76
76
|
`${context.dir}/learning/sources.yaml, ${context.dir}/evaluations/expected-behaviors.yaml y sus ` +
|