@ingeniomaps/cauce 0.30.0 → 0.31.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/README.md +36 -6
- package/engine/automation/index.js +103 -0
- package/engine/cli/bootstrap.js +6 -2
- package/engine/cli/ops.js +21 -12
- package/package.json +1 -1
- package/template/Makefile +17 -1
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,38 @@ desde este repositorio no va, porque el que lee no puede actuar sobre eso. Cuand
|
|
|
14
14
|
unas pocas líneas casi siempre es porque cuenta cómo se descubrió el problema o por qué se eligió el
|
|
15
15
|
diseño — eso vive en el commit y en el código.
|
|
16
16
|
|
|
17
|
+
## [0.31.0] - 2026-08-18
|
|
18
|
+
|
|
19
|
+
### Añadido
|
|
20
|
+
|
|
21
|
+
- **`ops automation uninstall <ops-root> <runner>`: sacar el wiring sin llevarse lo tuyo.** Hasta ahora
|
|
22
|
+
desinstalar era borrar la carpeta ops y descubrir después que cada llamada de herramienta ejecuta un
|
|
23
|
+
guard que ya no existe; la otra salida —borrar `.claude/` entero— se lleva puesto lo que hayas puesto
|
|
24
|
+
vos. El comando quita lo que Cauce entregó **y sigue igual que como lo entregó**: sus guards de la
|
|
25
|
+
configuración del runner, sus workflows, sus punteros a cargos. Tus hooks, tus workflows y tus skills
|
|
26
|
+
quedan donde están, y un archivo del toolkit que hayas editado se conserva y aparece nombrado en la
|
|
27
|
+
salida, porque decidir sobre él es tuyo. La instancia no se toca: borrarla es una decisión aparte.
|
|
28
|
+
También como `make uninstall-claude` y sus equivalentes.
|
|
29
|
+
|
|
30
|
+
### Corregido
|
|
31
|
+
|
|
32
|
+
- **Una instancia dejaba de enterarse de que había versiones nuevas.** `init` fija la versión exacta del
|
|
33
|
+
motor, así que `npm update` no la mueve y `upgrade` compara contra el que está instalado: quien
|
|
34
|
+
actualizaba con `make upgrade` recibía «la instancia está al día» en todas las versiones siguientes, sin
|
|
35
|
+
nada que le dijera que la comparación era local. Ahora la salida nombra contra qué comparó y da el
|
|
36
|
+
comando que trae un motor nuevo, y `make upgrade` lo corre antes de aplicar.
|
|
37
|
+
|
|
38
|
+
Actualizar son tres pasos y el tercero sigue siendo aparte: `npm install --save-dev
|
|
39
|
+
@ingeniomaps/cauce@latest`, `ops upgrade .` y `ops automation install . <runner>`. Los workflows y las
|
|
40
|
+
skills viven en el runner, no en la instancia, y `upgrade` lo recuerda al terminar.
|
|
41
|
+
|
|
42
|
+
### Cambiado
|
|
43
|
+
|
|
44
|
+
- **`init` termina en un solo cierre, y sus opciones se leen como una selección.** Las tres líneas finales
|
|
45
|
+
—cada una con tono de última— pasaron a ser una con la acción concreta, y las opciones de runner e
|
|
46
|
+
integración van una por línea con el default marcado donde se mira: `5) ninguno ← Enter`, en vez de un
|
|
47
|
+
`[ninguno]` pegado al prompt.
|
|
48
|
+
|
|
17
49
|
## [0.30.0] - 2026-08-18
|
|
18
50
|
|
|
19
51
|
### Añadido
|
package/README.md
CHANGED
|
@@ -31,12 +31,21 @@ instala la dependencia, deja el wiring del runner puesto y valida la instancia a
|
|
|
31
31
|
|
|
32
32
|
```text
|
|
33
33
|
¿Con qué runner vas a trabajar?
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
|
|
35
|
+
1) claude
|
|
36
|
+
2) codex
|
|
37
|
+
3) gemini
|
|
38
|
+
4) antigravity
|
|
39
|
+
5) ninguno ← Enter
|
|
40
|
+
|
|
41
|
+
> 1
|
|
36
42
|
|
|
37
43
|
¿Habilitar alguna integración?
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
|
|
45
|
+
1) jira
|
|
46
|
+
2) ninguna ← Enter
|
|
47
|
+
|
|
48
|
+
>
|
|
40
49
|
|
|
41
50
|
· npm install (el motor viene de la dependencia)
|
|
42
51
|
✓ claude: adaptador operativo (0 advertencia(s))
|
|
@@ -57,7 +66,8 @@ este proyecto, hasta cubrir lo que haga falta de esto:
|
|
|
57
66
|
|
|
58
67
|
Mientras tanto, esto es lo que hay: apps/api, apps/web
|
|
59
68
|
|
|
60
|
-
Abrí claude
|
|
69
|
+
→ Abrí claude acá y contestale esa pregunta.
|
|
70
|
+
Con tus respuestas escribe organization/, el mapa real de AGENTS.md y la primera épica.
|
|
61
71
|
El ciclo empieza en ops/planning/FLOW.md.
|
|
62
72
|
```
|
|
63
73
|
|
|
@@ -190,6 +200,7 @@ Lee [template/planning/PROTOCOL.md](template/planning/PROTOCOL.md) para el contr
|
|
|
190
200
|
| `ops automation list-hooks <ops-root>` | Describe los guards portables disponibles. |
|
|
191
201
|
| `ops automation check <ops-root>` | Valida guards, permisos y configuraciones. |
|
|
192
202
|
| `ops automation install <ops-root> <runner>` | Instala el wiring de Claude, Codex, Antigravity o Gemini. |
|
|
203
|
+
| `ops automation uninstall <ops-root> <runner>` | Quita ese wiring y conserva lo que no escribió Cauce. |
|
|
193
204
|
| `ops automation doctor <ops-root> <runner>` | Diagnostica una instalación materializada. |
|
|
194
205
|
|
|
195
206
|
`ops --help` lista las banderas de cada uno. En un proyecto generado, `make help` muestra los atajos
|
|
@@ -230,7 +241,20 @@ y actualizar no exige resolver conflictos: se reemplaza `system/` entero y nada
|
|
|
230
241
|
y sobrevive, desactivar uno del toolkit es quitarlo de la configuración del runner, y editar uno
|
|
231
242
|
existente detiene el `upgrade` antes de pisarlo.
|
|
232
243
|
|
|
233
|
-
###
|
|
244
|
+
### Actualizar
|
|
245
|
+
|
|
246
|
+
Son tres pasos y `make upgrade` hace los dos primeros:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
npm install --save-dev @ingeniomaps/cauce@latest # trae el motor nuevo
|
|
250
|
+
node tools/ops.js upgrade . # aplica system/ y el runtime
|
|
251
|
+
node tools/ops.js automation install . claude # el wiring del runner
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
El primero no se puede saltear: `init` fija la versión exacta, así que `npm update` no la mueve y
|
|
255
|
+
`upgrade` compara contra el motor instalado —lo dice en su salida—. El tercero tampoco: los workflows y
|
|
256
|
+
las skills viven en el runner, no en la instancia, y `upgrade` no los toca. `upgrade` lo recuerda al
|
|
257
|
+
terminar.
|
|
234
258
|
|
|
235
259
|
Como `upgrade` reemplaza `system/` sin pedir confirmación, un cambio en el protocolo, en una regla del
|
|
236
260
|
sistema o en un guard es visible para el usuario y sube minor aunque no toque código. `upgrade` y
|
|
@@ -277,6 +301,12 @@ La instalación fusiona la configuración propia del runner y conserva las entra
|
|
|
277
301
|
reemplaza los guards que el propio toolkit había registrado sueltos por el grupo que ahora los cubre, y
|
|
278
302
|
lista cuáles quitó. Nada que no haya escrito el toolkit se toca.
|
|
279
303
|
|
|
304
|
+
Para sacarlo, `automation uninstall` quita exactamente lo que Cauce entregó y sigue igual que como lo
|
|
305
|
+
entregó: los guards de la configuración del runner, los workflows, los punteros a cargos. Lo que no
|
|
306
|
+
escribió —tus hooks, tus workflows, tus skills— queda donde está, y un archivo suyo que hayas editado se
|
|
307
|
+
conserva y se nombra en la salida. Borrar la carpeta ops sin esto deja al runner ejecutando guards que ya
|
|
308
|
+
no existen.
|
|
309
|
+
|
|
280
310
|
Qué comprueba cada guard, qué no puede comprobar y cómo se agrupan por evento está en
|
|
281
311
|
[automatization/hooks/README.md](automatization/hooks/README.md).
|
|
282
312
|
|
|
@@ -478,6 +478,108 @@ function deliveryState(recorded, name, resolved, prefix = '') {
|
|
|
478
478
|
return delivered && delivered === current ? 'desactualizado' : 'ajeno'
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
+
// Quita de una estructura de configuración exactamente lo que este adaptador habría puesto, y nada más.
|
|
482
|
+
// Es el inverso de `mergeConfig`: una entrada del usuario nunca coincide literalmente con la nuestra, así
|
|
483
|
+
// que sobrevive; una que editó tampoco coincide, y por eso se conserva y se avisa en vez de borrarse.
|
|
484
|
+
function unmergeConfig(current, incoming) {
|
|
485
|
+
if (Array.isArray(incoming)) {
|
|
486
|
+
if (!Array.isArray(current)) return current
|
|
487
|
+
const nuestras = new Set(incoming.map((value) => JSON.stringify(value)))
|
|
488
|
+
return current.filter((value) => !nuestras.has(JSON.stringify(value)))
|
|
489
|
+
}
|
|
490
|
+
if (incoming && typeof incoming === 'object') {
|
|
491
|
+
if (!current || typeof current !== 'object' || Array.isArray(current)) return current
|
|
492
|
+
const result = { ...current }
|
|
493
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
494
|
+
if (!(key in result)) continue
|
|
495
|
+
const limpio = unmergeConfig(result[key], value)
|
|
496
|
+
// Una clave que queda vacía por habernos ido no es del usuario: la creamos nosotros al instalar.
|
|
497
|
+
const vacia = limpio === undefined
|
|
498
|
+
|| (Array.isArray(limpio) && !limpio.length)
|
|
499
|
+
|| (limpio && typeof limpio === 'object' && !Array.isArray(limpio) && !Object.keys(limpio).length)
|
|
500
|
+
if (vacia) delete result[key]
|
|
501
|
+
else result[key] = limpio
|
|
502
|
+
}
|
|
503
|
+
return result
|
|
504
|
+
}
|
|
505
|
+
return JSON.stringify(current) === JSON.stringify(incoming) ? undefined : current
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Borra el archivo y, de paso, los directorios que quedaron vacíos por haberlo sacado. Nunca sube más
|
|
509
|
+
// allá del límite: `.claude/` puede tener cosas del usuario aunque `.claude/workflows/` quede vacío.
|
|
510
|
+
function removeFile(file, boundary) {
|
|
511
|
+
fs.rmSync(file, { force: true })
|
|
512
|
+
let dir = path.dirname(file)
|
|
513
|
+
while (dir.startsWith(boundary) && dir !== boundary) {
|
|
514
|
+
try { if (fs.readdirSync(dir).length) return } catch { return }
|
|
515
|
+
fs.rmdirSync(dir)
|
|
516
|
+
dir = path.dirname(dir)
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Saca el wiring de un runner dejando intacto lo que no escribimos nosotros.
|
|
521
|
+
//
|
|
522
|
+
// Existe porque desinstalar a mano es borrar `ops/` y descubrir después que cada llamada de herramienta
|
|
523
|
+
// ejecuta un guard que ya no está. Y porque la alternativa —borrar `.claude/` entero— se lleva puesto lo
|
|
524
|
+
// que el usuario haya puesto ahí, que es suyo y no tiene por qué desaparecer con el toolkit.
|
|
525
|
+
//
|
|
526
|
+
// La regla es una sola: se quita lo que Cauce entregó y sigue igual que como lo entregó. Un archivo con
|
|
527
|
+
// cambios propios se conserva y se nombra; decidir sobre él es de la persona, no de este comando.
|
|
528
|
+
function uninstall(root, name, output = console) {
|
|
529
|
+
if (O.mode(root) === 'toolkit') {
|
|
530
|
+
throw new Error('Acá se fabrica Cauce, no se lo consume.')
|
|
531
|
+
}
|
|
532
|
+
const runner = runnerManifest(root, name)
|
|
533
|
+
const paths = runnerPaths(root, name, runner)
|
|
534
|
+
const prefix = opsPrefix(root)
|
|
535
|
+
const recorded = M.readRunners(root)
|
|
536
|
+
const conservados = []
|
|
537
|
+
let quitados = 0
|
|
538
|
+
|
|
539
|
+
const items = [...(runner.instructions || []), ...(runner.artifacts || [])]
|
|
540
|
+
const entregado = { ...recorded }
|
|
541
|
+
for (const item of items) {
|
|
542
|
+
const resolved = { item, ...resolveItem(paths, root, name, item) }
|
|
543
|
+
const key = deliveryKey(name, item.target)
|
|
544
|
+
if (!fs.existsSync(resolved.target)) { delete entregado[key]; continue }
|
|
545
|
+
const situacion = deliveryState(recorded, name, resolved, prefix)
|
|
546
|
+
if (situacion === 'ajeno') { conservados.push(item.target); continue }
|
|
547
|
+
removeFile(resolved.target, paths.install)
|
|
548
|
+
delete entregado[key]
|
|
549
|
+
quitados += 1
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Los punteros a cargos no se registran uno por uno —son cuarenta y siete y se regeneran enteros—,
|
|
553
|
+
// así que se reconocen por contenido: sólo se va el que sigue siendo el que generamos.
|
|
554
|
+
if (runner.capabilities.nativeSkills && runner.roleSkills) {
|
|
555
|
+
const base = path.resolve(paths.install, runner.roleSkills)
|
|
556
|
+
for (const role of roleCatalog(root)) {
|
|
557
|
+
const file = path.join(base, role.slug, 'SKILL.md')
|
|
558
|
+
if (!fs.existsSync(file)) continue
|
|
559
|
+
if (M.digest(file) !== M.digestText(roleSkill(role))) {
|
|
560
|
+
conservados.push(path.relative(paths.install, file))
|
|
561
|
+
continue
|
|
562
|
+
}
|
|
563
|
+
removeFile(file, paths.install)
|
|
564
|
+
quitados += 1
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
if (fs.existsSync(paths.configTarget)) {
|
|
569
|
+
const current = JSON.parse(fs.readFileSync(paths.configTarget, 'utf8'))
|
|
570
|
+
const limpio = unmergeConfig(current, runnerConfig(paths, root))
|
|
571
|
+
if (limpio && Object.keys(limpio).length) F.atomicWriteJson(paths.configTarget, limpio)
|
|
572
|
+
else { removeFile(paths.configTarget, paths.install); quitados += 1 }
|
|
573
|
+
output.log(`✓ ${name}: ${runner.config.target} sin las entradas de Cauce`)
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
M.write(root, undefined, entregado)
|
|
577
|
+
output.log(`✓ ${name}: ${quitados} archivo(s) del toolkit quitados de ${paths.install}`)
|
|
578
|
+
for (const file of conservados) output.log(`= ${name}: conservado ${file} (tiene cambios tuyos)`)
|
|
579
|
+
if (runner.activation) output.log(` ${name}: si lo habías registrado a mano, quitalo también.`)
|
|
580
|
+
return { removed: quitados, kept: conservados }
|
|
581
|
+
}
|
|
582
|
+
|
|
481
583
|
function install(root, name, output = console, options = {}) {
|
|
482
584
|
// `install` arma la superficie de consumo de una empresa: punteros a cada cargo, una copia de los
|
|
483
585
|
// workflows y los guards. Acá los cargos y los workflows son el producto —la copia divergiría— y
|
|
@@ -571,6 +673,7 @@ module.exports = {
|
|
|
571
673
|
check,
|
|
572
674
|
doctor,
|
|
573
675
|
install,
|
|
676
|
+
uninstall,
|
|
574
677
|
legacyGuardWiring,
|
|
575
678
|
roleCatalog,
|
|
576
679
|
roleSkill,
|
package/engine/cli/bootstrap.js
CHANGED
|
@@ -25,10 +25,14 @@ function terminal() {
|
|
|
25
25
|
// dejar que ese rechazo suba terminaba la corrida con «Aborted with Ctrl+D» y la instancia recién creada
|
|
26
26
|
// sin una línea que dijera cómo seguir. El default no hace nada, así que tomarlo no decide nada.
|
|
27
27
|
async function elegir(deps, texto, opciones, fallback) {
|
|
28
|
-
|
|
28
|
+
// Una opción por línea y el default señalado donde se mira: apretar Enter es la respuesta más común, y
|
|
29
|
+
// en una sola línea apretada el `[ninguno]` del final no se lee como «esto pasa si no elegís nada».
|
|
30
|
+
const listado = opciones
|
|
31
|
+
.map((opcion, indice) => ` ${indice + 1}) ${opcion}${opcion === fallback ? ' ← Enter' : ''}`)
|
|
32
|
+
.join('\n')
|
|
29
33
|
for (let intento = 0; intento < INTENTOS; intento += 1) {
|
|
30
34
|
let dicho
|
|
31
|
-
try { dicho = await deps.ask(`\n${texto}\n${listado}\n
|
|
35
|
+
try { dicho = await deps.ask(`\n${texto}\n\n${listado}\n\n> `) } catch {
|
|
32
36
|
deps.log(`\n sin respuesta: sigo con ${fallback}.`)
|
|
33
37
|
return fallback
|
|
34
38
|
}
|
package/engine/cli/ops.js
CHANGED
|
@@ -63,6 +63,7 @@ function usage() {
|
|
|
63
63
|
ops automation check <ops-root>
|
|
64
64
|
ops automation doctor <ops-root> claude|codex|gemini|antigravity
|
|
65
65
|
ops automation install <ops-root> claude|codex|gemini|antigravity
|
|
66
|
+
ops automation uninstall <ops-root> claude|codex|gemini|antigravity
|
|
66
67
|
ops learn <agent> [--proposal] [--applied [--period <AAAA-MM>]]
|
|
67
68
|
ops evaluate <agent> [--cases [--json]] [--bench [caso]] [--record [AAAA-MM-DD]]
|
|
68
69
|
ops agents list [ops-root] [--own|--system] [--json]
|
|
@@ -334,15 +335,8 @@ async function init(target, cli) {
|
|
|
334
335
|
// corriendo `init`, no cuesta nada, y es lo único que le dice a alguien qué hacer con lo que acaba de
|
|
335
336
|
// crear. Dejarlo adentro del camino feliz lo escondía justo de quien más lo necesita.
|
|
336
337
|
console.log('')
|
|
337
|
-
onboard(root, SIN_BANDERAS)
|
|
338
|
-
if (resultado.instalado && resultado.runner !== BOOT.SIN_RUNNER) {
|
|
339
|
-
console.log(`\nAbrí ${resultado.runner} en este directorio para que las escriba por vos.`)
|
|
340
|
-
}
|
|
341
|
-
console.log('')
|
|
338
|
+
onboard(root, SIN_BANDERAS, resultado.instalado ? resultado.runner : '')
|
|
342
339
|
for (const paso of initSteps(enter, resultado)) console.log(paso)
|
|
343
|
-
if (resultado.instalado) {
|
|
344
|
-
console.log(`El ciclo empieza en ${path.join(relative || '.', 'planning', 'FLOW.md')}.`)
|
|
345
|
-
}
|
|
346
340
|
if (resultado.error) fail(`${resultado.error}: la instancia quedó creada pero todavía no funciona.`)
|
|
347
341
|
}
|
|
348
342
|
|
|
@@ -399,7 +393,7 @@ function comandos(commands) {
|
|
|
399
393
|
|
|
400
394
|
// La guía de arranque: qué hay, qué falta y qué preguntar. Determinista y en milisegundos, porque es lo
|
|
401
395
|
// primero que ve alguien que acaba de instalar y todavía no sabe qué hace la herramienta.
|
|
402
|
-
function onboard(rootArg, cli) {
|
|
396
|
+
function onboard(rootArg, cli, runner = '') {
|
|
403
397
|
const root = path.resolve(rootArg || '.')
|
|
404
398
|
const services = inventory(root)
|
|
405
399
|
const state = OB.guide(root, services)
|
|
@@ -426,8 +420,12 @@ function onboard(rootArg, cli) {
|
|
|
426
420
|
console.log(`Esta instancia ya tiene ${escrito} escrito: el arranque no la va a pisar.`)
|
|
427
421
|
return
|
|
428
422
|
}
|
|
429
|
-
|
|
430
|
-
|
|
423
|
+
// Un solo cierre: tres líneas que suenan a final se leen como tres finales, y quien recién instaló
|
|
424
|
+
// termina sin saber cuál era el paso.
|
|
425
|
+
console.log(runner
|
|
426
|
+
? `\n→ Abrí ${runner} acá y contestale esa pregunta.`
|
|
427
|
+
: '\n→ Contestá esa pregunta cuando corras el arranque.')
|
|
428
|
+
console.log(' Con tus respuestas escribe organization/, el mapa real de AGENTS.md y la primera épica.')
|
|
431
429
|
}
|
|
432
430
|
|
|
433
431
|
function check(dir, cli) {
|
|
@@ -743,7 +741,13 @@ function upgrade(dir, cli) {
|
|
|
743
741
|
const overrides = O.overrides(root)
|
|
744
742
|
|
|
745
743
|
if (dry) {
|
|
746
|
-
if (from === to)
|
|
744
|
+
if (from === to) {
|
|
745
|
+
// Contra el motor instalado, no contra lo publicado: la comparación es local y sin red. Decirlo
|
|
746
|
+
// importa porque `init` fija la versión exacta, así que el motor no se mueve solo y esta línea,
|
|
747
|
+
// a secas, se leía como «no hay nada nuevo» durante todas las versiones siguientes.
|
|
748
|
+
console.log(`= ${to}: la instancia está al día con el motor instalado`)
|
|
749
|
+
return console.log(' para traer una versión más nueva: npm install --save-dev @ingeniomaps/cauce@latest')
|
|
750
|
+
}
|
|
747
751
|
console.log(`⚠ hay una versión más nueva: ${to} (la instancia tiene ${from || 'una previa'})`)
|
|
748
752
|
printChangelog(from, to)
|
|
749
753
|
for (const file of changed) console.log(` editado localmente: ${file}`)
|
|
@@ -1112,6 +1116,11 @@ function automation(action, rootArg, runnerName, cli) {
|
|
|
1112
1116
|
console.log(`✓ ${runnerName}: adaptador operativo (${result.warnings.length} advertencia(s))`)
|
|
1113
1117
|
return
|
|
1114
1118
|
}
|
|
1119
|
+
if (action === 'uninstall') {
|
|
1120
|
+
try { A.uninstall(root, runnerName, console) } catch (error) { fail(error.message, 2) }
|
|
1121
|
+
console.log(' la instancia sigue en pie: borrar la carpeta ops es una decisión aparte.')
|
|
1122
|
+
return
|
|
1123
|
+
}
|
|
1115
1124
|
if (action === 'install') {
|
|
1116
1125
|
let runner
|
|
1117
1126
|
const force = cli.has('--force')
|
package/package.json
CHANGED
package/template/Makefile
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
.PHONY: integration-check integration-sync require-key integration-promote
|
|
5
5
|
.PHONY: require-agent agent-learn agent-propose agent-evaluate require-team team-check team-show
|
|
6
6
|
.PHONY: install-claude install-codex install-gemini install-antigravity
|
|
7
|
+
.PHONY: uninstall-claude uninstall-codex uninstall-gemini uninstall-antigravity
|
|
7
8
|
.PHONY: doctor-claude doctor-codex doctor-gemini doctor-antigravity
|
|
8
9
|
|
|
9
10
|
# Jira es hoy el único proveedor; el día que haya otro se pasa PROVIDER=<slug>.
|
|
@@ -22,7 +23,10 @@ tree: ## Muestra roadmap, backlog, WIP y Done
|
|
|
22
23
|
context: ## Muestra el contexto mínimo de la tarea vigente
|
|
23
24
|
@node tools/ops.js context planning
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
# `init` fija la versión exacta del motor, así que `npm update` no la mueve: hay que pedir @latest.
|
|
27
|
+
# Sin este primer paso `upgrade` compara contra el motor instalado y contesta «al día» para siempre.
|
|
28
|
+
upgrade: ## Trae la última versión de Cauce y la aplica, sin tocar lo del proyecto
|
|
29
|
+
@npm install --save-dev @ingeniomaps/cauce@latest
|
|
26
30
|
@node tools/ops.js upgrade .
|
|
27
31
|
|
|
28
32
|
automation-check: ## Comprueba hooks, workflows y adaptadores
|
|
@@ -73,6 +77,18 @@ install-gemini: ## Instala contexto, comandos y configuración para Gemini
|
|
|
73
77
|
install-antigravity: ## Instala el plugin Cauce para Antigravity CLI
|
|
74
78
|
@node tools/ops.js automation install . antigravity
|
|
75
79
|
|
|
80
|
+
uninstall-claude: ## Quita de Claude el wiring de Cauce, conservando lo tuyo
|
|
81
|
+
@node tools/ops.js automation uninstall . claude
|
|
82
|
+
|
|
83
|
+
uninstall-codex: ## Quita de Codex el wiring de Cauce, conservando lo tuyo
|
|
84
|
+
@node tools/ops.js automation uninstall . codex
|
|
85
|
+
|
|
86
|
+
uninstall-gemini: ## Quita de Gemini el wiring de Cauce, conservando lo tuyo
|
|
87
|
+
@node tools/ops.js automation uninstall . gemini
|
|
88
|
+
|
|
89
|
+
uninstall-antigravity: ## Quita de Antigravity el wiring de Cauce, conservando lo tuyo
|
|
90
|
+
@node tools/ops.js automation uninstall . antigravity
|
|
91
|
+
|
|
76
92
|
doctor-claude: ## Diagnostica la instalación de Claude
|
|
77
93
|
@node tools/ops.js automation doctor . claude
|
|
78
94
|
|