@ingeniomaps/cauce 0.96.0 → 0.98.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 (78) hide show
  1. package/CHANGELOG.md +173 -0
  2. package/README.md +1 -0
  3. package/agents/roles/system/accounting-specialist/learning/AUTOMATION.md +2 -2
  4. package/agents/roles/system/ai-governance-lead/learning/AUTOMATION.md +1 -1
  5. package/agents/roles/system/ai-product-manager/learning/AUTOMATION.md +1 -1
  6. package/agents/roles/system/analytics-engineer/learning/AUTOMATION.md +1 -1
  7. package/agents/roles/system/backend-engineer/learning/AUTOMATION.md +2 -2
  8. package/agents/roles/system/business-strategist/learning/AUTOMATION.md +2 -2
  9. package/agents/roles/system/cloud-architect/learning/AUTOMATION.md +1 -1
  10. package/agents/roles/system/community-manager/learning/AUTOMATION.md +1 -1
  11. package/agents/roles/system/content-specialist/learning/AUTOMATION.md +2 -2
  12. package/agents/roles/system/customer-success-manager/learning/AUTOMATION.md +2 -2
  13. package/agents/roles/system/customer-support-specialist/learning/AUTOMATION.md +2 -2
  14. package/agents/roles/system/data-analyst/learning/AUTOMATION.md +2 -2
  15. package/agents/roles/system/data-engineer/learning/AUTOMATION.md +1 -1
  16. package/agents/roles/system/data-governance-steward/learning/AUTOMATION.md +2 -2
  17. package/agents/roles/system/data-scientist/learning/AUTOMATION.md +1 -1
  18. package/agents/roles/system/database-administrator/learning/AUTOMATION.md +1 -1
  19. package/agents/roles/system/developer-relations-engineer/learning/AUTOMATION.md +1 -1
  20. package/agents/roles/system/devops-engineer/learning/AUTOMATION.md +2 -2
  21. package/agents/roles/system/engineering-manager/learning/AUTOMATION.md +1 -1
  22. package/agents/roles/system/financial-controller/learning/AUTOMATION.md +2 -2
  23. package/agents/roles/system/finops-engineer/learning/AUTOMATION.md +2 -2
  24. package/agents/roles/system/fraud-risk-analyst/learning/AUTOMATION.md +2 -2
  25. package/agents/roles/system/frontend-engineer/learning/AUTOMATION.md +2 -2
  26. package/agents/roles/system/growth-marketer/learning/AUTOMATION.md +2 -2
  27. package/agents/roles/system/implementation-manager/learning/AUTOMATION.md +1 -1
  28. package/agents/roles/system/integrations-engineer/learning/AUTOMATION.md +3 -3
  29. package/agents/roles/system/kyc-aml-specialist/learning/AUTOMATION.md +3 -3
  30. package/agents/roles/system/legal-counsel/learning/AUTOMATION.md +1 -1
  31. package/agents/roles/system/logistics-operations-manager/learning/AUTOMATION.md +2 -2
  32. package/agents/roles/system/machine-learning-engineer/learning/AUTOMATION.md +1 -1
  33. package/agents/roles/system/mlops-engineer/learning/AUTOMATION.md +1 -1
  34. package/agents/roles/system/mobile-engineer/learning/AUTOMATION.md +2 -2
  35. package/agents/roles/system/partnerships-manager/learning/AUTOMATION.md +1 -1
  36. package/agents/roles/system/people-operations-manager/learning/AUTOMATION.md +1 -1
  37. package/agents/roles/system/privacy-compliance-specialist/learning/AUTOMATION.md +2 -2
  38. package/agents/roles/system/procurement-manager/learning/AUTOMATION.md +1 -1
  39. package/agents/roles/system/product-manager/learning/AUTOMATION.md +3 -3
  40. package/agents/roles/system/product-marketing-manager/learning/AUTOMATION.md +2 -2
  41. package/agents/roles/system/project-manager/learning/AUTOMATION.md +1 -1
  42. package/agents/roles/system/qa-engineer/learning/AUTOMATION.md +2 -2
  43. package/agents/roles/system/release-manager/learning/AUTOMATION.md +1 -1
  44. package/agents/roles/system/sales-representative/learning/AUTOMATION.md +2 -2
  45. package/agents/roles/system/security-engineer/learning/AUTOMATION.md +2 -2
  46. package/agents/roles/system/site-reliability-engineer/learning/AUTOMATION.md +2 -2
  47. package/agents/roles/system/software-architect/learning/AUTOMATION.md +2 -2
  48. package/agents/roles/system/solutions-engineer/learning/AUTOMATION.md +1 -1
  49. package/agents/roles/system/tech-lead/learning/AUTOMATION.md +2 -2
  50. package/agents/roles/system/technical-program-manager/learning/AUTOMATION.md +1 -1
  51. package/agents/roles/system/technical-writer/learning/AUTOMATION.md +1 -1
  52. package/agents/roles/system/treasury-analyst/learning/AUTOMATION.md +2 -2
  53. package/agents/roles/system/ui-designer/learning/AUTOMATION.md +3 -3
  54. package/agents/roles/system/user-researcher/learning/AUTOMATION.md +3 -3
  55. package/agents/roles/system/ux-designer/learning/AUTOMATION.md +3 -3
  56. package/automatization/hooks/README.md +4 -3
  57. package/automatization/workflows/agent-propose.js +2 -2
  58. package/automatization/workflows/autobuild.js +219 -29
  59. package/automatization/workflows/flow.js +30 -14
  60. package/engine/agents/learning-files.js +18 -0
  61. package/engine/agents/learning-seal.js +24 -12
  62. package/engine/agents/learning-sources.js +12 -10
  63. package/engine/agents/learning.js +29 -7
  64. package/engine/cli/args.js +2 -2
  65. package/engine/cli/catalog.js +12 -12
  66. package/engine/cli/ops.js +2 -1
  67. package/engine/cli/planning.js +4 -1
  68. package/engine/hooks/approval.js +5 -3
  69. package/engine/hooks/chat.js +19 -7
  70. package/engine/hooks/push.js +3 -2
  71. package/engine/hooks/self-approval.js +2 -2
  72. package/engine/hooks/shell.js +63 -6
  73. package/engine/planning/contracts.js +19 -0
  74. package/engine/planning/parser.js +35 -0
  75. package/package.json +1 -1
  76. package/template/AGENTS.md +5 -4
  77. package/template/Makefile +1 -1
  78. package/template/planning/rules/system/commits.md +9 -2
