@ingeniomaps/cauce 0.69.0 → 0.70.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +6 -6
  3. package/automatization/AGENTS.md +1 -1
  4. package/automatization/runners/antigravity/rules/cauce.md +1 -1
  5. package/automatization/runners/claude/CLAUDE.md +1 -1
  6. package/automatization/runners/codex/AGENTS.md +1 -1
  7. package/automatization/runners/gemini/GEMINI.md +1 -1
  8. package/automatization/shared/skills/autobuild/SKILL.md +1 -1
  9. package/automatization/workflows/autobuild.js +44 -8
  10. package/engine/cli/archive.js +87 -0
  11. package/engine/cli/args.js +6 -2
  12. package/engine/cli/catalog.js +9 -1
  13. package/engine/cli/claims.js +125 -0
  14. package/engine/cli/ops.js +15 -4
  15. package/engine/cli/planning.js +110 -107
  16. package/engine/cli/worktree.js +89 -0
  17. package/engine/core/ownership.js +13 -5
  18. package/engine/core/repos.js +67 -0
  19. package/engine/hooks/files.js +3 -2
  20. package/engine/planning/adoption.js +1 -1
  21. package/engine/planning/claims.js +153 -0
  22. package/engine/planning/contracts.js +43 -202
  23. package/engine/planning/parser.js +51 -12
  24. package/engine/planning/state.js +39 -6
  25. package/engine/planning/structure.js +220 -0
  26. package/package.json +1 -1
  27. package/template/.gitattributes +19 -0
  28. package/template/AGENTS.md +47 -5
  29. package/template/automatization/AGENTS.md +1 -1
  30. package/template/gitignore +9 -0
  31. package/template/planning/BACKLOG.md +5 -0
  32. package/template/planning/FLOW.md +1 -1
  33. package/template/planning/PROTOCOL.md +20 -8
  34. package/template/planning/README.md +3 -3
  35. package/template/planning/RECURRING.md +1 -1
  36. package/template/planning/adr/system/OPS-001-planificacion-como-fuente-de-verdad.md +3 -2
  37. package/template/planning/business-rules/system/BR-OPS-001-una-sola-tarea-activa.md +7 -4
  38. package/template/planning/business-rules/system/BR-OPS-005-una-tarea-un-runner.md +44 -0
  39. package/template/planning/claims/README.md +70 -0
  40. package/template/planning/delivery/README.md +1 -0
  41. package/template/planning/delivery/multi-repo.md +11 -0
  42. package/template/planning/delivery/teamwork.md +162 -0
  43. package/template/planning/done/README.md +41 -0
  44. package/template/planning/wip/README.md +49 -0
  45. package/template/planning/DONE.md +0 -13
  46. package/template/planning/WIP.md +0 -22
@@ -19,6 +19,17 @@ manifiesto es evidencia del pipeline, no una lista que una persona edita manualm
19
19
  - Bases de datos y APIs aplican expand/contract durante la ventana de convivencia.
20
20
  - Una entrega cross-repo registra qué PR y versión satisface cada lado del contrato.
21
21
 
22
+ ## El `service:` de una tarea tiene que resolver a un solo repositorio
23
+
24
+ Con varias raíces declaradas, un `service:` que existe en más de una es ambiguo: `.` existe en todas, y un
25
+ `src` puede existir en dos. `ops worktree` lo nombra y se niega en vez de elegir la primera, porque elegir
26
+ da una respuesta plausible y equivocada —el árbol de trabajo en el repositorio que no era— sin que nada lo
27
+ diga. El aviso de avance de un reclamo degrada por lo mismo: sin poder resolver el repositorio, mira sólo
28
+ la fecha en que se tomó.
29
+
30
+ La salida es escribir servicios que sólo existan en una raíz. Si dos repositorios tienen un directorio con
31
+ el mismo nombre y los dos son servicios de verdad, conviene una instancia por repositorio.
32
+
22
33
  ## Cuándo coordinar
23
34
 
24
35
  Coordinar solo cuando una propiedad no puede preservarse mediante compatibilidad temporal, por ejemplo una
