@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.
- package/CLAUDE.md +4 -4
- package/README.md +3 -3
- package/agentes/arquitecto-swl.md +1 -1
- package/agentes/auto-evolucion-swl.md +908 -908
- package/agentes/backend-csharp-swl.md +1 -1
- package/agentes/backend-go-swl.md +1 -1
- package/agentes/backend-java-swl.md +1 -1
- package/agentes/backend-rust-swl.md +1 -1
- package/agentes/evals/orquestador-swl.evals.json +1 -1
- package/agentes/implementador-swl.md +2 -2
- package/agentes/llm-apps-swl.md +1 -1
- package/agentes/orquestador-swl.md +7 -7
- package/agentes/pagos-swl.md +1 -1
- package/agentes/perfilador-usuario-swl.md +321 -321
- package/agentes/planificador-swl.md +1 -1
- package/agentes/producto-prd-swl.md +1 -1
- package/agentes/revisor-seguridad-swl.md +1 -1
- package/agentes/sre-swl.md +1 -1
- package/comandos/swl/aprobar-plan.md +146 -141
- package/comandos/swl/release.md +45 -8
- package/comandos/swl/status.md +343 -333
- package/comandos/swl/verificar.md +817 -817
- package/habilidades/compactacion-contexto/SKILL.md +3 -3
- package/habilidades/contenedores-docker/SKILL.md +3 -1
- package/habilidades/context-builder/SKILL.md +4 -4
- package/habilidades/control-profundidad/SKILL.md +5 -5
- package/habilidades/ejecutar-fase/SKILL.md +564 -541
- package/habilidades/extractor-de-aprendizajes/SKILL.md +3 -3
- package/habilidades/guardrail-semantico/SKILL.md +1 -1
- package/habilidades/harness-claude-code/SKILL.md +305 -305
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +1 -1
- package/habilidades/planear-fase/SKILL.md +15 -1
- package/habilidades/proceso-debate-adversarial/SKILL.md +191 -164
- package/habilidades/prompt-engineering/SKILL.md +5 -5
- package/habilidades/release-semver/SKILL.md +4 -1
- package/habilidades/tdd-workflow/SKILL.md +33 -1
- package/habilidades/workflow-claude-code/SKILL.md +6 -6
- package/hooks/captura-acciones-post.js +151 -0
- package/hooks/captura-acciones-session.js +155 -0
- package/hooks/lib/briefing.js +512 -474
- package/hooks/lib/captura-acciones.js +392 -0
- package/hooks/lib/context-builder.js +2 -2
- package/hooks/lib/model-router.js +1 -1
- package/hooks/lib/token-estimator.js +2 -0
- package/hooks/linea-estado.js +7 -5
- package/llms.txt +29 -29
- package/manifiestos/canonical-hashes.json +1964 -1310
- package/manifiestos/hooks-config.json +18 -0
- package/manifiestos/modulos.json +4 -0
- package/manifiestos/skills-lock.json +1282 -1282
- package/package.json +93 -93
- package/plugin.json +371 -371
- package/reglas/git-coauthor.md +100 -100
- package/reglas/memoria-consolidada.md +41 -0
- package/reglas/pruebas.md +15 -0
- package/reglas/seguridad-agentes.md +66 -0
- package/schemas/agent-frontmatter.schema.json +294 -294
- package/schemas/instinct.schema.json +161 -152
- package/scripts/bootstrap-instintos.js +25 -7
- package/scripts/lib/claude-sessions.js +1 -0
- package/scripts/lib/gitignore-manifest.js +44 -11
- package/scripts/lib/skill-metrics.js +41 -1
- package/scripts/lib/tool-cost-analyzer.js +1 -0
- package/scripts/publicar.js +34 -85
- package/scripts/verificar-trazabilidad.js +329 -298
- package/scripts/vendor/claude-usage/__pycache__/scanner.cpython-314.pyc +0 -0
|
@@ -1,152 +1,161 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://swl-ses.dev/schemas/instinct.json",
|
|
4
|
-
"$schemaVersion": "1.0.0",
|
|
5
|
-
"title": "SWL Instinct",
|
|
6
|
-
"description": "Schema de validacion para instintos YAML del sistema SWL",
|
|
7
|
-
"type": "object",
|
|
8
|
-
"required": [
|
|
9
|
-
"version",
|
|
10
|
-
"instintos"
|
|
11
|
-
],
|
|
12
|
-
"properties": {
|
|
13
|
-
"version": {
|
|
14
|
-
"type": "string"
|
|
15
|
-
},
|
|
16
|
-
"generado": {
|
|
17
|
-
"type": "string"
|
|
18
|
-
},
|
|
19
|
-
"total_instintos": {
|
|
20
|
-
"type": "integer",
|
|
21
|
-
"minimum": 0
|
|
22
|
-
},
|
|
23
|
-
"instintos": {
|
|
24
|
-
"type": "array",
|
|
25
|
-
"items": {
|
|
26
|
-
"type": "object",
|
|
27
|
-
"required": [
|
|
28
|
-
"id",
|
|
29
|
-
"pattern",
|
|
30
|
-
"confidence",
|
|
31
|
-
"scope",
|
|
32
|
-
"status"
|
|
33
|
-
],
|
|
34
|
-
"properties": {
|
|
35
|
-
"id": {
|
|
36
|
-
"type": "string",
|
|
37
|
-
"pattern": "^inst-\\d{3,}$",
|
|
38
|
-
"description": "Identificador unico secuencial"
|
|
39
|
-
},
|
|
40
|
-
"pattern": {
|
|
41
|
-
"type": "string",
|
|
42
|
-
"minLength": 10,
|
|
43
|
-
"maxLength": 500,
|
|
44
|
-
"description": "Descripcion del patron observado"
|
|
45
|
-
},
|
|
46
|
-
"confidence": {
|
|
47
|
-
"type": "number",
|
|
48
|
-
"minimum": 0,
|
|
49
|
-
"maximum": 1,
|
|
50
|
-
"description": "Nivel de confianza (0.0 bajo, 1.0 certeza)"
|
|
51
|
-
},
|
|
52
|
-
"scope": {
|
|
53
|
-
"type": "string",
|
|
54
|
-
"enum": [
|
|
55
|
-
"project",
|
|
56
|
-
"domain",
|
|
57
|
-
"global"
|
|
58
|
-
],
|
|
59
|
-
"description": "Alcance del instinto"
|
|
60
|
-
},
|
|
61
|
-
"source": {
|
|
62
|
-
"type": "string",
|
|
63
|
-
"description": "ID de sesion o 'manual'"
|
|
64
|
-
},
|
|
65
|
-
"evidence_count": {
|
|
66
|
-
"type": "integer",
|
|
67
|
-
"minimum": 0,
|
|
68
|
-
"description": "Veces que el patron ha sido observado"
|
|
69
|
-
},
|
|
70
|
-
"last_validated": {
|
|
71
|
-
"type": "string",
|
|
72
|
-
"description": "Fecha de ultima validacion (YYYY-MM-DD)"
|
|
73
|
-
},
|
|
74
|
-
"contradictions": {
|
|
75
|
-
"type": "integer",
|
|
76
|
-
"minimum": 0,
|
|
77
|
-
"description": "Veces que el patron ha sido contradicho"
|
|
78
|
-
},
|
|
79
|
-
"status": {
|
|
80
|
-
"type": "string",
|
|
81
|
-
"enum": [
|
|
82
|
-
"active",
|
|
83
|
-
"degraded",
|
|
84
|
-
"promoted",
|
|
85
|
-
"archived"
|
|
86
|
-
],
|
|
87
|
-
"description": "Estado actual del instinto"
|
|
88
|
-
},
|
|
89
|
-
"tags": {
|
|
90
|
-
"type": "array",
|
|
91
|
-
"items": {
|
|
92
|
-
"type": "string"
|
|
93
|
-
},
|
|
94
|
-
"description": "Etiquetas para clasificacion"
|
|
95
|
-
},
|
|
96
|
-
"created_at": {
|
|
97
|
-
"type": "string",
|
|
98
|
-
"description": "Fecha de creacion (YYYY-MM-DD)"
|
|
99
|
-
},
|
|
100
|
-
"decay_half_life_days": {
|
|
101
|
-
"type": "integer",
|
|
102
|
-
"minimum": 1,
|
|
103
|
-
"default": 90,
|
|
104
|
-
"description": "Dias para que la confianza decaiga a la mitad. 90 dias por defecto."
|
|
105
|
-
},
|
|
106
|
-
"helpful_count": {
|
|
107
|
-
"type": "integer",
|
|
108
|
-
"minimum": 0,
|
|
109
|
-
"default": 0,
|
|
110
|
-
"description": "Numero de veces que el instinto fue util en una sesion"
|
|
111
|
-
},
|
|
112
|
-
"harmful_count": {
|
|
113
|
-
"type": "integer",
|
|
114
|
-
"minimum": 0,
|
|
115
|
-
"default": 0,
|
|
116
|
-
"description": "Numero de veces que el instinto guio a un resultado incorrecto"
|
|
117
|
-
},
|
|
118
|
-
"last_validated_at": {
|
|
119
|
-
"type": "string",
|
|
120
|
-
"description": "Timestamp ISO o YYYY-MM-DD de la ultima validacion via feedback (sustituye a last_validated en sistemas con scoring)"
|
|
121
|
-
},
|
|
122
|
-
"source_sessions": {
|
|
123
|
-
"type": "array",
|
|
124
|
-
"items": {
|
|
125
|
-
"type": "string"
|
|
126
|
-
},
|
|
127
|
-
"uniqueItems": true,
|
|
128
|
-
"description": "IDs de sesiones que contribuyeron a este instinto (para priorizacion por evidencia multiple)"
|
|
129
|
-
},
|
|
130
|
-
"source_agents": {
|
|
131
|
-
"type": "array",
|
|
132
|
-
"items": {
|
|
133
|
-
"type": "string"
|
|
134
|
-
},
|
|
135
|
-
"uniqueItems": true,
|
|
136
|
-
"description": "Nombres de agentes que validaron este instinto (cross-agent enrichment)"
|
|
137
|
-
},
|
|
138
|
-
"maturity": {
|
|
139
|
-
"type": "string",
|
|
140
|
-
"enum": [
|
|
141
|
-
"candidate",
|
|
142
|
-
"established",
|
|
143
|
-
"proven",
|
|
144
|
-
"deprecated"
|
|
145
|
-
],
|
|
146
|
-
"description": "Estado de maduracion derivado (computado, no persistente). Ver scripts/lib/scoring-instintos.js"
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://swl-ses.dev/schemas/instinct.json",
|
|
4
|
+
"$schemaVersion": "1.0.0",
|
|
5
|
+
"title": "SWL Instinct",
|
|
6
|
+
"description": "Schema de validacion para instintos YAML del sistema SWL",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"required": [
|
|
9
|
+
"version",
|
|
10
|
+
"instintos"
|
|
11
|
+
],
|
|
12
|
+
"properties": {
|
|
13
|
+
"version": {
|
|
14
|
+
"type": "string"
|
|
15
|
+
},
|
|
16
|
+
"generado": {
|
|
17
|
+
"type": "string"
|
|
18
|
+
},
|
|
19
|
+
"total_instintos": {
|
|
20
|
+
"type": "integer",
|
|
21
|
+
"minimum": 0
|
|
22
|
+
},
|
|
23
|
+
"instintos": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"required": [
|
|
28
|
+
"id",
|
|
29
|
+
"pattern",
|
|
30
|
+
"confidence",
|
|
31
|
+
"scope",
|
|
32
|
+
"status"
|
|
33
|
+
],
|
|
34
|
+
"properties": {
|
|
35
|
+
"id": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"pattern": "^inst-\\d{3,}$",
|
|
38
|
+
"description": "Identificador unico secuencial"
|
|
39
|
+
},
|
|
40
|
+
"pattern": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"minLength": 10,
|
|
43
|
+
"maxLength": 500,
|
|
44
|
+
"description": "Descripcion del patron observado"
|
|
45
|
+
},
|
|
46
|
+
"confidence": {
|
|
47
|
+
"type": "number",
|
|
48
|
+
"minimum": 0,
|
|
49
|
+
"maximum": 1,
|
|
50
|
+
"description": "Nivel de confianza (0.0 bajo, 1.0 certeza)"
|
|
51
|
+
},
|
|
52
|
+
"scope": {
|
|
53
|
+
"type": "string",
|
|
54
|
+
"enum": [
|
|
55
|
+
"project",
|
|
56
|
+
"domain",
|
|
57
|
+
"global"
|
|
58
|
+
],
|
|
59
|
+
"description": "Alcance del instinto"
|
|
60
|
+
},
|
|
61
|
+
"source": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"description": "ID de sesion o 'manual'"
|
|
64
|
+
},
|
|
65
|
+
"evidence_count": {
|
|
66
|
+
"type": "integer",
|
|
67
|
+
"minimum": 0,
|
|
68
|
+
"description": "Veces que el patron ha sido observado"
|
|
69
|
+
},
|
|
70
|
+
"last_validated": {
|
|
71
|
+
"type": "string",
|
|
72
|
+
"description": "Fecha de ultima validacion (YYYY-MM-DD)"
|
|
73
|
+
},
|
|
74
|
+
"contradictions": {
|
|
75
|
+
"type": "integer",
|
|
76
|
+
"minimum": 0,
|
|
77
|
+
"description": "Veces que el patron ha sido contradicho"
|
|
78
|
+
},
|
|
79
|
+
"status": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"enum": [
|
|
82
|
+
"active",
|
|
83
|
+
"degraded",
|
|
84
|
+
"promoted",
|
|
85
|
+
"archived"
|
|
86
|
+
],
|
|
87
|
+
"description": "Estado actual del instinto"
|
|
88
|
+
},
|
|
89
|
+
"tags": {
|
|
90
|
+
"type": "array",
|
|
91
|
+
"items": {
|
|
92
|
+
"type": "string"
|
|
93
|
+
},
|
|
94
|
+
"description": "Etiquetas para clasificacion"
|
|
95
|
+
},
|
|
96
|
+
"created_at": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"description": "Fecha de creacion (YYYY-MM-DD)"
|
|
99
|
+
},
|
|
100
|
+
"decay_half_life_days": {
|
|
101
|
+
"type": "integer",
|
|
102
|
+
"minimum": 1,
|
|
103
|
+
"default": 90,
|
|
104
|
+
"description": "Dias para que la confianza decaiga a la mitad. 90 dias por defecto."
|
|
105
|
+
},
|
|
106
|
+
"helpful_count": {
|
|
107
|
+
"type": "integer",
|
|
108
|
+
"minimum": 0,
|
|
109
|
+
"default": 0,
|
|
110
|
+
"description": "Numero de veces que el instinto fue util en una sesion"
|
|
111
|
+
},
|
|
112
|
+
"harmful_count": {
|
|
113
|
+
"type": "integer",
|
|
114
|
+
"minimum": 0,
|
|
115
|
+
"default": 0,
|
|
116
|
+
"description": "Numero de veces que el instinto guio a un resultado incorrecto"
|
|
117
|
+
},
|
|
118
|
+
"last_validated_at": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"description": "Timestamp ISO o YYYY-MM-DD de la ultima validacion via feedback (sustituye a last_validated en sistemas con scoring)"
|
|
121
|
+
},
|
|
122
|
+
"source_sessions": {
|
|
123
|
+
"type": "array",
|
|
124
|
+
"items": {
|
|
125
|
+
"type": "string"
|
|
126
|
+
},
|
|
127
|
+
"uniqueItems": true,
|
|
128
|
+
"description": "IDs de sesiones que contribuyeron a este instinto (para priorizacion por evidencia multiple)"
|
|
129
|
+
},
|
|
130
|
+
"source_agents": {
|
|
131
|
+
"type": "array",
|
|
132
|
+
"items": {
|
|
133
|
+
"type": "string"
|
|
134
|
+
},
|
|
135
|
+
"uniqueItems": true,
|
|
136
|
+
"description": "Nombres de agentes que validaron este instinto (cross-agent enrichment)"
|
|
137
|
+
},
|
|
138
|
+
"maturity": {
|
|
139
|
+
"type": "string",
|
|
140
|
+
"enum": [
|
|
141
|
+
"candidate",
|
|
142
|
+
"established",
|
|
143
|
+
"proven",
|
|
144
|
+
"deprecated"
|
|
145
|
+
],
|
|
146
|
+
"description": "Estado de maduracion derivado (computado, no persistente). Ver scripts/lib/scoring-instintos.js"
|
|
147
|
+
},
|
|
148
|
+
"tipo_memoria": {
|
|
149
|
+
"type": "string",
|
|
150
|
+
"enum": [
|
|
151
|
+
"semantic",
|
|
152
|
+
"episodic",
|
|
153
|
+
"procedural"
|
|
154
|
+
],
|
|
155
|
+
"description": "Eje cognitivo de memoria (ORTOGONAL al canal de almacenamiento): semantic=hechos/decisiones, episodic=experiencia pasada de una sesion, procedural=como manejar un caso. Opcional y backward-compatible: instintos sin el campo siguen validos. Ver reglas/memoria-consolidada.md."
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -49,15 +49,31 @@ const flags = {
|
|
|
49
49
|
// Config de secciones → confidence/tags
|
|
50
50
|
// ---------------------------------------------------------------------------
|
|
51
51
|
|
|
52
|
+
// tipo_memoria (eje cognitivo, Fase 19): patron/anti-patron = "cómo hacer / qué
|
|
53
|
+
// evitar" → procedural; decisión/gotcha/regla = hechos → semantic. episodic NO se
|
|
54
|
+
// infiere del bootstrap (nace de registros de sesión, no de APRENDIZAJES).
|
|
52
55
|
const SECCIONES = [
|
|
53
|
-
{ regex: /anti[-\s]?patrones?/i, confidence: 0.7, tags: ['anti-patron'] },
|
|
54
|
-
{ regex: /patrones?\s+exitosos?/i, confidence: 0.6, tags: ['patron'] },
|
|
55
|
-
{ regex: /decisiones?\s+de\s+arquitectura/i, confidence: 0.8, tags: ['decision', 'arquitectura'] },
|
|
56
|
-
{ regex: /gotchas?/i, confidence: 0.6, tags: ['gotcha'] },
|
|
57
|
-
{ regex: /patrones?/i, confidence: 0.6, tags: ['patron'] },
|
|
58
|
-
{ regex: /reglas?\s+de\s+proyecto/i, confidence: 0.8, tags: ['regla-proyecto'] },
|
|
56
|
+
{ regex: /anti[-\s]?patrones?/i, confidence: 0.7, tags: ['anti-patron'], tipoMemoria: 'procedural' },
|
|
57
|
+
{ regex: /patrones?\s+exitosos?/i, confidence: 0.6, tags: ['patron'], tipoMemoria: 'procedural' },
|
|
58
|
+
{ regex: /decisiones?\s+de\s+arquitectura/i, confidence: 0.8, tags: ['decision', 'arquitectura'], tipoMemoria: 'semantic' },
|
|
59
|
+
{ regex: /gotchas?/i, confidence: 0.6, tags: ['gotcha'], tipoMemoria: 'semantic' },
|
|
60
|
+
{ regex: /patrones?/i, confidence: 0.6, tags: ['patron'], tipoMemoria: 'procedural' },
|
|
61
|
+
{ regex: /reglas?\s+de\s+proyecto/i, confidence: 0.8, tags: ['regla-proyecto'], tipoMemoria: 'semantic' },
|
|
59
62
|
];
|
|
60
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Infiere el eje cognitivo de memoria de un instinto por su sección de origen.
|
|
66
|
+
* Heurístico declarado (no autoritativo): default 'semantic' para hechos.
|
|
67
|
+
* @param {string} seccion
|
|
68
|
+
* @returns {'semantic'|'episodic'|'procedural'}
|
|
69
|
+
*/
|
|
70
|
+
function inferirTipoMemoria(seccion) {
|
|
71
|
+
for (const s of SECCIONES) {
|
|
72
|
+
if (s.regex.test(seccion || '')) return s.tipoMemoria;
|
|
73
|
+
}
|
|
74
|
+
return 'semantic';
|
|
75
|
+
}
|
|
76
|
+
|
|
61
77
|
function detectarConfidence(seccion) {
|
|
62
78
|
for (const s of SECCIONES) {
|
|
63
79
|
if (s.regex.test(seccion)) return { confidence: s.confidence, tags: [...s.tags] };
|
|
@@ -163,6 +179,7 @@ function generarInstintos(entradas) {
|
|
|
163
179
|
tags,
|
|
164
180
|
created_at: hoy,
|
|
165
181
|
seccion_origen: e.seccion,
|
|
182
|
+
tipo_memoria: inferirTipoMemoria(e.seccion),
|
|
166
183
|
decay_half_life_days: 90,
|
|
167
184
|
helpful_count: 0,
|
|
168
185
|
harmful_count: 0,
|
|
@@ -200,6 +217,7 @@ instintos:
|
|
|
200
217
|
` tags: [${i.tags.map(t => `"${t}"`).join(', ')}]`,
|
|
201
218
|
` created_at: "${i.created_at}"`,
|
|
202
219
|
` seccion_origen: ${escapeYaml(i.seccion_origen)}`,
|
|
220
|
+
` tipo_memoria: ${i.tipo_memoria}`,
|
|
203
221
|
` decay_half_life_days: ${i.decay_half_life_days}`,
|
|
204
222
|
` helpful_count: ${i.helpful_count}`,
|
|
205
223
|
` harmful_count: ${i.harmful_count}`,
|
|
@@ -266,4 +284,4 @@ function main() {
|
|
|
266
284
|
|
|
267
285
|
if (require.main === module) main();
|
|
268
286
|
|
|
269
|
-
module.exports = { parsearAprendizajes, generarInstintos, detectarConfidence, main };
|
|
287
|
+
module.exports = { parsearAprendizajes, generarInstintos, detectarConfidence, inferirTipoMemoria, main };
|
|
@@ -27,6 +27,7 @@ const TOLERANCIA_FUTURO_MS = 60 * 1000;
|
|
|
27
27
|
|
|
28
28
|
// Tabla de precios por modelo (USD por token)
|
|
29
29
|
const PRECIOS_MODELO = {
|
|
30
|
+
'claude-opus-4-8': { entrada: 15 / 1_000_000, salida: 75 / 1_000_000 },
|
|
30
31
|
'claude-opus-4-7': { entrada: 15 / 1_000_000, salida: 75 / 1_000_000 },
|
|
31
32
|
'claude-opus-4-6': { entrada: 15 / 1_000_000, salida: 75 / 1_000_000 },
|
|
32
33
|
'claude-sonnet-4-6': { entrada: 3 / 1_000_000, salida: 15 / 1_000_000 },
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
* Todo lo que instala o genera en runtime se ignora en git (framework, hooks,
|
|
12
12
|
* métricas, sesiones, aprendizajes, trazas, instintos).
|
|
13
13
|
*
|
|
14
|
-
* Solo se commitean: CLAUDE.md, .claude/settings.json,
|
|
15
|
-
* .planning/ que el equipo edita
|
|
14
|
+
* Solo se commitean: CLAUDE.md, .claude/settings.json, instintos/proyecto.yaml
|
|
15
|
+
* (memoria del proyecto), y las plantillas de .planning/ que el equipo edita
|
|
16
|
+
* (PROYECTO.md, REQUISITOS.md, etc.).
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
const fs = require("fs");
|
|
@@ -54,11 +55,8 @@ const ENTRADAS_BASE = [
|
|
|
54
55
|
".swl-ses",
|
|
55
56
|
|
|
56
57
|
// ── Runtime: archivos generados automáticamente por hooks ──────────
|
|
57
|
-
//
|
|
58
|
-
".planning/APRENDIZAJES.md",
|
|
58
|
+
// Métricas (tracking-costos)
|
|
59
59
|
".planning/METRICAS.md",
|
|
60
|
-
".planning/COMPACTACION.md",
|
|
61
|
-
".planning/REPORTE-GRAFO.md",
|
|
62
60
|
|
|
63
61
|
// Audit trail (audit-trail.js, merkle-audit.js)
|
|
64
62
|
".planning/*.jsonl",
|
|
@@ -88,8 +86,13 @@ const ENTRADAS_BASE = [
|
|
|
88
86
|
"!.planning/locks/*PLAN.md.lock",
|
|
89
87
|
".planning/user-profile/",
|
|
90
88
|
|
|
91
|
-
// Instintos
|
|
92
|
-
|
|
89
|
+
// Instintos: global/perfil-usuario/prompt-appendices/autonomia son framework +
|
|
90
|
+
// runtime + personal (no se commitean). proyecto.yaml es memoria del proyecto
|
|
91
|
+
// (hermano YAML de APRENDIZAJES.md, memoria-consolidada § canal 3) → versionable.
|
|
92
|
+
// Patrón dir/* + negación: git no re-incluye archivos bajo un dir ignorado
|
|
93
|
+
// (mismo gotcha documentado en locks/ arriba), por eso se ignora el contenido.
|
|
94
|
+
"instintos/*",
|
|
95
|
+
"!instintos/proyecto.yaml",
|
|
93
96
|
|
|
94
97
|
// Base de datos de uso
|
|
95
98
|
"usage.db",
|
|
@@ -305,8 +308,16 @@ function limpiarTracked(cwd, extras = []) {
|
|
|
305
308
|
return resultado; // No es repo git, nada que hacer
|
|
306
309
|
}
|
|
307
310
|
|
|
308
|
-
// Obtener todas las entradas gitignore de swl-ses (directorios y archivos)
|
|
309
|
-
|
|
311
|
+
// Obtener todas las entradas gitignore de swl-ses (directorios y archivos).
|
|
312
|
+
// Las negaciones (!...) marcan archivos versionables que NUNCA se des-trackean
|
|
313
|
+
// (instintos/proyecto.yaml, plan-locks G1 *PLAN.md.lock). git ls-files NO honra
|
|
314
|
+
// las negaciones del .gitignore, así que se excluyen explícitamente de la lista
|
|
315
|
+
// a limpiar — de lo contrario el glob padre (instintos/*, locks/*) las arrastraría.
|
|
316
|
+
const todas = [...new Set([...ENTRADAS_BASE, ...extras])];
|
|
317
|
+
const negaciones = todas
|
|
318
|
+
.filter((e) => e.startsWith("!"))
|
|
319
|
+
.map((e) => patronAGlobRegex(e.slice(1)));
|
|
320
|
+
const entradas = todas.filter((e) => !e.startsWith("!"));
|
|
310
321
|
|
|
311
322
|
for (const entrada of entradas) {
|
|
312
323
|
try {
|
|
@@ -322,7 +333,12 @@ function limpiarTracked(cwd, extras = []) {
|
|
|
322
333
|
|
|
323
334
|
if (!archivosTracked) continue;
|
|
324
335
|
|
|
325
|
-
const lista = archivosTracked
|
|
336
|
+
const lista = archivosTracked
|
|
337
|
+
.split("\n")
|
|
338
|
+
.filter(Boolean)
|
|
339
|
+
// Preservar archivos versionables cubiertos por una negación del gitignore
|
|
340
|
+
// (ej. instintos/proyecto.yaml frente al glob instintos/*).
|
|
341
|
+
.filter((archivo) => !negaciones.some((re) => re.test(archivo)));
|
|
326
342
|
if (lista.length === 0) continue;
|
|
327
343
|
|
|
328
344
|
// Quitar del índice uno por uno (--cached = solo del índice, no del disco)
|
|
@@ -353,6 +369,23 @@ function escapeRegex(str) {
|
|
|
353
369
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
354
370
|
}
|
|
355
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Convierte un patrón estilo gitignore (sin el '!' inicial) a una RegExp anclada
|
|
374
|
+
* para matchear rutas que devuelve `git ls-files` (siempre con '/' como separador).
|
|
375
|
+
* `*` no cruza '/' (semántica gitignore). Una entrada de directorio matchea también
|
|
376
|
+
* su contenido. Se usa en limpiarTracked para excluir archivos negados del untrack.
|
|
377
|
+
*
|
|
378
|
+
* @param {string} patron Ej. "instintos/proyecto.yaml", ".planning/locks/*PLAN.md.lock"
|
|
379
|
+
* @returns {RegExp}
|
|
380
|
+
*/
|
|
381
|
+
function patronAGlobRegex(patron) {
|
|
382
|
+
const cuerpo = patron
|
|
383
|
+
.replace(/\/$/, "")
|
|
384
|
+
.replace(/[.+?^${}()|[\]\\]/g, "\\$&")
|
|
385
|
+
.replace(/\*/g, "[^/]*");
|
|
386
|
+
return new RegExp("^" + cuerpo + "(?:/.*)?$");
|
|
387
|
+
}
|
|
388
|
+
|
|
356
389
|
module.exports = {
|
|
357
390
|
actualizarGitignore,
|
|
358
391
|
entradasParaRuntime,
|
|
@@ -199,11 +199,38 @@ function resumen(cwd) {
|
|
|
199
199
|
};
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
+
const MS_DIA = 86400000;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Skills "fríos": tuvieron uso previo pero su último uso es más antiguo que `dias`.
|
|
206
|
+
* Los skills NUNCA usados NO aparecen (obtenerMetricas solo incluye skills con ≥1
|
|
207
|
+
* entrada) — eso es bloat, dominio distinto a staleness (Fase 20 / análisis self-learning).
|
|
208
|
+
*
|
|
209
|
+
* @param {string} cwd
|
|
210
|
+
* @param {Date} [hoy=new Date()]
|
|
211
|
+
* @param {{dias?: number}} [opts] umbral en días (default SWL_SKILL_STALE_DIAS o 90)
|
|
212
|
+
* @returns {Array<{skill: string, ultimoUso: string, diasInactivo: number}>}
|
|
213
|
+
* ordenado por diasInactivo descendente.
|
|
214
|
+
*/
|
|
215
|
+
function skillsStale(cwd, hoy = new Date(), opts = {}) {
|
|
216
|
+
const dias = Number(opts.dias) || Number(process.env.SWL_SKILL_STALE_DIAS) || 90;
|
|
217
|
+
const ahora = (hoy instanceof Date ? hoy : new Date(hoy)).getTime();
|
|
218
|
+
const out = [];
|
|
219
|
+
for (const m of obtenerMetricas(cwd)) {
|
|
220
|
+
if (!m.ultimoUso) continue;
|
|
221
|
+
const t = new Date(m.ultimoUso).getTime();
|
|
222
|
+
if (Number.isNaN(t)) continue;
|
|
223
|
+
const diasInactivo = Math.floor((ahora - t) / MS_DIA);
|
|
224
|
+
if (diasInactivo > dias) out.push({ skill: m.skill, ultimoUso: m.ultimoUso, diasInactivo });
|
|
225
|
+
}
|
|
226
|
+
return out.sort((a, b) => b.diasInactivo - a.diasInactivo);
|
|
227
|
+
}
|
|
228
|
+
|
|
202
229
|
// ---------------------------------------------------------------------------
|
|
203
230
|
// Exports
|
|
204
231
|
// ---------------------------------------------------------------------------
|
|
205
232
|
|
|
206
|
-
module.exports = { registrarUso, obtenerMetricas, topFallidos, topLentos, resumen };
|
|
233
|
+
module.exports = { registrarUso, obtenerMetricas, topFallidos, topLentos, resumen, skillsStale };
|
|
207
234
|
|
|
208
235
|
// ---------------------------------------------------------------------------
|
|
209
236
|
// CLI dual-use
|
|
@@ -218,6 +245,19 @@ if (require.main === module) {
|
|
|
218
245
|
process.exit(0);
|
|
219
246
|
}
|
|
220
247
|
|
|
248
|
+
if (cmd === '--stale' || cmd === 'stale') {
|
|
249
|
+
const stale = skillsStale(cwd);
|
|
250
|
+
if (stale.length === 0) {
|
|
251
|
+
process.stdout.write('Sin skills fríos (todos con uso reciente o sin métricas).\n');
|
|
252
|
+
} else {
|
|
253
|
+
process.stdout.write('\nSkills fríos (uso previo, inactivos > umbral):\n');
|
|
254
|
+
for (const s of stale) {
|
|
255
|
+
process.stdout.write(` ${s.skill.padEnd(36)} ${String(s.diasInactivo).padStart(4)}d sin uso → /swl:evaluar-skill ${s.skill}\n`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
process.exit(0);
|
|
259
|
+
}
|
|
260
|
+
|
|
221
261
|
// Modo resumen (default)
|
|
222
262
|
const r = resumen(cwd);
|
|
223
263
|
process.stdout.write('\nMétricas de habilidades SWL\n');
|
|
@@ -23,6 +23,7 @@ const DB_PATH = path.join(os.homedir(), '.claude', 'usage.db');
|
|
|
23
23
|
|
|
24
24
|
// Precios estimados por 1M tokens (USD) — actualizados a 2026-04-17
|
|
25
25
|
const PRECIOS = {
|
|
26
|
+
'claude-opus-4-8': { input: 15.00, output: 75.00, cache_read: 1.50, cache_creation: 18.75 },
|
|
26
27
|
'claude-opus-4-7': { input: 15.00, output: 75.00, cache_read: 1.50, cache_creation: 18.75 },
|
|
27
28
|
'claude-opus-4-6': { input: 15.00, output: 75.00, cache_read: 1.50, cache_creation: 18.75 },
|
|
28
29
|
'claude-sonnet-4-6': { input: 3.00, output: 15.00, cache_read: 0.30, cache_creation: 3.75 },
|