@ingeniomaps/cauce 0.7.0 → 0.7.2
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
CHANGED
|
@@ -8,7 +8,19 @@ 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.
|
|
11
|
+
## [0.7.2] - 2026-08-15
|
|
12
|
+
|
|
13
|
+
### Cambiado
|
|
14
|
+
|
|
15
|
+
- **`team` gastaba un cuarto del recorrido en transcribir salida determinista de un CLI.** Dos agentes
|
|
16
|
+
resolvían el equipo y leían su manifiesto; ahora es uno. El segundo además leía `organization/`
|
|
17
|
+
"como contexto para etapas siguientes", y cada etapa es un agente nuevo con su propio contexto: esa
|
|
18
|
+
lectura no llegaba a ninguna parte y sólo costaba tokens.
|
|
19
|
+
- Cada etapa recibe la ruta exacta del contrato de su cargo. Antes le pasaban
|
|
20
|
+
`agents/<tipo>/<slug>/SKILL.md` —con el `<tipo>` literal— y desde 0.4.0 el catálogo ni siquiera está
|
|
21
|
+
en el proyecto, así que el agente salía a buscarlo antes de poder empezar.
|
|
22
|
+
|
|
23
|
+
## [0.7.1] - 2026-08-15
|
|
12
24
|
|
|
13
25
|
### Corregido
|
|
14
26
|
|
|
@@ -19,6 +31,10 @@ minor aunque no toque una sola línea de código.
|
|
|
19
31
|
|
|
20
32
|
La raíz ahora viaja escrita en el archivo, que es lo que `automation install` ya sabía completar, y
|
|
21
33
|
es relativa a donde se abre la herramienta.
|
|
34
|
+
- **Y al arreglar eso, `team` y `autobuild` morían en la línea de cierre**: llamaban a un `finish()`
|
|
35
|
+
que el runtime tampoco trae. Peor que el anterior, porque ocurría *después* de gastar cada etapa.
|
|
36
|
+
- Dos tests recorren los workflows: uno prohíbe lo que el sandbox no expone, otro falla si se llama a
|
|
37
|
+
algo que ni el runtime da ni el archivo define.
|
|
22
38
|
|
|
23
39
|
### Cambiado
|
|
24
40
|
|
|
@@ -124,6 +124,14 @@ const CONTRACT = {
|
|
|
124
124
|
const BASE = `Never invent credentials or decisions; register external blockers in ${HUMAN}. Never execute INBOX ` +
|
|
125
125
|
`automatically. Never push, deploy, amend, force, or use git add -A. Never edit process governance, and do not ` +
|
|
126
126
|
`edit planning bookkeeping unless this workflow explicitly requests it.`
|
|
127
|
+
// Cierre del recorrido. El runtime no trae un helper de cierre —el valor devuelto por el script ya
|
|
128
|
+
// es el resultado—, y darlo por sentado hacía reventar el archivo justo al terminar: después de
|
|
129
|
+
// gastar cada etapa, en la línea que las cerraba.
|
|
130
|
+
function finish(result) {
|
|
131
|
+
log(`Fin: ${JSON.stringify(result)}`)
|
|
132
|
+
return result
|
|
133
|
+
}
|
|
134
|
+
|
|
127
135
|
const stop = (reason, detail = '') => {
|
|
128
136
|
log(`Checkpoint: ${reason}${detail ? ` — ${detail}` : ''}`)
|
|
129
137
|
return finish({ stopped: true, reason, detail })
|
|
@@ -40,8 +40,12 @@ const CANDIDATE = String(input.team || (prefix ? prefix[1] : '') || 'product-dev
|
|
|
40
40
|
const INTENT = (input.team || !prefix ? raw : prefix[2]).trim()
|
|
41
41
|
|
|
42
42
|
const MANIFEST = {
|
|
43
|
-
|
|
43
|
+
// `exists` es lo único obligatorio: el mismo agente responde "no hay tal equipo" sin poder llenar
|
|
44
|
+
// un manifiesto que no existe. El resto se exige después, cuando sí lo hay.
|
|
45
|
+
type: 'object', additionalProperties: false, required: ['exists'],
|
|
44
46
|
properties: {
|
|
47
|
+
exists: { type: 'boolean' },
|
|
48
|
+
teams: { type: 'array', items: { type: 'string' } },
|
|
45
49
|
name: { type: 'string' }, purpose: { type: 'string' },
|
|
46
50
|
outcome: { type: 'string', enum: ['epic', 'report'] },
|
|
47
51
|
entryAgent: { type: 'string' }, facilitator: { type: 'string' },
|
|
@@ -53,6 +57,9 @@ const MANIFEST = {
|
|
|
53
57
|
id: { type: 'string' }, agent: { type: 'string' }, exitGate: { type: 'string' },
|
|
54
58
|
phase: { type: 'string', enum: ['discovery', 'delivery'] },
|
|
55
59
|
produces: { type: 'array', items: { type: 'string' } },
|
|
60
|
+
// Resuelto acá una vez: sin esto cada etapa gasta llamadas buscando el contrato de su cargo,
|
|
61
|
+
// que además ya no vive en el proyecto sino en el paquete.
|
|
62
|
+
skill: { type: 'string' },
|
|
56
63
|
} } },
|
|
57
64
|
},
|
|
58
65
|
}
|
|
@@ -78,6 +85,14 @@ const EPIC = {
|
|
|
78
85
|
},
|
|
79
86
|
}
|
|
80
87
|
|
|
88
|
+
// Cierre del recorrido. El runtime no trae un helper de cierre —el valor devuelto por el script ya
|
|
89
|
+
// es el resultado—, y darlo por sentado hacía reventar el archivo justo al terminar: después de
|
|
90
|
+
// gastar cada etapa, en la línea que las cerraba.
|
|
91
|
+
function finish(result) {
|
|
92
|
+
log(`Fin: ${JSON.stringify(result)}`)
|
|
93
|
+
return result
|
|
94
|
+
}
|
|
95
|
+
|
|
81
96
|
const stop = (reason, detail = '') => {
|
|
82
97
|
log(`Checkpoint: ${reason}${detail ? ` — ${detail}` : ''}`)
|
|
83
98
|
return finish({ stopped: true, reason, detail })
|
|
@@ -92,31 +107,35 @@ const BASE = `Nunca inventes clientes, métricas, restricciones ni decisiones. N
|
|
|
92
107
|
`haría falta averiguar. No promuevas trabajo al BACKLOG, no escribas en sistemas externos y no ` +
|
|
93
108
|
`declares validado nada sin evidencia observable.`
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
{ schema: { type: 'object', required: ['exists', 'teams'], properties: {
|
|
99
|
-
exists: { type: 'boolean' }, teams: { type: 'array', items: { type: 'string' } },
|
|
100
|
-
} }, label: 'team-resolve' },
|
|
101
|
-
)
|
|
102
|
-
if (!resolved) return stop('teams-unavailable', 'no se pudo listar los equipos')
|
|
103
|
-
if (!resolved.exists && input.team) {
|
|
104
|
-
return stop('equipo-inexistente', `${CANDIDATE} no existe. Disponibles: ${resolved.teams.join(', ')}`)
|
|
105
|
-
}
|
|
106
|
-
// El prefijo era parte de la intención, no un equipo: se recompone y sigue con el equipo por defecto.
|
|
107
|
-
const TEAM = resolved.exists ? CANDIDATE : 'product-development'
|
|
108
|
-
const GOAL = resolved.exists ? INTENT : raw
|
|
109
|
-
if (!resolved.exists && prefix) log(`"${CANDIDATE}" no es un equipo: se toma el texto completo como intención.`)
|
|
110
|
-
|
|
110
|
+
// Tres comandos deterministas en un solo agente. Eran dos agentes, y el segundo además leía
|
|
111
|
+
// `organization/` "como contexto para etapas siguientes": cada etapa es un agente nuevo con su
|
|
112
|
+
// propio contexto, así que esa lectura no llegaba a ninguna parte y sólo costaba tokens.
|
|
111
113
|
const contract = await agent(
|
|
112
|
-
`${BASE}\n\
|
|
113
|
-
`
|
|
114
|
-
`
|
|
115
|
-
`
|
|
116
|
-
|
|
114
|
+
`${BASE}\n\nFrom ${ROOT}, run exactly these commands and report only what they printed. Read no ` +
|
|
115
|
+
`other file.\n` +
|
|
116
|
+
`1. "node tools/ops.js team show ${CANDIDATE} --json".\n` +
|
|
117
|
+
` If it fails, run "node tools/ops.js team list", set exists=false, report teams, and stop.\n` +
|
|
118
|
+
`2. "node tools/ops.js agents list --json", which gives each role its resolved path.\n` +
|
|
119
|
+
`Report exists=true, the manifest fields —name, purpose, outcome, entryAgent, facilitator, ` +
|
|
120
|
+
`guardrails, stages with id, phase, agent, produces and exitGate, decisionOwners flattened into ` +
|
|
121
|
+
`owners as domain/agent pairs— and for every stage set skill to "<path>/SKILL.md" using the path ` +
|
|
122
|
+
`that command 2 printed for that stage's agent.`,
|
|
117
123
|
{ schema: MANIFEST, label: 'team-contract' },
|
|
118
124
|
)
|
|
119
|
-
if (!contract) return stop('contract-unavailable', `no se pudo leer el manifiesto de ${
|
|
125
|
+
if (!contract) return stop('contract-unavailable', `no se pudo leer el manifiesto de ${CANDIDATE}`)
|
|
126
|
+
if (contract.exists === false) {
|
|
127
|
+
if (input.team) {
|
|
128
|
+
return stop('equipo-inexistente', `${CANDIDATE} no existe. Disponibles: ${(contract.teams || []).join(', ')}`)
|
|
129
|
+
}
|
|
130
|
+
// El prefijo era parte de la intención, no un equipo: se recompone y se reintenta por defecto.
|
|
131
|
+
return stop('equipo-inexistente', `"${CANDIDATE}" no es un equipo. Repetí sin el prefijo: la ` +
|
|
132
|
+
`intención completa era "${raw}". Disponibles: ${(contract.teams || []).join(', ')}`)
|
|
133
|
+
}
|
|
134
|
+
if (!contract.name || !contract.stages || !contract.guardrails) {
|
|
135
|
+
return stop('contrato-incompleto', `el manifiesto de ${CANDIDATE} no trae nombre, etapas o guardrails`)
|
|
136
|
+
}
|
|
137
|
+
const TEAM = CANDIDATE
|
|
138
|
+
const GOAL = INTENT
|
|
120
139
|
|
|
121
140
|
const owners = (contract.owners || []).map((owner) => `${owner.domain}=${owner.agent}`).join(', ')
|
|
122
141
|
const RULES = `${BASE}\n\nEquipo ${contract.name}: ${contract.purpose}\n` +
|
|
@@ -139,7 +158,8 @@ for (const stage of discovery) {
|
|
|
139
158
|
|
|
140
159
|
const result = await agent(
|
|
141
160
|
`${RULES}\n\n${previous}\n\nActuá como ${stage.agent}, respetando su contrato en ` +
|
|
142
|
-
|
|
161
|
+
`${stage.skill || `${ROOT}/agents/roles/${stage.agent}/SKILL.md`} y sus límites. ` +
|
|
162
|
+
`Etapa "${stage.id}": producí ` +
|
|
143
163
|
`${(stage.produces || []).join(' y ')}. Distinguí hechos, evidencia, supuestos y preguntas ` +
|
|
144
164
|
`abiertas. El exit gate es: "${stage.exitGate}". Marcá gatePassed sólo si se cumple de verdad; ` +
|
|
145
165
|
`si no, explicá en missing qué falta y en humanAction la acción concreta que lo desbloquea.`,
|