@@ -383,6 +383,25 @@ function validateState({
383
383
  if (!row.valid) {
384
384
  errors.push(`HUMAN_ACTIONS ${row.task}: estado "${row.state}" fuera de `
385
385
  + `${P.HUMAN_ACTION_STATES.join(' | ')}; mientras no se entienda, la tarea queda bloqueada`)
386
+ continue
387
+ }
388
+ // La primera columna es a la vez lo que una persona lee y la clave con la que el motor bloquea:
389
+ // la selección de tarea (`state.js`) arma su conjunto de bloqueadas con ella tal cual. Esa doble
390
+ // función es libre a propósito —el molde manda
391
+ // nombrar la épica o el recorrido cuando la tarea todavía no existe— así que lo que no se puede
392
+ // recortar es la libertad, y lo que sí se puede es la forma intermedia: la celda que **menciona** una
393
+ // tarea de la cola sin ser su slug.
394
+ //
395
+ // Es la peor de las tres porque promete un bloqueo que no ocurre, y nada lo dice: la fila se escribe
396
+ // sin error, sale en `ops context` bajo HUMAN como si estuviera registrada, y la tarea se sigue
397
+ // ofreciendo. `**slug: de qué se trata**` es la que sale natural, porque esta tabla la lee una
398
+ // persona. Sin esto la ausencia no deja rastro, que es la forma de R15 aplicada a un mecanismo.
399
+ if (backlogSlugs.has(row.task)) continue
400
+ const casi = [...backlogSlugs].find((slug) => new RegExp(`\\b${slug}\\b`).test(row.task))
401
+ if (casi) {
402
+ errors.push(`HUMAN_ACTIONS: la fila "${row.task}" nombra a ${casi} y no bloquea nada, porque el `
403
+ + `motor bloquea por la primera columna exacta. Dejá "${casi}" sola ahí y contá el resto en la `
404
+ + 'acción, o nombrá la épica o el recorrido si lo que se frena no es esa tarea')
386
405
  }
387
406
  }
388
407
 
@@ -176,6 +176,10 @@ function readCast(rest) {
176
176
  // devolvía `MAX` con `check` en verde, que es la forma cara del error —la tarea se lee completa y no
177
177
  // lo está—. Cierra el `_` que markdown cerraría: el que no está entre caracteres de palabra.
178
178
  const ACCEPTANCE = /_Aceptaci[oó]n:\s*(.*?\S)_(?![A-Za-z0-9])/i
179
+ // Los paréntesis del contrato de una línea de tarea. Se enumeran por su clave y no como «cualquier
180
+ // paréntesis» para no llevarse puesta una aclaración de la prosa: la descripción usa paréntesis igual
181
+ // que cualquier texto, y el criterio `(→ C1)` va acá porque `criteria` ya lo extrae.
182
+ const MARKERS = /\((?:→|->|criterios?\s|epic:|service:|cast:|depende:|sin partir:)[^)]*\)/gi
179
183
 
180
184
  // Cuántas condiciones tiene una aceptación escrita en prosa. Estuvo mucho tiempo sin contarse con una
181
185
  // razón buena —contar condiciones en una frase es una lectura, y un número inventado es peor que
@@ -207,6 +211,19 @@ function taskFromLine(line) {
207
211
  epic: ((rest.match(/\(epic:\s*(\d{3})\)/) || [])[1] || ''),
208
212
  service: ((rest.match(/\(service:\s*([^)]+)\)/) || [])[1] || '').trim(),
209
213
  acceptance,
214
+ // Lo que la aceptación no puede decir y alguien ya decidió: dónde vive un símbolo, qué queda fuera de
215
+ // alcance, con qué se produce la evidencia. Por contrato la aceptación describe estado observable del
216
+ // producto, así que una decisión de diseño no cabe ahí — y hasta acá tampoco salía del BACKLOG: el
217
+ // texto vivía en `rest` y se descartaba.
218
+ //
219
+ // Sin ella el que planifica vuelve a decidir lo ya decidido, y decide distinto. La crítica **sí** abre
220
+ // el BACKLOG y bloquea el plan citando la línea palabra por palabra: una compuerta juzga contra un
221
+ // texto que la otra no recibió. Dos corridas reales se pagaron enteras para descubrirlo, 1,10 M y
222
+ // 815 k tokens, la segunda con sus cuatro objeciones diciendo lo mismo (caso 177).
223
+ //
224
+ // Se recorta la aceptación y los marcadores del contrato porque cada uno ya tiene su campo: repetirlos
225
+ // acá los pone dos veces en el prompt de cada fase, que es lo que R16 cobra una vez por etapa.
226
+ description: rest.replace(ACCEPTANCE, '').replace(MARKERS, '').replace(/\s+/g, ' ').trim(),
210
227
  conditions: acceptanceConditions(acceptance),
211
228
  criteria: criteriaRefs(rest),
212
229
  // De qué otras tareas depende. El orden del BACKLOG alcanzaba mientras hubiera un runner: con dos,
@@ -388,6 +405,23 @@ function readWip(dir, runner) {
388
405
  return parseWip(read(path.join(dir, 'wip', `${name}.md`)), name)
389
406
  }
390
407
 
408
+ // Si el checkpoint de hito sigue frenando, leído del archivo y no de que el archivo esté. Es la misma
409
+ // forma que el WIP de acá arriba —`status: IDLE` es un estado escrito— y la razón es R28: un centinela
410
+ // cuya única información es existir obliga a que el borrado sea parte de la resolución, y esa es una
411
+ // convención que alguien va a olvidar. Cuando se olvida, quien revisa lee que el hito ya se revisó
412
+ // mientras el mecanismo sigue leyendo que el archivo está, y la corrida siguiente muere en la puerta de
413
+ // entrada habiendo cargado el estado entero.
414
+ //
415
+ // Cerrado por defecto (R27): frena salvo que diga `resuelta`. Un archivo de una instancia anterior no
416
+ // trae `status`, y abrirlo por eso destrabaría en silencio al actualizar, que es la quita escrita como
417
+ // agregado que R9 nombra. El vocabulario es el mismo de `HUMAN_ACTIONS.md` a propósito: es el mismo acto
418
+ // —una persona contesta— y dos palabras para eso serían dos convenciones que aprender.
419
+ function checkpointHolds(dir) {
420
+ const text = read(path.join(dir, 'AWAITING_REVIEW.md'))
421
+ if (!text) return false
422
+ return !/^status:\s*resuelta\b/mi.test(text)
423
+ }
424
+
391
425
  // Todos los que hay. Lo pregunta `check`, que juzga si cada plan apunta a una tarea que existe, y `tree`,
392
426
  // que muestra qué está en vuelo: las dos son preguntas sobre la instancia y no sobre quien pregunta.
393
427
  function readWips(dir) {
@@ -436,6 +470,7 @@ module.exports = {
436
470
  EPIC_STATES, HUMAN_ACTION_STATES, LANES, MILESTONE_HEADING, STOP_REASONS,
437
471
  TASK_LINE, TASK_LINE_ANY_LANE,
438
472
  read, section, withoutComments, frontmatter, readEpics, readBacklog, readDone, readWip, readWips, wipName,
473
+ checkpointHolds,
439
474
  acceptanceConditions, tableRows, taskFromLine,
440
475
  readInbox, inboxHeads, readHumanActions,
441
476
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingeniomaps/cauce",
3
- "version": "0.96.0",
3
+ "version": "0.98.0",
4
4
  "description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
5
5
  "keywords": [
6
6
  "planning",
@@ -57,7 +57,7 @@ comando, sin cron —activarlo en tu repositorio es decisión tuya—:
57
57
 
58
58
  ```bash
59
59
  node tools/ops.js agents list --own # sólo los tuyos, sin los del catálogo
60
- node tools/ops.js learn <slug> # arma el informe de la semana
60
+ node tools/ops.js learn <slug> # arma el informe de investigación
61
61
  /agent-propose <slug> # escribe el cambio concreto sobre esos informes
62
62
  # ↑ firmá «Aprobación humana» en la propuesta antes de seguir
63
63
  /agent-promote <slug> # lo aplica, registra y manda a verificar
@@ -108,8 +108,9 @@ te frena es el peor para elegir bien.
108
108
  **Si lo pediste vos en el chat, no hace falta nada.** Los guards contienen al agente cuando decide solo o
109
109
  cuando trabaja dentro de un recorrido; lo que vos pedís directo no se frena. Nombrá lo que querés que
110
110
  toque —«borrá la prueba de altas», «reescribí la migración 004»— y pasa sin preguntarte de nuevo. Si tu
111
- pedido no lo nombraba y algo se frena, el agente te dice qué y por qué: contestá «dale» y pasa exactamente
112
- eso. **Con los gates de un commit se pregunta cada vez**, como con publicar: gobernanza, los gates del
111
+ pedido no lo nombraba y algo se frena, el agente te dice qué y por qué: confirmalo con tus palabras —un
112
+ «dale» alcanza, pero no hace falta esa palabra— y pasa exactamente eso. Si contestás negando, frenando o
113
+ preguntando, no pasa. **Con los gates de un commit se pregunta cada vez**, como con publicar: gobernanza, los gates del
113
114
  stack y los lockfiles no heredan lo que autorizaste en un mensaje anterior, porque cada commit es otra
114
115
  operación. Y `plan-first` no te pide un plan cuando el cambio lo pediste vos: el plan es para el trabajo que va
115
116
  por tareas. Funciona en Claude Code, Codex y Gemini, que le avisan a Cauce cuando mandás un mensaje; en
@@ -258,7 +259,7 @@ Publicar es lo único de todo eso que este proyecto puede habilitar, y `runner.a
258
259
  `ops.config.json` es la autorización que R10 pide para las ramas de trabajo. La rama viva —`main`,
259
260
  `master` o la rama por defecto del remoto— no la alcanza si el proyecto no la nombra en
260
261
  `runner.pushToLiveBranches`, y un subagente no publica con ningún permiso. Sin la llave, pasa el push
261
- que la persona pide en el chat nombrando el remoto y la rama, o el que ella aprueba contestando «dale».
262
+ que la persona pide en el chat nombrando el remoto y la rama, o el que ella confirma cuando se frena.
262
263
  Reescribir historia publicada no entra en el trato: un `push --force` se frena con la llave prendida o
263
264
  apagada.
264
265
 
package/template/Makefile CHANGED
@@ -53,7 +53,7 @@ integration-promote: require-key ## Promueve el draft KEY=<clave> al roadmap
53
53
  require-agent:
54
54
  @test -n "$(AGENT)" || (echo "Falta AGENT=<slug>" >&2; exit 2)
55
55
 
56
- agent-learn: require-agent ## Prepara el informe semanal de AGENT=<slug>
56
+ agent-learn: require-agent ## Prepara el informe de investigación de AGENT=<slug>
57
57
  @node tools/ops.js learn "$(AGENT)"
58
58
 
59
59
  agent-propose: require-agent ## Consolida una propuesta para AGENT=<slug>
@@ -3,7 +3,13 @@
3
3
  ## R8 — Un commit por naturaleza
4
4
 
5
5
  Stagear rutas explícitas, revisar el diff staged y crear un Conventional Commit en inglés. No usar
6
- `git add .`, `git add -A`, amend, force ni trailers de IA.
6
+ `git add .`, `git add -A`, force ni trailers de IA.
7
+
8
+ **Y no reescribir historia que otro ya leyó.** Lo que se protege es eso, no el comando: un `--amend`
9
+ sobre un commit publicado es la misma reescritura que un force-push y se frena igual; sobre uno que no
10
+ salió de tu máquina es la corrección, y prohibirlo no impide el resultado —`git reset --soft HEAD~1` y
11
+ volver a commitear produce exactamente lo mismo— sino el comando que lo nombra. Una regla que se cumple
12
+ mejor esquivándola se termina esquivando siempre.
7
13
 
8
14
  Dónde corta un commit lo decide la naturaleza del diff, no su tamaño ni un conteo. Una tarea suele
9
15
  tener una sola, y por eso un commit por tarea es lo habitual; cuando tiene dos, se hacen dos. Un
@@ -90,7 +96,8 @@ Push, PR, merge, tags, deploy y rollback requieren la autorización configurada
90
96
  De esos seis, el motor comprueba uno: el push, contra `runner.allowPush` —que no llega a la rama viva
91
97
  sin `runner.pushToLiveBranches`, ni a un subagente— o contra la orden que la persona da en el chat
92
98
  nombrando el remoto y la rama. Reescribir historia publicada
93
- no entra en esa autorización y se frena siempre, igual que `--amend`. Los otros cinco no tienen una
99
+ no entra en esa autorización y se frena siempre — también cuando la reescritura es un `--amend`, que el
100
+ guard distingue mirando si algún remoto alcanza al commit. Los otros cinco no tienen una
94
101
  forma reconocible en un comando —un deploy es `kubectl`, `terraform`, un script o un botón— y los
95
102
  sostiene esta regla y el review, no un guard.
96
103