@ingeniomaps/cauce 0.7.5 → 0.8.1

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,34 @@ 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.1] - 2026-08-15
12
+
13
+ ### Corregido
14
+
15
+ - `integration enable` no falla si el andamiaje ya está. Habilitar no es inicializar: una instancia
16
+ que lo arrastra de una versión anterior —o que ya tiene snapshots— sólo quiere el interruptor, y
17
+ recibía un error pidiéndole un directorio vacío. Ahora repone lo que falte, conserva lo que haya y
18
+ enciende el registro.
19
+
20
+ ## [0.8.0] - 2026-08-15
21
+
22
+ ### Cambiado
23
+
24
+ - **El andamiaje de una integración se materializa al habilitarla, no antes.** Una instancia recibía
25
+ 32 KB de Jira —configuración, `staging/`, `proposed/`, tres READMEs— para un proveedor con
26
+ `enabled: false` que quizá no use nunca, y que además nadie actualizaba después. Ahora llega con
27
+ `ops integration enable <raíz> <proveedor>`, que copia el andamiaje y enciende el registro.
28
+ - `check` valida sólo los proveedores habilitados. Un proveedor registrado y apagado no tiene
29
+ andamiaje, y exigirle configuración era pedirle a la empresa que mantenga lo que no usa.
30
+ Nombrarlo explícitamente sí lo valida, que es como se comprueba antes de encenderlo.
31
+ - Una instancia existente conserva lo suyo: `integrations/<proveedor>/` puede tener snapshots y
32
+ borradores de la empresa, así que no se retira nada.
33
+
34
+ ### Corregido
35
+
36
+ - `integrations/README.md`, `integrations/AGENTS.md` y `organization/README.md` se actualizan con el
37
+ toolkit. Los escribe Cauce y envejecían para siempre en cada instancia.
38
+
11
39
  ## [0.7.5] - 2026-08-15
12
40
 
13
41
  ### Corregido
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,24 @@ 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
+ // Habilitar no es inicializar: repone lo que falte y conserva lo que ya esté. Una instancia que
698
+ // trae el andamiaje de una versión anterior —o que ya tiene snapshots— sólo quiere el interruptor.
699
+ copyTemplate(source, path.join(root, 'integrations', provider), {}, true)
700
+ config.providers[provider].enabled = true
701
+ F.atomicWriteJson(registry, config)
702
+ console.log(`✓ ${provider}: habilitado. Completá integrations/${provider}/config.json antes de sincronizar.`)
703
+ return
704
+ }
676
705
  if (action === 'check') {
677
706
  const result = I.validate(root, provider || '')
678
707
  for (const warning of result.warnings) console.warn(`⚠ ${warning}`)
@@ -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
- const providers = Object.entries(registry.providers || {}).filter(([name]) => !onlyProvider || name === onlyProvider)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingeniomaps/cauce",
3
- "version": "0.7.5",
3
+ "version": "0.8.1",
4
4
  "description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -1,4 +1,4 @@
1
- # Integraciones de {{PROJECT_NAME}}
1
+ # Integraciones
2
2
 
3
3
  Los proveedores se registran en `config.json`. Todos siguen el ciclo:
4
4