@ingeniomaps/cauce 0.32.0 → 0.33.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
@@ -14,6 +14,22 @@ desde este repositorio no va, porque el que lee no puede actuar sobre eso. Cuand
14
14
  unas pocas líneas casi siempre es porque cuenta cómo se descubrió el problema o por qué se eligió el
15
15
  diseño — eso vive en el commit y en el código.
16
16
 
17
+ ## [0.33.0] - 2026-08-19
18
+
19
+ ### Corregido
20
+
21
+ - **Con varias raíces declaradas, ningún servicio tenía nombre.** Cada repositorio es la raíz de su
22
+ propio escaneo, así que su proyecto principal volvía como `.`: tres servicios llamados igual y nada que
23
+ los distinga. Una credencial no se podía atribuir a un servicio porque ningún servicio era nombrable, y
24
+ una corrida real terminó pidiéndole a una persona que declarara variables que su propio repositorio ya
25
+ declaraba. Ahora cada candidato lleva el nombre de su raíz, y donde hay una sola el proyecto de arriba
26
+ se nombra por su carpeta en vez de aparecer como `.` a secas.
27
+
28
+ - **El arranque podía negar lo que el inventario le entregó.** Se le dice explícitamente que un nombre
29
+ que el inventario trae está declarado, así que pedir que se declare de nuevo contradice al repositorio.
30
+ La mitad de la corrección anterior que tocaba el recorrido —la que le hace copiar los nombres de
31
+ variable por servicio— no había llegado a publicarse.
32
+
17
33
  ## [0.32.0] - 2026-08-19
18
34
 
19
35
  ### Corregido
@@ -85,6 +85,10 @@ const SCAN = {
85
85
  required: ['kind', 'command', 'source'], properties: {
86
86
  kind: { type: 'string' }, command: { type: 'string' }, source: { type: 'string' },
87
87
  } } },
88
+ // Los nombres de variable que ese servicio espera, copiados del inventario. En un multirepo cada
89
+ // repositorio trae su propio ejemplo, y sin esto las credenciales de tres repos no existían para
90
+ // el arranque: las filas terminaban diciendo «la credencial del proveedor» sin nombrarla.
91
+ env: { type: 'array', items: { type: 'string' } },
88
92
  } } },
89
93
  externals: { type: 'array', items: { type: 'string' } },
90
94
  secrets: { type: 'array', items: { type: 'string' } },
@@ -110,11 +114,12 @@ const state = await agent(
110
114
  `else and open no file other than .env.example at the workspace root.\n` +
111
115
  `1. "node tools/ops.js onboard --json": the instance state, the workspace inventory, the opening ` +
112
116
  `question and the dimensions still uncovered. Copy fresh, opening, followUps, the "need" of each ` +
113
- `dimension, and every service with its path, its runtimes and its declared commands keeping the source ` +
114
- `file each command came from. Add nothing it did not print.\n` +
117
+ `dimension, and every service with its path, its runtimes, its declared commands keeping the source ` +
118
+ `file each command came from, and the variable names its "env" carries. Add nothing it did not print.\n` +
115
119
  `2. "node tools/ops.js check planning".\n` +
116
- `If .env.example exists at the workspace root, report the variable names in secrets —names only— and ` +
117
- `the external services they point at in externals.`,
120
+ `The inventory already names every credential each service expects: never open a .env file to look for ` +
121
+ `more. Report those names in secrets and the services they point at in externals. A name the inventory ` +
122
+ `carries is declared, and saying otherwise is a claim the repository contradicts.`,
118
123
  { schema: SCAN, label: 'inventario' },
119
124
  )
120
125
  if (!state) return stop('scan-unavailable', 'no se pudo leer el estado del workspace')
@@ -167,9 +172,10 @@ const drafted = await agent(
167
172
  'completa.\n'}` +
168
173
  `4. ${HUMAN}: una fila por cada cosa que necesita a una persona, con la tarea, el estado pendiente, el ` +
169
174
  `origen "onboard" y la acción concreta que la desbloquea. Como mínimo, una por cada credencial que el ` +
170
- `inventario nombra, diciendo la variable y el servicio que la espera —dónde se carga y quién lo hace, ` +
171
- `sin proponer ningún valor—, una por cada sistema externo o MCP a conectar, y una por la autoridad del ` +
172
- `runner, que hoy declara runner.allowPush=false.\n` +
175
+ `inventario nombra, diciendo la variable y el servicio que la espera. El nombre ya está declarado, así ` +
176
+ `que no pidas declararlo de nuevo: lo que falta es dónde se carga el valor y quién lo hace, y ningún ` +
177
+ `valor se propone acá. Además, una por cada sistema externo o MCP a conectar, y una por la autoridad ` +
178
+ `del runner, que hoy declara runner.allowPush=false.\n` +
173
179
  `5. Las preguntas que queden abiertas, en la sección Ideas de ${INBOX}, sin promover.\n` +
174
180
  `Devolvé en files cada archivo que tocaste y en assumptions cada supuesto que dejaste marcado.`,
175
181
  { schema: WRITTEN, label: 'contexto' },
package/engine/cli/ops.js CHANGED
@@ -363,8 +363,16 @@ function candidates(workspace, skip = '') {
363
363
  return [...found, ...result.services.map((service) => ({ ...service, root: workspace }))]
364
364
  }
365
365
 
366
+ // Con varias raíces, cada repositorio es la raíz de su propio escaneo y su candidato principal se llama
367
+ // `.`: tres servicios con el mismo nombre y nada que los distinga. El prefijo los vuelve nombrables, que
368
+ // es la única forma de que una credencial pueda atribuirse a un servicio en vez de quedar suelta.
366
369
  function inventory(root) {
367
- return workspaceRoots(root).flatMap((workspace) => candidates(workspace, root))
370
+ const roots = workspaceRoots(root)
371
+ if (roots.length === 1) return candidates(roots[0], root)
372
+ return roots.flatMap((workspace) => candidates(workspace, root).map((service) => ({
373
+ ...service,
374
+ path: service.path === '.' ? path.basename(workspace) : `${path.basename(workspace)}/${service.path}`,
375
+ })))
368
376
  }
369
377
 
370
378
  function scan(target, cli) {
@@ -374,10 +382,11 @@ function scan(target, cli) {
374
382
  // Un monorepo de sesenta paquetes no se lee en pantalla. Se recorta, y se dice cuánto: un corte que no
375
383
  // se anuncia hace pasar lo listado por todo lo que hay.
376
384
  for (const service of result.services.slice(0, LISTA)) {
377
- const donde = service.root && service.root !== result.root ? `${path.basename(service.root)}/` : ''
385
+ // El proyecto que vive en la raíz se nombra por su carpeta: `.` a secas no dice de cuál se habla.
386
+ const nombre = service.path === '.' ? `. (${path.basename(service.root || result.root)})` : service.path
378
387
  const espera = service.env ? `\n espera ${service.env.names.join(', ')} (${service.env.file})` : ''
379
388
  console.log(
380
- `${donde}${service.path} [${(service.runtimes || []).join(', ')}]${comandos(service.commands)}${espera}`,
389
+ `${nombre} [${(service.runtimes || []).join(', ')}]${comandos(service.commands)}${espera}`,
381
390
  )
382
391
  }
383
392
  if (result.services.length > LISTA) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingeniomaps/cauce",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
5
5
  "keywords": [
6
6
  "planning",