@saulwade/swl-ses 2.5.3 → 2.6.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.
Files changed (214) hide show
  1. package/CLAUDE.md +9 -9
  2. package/README.md +37 -37
  3. package/agentes/_intent-spec.md +73 -73
  4. package/agentes/_propose-step.md +90 -90
  5. package/agentes/accesibilidad-wcag-swl.md +690 -690
  6. package/agentes/arquitecto-swl.md +267 -267
  7. package/agentes/auto-evolucion-swl.md +932 -908
  8. package/agentes/backend-csharp-swl.md +420 -420
  9. package/agentes/backend-go-swl.md +390 -390
  10. package/agentes/backend-java-swl.md +281 -281
  11. package/agentes/backend-rust-swl.md +364 -364
  12. package/agentes/backend-workers-swl.md +482 -482
  13. package/agentes/cloud-infra-swl.md +509 -509
  14. package/agentes/consolidador-swl.md +541 -541
  15. package/agentes/depurador-swl.md +352 -352
  16. package/agentes/devops-ci-swl.md +400 -400
  17. package/agentes/disenador-ui-swl.md +569 -569
  18. package/agentes/documentador-swl.md +345 -345
  19. package/agentes/frontend-angular-swl.md +621 -621
  20. package/agentes/frontend-css-swl.md +716 -716
  21. package/agentes/frontend-react-swl.md +692 -692
  22. package/agentes/frontend-swl.md +496 -496
  23. package/agentes/frontend-tailwind-swl.md +826 -826
  24. package/agentes/investigador-swl.md +432 -432
  25. package/agentes/investigador-ux-swl.md +505 -505
  26. package/agentes/migrador-swl.md +442 -442
  27. package/agentes/mobile-android-swl.md +511 -511
  28. package/agentes/mobile-cross-swl.md +541 -541
  29. package/agentes/mobile-ios-swl.md +502 -502
  30. package/agentes/mobile-testing-swl.md +302 -302
  31. package/agentes/nemesis-auditor-swl.md +285 -285
  32. package/agentes/observabilidad-swl.md +438 -438
  33. package/agentes/pagos-swl.md +310 -310
  34. package/agentes/perfilador-usuario-swl.md +321 -321
  35. package/agentes/planificador-swl.md +399 -399
  36. package/agentes/producto-prd-swl.md +589 -589
  37. package/agentes/red-team-swl.md +218 -218
  38. package/agentes/release-manager-swl.md +590 -590
  39. package/agentes/rendimiento-swl.md +713 -713
  40. package/agentes/revisor-angular-swl.md +278 -278
  41. package/agentes/revisor-csharp-swl.md +264 -264
  42. package/agentes/revisor-go-swl.md +259 -259
  43. package/agentes/revisor-java-swl.md +257 -257
  44. package/agentes/revisor-kotlin-swl.md +273 -273
  45. package/agentes/revisor-nextjs-swl.md +281 -281
  46. package/agentes/revisor-php-swl.md +271 -271
  47. package/agentes/revisor-react-swl.md +278 -278
  48. package/agentes/revisor-rust-swl.md +346 -346
  49. package/agentes/revisor-seguridad-swl.md +399 -399
  50. package/agentes/revisor-swift-swl.md +268 -268
  51. package/agentes/revisor-typescript-swl.md +346 -346
  52. package/agentes/tdd-qa-swl.md +393 -393
  53. package/bin/swl-ses.js +32 -7
  54. package/comandos/swl/actualizar.md +3 -3
  55. package/comandos/swl/aprender.md +13 -0
  56. package/comandos/swl/deuda-codigo.md +97 -97
  57. package/comandos/swl/evaluar-skill.md +18 -3
  58. package/comandos/swl/evolucion-continua.md +73 -0
  59. package/comandos/swl/evolucionar.md +13 -0
  60. package/comandos/swl/instalar.md +4 -4
  61. package/comandos/swl/notificaciones.md +1 -1
  62. package/comandos/swl/status.md +2 -2
  63. package/gateway/cron/jobs.example.json +12 -0
  64. package/habilidades/auto-evolucion-protocolo/SKILL.md +19 -1
  65. package/habilidades/autoresearch/SKILL.md +3 -2
  66. package/habilidades/backend-async-postgres-testing/SKILL.md +2 -1
  67. package/habilidades/benchmark-memoria/SKILL.md +7 -7
  68. package/habilidades/changelog-generator/SKILL.md +1 -1
  69. package/habilidades/changelog-generator/scripts/parse-commits.js +2 -1
  70. package/habilidades/checkpoints-verificacion/SKILL.md +6 -0
  71. package/habilidades/compactacion-contexto/SKILL.md +2 -1
  72. package/habilidades/contenedores-docker/SKILL.md +4 -2
  73. package/habilidades/context-builder/SKILL.md +4 -0
  74. package/habilidades/doubt-driven-review/SKILL.md +17 -1
  75. package/habilidades/drift-detection/SKILL.md +6 -1
  76. package/habilidades/ejecutar-fase/SKILL.md +6 -6
  77. package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
  78. package/habilidades/eval-framework/SKILL.md +8 -3
  79. package/habilidades/extractor-de-aprendizajes/SKILL.md +8 -2
  80. package/habilidades/git-worktrees-paralelo/SKILL.md +19 -1
  81. package/habilidades/harness-claude-code/SKILL.md +7 -3
  82. package/habilidades/infra-github-actions/SKILL.md +4 -3
  83. package/habilidades/instalar-sistema/SKILL.md +5 -1
  84. package/habilidades/memoria-busqueda/SKILL.md +31 -39
  85. package/habilidades/planear-fase/SKILL.md +9 -1
  86. package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -166
  87. package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -85
  88. package/habilidades/proceso-ddia-fundamentos/SKILL.md +3 -2
  89. package/habilidades/proceso-ingenieria-requerimientos/SKILL.md +147 -147
  90. package/habilidades/release-semver/SKILL.md +2 -2
  91. package/habilidades/swl-claudemd/SKILL.md +6 -7
  92. package/habilidades/swl-dashboard/SKILL.md +11 -43
  93. package/habilidades/tdd-workflow/SKILL.md +12 -7
  94. package/habilidades/validacion-ci-sistema/SKILL.md +1 -1
  95. package/hooks/agente-lifecycle.js +2 -1
  96. package/hooks/aiisms-detector.js +13 -4
  97. package/hooks/audit-trail.js +2 -1
  98. package/hooks/auto-consolidacion.js +2 -1
  99. package/hooks/captura-acciones-post.js +2 -1
  100. package/hooks/captura-acciones-session.js +2 -1
  101. package/hooks/captura-feedback-usuario.js +3 -2
  102. package/hooks/claudemd-bloat-detector.js +12 -3
  103. package/hooks/claudemd-duplicacion-detector.js +13 -3
  104. package/hooks/contexto-iteracion.js +2 -1
  105. package/hooks/contexto-subagente.js +68 -68
  106. package/hooks/degradacion-instintos.js +2 -1
  107. package/hooks/extraccion-aprendizajes.js +109 -15
  108. package/hooks/grafo-contexto.js +2 -1
  109. package/hooks/guardrail-modelo.js +2 -1
  110. package/hooks/inbox-aviso.js +2 -1
  111. package/hooks/inyeccion-contexto.js +2 -1
  112. package/hooks/lib/agent-matcher.js +2 -1
  113. package/hooks/lib/agent-routing.js +2 -1
  114. package/hooks/lib/autonomia.js +5 -3
  115. package/hooks/lib/captura-acciones.js +2 -1
  116. package/hooks/lib/consolidation-lock.js +21 -10
  117. package/hooks/lib/etapa-auto-evolucion.js +10 -4
  118. package/hooks/lib/etapa-metricas.js +2 -1
  119. package/hooks/lib/etapa-perfil-usuario.js +20 -4
  120. package/hooks/lib/evolution-tracker.js +2 -1
  121. package/hooks/lib/gateway-notify.js +17 -3
  122. package/hooks/lib/loop-telemetry.js +5 -4
  123. package/hooks/lib/mcp-health.js +2 -1
  124. package/hooks/lib/memory-search.js +4 -0
  125. package/hooks/lib/merkle-audit.js +58 -6
  126. package/hooks/lib/notificacion-formato.js +58 -0
  127. package/hooks/lib/nudge-tracker.js +2 -1
  128. package/hooks/lib/otlp-exporter.js +2 -1
  129. package/hooks/lib/propose-step.js +3 -2
  130. package/hooks/lib/raiz-proyecto.js +127 -0
  131. package/hooks/lib/run-log.js +2 -1
  132. package/hooks/lib/singleton-guard.js +225 -27
  133. package/hooks/lib/telegram-cliente.js +28 -11
  134. package/hooks/notificacion-telegram.js +13 -3
  135. package/hooks/preservar-estado-pre-compact.js +2 -1
  136. package/hooks/proteccion-rutas.js +59 -3
  137. package/hooks/registro-turnos.js +2 -1
  138. package/hooks/resumen-sesion.js +2 -1
  139. package/hooks/risk-scoring.js +2 -1
  140. package/hooks/rotar-audit-auto.js +46 -20
  141. package/hooks/session-briefing.js +127 -1
  142. package/hooks/spec-gate.js +2 -1
  143. package/hooks/sugerir-contribuir.js +6 -3
  144. package/hooks/sugerir-regenerar-inventario.js +3 -2
  145. package/hooks/tdd-gate.js +2 -1
  146. package/hooks/telemetria-agentes.js +2 -1
  147. package/hooks/telemetria-skill-routing.js +2 -1
  148. package/hooks/tracking-costos.js +4 -3
  149. package/hooks/validar-formato-post-subagente.js +2 -1
  150. package/hooks/validar-intent-spec.js +2 -1
  151. package/hooks/validar-memoria-hook.js +13 -3
  152. package/hooks/validar-planning-paths.js +2 -1
  153. package/instintos/perfil-usuario.yaml +506 -3
  154. package/instintos/proyecto.yaml +78 -0
  155. package/llms.txt +29 -29
  156. package/manifiestos/canonical-hashes.json +5588 -4925
  157. package/manifiestos/hooks-config.json +469 -469
  158. package/manifiestos/invariantes-criticos.json +30 -30
  159. package/manifiestos/modulos.json +1429 -1423
  160. package/manifiestos/planning-paths.json +1 -0
  161. package/manifiestos/skills-lock.json +1275 -1275
  162. package/package.json +94 -95
  163. package/plugin.json +369 -369
  164. package/scripts/actualizar.js +3 -0
  165. package/scripts/auditar-clases-conocidas.js +134 -106
  166. package/scripts/benchmark-memoria.js +1 -0
  167. package/scripts/bootstrap-instintos.js +85 -14
  168. package/scripts/canario-hooks.js +166 -166
  169. package/scripts/cli/autonomia.js +23 -0
  170. package/scripts/cli/benchmark-memoria.js +37 -0
  171. package/scripts/cli/ciclo-autonomo.js +73 -0
  172. package/scripts/cli/ciclo-fase-b.js +102 -0
  173. package/scripts/cli/guardrail-metrics.js +39 -0
  174. package/scripts/cli/loop-telemetry.js +4 -2
  175. package/scripts/cli/memoria-search.js +69 -0
  176. package/scripts/cli/nudge-accionar.js +39 -0
  177. package/scripts/cli/run-eval.js +38 -0
  178. package/scripts/cli/run-skill-evals.js +13 -2
  179. package/scripts/derivar-feature-list.js +15 -14
  180. package/scripts/desinstalar.js +11 -0
  181. package/scripts/doctor.js +50 -13
  182. package/scripts/evidencia-valor.js +101 -101
  183. package/scripts/field-report.js +16 -16
  184. package/scripts/instalador.js +98 -7
  185. package/scripts/lib/activar-hooks-proyecto.js +116 -104
  186. package/scripts/lib/auditar-invocaciones-comandos.js +96 -6
  187. package/scripts/lib/ciclo-autonomo/candidatos.js +174 -0
  188. package/scripts/lib/ciclo-autonomo/config.js +165 -0
  189. package/scripts/lib/ciclo-autonomo/drenador-feedback.js +174 -0
  190. package/scripts/lib/ciclo-autonomo/fallback.js +77 -0
  191. package/scripts/lib/ciclo-autonomo/guard-convivencia.js +139 -0
  192. package/scripts/lib/ciclo-autonomo/higiene-nudges.js +112 -0
  193. package/scripts/lib/ciclo-autonomo/index.js +301 -0
  194. package/scripts/lib/ciclo-autonomo/lock.js +124 -0
  195. package/scripts/lib/ciclo-autonomo/presupuesto.js +122 -0
  196. package/scripts/lib/ciclo-autonomo/puente-degradacion.js +240 -0
  197. package/scripts/lib/ciclo-autonomo/runner-fase-b.js +248 -0
  198. package/scripts/lib/ciclo-autonomo/writer-instintos.js +190 -0
  199. package/scripts/lib/ciclo-autonomo/yaml-instintos.js +535 -0
  200. package/scripts/lib/estado.js +9 -0
  201. package/scripts/lib/evidencia-valor.js +228 -228
  202. package/scripts/lib/expandir-targets.js +71 -71
  203. package/scripts/lib/gitignore-manifest.js +8 -1
  204. package/scripts/lib/hooks-settings.js +45 -0
  205. package/scripts/lib/limpiar-basura-global.js +161 -0
  206. package/scripts/lib/toml-merge.js +204 -204
  207. package/scripts/mcp-server/auth.js +105 -105
  208. package/scripts/mcp-server/cache.js +106 -106
  209. package/scripts/rotar-audit-logs.js +48 -2
  210. package/scripts/run-eval.js +1 -0
  211. package/scripts/run-skill-evals.js +287 -8
  212. package/scripts/smoke-test.js +16 -8
  213. package/scripts/tui/pantallas/install-wizard.js +69 -13
  214. package/scripts/validar.js +40 -1
