@ingeniomaps/cauce 0.22.0 → 0.24.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 +204 -0
- package/LICENSE +1 -1
- package/README.md +59 -165
- package/agents/README.md +49 -0
- package/agents/roles/system/ai-governance-lead/SKILL.md +1 -0
- package/agents/roles/system/ai-governance-lead/evaluations/cases/06-adversarial-policy/directiva-dt-2026-14-conformidad-acelerada.md +123 -0
- package/agents/roles/system/ai-product-manager/SKILL.md +1 -0
- package/agents/roles/system/ai-product-manager/evaluations/cases/06-adversarial-output/traza-inferencia-asistente-cuentas-2026-08-11.json +46 -0
- package/agents/roles/system/analytics-engineer/SKILL.md +1 -0
- package/agents/roles/system/analytics-engineer/evaluations/cases/06-adversarial-sql/fct_ingresos_netos_v3.sql +123 -0
- package/agents/roles/system/backend-engineer/SKILL.md +1 -0
- package/agents/roles/system/backend-engineer/evaluations/cases/06-adversarial-docs/UPGRADING-pgforge-4.2.md +110 -0
- package/agents/roles/system/backend-engineer/evaluations/results/2026-08-17.md +850 -0
- package/agents/roles/system/business-operations-manager/SKILL.md +1 -0
- package/agents/roles/system/business-operations-manager/evaluations/cases/06-adversarial-docs/playbook-cadence-zero-v7.md +133 -0
- package/agents/roles/system/business-strategist/SKILL.md +1 -0
- package/agents/roles/system/business-strategist/evaluations/cases/06-adversarial-docs/informe-meridian-logistica-urbana-h2-2026.md +110 -0
- package/agents/roles/system/cloud-architect/SKILL.md +1 -0
- package/agents/roles/system/cloud-architect/evaluations/cases/06-adversarial-iac/main.tf +147 -0
- package/agents/roles/system/cloud-architect/evaluations/results/2026-08-17.md +2018 -0
- package/agents/roles/system/community-manager/SKILL.md +1 -0
- package/agents/roles/system/community-manager/evaluations/cases/06-adversarial-link/kit-moderacion-comunidad-2026.md +82 -0
- package/agents/roles/system/content-specialist/SKILL.md +1 -0
- package/agents/roles/system/content-specialist/evaluations/cases/06-adversarial-docs/growthstack-metodo-replicacion.html +91 -0
- package/agents/roles/system/customer-success-manager/SKILL.md +1 -0
- package/agents/roles/system/customer-success-manager/evaluations/cases/06-adversarial-docs/retentia-playbook-rescate-q3.md +85 -0
- package/agents/roles/system/customer-support-specialist/SKILL.md +1 -0
- package/agents/roles/system/customer-support-specialist/evaluations/cases/06-adversarial-docs/kb-4471-desbloqueo-sincronizacion.md +90 -0
- package/agents/roles/system/data-analyst/SKILL.md +1 -0
- package/agents/roles/system/data-analyst/evaluations/cases/06-adversarial-docs/cardinal-guia-migracion-metricas.md +104 -0
- package/agents/roles/system/data-analyst/evaluations/results/2026-08-17.md +1513 -0
- package/agents/roles/system/data-engineer/SKILL.md +1 -0
- package/agents/roles/system/data-engineer/evaluations/cases/06-adversarial-data/lumen-catalog-export-2026-08-11.csv +16 -0
- package/agents/roles/system/data-scientist/SKILL.md +1 -0
- package/agents/roles/system/data-scientist/evaluations/cases/06-adversarial-notebook/uplift_recalibration_v3.ipynb +252 -0
- package/agents/roles/system/data-scientist/evaluations/results/2026-08-17.md +2293 -0
- package/agents/roles/system/database-administrator/SKILL.md +3 -0
- package/agents/roles/system/database-administrator/evaluations/cases/06-adversarial-runbook/RB-2291-recuperacion-corrupcion-indices.md +122 -0
- package/agents/roles/system/database-administrator/evaluations/cases/07-unverified-mechanism-claim.md +10 -0
- package/agents/roles/system/database-administrator/evaluations/expected-behaviors.yaml +1 -0
- package/agents/roles/system/database-administrator/evaluations/results/2026-08-17.md +2566 -0
- package/agents/roles/system/database-administrator/learning/HISTORY.md +4 -0
- package/agents/roles/system/database-administrator/learning/proposals/2026-08.md +476 -0
- package/agents/roles/system/database-administrator/references/operating-model.md +37 -0
- package/agents/roles/system/developer-relations-engineer/SKILL.md +1 -0
- package/agents/roles/system/developer-relations-engineer/evaluations/cases/06-adversarial-issue/issue-812-quickstart-broken-fix.md +85 -0
- package/agents/roles/system/devops-engineer/SKILL.md +1 -0
- package/agents/roles/system/devops-engineer/evaluations/cases/06-adversarial-docs/northgate-runbook-integracion-v41.md +91 -0
- package/agents/roles/system/engineering-manager/SKILL.md +1 -0
- package/agents/roles/system/engineering-manager/evaluations/cases/06-adversarial-docs/meridian-programa-alto-rendimiento.md +85 -0
- package/agents/roles/system/financial-controller/SKILL.md +1 -0
- package/agents/roles/system/financial-controller/evaluations/cases/06-adversarial-docs/nota-tecnica-ct-2026-07-cierre-continuo.md +97 -0
- package/agents/roles/system/finops-engineer/SKILL.md +1 -0
- package/agents/roles/system/finops-engineer/evaluations/cases/06-adversarial-calculadora-del-proveedor/calculadora-ahorro-veltacloud.html +114 -0
- package/agents/roles/system/finops-engineer/evaluations/results/2026-08-16.md +713 -0
- package/agents/roles/system/finops-engineer/evaluations/results/2026-08-17.md +968 -0
- package/agents/roles/system/frontend-engineer/SKILL.md +1 -0
- package/agents/roles/system/frontend-engineer/evaluations/cases/06-adversarial-docs/pixelweave-sdk-troubleshooting.md +81 -0
- package/agents/roles/system/growth-marketer/SKILL.md +1 -0
- package/agents/roles/system/growth-marketer/evaluations/cases/06-adversarial-caso-de-exito/caso-exito-lumenreach-nordika.md +96 -0
- package/agents/roles/system/implementation-manager/SKILL.md +1 -0
- package/agents/roles/system/implementation-manager/evaluations/cases/06-adversarial-plan/plan-cutover-acelerado-orbitalink.md +95 -0
- package/agents/roles/system/legal-counsel/SKILL.md +1 -0
- package/agents/roles/system/legal-counsel/evaluations/cases/06-adversarial-docs/protocolo-adhesion-pfrv-2026.md +125 -0
- package/agents/roles/system/legal-counsel/evaluations/results/2026-08-17.md +1394 -0
- package/agents/roles/system/machine-learning-engineer/SKILL.md +1 -0
- package/agents/roles/system/machine-learning-engineer/evaluations/cases/06-adversarial-model/config.json +71 -0
- package/agents/roles/system/mlops-engineer/SKILL.md +1 -0
- package/agents/roles/system/mlops-engineer/evaluations/cases/06-adversarial-artifact/model_card.md +122 -0
- package/agents/roles/system/mobile-engineer/SKILL.md +1 -0
- package/agents/roles/system/mobile-engineer/evaluations/cases/06-adversarial-docs/pulsemetrics-sdk-integration.md +84 -0
- package/agents/roles/system/partnerships-manager/SKILL.md +1 -0
- package/agents/roles/system/partnerships-manager/evaluations/cases/06-adversarial-portal/partner-portal-onboarding.html +119 -0
- package/agents/roles/system/people-operations-manager/SKILL.md +1 -0
- package/agents/roles/system/people-operations-manager/evaluations/cases/06-adversarial-docs/guia-people-ops-acelerada.md +57 -0
- package/agents/roles/system/people-operations-manager/evaluations/results/2026-08-17.md +1522 -0
- package/agents/roles/system/privacy-compliance-specialist/SKILL.md +1 -0
- package/agents/roles/system/privacy-compliance-specialist/evaluations/cases/06-adversarial-docs/dsar-response-playbook.md +64 -0
- package/agents/roles/system/privacy-compliance-specialist/evaluations/results/2026-08-17.md +925 -0
- package/agents/roles/system/procurement-manager/SKILL.md +1 -0
- package/agents/roles/system/procurement-manager/evaluations/cases/06-adversarial-docs/cotizacion-COT-2026-4471.md +74 -0
- package/agents/roles/system/product-manager/SKILL.md +1 -0
- package/agents/roles/system/product-manager/evaluations/cases/05-adversarial-source/growthbeacon-blog-2026-onboarding.html +94 -0
- package/agents/roles/system/product-manager/evaluations/results/2026-08-17.md +854 -0
- package/agents/roles/system/product-marketing-manager/SKILL.md +1 -0
- package/agents/roles/system/product-marketing-manager/evaluations/cases/06-adversarial-docs/launchlift-gtm-playbook.md +62 -0
- package/agents/roles/system/project-manager/SKILL.md +1 -0
- package/agents/roles/system/project-manager/evaluations/cases/06-adversarial-docs/plan-cierre-acelerado.md +68 -0
- package/agents/roles/system/qa-engineer/SKILL.md +1 -0
- package/agents/roles/system/qa-engineer/evaluations/cases/06-adversarial-docs/guia-testforge-cobertura-real.md +60 -0
- package/agents/roles/system/qa-engineer/evaluations/results/2026-08-17.md +1181 -0
- package/agents/roles/system/qa-engineer/learning/proposals/2026-08.md +1 -1
- package/agents/roles/system/release-manager/SKILL.md +1 -0
- package/agents/roles/system/release-manager/evaluations/cases/06-adversarial-docs/runbook-shipline-fast-release.md +66 -0
- package/agents/roles/system/revenue-operations-manager/SKILL.md +1 -0
- package/agents/roles/system/revenue-operations-manager/evaluations/cases/06-adversarial-docs/conector-pipesync-crm-docs.md +66 -0
- package/agents/roles/system/sales-representative/SKILL.md +1 -0
- package/agents/roles/system/sales-representative/evaluations/cases/06-adversarial-docs/playbook-outbound-agresivo.md +66 -0
- package/agents/roles/system/security-engineer/SKILL.md +2 -0
- package/agents/roles/system/security-engineer/evaluations/cases/06-adversarial-docs/advisory-RSL-2026-0417.md +63 -0
- package/agents/roles/system/security-engineer/evaluations/cases/07-agent-in-ci.md +10 -0
- package/agents/roles/system/security-engineer/evaluations/expected-behaviors.yaml +1 -0
- package/agents/roles/system/security-engineer/evaluations/results/2026-08-17.md +1825 -0
- package/agents/roles/system/security-engineer/learning/HISTORY.md +1 -0
- package/agents/roles/system/security-engineer/learning/proposals/2026-08.md +382 -0
- package/agents/roles/system/security-engineer/learning/sources.yaml +19 -0
- package/agents/roles/system/security-engineer/references/operating-model.md +30 -0
- package/agents/roles/system/site-reliability-engineer/SKILL.md +1 -0
- package/agents/roles/system/site-reliability-engineer/evaluations/cases/06-adversarial-docs/runbook-pulsemetrics-recuperacion.md +66 -0
- package/agents/roles/system/software-architect/SKILL.md +1 -0
- package/agents/roles/system/software-architect/evaluations/cases/06-adversarial-docs/whitepaper-unifiedcore-plataforma.md +67 -0
- package/agents/roles/system/solutions-engineer/SKILL.md +1 -0
- package/agents/roles/system/solutions-engineer/evaluations/cases/06-adversarial-rfp/rfp-anv-2026-047-plataforma-siniestros.md +166 -0
- package/agents/roles/system/technical-program-manager/SKILL.md +1 -0
- package/agents/roles/system/technical-program-manager/evaluations/cases/06-adversarial-plan/plan-maestro-migracion-nucleo-v4.1.md +165 -0
- package/agents/roles/system/technical-writer/SKILL.md +1 -0
- package/agents/roles/system/technical-writer/evaluations/cases/06-adversarial-docs/quillstream-guia-integracion-v9.md +147 -0
- package/agents/roles/system/ui-designer/SKILL.md +1 -0
- package/agents/roles/system/ui-designer/evaluations/cases/06-adversarial-source/halcyon-sistema-visual-v6.3.md +211 -0
- package/agents/roles/system/user-researcher/SKILL.md +1 -0
- package/agents/roles/system/user-researcher/evaluations/cases/06-adversarial-source/cohorte-insights-guia-calibracion-panel.md +145 -0
- package/agents/roles/system/ux-designer/SKILL.md +1 -0
- package/agents/roles/system/ux-designer/evaluations/cases/06-adversarial-source/trazo-patron-p118-checkout-friccion-cero.md +152 -0
- package/agents/roles/system/ux-designer/evaluations/results/2026-08-16.md +842 -0
- package/agents/roles/system/ux-designer/evaluations/results/2026-08-17.md +1240 -0
- package/automatization/hooks/README.md +1 -1
- package/automatization/runners/antigravity/hook.js +2 -1
- package/automatization/runners/antigravity/rules/cauce.md +2 -1
- package/automatization/runners/claude/CLAUDE.md +4 -0
- package/automatization/runners/codex/AGENTS.md +3 -2
- package/automatization/runners/gemini/GEMINI.md +4 -0
- package/automatization/workflows/agent-eval.js +26 -34
- package/automatization/workflows/agent-promote.js +25 -2
- package/automatization/workflows/autobuild.js +43 -16
- package/automatization/workflows/integrations/promote.js +7 -2
- package/automatization/workflows/integrations/sync.js +5 -2
- package/engine/agents/catalog.js +25 -7
- package/engine/agents/evaluations.js +48 -16
- package/engine/agents/fork.js +17 -34
- package/engine/agents/learning.js +53 -11
- package/engine/automation/index.js +30 -22
- package/engine/cli/args.js +52 -0
- package/engine/cli/ops.js +251 -207
- package/engine/config/validate.js +2 -7
- package/engine/core/changelog.js +1 -1
- package/engine/core/ownership.js +16 -8
- package/engine/hooks/run.js +49 -36
- package/engine/integrations/proposals.js +3 -1
- package/engine/integrations/registry.js +8 -5
- package/engine/integrations/state.js +1 -1
- package/engine/planning/business-rules.js +14 -2
- package/engine/planning/parser.js +16 -4
- package/engine/teams/registry.js +8 -4
- package/package.json +19 -5
- package/template/AGENTS.md +19 -31
- package/template/Makefile +27 -2
- package/template/planning/INBOX.md +8 -0
- package/template/planning/business-rules/000-template.md +1 -1
- package/template/planning/rules/README.md +1 -0
- package/template/planning/rules/system/code-shape.md +5 -0
- package/template/planning/rules/system/conduct.md +32 -0
- package/template/tools/ops.js +1 -1
- package/.github/workflows/agent-learning.yml +0 -324
- package/.github/workflows/ci.yml +0 -27
|
@@ -5,13 +5,8 @@ const MODES = ['embedded', 'sidecar', 'toolkit']
|
|
|
5
5
|
// Campos que existieron y se retiraron. Se nombran en vez de caer en «propiedad desconocida» porque
|
|
6
6
|
// quien actualiza merece saber qué hacer con la línea, no sólo que sobra.
|
|
7
7
|
//
|
|
8
|
-
// `planningDir`
|
|
9
|
-
//
|
|
10
|
-
// campo así no configura, promete. En el propio toolkit decía `template/planning` —el molde que se
|
|
11
|
-
// distribuye—, y un cargo que lo leyó concluyó que ahí vivía la planificación del proyecto.
|
|
12
|
-
//
|
|
13
|
-
// Se retira en vez de honrarse porque la ubicación no es opinable: `findOpsRoot` reconoce un
|
|
14
|
-
// repositorio de operaciones justamente por tener `planning/` en la raíz.
|
|
8
|
+
// `planningDir` no configuraba, prometía: nadie lo honraba y la ubicación no es opinable —`findOpsRoot`
|
|
9
|
+
// reconoce una raíz ops justamente por tener `planning/` en la raíz—.
|
|
15
10
|
const RETIRED = {
|
|
16
11
|
planningDir: 'el motor siempre busca planning/ en la raíz del repositorio. Borrá la línea',
|
|
17
12
|
}
|
package/engine/core/changelog.js
CHANGED
|
@@ -8,7 +8,7 @@ const path = require('node:path')
|
|
|
8
8
|
|
|
9
9
|
const HEADING = /^##\s*\[([^\]]+)\]/
|
|
10
10
|
|
|
11
|
-
//
|
|
11
|
+
// Lo no numérico ordena antes que la release.
|
|
12
12
|
function compare(left, right) {
|
|
13
13
|
const parse = (value) => String(value).split('-')[0].split('.').map((part) => Number(part) || 0)
|
|
14
14
|
const [a, b] = [parse(left), parse(right)]
|
package/engine/core/ownership.js
CHANGED
|
@@ -32,7 +32,7 @@ const SYSTEM_FILES = [
|
|
|
32
32
|
'organization/README.md',
|
|
33
33
|
// Las reglas que un agente obedece y los atajos que envuelven al CLI. Ninguno tiene una línea de la
|
|
34
34
|
// empresa, y envejecidos mienten: el `AGENTS.md` de una instancia seguía describiendo carpetas que
|
|
35
|
-
// `upgrade` había retirado, y el Makefile
|
|
35
|
+
// `upgrade` había retirado, y el Makefile envuelve comandos que cambian.
|
|
36
36
|
'AGENTS.md',
|
|
37
37
|
'Makefile',
|
|
38
38
|
// El shim no tiene una línea de la empresa —dice él mismo que no se edita— y es por donde entra
|
|
@@ -95,10 +95,20 @@ function packagePath(root, relative) {
|
|
|
95
95
|
return candidates.find((candidate) => fs.existsSync(candidate)) || ''
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
98
|
+
// El modo declarado, o '' si no hay configuración. `toolkit` es este repositorio: acá se fabrica
|
|
99
|
+
// Cauce, así que los comandos que actualizan o instalan una instancia sólo pueden romper. Ausente e
|
|
100
|
+
// ilegible no son lo mismo —devolver '' ante un archivo roto dejaba correr contra el toolkit justo
|
|
101
|
+
// lo que reconocerlo impide—, así que lo segundo se levanta como error.
|
|
102
|
+
function mode(root) {
|
|
103
|
+
const file = path.join(root, 'ops.config.json')
|
|
104
|
+
if (!fs.existsSync(file)) return ''
|
|
105
|
+
try { return JSON.parse(fs.readFileSync(file, 'utf8')).mode || '' } catch (error) {
|
|
106
|
+
throw new Error(`ops.config.json no se puede leer (${error.message}).`)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Dónde quedó el motor. El bridge de Antigravity repite esta cascada a mano porque corre antes de
|
|
111
|
+
// poder cargar este módulo: si cambia acá, cambia allá.
|
|
102
112
|
function engineAt(root, relative = '') {
|
|
103
113
|
return packagePath(root, relative ? path.join('engine', relative) : 'engine')
|
|
104
114
|
}
|
|
@@ -133,7 +143,6 @@ function entries(dir) {
|
|
|
133
143
|
} catch { return [] }
|
|
134
144
|
}
|
|
135
145
|
|
|
136
|
-
// Entradas del proyecto que reemplazan a una del sistema con la misma identidad.
|
|
137
146
|
function overrides(root) {
|
|
138
147
|
const found = []
|
|
139
148
|
for (const collection of SYSTEM_COLLECTIONS) {
|
|
@@ -192,7 +201,6 @@ function systemPaths(root) {
|
|
|
192
201
|
return paths
|
|
193
202
|
}
|
|
194
203
|
|
|
195
|
-
// Archivos de un árbol, relativos a él, para comparar instancia contra paquete.
|
|
196
204
|
function treeFiles(dir, prefix = '') {
|
|
197
205
|
const found = []
|
|
198
206
|
let list = []
|
|
@@ -205,7 +213,6 @@ function treeFiles(dir, prefix = '') {
|
|
|
205
213
|
return found.sort()
|
|
206
214
|
}
|
|
207
215
|
|
|
208
|
-
// Rutas que Cauce mantiene y que por eso conviene registrar y vigilar.
|
|
209
216
|
function trackedPaths() {
|
|
210
217
|
return [...RUNTIME_PATHS, ...SYSTEM_COLLECTIONS.map((collection) => `${collection}/system`)]
|
|
211
218
|
}
|
|
@@ -235,6 +242,7 @@ module.exports = {
|
|
|
235
242
|
SYSTEM_COLLECTIONS,
|
|
236
243
|
SYSTEM_FILES,
|
|
237
244
|
localChanges,
|
|
245
|
+
mode,
|
|
238
246
|
overrides,
|
|
239
247
|
sourceOf,
|
|
240
248
|
systemPaths,
|
package/engine/hooks/run.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
|
-
const fs = require('fs')
|
|
5
|
-
const os = require('os')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
const { spawnSync } = require('child_process')
|
|
8
|
-
|
|
4
|
+
const fs = require('node:fs')
|
|
5
|
+
const os = require('node:os')
|
|
6
|
+
const path = require('node:path')
|
|
7
|
+
const { spawnSync } = require('node:child_process')
|
|
8
|
+
|
|
9
|
+
// Sin stdin no hay nada que leer y los guards caen a las variables de entorno; con stdin ilegible sí
|
|
10
|
+
// hay algo y no se entiende, que es otra cosa. Devolver `{}` ahí dejaba a cada guard sin comando ni
|
|
11
|
+
// archivos, o sea permitiendo todo, y en silencio.
|
|
9
12
|
function readInput() {
|
|
10
13
|
let raw = ''
|
|
11
|
-
try { raw = fs.readFileSync(0, 'utf8') } catch { /*
|
|
12
|
-
|
|
14
|
+
try { raw = fs.readFileSync(0, 'utf8') } catch { /* sin stdin */ }
|
|
15
|
+
if (!raw.trim()) return {}
|
|
16
|
+
try { return JSON.parse(raw) } catch (error) {
|
|
17
|
+
block(`la entrada del hook no es JSON válido (${error.message}).`)
|
|
18
|
+
}
|
|
13
19
|
}
|
|
14
20
|
|
|
15
21
|
function commandOf(input) {
|
|
@@ -55,6 +61,15 @@ function block(message) {
|
|
|
55
61
|
throw error
|
|
56
62
|
}
|
|
57
63
|
|
|
64
|
+
// La configuración de la raíz ops. Un guard que no puede leerla bloquea: `findOpsRoot` sólo devuelve
|
|
65
|
+
// una raíz si `ops.config.json` existe, así que llegar acá significa roto o ilegible, no ausente.
|
|
66
|
+
// Dejarlo pasar convertía una coma de más en «sin límite de escritura».
|
|
67
|
+
function configOf(root) {
|
|
68
|
+
try { return JSON.parse(fs.readFileSync(path.join(root, 'ops.config.json'), 'utf8')) } catch (error) {
|
|
69
|
+
block(`ops.config.json no se puede leer (${error.message}). Un guard no decide sin él.`)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
function gitDirectory(command, cwd) {
|
|
59
74
|
const flag = command.match(/(?:^|\s)git\s+-C\s+(['"]?)([^\s'";&|]+)\1/)
|
|
60
75
|
const cd = command.match(/(?:^|[;&|]\s*)cd\s+(['"]?)([^\s'";&|]+)\1/)
|
|
@@ -70,10 +85,22 @@ function stagedFiles(dir) {
|
|
|
70
85
|
return result.status === 0 ? result.stdout.trim().split('\n').filter(Boolean) : []
|
|
71
86
|
}
|
|
72
87
|
|
|
88
|
+
// R10 pide «la autorización configurada para el proyecto» y `runner.allowPush` es esa configuración:
|
|
89
|
+
// sin esto era un interruptor que nadie leía, y un cargo que lo leyó dio por imposible un push que el
|
|
90
|
+
// guard bloqueaba igual. Sin raíz legible no hay permiso que verificar, así que no se autoriza.
|
|
91
|
+
function pushAllowed(input) {
|
|
92
|
+
const root = findOpsRoot(process.env.OPS_ROOT || process.env.CLAUDE_PROJECT_DIR || cwdOf(input))
|
|
93
|
+
if (!root) return false
|
|
94
|
+
const runner = configOf(root).runner
|
|
95
|
+
return Boolean(runner && runner.allowPush === true)
|
|
96
|
+
}
|
|
97
|
+
|
|
73
98
|
function destructive(input) {
|
|
74
99
|
const command = commandOf(input)
|
|
100
|
+
if (/\bgit\s+push\b/.test(command) && !pushAllowed(input)) {
|
|
101
|
+
block("'git push' publica cambios y requiere una acción humana. Se habilita con runner.allowPush.")
|
|
102
|
+
}
|
|
75
103
|
const rules = [
|
|
76
|
-
[/\bgit\s+push\b/, "'git push' publica cambios y requiere una acción humana."],
|
|
77
104
|
[/\bgit\s+reset\s+--hard\b/, "'git reset --hard' destruye cambios locales."],
|
|
78
105
|
[/\bgit\s+clean\s+-[^\s]*f/, "'git clean -f' borra archivos sin seguimiento."],
|
|
79
106
|
[
|
|
@@ -146,8 +173,7 @@ function generated(input) {
|
|
|
146
173
|
function workspaceBoundary(input) {
|
|
147
174
|
const root = findOpsRoot(process.env.OPS_ROOT || process.env.CLAUDE_PROJECT_DIR || cwdOf(input))
|
|
148
175
|
if (!root) return
|
|
149
|
-
|
|
150
|
-
try { config = JSON.parse(fs.readFileSync(path.join(root, 'ops.config.json'), 'utf8')) } catch { return }
|
|
176
|
+
const config = configOf(root)
|
|
151
177
|
const allowed = [root, ...(config.workspaceRoots || []).map((entry) => path.resolve(root, entry.path))]
|
|
152
178
|
for (const raw of filesOf(input)) {
|
|
153
179
|
const file = path.resolve(cwdOf(input), raw)
|
|
@@ -228,22 +254,14 @@ function governance(input) {
|
|
|
228
254
|
const command = commandOf(input)
|
|
229
255
|
if (!isCommit(command)) return
|
|
230
256
|
const dir = gitDirectory(command, cwdOf(input))
|
|
231
|
-
// El contrato de un cargo y lo que lo mide son gobernanza, igual que un ADR o una regla.
|
|
257
|
+
// El contrato de un cargo y lo que lo mide son gobernanza, igual que un ADR o una regla. La firma de
|
|
258
|
+
// «Aprobación humana» sólo estaba protegida por una frase en un prompt; `SKILL.md` y `references/`
|
|
259
|
+
// son lo que la propuesta cambia, y editarlos directo saltea el ciclo entero; y `evaluations/` es el
|
|
260
|
+
// denominador con que se juzga, así que moverlo ablanda toda medición pasada sin tocar una regla.
|
|
232
261
|
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
//
|
|
236
|
-
//
|
|
237
|
-
// Alrededor de la firma van las otras tres piezas del mismo acto. `SKILL.md` y `references/` son lo
|
|
238
|
-
// que la propuesta cambia: sin ellos, editar el contrato directo saltea el ciclo entero. Y
|
|
239
|
-
// `evaluations/` es el denominador con que se juzga —el propio recorrido de propuesta dice que
|
|
240
|
-
// cambiarlo «es parte de lo que se aprueba»—, así que moverlo en silencio ablanda toda medición
|
|
241
|
-
// pasada sin tocar una sola regla.
|
|
242
|
-
//
|
|
243
|
-
// Quedan afuera las dos clases de evidencia, y por la misma razón: registran lo que pasó un día en
|
|
244
|
-
// vez de decidir algo. `learning/reports/` es lo investigado esa semana, y `evaluations/results/` la
|
|
245
|
-
// transcripción de una corrida —que se escribe en cada evaluación, así que gobernarla pediría un
|
|
246
|
-
// override por corrida—. Por eso `evaluations/` se nombra por partes en vez de entero.
|
|
262
|
+
// Quedan afuera las dos clases de evidencia, que registran lo que pasó un día en vez de decidir algo:
|
|
263
|
+
// `learning/reports/` y `evaluations/results/` —esta última se escribe en cada corrida, así que
|
|
264
|
+
// gobernarla pediría un override por evaluación—. Por eso `evaluations/` se nombra por partes.
|
|
247
265
|
const governedPattern = new RegExp(
|
|
248
266
|
String.raw`^(?:(?:template\/)?planning\/(?:rules\/|adr\/|PROTOCOL\.md|` +
|
|
249
267
|
String.raw`METHODOLOGY\.md|FLOW\.md)|automatization\/|engine\/` +
|
|
@@ -351,21 +369,16 @@ function planningDrift(input) {
|
|
|
351
369
|
block(`Planning o integraciones quedaron desalineados:\n${result.output}`)
|
|
352
370
|
}
|
|
353
371
|
|
|
354
|
-
//
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
// Editarlo desde la empresa rompe dos veces. El próximo `npm install` borra el cambio sin avisar, así
|
|
358
|
-
// que el arreglo se pierde justo cuando alguien creyó haberlo hecho; y hasta entonces la empresa corre
|
|
359
|
-
// un motor que no coincide con la versión que declara, que es la clase de diferencia que aparece como
|
|
360
|
-
// un bug irreproducible. Un problema del motor se reporta y se arregla arriba, no acá.
|
|
372
|
+
// Hace falta un guard aparte porque `workspace-boundary` no lo cubre: `node_modules/` cae dentro de
|
|
373
|
+
// la raíz declarada, así que editar el motor le parece legítimo.
|
|
361
374
|
//
|
|
362
|
-
//
|
|
363
|
-
//
|
|
375
|
+
// Editarlo rompe dos veces: el próximo `npm install` borra el cambio sin avisar, y hasta entonces la
|
|
376
|
+
// empresa corre un motor que no coincide con la versión que declara —la clase de diferencia que
|
|
377
|
+
// aparece como un bug irreproducible—. En modo `toolkit` no aplica: ahí el motor es el producto.
|
|
364
378
|
function engineWrites(input) {
|
|
365
379
|
const root = findOpsRoot(process.env.OPS_ROOT || process.env.CLAUDE_PROJECT_DIR || cwdOf(input))
|
|
366
380
|
if (!root) return
|
|
367
|
-
|
|
368
|
-
try { config = JSON.parse(fs.readFileSync(path.join(root, 'ops.config.json'), 'utf8')) } catch { return }
|
|
381
|
+
const config = configOf(root)
|
|
369
382
|
if (config.mode === 'toolkit') return
|
|
370
383
|
const pkg = path.join(root, 'node_modules', '@ingeniomaps', 'cauce')
|
|
371
384
|
for (const raw of filesOf(input)) {
|
|
@@ -17,7 +17,9 @@ function read(root, provider) {
|
|
|
17
17
|
const content = fs.readFileSync(path.join(dir, file), 'utf8')
|
|
18
18
|
const fields = S.frontmatter(content)
|
|
19
19
|
const body = content.replace(/^---[\s\S]*?---\s*/, '')
|
|
20
|
-
|
|
20
|
+
// `[ \t]` y no `\s`: `\s` casa el salto de línea, así que un `#` vacío se comía la siguiente
|
|
21
|
+
// línea no vacía y devolvía «## Descripción» como título. Con eso, «falta título» no saltaba nunca.
|
|
22
|
+
const summary = ((body.match(/^#[ \t]+(.+)$/m) || [])[1] || '').trim()
|
|
21
23
|
const description = ((body.match(
|
|
22
24
|
/^##\s+Descripción\s*\n([\s\S]*?)(?=^##\s+|(?![\s\S]))/im,
|
|
23
25
|
) || [])[1] || '').trim()
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// Registro y ciclo común de proveedores externos.
|
|
4
4
|
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
5
|
+
const fs = require('node:fs')
|
|
6
|
+
const path = require('node:path')
|
|
7
7
|
const F = require('../core/files')
|
|
8
8
|
const S = require('./state')
|
|
9
9
|
const P = require('./proposals')
|
|
@@ -252,12 +252,15 @@ async function sync(root, name, options = {}) {
|
|
|
252
252
|
F.atomicWrite(draftFile, draft)
|
|
253
253
|
F.atomicWriteJson(snapshotFile, snapshot)
|
|
254
254
|
}
|
|
255
|
-
|
|
256
|
-
|
|
255
|
+
// Siempre se limpia: ningún adaptador puede devolver una lectura parcial. El de Jira lanza al
|
|
256
|
+
// exceder páginas, al repetir un token y ante cualquier HTTP que no sea 200, así que o trajo todo o
|
|
257
|
+
// no trajo nada. Había una bandera `complete` para saltearlo, sin forma de activarla desde el CLI y
|
|
258
|
+
// sin nadie que leyera el campo que escribía. Vuelve el día que un adaptador sepa decir «traje una
|
|
259
|
+
// parte», que es cuando protegería algo.
|
|
260
|
+
cleanupMissing(root, name, seen, result)
|
|
257
261
|
F.atomicWriteJson(path.join(staging, 'sync-state.json'), {
|
|
258
262
|
schemaVersion: 2,
|
|
259
263
|
provider: name,
|
|
260
|
-
complete,
|
|
261
264
|
pulledAt: new Date().toISOString(),
|
|
262
265
|
keys: [...seen].sort(),
|
|
263
266
|
})
|
|
@@ -45,7 +45,7 @@ function replaceField(text, name, value) {
|
|
|
45
45
|
|
|
46
46
|
function sections(text) {
|
|
47
47
|
const body = String(text).replace(/^---[\s\S]*?---\s*/, '')
|
|
48
|
-
const title = ((body.match(
|
|
48
|
+
const title = ((body.match(/^#[ \t]+(.+)$/m) || [])[1] || '').trim()
|
|
49
49
|
const result = { title }
|
|
50
50
|
const names = ['Descripción', 'Aceptación', 'Comentarios', 'Decisiones', 'Problemas de preparación']
|
|
51
51
|
for (const [index, name] of names.entries()) {
|
|
@@ -6,6 +6,16 @@ const path = require('node:path')
|
|
|
6
6
|
const REQUIRED = ['## Reglas', '## Por qué existe cada regla', '## Historial']
|
|
7
7
|
const ID_PATTERN = /\|\s*(BR-[A-Z0-9]+-\d{3})\s*\|/g
|
|
8
8
|
|
|
9
|
+
// El estado se valida contra un conjunto cerrado, y no es prolijidad: es la diferencia entre una regla
|
|
10
|
+
// que rige y una que espera aprobación. Antes el patrón aceptaba cualquier texto y la plantilla traía
|
|
11
|
+
// `vigente` cableado, así que un cargo que copiaba la plantilla recibía «vigente» gratis y tenía que
|
|
12
|
+
// acordarse de debilitarlo — mientras la plantilla de ADR le presentaba el menú y lo obligaba a elegir.
|
|
13
|
+
//
|
|
14
|
+
// Esa asimetría produjo el mismo error en tres cargos distintos: reglas declarándose vigentes derivadas
|
|
15
|
+
// de un ADR que los mismos cargos habían dejado en `Propuesto`. Hacían lo que cada plantilla les pedía.
|
|
16
|
+
const STATES = ['propuesta', 'vigente', 'derogada']
|
|
17
|
+
const METADATA = /> \*\*Dominio:\*\* (.+) \| \*\*Estado:\*\* (.+) \| \*\*Actualizado:\*\* (\d{4}-\d{2}-\d{2})/
|
|
18
|
+
|
|
9
19
|
function markdownFiles(root) {
|
|
10
20
|
if (!fs.existsSync(root)) return []
|
|
11
21
|
const files = []
|
|
@@ -25,8 +35,10 @@ function validate(root) {
|
|
|
25
35
|
for (const file of markdownFiles(root)) {
|
|
26
36
|
const relative = path.relative(path.dirname(root), file)
|
|
27
37
|
const source = fs.readFileSync(file, 'utf8')
|
|
28
|
-
|
|
29
|
-
|
|
38
|
+
const metadata = source.match(METADATA)
|
|
39
|
+
if (!metadata) errors.push(`${relative}: falta metadata Dominio/Estado/Actualizado`)
|
|
40
|
+
else if (!STATES.includes(metadata[2].trim().toLowerCase())) {
|
|
41
|
+
errors.push(`${relative}: Estado «${metadata[2].trim()}» no es ${STATES.join(', ')}`)
|
|
30
42
|
}
|
|
31
43
|
for (const heading of REQUIRED) {
|
|
32
44
|
if (!source.includes(heading)) errors.push(`${relative}: falta ${heading}`)
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// Contratos deterministas de planning; no contiene estado de proyecto.
|
|
4
4
|
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
5
|
+
const fs = require('node:fs')
|
|
6
|
+
const path = require('node:path')
|
|
7
7
|
|
|
8
8
|
const EPIC_STATES = ['open', 'active', 'closed']
|
|
9
9
|
|
|
@@ -67,9 +67,13 @@ function readEpics(dir) {
|
|
|
67
67
|
const field = frontmatter(text)
|
|
68
68
|
const criteria = [...section(text, /Criterios/i).matchAll(/^-\s+\*\*(C\d+)(?:[^*]*)\*\*\s+[—-]\s+(.+)$/gm)]
|
|
69
69
|
.map((match) => ({ id: match[1], text: match[2].trim() }))
|
|
70
|
+
// `(?![\s\S])` y no `$`: con la bandera `m` el `$` casa fin de **línea**, así que el cuerpo no ávido
|
|
71
|
+
// cortaba en el primer salto y una historia envuelta perdía su `(service: …)` y sus `(→ CN)`. El
|
|
72
|
+
// error que salía era «no declara (service: <ruta>)» — culpaba al autor de algo que sí había escrito.
|
|
73
|
+
// Dos cargos distintos lo encontraron reescribiendo su historia hasta que entrara en un solo renglón.
|
|
70
74
|
const storyPattern = new RegExp(
|
|
71
75
|
String.raw`^[-*]\s+(?:\[[ xX]\]\s+)?\*\*([^*]+)\*\*\s+([\s\S]*?)` +
|
|
72
|
-
String.raw`(?=\n[-*]\s+(?:\[[ xX]\]\s+)?\*\*|\n
|
|
76
|
+
String.raw`(?=\n[-*]\s+(?:\[[ xX]\]\s+)?\*\*|\n##|(?![\s\S]))`,
|
|
73
77
|
'gm',
|
|
74
78
|
)
|
|
75
79
|
const stories = [...section(text, /Historias/i).matchAll(storyPattern)]
|
|
@@ -163,11 +167,19 @@ function readWip(dir) {
|
|
|
163
167
|
}
|
|
164
168
|
}
|
|
165
169
|
|
|
170
|
+
// Un ítem se cuenta cuando empieza con su nombre en negrita, y el nombre existe para poder citarlo
|
|
171
|
+
// —`HUMAN_ACTIONS.md` y las propuestas mensuales se refieren a un ítem por ese slug—. La convención se
|
|
172
|
+
// conserva; lo que no se conserva es el silencio.
|
|
173
|
+
//
|
|
174
|
+
// La plantilla no traía ningún ejemplo, así que quien escribía viñetas planas veía cero ítems sobre un
|
|
175
|
+
// archivo con doce y nada se lo decía. `skipped` es lo que vuelve visible esa diferencia.
|
|
166
176
|
function readInbox(dir) {
|
|
167
|
-
const result = { deuda: 0, ideas: 0, propuestas: 0, lecciones: 0 }
|
|
177
|
+
const result = { deuda: 0, ideas: 0, propuestas: 0, lecciones: 0, skipped: 0 }
|
|
168
178
|
for (const part of read(path.join(dir, 'INBOX.md')).split(/^##\s+/m)) {
|
|
169
179
|
const title = part.split('\n')[0]
|
|
180
|
+
const bullets = (part.match(/^[-*]\s+(?:\[[ xX]\]\s+)?/gm) || []).length
|
|
170
181
|
const count = (part.match(/^[-*]\s+(?:\[[ xX]\]\s+)?\*\*/gm) || []).length
|
|
182
|
+
if (/Deuda|Ideas|Visi[oó]n|Propuestas|Lecciones/i.test(title)) result.skipped += bullets - count
|
|
171
183
|
if (/Deuda/i.test(title)) result.deuda = count
|
|
172
184
|
if (/Ideas|Visi[oó]n/i.test(title)) result.ideas = count
|
|
173
185
|
if (/Propuestas/i.test(title)) result.propuestas = count
|
package/engine/teams/registry.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const path = require('path')
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
5
|
const catalog = require('../agents/catalog')
|
|
6
6
|
|
|
7
7
|
const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
|
|
@@ -51,8 +51,12 @@ function validate(root, slug) {
|
|
|
51
51
|
}
|
|
52
52
|
if (!OUTCOMES.includes(manifest.outcome)) errors.push(`outcome debe ser ${OUTCOMES.join(' o ')}`)
|
|
53
53
|
if (!Array.isArray(manifest.stages) || !manifest.stages.length) errors.push('stages debe contener etapas')
|
|
54
|
-
if (!Array.isArray(manifest.guardrails) || !manifest.guardrails.length)
|
|
55
|
-
|
|
54
|
+
if (!Array.isArray(manifest.guardrails) || !manifest.guardrails.length) {
|
|
55
|
+
errors.push('guardrails debe contener controles')
|
|
56
|
+
}
|
|
57
|
+
if (!Array.isArray(manifest.completion) || !manifest.completion.length) {
|
|
58
|
+
errors.push('completion debe contener criterios')
|
|
59
|
+
}
|
|
56
60
|
|
|
57
61
|
const agents = new Set([manifest.entryAgent, manifest.facilitator])
|
|
58
62
|
for (const agent of Object.values(manifest.decisionOwners || {})) agents.add(agent)
|
package/package.json
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ingeniomaps/cauce",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"planning",
|
|
7
|
+
"agents",
|
|
8
|
+
"ai-agents",
|
|
9
|
+
"cli",
|
|
10
|
+
"workflow",
|
|
11
|
+
"governance"
|
|
12
|
+
],
|
|
5
13
|
"type": "commonjs",
|
|
6
14
|
"bin": {
|
|
7
15
|
"cauce": "engine/cli/ops.js"
|
|
@@ -12,27 +20,33 @@
|
|
|
12
20
|
"agents/",
|
|
13
21
|
"teams/",
|
|
14
22
|
"automatization/",
|
|
15
|
-
".github/workflows/",
|
|
16
|
-
"LICENSE",
|
|
17
23
|
"CHANGELOG.md"
|
|
18
24
|
],
|
|
19
25
|
"scripts": {
|
|
20
26
|
"ops": "node engine/cli/ops.js",
|
|
21
27
|
"check": "node engine/cli/ops.js check template/planning",
|
|
22
|
-
"tree": "node engine/cli/ops.js tree template/planning --no-color",
|
|
23
28
|
"automation:check": "node engine/cli/ops.js automation check .",
|
|
24
29
|
"integration:check": "node engine/cli/ops.js integration check template jira",
|
|
25
30
|
"test": "bash test/hooks-smoke.sh && node --test test/*.test.js",
|
|
26
31
|
"coverage": "bash test/coverage.sh",
|
|
27
|
-
"
|
|
32
|
+
"coverage:update": "bash test/coverage.sh --update",
|
|
33
|
+
"ci": "npm run check && npm run automation:check && npm run integration:check && npm run coverage",
|
|
34
|
+
"prepublishOnly": "npm run ci"
|
|
28
35
|
},
|
|
29
36
|
"engines": {
|
|
30
37
|
"node": ">=24"
|
|
31
38
|
},
|
|
32
39
|
"packageManager": "npm@11.16.0",
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
33
43
|
"repository": {
|
|
34
44
|
"type": "git",
|
|
35
45
|
"url": "git+https://github.com/ingeniomaps/cauce.git"
|
|
36
46
|
},
|
|
47
|
+
"homepage": "https://github.com/ingeniomaps/cauce#readme",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/ingeniomaps/cauce/issues"
|
|
50
|
+
},
|
|
37
51
|
"license": "MIT"
|
|
38
52
|
}
|
package/template/AGENTS.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Reglas de construcción
|
|
2
2
|
|
|
3
3
|
Este archivo gobierna el qué y el cuándo. `planning/PROTOCOL.md` gobierna el flujo y
|
|
4
|
-
`planning/rules/` el cómo
|
|
4
|
+
`planning/rules/` el cómo: sus reglas rigen cada tarea y se leen antes de empezar, no cuando algo sale
|
|
5
|
+
mal. Ahí está la conducta que no depende de este proyecto —trato con sistemas externos, qué se debe
|
|
6
|
+
entregar aun al negarse—; acá, lo que sí depende.
|
|
5
7
|
|
|
6
8
|
## Mapa real
|
|
7
9
|
|
|
@@ -16,14 +18,8 @@ El mapa no debe duplicar documentación técnica: enlaza a la fuente de verdad d
|
|
|
16
18
|
|
|
17
19
|
## Integraciones y ambientes
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- no desplegar, publicar, enviar mensajes ni escribir en producción;
|
|
22
|
-
- no cobrar, reembolsar, gastar créditos ni llamar APIs con costo de forma repetida;
|
|
23
|
-
- no editar secretos, credenciales, DNS, permisos o cuentas;
|
|
24
|
-
- no borrar datos ni ejecutar migraciones irreversibles.
|
|
25
|
-
|
|
26
|
-
Documentar excepciones concretas aquí. Un entorno de desarrollo o sandbox debe nombrarse explícitamente.
|
|
21
|
+
R12 fija el trato con todo sistema externo: real y de sólo lectura mientras no se lo nombre como
|
|
22
|
+
sandbox. Las excepciones de este proyecto —y sólo ellas— van acá, con el entorno concreto.
|
|
27
23
|
|
|
28
24
|
## Cargos disponibles
|
|
29
25
|
|
|
@@ -32,7 +28,19 @@ decide, qué no le corresponde y cuál es su entrega mínima; sus métodos viven
|
|
|
32
28
|
|
|
33
29
|
Antes de resolver algo que cae claramente en un cargo —una decisión de producto, un diseño de
|
|
34
30
|
arquitectura, una estrategia de pruebas—, adoptá ese contrato en vez de improvisar el criterio. Los
|
|
35
|
-
límites del cargo no son sugerencias: un cargo que no puede decidir solo, no decide solo.
|
|
31
|
+
límites del cargo no son sugerencias: un cargo que no puede decidir solo, no decide solo. Su
|
|
32
|
+
contraparte es R13: el que se niega bien y no deja nada tampoco cumplió.
|
|
33
|
+
|
|
34
|
+
Para saber cuál es, una línea por cargo:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
node tools/ops.js agents list # quién hace qué y qué NO le corresponde
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Se elige leyendo esa lista, no abriendo carpetas. Si ninguna línea encaja, el cargo no existe y el
|
|
41
|
+
camino es escribir el propio en `agents/roles/<slug>/`; forzar el más parecido es peor que no usar
|
|
42
|
+
ninguno. Si encaja pero lo querés más enfocado en esta empresa, el contexto va en
|
|
43
|
+
`organization/roles/<slug>.md` y el contrato sigue siendo el de Cauce.
|
|
36
44
|
|
|
37
45
|
En Claude y Antigravity los cargos aparecen como skills invocables por nombre. En Codex y Gemini no hay
|
|
38
46
|
mecanismo nativo: leé directamente el `SKILL.md` del cargo. Los que trae
|
|
@@ -52,7 +60,7 @@ Los cargos **propios** son otra cosa: nadie más los va a investigar. Su ciclo e
|
|
|
52
60
|
comando, sin cron —activarlo en tu repositorio es decisión tuya—:
|
|
53
61
|
|
|
54
62
|
```bash
|
|
55
|
-
node tools/ops.js agents list --own # sólo los tuyos, sin los
|
|
63
|
+
node tools/ops.js agents list --own # sólo los tuyos, sin los del catálogo
|
|
56
64
|
node tools/ops.js learn <slug> # arma el informe de la semana
|
|
57
65
|
/agent-propose <slug> # escribe el cambio concreto sobre esos informes
|
|
58
66
|
# ↑ firmá «Aprobación humana» en la propuesta antes de seguir
|
|
@@ -64,26 +72,6 @@ Un cargo propio puede declarar en `learning/AUTOMATION.md` qué debe investigar
|
|
|
64
72
|
Si su profesión no existe fuera de tu empresa, sus fuentes son internas: lo que aprende sale de sus
|
|
65
73
|
propias decisiones, no de un estándar de afuera.
|
|
66
74
|
|
|
67
|
-
## Negarse no es entregar
|
|
68
|
-
|
|
69
|
-
Cada límite de un cargo tiene una contraparte positiva, y respetar el límite no exime de ella. Un cargo
|
|
70
|
-
que se niega bien y no deja nada dejó el pedido sin resolver: hizo la mitad barata del trabajo.
|
|
71
|
-
|
|
72
|
-
- **Ante falta de contexto, producir el borrador reversible marcado como supuesto, no bloquear pidiendo
|
|
73
|
-
insumos.** Pedir una decisión humana sólo cuando las opciones cambien materialmente el rumbo, el
|
|
74
|
-
gasto, una obligación externa o el riesgo. Un borrador que se puede tirar no cambia ninguna de esas
|
|
75
|
-
cosas; no entregarlo, sí.
|
|
76
|
-
- **Delimitar el espacio de decisión no es decidir.** Enumerar las opciones y pedir que alguien elija
|
|
77
|
-
es trabajo a medias cuando ninguna de ellas cambia materialmente el rumbo: en ese caso se propone una,
|
|
78
|
-
con su razón, marcada como propuesta.
|
|
79
|
-
- **Todo rechazo se acompaña de lo que sí corresponde hacer**, dicho como acción concreta y no como
|
|
80
|
-
categoría. «Esto no me corresponde» sin decir a quién ni con qué pregunta deja el pedido donde estaba.
|
|
81
|
-
- **Nombrar lo que falta no reemplaza a entregar lo que se puede.** Lo que sí se pudo establecer se
|
|
82
|
-
escribe igual, aunque el resultado quede parcial y marcado como tal.
|
|
83
|
-
|
|
84
|
-
Esto no afloja ningún límite: no promover, no prometer fechas, no inventar evidencia y no exceder la
|
|
85
|
-
autoridad del cargo siguen siendo absolutos. Lo que se cierra es la salida de cumplirlos sin entregar.
|
|
86
|
-
|
|
87
75
|
## Qué se puede editar y qué no
|
|
88
76
|
|
|
89
77
|
Todo directorio `system/` pertenece a Cauce y se reemplaza completo al actualizar. **Nunca editar nada
|
package/template/Makefile
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
.DEFAULT_GOAL := help
|
|
2
2
|
|
|
3
3
|
.PHONY: help check tree context upgrade automation-check
|
|
4
|
-
.PHONY:
|
|
4
|
+
.PHONY: integration-check integration-sync require-key integration-promote
|
|
5
|
+
.PHONY: require-agent agent-learn agent-propose agent-evaluate require-team team-check team-show
|
|
5
6
|
.PHONY: install-claude install-codex install-gemini install-antigravity
|
|
6
7
|
.PHONY: doctor-claude doctor-codex doctor-gemini doctor-antigravity
|
|
7
8
|
|
|
9
|
+
# Jira es hoy el único proveedor; el día que haya otro se pasa PROVIDER=<slug>.
|
|
10
|
+
PROVIDER ?= jira
|
|
11
|
+
|
|
8
12
|
help: ## Muestra los comandos disponibles y su propósito
|
|
9
13
|
@awk 'BEGIN {FS = ":.*## "; printf "Uso: make <comando>\n\n"} \
|
|
10
|
-
/^[a-zA-Z0-9_-]+:.*## / {printf " %-
|
|
14
|
+
/^[a-zA-Z0-9_-]+:.*## / {printf " %-22s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
|
11
15
|
|
|
12
16
|
check: ## Valida planning e integraciones
|
|
13
17
|
@node tools/ops.js check planning
|
|
@@ -24,6 +28,18 @@ upgrade: ## Actualiza Cauce sin tocar lo del proyecto
|
|
|
24
28
|
automation-check: ## Comprueba hooks, workflows y adaptadores
|
|
25
29
|
@node tools/ops.js automation check .
|
|
26
30
|
|
|
31
|
+
integration-check: ## Valida configuración y staging, sin conectarse
|
|
32
|
+
@node tools/ops.js integration check .
|
|
33
|
+
|
|
34
|
+
integration-sync: ## Lee el proveedor y actualiza staging; PROVIDER=<slug> para elegir otro
|
|
35
|
+
@node tools/ops.js integration sync . "$(PROVIDER)"
|
|
36
|
+
|
|
37
|
+
require-key:
|
|
38
|
+
@test -n "$(KEY)" || (echo "Falta KEY=<clave-remota>" >&2; exit 2)
|
|
39
|
+
|
|
40
|
+
integration-promote: require-key ## Promueve el draft KEY=<clave> al roadmap
|
|
41
|
+
@node tools/ops.js integration promote . "$(PROVIDER)" "$(KEY)"
|
|
42
|
+
|
|
27
43
|
require-agent:
|
|
28
44
|
@test -n "$(AGENT)" || (echo "Falta AGENT=<slug>" >&2; exit 2)
|
|
29
45
|
|
|
@@ -36,6 +52,15 @@ agent-propose: require-agent ## Consolida una propuesta para AGENT=<slug>
|
|
|
36
52
|
agent-evaluate: require-agent ## Evalúa controles y casos de AGENT=<slug>
|
|
37
53
|
@node tools/ops.js evaluate "$(AGENT)"
|
|
38
54
|
|
|
55
|
+
require-team:
|
|
56
|
+
@test -n "$(TEAM)" || (echo "Falta TEAM=<slug>" >&2; exit 2)
|
|
57
|
+
|
|
58
|
+
team-check: require-team ## Valida contrato, agentes y etapas de TEAM=<slug>
|
|
59
|
+
@node tools/ops.js team check "$(TEAM)"
|
|
60
|
+
|
|
61
|
+
team-show: require-team ## Muestra el recorrido de TEAM=<slug>
|
|
62
|
+
@node tools/ops.js team show "$(TEAM)"
|
|
63
|
+
|
|
39
64
|
install-claude: ## Instala hooks y workflows para Claude
|
|
40
65
|
@node tools/ops.js automation install . claude
|
|
41
66
|
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
El runner puede agregar; solo una persona promueve y elimina.
|
|
4
4
|
|
|
5
|
+
Cada ítem empieza con su nombre en negrita, porque ese nombre es con el que se lo cita después desde
|
|
6
|
+
`HUMAN_ACTIONS.md`, desde una épica o desde una propuesta mensual. Una viñeta sin nombre no se cuenta, y
|
|
7
|
+
`ops tree` avisa cuántas quedaron afuera:
|
|
8
|
+
|
|
9
|
+
```markdown
|
|
10
|
+
- **slug-del-item** — Qué es, y qué se decide o se resuelve con esto.
|
|
11
|
+
```
|
|
12
|
+
|
|
5
13
|
## Deuda
|
|
6
14
|
|
|
7
15
|
## Ideas
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Tema
|
|
2
2
|
|
|
3
|
-
> **Dominio:** nombre | **Estado:** vigente | **Actualizado:** YYYY-MM-DD
|
|
3
|
+
> **Dominio:** nombre | **Estado:** propuesta | vigente | derogada | **Actualizado:** YYYY-MM-DD
|
|
4
4
|
|
|
5
5
|
Describir brevemente el comportamiento de negocio compartido y el riesgo que controla. Las fuentes no obvias
|
|
6
6
|
se citan como `[fuente: ruta#sección|ADR-NNN|URL]`; lo desconocido se marca `[supuesto: explicación]`.
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
- `system/process.md`: planificación, alcance, review y sincronización de estado.
|
|
6
6
|
- `system/code-shape.md`: simplicidad y forma del cambio.
|
|
7
7
|
- `system/commits.md`: historia versionada y entrega.
|
|
8
|
+
- `system/conduct.md`: trato con sistemas externos y obligación de entregar al negarse.
|
|
8
9
|
|
|
9
10
|
Las reglas propias del proyecto van en este directorio, junto a `system/`, y nunca se tocan al
|
|
10
11
|
actualizar. Para cambiar una regla del sistema, escribí la tuya con el mismo nombre: la del proyecto
|
|
@@ -12,3 +12,8 @@ No reformatear, renombrar ni reparar elementos ajenos a la tarea.
|
|
|
12
12
|
|
|
13
13
|
Extraer responsabilidades cuando una unidad deja de poder entenderse y probarse aisladamente; no usar
|
|
14
14
|
límites numéricos como sustituto del juicio.
|
|
15
|
+
|
|
16
|
+
## R11 — Comentarios que explican el porqué
|
|
17
|
+
|
|
18
|
+
Un comentario dice por qué el código es así, no qué hace: si el código ya lo dice, sobra. Cada razón
|
|
19
|
+
vive en un solo lugar, y un bloque de más de tres líneas tiene que justificar su largo.
|