@saulwade/swl-ses 2.2.3 → 2.3.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.
Files changed (66) hide show
  1. package/CLAUDE.md +4 -4
  2. package/README.md +3 -3
  3. package/agentes/arquitecto-swl.md +1 -1
  4. package/agentes/auto-evolucion-swl.md +908 -908
  5. package/agentes/backend-csharp-swl.md +1 -1
  6. package/agentes/backend-go-swl.md +1 -1
  7. package/agentes/backend-java-swl.md +1 -1
  8. package/agentes/backend-rust-swl.md +1 -1
  9. package/agentes/evals/orquestador-swl.evals.json +1 -1
  10. package/agentes/implementador-swl.md +2 -2
  11. package/agentes/llm-apps-swl.md +1 -1
  12. package/agentes/orquestador-swl.md +7 -7
  13. package/agentes/pagos-swl.md +1 -1
  14. package/agentes/perfilador-usuario-swl.md +321 -321
  15. package/agentes/planificador-swl.md +1 -1
  16. package/agentes/producto-prd-swl.md +1 -1
  17. package/agentes/revisor-seguridad-swl.md +1 -1
  18. package/agentes/sre-swl.md +1 -1
  19. package/comandos/swl/aprobar-plan.md +146 -141
  20. package/comandos/swl/release.md +45 -8
  21. package/comandos/swl/status.md +343 -333
  22. package/comandos/swl/verificar.md +817 -817
  23. package/habilidades/compactacion-contexto/SKILL.md +3 -3
  24. package/habilidades/contenedores-docker/SKILL.md +3 -1
  25. package/habilidades/context-builder/SKILL.md +4 -4
  26. package/habilidades/control-profundidad/SKILL.md +5 -5
  27. package/habilidades/ejecutar-fase/SKILL.md +564 -541
  28. package/habilidades/extractor-de-aprendizajes/SKILL.md +3 -3
  29. package/habilidades/guardrail-semantico/SKILL.md +1 -1
  30. package/habilidades/harness-claude-code/SKILL.md +305 -305
  31. package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +1 -1
  32. package/habilidades/planear-fase/SKILL.md +15 -1
  33. package/habilidades/proceso-debate-adversarial/SKILL.md +191 -164
  34. package/habilidades/prompt-engineering/SKILL.md +5 -5
  35. package/habilidades/release-semver/SKILL.md +4 -1
  36. package/habilidades/tdd-workflow/SKILL.md +33 -1
  37. package/habilidades/workflow-claude-code/SKILL.md +6 -6
  38. package/hooks/captura-acciones-post.js +151 -0
  39. package/hooks/captura-acciones-session.js +155 -0
  40. package/hooks/lib/briefing.js +512 -474
  41. package/hooks/lib/captura-acciones.js +392 -0
  42. package/hooks/lib/context-builder.js +2 -2
  43. package/hooks/lib/model-router.js +1 -1
  44. package/hooks/lib/token-estimator.js +2 -0
  45. package/hooks/linea-estado.js +7 -5
  46. package/llms.txt +29 -29
  47. package/manifiestos/canonical-hashes.json +1964 -1310
  48. package/manifiestos/hooks-config.json +18 -0
  49. package/manifiestos/modulos.json +4 -0
  50. package/manifiestos/skills-lock.json +1282 -1282
  51. package/package.json +93 -93
  52. package/plugin.json +371 -371
  53. package/reglas/git-coauthor.md +100 -100
  54. package/reglas/memoria-consolidada.md +41 -0
  55. package/reglas/pruebas.md +15 -0
  56. package/reglas/seguridad-agentes.md +66 -0
  57. package/schemas/agent-frontmatter.schema.json +294 -294
  58. package/schemas/instinct.schema.json +161 -152
  59. package/scripts/bootstrap-instintos.js +25 -7
  60. package/scripts/lib/claude-sessions.js +1 -0
  61. package/scripts/lib/gitignore-manifest.js +44 -11
  62. package/scripts/lib/skill-metrics.js +41 -1
  63. package/scripts/lib/tool-cost-analyzer.js +1 -0
  64. package/scripts/publicar.js +34 -85
  65. package/scripts/verificar-trazabilidad.js +329 -298
  66. package/scripts/vendor/claude-usage/__pycache__/scanner.cpython-314.pyc +0 -0
