@ingeniomaps/cauce 0.7.4 → 0.8.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
CHANGED
|
@@ -8,6 +8,37 @@ 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.8.0] - 2026-08-15
|
|
12
|
+
|
|
13
|
+
### Cambiado
|
|
14
|
+
|
|
15
|
+
- **El andamiaje de una integración se materializa al habilitarla, no antes.** Una instancia recibía
|
|
16
|
+
32 KB de Jira —configuración, `staging/`, `proposed/`, tres READMEs— para un proveedor con
|
|
17
|
+
`enabled: false` que quizá no use nunca, y que además nadie actualizaba después. Ahora llega con
|
|
18
|
+
`ops integration enable <raíz> <proveedor>`, que copia el andamiaje y enciende el registro.
|
|
19
|
+
- `check` valida sólo los proveedores habilitados. Un proveedor registrado y apagado no tiene
|
|
20
|
+
andamiaje, y exigirle configuración era pedirle a la empresa que mantenga lo que no usa.
|
|
21
|
+
Nombrarlo explícitamente sí lo valida, que es como se comprueba antes de encenderlo.
|
|
22
|
+
- Una instancia existente conserva lo suyo: `integrations/<proveedor>/` puede tener snapshots y
|
|
23
|
+
borradores de la empresa, así que no se retira nada.
|
|
24
|
+
|
|
25
|
+
### Corregido
|
|
26
|
+
|
|
27
|
+
- `integrations/README.md`, `integrations/AGENTS.md` y `organization/README.md` se actualizan con el
|
|
28
|
+
toolkit. Los escribe Cauce y envejecían para siempre en cada instancia.
|
|
29
|
+
|
|
30
|
+
## [0.7.5] - 2026-08-15
|
|
31
|
+
|
|
32
|
+
### Corregido
|
|
33
|
+
|
|
34
|
+
- `learn` y `evaluate` resuelven la raíz ops como el resto de los comandos. Quedaron con `cwd` cuando
|
|
35
|
+
los demás pasaron a usarla: invocados desde la carpeta de la compañía —lo normal en sidecar— no
|
|
36
|
+
encontraban ningún cargo.
|
|
37
|
+
- **`evaluate` le exigía a una empresa un archivo del toolkit.** `learning/CODEX_AUTOMATION.md`
|
|
38
|
+
documenta cómo corre nuestra automatización de aprendizaje; pedírselo a quien escribe un cargo
|
|
39
|
+
propio era pedirle contabilidad interna nuestra. Ahora sólo se exige a los cargos del sistema: el
|
|
40
|
+
cargo de una empresa necesita contrato, fuentes e historia, no nuestro andamiaje.
|
|
41
|
+
|
|
11
42
|
## [0.7.4] - 2026-08-15
|
|
12
43
|
|
|
13
44
|
### Corregido
|
|
@@ -127,9 +127,12 @@ function evaluate(root, agent) {
|
|
|
127
127
|
const requiredFiles = [
|
|
128
128
|
'learning/sources.yaml',
|
|
129
129
|
'learning/HISTORY.md',
|
|
130
|
-
'learning/CODEX_AUTOMATION.md',
|
|
131
130
|
'evaluations/expected-behaviors.yaml',
|
|
132
131
|
]
|
|
132
|
+
// `CODEX_AUTOMATION.md` documenta cómo corre la automatización de aprendizaje del toolkit. Exigírselo
|
|
133
|
+
// a una empresa que escribe un cargo propio era pedirle contabilidad interna nuestra: su cargo debe
|
|
134
|
+
// tener contrato, fuentes e historia, no nuestro andamiaje.
|
|
135
|
+
if (require('./catalog').find(root, agent).system) requiredFiles.push('learning/CODEX_AUTOMATION.md')
|
|
133
136
|
for (const relative of requiredFiles) {
|
|
134
137
|
if (!fs.existsSync(path.join(target, relative))) errors.push(`falta ${relative}`)
|
|
135
138
|
}
|
package/engine/cli/ops.js
CHANGED
|
@@ -33,6 +33,7 @@ function usage() {
|
|
|
33
33
|
ops upgrade <ops-root> [--check] [--force]
|
|
34
34
|
ops archive <planning-dir> <NNN>
|
|
35
35
|
ops integration list <ops-root>
|
|
36
|
+
ops integration enable <ops-root> <provider>
|
|
36
37
|
ops integration check <ops-root> [provider]
|
|
37
38
|
ops integration sync <ops-root> <provider> [--fixture <json>]
|
|
38
39
|
ops integration promote <ops-root> <provider> <remote-key>
|
|
@@ -127,6 +128,16 @@ function declareEngine(manifest, version) {
|
|
|
127
128
|
F.atomicWriteJson(manifest, pkg)
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
// Proveedores que el toolkit conoce. El andamiaje de cada uno —configuración, staging/, proposed/—
|
|
132
|
+
// no se materializa hasta que alguien lo habilite: hoy una instancia recibe 32 KB de un proveedor
|
|
133
|
+
// apagado que quizá no use nunca, y que nadie actualiza después.
|
|
134
|
+
function providerNames() {
|
|
135
|
+
try {
|
|
136
|
+
const file = path.join(PROJECT_ROOT, 'template', 'integrations', 'config.json')
|
|
137
|
+
return Object.keys(JSON.parse(fs.readFileSync(file, 'utf8')).providers || {})
|
|
138
|
+
} catch { return [] }
|
|
139
|
+
}
|
|
140
|
+
|
|
130
141
|
function init(target) {
|
|
131
142
|
if (!target) fail('Falta <destino>.', 2)
|
|
132
143
|
const mode = option('--mode', 'embedded')
|
|
@@ -142,7 +153,7 @@ function init(target) {
|
|
|
142
153
|
'{{MODE}}': mode,
|
|
143
154
|
'{{PLANNING_DIR}}': 'planning',
|
|
144
155
|
'{{WORKSPACE_PATH}}': mode === 'embedded' ? '.' : '..',
|
|
145
|
-
}, process.argv.includes('--force'))
|
|
156
|
+
}, process.argv.includes('--force'), providerNames())
|
|
146
157
|
// `ci.yml` valida el toolkit con `npm run ci`; una instancia no tiene ese script ni sus pruebas.
|
|
147
158
|
copyTemplate(path.join(PROJECT_ROOT, '.github', 'workflows'), path.join(root, '.github', 'workflows'), {
|
|
148
159
|
'{{PROJECT_NAME}}': name,
|
|
@@ -673,6 +684,22 @@ async function integration(action, rootArg, provider, key) {
|
|
|
673
684
|
}
|
|
674
685
|
return
|
|
675
686
|
}
|
|
687
|
+
if (action === 'enable') {
|
|
688
|
+
if (!provider) fail('Falta <provider>.', 2)
|
|
689
|
+
const source = path.join(PROJECT_ROOT, 'template', 'integrations', provider)
|
|
690
|
+
if (!fs.existsSync(source)) fail(`Cauce no trae un adaptador para ${provider}.`, 2)
|
|
691
|
+
const registry = path.join(root, 'integrations', 'config.json')
|
|
692
|
+
let config
|
|
693
|
+
try { config = JSON.parse(fs.readFileSync(registry, 'utf8')) } catch (error) {
|
|
694
|
+
fail(`integrations/config.json ilegible: ${error.message}`)
|
|
695
|
+
}
|
|
696
|
+
if (!config.providers || !config.providers[provider]) fail(`${provider} no está en integrations/config.json.`)
|
|
697
|
+
copyTemplate(source, path.join(root, 'integrations', provider), {}, process.argv.includes('--force'))
|
|
698
|
+
config.providers[provider].enabled = true
|
|
699
|
+
F.atomicWriteJson(registry, config)
|
|
700
|
+
console.log(`✓ ${provider}: habilitado. Completá integrations/${provider}/config.json antes de sincronizar.`)
|
|
701
|
+
return
|
|
702
|
+
}
|
|
676
703
|
if (action === 'check') {
|
|
677
704
|
const result = I.validate(root, provider || '')
|
|
678
705
|
for (const warning of result.warnings) console.warn(`⚠ ${warning}`)
|
|
@@ -761,16 +788,16 @@ function automation(action, rootArg, runnerName) {
|
|
|
761
788
|
function learn(agent) {
|
|
762
789
|
try {
|
|
763
790
|
const result = process.argv.includes('--proposal')
|
|
764
|
-
? L.prepareProposal(
|
|
765
|
-
: L.prepareReport(
|
|
766
|
-
console.log(`${result.created ? '+' : '='} ${path.relative(
|
|
791
|
+
? L.prepareProposal(opsRoot(), agent)
|
|
792
|
+
: L.prepareReport(opsRoot(), agent)
|
|
793
|
+
console.log(`${result.created ? '+' : '='} ${path.relative(opsRoot(), result.file)}`)
|
|
767
794
|
if (typeof result.reports === 'number') console.log(` ${result.reports} informe(s) semanal(es) incluidos`)
|
|
768
795
|
} catch (error) { fail(error.message, 2) }
|
|
769
796
|
}
|
|
770
797
|
|
|
771
798
|
function evaluate(agent) {
|
|
772
799
|
try {
|
|
773
|
-
const result = L.evaluate(
|
|
800
|
+
const result = L.evaluate(opsRoot(), agent)
|
|
774
801
|
for (const error of result.errors) console.error(`✗ ${error}`)
|
|
775
802
|
if (result.errors.length) fail(`\n${result.errors.length} error(es)`, 1)
|
|
776
803
|
console.log(
|
package/engine/core/ownership.js
CHANGED
|
@@ -27,6 +27,9 @@ const SYSTEM_FILES = [
|
|
|
27
27
|
'teams/README.md',
|
|
28
28
|
'automatization/README.md',
|
|
29
29
|
'automatization/AGENTS.md',
|
|
30
|
+
'integrations/README.md',
|
|
31
|
+
'integrations/AGENTS.md',
|
|
32
|
+
'organization/README.md',
|
|
30
33
|
// El shim no tiene una línea de la empresa —dice él mismo que no se edita— y es por donde entra
|
|
31
34
|
// cada comando. Sin declararlo, envejecía para siempre en la instancia.
|
|
32
35
|
'tools/ops.js',
|
|
@@ -68,7 +68,11 @@ function validate(root, onlyProvider = '') {
|
|
|
68
68
|
const warnings = []
|
|
69
69
|
let registry
|
|
70
70
|
try { registry = readJson(registryFile) } catch (error) { return { errors: [error.message], warnings } }
|
|
71
|
-
|
|
71
|
+
// Sólo los habilitados: un proveedor registrado y apagado no tiene andamiaje —se materializa al
|
|
72
|
+
// habilitarlo— y exigirle configuración sería pedirle a la empresa que mantenga lo que no usa.
|
|
73
|
+
// Nombrarlo explícitamente sí lo valida, que es como se comprueba antes de encenderlo.
|
|
74
|
+
const providers = Object.entries(registry.providers || {})
|
|
75
|
+
.filter(([name, entry]) => (onlyProvider ? name === onlyProvider : entry && entry.enabled))
|
|
72
76
|
let workspaces = []
|
|
73
77
|
try {
|
|
74
78
|
const ops = readJson(path.join(root, 'ops.config.json'))
|
|
@@ -81,6 +85,10 @@ function validate(root, onlyProvider = '') {
|
|
|
81
85
|
}
|
|
82
86
|
if (!providers.length && onlyProvider) errors.push(`Proveedor no registrado: ${onlyProvider}`)
|
|
83
87
|
for (const [name, entry] of providers) {
|
|
88
|
+
if (!fs.existsSync(path.join(root, 'integrations', name))) {
|
|
89
|
+
errors.push(`${name}: no está materializado. Corré "ops integration enable <raíz> ${name}"`)
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
84
92
|
if (!entry.adapter) errors.push(`${name}: falta adapter`)
|
|
85
93
|
let loaded
|
|
86
94
|
try { loaded = providerConfig(root, name) } catch (error) { errors.push(error.message); continue }
|
package/package.json
CHANGED