@ingeniomaps/cauce 0.6.0 → 0.7.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 +32 -0
- package/automatization/runners/antigravity/hook.js +15 -0
- package/automatization/runners/antigravity/manifest.json +9 -1
- package/automatization/workflows/README.md +2 -2
- package/automatization/workflows/autobuild.js +4 -4
- package/automatization/workflows/integrations/README.md +2 -2
- package/automatization/workflows/integrations/promote.js +10 -7
- package/automatization/workflows/integrations/sync.js +8 -6
- package/automatization/workflows/team.js +7 -7
- package/engine/automation/index.js +17 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,38 @@ esa operación sea confiable en vez de sólo cómoda: acá se lee qué cambió a
|
|
|
8
8
|
un cambio en el protocolo, en las reglas del sistema o en un guard es visible para el usuario y sube
|
|
9
9
|
minor aunque no toque una sola línea de código.
|
|
10
10
|
|
|
11
|
+
## [0.7.0] - 2026-08-15
|
|
12
|
+
|
|
13
|
+
### Corregido
|
|
14
|
+
|
|
15
|
+
- **Los cuatro workflows reventaban en su primera línea y nunca habían corrido.** Resolvían su raíz
|
|
16
|
+
con `process.env`, y el runtime de workflows es un sandbox que no expone `process`: `ReferenceError`
|
|
17
|
+
antes de ejecutar nada. `/team` y `/autobuild` —el centro del producto— estaban muertos, y los tests
|
|
18
|
+
no lo veían porque leían los archivos como texto en vez de ejecutarlos.
|
|
19
|
+
|
|
20
|
+
La raíz ahora viaja escrita en el archivo, que es lo que `automation install` ya sabía completar, y
|
|
21
|
+
es relativa a donde se abre la herramienta.
|
|
22
|
+
|
|
23
|
+
### Cambiado
|
|
24
|
+
|
|
25
|
+
- Los workflows de integración se invocan con argumentos en vez de variables de entorno, que tampoco
|
|
26
|
+
existen ahí: `/integration-sync jira` y `/integration-promote jira KEY-123`.
|
|
27
|
+
- Un test comprueba que ningún workflow use `process`, `require`, `Date.now` ni `Math.random`. El
|
|
28
|
+
sandbox los prohíbe, y usarlos no falla en una rama rara: impide que el archivo arranque.
|
|
29
|
+
|
|
30
|
+
## [0.6.1] - 2026-08-15
|
|
31
|
+
|
|
32
|
+
### Corregido
|
|
33
|
+
|
|
34
|
+
- **El bridge de Antigravity negaba cada llamada a herramienta.** Resolvía la raíz ops subiendo por el
|
|
35
|
+
árbol, y en sidecar es un *hermano* de los repos de producto: no la encontraba y, como falla cerrado,
|
|
36
|
+
bloqueaba todo. Ahora `automation install` le deja escrito dónde quedó, con el recorrido hacia arriba
|
|
37
|
+
como respaldo.
|
|
38
|
+
- **`automation install antigravity` copiaba el plugin y lo dejaba inerte.** Antigravity exige un
|
|
39
|
+
registro explícito —`agy plugin install`—, así que los archivos quedaban en su lugar, `doctor` daba
|
|
40
|
+
verde y no se ejecutaba nada. `install` ahora dice el comando exacto y `doctor` avisa si falta, sin
|
|
41
|
+
tocar por su cuenta la configuración global del usuario.
|
|
42
|
+
|
|
11
43
|
## [0.6.0] - 2026-08-15
|
|
12
44
|
|
|
13
45
|
### Cambiado
|
|
@@ -11,7 +11,22 @@ function readInput() {
|
|
|
11
11
|
} catch { return {} }
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// Dónde quedó la raíz ops respecto de la carpeta que Antigravity abre. Lo completa
|
|
15
|
+
// `automation install`, que es el único momento en que se sabe: en modo sidecar la raíz ops es un
|
|
16
|
+
// hermano de los repos de producto, y ninguna búsqueda hacia arriba la encuentra. Sin esto el bridge
|
|
17
|
+
// no hallaba `ops.config.json` y, como falla cerrado, negaba cada llamada a herramienta.
|
|
18
|
+
const OPS_DIR = '{{OPS_DIR}}'
|
|
19
|
+
|
|
20
|
+
function declaredRoot() {
|
|
21
|
+
// El plugin vive en <raíz-de-instalación>/.agents/plugins/cauce/.
|
|
22
|
+
const installed = path.resolve(__dirname, '..', '..', '..')
|
|
23
|
+
const root = OPS_DIR.startsWith('{{') ? installed : path.join(installed, OPS_DIR)
|
|
24
|
+
return fs.existsSync(path.join(root, 'ops.config.json')) ? root : ''
|
|
25
|
+
}
|
|
26
|
+
|
|
14
27
|
function findRoot(input) {
|
|
28
|
+
const declared = declaredRoot()
|
|
29
|
+
if (declared) return declared
|
|
15
30
|
const args = input.toolCall && input.toolCall.args || {}
|
|
16
31
|
const starts = [args.Cwd, process.cwd(), ...(input.workspacePaths || [])].filter(Boolean)
|
|
17
32
|
for (const start of starts) {
|
|
@@ -48,5 +48,13 @@
|
|
|
48
48
|
"checkpointing": false,
|
|
49
49
|
"nativeSkills": true
|
|
50
50
|
},
|
|
51
|
-
"roleSkills": ".agents/plugins/cauce/skills"
|
|
51
|
+
"roleSkills": ".agents/plugins/cauce/skills",
|
|
52
|
+
"activation": {
|
|
53
|
+
"hint": "agy plugin install .agents/plugins/cauce",
|
|
54
|
+
"verify": [
|
|
55
|
+
"plugin",
|
|
56
|
+
"list"
|
|
57
|
+
],
|
|
58
|
+
"expect": "cauce"
|
|
59
|
+
}
|
|
52
60
|
}
|
|
@@ -28,8 +28,8 @@ para revisión humana. `integrations/promote.js` exige proveedor, clave y un dra
|
|
|
28
28
|
el sistema remoto; Jira es actualmente el primer adaptador del contrato general.
|
|
29
29
|
|
|
30
30
|
```bash
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/integration-sync jira
|
|
32
|
+
/integration-promote jira KEY-123
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## Aprendizaje de agentes
|
|
@@ -10,10 +10,10 @@ export const meta = {
|
|
|
10
10
|
].map((title) => ({ title, detail: `Fase ${title} del protocolo agnóstico` })),
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// El prefijo lo completa `automation install
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
// El prefijo lo completa `automation install`. No puede venir del entorno: el runtime de workflows no
|
|
14
|
+
// expone `process`, así que leerlo de ahí reventaba el archivo entero en su primera línea. Viaja
|
|
15
|
+
// escrito, relativo a la carpeta donde se abre la herramienta, que es el cwd de los agentes.
|
|
16
|
+
const ROOT = '{{OPS_DIR}}'.replace(/\/+$/, '') || '.'
|
|
17
17
|
const CONFIG = `${ROOT}/ops.config.json`
|
|
18
18
|
const P = `${ROOT}/planning`
|
|
19
19
|
const BACKLOG = `${P}/BACKLOG.md`
|
|
@@ -9,6 +9,6 @@ remoto → sync → staging → revisión humana → promote → planning
|
|
|
9
9
|
- `sync.js`: valida y refresca staging sin promover ni escribir remoto.
|
|
10
10
|
- `promote.js`: materializa localmente un candidato cuyo draft está `ready`.
|
|
11
11
|
|
|
12
|
-
El proveedor se
|
|
13
|
-
|
|
12
|
+
El proveedor se pasa como argumento —`/integration-sync jira`—; `promote` requiere además la clave
|
|
13
|
+
remota: `/integration-promote jira KEY-123`. La implementación particular de Jira vive en `engine/integrations/providers/jira.js`,
|
|
14
14
|
no en estos workflows.
|
|
@@ -10,12 +10,15 @@ export const meta = {
|
|
|
10
10
|
],
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// El prefijo lo completa `automation install
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
13
|
+
// El prefijo lo completa `automation install`. No puede venir del entorno: el runtime de workflows no
|
|
14
|
+
// expone `process`, así que leerlo de ahí reventaba el archivo entero en su primera línea. Viaja
|
|
15
|
+
// escrito, relativo a la carpeta donde se abre la herramienta, que es el cwd de los agentes.
|
|
16
|
+
const ROOT = '{{OPS_DIR}}'.replace(/\/+$/, '') || '.'
|
|
17
|
+
// `/integration-promote jira KEY-123` o `{"provider": "jira", "key": "KEY-123"}`.
|
|
18
|
+
const parts = typeof args === 'string' ? args.trim().split(/\s+/) : []
|
|
19
|
+
const input = typeof args === 'string' ? { provider: parts[0], key: parts[1] } : (args || {})
|
|
20
|
+
const PROVIDER = String(input.provider || '').trim()
|
|
21
|
+
const KEY = String(input.key || '').trim()
|
|
19
22
|
const RESULT = {
|
|
20
23
|
type: 'object', additionalProperties: false, required: ['passed', 'provider', 'key', 'details'],
|
|
21
24
|
properties: { passed: { type: 'boolean' }, provider: { type: 'string' }, key: { type: 'string' }, details: { type: 'string' }, kind: { type: 'string' } },
|
|
@@ -24,7 +27,7 @@ const RESULT = {
|
|
|
24
27
|
phase('Preflight')
|
|
25
28
|
const result = await agent(
|
|
26
29
|
`Read ${ROOT}/integrations/README.md, integrations config, the provider contract and planning/PROTOCOL.md. ` +
|
|
27
|
-
`
|
|
30
|
+
`The provider is ${JSON.stringify(PROVIDER)} and the remote key ${JSON.stringify(KEY)}; both are required. ` +
|
|
28
31
|
`Run integration check. Inspect only that candidate's draft and snapshot; stop unless draft state is ready and ` +
|
|
29
32
|
`acceptance, hierarchy and service mapping are concrete. Never call or write the remote provider.\n\n` +
|
|
30
33
|
`If valid, enter Promote and run "node tools/ops.js integration promote ${ROOT} ${PROVIDER} ${KEY}" exactly once. ` +
|
|
@@ -10,11 +10,13 @@ export const meta = {
|
|
|
10
10
|
],
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
// El prefijo lo completa `automation install
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
// El prefijo lo completa `automation install`. No puede venir del entorno: el runtime de workflows no
|
|
14
|
+
// expone `process`, así que leerlo de ahí reventaba el archivo entero en su primera línea. Viaja
|
|
15
|
+
// escrito, relativo a la carpeta donde se abre la herramienta, que es el cwd de los agentes.
|
|
16
|
+
const ROOT = '{{OPS_DIR}}'.replace(/\/+$/, '') || '.'
|
|
17
|
+
// `/integration-sync jira` o `{"provider": "jira"}`: sin entorno, el argumento es la única entrada.
|
|
18
|
+
const input = typeof args === 'string' ? { provider: args } : (args || {})
|
|
19
|
+
const REQUESTED = String(input.provider || '').trim()
|
|
18
20
|
const RESULT = {
|
|
19
21
|
type: 'object', additionalProperties: false, required: ['passed', 'provider', 'details'],
|
|
20
22
|
properties: {
|
|
@@ -26,7 +28,7 @@ const RESULT = {
|
|
|
26
28
|
phase('Preflight')
|
|
27
29
|
const result = await agent(
|
|
28
30
|
`Read ${ROOT}/integrations/README.md, ${ROOT}/integrations/config.json and ${ROOT}/planning/PROTOCOL.md. ` +
|
|
29
|
-
`
|
|
31
|
+
`The requested provider is ${JSON.stringify(REQUESTED)}; if empty, continue only when exactly ` +
|
|
30
32
|
`one provider is enabled. Run "node tools/ops.js integration check ${ROOT} <provider>" and read its exit code. ` +
|
|
31
33
|
`Do not edit config and do not call a remote write operation.\n\n` +
|
|
32
34
|
`If green, enter Sync and run "node tools/ops.js integration sync ${ROOT} <provider>". The registered adapter owns ` +
|
|
@@ -15,10 +15,10 @@ export const meta = {
|
|
|
15
15
|
],
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
// El prefijo lo completa `automation install
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
// El prefijo lo completa `automation install`. No puede venir del entorno: el runtime de workflows no
|
|
19
|
+
// expone `process`, así que leerlo de ahí reventaba el archivo entero en su primera línea. Viaja
|
|
20
|
+
// escrito, relativo a la carpeta donde se abre la herramienta, que es el cwd de los agentes.
|
|
21
|
+
const ROOT = '{{OPS_DIR}}'.replace(/\/+$/, '') || '.'
|
|
22
22
|
const P = `${ROOT}/planning`
|
|
23
23
|
const ROADMAP = `${P}/roadmap`
|
|
24
24
|
const HUMAN = `${P}/HUMAN_ACTIONS.md`
|
|
@@ -34,9 +34,9 @@ const REPORTS = `${P}/reports`
|
|
|
34
34
|
// El prefijo se toma como candidato y se confirma más abajo contra los equipos que existen: si no es
|
|
35
35
|
// uno, el texto completo era la intención y nadie tuvo que aprenderse una sintaxis.
|
|
36
36
|
const input = typeof args === 'string' ? { intent: args } : (args || {})
|
|
37
|
-
const raw = String(input.intent ||
|
|
37
|
+
const raw = String(input.intent || '').trim()
|
|
38
38
|
const prefix = raw.match(/^([a-z][a-z0-9-]*)\s*:\s*(.+)$/s)
|
|
39
|
-
const CANDIDATE = String(input.team ||
|
|
39
|
+
const CANDIDATE = String(input.team || (prefix ? prefix[1] : '') || 'product-development')
|
|
40
40
|
const INTENT = (input.team || !prefix ? raw : prefix[2]).trim()
|
|
41
41
|
|
|
42
42
|
const MANIFEST = {
|
|
@@ -100,7 +100,7 @@ const resolved = await agent(
|
|
|
100
100
|
} }, label: 'team-resolve' },
|
|
101
101
|
)
|
|
102
102
|
if (!resolved) return stop('teams-unavailable', 'no se pudo listar los equipos')
|
|
103
|
-
if (!resolved.exists &&
|
|
103
|
+
if (!resolved.exists && input.team) {
|
|
104
104
|
return stop('equipo-inexistente', `${CANDIDATE} no existe. Disponibles: ${resolved.teams.join(', ')}`)
|
|
105
105
|
}
|
|
106
106
|
// El prefijo era parte de la intención, no un equipo: se recompone y sigue con el equipo por defecto.
|
|
@@ -182,6 +182,15 @@ function installRoleSkills(root, runner, output) {
|
|
|
182
182
|
return roles.length
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
+
// Runners que además de los archivos necesitan un registro propio para que el wiring cuente. Copiar
|
|
186
|
+
// y quedarse ahí deja un plugin inerte: los archivos están, `doctor` da verde y nada se ejecuta.
|
|
187
|
+
function activated(runner) {
|
|
188
|
+
if (!runner.activation) return true
|
|
189
|
+
const result = spawnSync(runner.command, runner.activation.verify, { encoding: 'utf8' })
|
|
190
|
+
if (result.status !== 0) return null
|
|
191
|
+
return `${result.stdout || ''}`.includes(runner.activation.expect)
|
|
192
|
+
}
|
|
193
|
+
|
|
185
194
|
function hasHooks(config) {
|
|
186
195
|
if (config.hooks && Object.keys(config.hooks).length) return true
|
|
187
196
|
const events = [
|
|
@@ -423,6 +432,10 @@ function doctor(root, name, output = console) {
|
|
|
423
432
|
['-c', 'command -v "$1" >/dev/null 2>&1', 'runner-doctor', runner.command],
|
|
424
433
|
)
|
|
425
434
|
if (executable.status !== 0) warnings.push(`${runner.command}: CLI no encontrado en PATH`)
|
|
435
|
+
else if (activated(runner) === false) {
|
|
436
|
+
warnings.push(`el plugin está copiado pero no registrado, así que no se ejecuta. `
|
|
437
|
+
+ `Corré desde ${paths.install}: ${runner.activation.hint}`)
|
|
438
|
+
}
|
|
426
439
|
for (const warning of warnings) output.warn(`⚠ ${name}: ${warning}`)
|
|
427
440
|
for (const error of errors) output.error(`✗ ${name}: ${error}`)
|
|
428
441
|
return { runner, errors, warnings }
|
|
@@ -516,6 +529,10 @@ function install(root, name, output = console, options = {}) {
|
|
|
516
529
|
}
|
|
517
530
|
}
|
|
518
531
|
installRoleSkills(root, runner, output)
|
|
532
|
+
if (runner.activation && activated(runner) !== true) {
|
|
533
|
+
output.log(` ${name}: falta registrarlo para que corra. Desde ${paths.install}:`)
|
|
534
|
+
output.log(` ${runner.activation.hint}`)
|
|
535
|
+
}
|
|
519
536
|
M.write(root, undefined, entregado)
|
|
520
537
|
return runner
|
|
521
538
|
}
|