swl-ses 3.3.2
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 +425 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/accesibilidad-wcag-swl.md +683 -0
- package/agentes/arquitecto-swl.md +210 -0
- package/agentes/auto-evolucion-swl.md +408 -0
- package/agentes/backend-api-swl.md +442 -0
- package/agentes/backend-node-swl.md +439 -0
- package/agentes/backend-python-swl.md +469 -0
- package/agentes/backend-workers-swl.md +444 -0
- package/agentes/cloud-infra-swl.md +466 -0
- package/agentes/consolidador-swl.md +487 -0
- package/agentes/datos-swl.md +568 -0
- package/agentes/depurador-swl.md +301 -0
- package/agentes/devops-ci-swl.md +352 -0
- package/agentes/disenador-ui-swl.md +546 -0
- package/agentes/documentador-swl.md +323 -0
- package/agentes/frontend-angular-swl.md +603 -0
- package/agentes/frontend-css-swl.md +700 -0
- package/agentes/frontend-react-swl.md +672 -0
- package/agentes/frontend-swl.md +483 -0
- package/agentes/frontend-tailwind-swl.md +808 -0
- package/agentes/implementador-swl.md +235 -0
- package/agentes/investigador-swl.md +274 -0
- package/agentes/investigador-ux-swl.md +482 -0
- package/agentes/migrador-swl.md +389 -0
- package/agentes/mobile-android-swl.md +473 -0
- package/agentes/mobile-cross-swl.md +501 -0
- package/agentes/mobile-ios-swl.md +464 -0
- package/agentes/notificador-swl.md +886 -0
- package/agentes/observabilidad-swl.md +408 -0
- package/agentes/orquestador-swl.md +490 -0
- package/agentes/planificador-swl.md +222 -0
- package/agentes/producto-prd-swl.md +565 -0
- package/agentes/release-manager-swl.md +545 -0
- package/agentes/rendimiento-swl.md +691 -0
- package/agentes/revisor-codigo-swl.md +254 -0
- package/agentes/revisor-seguridad-swl.md +316 -0
- package/agentes/tdd-qa-swl.md +323 -0
- package/agentes/ux-disenador-swl.md +498 -0
- package/bin/swl-ses.js +119 -0
- package/comandos/swl/actualizar.md +117 -0
- package/comandos/swl/aprender.md +348 -0
- package/comandos/swl/auditar-deps.md +390 -0
- package/comandos/swl/autoresearch.md +346 -0
- package/comandos/swl/checkpoint.md +296 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/crear-skill.md +609 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +302 -0
- package/comandos/swl/evolucionar.md +377 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/mapear-codebase.md +205 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/release.md +405 -0
- package/comandos/swl/salud.md +382 -0
- package/comandos/swl/verificar.md +292 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +584 -0
- package/habilidades/angular-avanzado/SKILL.md +491 -0
- package/habilidades/angular-moderno/SKILL.md +326 -0
- package/habilidades/api-rest-diseno/SKILL.md +302 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +369 -0
- package/habilidades/async-python/SKILL.md +474 -0
- package/habilidades/auth-patrones/SKILL.md +488 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +376 -0
- package/habilidades/autoresearch/SKILL.md +248 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/checklist-calidad/SKILL.md +247 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +224 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +309 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +583 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/cloud-aws/SKILL.md +497 -0
- package/habilidades/compactacion-contexto/SKILL.md +201 -0
- package/habilidades/contenedores-docker/SKILL.md +453 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/css-moderno/SKILL.md +463 -0
- package/habilidades/datos-etl/SKILL.md +486 -0
- package/habilidades/dependencias-auditoria/SKILL.md +293 -0
- package/habilidades/deprecacion-migracion/SKILL.md +485 -0
- package/habilidades/design-tokens/SKILL.md +519 -0
- package/habilidades/discutir-fase/SKILL.md +167 -0
- package/habilidades/diseno-responsivo/SKILL.md +326 -0
- package/habilidades/django-experto/SKILL.md +395 -0
- package/habilidades/doc-sync/SKILL.md +259 -0
- package/habilidades/ejecutar-fase/SKILL.md +199 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +459 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +213 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/event-driven/SKILL.md +580 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +234 -0
- package/habilidades/fastapi-experto/SKILL.md +368 -0
- package/habilidades/frontend-avanzado/SKILL.md +555 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +246 -0
- package/habilidades/iam-secretos/SKILL.md +511 -0
- package/habilidades/instalar-sistema/SKILL.md +140 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +549 -0
- package/habilidades/manejo-errores/SKILL.md +512 -0
- package/habilidades/mapear-codebase/SKILL.md +199 -0
- package/habilidades/microservicios/SKILL.md +473 -0
- package/habilidades/mobile-flutter/SKILL.md +566 -0
- package/habilidades/mobile-react-native/SKILL.md +493 -0
- package/habilidades/monitoring-alertas/SKILL.md +447 -0
- package/habilidades/node-experto/SKILL.md +521 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +448 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/nuevo-proyecto/SKILL.md +183 -0
- package/habilidades/patrones-python/SKILL.md +381 -0
- package/habilidades/performance-baseline/SKILL.md +243 -0
- package/habilidades/planear-fase/SKILL.md +184 -0
- package/habilidades/postgresql-experto/SKILL.md +379 -0
- package/habilidades/react-experto/SKILL.md +434 -0
- package/habilidades/react-optimizacion/SKILL.md +328 -0
- package/habilidades/release-semver/SKILL.md +226 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/sql-optimizacion/SKILL.md +314 -0
- package/habilidades/tailwind-experto/SKILL.md +412 -0
- package/habilidades/tdd-workflow/SKILL.md +267 -0
- package/habilidades/testing-python/SKILL.md +350 -0
- package/habilidades/threat-model-lite/SKILL.md +218 -0
- package/habilidades/typescript-avanzado/SKILL.md +454 -0
- package/habilidades/ux-diseno/SKILL.md +488 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +543 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificar-trabajo/SKILL.md +208 -0
- package/habilidades/wireframes-flujos/SKILL.md +396 -0
- package/habilidades/workflow-claude-code/SKILL.md +359 -0
- package/hooks/calidad-pre-commit.js +578 -0
- package/hooks/escaneo-secretos.js +302 -0
- package/hooks/extraccion-aprendizajes.js +550 -0
- package/hooks/linea-estado.js +249 -0
- package/hooks/monitor-contexto.js +230 -0
- package/hooks/proteccion-rutas.js +249 -0
- package/manifiestos/hooks-config.json +41 -0
- package/manifiestos/modulos.json +318 -0
- package/manifiestos/perfiles.json +189 -0
- package/package.json +45 -0
- package/plantillas/PROJECT.md +122 -0
- package/plantillas/REQUIREMENTS.md +132 -0
- package/plantillas/ROADMAP.md +143 -0
- package/plantillas/STATE.md +109 -0
- package/plantillas/research/ARCHITECTURE.md +220 -0
- package/plantillas/research/FEATURES.md +175 -0
- package/plantillas/research/PITFALLS.md +299 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/SUMMARY.md +165 -0
- package/plugin.json +144 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +183 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +179 -0
- package/reglas/git-workflow.md +186 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +473 -0
- package/scripts/actualizar.js +51 -0
- package/scripts/desinstalar.js +86 -0
- package/scripts/doctor.js +222 -0
- package/scripts/inicializar.js +89 -0
- package/scripts/instalador.js +333 -0
- package/scripts/lib/detectar-runtime.js +177 -0
- package/scripts/lib/estado.js +112 -0
- package/scripts/lib/hooks-settings.js +283 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/publicar.js +209 -0
- package/scripts/validar.js +120 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cloud-aws
|
|
3
|
+
description: Mejores prácticas de AWS. EC2, S3, RDS, Lambda, ECS/EKS, CloudFront, IAM, VPC, SQS/SNS, DynamoDB. Well-Architected Framework, optimización de costos, patrones serverless vs containers.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AWS — Mejores Prácticas de Nube
|
|
7
|
+
|
|
8
|
+
Este skill cubre decisiones de arquitectura, seguridad y costos en AWS para sistemas
|
|
9
|
+
de producción. Los ejemplos usan Python (boto3) y configuración de infraestructura.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Well-Architected Framework — 6 Pilares
|
|
14
|
+
|
|
15
|
+
| Pilar | Pregunta clave |
|
|
16
|
+
|-------|---------------|
|
|
17
|
+
| **Excelencia operativa** | ¿Puedes operar y mejorar continuamente? |
|
|
18
|
+
| **Seguridad** | ¿Proteges la información y los sistemas? |
|
|
19
|
+
| **Confiabilidad** | ¿Recuperas de fallos automáticamente? |
|
|
20
|
+
| **Eficiencia de desempeño** | ¿Usas recursos eficientemente? |
|
|
21
|
+
| **Optimización de costos** | ¿Pagas solo por lo que usas? |
|
|
22
|
+
| **Sostenibilidad** | ¿Minimizas impacto ambiental? |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 2. IAM — Mínimo Privilegio Siempre
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
// MAL: permisos de administrador para una Lambda
|
|
30
|
+
{
|
|
31
|
+
"Effect": "Allow",
|
|
32
|
+
"Action": "*",
|
|
33
|
+
"Resource": "*"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// BIEN: solo lo que necesita la función
|
|
37
|
+
{
|
|
38
|
+
"Version": "2012-10-17",
|
|
39
|
+
"Statement": [
|
|
40
|
+
{
|
|
41
|
+
"Sid": "LeerBucketNomina",
|
|
42
|
+
"Effect": "Allow",
|
|
43
|
+
"Action": ["s3:GetObject", "s3:ListBucket"],
|
|
44
|
+
"Resource": [
|
|
45
|
+
"arn:aws:s3:::empresa-nomina-prod",
|
|
46
|
+
"arn:aws:s3:::empresa-nomina-prod/*"
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"Sid": "EscribirSecretosNomina",
|
|
51
|
+
"Effect": "Allow",
|
|
52
|
+
"Action": ["secretsmanager:GetSecretValue"],
|
|
53
|
+
"Resource": "arn:aws:secretsmanager:us-east-1:123456789:secret:nomina/*"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import boto3
|
|
61
|
+
|
|
62
|
+
# NUNCA hardcodear credenciales AWS
|
|
63
|
+
# MAL:
|
|
64
|
+
# cliente = boto3.client('s3', aws_access_key_id='AKIA...', aws_secret_access_key='...')
|
|
65
|
+
|
|
66
|
+
# BIEN: usar IAM roles (en EC2/ECS/Lambda automático) o ~/.aws/credentials en local
|
|
67
|
+
cliente_s3 = boto3.client('s3', region_name='us-east-1')
|
|
68
|
+
|
|
69
|
+
# BIEN: usar AWS Secrets Manager para credenciales de terceros
|
|
70
|
+
import json
|
|
71
|
+
|
|
72
|
+
def obtener_credenciales_db() -> dict:
|
|
73
|
+
cliente = boto3.client('secretsmanager', region_name='us-east-1')
|
|
74
|
+
respuesta = cliente.get_secret_value(SecretId='prod/miaplicacion/rds')
|
|
75
|
+
return json.loads(respuesta['SecretString'])
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 3. VPC — Red Segura
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
Arquitectura de red recomendada:
|
|
84
|
+
|
|
85
|
+
VPC: 10.0.0.0/16
|
|
86
|
+
├── Public Subnets (2 AZs) — ALB, NAT Gateway, Bastion
|
|
87
|
+
│ ├── 10.0.1.0/24 (us-east-1a)
|
|
88
|
+
│ └── 10.0.2.0/24 (us-east-1b)
|
|
89
|
+
├── Private App Subnets (2 AZs) — ECS Tasks, EC2 App servers
|
|
90
|
+
│ ├── 10.0.11.0/24 (us-east-1a)
|
|
91
|
+
│ └── 10.0.12.0/24 (us-east-1b)
|
|
92
|
+
└── Private Data Subnets (2 AZs) — RDS, ElastiCache
|
|
93
|
+
├── 10.0.21.0/24 (us-east-1a)
|
|
94
|
+
└── 10.0.22.0/24 (us-east-1b)
|
|
95
|
+
|
|
96
|
+
Reglas:
|
|
97
|
+
- Internet → ALB (80, 443) ✓
|
|
98
|
+
- ALB → App Servers (8000) ✓
|
|
99
|
+
- App Servers → RDS (5432) ✓
|
|
100
|
+
- App Servers → Internet via NAT (outbound) ✓
|
|
101
|
+
- RDS → Internet ✗ NUNCA
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Security Groups — Regla de mínimo privilegio
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
# Terraform-style pseudocódigo
|
|
108
|
+
security_groups = {
|
|
109
|
+
"alb_sg": {
|
|
110
|
+
"ingress": [
|
|
111
|
+
{"from": 80, "to": 80, "cidr": "0.0.0.0/0"},
|
|
112
|
+
{"from": 443, "to": 443, "cidr": "0.0.0.0/0"},
|
|
113
|
+
],
|
|
114
|
+
"egress": [{"from": 8000, "to": 8000, "sg": "app_sg"}],
|
|
115
|
+
},
|
|
116
|
+
"app_sg": {
|
|
117
|
+
"ingress": [{"from": 8000, "to": 8000, "sg": "alb_sg"}],
|
|
118
|
+
"egress": [
|
|
119
|
+
{"from": 5432, "to": 5432, "sg": "rds_sg"},
|
|
120
|
+
{"from": 443, "to": 443, "cidr": "0.0.0.0/0"}, # APIs externas
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
"rds_sg": {
|
|
124
|
+
"ingress": [{"from": 5432, "to": 5432, "sg": "app_sg"}],
|
|
125
|
+
"egress": [], # RDS no necesita salida
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 4. S3 — Almacenamiento Seguro
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import boto3
|
|
136
|
+
from botocore.exceptions import ClientError
|
|
137
|
+
|
|
138
|
+
cliente_s3 = boto3.client('s3')
|
|
139
|
+
|
|
140
|
+
# OBLIGATORIO: cifrado en reposo + versionado + bloquear acceso público
|
|
141
|
+
def configurar_bucket_seguro(nombre_bucket: str) -> None:
|
|
142
|
+
s3 = boto3.client('s3')
|
|
143
|
+
|
|
144
|
+
# Bloquear acceso público (SIEMPRE para datos sensibles)
|
|
145
|
+
s3.put_public_access_block(
|
|
146
|
+
Bucket=nombre_bucket,
|
|
147
|
+
PublicAccessBlockConfiguration={
|
|
148
|
+
'BlockPublicAcls': True,
|
|
149
|
+
'IgnorePublicAcls': True,
|
|
150
|
+
'BlockPublicPolicy': True,
|
|
151
|
+
'RestrictPublicBuckets': True,
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# Cifrado AES-256 o KMS
|
|
156
|
+
s3.put_bucket_encryption(
|
|
157
|
+
Bucket=nombre_bucket,
|
|
158
|
+
ServerSideEncryptionConfiguration={
|
|
159
|
+
'Rules': [{'ApplyServerSideEncryptionByDefault': {
|
|
160
|
+
'SSEAlgorithm': 'aws:kms',
|
|
161
|
+
'KMSMasterKeyID': 'arn:aws:kms:...',
|
|
162
|
+
}}]
|
|
163
|
+
}
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Versionado (recuperación ante errores)
|
|
167
|
+
s3.put_bucket_versioning(
|
|
168
|
+
Bucket=nombre_bucket,
|
|
169
|
+
VersioningConfiguration={'Status': 'Enabled'}
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# URLs prefirmadas para descarga sin exponer bucket público
|
|
173
|
+
def generar_url_descarga(bucket: str, clave: str, segundos: int = 3600) -> str:
|
|
174
|
+
return cliente_s3.generate_presigned_url(
|
|
175
|
+
'get_object',
|
|
176
|
+
Params={'Bucket': bucket, 'Key': clave},
|
|
177
|
+
ExpiresIn=segundos,
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
# Ciclo de vida — bajar costos moviendo a clases más baratas
|
|
181
|
+
lifecycle_policy = {
|
|
182
|
+
'Rules': [{
|
|
183
|
+
'ID': 'ArchivarDocumentosViejos',
|
|
184
|
+
'Status': 'Enabled',
|
|
185
|
+
'Transitions': [
|
|
186
|
+
{'Days': 30, 'StorageClass': 'STANDARD_IA'},
|
|
187
|
+
{'Days': 90, 'StorageClass': 'GLACIER'},
|
|
188
|
+
{'Days': 365, 'StorageClass': 'DEEP_ARCHIVE'},
|
|
189
|
+
],
|
|
190
|
+
'Expiration': {'Days': 2555}, # 7 años
|
|
191
|
+
}]
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## 5. RDS — Base de Datos en Producción
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
# Configuración recomendada para PostgreSQL en RDS
|
|
201
|
+
rds_config = {
|
|
202
|
+
"DBInstanceClass": "db.t3.medium", # Tamaño según carga
|
|
203
|
+
"Engine": "postgres",
|
|
204
|
+
"EngineVersion": "15.4",
|
|
205
|
+
"MultiAZ": True, # OBLIGATORIO en producción
|
|
206
|
+
"StorageEncrypted": True, # OBLIGATORIO
|
|
207
|
+
"BackupRetentionPeriod": 7, # 7 días de backups automáticos
|
|
208
|
+
"EnablePerformanceInsights": True,
|
|
209
|
+
"PerformanceInsightsRetentionPeriod": 7,
|
|
210
|
+
"MonitoringInterval": 60, # Enhanced monitoring
|
|
211
|
+
"DeletionProtection": True, # Evitar eliminación accidental
|
|
212
|
+
"StorageType": "gp3",
|
|
213
|
+
"Iops": 3000,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# Connection pool recomendado para Python
|
|
217
|
+
DATABASE_URL = (
|
|
218
|
+
f"postgresql+asyncpg://{usuario}:{password}@{host}:{puerto}/{db}"
|
|
219
|
+
"?ssl=require" # SIEMPRE ssl en RDS
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Pool sizing: (núcleos_cpu * 2) + disco_efectivo
|
|
223
|
+
# Para db.t3.medium (2 vCPUs): pool_size = 5, max_overflow = 10
|
|
224
|
+
engine = create_async_engine(
|
|
225
|
+
DATABASE_URL,
|
|
226
|
+
pool_size=5,
|
|
227
|
+
max_overflow=10,
|
|
228
|
+
pool_pre_ping=True,
|
|
229
|
+
pool_recycle=3600, # Reciclar conexiones cada hora (evitar timeout RDS)
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## 6. Lambda — Funciones Serverless
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
import json
|
|
239
|
+
import logging
|
|
240
|
+
import os
|
|
241
|
+
from typing import Any
|
|
242
|
+
|
|
243
|
+
logger = logging.getLogger()
|
|
244
|
+
logger.setLevel(logging.INFO)
|
|
245
|
+
|
|
246
|
+
# Inicializar clientes FUERA del handler (reutilización en warm start)
|
|
247
|
+
import boto3
|
|
248
|
+
sqs = boto3.client('sqs')
|
|
249
|
+
s3 = boto3.client('s3')
|
|
250
|
+
|
|
251
|
+
def handler(event: dict, context: Any) -> dict:
|
|
252
|
+
"""Lambda handler para procesamiento de eventos SQS."""
|
|
253
|
+
logger.info("Evento recibido: %s registros", len(event.get('Records', [])))
|
|
254
|
+
|
|
255
|
+
errores = []
|
|
256
|
+
for record in event.get('Records', []):
|
|
257
|
+
try:
|
|
258
|
+
body = json.loads(record['body'])
|
|
259
|
+
procesar_registro(body)
|
|
260
|
+
except Exception as e:
|
|
261
|
+
logger.error("Error en record %s: %s", record['messageId'], e)
|
|
262
|
+
errores.append({'itemIdentifier': record['messageId']})
|
|
263
|
+
|
|
264
|
+
# Partial batch response — solo reintentar los que fallaron
|
|
265
|
+
return {'batchItemFailures': errores}
|
|
266
|
+
|
|
267
|
+
def procesar_registro(datos: dict) -> None:
|
|
268
|
+
# Lógica de negocio aquí
|
|
269
|
+
pass
|
|
270
|
+
|
|
271
|
+
# Configuración recomendada en serverless.yml / CDK
|
|
272
|
+
lambda_config = {
|
|
273
|
+
"timeout": 30, # Segundos. Nunca dejar el default (3s)
|
|
274
|
+
"memory_size": 512, # MB. Benchmark para encontrar sweet spot
|
|
275
|
+
"reserved_concurrency": 10, # Evitar que explote en concurrencia
|
|
276
|
+
"environment": {
|
|
277
|
+
"QUEUE_URL": "${ssm:/prod/cola-procesamiento}",
|
|
278
|
+
"LOG_LEVEL": "INFO",
|
|
279
|
+
},
|
|
280
|
+
"layers": ["arn:aws:lambda:us-east-1:...:layer:deps:5"], # Dependencias
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## 7. ECS Fargate — Containers Administrados
|
|
287
|
+
|
|
288
|
+
```yaml
|
|
289
|
+
# task-definition.json
|
|
290
|
+
{
|
|
291
|
+
"family": "api-nomina",
|
|
292
|
+
"networkMode": "awsvpc",
|
|
293
|
+
"requiresCompatibilities": ["FARGATE"],
|
|
294
|
+
"cpu": "512",
|
|
295
|
+
"memory": "1024",
|
|
296
|
+
"executionRoleArn": "arn:aws:iam::...:role/ecsTaskExecutionRole",
|
|
297
|
+
"taskRoleArn": "arn:aws:iam::...:role/ecsTaskRole",
|
|
298
|
+
"containerDefinitions": [{
|
|
299
|
+
"name": "api",
|
|
300
|
+
"image": "123456789.dkr.ecr.us-east-1.amazonaws.com/api-nomina:latest",
|
|
301
|
+
"portMappings": [{"containerPort": 8000, "protocol": "tcp"}],
|
|
302
|
+
"environment": [],
|
|
303
|
+
"secrets": [
|
|
304
|
+
{
|
|
305
|
+
"name": "DATABASE_URL",
|
|
306
|
+
"valueFrom": "arn:aws:secretsmanager:...:secret:prod/db-url"
|
|
307
|
+
}
|
|
308
|
+
],
|
|
309
|
+
"logConfiguration": {
|
|
310
|
+
"logDriver": "awslogs",
|
|
311
|
+
"options": {
|
|
312
|
+
"awslogs-group": "/ecs/api-nomina",
|
|
313
|
+
"awslogs-region": "us-east-1",
|
|
314
|
+
"awslogs-stream-prefix": "ecs"
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"healthCheck": {
|
|
318
|
+
"command": ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"],
|
|
319
|
+
"interval": 30,
|
|
320
|
+
"timeout": 5,
|
|
321
|
+
"retries": 3,
|
|
322
|
+
"startPeriod": 60
|
|
323
|
+
}
|
|
324
|
+
}]
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## 8. SQS/SNS — Mensajería Desacoplada
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
import boto3
|
|
334
|
+
import json
|
|
335
|
+
from typing import Any
|
|
336
|
+
|
|
337
|
+
sqs = boto3.client('sqs', region_name='us-east-1')
|
|
338
|
+
sns = boto3.client('sns', region_name='us-east-1')
|
|
339
|
+
|
|
340
|
+
QUEUE_URL = os.environ['QUEUE_URL']
|
|
341
|
+
|
|
342
|
+
def enviar_mensaje(payload: dict, grupo_id: str | None = None) -> str:
|
|
343
|
+
"""Enviar mensaje a SQS. grupo_id para FIFO queues."""
|
|
344
|
+
kwargs: dict[str, Any] = {
|
|
345
|
+
'QueueUrl': QUEUE_URL,
|
|
346
|
+
'MessageBody': json.dumps(payload, ensure_ascii=False),
|
|
347
|
+
'MessageAttributes': {
|
|
348
|
+
'ContentType': {
|
|
349
|
+
'StringValue': 'application/json',
|
|
350
|
+
'DataType': 'String',
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
}
|
|
354
|
+
if grupo_id: # FIFO queue
|
|
355
|
+
import uuid
|
|
356
|
+
kwargs['MessageGroupId'] = grupo_id
|
|
357
|
+
kwargs['MessageDeduplicationId'] = str(uuid.uuid4())
|
|
358
|
+
|
|
359
|
+
respuesta = sqs.send_message(**kwargs)
|
|
360
|
+
return respuesta['MessageId']
|
|
361
|
+
|
|
362
|
+
def procesar_mensajes(max_mensajes: int = 10) -> None:
|
|
363
|
+
"""Polling de mensajes con visibilidad extendida."""
|
|
364
|
+
mensajes = sqs.receive_message(
|
|
365
|
+
QueueUrl=QUEUE_URL,
|
|
366
|
+
MaxNumberOfMessages=max_mensajes,
|
|
367
|
+
WaitTimeSeconds=20, # Long polling — más eficiente
|
|
368
|
+
VisibilityTimeout=60, # Tiempo para procesar
|
|
369
|
+
AttributeNames=['All'],
|
|
370
|
+
).get('Messages', [])
|
|
371
|
+
|
|
372
|
+
for msg in mensajes:
|
|
373
|
+
try:
|
|
374
|
+
body = json.loads(msg['Body'])
|
|
375
|
+
procesar(body)
|
|
376
|
+
# Eliminar solo si se procesó exitosamente
|
|
377
|
+
sqs.delete_message(
|
|
378
|
+
QueueUrl=QUEUE_URL,
|
|
379
|
+
ReceiptHandle=msg['ReceiptHandle'],
|
|
380
|
+
)
|
|
381
|
+
except Exception as e:
|
|
382
|
+
logger.error("Error procesando mensaje %s: %s", msg['MessageId'], e)
|
|
383
|
+
# Dejar en cola — irá a DLQ después de maxReceiveCount intentos
|
|
384
|
+
|
|
385
|
+
# Dead Letter Queue — SIEMPRE configurar para auditoría
|
|
386
|
+
dlq_config = {
|
|
387
|
+
'deadLetterTargetArn': 'arn:aws:sqs:...:cola-nomina-dlq',
|
|
388
|
+
'maxReceiveCount': '3', # 3 intentos antes de enviar a DLQ
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## 9. CloudFront — CDN y Caché
|
|
395
|
+
|
|
396
|
+
```python
|
|
397
|
+
# Política de caché para API (no cachear datos privados)
|
|
398
|
+
cache_policy = {
|
|
399
|
+
"DefaultTTL": 0,
|
|
400
|
+
"MaxTTL": 0,
|
|
401
|
+
"MinTTL": 0,
|
|
402
|
+
# Assets estáticos: TTL largo
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
# Para frontend SPA en S3 + CloudFront
|
|
406
|
+
distribution_config = {
|
|
407
|
+
"Origins": [{
|
|
408
|
+
"DomainName": "mi-bucket.s3.amazonaws.com",
|
|
409
|
+
"S3OriginConfig": {"OriginAccessIdentity": "origin-access-identity/cloudfront/..."},
|
|
410
|
+
}],
|
|
411
|
+
"DefaultCacheBehavior": {
|
|
412
|
+
"ViewerProtocolPolicy": "redirect-to-https", # SIEMPRE
|
|
413
|
+
"CachePolicyId": "...",
|
|
414
|
+
"ResponseHeadersPolicyId": "...", # Security headers
|
|
415
|
+
},
|
|
416
|
+
"CustomErrorResponses": [
|
|
417
|
+
# SPA routing: 404 → index.html
|
|
418
|
+
{"ErrorCode": 404, "ResponseCode": 200, "ResponsePagePath": "/index.html"},
|
|
419
|
+
{"ErrorCode": 403, "ResponseCode": 200, "ResponsePagePath": "/index.html"},
|
|
420
|
+
],
|
|
421
|
+
"HttpVersion": "http2and3",
|
|
422
|
+
"PriceClass": "PriceClass_100", # Solo Norte América + Europa
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## 10. Optimización de Costos
|
|
429
|
+
|
|
430
|
+
### Estrategias principales
|
|
431
|
+
|
|
432
|
+
| Servicio | Optimización | Ahorro estimado |
|
|
433
|
+
|----------|-------------|-----------------|
|
|
434
|
+
| EC2/ECS | Spot instances para workers | 60-90% |
|
|
435
|
+
| EC2 | Reserved instances (1-3 años) | 30-60% |
|
|
436
|
+
| RDS | Stop en entornos de dev/staging | 60-70% |
|
|
437
|
+
| S3 | Lifecycle policies | 40-80% en archivos viejos |
|
|
438
|
+
| Lambda | Ajustar memoria (benchmark) | 20-50% |
|
|
439
|
+
| CloudFront | Comprimir respuestas | Reduce transferencia |
|
|
440
|
+
| Data Transfer | Mantener tráfico en misma AZ/región | Evita cargos |
|
|
441
|
+
|
|
442
|
+
```python
|
|
443
|
+
# AWS Cost Anomaly Detection — alertas automáticas
|
|
444
|
+
import boto3
|
|
445
|
+
|
|
446
|
+
ce = boto3.client('ce', region_name='us-east-1')
|
|
447
|
+
|
|
448
|
+
def crear_monitor_costos(email: str) -> None:
|
|
449
|
+
monitor = ce.create_anomaly_monitor(
|
|
450
|
+
AnomalyMonitor={
|
|
451
|
+
'MonitorName': 'MonitorGeneral',
|
|
452
|
+
'MonitorType': 'DIMENSIONAL',
|
|
453
|
+
'MonitorDimension': 'SERVICE',
|
|
454
|
+
}
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
ce.create_anomaly_subscription(
|
|
458
|
+
AnomalySubscription={
|
|
459
|
+
'MonitorArnList': [monitor['MonitorArn']],
|
|
460
|
+
'Subscribers': [{'Address': email, 'Type': 'EMAIL'}],
|
|
461
|
+
'Threshold': 20.0, # Alertar si costo aumenta $20 USD
|
|
462
|
+
'Frequency': 'DAILY',
|
|
463
|
+
'SubscriptionName': 'AlertasCostoDiario',
|
|
464
|
+
}
|
|
465
|
+
)
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## 11. Checklist de Arquitectura AWS
|
|
471
|
+
|
|
472
|
+
### Seguridad
|
|
473
|
+
- [ ] Sin credenciales hardcodeadas — IAM roles siempre
|
|
474
|
+
- [ ] MFA activado en cuenta root y usuarios IAM admin
|
|
475
|
+
- [ ] CloudTrail habilitado en todas las regiones
|
|
476
|
+
- [ ] Config Rules para compliance
|
|
477
|
+
- [ ] GuardDuty habilitado para detección de amenazas
|
|
478
|
+
|
|
479
|
+
### Confiabilidad
|
|
480
|
+
- [ ] Multi-AZ en RDS, ElastiCache, ALB
|
|
481
|
+
- [ ] Auto Scaling Groups con mínimo 2 instancias
|
|
482
|
+
- [ ] Health checks en ALB y ECS
|
|
483
|
+
- [ ] Backups automatizados con retención mínima 7 días
|
|
484
|
+
- [ ] Runbooks documentados para fallos comunes
|
|
485
|
+
|
|
486
|
+
### Costos
|
|
487
|
+
- [ ] Budget alerts configuradas ($X USD/mes)
|
|
488
|
+
- [ ] Lifecycle policies en S3
|
|
489
|
+
- [ ] Snapshots de RDS/EBS con retención limitada
|
|
490
|
+
- [ ] Recursos de dev/staging apagados fuera de horario laboral
|
|
491
|
+
- [ ] Reserved instances para carga base predecible
|
|
492
|
+
|
|
493
|
+
### Desempeño
|
|
494
|
+
- [ ] CloudFront para assets estáticos
|
|
495
|
+
- [ ] ElastiCache para queries frecuentes
|
|
496
|
+
- [ ] Connection pooling en aplicación
|
|
497
|
+
- [ ] Read replicas para reportes pesados
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compactacion-contexto
|
|
3
|
+
description: Anti-context-rot. Detectar cuándo compactar el contexto, guardar estado antes de compactar, técnicas de resumen progresivo y handoff limpio entre contextos.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Compactación de Contexto
|
|
7
|
+
|
|
8
|
+
## El problema: context-rot
|
|
9
|
+
|
|
10
|
+
Un contexto largo y sin estructura se degrada con el tiempo:
|
|
11
|
+
- Las instrucciones tempranas quedan enterradas y se olvidan.
|
|
12
|
+
- El modelo pierde el hilo de qué se hizo y qué falta.
|
|
13
|
+
- Las respuestas se vuelven repetitivas o contradictorias.
|
|
14
|
+
- El rendimiento cae porque el contexto útil se diluye en tokens de ruido.
|
|
15
|
+
|
|
16
|
+
**Context-rot** es el fenómeno donde un contexto largo produce peores resultados que
|
|
17
|
+
uno compacto y fresco con el estado correcto cargado.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Señales de que es hora de compactar
|
|
22
|
+
|
|
23
|
+
### Señales cuantitativas
|
|
24
|
+
- La ventana de contexto está al 60% o más de su límite.
|
|
25
|
+
- La conversación lleva más de 40 turnos sobre el mismo proyecto.
|
|
26
|
+
- Se han cargado más de 5 archivos grandes sin eliminar contexto anterior.
|
|
27
|
+
|
|
28
|
+
### Señales cualitativas
|
|
29
|
+
- El agente empieza a repetir preguntas ya respondidas.
|
|
30
|
+
- El agente olvida decisiones tomadas hace 10+ turnos.
|
|
31
|
+
- Las respuestas son más genéricas y menos específicas al proyecto.
|
|
32
|
+
- El agente contradice algo que él mismo propuso anteriormente.
|
|
33
|
+
- La latencia de respuesta aumenta notablemente.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Protocolo: guardar estado ANTES de compactar
|
|
38
|
+
|
|
39
|
+
Antes de iniciar cualquier compactación, el agente DEBE persistir el estado en archivos.
|
|
40
|
+
El estado en la memoria del contexto desaparece; el estado en disco persiste.
|
|
41
|
+
|
|
42
|
+
### Archivo STATE.md — estado de ejecución
|
|
43
|
+
|
|
44
|
+
```markdown
|
|
45
|
+
# STATE.md — Estado del proyecto al 2026-03-25T14:32:00
|
|
46
|
+
|
|
47
|
+
## Fase actual
|
|
48
|
+
- Fase: 3 — Implementación de módulo de reportes
|
|
49
|
+
- Sprint: 2 de 3
|
|
50
|
+
- Última tarea completada: Endpoint GET /reportes/{id}
|
|
51
|
+
- Próxima tarea: Endpoint POST /reportes (slice 3.2)
|
|
52
|
+
|
|
53
|
+
## Decisiones arquitectónicas tomadas
|
|
54
|
+
- Se usa PostgreSQL con JSONB para metadatos de reportes (no MongoDB).
|
|
55
|
+
- Autenticación via JWT con refresh tokens, no sesiones.
|
|
56
|
+
- El frontend es Angular standalone, sin NgModules.
|
|
57
|
+
- Paginación por cursor, no por offset.
|
|
58
|
+
|
|
59
|
+
## Archivos modificados en esta sesión
|
|
60
|
+
- backend/app/routers/reportes.py (creado)
|
|
61
|
+
- backend/app/schemas/reporte.py (creado)
|
|
62
|
+
- backend/app/models/reporte.py (modificado: campo metadata JSONB)
|
|
63
|
+
- frontend/src/app/reportes/reportes.component.ts (creado)
|
|
64
|
+
|
|
65
|
+
## Problemas conocidos / deuda técnica
|
|
66
|
+
- El endpoint DELETE /reportes/{id} falta validación de permisos (ticket #47)
|
|
67
|
+
- La migración 003_reportes.py necesita revisión manual antes de producción
|
|
68
|
+
|
|
69
|
+
## Tests en estado rojo
|
|
70
|
+
- test_reporte_exportar_pdf → falta dependencia wkhtmltopdf en CI
|
|
71
|
+
|
|
72
|
+
## Contexto del negocio relevante
|
|
73
|
+
- Los reportes son propiedad del usuario que los crea (no del admin).
|
|
74
|
+
- Los reportes tienen un TTL de 30 días, luego se archivan.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Archivo DECISIONS.md — registro de decisiones
|
|
78
|
+
|
|
79
|
+
```markdown
|
|
80
|
+
# DECISIONS.md
|
|
81
|
+
|
|
82
|
+
## 2026-03-25 — Paginación por cursor
|
|
83
|
+
**Contexto**: El endpoint GET /reportes necesitaba paginación.
|
|
84
|
+
**Opciones evaluadas**: offset/limit, cursor, keyset.
|
|
85
|
+
**Decisión**: Cursor basado en (created_at, id) para estabilidad con datos en tiempo real.
|
|
86
|
+
**Consecuencia**: Los clientes no pueden saltar a página N directamente.
|
|
87
|
+
|
|
88
|
+
## 2026-03-24 — JSONB para metadatos
|
|
89
|
+
**Contexto**: Los reportes tienen atributos variables por tipo.
|
|
90
|
+
**Decisión**: Un campo `metadata JSONB` en lugar de tabla EAV.
|
|
91
|
+
**Consecuencia**: Queries de metadatos requieren índices GIN.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Técnicas de resumen progresivo
|
|
97
|
+
|
|
98
|
+
### Técnica 1: Resumen en capas
|
|
99
|
+
|
|
100
|
+
No resumir todo en un solo párrafo plano. Usar capas de detalle:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
Nivel 0 (1 línea): "Construyendo API REST de reportes con FastAPI + PostgreSQL."
|
|
104
|
+
Nivel 1 (5 líneas): qué fases hay, en cuál estamos, cuál es el siguiente paso.
|
|
105
|
+
Nivel 2 (20 líneas): decisiones clave, archivos importantes, problemas abiertos.
|
|
106
|
+
Nivel 3 (archivo completo): STATE.md detallado.
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Cargar el nivel de detalle apropiado según la tarea a realizar.
|
|
110
|
+
|
|
111
|
+
### Técnica 2: Resumen por dominios
|
|
112
|
+
|
|
113
|
+
Separar el contexto en dominios independientes:
|
|
114
|
+
|
|
115
|
+
```markdown
|
|
116
|
+
## Dominio: Backend API
|
|
117
|
+
- Rutas implementadas: GET/POST/DELETE /reportes
|
|
118
|
+
- Pendiente: PUT /reportes/{id}, webhooks
|
|
119
|
+
|
|
120
|
+
## Dominio: Frontend Angular
|
|
121
|
+
- Componentes: ReportesListComponent, ReporteDetalleComponent
|
|
122
|
+
- Pendiente: ReporteCrearComponent, filtros de búsqueda
|
|
123
|
+
|
|
124
|
+
## Dominio: Base de datos
|
|
125
|
+
- Migraciones aplicadas: 001, 002, 003
|
|
126
|
+
- Pendiente: índice GIN en metadata (pendiente de medir impacto)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Técnica 3: El "snapshot de trabajo"
|
|
130
|
+
|
|
131
|
+
Antes de compactar, crear un mensaje de handoff en lenguaje natural que un nuevo
|
|
132
|
+
contexto pueda leer y continuar sin perder información:
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
Proyecto: Sistema de reportes SIGAF
|
|
136
|
+
Estoy implementando el módulo de reportes. Completé los endpoints de lectura
|
|
137
|
+
(GET /reportes y GET /reportes/{id}) con paginación por cursor y RBAC.
|
|
138
|
+
|
|
139
|
+
El siguiente paso ES implementar POST /reportes. El schema ReporteCreate ya está
|
|
140
|
+
en backend/app/schemas/reporte.py. El modelo ORM está en backend/app/models/reporte.py.
|
|
141
|
+
El servicio parcial está en backend/app/services/reporte_service.py (falta el método crear).
|
|
142
|
+
|
|
143
|
+
Importante: los reportes deben asociarse al usuario del JWT, nunca confiar en el
|
|
144
|
+
body del request para el owner_id.
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Protocolo de handoff entre contextos
|
|
150
|
+
|
|
151
|
+
### El contexto saliente (antes de compactar)
|
|
152
|
+
|
|
153
|
+
1. Escribir STATE.md actualizado con toda la información relevante.
|
|
154
|
+
2. Hacer commit de todos los cambios pendientes.
|
|
155
|
+
3. Anotar el hash del último commit en STATE.md.
|
|
156
|
+
4. Escribir el "snapshot de trabajo" como primer mensaje del nuevo contexto.
|
|
157
|
+
|
|
158
|
+
### El contexto entrante (después de compactar)
|
|
159
|
+
|
|
160
|
+
Protocolo de arranque:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
1. Leer STATE.md para entender el estado actual.
|
|
164
|
+
2. Leer DECISIONS.md para entender las decisiones ya tomadas.
|
|
165
|
+
3. Revisar los últimos 3 commits para entender qué se hizo recientemente.
|
|
166
|
+
4. Hacer git status para ver si hay cambios sin commitear.
|
|
167
|
+
5. Leer ÚNICAMENTE los archivos relevantes para la tarea actual.
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Nunca cargar TODO el codebase en el nuevo contexto. Cargar solo lo necesario para
|
|
171
|
+
la tarea inmediata.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Estrategias de compactación activa
|
|
176
|
+
|
|
177
|
+
### Compactación por completitud de tarea
|
|
178
|
+
|
|
179
|
+
Compactar al terminar cada tarea atómica. Una tarea completada = contexto que ya
|
|
180
|
+
no necesita vivir en memoria activa.
|
|
181
|
+
|
|
182
|
+
### Compactación por fase del proyecto
|
|
183
|
+
|
|
184
|
+
Al pasar de una fase a otra (ej. del diseño a la implementación), compactar toda
|
|
185
|
+
la discusión de diseño y cargar solo las decisiones finales.
|
|
186
|
+
|
|
187
|
+
### Compactación de archivos grandes
|
|
188
|
+
|
|
189
|
+
Si se leyó un archivo de 500 líneas para extraer 3 funciones relevantes, compactar
|
|
190
|
+
el archivo completo y mantener solo los 3 fragmentos extraídos con sus firmas.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Anti-patrones a evitar
|
|
195
|
+
|
|
196
|
+
- **Compactar sin guardar estado**: El estado debe estar en disco ANTES de compactar.
|
|
197
|
+
- **Cargar todo el codebase al nuevo contexto**: Cargar solo lo necesario para la tarea.
|
|
198
|
+
- **Hacer el handoff en lenguaje ambiguo**: El snapshot debe ser preciso y accionable.
|
|
199
|
+
- **No registrar decisiones tomadas**: Las decisiones no escritas se pierden al compactar.
|
|
200
|
+
- **Compactar en medio de una tarea**: Terminar la unidad atómica de trabajo primero.
|
|
201
|
+
- **Depender de la memoria del contexto para información crítica**: Todo lo crítico va a disco.
|