@@ -0,0 +1,162 @@
1
+ # Trabajo en equipo
2
+
3
+ > Camino recomendado. Adaptar en `project.md` y registrar excepciones durables mediante ADR.
4
+
5
+ Una instancia la comparte un equipo, y lo que comparte es de tres clases distintas. Casi todos los
6
+ choques entre dos personas —o entre dos agentes— salen de tratarlas igual.
7
+
8
+ ## Los tres anillos
9
+
10
+ | Anillo | Qué vive ahí | Escritores | Frecuencia |
11
+ |---|---|---|---|
12
+ | **Compartido** | `roadmap/`, `BACKLOG.md`, `INBOX.md`, `HUMAN_ACTIONS.md`, `done/`, reglas y ADR | cualquiera, en actos humanos | baja |
13
+ | **Coordinación** | `claims/`, un archivo por tarea tomada | uno por tarea | dos veces por tarea |
14
+ | **Local** | `wip/<runner>.md`, `.verify-log`, el árbol de trabajo | vos | continua |
15
+
16
+ La regla que los separa: **un archivo con más de un escritor tiene que cambiar poco; uno que cambia mucho
17
+ tiene que tener un solo escritor.** Cuando uno viola las dos a la vez, el equipo se pisa en cada commit.
18
+
19
+ De ahí sale el corolario que ahorra la mayor parte de las conversaciones: **no hace falta que cada persona
20
+ sepa qué está haciendo la otra.** Hacen falta dos cosas y sólo dos — qué está tomado, para no tomarlo dos
21
+ veces, y qué terminó, porque es evidencia y destraba lo que dependía de eso. Todo lo del medio —el plan,
22
+ los pasos, las decisiones en vuelo— no le sirve a nadie más y es justo lo que más cambia.
23
+
24
+ ## Un árbol de trabajo por persona o por agente
25
+
26
+ Dos agentes en el mismo directorio comparten índice de git y archivos: uno stagea lo del otro, uno
27
+ commitea trabajo ajeno, y los errores no se parecen a la causa — un archivo trackeado que «no existe»
28
+ suele ser la otra sesión y no tu cambio. No es un problema de este toolkit sino del filesystem, y la
29
+ respuesta es un árbol por cada uno:
30
+
31
+ ```bash
32
+ git worktree add ../repo-dashboard feat/dashboard-filtros
33
+ git worktree add ../repo-exportar feat/boton-exportar
34
+ ```
35
+
36
+ Mismo `.git`, índices separados, archivos separados. Es la **precondición** para correr dos agentes a la
37
+ vez: sin esto, nada de lo demás de esta guía alcanza.
38
+
39
+ Cada árbol necesita además sus propios recursos —puertos, contenedores, base—. Dos agentes levantando el
40
+ mismo entorno de desarrollo en el mismo puerto fallan mucho antes que cualquier archivo de planning.
41
+
42
+ La rama por tarea y su ciclo viven en `branches.md`; acá se agrega que el árbol también se separa.
43
+
44
+ ## Tomar una tarea sin pisarse
45
+
46
+ Tomar es un acto y tiene comando:
47
+
48
+ ```bash
49
+ node tools/ops.js claim planning dashboard-filtros
50
+ node tools/ops.js release planning dashboard-filtros
51
+ ```
52
+
53
+ `ops context` no ofrece una tarea con reclamo ajeno y nombra quién la tiene, así que dos runners
54
+ preguntando a la vez ya no reciben la misma. Y devuelve antes lo que vos reclamaste que lo que está
55
+ libre: es lo que dijiste que ibas a hacer. El contrato completo está en `../claims/README.md`.
56
+
57
+ Lo que el comando **no** hace, y hay que saberlo: un reclamo sin empujar no reserva nada, porque el otro
58
+ runner lee lo que hay en su copia. Entre `claim` y el push hay una ventana, y es de minutos sólo si se
59
+ commitea el reclamo enseguida.
60
+
61
+ **Lo que sigue a una tarea en vuelo no se le ofrece a nadie más.** Una tarea puede declarar
62
+ `(depende: slug)`, y mientras eso no esté en DONE no se ofrece ni se puede tomar: el trabajo que sigue es
63
+ de quien tiene la cabeza, y dárselo a otro produce dos ramas que se pisan al integrar. `context` lo dice
64
+ con una línea `WAIT` que nombra la dependencia y quién la tiene, para que la cola trabada no se lea como
65
+ una cola vacía. `check` rechaza una dependencia que no existe y nombra el ciclo entero cuando lo hay.
66
+
67
+ Dos cosas que el mecanismo no reemplaza:
68
+
69
+ - **Mirar el `service:`.** Es el dominio de colisión y ya está declarado en cada tarea: dos tareas de
70
+ servicios distintos no se pueden pisar en el código, dos del mismo pueden. `ops check` avisa cuando hay
71
+ dos reclamos sobre el mismo servicio, y avisa nada más — frenar serializaría a un equipo entero sobre
72
+ un servicio, que es peor que la colisión que evita.
73
+ - **Repartir por hito.** Cada persona toma de un `## Hito` distinto, y `ops context planning --hito <slug>`
74
+ acota la cola a ése. Dos personas en hitos distintos casi nunca dependen entre sí ni tocan los mismos
75
+ archivos, así que los dos avisos de arriba casi no aparecen.
76
+
77
+ ## Varios agentes en una misma máquina
78
+
79
+ Una tarea larga deja horas muertas, y ese hueco alcanza para poner otro agente a trabajar. Cuatro cosas
80
+ lo hacen posible, y ninguna pide clonar el repositorio dos veces.
81
+
82
+ **Un clon, varios árboles de trabajo.** `git worktree` no clona: comparte el mismo `.git`, el mismo
83
+ historial y los mismos objetos, y sólo materializa un segundo directorio de archivos. Cada árbol queda
84
+ fijado a su rama, así que **nadie hace `checkout` nunca** — que es lo que pisaría el trabajo del otro.
85
+
86
+ ```bash
87
+ node tools/ops.js worktree planning dashboard-filtros
88
+ ```
89
+
90
+ Resuelve en qué repositorio vive el `service:` de la tarea, crea la rama `task/<slug>` y el árbol al
91
+ lado, y devuelve la ruta con el `export CAUCE_RUNNER` ya escrito. Correrlo dos veces devuelve el árbol que
92
+ ya existe en vez de crear otro.
93
+
94
+ **La instancia, una sola y compartida.** Si `ops/` vive dentro del repositorio (`mode: embedded`), cada
95
+ árbol se lleva su propia copia de `planning/` — o ninguna, si todavía no se commiteó— y los reclamos de un
96
+ agente no los ve el otro hasta mergear: justo la coordinación que en una máquina tendría que ser
97
+ instantánea. Con `mode: sidecar` la instancia es una, al lado de los repos, y los reclamos se ven al
98
+ momento y sin git de por medio.
99
+
100
+ `ops worktree` lo avisa cuando prepara un árbol sobre una instancia embebida. No lo frena: un árbol por
101
+ rama con un solo agente es un uso legítimo, y lo que se rompe es la coordinación entre varios.
102
+
103
+ **Un id por agente.** Sin eso los dos resuelven la misma identidad de git y el segundo toma por propia la
104
+ tarea del primero. Al abrir una sesión, `ops runners planning` dice qué runners tienen trabajo abierto;
105
+ el agente pregunta cuál se retoma o si arranca uno nuevo, y **exporta el id él mismo**. A una persona no
106
+ se le pide que escriba una variable de entorno. El contrato está en `../claims/README.md`.
107
+
108
+ **Recursos propios.** Puertos, contenedores y base por agente. Dos sesiones levantando el mismo entorno
109
+ en el mismo puerto fallan antes que cualquier archivo de planning.
110
+
111
+ Sirve igual para dos agentes de la misma herramienta o de herramientas distintas: la reserva es del CLI,
112
+ no del runner que la invoca.
113
+
114
+ ## Pasar una tarea a otra persona
115
+
116
+ El plan es local, así que no viaja: quien recibe la tarea ve el reclamo y no cómo venía pensada. Eso está
117
+ bien casi siempre —nadie necesita el plan de otro— y falla justo cuando hace falta.
118
+
119
+ Por eso el traspaso es un acto y tiene tres pasos: quien deja **publica su plan** donde el otro lo lea —una
120
+ nota en la tarea, un mensaje, lo que el equipo use—, suelta el reclamo, y quien toma lo reclama. El costo
121
+ de compartir el plan se paga entonces, que es cuando sirve.
122
+
123
+ Lo que no hay que hacer es empujar tu `wip/<runner>.md`: sería devolver a git el archivo que más cambia,
124
+ todos los días, para resolver algo que pasa una vez cada tanto.
125
+
126
+ ## Cuando el equipo crece o se achica
127
+
128
+ **No se escala por archivo: se escala por instancia.** Los umbrales no son leyes; son el momento de mirar.
129
+
130
+ | Tamaño | Qué alcanza | Qué se rompe primero |
131
+ |---|---|---|
132
+ | 1 | todo tal cual | nada |
133
+ | 2 a 8 | un `planning/`, un árbol por persona, reparto por hito | sacar la tarea de `BACKLOG.md` al cerrarla, que es lo único que dos personas se disputan |
134
+ | 8 a 20 | lo mismo, con la cola acotada por hito (`--hito`) | el `BACKLOG` se vuelve **ilegible** antes que contencioso: nadie lee sesenta tareas para elegir la suya, y acotar por hito ayuda sólo si los hitos están bien cortados |
135
+ | 20+ | una instancia por equipo o por dominio | la coordinación pasa a ser entre instancias, que es `multi-repo.md` |
136
+
137
+ Achicarse parece más fácil y tiene una trampa: **lo que tomó quien se fue no se libera solo.** `ops check`
138
+ avisa a los tres días sin que la rama de la tarea se mueva —una tarea larga que avanza no se apura—, pero
139
+ soltarlo es borrar el archivo de `claims/` a mano — `ops release` se niega a
140
+ hacerlo por vos—. Al bajar de tamaño se recorren esos reclamos igual que las filas de `HUMAN_ACTIONS.md`
141
+ que esperaban a esa persona.
142
+
143
+ ## Dónde va cada cosa que el equipo se dice
144
+
145
+ | Lo que pasó | Dónde va | Por qué ahí |
146
+ |---|---|---|
147
+ | Una decisión que cambia cómo se construye | `adr/` | se consulta dentro de un año |
148
+ | Una norma que hay que cumplir siempre | `business-rules/` o `rules/` | la lee un agente en cada tarea |
149
+ | Algo que sólo puede hacer una persona | `HUMAN_ACTIONS.md` | frena su tarea hasta que se resuelva |
150
+ | Una idea, una deuda, una lección | `INBOX.md` | espera promoción humana |
151
+ | Lo que una tarea entregó, con su evidencia | `done/<slug>.md` | es lo que se audita |
152
+ | Qué tarea estoy haciendo | `claims/` | para que nadie la tome dos veces |
153
+ | «Salgo a almorzar», «está lento el CI» | el canal del equipo | no es durable y no se audita |
154
+
155
+ La última fila pesa tanto como las otras: meter conversación en el repositorio lo vuelve ilegible, y sacar
156
+ decisiones del repositorio las pierde.
157
+
158
+ ## Lo que git tiene que saber
159
+
160
+ `.gitattributes` declara que `HUMAN_ACTIONS.md` y su histórico se concatenan en vez de conflictuar cuando
161
+ dos personas registran un bloqueo el mismo día. Llega con la instancia y sus bordes están escritos ahí
162
+ adentro. La evidencia de una tarea no lo necesita: vive en su propio archivo y nadie escribe el de nadie.
@@ -0,0 +1,41 @@
1
+ # Evidencia de lo terminado
2
+
3
+ Un archivo por tarea cerrada, con el slug de la tarea como nombre: `alta-de-cliente.md` es lo que esa
4
+ tarea entregó y con qué se comprueba.
5
+
6
+ ```markdown
7
+ - [x] **alta-de-cliente** (epic: 001) — Alta de cliente
8
+ acept: el alta rechaza un duplicado
9
+ fecha: 2026-09-08
10
+ done: cambios y comandos de verificación con exit codes
11
+ qa: comportamiento observado por el camino real
12
+ tests: C1 → nombre de prueba o comando; C2 → nombre de prueba o comando
13
+ decisions: decisión no obvia [fuente: ruta/archivo] o [supuesto: motivo verificable]
14
+ commit: abc1234 feat(scope): subject (repo@branch)
15
+ ```
16
+
17
+ El contrato completo de esos campos está en `../PROTOCOL.md`; acá va por qué el archivo es uno por tarea.
18
+
19
+ ## Por qué uno por tarea
20
+
21
+ Cerrar es lo que más se hace, y mientras la evidencia se acumulaba en un archivo compartido, cerrar era
22
+ agregarle una entrada a algo que otro también estaba tocando. Con un archivo por tarea, **dos personas
23
+ —o dos agentes— que cierran a la vez escriben archivos distintos**: no hay conflicto que resolver ni
24
+ regla de merge que aplicar.
25
+
26
+ El nombre del archivo es una conveniencia; lo que identifica la tarea es el slug de la viñeta. Renombrar
27
+ el archivo no cambia de qué tarea habla, y cerrar dos veces la misma sigue siendo un error que `check`
28
+ rechaza, ahora entre archivos.
29
+
30
+ ## Por qué la fecha
31
+
32
+ Mientras las entradas vivían en un archivo, «la última» era la última del archivo. Con archivos sueltos
33
+ el orden lo daría el listado del directorio, que es alfabético: la respuesta equivocada se leería igual
34
+ de bien que la correcta. Por eso `fecha:` es la del cierre y es obligatoria — y por eso `ops evidence`
35
+ sin `--task` puede contestar por la más reciente.
36
+
37
+ ## Qué más vive acá
38
+
39
+ `human-actions.md`, con las filas resueltas que `ops archive human-actions` mueve desde
40
+ `../HUMAN_ACTIONS.md`. Es una tabla y no una entrada, así que el lector no la confunde con una tarea —
41
+ igual que a este README—.
@@ -0,0 +1,49 @@
1
+ # El plan en vuelo
2
+
3
+ Un archivo por runner: `wip/<runner>.md` es el plan de quien lo escribió, y **no viaja por git**. Existe
4
+ para recuperar esa sesión si se corta, y nadie más puede retomarla — el árbol de trabajo es otro.
5
+
6
+ ```markdown
7
+ ---
8
+ task: slug
9
+ hito: "Hito slug — Título"
10
+ epic: 001
11
+ phase: Build
12
+ started: AAAA-MM-DD
13
+ service: ruta
14
+ acceptance: "criterio observable"
15
+ ---
16
+
17
+ ## Plan aprobado
18
+ 1. [ ] Paso verificable
19
+
20
+ ## Decisiones tomadas
21
+ - (ninguna)
22
+
23
+ ## Bloqueos
24
+ - (ninguno)
25
+ ```
26
+
27
+ Sin archivo, el runner está en IDLE: un clon nuevo no trae ninguno y eso no es un error.
28
+
29
+ ## Por qué uno por runner y no uno solo
30
+
31
+ Con `mode: sidecar` hay un solo `planning/` por máquina, así que un archivo compartido lo escriben todos
32
+ los agentes que corren ahí: el segundo pisa el plan del primero, y `ops context` le entrega la tarea que
33
+ el primero está construyendo — con el plan ajeno adentro y diciéndole que está libre.
34
+
35
+ El nombre sale del id del runner, aplanado para poder ser un nombre de archivo. Queda largo y legible a
36
+ propósito: sirve para ver de quién es cada plan cuando algo quedó a medias.
37
+
38
+ ## Qué mira cada comando
39
+
40
+ `ops context` honra **sólo el tuyo**, que es el único que te corresponde continuar, y `ops check` los
41
+ recorre todos — que cada plan apunte a una tarea que existe es una pregunta sobre la instancia, no sobre
42
+ quien pregunta.
43
+
44
+ ## Volver al día siguiente
45
+
46
+ El plan sigue acá, el reclamo en `../claims/` y el árbol de trabajo donde lo dejaste. Lo único que hay
47
+ que reponer es el id: exportá el mismo `CAUCE_RUNNER` —`ops worktree` lo imprime— y `ops context` te
48
+ devuelve tu tarea donde la dejaste. Con otro id, tu propio reclamo se ve ajeno, y `ops claim` te lo dice
49
+ en vez de decidir por vos.
@@ -1,13 +0,0 @@
1
- # Done activo
2
-
3
- <!--
4
- ## Hito slug — Título
5
-
6
- - [x] **slug-de-tarea** (epic: 001) — Resultado
7
- acept: comportamiento aceptado
8
- done: cambios y comandos de verificación con exit codes
9
- qa: comportamiento observado por el camino real
10
- tests: C1 → nombre de prueba o comando; C2 → nombre de prueba o comando
11
- decisions: decisión no obvia [fuente: ruta/archivo] o [supuesto: motivo verificable]
12
- commit: abc1234 feat(scope): subject (repo@branch)
13
- -->
@@ -1,22 +0,0 @@
1
- status: IDLE
2
-
3
- <!-- Activo:
4
- ---
5
- task: slug
6
- hito: "Hito slug — Título"
7
- epic: 001
8
- phase: Build
9
- started: YYYY-MM-DD
10
- service: ruta
11
- acceptance: "criterio observable"
12
- ---
13
-
14
- ## Plan aprobado
15
- 1. [ ] Paso verificable
16
-
17
- ## Decisiones tomadas
18
- - (ninguna)
19
-
20
- ## Bloqueos
21
- - (ninguno)
22
- -->