@saulwade/swl-ses 2.6.1 → 2.8.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 (268) hide show
  1. package/CLAUDE.md +14 -2
  2. package/README.md +65 -18
  3. package/agentes/_intent-spec.md +73 -73
  4. package/agentes/_propose-step.md +90 -90
  5. package/bin/swl-ses.js +10 -0
  6. package/comandos/swl/brainstorm.md +1 -0
  7. package/comandos/swl/briefing.md +119 -119
  8. package/comandos/swl/contribuir.md +233 -233
  9. package/comandos/swl/deuda-codigo.md +97 -97
  10. package/comandos/swl/mcp-status.md +1 -0
  11. package/gateway/lib/event-channel.js +191 -191
  12. package/habilidades/agent-deep-links/SKILL.md +148 -148
  13. package/habilidades/backend-async-postgres-testing/SKILL.md +216 -216
  14. package/habilidades/backend-error-design/SKILL.md +221 -221
  15. package/habilidades/backend-production-resilience/SKILL.md +288 -288
  16. package/habilidades/calidad-anti-patrones-universales/SKILL.md +105 -1
  17. package/habilidades/calidad-contract-testing/SKILL.md +165 -165
  18. package/habilidades/calidad-mutation-testing/SKILL.md +25 -1
  19. package/habilidades/checklist-seguridad/recursos/stride-cobertura.md +60 -60
  20. package/habilidades/ci-cd-pipelines/SKILL.md +5 -1
  21. package/habilidades/css-moderno/SKILL.md +7 -1
  22. package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
  23. package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
  24. package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +57 -57
  25. package/habilidades/extractor-de-aprendizajes/SKILL.md +5 -1
  26. package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
  27. package/habilidades/harness-claude-code/SKILL.md +3 -2
  28. package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
  29. package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
  30. package/habilidades/perfil-usuario/SKILL.md +200 -200
  31. package/habilidades/prevencion-sobreingenieria/recursos/EXAMPLES.md +580 -580
  32. package/habilidades/prevencion-sobreingenieria/recursos/soluciones-nativas.md +166 -166
  33. package/habilidades/prevencion-sobreingenieria/recursos/variables-residuales-post-refactor.md +85 -85
  34. package/habilidades/proceso-ddia-streaming/SKILL.md +231 -231
  35. package/habilidades/proceso-discovery-machote/SKILL.md +157 -157
  36. package/habilidades/proceso-dynamic-workflows/SKILL.md +60 -0
  37. package/habilidades/proceso-dynamic-workflows/recursos/template-adversarial-verify.js +65 -65
  38. package/habilidades/proceso-dynamic-workflows/recursos/template-triage.js +65 -65
  39. package/habilidades/proceso-intent-engineering/SKILL.md +269 -269
  40. package/habilidades/proceso-modular-split/SKILL.md +256 -256
  41. package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
  42. package/habilidades/swl-claudemd/recursos/contrato-aprender.md +83 -83
  43. package/habilidades/swl-claudemd/recursos/duplicacion-reglas-globales.md +85 -85
  44. package/habilidades/swl-claudemd/recursos/plantillas-init.md +94 -94
  45. package/habilidades/tdd-workflow/recursos/gherkin-bdd.md +111 -111
  46. package/hooks/calidad-pre-commit.js +159 -10
  47. package/hooks/ciclo-evolucion-subagente.js +26 -26
  48. package/hooks/ciclo-evolucion.js +26 -26
  49. package/hooks/contexto-subagente.js +68 -68
  50. package/hooks/lib/auto-consolidator.js +335 -335
  51. package/hooks/lib/ciclo-evolucion.js +47 -47
  52. package/hooks/lib/deep-links.js +185 -185
  53. package/hooks/lib/error-classifier.js +308 -308
  54. package/hooks/lib/notificacion-formato.js +45 -11
  55. package/hooks/lib/provenance-tracker.js +191 -191
  56. package/hooks/lib/raiz-proyecto.js +35 -4
  57. package/hooks/lib/resource-quota.js +122 -122
  58. package/hooks/lib/retry-jitter.js +165 -165
  59. package/hooks/lib/security-net.js +201 -201
  60. package/hooks/lib/skill-auditor.js +588 -588
  61. package/hooks/lib/sync-status.js +228 -228
  62. package/hooks/lib/taint-tracker.js +107 -107
  63. package/hooks/lib/text-similarity.js +241 -241
  64. package/hooks/lib/toon-compressor.js +245 -245
  65. package/hooks/notificacion-telegram.js +5 -11
  66. package/hooks/session-briefing.js +12 -4
  67. package/instintos/autonomia.yaml +27 -27
  68. package/instintos/prompt-appendices.yaml +57 -57
  69. package/llms.txt +1 -1
  70. package/manifiestos/agent-output-schemas.json +57 -57
  71. package/manifiestos/canonical-hashes.json +662 -0
  72. package/manifiestos/harness-ir.json +47536 -0
  73. package/manifiestos/hooks-config.json +469 -469
  74. package/manifiestos/invariantes-criticos.json +30 -30
  75. package/manifiestos/policy-bundle.json +2065 -0
  76. package/manifiestos/policy-corpus-w2.json +3926 -0
  77. package/manifiestos/runtime-adapters-core3.json +208 -0
  78. package/manifiestos/runtime-conformance.json +139 -0
  79. package/manifiestos/skills-lock.json +43 -43
  80. package/package.json +2 -2
  81. package/plantillas/auditor-veto-template.md +105 -105
  82. package/plantillas/github-workflows/release-please.yml +44 -44
  83. package/plantillas/github-workflows/swl-ci.yml +107 -107
  84. package/plantillas/github-workflows/swl-security.yml +51 -51
  85. package/plugin.json +2 -2
  86. package/reglas/accesibilidad.md +10 -10
  87. package/reglas/auditorias-documentales-estructurales.md +7 -7
  88. package/reglas/cloud-infra.md +8 -8
  89. package/reglas/consultar-vault-primero.md +195 -195
  90. package/reglas/git-workflow.md +1 -0
  91. package/reglas/hooks.md +6 -6
  92. package/reglas/intent-engineering.md +218 -218
  93. package/reglas/markitdown.md +8 -8
  94. package/reglas/monitor-ci.md +12 -0
  95. package/reglas/patrones.md +6 -6
  96. package/reglas/testing.md +7 -7
  97. package/reglas/tests-cleanup.md +224 -224
  98. package/schemas/agent-message.schema.json +73 -73
  99. package/schemas/agent-output-implementacion.schema.json +114 -114
  100. package/schemas/agent-output-planificacion.schema.json +150 -150
  101. package/schemas/agent-output-review.schema.json +98 -98
  102. package/schemas/diary-entry.schema.json +112 -112
  103. package/schemas/gate-state.schema.json +76 -0
  104. package/schemas/harness-ir.schema.json +369 -0
  105. package/schemas/hook-profiles.schema.json +54 -54
  106. package/schemas/hooks-config.schema.json +89 -89
  107. package/schemas/legacy-gates.schema.json +45 -0
  108. package/schemas/modulos.schema.json +38 -38
  109. package/schemas/perfiles.schema.json +36 -36
  110. package/schemas/plugin.schema.json +77 -77
  111. package/schemas/policy-bundle.schema.json +140 -0
  112. package/schemas/policy-enforcement.schema.json +117 -0
  113. package/schemas/policy-operation.schema.json +261 -0
  114. package/schemas/runtime-adapter.schema.json +176 -0
  115. package/schemas/runtime-build-attestation.schema.json +100 -0
  116. package/schemas/runtime-conformance.schema.json +239 -0
  117. package/schemas/runtime-diagnostic.schema.json +395 -0
  118. package/schemas/skill-evals.schema.json +119 -119
  119. package/schemas/skill-frontmatter.schema.json +245 -245
  120. package/schemas/w4-certification-request.schema.json +72 -0
  121. package/schemas/w4-certification-verdict.schema.json +224 -0
  122. package/schemas/w4-corpus.schema.json +172 -0
  123. package/schemas/w4-mutation-report.schema.json +116 -0
  124. package/schemas/w4-replay-result.schema.json +164 -0
  125. package/schemas/w4-scoring-report.schema.json +89 -0
  126. package/scripts/audit-tools/audit-history.js +330 -330
  127. package/scripts/audit-tools/bundle-tracker.js +290 -290
  128. package/scripts/audit-tools/canary-monitor.js +352 -352
  129. package/scripts/audit-tools/code-profiler.js +605 -605
  130. package/scripts/audit-tools/dep-doctor.js +320 -320
  131. package/scripts/audit-tools/env-validator.js +206 -206
  132. package/scripts/audit-tools/lib/fs-walk.js +48 -48
  133. package/scripts/audit-tools/lib/output.js +23 -23
  134. package/scripts/audit-tools/migration-checker.js +392 -392
  135. package/scripts/audit-tools/pentest-scanner.js +1436 -1436
  136. package/scripts/bootstrap-instintos.js +3 -0
  137. package/scripts/cli/aprobar-plan.js +73 -73
  138. package/scripts/cli/briefing.js +23 -23
  139. package/scripts/cli/ciclo-evolucion.js +26 -26
  140. package/scripts/cli/derivar-feature-list.js +25 -25
  141. package/scripts/cli/detectar-host.js +27 -27
  142. package/scripts/cli/diary-entry.js +69 -69
  143. package/scripts/cli/execution-state.js +18 -18
  144. package/scripts/cli/gateway-notify.js +41 -41
  145. package/scripts/cli/liberar-fase.js +42 -42
  146. package/scripts/cli/mark-evolved.js +56 -56
  147. package/scripts/cli/metricas-dora.js +26 -26
  148. package/scripts/cli/near-duplicate.js +55 -55
  149. package/scripts/cli/notificaciones.js +123 -123
  150. package/scripts/cli/propose-step.js +29 -29
  151. package/scripts/cli/schedule-parse.js +19 -19
  152. package/scripts/cli/sugerir-modelo.js +20 -20
  153. package/scripts/cli/verificar-plan.js +36 -36
  154. package/scripts/cli/verificar-trazabilidad.js +35 -35
  155. package/scripts/comandos/install-asistido.js +8 -7
  156. package/scripts/configurar-branch-protection.js +418 -418
  157. package/scripts/detectar-aprendizajes-duplicados.js +151 -151
  158. package/scripts/doctor.js +61 -36
  159. package/scripts/generar-checklists-consolidados.js +273 -273
  160. package/scripts/generar-claims-runtime.js +1342 -0
  161. package/scripts/generar-harness-ir.js +257 -0
  162. package/scripts/generar-inventario.js +52 -54
  163. package/scripts/generar-policy-bundle.js +202 -0
  164. package/scripts/instalador.js +26 -7
  165. package/scripts/lib/approval-receipts.js +190 -0
  166. package/scripts/lib/artefactos-python.js +43 -43
  167. package/scripts/lib/benchmark-metrics.js +160 -160
  168. package/scripts/lib/budget-enforcer.js +252 -252
  169. package/scripts/lib/certificacion-loop-state.js +421 -0
  170. package/scripts/lib/ci-reader.js +193 -193
  171. package/scripts/lib/ciclo-autonomo/yaml-instintos.js +56 -0
  172. package/scripts/lib/clasificar-directorio.js +92 -0
  173. package/scripts/lib/contadores-inventario.js +217 -217
  174. package/scripts/lib/detectar-host-swl.js +175 -175
  175. package/scripts/lib/detectar-runtime.js +29 -20
  176. package/scripts/lib/detectar-stack-detallado.js +307 -307
  177. package/scripts/lib/detector-autoduplicacion-intra-archivo.js +234 -234
  178. package/scripts/lib/detector-reglas-duplicadas.js +220 -220
  179. package/scripts/lib/eval-metrics-store.js +218 -218
  180. package/scripts/lib/eval-quality.js +171 -171
  181. package/scripts/lib/eval-schemas.js +144 -144
  182. package/scripts/lib/eval-self-correct.js +106 -106
  183. package/scripts/lib/eval-validator.js +185 -185
  184. package/scripts/lib/evidence-verifier.js +192 -0
  185. package/scripts/lib/evidencia-release.js +322 -322
  186. package/scripts/lib/frontmatter-canonico.js +509 -0
  187. package/scripts/lib/gate-engine.js +871 -0
  188. package/scripts/lib/gate-hooks-requires.js +249 -249
  189. package/scripts/lib/gate-licencias.js +212 -212
  190. package/scripts/lib/git-config-preflight.js +48 -0
  191. package/scripts/lib/git-metricas.js +257 -257
  192. package/scripts/lib/harness-ir.js +778 -0
  193. package/scripts/lib/harness-source-snapshot.js +309 -0
  194. package/scripts/lib/integrity-ledger.js +1147 -0
  195. package/scripts/lib/jaccard-similarity.js +98 -98
  196. package/scripts/lib/legacy-gate-migration.js +324 -0
  197. package/scripts/lib/limpiar-basura-global.js +45 -2
  198. package/scripts/lib/longmemeval-runner.js +125 -125
  199. package/scripts/lib/metricas-dora.js +204 -204
  200. package/scripts/lib/notificaciones-telegram.js +1 -0
  201. package/scripts/lib/npm-version.js +1 -0
  202. package/scripts/lib/paquetes-conocidos.js +50 -50
  203. package/scripts/lib/plan-lock.js +61 -13
  204. package/scripts/lib/policy-broker.js +338 -0
  205. package/scripts/lib/policy-bundle.js +342 -0
  206. package/scripts/lib/policy-context-provider.js +310 -0
  207. package/scripts/lib/policy-contract.js +479 -0
  208. package/scripts/lib/policy-verifier-utils.js +65 -0
  209. package/scripts/lib/pr-analyzer.js +399 -399
  210. package/scripts/lib/principal-verifier.js +178 -0
  211. package/scripts/lib/prompt-builder.js +264 -264
  212. package/scripts/lib/resolver-plan-fase.js +37 -37
  213. package/scripts/lib/rrf-fusion.js +175 -175
  214. package/scripts/lib/runtime-adapter-contract.js +267 -0
  215. package/scripts/lib/runtime-artifact-verifier.js +426 -0
  216. package/scripts/lib/runtime-build-attestation.js +127 -0
  217. package/scripts/lib/runtime-bundle-installer.js +586 -0
  218. package/scripts/lib/runtime-compiler.js +327 -0
  219. package/scripts/lib/runtime-conformance.js +202 -0
  220. package/scripts/lib/runtime-doctor-core3.js +567 -0
  221. package/scripts/lib/runtime-doctor-input.js +59 -0
  222. package/scripts/lib/runtime-operation-adapter.js +267 -0
  223. package/scripts/lib/schema-version.js +164 -164
  224. package/scripts/lib/semantic-search.js +252 -252
  225. package/scripts/lib/signed-envelope.js +545 -0
  226. package/scripts/lib/single-use-store.js +359 -0
  227. package/scripts/lib/skills-externas.js +31 -0
  228. package/scripts/lib/transformadores/codex.js +15 -8
  229. package/scripts/lib/transformadores/gemini.js +79 -5
  230. package/scripts/lib/w4-attestation-adapter.js +158 -0
  231. package/scripts/lib/w4-canario.js +337 -0
  232. package/scripts/lib/w4-claims.js +182 -0
  233. package/scripts/lib/w4-corpus-generador.js +542 -0
  234. package/scripts/lib/w4-gate-c5.js +115 -0
  235. package/scripts/lib/w4-harness-bajo-prueba.js +155 -0
  236. package/scripts/lib/w4-matriz-combos.js +55 -0
  237. package/scripts/lib/w4-motor-mutacion.js +1348 -0
  238. package/scripts/lib/w4-motor-replay.js +735 -0
  239. package/scripts/lib/w4-pin-origen.js +54 -0
  240. package/scripts/lib/w4-publicar-request.js +132 -0
  241. package/scripts/lib/w4-revocacion.js +62 -0
  242. package/scripts/lib/w4-runtimes-core3.js +38 -0
  243. package/scripts/lib/w4-scorer-certificacion.js +692 -0
  244. package/scripts/lib/w4-superficie-candidato.js +49 -0
  245. package/scripts/lib/w4-veredicto.js +452 -0
  246. package/scripts/lib/w4-verificar-veredicto.js +302 -0
  247. package/scripts/limpiar-artefactos-python.js +131 -131
  248. package/scripts/migrar-csv-a-array.js +168 -168
  249. package/scripts/migrar-fase-dominio.js +200 -200
  250. package/scripts/migrar-gates-legacy.js +108 -0
  251. package/scripts/publicar-certification-request.js +115 -0
  252. package/scripts/runtime-doctor.js +107 -0
  253. package/scripts/tui/componentes/selector-multi.js +189 -189
  254. package/scripts/tui/componentes/selector-unico.js +158 -158
  255. package/scripts/tui/ejecutores.js +375 -375
  256. package/scripts/tui/lib/colores.js +129 -129
  257. package/scripts/tui/lib/render.js +264 -264
  258. package/scripts/tui/lib/teclas.js +113 -113
  259. package/scripts/tui/pantallas/install-wizard.js +12 -7
  260. package/scripts/tui/pantallas/menu-principal.js +52 -52
  261. package/scripts/tui/pantallas/progreso.js +274 -274
  262. package/scripts/tui/pantallas/resumen.js +132 -132
  263. package/scripts/validar-userland-vacio.js +110 -110
  264. package/scripts/verificar-aislamiento-swl-eval.js +87 -0
  265. package/scripts/verificar-empaquetado-downstream.js +375 -0
  266. package/scripts/verificar-loop-constructor.js +215 -0
  267. package/scripts/verificar-trazabilidad.js +13 -6
  268. package/scripts/verificar-veredicto-real.js +84 -0