@@ -0,0 +1,392 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Lib: captura-acciones.js
5
+ *
6
+ * Núcleo puro y testeable de la captura de SEÑALES DE ACCIÓN del usuario
7
+ * (Fase 17, "Aprendizaje de señales de usuario"). Mientras
8
+ * `captura-feedback-usuario.js` captura las señales VERBALES (palabras tecleadas
9
+ * en UserPromptSubmit), esta lib alimenta las señales de ACCIÓN — la mitad
10
+ * procedural que hoy se pierde:
11
+ * - revert/reset de commits hechos por el agente,
12
+ * - edición manual de archivos que el agente escribió,
13
+ * - rechazo de un PLAN propuesto,
14
+ * - override de un veredicto de /swl:verificar.
15
+ *
16
+ * Las señales se encolan en el MISMO `.planning/evolution/feedback-queue.jsonl`
17
+ * con `tipo:"accion"` (esquema extendido backward-compatible con las verbales),
18
+ * para el mismo consumidor (perfilador-usuario-swl + ciclo AGP). Alcance Fase 17:
19
+ * **solo capturar + telemetría** — sin conversión a memoria procedural.
20
+ *
21
+ * Consumida por los hooks `captura-acciones-post.js` (PostToolUse) y
22
+ * `captura-acciones-session.js` (SessionStart). Zero-deps salvo `atomic-write`
23
+ * (sibling en hooks/lib/). Todas las funciones son puras o reciben `baseDir`
24
+ * explícito → testeables en aislamiento.
25
+ *
26
+ * Opt-out unificado (en los hooks, no aquí): SWL_CAPTURAR_FEEDBACK=0.
27
+ */
28
+
29
+ const fs = require('fs');
30
+ const path = require('path');
31
+ const crypto = require('crypto');
32
+
33
+ // atomic-write es sibling en hooks/lib/ (y queda en el mismo dir tras el
34
+ // aplanado del instalador). Fallback inline si faltara.
35
+ let atomicWriteJSON;
36
+ try {
37
+ ({ atomicWriteJSON } = require('./atomic-write'));
38
+ } catch (_) {
39
+ atomicWriteJSON = (p, obj) => fs.writeFileSync(p, JSON.stringify(obj, null, 2), 'utf8');
40
+ }
41
+
42
+ // ---------------------------------------------------------------------------
43
+ // Sanitización de evidencia (REQ-17-07)
44
+ //
45
+ // Port de los 5 patrones de `registro-turnos.js:67-82` + `reglas/seguridad.md
46
+ // § Sanitización PII centralizada`. La sanitización vive en el punto de
47
+ // persistencia (encolarAccion) — ningún path de encolado puede omitirla.
48
+ // ---------------------------------------------------------------------------
49
+
50
+ const PATRONES_REDACT = [
51
+ /\b[A-Za-z0-9_-]{32,}\b/g, // tokens largos
52
+ /(?:sk|pk|key|token|secret|password|pwd|api[_-]?key)["':\s=]+[A-Za-z0-9_\-./]{8,}/gi,
53
+ /\bey[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/g, // JWT
54
+ /https?:\/\/[^:]+:[^@\s]+@/g, // basic auth en URL
55
+ /-----BEGIN [A-Z ]+-----[\s\S]*?-----END [A-Z ]+-----/g, // PEM blocks
56
+ ];
57
+
58
+ /** Redacta secretos de un texto libre (REQ-17-07). Best-effort, no lanza. */
59
+ function sanitizarEvidencia(texto) {
60
+ if (!texto) return '';
61
+ let r = String(texto);
62
+ for (const re of PATRONES_REDACT) r = r.replace(re, '[REDACTED]');
63
+ return r;
64
+ }
65
+
66
+ /** SHA-256 hex de un string (módulo nativo, sin deps). */
67
+ function hashContenido(str) {
68
+ return crypto.createHash('sha256').update(String(str == null ? '' : str)).digest('hex');
69
+ }
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // Rutas runtime (gitignored)
73
+ // ---------------------------------------------------------------------------
74
+
75
+ const MAX_EVIDENCIA_LEN = 500;
76
+
77
+ function rutaCola(baseDir) {
78
+ return path.join(baseDir, '.planning', 'evolution', 'feedback-queue.jsonl');
79
+ }
80
+ function rutaIndiceWrites(baseDir) {
81
+ return path.join(baseDir, '.planning', 'evolution', 'agent-writes-index.json');
82
+ }
83
+ function rutaCommits(baseDir) {
84
+ return path.join(baseDir, '.planning', 'evolution', 'agent-commits.jsonl');
85
+ }
86
+
87
+ function asegurarEvolutionDir(baseDir) {
88
+ const dir = path.join(baseDir, '.planning', 'evolution');
89
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
90
+ return dir;
91
+ }
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // Encolado (REQ-17-06, REQ-17-07)
95
+ // ---------------------------------------------------------------------------
96
+
97
+ /**
98
+ * Encola una señal de acción en feedback-queue.jsonl. Esquema extendido
99
+ * backward-compatible: las entradas verbales legacy (sin `accion`) siguen
100
+ * parseando. La `evidencia` se sanitiza SIEMPRE aquí (invariante REQ-17-07).
101
+ *
102
+ * @param {string} baseDir raíz del proyecto (cwd del hook).
103
+ * @param {object} accion { accion, archivo?, evidencia?, sessionId?, cwd? }.
104
+ */
105
+ function encolarAccion(baseDir, accion) {
106
+ try {
107
+ asegurarEvolutionDir(baseDir);
108
+ const entrada = {
109
+ ts: new Date().toISOString(),
110
+ sessionId: String(accion.sessionId || 'default'),
111
+ tipo: 'accion',
112
+ accion: accion.accion,
113
+ cwd: accion.cwd || baseDir,
114
+ procesado: false,
115
+ };
116
+ if (accion.archivo) entrada.archivo = String(accion.archivo);
117
+ if (accion.evidencia != null) {
118
+ entrada.evidencia = sanitizarEvidencia(accion.evidencia).slice(0, MAX_EVIDENCIA_LEN);
119
+ }
120
+ fs.appendFileSync(rutaCola(baseDir), JSON.stringify(entrada) + '\n');
121
+ } catch (_) {
122
+ /* nunca bloquear */
123
+ }
124
+ }
125
+
126
+ // ---------------------------------------------------------------------------
127
+ // Índice de escrituras del agente (REQ-17-02, REQ-17-03)
128
+ // ---------------------------------------------------------------------------
129
+
130
+ /** Lee el índice de hashes de escritura del agente; {} si ausente/corrupto. */
131
+ function leerIndiceWrites(baseDir) {
132
+ try {
133
+ const p = rutaIndiceWrites(baseDir);
134
+ if (!fs.existsSync(p)) return {};
135
+ const obj = JSON.parse(fs.readFileSync(p, 'utf8'));
136
+ return obj && typeof obj === 'object' ? obj : {};
137
+ } catch (_) {
138
+ return {};
139
+ }
140
+ }
141
+
142
+ function escribirIndiceWrites(baseDir, indice) {
143
+ try {
144
+ asegurarEvolutionDir(baseDir);
145
+ atomicWriteJSON(rutaIndiceWrites(baseDir), indice);
146
+ } catch (_) {
147
+ /* best-effort */
148
+ }
149
+ }
150
+
151
+ /** Registra el hash del último write del agente sobre `rutaRel`. */
152
+ function registrarEscrituraAgente(baseDir, rutaRel, contenido, meta = {}) {
153
+ const indice = leerIndiceWrites(baseDir);
154
+ indice[rutaRel] = {
155
+ sha256: hashContenido(contenido),
156
+ ts: new Date().toISOString(),
157
+ sessionId: String(meta.sessionId || 'default'),
158
+ };
159
+ escribirIndiceWrites(baseDir, indice);
160
+ return indice;
161
+ }
162
+
163
+ // ---------------------------------------------------------------------------
164
+ // Registro de commits del agente (REQ-17-01) — sin co-author (git-coauthor.md)
165
+ // ---------------------------------------------------------------------------
166
+
167
+ /** Registra un SHA commiteado por el agente en agent-commits.jsonl. */
168
+ function registrarCommitAgente(baseDir, { sessionId, sha, mensaje } = {}) {
169
+ try {
170
+ if (!sha) return;
171
+ asegurarEvolutionDir(baseDir);
172
+ const entrada = { ts: new Date().toISOString(), sessionId: String(sessionId || 'default'), sha: String(sha) };
173
+ // `mensaje` también se sanitiza (un mensaje de commit puede llevar un token
174
+ // pegado): este es un segundo path de persistencia y la invariante de no
175
+ // filtrar secretos aplica a TODO path, no solo a encolarAccion (sec BAJA-1).
176
+ if (mensaje) entrada.mensaje = sanitizarEvidencia(String(mensaje)).slice(0, 200);
177
+ fs.appendFileSync(rutaCommits(baseDir), JSON.stringify(entrada) + '\n');
178
+ } catch (_) {
179
+ /* best-effort */
180
+ }
181
+ }
182
+
183
+ /** Lee los SHAs registrados por el agente; [] si ausente/corrupto. */
184
+ function leerCommitsAgente(baseDir) {
185
+ try {
186
+ const p = rutaCommits(baseDir);
187
+ if (!fs.existsSync(p)) return [];
188
+ return fs
189
+ .readFileSync(p, 'utf8')
190
+ .split(/\r?\n/)
191
+ .filter(Boolean)
192
+ .map((l) => {
193
+ try {
194
+ return JSON.parse(l);
195
+ } catch (_) {
196
+ return null;
197
+ }
198
+ })
199
+ .filter(Boolean);
200
+ } catch (_) {
201
+ return [];
202
+ }
203
+ }
204
+
205
+ // ---------------------------------------------------------------------------
206
+ // Detectores puros
207
+ // ---------------------------------------------------------------------------
208
+
209
+ /**
210
+ * SHAs registrados por el agente que ya NO están en el historial actual
211
+ * (revert/reset). REQ-17-01.
212
+ * @param {Array<{sha:string}>|string[]} commitsRegistrados
213
+ * @param {string[]} shasHistorialActual
214
+ * @returns {string[]}
215
+ */
216
+ function detectarRevert(commitsRegistrados, shasHistorialActual) {
217
+ const hist = new Set(shasHistorialActual || []);
218
+ const vistos = new Set();
219
+ const out = [];
220
+ for (const c of commitsRegistrados || []) {
221
+ const sha = typeof c === 'string' ? c : c && c.sha;
222
+ if (!sha || vistos.has(sha)) continue;
223
+ vistos.add(sha);
224
+ if (!hist.has(sha)) out.push(sha);
225
+ }
226
+ return out;
227
+ }
228
+
229
+ /**
230
+ * Archivos cuyo hash en disco difiere del último write del agente (edición
231
+ * neta del usuario fuera de sesión). REQ-17-02.
232
+ * @param {Object} indiceWrites { ruta: { sha256 } }
233
+ * @param {Object} hashActualPorArchivo { ruta: sha256 }
234
+ * @returns {string[]}
235
+ */
236
+ function detectarEdicionNeta(indiceWrites, hashActualPorArchivo) {
237
+ const out = [];
238
+ for (const ruta of Object.keys(indiceWrites || {})) {
239
+ const actual = hashActualPorArchivo ? hashActualPorArchivo[ruta] : undefined;
240
+ if (actual === undefined) continue; // archivo borrado/ilegible → no inferir
241
+ const registrado = indiceWrites[ruta] && indiceWrites[ruta].sha256;
242
+ if (registrado && actual !== registrado) out.push(ruta);
243
+ }
244
+ return out;
245
+ }
246
+
247
+ /**
248
+ * true si el contenido re-leído difiere del último write del agente (edición
249
+ * manual en caliente). false si coincide o no hay registro. REQ-17-03.
250
+ */
251
+ function detectarEdicionManual(rutaArchivo, contenidoReleido, indiceWrites) {
252
+ const rec = indiceWrites && indiceWrites[rutaArchivo];
253
+ if (!rec || !rec.sha256) return false;
254
+ return hashContenido(contenidoReleido) !== rec.sha256;
255
+ }
256
+
257
+ function _frontmatterCampo(contenido, campo) {
258
+ const m = contenido.match(new RegExp(`^${campo}:\\s*(.+)$`, 'm'));
259
+ return m ? m[1].trim() : null;
260
+ }
261
+
262
+ function _faseDeNombre(nombre) {
263
+ const m = nombre.match(/^(\d{1,3})-/);
264
+ return m ? parseInt(m[1], 10) : null;
265
+ }
266
+
267
+ /**
268
+ * PLANs que parecen rechazados: estado `rechazado` explícito, o estado
269
+ * `borrador` sin lock G1 mientras la fase ya cerró (existe NN-RESUMEN.md).
270
+ * REQ-17-04.
271
+ * @returns {Array<{fase:number, archivo:string}>}
272
+ */
273
+ function _evaluarPlanRechazado(archivo, fasesDir, locksDir) {
274
+ let contenido = '';
275
+ try {
276
+ contenido = fs.readFileSync(path.join(fasesDir, archivo), 'utf8');
277
+ } catch (_) {
278
+ return null;
279
+ }
280
+ const estado = (_frontmatterCampo(contenido, 'estado') || '').toLowerCase();
281
+ const fase = _faseDeNombre(archivo);
282
+ if (estado === 'rechazado') return { fase, archivo };
283
+ if (estado === 'borrador') {
284
+ const lock = path.join(locksDir, archivo + '.lock');
285
+ const resumen = path.join(fasesDir, archivo.replace('-PLAN.md', '-RESUMEN.md'));
286
+ if (!fs.existsSync(lock) && fs.existsSync(resumen)) return { fase, archivo };
287
+ }
288
+ return null;
289
+ }
290
+
291
+ function detectarPlanRechazado(baseDir) {
292
+ const fasesDir = path.join(baseDir, '.planning', 'fases');
293
+ const locksDir = path.join(baseDir, '.planning', 'locks');
294
+ let archivos;
295
+ try {
296
+ archivos = fs.readdirSync(fasesDir).filter((f) => /-PLAN\.md$/.test(f));
297
+ } catch (_) {
298
+ return [];
299
+ }
300
+ return archivos.map((a) => _evaluarPlanRechazado(a, fasesDir, locksDir)).filter(Boolean);
301
+ }
302
+
303
+ /**
304
+ * VERIFICACIONes con veredicto no-aprobatorio (caso determinista de override).
305
+ * La inferencia "se procedió igual" queda como inspección (T-10). REQ-17-05.
306
+ * @returns {Array<{fase:number, archivo:string, veredicto:string}>}
307
+ */
308
+ function detectarVeredictoOverride(baseDir) {
309
+ const out = [];
310
+ const fasesDir = path.join(baseDir, '.planning', 'fases');
311
+ let archivos;
312
+ try {
313
+ archivos = fs.readdirSync(fasesDir).filter((f) => /-VERIFICACION\.md$/.test(f));
314
+ } catch (_) {
315
+ return out;
316
+ }
317
+ for (const archivo of archivos) {
318
+ let contenido = '';
319
+ try {
320
+ contenido = fs.readFileSync(path.join(fasesDir, archivo), 'utf8');
321
+ } catch (_) {
322
+ continue;
323
+ }
324
+ const m = contenido.match(/VEREDICTO:?\s*(RECHAZADO|REQUIERE[_\s]CORRECCIONES)/i);
325
+ if (m) out.push({ fase: _faseDeNombre(archivo), archivo, veredicto: m[1].toUpperCase().replace(/\s/g, '_') });
326
+ }
327
+ return out;
328
+ }
329
+
330
+ // ---------------------------------------------------------------------------
331
+ // Telemetría (REQ-17-09)
332
+ // ---------------------------------------------------------------------------
333
+
334
+ const SUBTIPOS = ['revert', 'edicion-manual', 'plan-rechazado', 'veredicto-override'];
335
+
336
+ /** Conteo por subtipo de acción en la cola; ignora entradas verbales. */
337
+ function contarPorSubtipo(baseDir) {
338
+ const conteo = Object.fromEntries(SUBTIPOS.map((s) => [s, 0]));
339
+ try {
340
+ const p = rutaCola(baseDir);
341
+ if (!fs.existsSync(p)) return conteo;
342
+ for (const linea of fs.readFileSync(p, 'utf8').split(/\r?\n/)) {
343
+ if (!linea) continue;
344
+ let e;
345
+ try {
346
+ e = JSON.parse(linea);
347
+ } catch (_) {
348
+ continue;
349
+ }
350
+ if (e && e.tipo === 'accion' && Object.prototype.hasOwnProperty.call(conteo, e.accion)) {
351
+ conteo[e.accion] += 1;
352
+ }
353
+ }
354
+ } catch (_) {
355
+ /* devuelve ceros */
356
+ }
357
+ return conteo;
358
+ }
359
+
360
+ module.exports = {
361
+ sanitizarEvidencia,
362
+ hashContenido,
363
+ encolarAccion,
364
+ leerIndiceWrites,
365
+ escribirIndiceWrites,
366
+ registrarEscrituraAgente,
367
+ registrarCommitAgente,
368
+ leerCommitsAgente,
369
+ detectarRevert,
370
+ detectarEdicionNeta,
371
+ detectarEdicionManual,
372
+ detectarPlanRechazado,
373
+ detectarVeredictoOverride,
374
+ contarPorSubtipo,
375
+ SUBTIPOS,
376
+ MAX_EVIDENCIA_LEN,
377
+ _internals: { PATRONES_REDACT, rutaCola, rutaIndiceWrites, rutaCommits },
378
+ };
379
+
380
+ // ---------------------------------------------------------------------------
381
+ // CLI: `node hooks/lib/captura-acciones.js --conteo` (REQ-17-09 consultable)
382
+ // ---------------------------------------------------------------------------
383
+
384
+ if (require.main === module) {
385
+ try {
386
+ if (process.argv.includes('--conteo')) {
387
+ process.stdout.write(JSON.stringify(contarPorSubtipo(process.cwd()), null, 2) + '\n');
388
+ }
389
+ } catch (_) {
390
+ /* exit 0 siempre */
391
+ }
392
+ }
@@ -19,7 +19,7 @@
19
19
  const fs = require('fs');
20
20
  const path = require('path');
21
21
 
22
- const DEFAULT_TOKEN_BUDGET = 2500; // Recalibrado para Opus 4.7 (tokenizer 1.0-1.35x vs 4.6)
22
+ const DEFAULT_TOKEN_BUDGET = 2500; // Recalibrado para Opus 4.8 (tokenizer 1.0-1.35x vs 4.6)
23
23
  const CHARS_POR_TOKEN = 4; // Heuristica para espanol
24
24
 
25
25
  // ---------------------------------------------------------------------------
@@ -211,7 +211,7 @@ function buildAprendizajes(baseDir, max, budgetRestante) {
211
211
  *
212
212
  * @param {string} baseDir - Directorio raiz del proyecto.
213
213
  * @param {object} [opciones]
214
- * @param {number} [opciones.tokenBudget=2500] - Presupuesto de tokens (default 2500 — recalibrado para Opus 4.7).
214
+ * @param {number} [opciones.tokenBudget=2500] - Presupuesto de tokens (default 2500 — recalibrado para Opus 4.8).
215
215
  * @param {number} [opciones.maxAprendizajes=5] - Max aprendizajes a incluir.
216
216
  * @param {number} [opciones.maxInstintos=5] - Max instintos a incluir.
217
217
  * @returns {{ contexto: string, tokensUsados: number, seccionesTruncadas: string[] }}
@@ -182,7 +182,7 @@ const PROVEEDORES = {
182
182
  anthropic: {
183
183
  nombre: 'Anthropic',
184
184
  modelos: {
185
- opus: 'claude-opus-4-7',
185
+ opus: 'claude-opus-4-8',
186
186
  sonnet: 'claude-sonnet-4-6',
187
187
  haiku: 'claude-haiku-4-5-20251001',
188
188
  },
@@ -87,6 +87,7 @@ const COSTO_DEFAULT_POR_MILLON = 3.0;
87
87
  */
88
88
  const PRICING_CANONICO = {
89
89
  // Anthropic — precios por 1M tokens (nombres canónicos)
90
+ 'claude-opus-4-8': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
90
91
  'claude-opus-4-7': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
91
92
  'claude-opus-4-6': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
92
93
  'claude-opus-4-5': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
@@ -97,6 +98,7 @@ const PRICING_CANONICO = {
97
98
  'claude-haiku-4-5': { input: 0.80, output: 4.00, cacheRead: 0.08, cacheWrite: 1.00 },
98
99
  'claude-3-5-haiku': { input: 0.80, output: 4.00, cacheRead: 0.08, cacheWrite: 1.00 },
99
100
  // Aliases con prefijo anthropic/ (compatibilidad con mission-control y gateways)
101
+ 'anthropic/claude-opus-4-8': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
100
102
  'anthropic/claude-opus-4-7': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
101
103
  'anthropic/claude-opus-4-6': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
102
104
  'anthropic/claude-opus-4-5': { input: 15.00, output: 75.00, cacheRead: 1.50, cacheWrite: 18.75 },
@@ -43,15 +43,17 @@ const TOKENS_MAXIMOS_DEFAULT = 200_000;
43
43
  *
44
44
  * IMPORTANTE: las claves son prefijos del `model_id` reportado por Claude Code
45
45
  * en el evento del hook. La detección hace `modelId.includes(prefijo)` en orden;
46
- * los prefijos más específicos van primero para que `claude-opus-4-7` no
46
+ * los prefijos más específicos van primero para que `claude-opus-4-8` no
47
47
  * matchee accidentalmente con la entrada genérica `claude-opus`.
48
48
  *
49
- * Si el `model_id` contiene el sufijo `[1m]` (ej: `claude-opus-4-7[1m]`), el
49
+ * Si el `model_id` contiene el sufijo `[1m]` (ej: `claude-opus-4-8[1m]`), el
50
50
  * techo se fuerza a 1M independientemente del modelo base — Anthropic usa
51
51
  * ese sufijo para indicar la variante de 1M context.
52
52
  */
53
53
  const TECHOS_POR_MODELO = {
54
- // Opus 4.7 — variante de 1M context (la actual por defecto)
54
+ // Opus 4.8 — variante de 1M context (la actual por defecto)
55
+ 'claude-opus-4-8': 1_000_000,
56
+ // Opus 4.7 — variante de 1M context (histórica)
55
57
  'claude-opus-4-7': 1_000_000,
56
58
  // Resto de modelos modernos: 200k context
57
59
  'claude-opus-4-6': 200_000,
@@ -84,7 +86,7 @@ const ETIQUETAS_MODELO = {
84
86
  * 3. Default → TOKENS_MAXIMOS_DEFAULT (200k).
85
87
  *
86
88
  * @param {string} modelId - Identificador completo del modelo, posiblemente
87
- * con sufijo de variante (ej: `claude-opus-4-7[1m]`).
89
+ * con sufijo de variante (ej: `claude-opus-4-8[1m]`).
88
90
  * @returns {number} Techo de tokens del contexto.
89
91
  */
90
92
  function techoTokens(modelId) {
@@ -261,7 +263,7 @@ process.stdin.on('end', () => {
261
263
  // Ruta del archivo bridge compartido entre hooks
262
264
  const bridgePath = path.join(os.tmpdir(), `swl-ctx-${sessionId}.json`);
263
265
 
264
- // Resolver techo según modelo (Opus 4.7 con sufijo [1m] = 1M; resto 200k)
266
+ // Resolver techo según modelo (Opus 4.8 con sufijo [1m] = 1M; resto 200k)
265
267
  const techo = techoTokens(modelId);
266
268
 
267
269
  // Calcular métricas
package/llms.txt CHANGED
@@ -1,29 +1,29 @@
1
- # swl-ses (@saulwade/swl-ses)
2
-
3
- > Sistema de ingeniería de software auto-evolutivo multi-runtime polyglot (SDLC completo), distribuido como paquete npm y plugin de Claude Code. 60 agentes, 182 habilidades, 44 comandos, 37 reglas base y 48 hooks. Soporta 11 lenguajes y 7 runtimes (Claude Code, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot). Versión 2.2.3.
4
-
5
- Archivo generado por `node scripts/generar-inventario.js` — no editar a mano. Las cifras se sincronizan con INVENTARIO.md en cada regeneración.
6
-
7
- ## Documentación
8
-
9
- - [README](README.md): overview público y quickstart
10
- - [Manual de uso](MANUAL_USO.md): manual operacional completo
11
- - [Comandos](COMANDOS.md): referencia detallada de cada comando `/swl:*`
12
- - [Agentes](AGENTS.md): catálogo de agentes con capacidades
13
- - [Inventario](INVENTARIO.md): conteos oficiales de todos los componentes
14
- - [Instalación](INSTALACION.md): instalación, perfiles y configuración
15
- - [Instrucciones del proyecto](CLAUDE.md): convenciones, stack y reglas
16
-
17
- ## Componentes
18
-
19
- - 60 agentes especializados en `agentes/` (orquestación, implementación por stack, revisión, calidad, diseño)
20
- - 182 habilidades cargables bajo demanda en `habilidades/` (conocimiento operacional con divulgación progresiva)
21
- - 44 comandos `/swl:*` en `comandos/swl/` (ciclo GSD, calidad, release, diagnóstico)
22
- - 37 reglas base + 40 reglas por lenguaje en `reglas/` (políticas obligatorias por matcher)
23
- - 48 hooks en `hooks/` (telemetría, validación, seguridad; zero-deps, escrituras atómicas)
24
-
25
- ## Opcional
26
-
27
- - [CHANGELOG](CHANGELOG.md): historial de versiones
28
- - [Índice de ADRs](.planning/adrs/README.md): decisiones de arquitectura
29
- - [Variables de entorno](docs/variables-entorno.md): configuración opt-in
1
+ # swl-ses (@saulwade/swl-ses)
2
+
3
+ > Sistema de ingeniería de software auto-evolutivo multi-runtime polyglot (SDLC completo), distribuido como paquete npm y plugin de Claude Code. 60 agentes, 182 habilidades, 44 comandos, 37 reglas base y 50 hooks. Soporta 11 lenguajes y 7 runtimes (Claude Code, OpenClaude, OpenCode, Gemini, Cursor, Codex, Copilot). Versión 2.3.0.
4
+
5
+ Archivo generado por `node scripts/generar-inventario.js` — no editar a mano. Las cifras se sincronizan con INVENTARIO.md en cada regeneración.
6
+
7
+ ## Documentación
8
+
9
+ - [README](README.md): overview público y quickstart
10
+ - [Manual de uso](MANUAL_USO.md): manual operacional completo
11
+ - [Comandos](COMANDOS.md): referencia detallada de cada comando `/swl:*`
12
+ - [Agentes](AGENTS.md): catálogo de agentes con capacidades
13
+ - [Inventario](INVENTARIO.md): conteos oficiales de todos los componentes
14
+ - [Instalación](INSTALACION.md): instalación, perfiles y configuración
15
+ - [Instrucciones del proyecto](CLAUDE.md): convenciones, stack y reglas
16
+
17
+ ## Componentes
18
+
19
+ - 60 agentes especializados en `agentes/` (orquestación, implementación por stack, revisión, calidad, diseño)
20
+ - 182 habilidades cargables bajo demanda en `habilidades/` (conocimiento operacional con divulgación progresiva)
21
+ - 44 comandos `/swl:*` en `comandos/swl/` (ciclo GSD, calidad, release, diagnóstico)
22
+ - 37 reglas base + 40 reglas por lenguaje en `reglas/` (políticas obligatorias por matcher)
23
+ - 50 hooks en `hooks/` (telemetría, validación, seguridad; zero-deps, escrituras atómicas)
24
+
25
+ ## Opcional
26
+
27
+ - [CHANGELOG](CHANGELOG.md): historial de versiones
28
+ - [Índice de ADRs](.planning/adrs/README.md): decisiones de arquitectura
29
+ - [Variables de entorno](docs/variables-entorno.md): configuración opt-in