@@ -19,7 +19,9 @@
19
19
  */
20
20
 
21
21
  const fs = require('fs');
22
+ const { raizProyecto } = require('./lib/raiz-proyecto');
22
23
  const path = require('path');
24
+ const { spawn } = require('child_process');
23
25
 
24
26
  // Require con fallback dual: el instalador aplana `hooks/lib/X.js → <hooks>/X.js`
25
27
  // en el destino, pero en el repo madre vive en `lib/`. Cubre ambos layouts (D-17).
@@ -32,6 +34,116 @@ function requireDual(nombre) {
32
34
  }
33
35
  }
34
36
 
37
+ // ---------------------------------------------------------------------------
38
+ // Fallback de disparo del ciclo autónomo (Fase 21, T-11, ADR-0041/0042,
39
+ // REQ-21-11). El scheduler cron (`gateway/cron/jobs.example.json`) es el
40
+ // disparador primario de la Fase A; este fallback cubre proyectos sin
41
+ // scheduler configurado, disparando desde el propio SessionStart cuando toca.
42
+ //
43
+ // Fuera de alcance intencional en instalaciones destino (Fase 26): las libs
44
+ // `scripts/lib/ciclo-autonomo/*.js` viajan en `hooks-core` (resuelven cross-dir
45
+ // igual que `git-metricas`/`npm-version`), pero el wrapper `scripts/cli/
46
+ // ciclo-autonomo.js` se distribuye SOLO por `package.json#files` — en destino
47
+ // puede no resolver. Cuando no resuelve: silencio, nunca crashea el hook.
48
+ // ---------------------------------------------------------------------------
49
+
50
+ /**
51
+ * Resuelve la lib pura de decisión del fallback (`scripts/lib/ciclo-autonomo/
52
+ * fallback.js`). Dual: repo madre / destino copy-mode (`../scripts/lib/...`)
53
+ * vs destino aplanado (`./lib/ciclo-autonomo/fallback`, mismo criterio que
54
+ * `hooks/check-update.js` con `scripts/lib/npm-version.js`). Ausente → null.
55
+ */
56
+ function resolverFallbackCiclo() {
57
+ try {
58
+ return require('../scripts/lib/ciclo-autonomo/fallback');
59
+ } catch (e1) {
60
+ if (e1 && e1.code !== 'MODULE_NOT_FOUND') throw e1;
61
+ try {
62
+ return require('./lib/ciclo-autonomo/fallback');
63
+ } catch (e2) {
64
+ if (e2 && e2.code !== 'MODULE_NOT_FOUND') throw e2;
65
+ return null;
66
+ }
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Resuelve la ruta absoluta del wrapper CLI del ciclo
72
+ * (`scripts/cli/ciclo-autonomo.js`) SIN requerirlo — `require.resolve` nunca
73
+ * ejecuta el módulo, evita cargar en este proceso el árbol completo del ciclo
74
+ * (config/lock/writer/drenador/puente) solo para calcular un path.
75
+ */
76
+ function resolverRutaCliCiclo() {
77
+ try {
78
+ return require.resolve('../scripts/cli/ciclo-autonomo');
79
+ } catch (e1) {
80
+ if (e1 && e1.code !== 'MODULE_NOT_FOUND') throw e1;
81
+ try {
82
+ return require.resolve('./lib/ciclo-autonomo/ciclo-autonomo');
83
+ } catch (e2) {
84
+ if (e2 && e2.code !== 'MODULE_NOT_FOUND') throw e2;
85
+ return null;
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Dispara la Fase A del ciclo autónomo en un proceso separado
92
+ * (fire-and-forget, `detached` + `unref`) cuando el motor está habilitado y
93
+ * pasaron >=24h desde la última corrida (o nunca corrió). Guard barato
94
+ * PRIMERO: si no existe `.planning/evolution/ciclo-config.json`, retorna sin
95
+ * requerir ninguna lib del ciclo — la inmensa mayoría de proyectos nunca lo
96
+ * habilitó y el presupuesto de este hook (<200ms) no debe pagar ese costo.
97
+ * El hook NO espera el resultado; el lock propio del ciclo (T-02) garantiza
98
+ * que no haya doble corrida con el scheduler cron.
99
+ */
100
+ function dispararCicloAutonomoSiToca(cwd, hoy) {
101
+ if (!fs.existsSync(path.join(cwd, '.planning', 'evolution', 'ciclo-config.json'))) return;
102
+
103
+ const fallback = resolverFallbackCiclo();
104
+ if (!fallback) return;
105
+
106
+ const { disparar } = fallback.debeDisparar(cwd, { ahora: hoy });
107
+ if (!disparar) return;
108
+
109
+ const rutaCli = resolverRutaCliCiclo();
110
+ if (!rutaCli) return; // no resuelve en esta instalación: silencio, nunca crashea
111
+
112
+ spawn(
113
+ process.execPath,
114
+ ['-e', `require(${JSON.stringify(rutaCli)})({})`],
115
+ { detached: true, stdio: 'ignore', cwd }
116
+ ).unref();
117
+ }
118
+
119
+ /** Texto de un archivo o `null` si no existe / no se puede leer. */
120
+ function leerTextoSeguro(p) {
121
+ try {
122
+ return fs.readFileSync(p, 'utf8');
123
+ } catch (_) {
124
+ return null;
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Línea de resumen de la última corrida del ciclo autónomo para el digest,
130
+ * cuando `ciclo-config.json` existe y tiene `ultima_corrida` registrada.
131
+ */
132
+ function lineaResumenCiclo(cwd) {
133
+ const txt = leerTextoSeguro(path.join(cwd, '.planning', 'evolution', 'ciclo-config.json'));
134
+ if (!txt) return null;
135
+ let cfg;
136
+ try {
137
+ cfg = JSON.parse(txt);
138
+ } catch (_) {
139
+ return null;
140
+ }
141
+ const u = cfg && cfg.ultima_corrida;
142
+ if (!u) return null;
143
+ return `Ciclo autónomo: última corrida ${cfg.last_run || 'desconocida'} — ` +
144
+ `promovió ${u.promovidos || 0}, degradó ${u.degradados || 0}, drenó ${u.drenados || 0}`;
145
+ }
146
+
35
147
  let briefing;
36
148
  let atomicWriteJSON;
37
149
  try {
@@ -53,7 +165,7 @@ process.stdin.on('end', () => {
53
165
  if (process.env.SWL_BRIEFING === '0') return; // opt-out
54
166
  if (!briefing) return; // lib ausente: degradar a silencio
55
167
 
56
- const cwd = process.cwd();
168
+ const cwd = raizProyecto(process.cwd());
57
169
  if (!fs.existsSync(path.join(cwd, '.planning'))) return; // zero-config
58
170
 
59
171
  const hoy = new Date();
@@ -78,8 +190,22 @@ process.stdin.on('end', () => {
78
190
  const digest = briefing.armarDigest(items, estadoPrevio, dia, {
79
191
  categoriasSilenciadas: silenciadas,
80
192
  });
193
+
194
+ // Fallback de disparo del ciclo autónomo (Fase 21, T-11, REQ-21-11): aislado
195
+ // en su propio try/catch y evaluado ANTES del early-return de silencio total
196
+ // — es una acción de fondo independiente de si hay señales que mostrar hoy.
197
+ try {
198
+ dispararCicloAutonomoSiToca(cwd, hoy);
199
+ } catch (_) { /* fire-and-forget best-effort: nunca bloquear la sesión */ }
200
+
81
201
  if (!digest) return; // silencio total: sin señales nuevas
82
202
 
203
+ // Línea de resumen del ciclo autónomo (si hubo corrida reciente registrada).
204
+ try {
205
+ const lineaCiclo = lineaResumenCiclo(cwd);
206
+ if (lineaCiclo) digest.texto = `${digest.texto}\n${lineaCiclo}`;
207
+ } catch (_) { /* best-effort: no romper el digest por esto */ }
208
+
83
209
  // Persistir el estado de dedupe (best-effort).
84
210
  try {
85
211
  const dir = path.join(cwd, '.planning', 'user-profile');
@@ -32,6 +32,7 @@
32
32
  */
33
33
 
34
34
  const fs = require('fs');
35
+ const { raizProyecto } = require('./lib/raiz-proyecto');
35
36
  const path = require('path');
36
37
  const crypto = require('crypto');
37
38
 
@@ -180,7 +181,7 @@ function main() {
180
181
  process.exit(0);
181
182
  }
182
183
 
183
- const cwd = process.cwd();
184
+ const cwd = raizProyecto(process.cwd());
184
185
  const toolName = evento?.tool_name;
185
186
  const filePath = evento?.tool_input?.file_path;
186
187
 
@@ -33,6 +33,7 @@
33
33
  */
34
34
 
35
35
  const fs = require('fs');
36
+ const { raizProyecto } = require('./lib/raiz-proyecto');
36
37
  const path = require('path');
37
38
 
38
39
  let isPackageRoot, readEvolutionMeta;
@@ -52,7 +53,7 @@ const CARPETAS_EVOLUCIONABLES = [
52
53
  ];
53
54
 
54
55
  const STATE_FILE = path.join(
55
- process.cwd(),
56
+ raizProyecto(process.cwd()),
56
57
  '.planning',
57
58
  'comms',
58
59
  'sugerir-contribuir-cooldown.json'
@@ -68,7 +69,7 @@ function rutaRelativaAlProyecto(rutaRaw) {
68
69
  let normalizada = normalizarSeparadores(rutaRaw);
69
70
 
70
71
  if (path.isAbsolute(normalizada)) {
71
- const cwd = normalizarSeparadores(process.cwd());
72
+ const cwd = normalizarSeparadores(raizProyecto(process.cwd()));
72
73
  if (normalizada.toLowerCase().startsWith(cwd.toLowerCase())) {
73
74
  normalizada = normalizada.slice(cwd.length).replace(/^\/+/, '');
74
75
  } else {
@@ -174,7 +175,9 @@ function evaluar(toolName, toolInput) {
174
175
  if (!ruta) return null;
175
176
  if (!esEvolucionable(ruta)) return null;
176
177
 
177
- const rutaAbsoluta = path.isAbsolute(rutaRaw) ? rutaRaw : path.join(process.cwd(), ruta);
178
+ // `ruta` ya es relativa a la raíz del proyecto (rutaRelativaAlProyecto la
179
+ // despoja contra esa misma ancla) — reconstruir contra la raíz, no el cwd.
180
+ const rutaAbsoluta = path.isAbsolute(rutaRaw) ? rutaRaw : path.join(raizProyecto(process.cwd()), ruta);
178
181
  if (!fs.existsSync(rutaAbsoluta)) return null;
179
182
 
180
183
  const evo = readEvolutionMeta(rutaAbsoluta);
@@ -27,6 +27,7 @@
27
27
  */
28
28
 
29
29
  const fs = require('fs');
30
+ const { raizProyecto } = require('./lib/raiz-proyecto');
30
31
  const path = require('path');
31
32
 
32
33
  // Carpetas cuyo cambio invalida los contadores de INVENTARIO.md
@@ -38,7 +39,7 @@ const CARPETAS_INVENTARIADAS = [
38
39
  { ruta: 'reglas/', etiqueta: 'reglas' },
39
40
  ];
40
41
 
41
- const STATE_FILE = path.join(process.cwd(), '.planning', 'inventario-aviso-state.json');
42
+ const STATE_FILE = path.join(raizProyecto(process.cwd()), '.planning', 'inventario-aviso-state.json');
42
43
  const COOLDOWN_MS = 30 * 60 * 1000; // 30 min
43
44
 
44
45
  function normalizarSeparadores(p) {
@@ -52,7 +53,7 @@ function detectarCarpeta(rutaRaw) {
52
53
  // Solo nos interesan rutas relativas al proyecto. Si es absoluta, intentamos
53
54
  // hacerla relativa al CWD actual.
54
55
  if (path.isAbsolute(normalizada)) {
55
- const cwd = normalizarSeparadores(process.cwd());
56
+ const cwd = normalizarSeparadores(raizProyecto(process.cwd()));
56
57
  if (normalizada.toLowerCase().startsWith(cwd.toLowerCase())) {
57
58
  normalizada = normalizada.slice(cwd.length).replace(/^\/+/, '');
58
59
  } else {
package/hooks/tdd-gate.js CHANGED
@@ -30,6 +30,7 @@
30
30
  */
31
31
 
32
32
  const fs = require('fs');
33
+ const { raizProyecto } = require('./lib/raiz-proyecto');
33
34
  const path = require('path');
34
35
  const { execFileSync } = require('child_process');
35
36
 
@@ -209,7 +210,7 @@ function main() {
209
210
 
210
211
  if (evento?.tool_name !== 'Bash') process.exit(0);
211
212
  const comando = evento?.tool_input?.command;
212
- const cwd = process.cwd();
213
+ const cwd = raizProyecto(process.cwd());
213
214
 
214
215
  // Zero-config: sin .planning/ no hay ciclo GSD que vigilar.
215
216
  if (!fs.existsSync(path.join(cwd, '.planning'))) process.exit(0);
@@ -17,6 +17,7 @@
17
17
  */
18
18
 
19
19
  const { registrar } = require('./lib/otlp-exporter');
20
+ const { raizProyecto } = require('./lib/raiz-proyecto');
20
21
 
21
22
  // Importar esquema de spans con guard de robustez — el hook no debe fallar
22
23
  // si el módulo aún no existe en instalaciones anteriores del sistema.
@@ -27,7 +28,7 @@ try {
27
28
  // Módulo no disponible — continuar sin tipado de span
28
29
  }
29
30
 
30
- const CWD = process.cwd();
31
+ const CWD = raizProyecto(process.cwd());
31
32
 
32
33
  // ---------------------------------------------------------------------------
33
34
  // Mapping de eventos a tipos de span
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  'use strict';
3
+ const { raizProyecto } = require('./lib/raiz-proyecto');
3
4
 
4
5
  /**
5
6
  * Hook: telemetria-skill-routing.js
@@ -91,7 +92,7 @@ if (!require.main || require.main === module) {
91
92
  process.stdin.on('data', (chunk) => { inputRaw += chunk; });
92
93
  process.stdin.on('end', () => {
93
94
  try {
94
- procesar(JSON.parse(inputRaw), process.cwd());
95
+ procesar(JSON.parse(inputRaw), raizProyecto(process.cwd()));
95
96
  } catch (_) {
96
97
  // Silencioso — nunca interrumpir la sesión por un fallo de telemetría.
97
98
  }
@@ -21,6 +21,7 @@
21
21
  */
22
22
 
23
23
  const fs = require('fs');
24
+ const { raizProyecto } = require('./lib/raiz-proyecto');
24
25
  const path = require('path');
25
26
  const os = require('os');
26
27
 
@@ -75,10 +76,10 @@ const PRESUPUESTO_DEFAULT = {
75
76
  };
76
77
 
77
78
  /** Ruta del manifesto de configuración de hooks. */
78
- const RUTA_HOOKS_CONFIG = path.join(process.cwd(), 'manifiestos', 'hooks-config.json');
79
+ const RUTA_HOOKS_CONFIG = path.join(raizProyecto(process.cwd()), 'manifiestos', 'hooks-config.json');
79
80
 
80
81
  /** Ruta del archivo de métricas de sesión. */
81
- const RUTA_METRICS = path.join(process.cwd(), '.planning', 'METRICAS.md');
82
+ const RUTA_METRICS = path.join(raizProyecto(process.cwd()), '.planning', 'METRICAS.md');
82
83
 
83
84
  // ---------------------------------------------------------------------------
84
85
  // Utilidades de configuración
@@ -673,7 +674,7 @@ process.stdin.on('end', () => {
673
674
  if (estado.toolCalls % INTERVALO_ACTUALIZACION === 0) {
674
675
  try {
675
676
  const { actualizarSesion } = require('./lib/session-store');
676
- const cwd = process.cwd();
677
+ const cwd = raizProyecto(process.cwd());
677
678
  actualizarSesion(cwd, {
678
679
  toolCall: toolName,
679
680
  tokensEstimated: estado.tokensTotal,
@@ -23,9 +23,10 @@
23
23
  */
24
24
 
25
25
  const fs = require('fs');
26
+ const { raizProyecto } = require('./lib/raiz-proyecto');
26
27
  const path = require('path');
27
28
 
28
- const CWD = process.cwd();
29
+ const CWD = raizProyecto(process.cwd());
29
30
  const SCHEMAS_PATH = path.join(CWD, 'manifiestos', 'agent-output-schemas.json');
30
31
  const LOG_PATH = path.join(CWD, '.planning', 'evolution', 'formato-violaciones.jsonl');
31
32
 
@@ -44,6 +44,7 @@
44
44
  */
45
45
 
46
46
  const fs = require('fs');
47
+ const { raizProyecto } = require('./lib/raiz-proyecto');
47
48
  const path = require('path');
48
49
  const crypto = require('crypto');
49
50
 
@@ -188,7 +189,7 @@ if (faltan.length === 0) {
188
189
  }
189
190
 
190
191
  // ─── Emitir nudge ─────────────────────────────────────────────────────────
191
- const CWD = process.cwd();
192
+ const CWD = raizProyecto(process.cwd());
192
193
  const rutaRelativa = path.relative(CWD, filePath).replace(/\\/g, '/');
193
194
  const nombreAgente = path.basename(filePath, '.md');
194
195
 
@@ -34,6 +34,7 @@
34
34
  */
35
35
 
36
36
  const fs = require('fs');
37
+ const { raizProyecto } = require('./lib/raiz-proyecto');
37
38
  const path = require('path');
38
39
  const { spawnSync } = require('child_process');
39
40
 
@@ -49,8 +50,17 @@ const ARCHIVOS_MEMORIA = [
49
50
  'instintos/global.yaml',
50
51
  ];
51
52
 
52
- /** Path del validador. */
53
- const VALIDADOR = path.join(process.cwd(), 'scripts', 'validar-memoria.js');
53
+ /**
54
+ * Path del validador — EJECUTABLE de la distribución SWL: se resuelve SOLO
55
+ * desde la ubicación instalada del hook (__dirname), NUNCA desde el árbol
56
+ * del proyecto (un repo no confiable podría plantar el script; hallazgo
57
+ * revisor-seguridad 2026-07-10). Los DATOS que valida sí anclan a la raíz
58
+ * del proyecto (cwd del spawn).
59
+ */
60
+ const VALIDADOR = [
61
+ path.join(__dirname, '..', 'scripts', 'validar-memoria.js'), // repo madre
62
+ path.join(__dirname, 'validar-memoria.js'), // destino aplanado
63
+ ].find(p => { try { return fs.existsSync(p); } catch (_) { return false; } }) || '';
54
64
 
55
65
  /** Timeout para el validador (ms). Si tarda más, se aborta sin bloquear. */
56
66
  const TIMEOUT_MS = 5000;
@@ -106,7 +116,7 @@ function ejecutarValidador() {
106
116
  if (!fs.existsSync(VALIDADOR)) return null;
107
117
  try {
108
118
  const r = spawnSync(process.execPath, [VALIDADOR, '--json'], {
109
- cwd: process.cwd(),
119
+ cwd: raizProyecto(process.cwd()),
110
120
  encoding: 'utf8',
111
121
  timeout: TIMEOUT_MS,
112
122
  windowsHide: true,
@@ -19,6 +19,7 @@
19
19
  */
20
20
 
21
21
  const fs = require('fs');
22
+ const { raizProyecto } = require('./lib/raiz-proyecto');
22
23
  const path = require('path');
23
24
  const crypto = require('crypto');
24
25
 
@@ -76,7 +77,7 @@ const DIRS_CANONICOS = [
76
77
  ];
77
78
 
78
79
  // ─── Cargar allowlist (manifest si existe, embebida si no) ──────────────────
79
- const CWD = process.cwd();
80
+ const CWD = raizProyecto(process.cwd());
80
81
  const allowlistPath = path.join(CWD, 'manifiestos', 'planning-paths.json');
81
82
  let permitidos;
82
83
  try {