@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.
- package/CHANGELOG.md +173 -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 +4 -3
- package/automatization/workflows/agent-propose.js +2 -2
- package/automatization/workflows/autobuild.js +219 -29
- package/automatization/workflows/flow.js +30 -14
- 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/cli/args.js +2 -2
- package/engine/cli/catalog.js +12 -12
- package/engine/cli/ops.js +2 -1
- package/engine/cli/planning.js +4 -1
- package/engine/hooks/approval.js +5 -3
- package/engine/hooks/chat.js +19 -7
- package/engine/hooks/push.js +3 -2
- package/engine/hooks/self-approval.js +2 -2
- package/engine/hooks/shell.js +63 -6
- package/engine/planning/contracts.js +19 -0
- package/engine/planning/parser.js +35 -0
- package/package.json +1 -1
- package/template/AGENTS.md +5 -4
- package/template/Makefile +1 -1
- 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
package/template/AGENTS.md
CHANGED
|
@@ -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
|
|
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é:
|
|
112
|
-
|
|
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
|
|
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
|
|
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`,
|
|
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
|
|
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
|
|