@@ -1,166 +1,166 @@
1
- # Soluciones nativas de plataforma
2
-
3
- Recurso de `prevencion-sobreingenieria` — peldaño 4 de la escalera de decisión.
4
- La primera pregunta del ingeniero perezoso-eficiente: *¿la plataforma ya hace
5
- esto?* Antes de instalar un paquete o escribir un componente, revisar aquí.
6
- La plataforma viaja gratis con la app, no se rompe en updates, y la escribió
7
- gente cuyo trabajo es exactamente ese problema.
8
-
9
- Adaptado de [ponytail](https://github.com/DietrichGebert/ponytail)
10
- `docs/platform-native.md` (MIT, DietrichGebert).
11
-
12
- ---
13
-
14
- ## Elementos HTML
15
-
16
- | Crees que necesitas | La plataforma ya tiene |
17
- |---|---|
18
- | Lib de date picker | `<input type="date">` |
19
- | Lib de time picker | `<input type="time">` |
20
- | Lib de color picker | `<input type="color">` |
21
- | Lib de range slider | `<input type="range">` |
22
- | Componente de progress bar | `<progress value="70" max="100">` |
23
- | Componente meter/gauge | `<meter value="0.7">` |
24
- | Lib de modal/diálogo | `<dialog>` + `dialog.showModal()` |
25
- | Componente acordeón/FAQ | `<details><summary>Título</summary>…</details>` |
26
- | Lib de tooltips | atributo `title` + CSS `::before`/`::after` |
27
- | Dropdown con búsqueda | `<input list="id"> <datalist id="id">` |
28
- | Textarea auto-crecible | `field-sizing: content` (CSS) |
29
- | Header sticky | `position: sticky; top: 0` (CSS) |
30
-
31
- ## Capacidades CSS (donde se suele usar JS)
32
-
33
- | Crees que necesitas JS para | CSS ya tiene |
34
- |---|---|
35
- | Font size responsivo | `font-size: clamp(1rem, 2.5vw, 2rem)` |
36
- | Espaciado fluido | `padding: clamp(1rem, 5vw, 3rem)` |
37
- | Dark mode | `@media (prefers-color-scheme: dark)` |
38
- | Reduced motion | `@media (prefers-reduced-motion: reduce)` |
39
- | Layout responsivo sin breakpoints | `grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))` |
40
- | Responsive a nivel componente | `@container` queries |
41
- | Design tokens / theming global | Custom properties (`--color-primario: #7c3aed`) |
42
- | Smooth scroll | `scroll-behavior: smooth` |
43
- | Carrusel con scroll-snap | `scroll-snap-type: x mandatory` + `scroll-snap-align: start` |
44
- | Aspect ratio | `aspect-ratio: 16 / 9` |
45
- | Truncar texto con elipsis | `overflow: hidden; text-overflow: ellipsis; white-space: nowrap` |
46
- | Clamp multilínea | `-webkit-line-clamp: 3` |
47
- | Aislamiento de estilos por capas | `@layer base, components, utilities` |
48
- | Selectores anidados | CSS nesting nativo (sin preprocesador) |
49
- | Selector de padre | `:has(input:checked)` |
50
-
51
- ## JavaScript / APIs del navegador
52
-
53
- | Crees que necesitas | La plataforma ya tiene |
54
- |---|---|
55
- | `query-string` / `qs` | `new URLSearchParams(location.search)` |
56
- | `lodash.clonedeep` | `structuredClone(obj)` |
57
- | `lodash.groupby` | `Object.groupBy(arr, fn)` |
58
- | `numeral` / `accounting` | `new Intl.NumberFormat("es-MX", { style: "currency", currency: "MXN" })` |
59
- | `date-fns` format | `new Intl.DateTimeFormat("es-MX", { dateStyle: "long" }).format(fecha)` |
60
- | Tiempo relativo | `new Intl.RelativeTimeFormat("es", { numeric: "auto" }).format(-3, "day")` |
61
- | Plurales i18n | `new Intl.PluralRules("es-MX").select(cantidad)` |
62
- | `clipboard.js` | `navigator.clipboard.writeText(texto)` |
63
- | `uuid` (v4) | `crypto.randomUUID()` |
64
- | Lib de infinite scroll | `new IntersectionObserver(cb).observe(sentinela)` |
65
- | Lib de resize listener | `new ResizeObserver(cb).observe(elemento)` |
66
- | Watcher de mutaciones DOM | `new MutationObserver(cb).observe(el, opciones)` |
67
- | Check de conectividad | `navigator.onLine` + eventos `online`/`offline` |
68
- | Lib de share sheet | `navigator.share({ title, text, url })` |
69
- | `store.js` / `localForage` (caso simple) | `localStorage.setItem(clave, JSON.stringify(valor))` |
70
- | Abortar fetch por timeout | `AbortSignal.timeout(5000)` pasado a `fetch` |
71
- | Event bus custom | `new EventTarget()` / `dispatchEvent(new CustomEvent("x", { detail }))` |
72
-
73
- **Debounce en 3 líneas** (sin dependencia):
74
-
75
- ```js
76
- // simplificado: debounce de una sola instancia; lib si se necesitan N independientes
77
- let t;
78
- const debounce = (fn, ms) => (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms); };
79
- ```
80
-
81
- ## Swift / SwiftUI
82
-
83
- | Crees que necesitas | La plataforma ya tiene |
84
- |---|---|
85
- | Lib de date/time picker | `DatePicker` |
86
- | Lib de color picker | `ColorPicker` |
87
- | Search bar + filtrado | `.searchable(text:)` |
88
- | Lib de pull-to-refresh | `.refreshable { }` |
89
- | Swipe-to-delete / acciones de fila | `.swipeActions { }` |
90
- | Carga async de imágenes + caché | `AsyncImage` |
91
- | Lib de gráficas | Swift Charts (`import Charts`) |
92
- | Render de Markdown | `Text(...)` markdown / `AttributedString(markdown:)` |
93
- | Share sheet | `ShareLink` |
94
- | Spinner de carga | `ProgressView()` |
95
- | Photo picker | `PhotosPicker` |
96
- | JSON (SwiftyJSON) | `Codable` + `JSONDecoder`/`JSONEncoder` |
97
- | HTTP simple (Alamofire) | `URLSession` async/await |
98
- | Crypto (CryptoSwift) | `CryptoKit` |
99
- | Persistencia / ORM | `SwiftData`, o `@AppStorage` para key-values |
100
- | Logging | `Logger` (`os.log`) |
101
-
102
- ## Stdlib de Node.js
103
-
104
- | Crees que necesitas | Node ya tiene |
105
- |---|---|
106
- | `mkdirp` / `make-dir` | `fs.mkdirSync(ruta, { recursive: true })` |
107
- | `rimraf` | `fs.rmSync(ruta, { recursive: true, force: true })` |
108
- | `uuid` (v4) | `crypto.randomUUID()` |
109
- | `object-assign` | `Object.assign()` / spread |
110
- | `array-uniq` | `[...new Set(arr)]` |
111
- | `array-flatten` / `flat` | `arr.flat(profundidad)` |
112
- | `path-exists` | `fs.existsSync(ruta)` |
113
- | `load-json-file` | `JSON.parse(fs.readFileSync(ruta, "utf8"))` |
114
- | `write-json-file` | `fs.writeFileSync(ruta, JSON.stringify(obj, null, 2))` |
115
- | `pkg-dir` | `path.resolve(__dirname, "..")` / `import.meta.dirname` |
116
-
117
- ## Stdlib de Python
118
-
119
- | Crees que necesitas | Python ya tiene |
120
- |---|---|
121
- | `python-dateutil` (parsing básico) | `datetime.fromisoformat()` (3.7+) |
122
- | `pytz` | `zoneinfo.ZoneInfo("America/Mexico_City")` (3.9+) |
123
- | `attrs` (data classes simples) | `@dataclass` |
124
- | `pathlib2` | `pathlib.Path` (3.4+) |
125
- | `simplejson` (uso básico) | `json` (stdlib) |
126
- | `requests` (GET simple) | `urllib.request.urlopen(url)`; `requests` para algo real |
127
- | `click` (comando único) | `argparse` (stdlib) |
128
- | `mergedeep` | `dict \| otro_dict` (3.9+) |
129
- | `more-itertools` (básico) | `itertools`: `chain`, `islice`, `groupby`, `product` |
130
- | `toolz` (básico) | `functools`: `lru_cache`, `partial`, `reduce` |
131
-
132
- ## Base de datos
133
-
134
- | Crees que necesitas código de app para | La BD ya tiene |
135
- |---|---|
136
- | Paginación | `LIMIT 20 OFFSET 40` |
137
- | Totales acumulados | `SUM(...) OVER (ORDER BY fecha)` (window function) |
138
- | Rank por grupo | `RANK() OVER (PARTITION BY categoria ORDER BY score DESC)` |
139
- | Deduplicación | `SELECT DISTINCT` / `ON CONFLICT DO NOTHING` |
140
- | Recorrido de árboles | CTE recursivo (`WITH RECURSIVE`) |
141
- | Full-text search (básico) | `tsvector` / `MATCH AGAINST` / `FTS5` |
142
- | Almacenar + consultar JSON | `jsonb` (Postgres) / `JSON_EXTRACT` (SQLite/MySQL) |
143
- | Generación de UUID | `gen_random_uuid()` (Postgres) / `UUID()` (MySQL) |
144
- | Timestamps de insert/update | `DEFAULT now()` + trigger / `ON UPDATE CURRENT_TIMESTAMP` |
145
- | Unicidad | constraint `UNIQUE`, no checks en la app |
146
- | Integridad referencial | `FOREIGN KEY`, no checks en la app |
147
- | Rangos de valores | `CHECK (precio > 0)`, no validación en la app |
148
-
149
- ---
150
-
151
- ## El patrón
152
-
153
- En todas las capas es el mismo ciclo:
154
-
155
- ```
156
- El equipo de la plataforma pasa años resolviendo el problema.
157
- Alguien lo envuelve en un paquete.
158
- Instalas el wrapper.
159
- El wrapper queda sin mantenimiento.
160
- Terminas debugueando el wrapper.
161
- ```
162
-
163
- Sáltate el wrapper. Cuando la solución nativa es genuinamente insuficiente
164
- (soporte de navegadores viejos, edge cases que no cubre, ergonomía que importa
165
- a escala), la librería se gana su lugar — instálala entonces, no antes
166
- (y verifica su vigencia con Context7, regla `usar-context7.md`).
1
+ # Soluciones nativas de plataforma
2
+
3
+ Recurso de `prevencion-sobreingenieria` — peldaño 4 de la escalera de decisión.
4
+ La primera pregunta del ingeniero perezoso-eficiente: *¿la plataforma ya hace
5
+ esto?* Antes de instalar un paquete o escribir un componente, revisar aquí.
6
+ La plataforma viaja gratis con la app, no se rompe en updates, y la escribió
7
+ gente cuyo trabajo es exactamente ese problema.
8
+
9
+ Adaptado de [ponytail](https://github.com/DietrichGebert/ponytail)
10
+ `docs/platform-native.md` (MIT, DietrichGebert).
11
+
12
+ ---
13
+
14
+ ## Elementos HTML
15
+
16
+ | Crees que necesitas | La plataforma ya tiene |
17
+ |---|---|
18
+ | Lib de date picker | `<input type="date">` |
19
+ | Lib de time picker | `<input type="time">` |
20
+ | Lib de color picker | `<input type="color">` |
21
+ | Lib de range slider | `<input type="range">` |
22
+ | Componente de progress bar | `<progress value="70" max="100">` |
23
+ | Componente meter/gauge | `<meter value="0.7">` |
24
+ | Lib de modal/diálogo | `<dialog>` + `dialog.showModal()` |
25
+ | Componente acordeón/FAQ | `<details><summary>Título</summary>…</details>` |
26
+ | Lib de tooltips | atributo `title` + CSS `::before`/`::after` |
27
+ | Dropdown con búsqueda | `<input list="id"> <datalist id="id">` |
28
+ | Textarea auto-crecible | `field-sizing: content` (CSS) |
29
+ | Header sticky | `position: sticky; top: 0` (CSS) |
30
+
31
+ ## Capacidades CSS (donde se suele usar JS)
32
+
33
+ | Crees que necesitas JS para | CSS ya tiene |
34
+ |---|---|
35
+ | Font size responsivo | `font-size: clamp(1rem, 2.5vw, 2rem)` |
36
+ | Espaciado fluido | `padding: clamp(1rem, 5vw, 3rem)` |
37
+ | Dark mode | `@media (prefers-color-scheme: dark)` |
38
+ | Reduced motion | `@media (prefers-reduced-motion: reduce)` |
39
+ | Layout responsivo sin breakpoints | `grid-template-columns: repeat(auto-fill, minmax(250px, 1fr))` |
40
+ | Responsive a nivel componente | `@container` queries |
41
+ | Design tokens / theming global | Custom properties (`--color-primario: #7c3aed`) |
42
+ | Smooth scroll | `scroll-behavior: smooth` |
43
+ | Carrusel con scroll-snap | `scroll-snap-type: x mandatory` + `scroll-snap-align: start` |
44
+ | Aspect ratio | `aspect-ratio: 16 / 9` |
45
+ | Truncar texto con elipsis | `overflow: hidden; text-overflow: ellipsis; white-space: nowrap` |
46
+ | Clamp multilínea | `-webkit-line-clamp: 3` |
47
+ | Aislamiento de estilos por capas | `@layer base, components, utilities` |
48
+ | Selectores anidados | CSS nesting nativo (sin preprocesador) |
49
+ | Selector de padre | `:has(input:checked)` |
50
+
51
+ ## JavaScript / APIs del navegador
52
+
53
+ | Crees que necesitas | La plataforma ya tiene |
54
+ |---|---|
55
+ | `query-string` / `qs` | `new URLSearchParams(location.search)` |
56
+ | `lodash.clonedeep` | `structuredClone(obj)` |
57
+ | `lodash.groupby` | `Object.groupBy(arr, fn)` |
58
+ | `numeral` / `accounting` | `new Intl.NumberFormat("es-MX", { style: "currency", currency: "MXN" })` |
59
+ | `date-fns` format | `new Intl.DateTimeFormat("es-MX", { dateStyle: "long" }).format(fecha)` |
60
+ | Tiempo relativo | `new Intl.RelativeTimeFormat("es", { numeric: "auto" }).format(-3, "day")` |
61
+ | Plurales i18n | `new Intl.PluralRules("es-MX").select(cantidad)` |
62
+ | `clipboard.js` | `navigator.clipboard.writeText(texto)` |
63
+ | `uuid` (v4) | `crypto.randomUUID()` |
64
+ | Lib de infinite scroll | `new IntersectionObserver(cb).observe(sentinela)` |
65
+ | Lib de resize listener | `new ResizeObserver(cb).observe(elemento)` |
66
+ | Watcher de mutaciones DOM | `new MutationObserver(cb).observe(el, opciones)` |
67
+ | Check de conectividad | `navigator.onLine` + eventos `online`/`offline` |
68
+ | Lib de share sheet | `navigator.share({ title, text, url })` |
69
+ | `store.js` / `localForage` (caso simple) | `localStorage.setItem(clave, JSON.stringify(valor))` |
70
+ | Abortar fetch por timeout | `AbortSignal.timeout(5000)` pasado a `fetch` |
71
+ | Event bus custom | `new EventTarget()` / `dispatchEvent(new CustomEvent("x", { detail }))` |
72
+
73
+ **Debounce en 3 líneas** (sin dependencia):
74
+
75
+ ```js
76
+ // simplificado: debounce de una sola instancia; lib si se necesitan N independientes
77
+ let t;
78
+ const debounce = (fn, ms) => (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms); };
79
+ ```
80
+
81
+ ## Swift / SwiftUI
82
+
83
+ | Crees que necesitas | La plataforma ya tiene |
84
+ |---|---|
85
+ | Lib de date/time picker | `DatePicker` |
86
+ | Lib de color picker | `ColorPicker` |
87
+ | Search bar + filtrado | `.searchable(text:)` |
88
+ | Lib de pull-to-refresh | `.refreshable { }` |
89
+ | Swipe-to-delete / acciones de fila | `.swipeActions { }` |
90
+ | Carga async de imágenes + caché | `AsyncImage` |
91
+ | Lib de gráficas | Swift Charts (`import Charts`) |
92
+ | Render de Markdown | `Text(...)` markdown / `AttributedString(markdown:)` |
93
+ | Share sheet | `ShareLink` |
94
+ | Spinner de carga | `ProgressView()` |
95
+ | Photo picker | `PhotosPicker` |
96
+ | JSON (SwiftyJSON) | `Codable` + `JSONDecoder`/`JSONEncoder` |
97
+ | HTTP simple (Alamofire) | `URLSession` async/await |
98
+ | Crypto (CryptoSwift) | `CryptoKit` |
99
+ | Persistencia / ORM | `SwiftData`, o `@AppStorage` para key-values |
100
+ | Logging | `Logger` (`os.log`) |
101
+
102
+ ## Stdlib de Node.js
103
+
104
+ | Crees que necesitas | Node ya tiene |
105
+ |---|---|
106
+ | `mkdirp` / `make-dir` | `fs.mkdirSync(ruta, { recursive: true })` |
107
+ | `rimraf` | `fs.rmSync(ruta, { recursive: true, force: true })` |
108
+ | `uuid` (v4) | `crypto.randomUUID()` |
109
+ | `object-assign` | `Object.assign()` / spread |
110
+ | `array-uniq` | `[...new Set(arr)]` |
111
+ | `array-flatten` / `flat` | `arr.flat(profundidad)` |
112
+ | `path-exists` | `fs.existsSync(ruta)` |
113
+ | `load-json-file` | `JSON.parse(fs.readFileSync(ruta, "utf8"))` |
114
+ | `write-json-file` | `fs.writeFileSync(ruta, JSON.stringify(obj, null, 2))` |
115
+ | `pkg-dir` | `path.resolve(__dirname, "..")` / `import.meta.dirname` |
116
+
117
+ ## Stdlib de Python
118
+
119
+ | Crees que necesitas | Python ya tiene |
120
+ |---|---|
121
+ | `python-dateutil` (parsing básico) | `datetime.fromisoformat()` (3.7+) |
122
+ | `pytz` | `zoneinfo.ZoneInfo("America/Mexico_City")` (3.9+) |
123
+ | `attrs` (data classes simples) | `@dataclass` |
124
+ | `pathlib2` | `pathlib.Path` (3.4+) |
125
+ | `simplejson` (uso básico) | `json` (stdlib) |
126
+ | `requests` (GET simple) | `urllib.request.urlopen(url)`; `requests` para algo real |
127
+ | `click` (comando único) | `argparse` (stdlib) |
128
+ | `mergedeep` | `dict \| otro_dict` (3.9+) |
129
+ | `more-itertools` (básico) | `itertools`: `chain`, `islice`, `groupby`, `product` |
130
+ | `toolz` (básico) | `functools`: `lru_cache`, `partial`, `reduce` |
131
+
132
+ ## Base de datos
133
+
134
+ | Crees que necesitas código de app para | La BD ya tiene |
135
+ |---|---|
136
+ | Paginación | `LIMIT 20 OFFSET 40` |
137
+ | Totales acumulados | `SUM(...) OVER (ORDER BY fecha)` (window function) |
138
+ | Rank por grupo | `RANK() OVER (PARTITION BY categoria ORDER BY score DESC)` |
139
+ | Deduplicación | `SELECT DISTINCT` / `ON CONFLICT DO NOTHING` |
140
+ | Recorrido de árboles | CTE recursivo (`WITH RECURSIVE`) |
141
+ | Full-text search (básico) | `tsvector` / `MATCH AGAINST` / `FTS5` |
142
+ | Almacenar + consultar JSON | `jsonb` (Postgres) / `JSON_EXTRACT` (SQLite/MySQL) |
143
+ | Generación de UUID | `gen_random_uuid()` (Postgres) / `UUID()` (MySQL) |
144
+ | Timestamps de insert/update | `DEFAULT now()` + trigger / `ON UPDATE CURRENT_TIMESTAMP` |
145
+ | Unicidad | constraint `UNIQUE`, no checks en la app |
146
+ | Integridad referencial | `FOREIGN KEY`, no checks en la app |
147
+ | Rangos de valores | `CHECK (precio > 0)`, no validación en la app |
148
+
149
+ ---
150
+
151
+ ## El patrón
152
+
153
+ En todas las capas es el mismo ciclo:
154
+
155
+ ```
156
+ El equipo de la plataforma pasa años resolviendo el problema.
157
+ Alguien lo envuelve en un paquete.
158
+ Instalas el wrapper.
159
+ El wrapper queda sin mantenimiento.
160
+ Terminas debugueando el wrapper.
161
+ ```
162
+
163
+ Sáltate el wrapper. Cuando la solución nativa es genuinamente insuficiente
164
+ (soporte de navegadores viejos, edge cases que no cubre, ergonomía que importa
165
+ a escala), la librería se gana su lugar — instálala entonces, no antes
166
+ (y verifica su vigencia con Context7, regla `usar-context7.md`).
@@ -1,85 +1,85 @@
1
- # Variables residuales post-refactor son code smell
2
-
3
- Recurso de `prevencion-sobreingenieria`. Extraído del SKILL.md en v1.3.0 para
4
- respetar el límite de 300 líneas; el contenido es normativo sin cambios.
5
-
6
- ## Regla
7
-
8
- Variables asignadas pero no usadas (F841 en ruff/flake8) **post-refactor** son
9
- casi siempre residuos de una versión anterior del código que el refactor no
10
- limpió. Se parecen a "variables temporales del desarrollador" pero delatan un
11
- refactor incompleto — la lógica que las usaba se movió o eliminó, pero las
12
- asignaciones quedaron.
13
-
14
- ## Por qué son peligrosas
15
-
16
- - **Confunden al próximo lector**: asumirá que la variable se usa más abajo.
17
- - **Inflan el diff cognitivo** del refactor real.
18
- - **Ocultan bugs sutiles**: el valor asignado puede tener side effects (llamada
19
- a función costosa o con efecto en estado) que ya no aporta nada al flujo.
20
- - **Invalidan la métrica de cobertura**: líneas "cubiertas" por tests que en
21
- realidad no afectan el resultado.
22
-
23
- ## Patrón operativo
24
-
25
- Después de **cualquier refactor** que modifique el flujo de una función (extraer
26
- método, inlinear función, cambiar el shape de un return), correr:
27
-
28
- ```bash
29
- ruff check --select=F841 ruta/al/modulo.py
30
- # o para todo el proyecto
31
- ruff check --select=F841 .
32
- ```
33
-
34
- Cada F841 detectado post-refactor es candidato 1 de 2:
35
-
36
- 1. **Variable muerta** (caso común post-refactor): eliminarla.
37
- 2. **Variable viva pero mal nombrada** (caso raro): si el valor se usa como
38
- side effect intencional (ej: evaluar una propiedad para cachear), renombrar
39
- con prefijo `_` y comentar el propósito.
40
-
41
- ## Anti-patrón típico
42
-
43
- ```python
44
- # Antes del refactor: había un if que usaba exito_key
45
- def procesar(data):
46
- exito, exito_key = intentar(data)
47
- if exito_key == "via_rapida":
48
- return procesar_rapido(data)
49
- return procesar_normal(data, exito_key)
50
-
51
-
52
- # Después de refactor que eliminó la rama "via_rapida"
53
- def procesar(data):
54
- exito, exito_key = intentar(data) # ← F841: exito_key asignado, no usado
55
- return procesar_normal(data) # ← también exito residual
56
- ```
57
-
58
- ## Patrón canónico
59
-
60
- ```python
61
- # Post-refactor limpio
62
- def procesar(data):
63
- _ = intentar(data) # si el side effect de intentar() importa
64
- return procesar_normal(data)
65
-
66
- # o mejor: si ni siquiera el side effect importa
67
- def procesar(data):
68
- return procesar_normal(data)
69
- ```
70
-
71
- ## Reglas
72
-
73
- - **Gate pre-commit**: agregar `ruff check --select=F841` al pre-commit hook del proyecto. No bloquea en un repo grande donde F841 preexiste, pero sí bloquea en los archivos modificados por el commit actual.
74
- - **Revisión explícita post-refactor grande**: tras extraer 5+ métodos o mover 5+ bloques, correr `ruff --select=F401,F841` sobre los archivos tocados.
75
- - **NO silenciar con `# noqa: F841` sin justificación** — la excepción legítima (side effect intencional con nombre `_`) es tan rara que vale la pena documentarla; silenciar sin comentario es ocultar deuda.
76
- - **Incluir en checklist de PR**: "F841 limpio en archivos tocados" como item explícito.
77
-
78
- ## Aplicabilidad
79
-
80
- Detectable en:
81
-
82
- - Python: `ruff --select=F841`, `flake8 --select=F841`.
83
- - TypeScript/JavaScript: `eslint --rule 'no-unused-vars: error'`.
84
- - Go: el compilador lo hace obligatorio (`declared but not used`).
85
- - Rust: warning `unused_variables`, promovido a error con `#![deny(unused_variables)]`.
1
+ # Variables residuales post-refactor son code smell
2
+
3
+ Recurso de `prevencion-sobreingenieria`. Extraído del SKILL.md en v1.3.0 para
4
+ respetar el límite de 300 líneas; el contenido es normativo sin cambios.
5
+
6
+ ## Regla
7
+
8
+ Variables asignadas pero no usadas (F841 en ruff/flake8) **post-refactor** son
9
+ casi siempre residuos de una versión anterior del código que el refactor no
10
+ limpió. Se parecen a "variables temporales del desarrollador" pero delatan un
11
+ refactor incompleto — la lógica que las usaba se movió o eliminó, pero las
12
+ asignaciones quedaron.
13
+
14
+ ## Por qué son peligrosas
15
+
16
+ - **Confunden al próximo lector**: asumirá que la variable se usa más abajo.
17
+ - **Inflan el diff cognitivo** del refactor real.
18
+ - **Ocultan bugs sutiles**: el valor asignado puede tener side effects (llamada
19
+ a función costosa o con efecto en estado) que ya no aporta nada al flujo.
20
+ - **Invalidan la métrica de cobertura**: líneas "cubiertas" por tests que en
21
+ realidad no afectan el resultado.
22
+
23
+ ## Patrón operativo
24
+
25
+ Después de **cualquier refactor** que modifique el flujo de una función (extraer
26
+ método, inlinear función, cambiar el shape de un return), correr:
27
+
28
+ ```bash
29
+ ruff check --select=F841 ruta/al/modulo.py
30
+ # o para todo el proyecto
31
+ ruff check --select=F841 .
32
+ ```
33
+
34
+ Cada F841 detectado post-refactor es candidato 1 de 2:
35
+
36
+ 1. **Variable muerta** (caso común post-refactor): eliminarla.
37
+ 2. **Variable viva pero mal nombrada** (caso raro): si el valor se usa como
38
+ side effect intencional (ej: evaluar una propiedad para cachear), renombrar
39
+ con prefijo `_` y comentar el propósito.
40
+
41
+ ## Anti-patrón típico
42
+
43
+ ```python
44
+ # Antes del refactor: había un if que usaba exito_key
45
+ def procesar(data):
46
+ exito, exito_key = intentar(data)
47
+ if exito_key == "via_rapida":
48
+ return procesar_rapido(data)
49
+ return procesar_normal(data, exito_key)
50
+
51
+
52
+ # Después de refactor que eliminó la rama "via_rapida"
53
+ def procesar(data):
54
+ exito, exito_key = intentar(data) # ← F841: exito_key asignado, no usado
55
+ return procesar_normal(data) # ← también exito residual
56
+ ```
57
+
58
+ ## Patrón canónico
59
+
60
+ ```python
61
+ # Post-refactor limpio
62
+ def procesar(data):
63
+ _ = intentar(data) # si el side effect de intentar() importa
64
+ return procesar_normal(data)
65
+
66
+ # o mejor: si ni siquiera el side effect importa
67
+ def procesar(data):
68
+ return procesar_normal(data)
69
+ ```
70
+
71
+ ## Reglas
72
+
73
+ - **Gate pre-commit**: agregar `ruff check --select=F841` al pre-commit hook del proyecto. No bloquea en un repo grande donde F841 preexiste, pero sí bloquea en los archivos modificados por el commit actual.
74
+ - **Revisión explícita post-refactor grande**: tras extraer 5+ métodos o mover 5+ bloques, correr `ruff --select=F401,F841` sobre los archivos tocados.
75
+ - **NO silenciar con `# noqa: F841` sin justificación** — la excepción legítima (side effect intencional con nombre `_`) es tan rara que vale la pena documentarla; silenciar sin comentario es ocultar deuda.
76
+ - **Incluir en checklist de PR**: "F841 limpio en archivos tocados" como item explícito.
77
+
78
+ ## Aplicabilidad
79
+
80
+ Detectable en:
81
+
82
+ - Python: `ruff --select=F841`, `flake8 --select=F841`.
83
+ - TypeScript/JavaScript: `eslint --rule 'no-unused-vars: error'`.
84
+ - Go: el compilador lo hace obligatorio (`declared but not used`).
85
+ - Rust: warning `unused_variables`, promovido a error con `#![deny(unused_variables)]`.