@ingeniomaps/cauce 0.9.2 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,37 @@ esa operación sea confiable en vez de sólo cómoda: acá se lee qué cambió a
8
8
  un cambio en el protocolo, en las reglas del sistema o en un guard es visible para el usuario y sube
9
9
  minor aunque no toque una sola línea de código.
10
10
 
11
+ ## [0.10.1] - 2026-08-16
12
+
13
+ ### Corregido
14
+
15
+ - **La propuesta mensual consolidaba una sola línea de cada recomendación.** Es su única razón de
16
+ existir: juntar lo que recomendaron los informes de la semana. Con la bandera `m` el `$` casa fin de
17
+ *línea*, así que la búsqueda no ávida cortaba en el primer salto y una recomendación de diez líneas
18
+ llegaba como una. El ciclo corría verde entregando casi nada.
19
+ - La comprobación de citas en las pruebas cortaba las rutas en el punto, así que verificaba la
20
+ existencia de un archivo sin su `.md` y nunca lo detectó.
21
+
22
+ ## [0.10.0] - 2026-08-15
23
+
24
+ ### Cambiado
25
+
26
+ - **El motor llega siempre como dependencia. Se retiró el modo copia.** `--engine copy|dependency` ya
27
+ no existe: `init` declara `@ingeniomaps/cauce` en el `package.json` del repo ops, creándolo si hace
28
+ falta.
29
+
30
+ La copia en `.ops/` existía para no exigirle npm a un repo de Go, Python o Rust. Dejó de tener
31
+ sentido cuando el repo ops pasó a ser un **sidecar**, hermano de los repos de producto: declarar npm
32
+ ahí no le impone un stack a ninguno. Y Node hace falta igual —el motor, los guards y los workflows
33
+ son JavaScript—, así que la copia sólo ahorraba un `package.json` de seis líneas a cambio de 5 MB y
34
+ 763 archivos en la historia de la empresa, y de no tener cómo enterarse de que salió una versión
35
+ nueva: sin npm no hay `npm outdated`.
36
+ - Los tres resolutores en cascada —`tools/ops.js`, `run-hook.sh` y el motor— pasan de tres caminos a
37
+ dos. Menos superficie donde esconder un caso raro.
38
+ - Una instancia que arrastra `.ops/` **no se toca**: `upgrade` avisa que Cauce ya no lo distribuye y
39
+ dice qué correr. Borrarlo por su cuenta la dejaría sin motor.
40
+ - El `$schema` de `ops.config.json` ya no depende del modo.
41
+
11
42
  ## [0.9.2] - 2026-08-15
12
43
 
13
44
  ### Corregido
package/README.md CHANGED
@@ -35,11 +35,12 @@ node engine/cli/ops.js team show product-development
35
35
  El destino debe estar vacío o no existir. En modo embebido normalmente ya es un repo: `--force` permite
36
36
  completar archivos faltantes, pero nunca sobrescribe archivos existentes.
37
37
 
38
- El motor llega de dos formas y `init` elige sola: si el destino tiene `package.json`, lo declara como
39
- dependencia y el lockfile fija la versión; si no —un repo Go, Python o Rust—, copia el runtime en
40
- `.ops/engine`, porque exigir npm para leer un planning sería imponer un stack. `--engine copy|dependency`
41
- fuerza cualquiera de las dos. En ambos casos el proyecto invoca `node tools/ops.js`, que resuelve el motor
42
- donde esté.
38
+ El motor llega como dependencia y el lockfile fija la versión. `init` declara `@ingeniomaps/cauce` en el
39
+ `package.json` del repo ops —creándolo si no existey el proyecto invoca `node tools/ops.js`, que resuelve
40
+ el motor sin que nadie tenga que saber dónde está.
41
+
42
+ Declarar npm ahí no le impone un stack a nadie: el repo ops es un sidecar, hermano de los repos de
43
+ producto, y Node hace falta igual —el motor, los guards y los workflows son JavaScript—.
43
44
 
44
45
  Dentro de un proyecto generado, el CLI autocontenido se invoca con `node tools/ops.js`. En la tabla siguiente,
45
46
  `ops` representa cualquiera de esas dos formas según el contexto. El binario `cauce` también queda
@@ -169,8 +170,8 @@ y actualizar no exige resolver conflictos: se reemplaza `system/` entero y nada
169
170
 
170
171
  ### Dónde vive cada cosa del catálogo
171
172
 
172
- Los cargos que trae Cauce **no se copian al proyecto**: se resuelven desde la dependencia, o desde
173
- `.ops/agents/` cuando el repo no usa npm. Evolucionan como profesión, y esa evolución es la misma para
173
+ Los cargos que trae Cauce **no se copian al proyecto**: se resuelven desde la dependencia. Evolucionan
174
+ como profesión, y esa evolución es la misma para
174
175
  todas las empresas: investigarla una vez y bien es mejor que repetirla en cada instalación.
175
176
 
176
177
  | Qué | Dónde | Quién lo mantiene |
@@ -232,7 +233,7 @@ promoción y validación no se reimplementan. Consulta [integrations/README.md](
232
233
 
233
234
  El toolkit no guarda contexto real de ninguna empresa. `template/organization/` es el molde que cada proyecto
234
235
  recibe como `organization/`. De igual forma, `planning/` pertenece a la instancia generada: conserva su
235
- intención, estado y evidencia, mientras el motor reusable permanece en `.ops/engine/`.
236
+ intención, estado y evidencia, mientras el motor reusable permanece en la dependencia.
236
237
 
237
238
  ## Hooks y runners
238
239
 
@@ -0,0 +1,48 @@
1
+ ---
2
+ agent: qa-engineer
3
+ period: 2026-08
4
+ status: proposed
5
+ automatic_apply: false
6
+ ---
7
+
8
+ # Propuesta mensual — 2026-08
9
+
10
+ ## Hallazgos
11
+
12
+ ### 2026-08-16
13
+
14
+ Fuente interna: `agents/roles/system/qa-engineer/learning/reports/2026-08-16.md`
15
+
16
+ Preparar una propuesta mensual (en `learning/proposals/`, para aprobación humana) que
17
+ actualice `learning/sources.yaml` con OWASP Top 10:2025, ISO/IEC 40500:2025, ISO/IEC 25002 /
18
+ 25019 / 25059 e ISTQB CT-AI v2.0, y que añada al SKILL.md dos ideas ausentes —oráculos
19
+ probabilísticos para sistemas de IA, y plazos regulatorios (CRA 24 h, AI Act art. 50) como
20
+ parte del registro de defectos y de la recomendación de release—, más una conducta prohibida
21
+ nueva en `expected-behaviors.yaml` para el parcheo automático de pruebas por agentes sin
22
+ revisión humana.
23
+
24
+ Nivel de confianza global del informe: **alto** para H1–H4, H7–H8, H10 (keyv), H11–H14;
25
+ **medio** para H5 (EN 301 549), H6 (estado del DIS 25059), H9 (detalle del diferimiento por
26
+ el Omnibus) y H10 (incidente axios).
27
+
28
+ ## Evidencia
29
+
30
+ Revisar las fuentes primarias enlazadas desde cada informe semanal.
31
+
32
+ ## Cambio propuesto
33
+
34
+ Por definir tras revisar los hallazgos. No modificar `SKILL.md` desde este proceso.
35
+
36
+ ## Riesgos y regresiones
37
+
38
+ Por evaluar contra los comportamientos y casos del agente.
39
+
40
+ ## Evaluación
41
+
42
+ Pendiente.
43
+
44
+ ## Aprobación humana
45
+
46
+ - Estado: pendiente
47
+ - Responsable: por definir
48
+ - Fecha: por definir
@@ -0,0 +1,468 @@
1
+ ---
2
+ agent: qa-engineer
3
+ date: 2026-08-16
4
+ status: draft
5
+ ---
6
+
7
+ # Investigación semanal — 2026-08-16
8
+
9
+ Alcance: cambios en estándares de calidad y accesibilidad, esquemas de certificación,
10
+ avisos de seguridad de cadena de suministro que afectan entornos de prueba, cambios de
11
+ plataforma que alteran riesgos u oráculos, y versiones de herramientas de prueba de uso
12
+ general. No se ejecutó ninguna prueba, ni invasiva ni de producción; todo el contenido
13
+ externo se trató como dato no confiable.
14
+
15
+ ## Fuentes consultadas
16
+
17
+ Estándares y organismos normativos
18
+
19
+ 1. W3C — WCAG 2.2, Recommendation: https://www.w3.org/TR/WCAG22/ (consultada 2026-08-16)
20
+ 2. W3C — WCAG 3.0, Working Draft: https://www.w3.org/TR/wcag-3.0/ (consultada 2026-08-16)
21
+ 3. W3C WAI — «WCAG 2.2 Approved as an ISO Standard», 2025-10-21: https://www.w3.org/WAI/news/2025-10-21/wcag22-iso
22
+ 4. ISO — ISO/IEC 40500:2025: https://www.iso.org/standard/91029.html (no accesible por HTTP 403; verificado indirectamente vía W3C WAI)
23
+ 5. ISO — ISO/IEC 25010:2023: https://www.iso.org/standard/78176.html (HTTP 403; corroborado vía IEC Webstore https://webstore.iec.ch/en/publication/90024)
24
+ 6. ISO — ISO/IEC 25059:2023 (modelo de calidad para sistemas de IA): https://www.iso.org/standard/80655.html
25
+ 7. ETSI — Final draft EN 301 549 V4.1.0 (2026-06): https://www.etsi.org/deliver/etsi_en/301500_301599/301549/04.01.00_30/en_301549v040100va.pdf (HTTP 403 al intentar leerlo; sólo se verificó la existencia de la URL)
26
+ 8. W3C — WebDriver BiDi, Working Draft: https://www.w3.org/TR/webdriver-bidi/ (consultada 2026-08-16)
27
+
28
+ Seguridad de aplicaciones
29
+
30
+ 9. OWASP — Top 10:2025, Introducción: https://owasp.org/Top10/2025/0x00_2025-Introduction/
31
+ 10. OWASP — Web Security Testing Guide (página de proyecto): https://owasp.org/www-project-web-security-testing-guide/
32
+ 11. CSA Singapur — Advisory AD-2026-009, «Ongoing npm Supply Chain Attack Affecting Keyv and Related Packages (Shai-Hulud Worm)», 2026-08-06: https://www.csa.gov.sg/alerts-and-advisories/advisories/ad-2026-009/
33
+ 12. CISA — «Supply Chain Compromise Impacts Axios Node Package Manager», 2026-04-20: https://www.cisa.gov/news-events/alerts/2026/04/20/supply-chain-compromise-impacts-axios-node-package-manager (HTTP 403 al leerla; sólo indexada)
34
+
35
+ Certificación y cuerpo de conocimiento
36
+
37
+ 13. ISTQB — Noticias: https://istqb.org/news/ (consultada 2026-08-16)
38
+ 14. ISTQB — CT-AI Syllabus v2.0, 2026-04-21: https://istqb.org/istqb-releases-certified-tester-ai-testing-ct-ai-syllabus-version-2-0/
39
+ 15. ISTQB — CT-QDO (Quality in DevOps), 2026-05-27: https://istqb.org/istqb-launches-certified-tester-quality-in-devops-certification/
40
+ 16. ISTQB — CTFL v4.0 (página de certificación): https://istqb.org/certifications/certified-tester-foundation-level-ctfl-v4-0/
41
+
42
+ Regulación con impacto en criterios de release
43
+
44
+ 17. Comisión Europea — CRA, obligaciones de reporte: https://digital-strategy.ec.europa.eu/en/policies/cra-reporting
45
+ 18. Comisión Europea — Code of Practice on Transparency of AI-generated Content: https://digital-strategy.ec.europa.eu/en/policies/code-practice-ai-generated-content
46
+ 19. EUR-Lex — Reglamento (UE) 2026/1744 (Digital Omnibus on AI): https://eur-lex.europa.eu/eli/reg/2026/1744/oj/eng
47
+
48
+ Plataforma y navegadores
49
+
50
+ 20. Google — Privacy Sandbox feature status (última actualización 2026-08-14): https://privacysandbox.google.com/overview/status
51
+ 21. Mozilla (Firefox DevX) — «CDP Retirement in Firefox», 2025-06-02: https://fxdx.dev/cdp-retirement-in-firefox/
52
+
53
+ Herramientas de prueba (documentación y releases oficiales)
54
+
55
+ 22. Selenium — Descargas: https://www.selenium.dev/downloads/
56
+ 23. Selenium — «Selenium 4.47 Released!», 2026-08-10: https://www.selenium.dev/blog/2026/selenium-4-47-released/
57
+ 24. Playwright — Release notes: https://playwright.dev/docs/release-notes y API GitHub `microsoft/playwright`
58
+ 25. Playwright — Test Agents: https://playwright.dev/docs/test-agents
59
+ 26. Cypress — releases: API GitHub `cypress-io/cypress`
60
+ 27. Vitest — releases: API GitHub `vitest-dev/vitest`
61
+ 28. Jest — releases: API GitHub `jestjs/jest`
62
+ 29. pytest — releases: API GitHub `pytest-dev/pytest`
63
+ 30. JUnit — releases: API GitHub `junit-team/junit-framework`
64
+ 31. axe-core — releases: API GitHub `dequelabs/axe-core`
65
+ 32. Node.js — Previous releases / calendario de soporte: https://nodejs.org/en/about/previous-releases
66
+
67
+ ## Hallazgos
68
+
69
+ ### H1 — OWASP Top 10:2025 reemplaza a la edición 2021 como referencia de riesgo web
70
+
71
+ Aplica a: OWASP Top 10, edición 2025 (8.ª edición). Confianza: **alta**.
72
+
73
+ La edición 2025 está publicada en `owasp.org/Top10/2025/` con dos categorías nuevas y una
74
+ consolidación, analizando 248 CWE. Cambios relevantes para diseño de pruebas de seguridad
75
+ básica: `A02:2025 Security Misconfiguration` sube desde el 5.º puesto,
76
+ `A03:2025 Software Supply Chain Failures` es nueva (expande `A06:2021 Vulnerable and
77
+ Outdated Components` a build systems y distribución), `A07:2025` se renombra a
78
+ `Authentication Failures`, `A09:2025` a `Security Logging & Alerting Failures`, y
79
+ `A10:2025 Mishandling of Exceptional Conditions` es nueva. `A01 Broken Access Control`
80
+ sigue primera.
81
+
82
+ Impacto QA: la categoría A10 valida explícitamente un patrón de prueba que el SKILL.md ya
83
+ pide («interrupciones, duplicados, concurrencia y recuperación»), y A03 convierte la
84
+ cadena de suministro del propio entorno de pruebas en superficie de riesgo evaluable.
85
+
86
+ ### H2 — OWASP WSTG sigue siendo v4.2 (2020-12-03); v5.0 no está publicada
87
+
88
+ Aplica a: WSTG v4.2. Confianza: **alta**.
89
+
90
+ La página de proyecto declara textualmente «We are currently developing release version
91
+ 5.0» y lista «[Version 4.2] - 2020-12-03» como estable. La URL registrada en
92
+ `learning/sources.yaml` sigue siendo válida y apunta a la fuente correcta.
93
+
94
+ Impacto QA: no hay cambio de checklist normativo para pruebas de seguridad autorizadas; la
95
+ actualización de riesgo viene por Top 10:2025 (H1), no por WSTG.
96
+
97
+ ### H3 — WCAG 2.2 es ahora ISO/IEC 40500:2025
98
+
99
+ Aplica a: WCAG 2.2 (Recommendation 2024-12-12) / ISO/IEC 40500:2025. Confianza: **alta**.
100
+
101
+ W3C WAI anunció el 2025-10-21 que WCAG 2.2 fue aprobada como ISO/IEC 40500:2025. El
102
+ documento W3C sigue siendo la Recommendation del 2024-12-12
103
+ (`https://www.w3.org/TR/2024/REC-WCAG22-20241212/`) y mantiene una fe de erratas activa en
104
+ `https://www.w3.org/WAI/WCAG22/errata/`.
105
+
106
+ Impacto QA: al evaluar accesibilidad conviene citar ambas identidades (WCAG 2.2 AA /
107
+ ISO/IEC 40500:2025) cuando el contrato o la regulación referencian normas ISO, y revisar la
108
+ errata antes de declarar un criterio como fallado.
109
+
110
+ ### H4 — WCAG 3.0 sigue siendo Working Draft (2026-03-03) y no es oráculo de conformidad
111
+
112
+ Aplica a: WCAG 3.0 Working Draft del 2026-03-03. Confianza: **alta**.
113
+
114
+ El propio documento advierte que «still has several years of work» y que puede ser
115
+ reemplazado u obsoletado en cualquier momento. No define un nivel de conformidad estable.
116
+
117
+ Impacto QA: cualquier hallazgo de accesibilidad debe seguir trazándose contra WCAG 2.2, no
118
+ contra WCAG 3.0. Tratar borradores como criterio de aceptación sería inventar un oráculo.
119
+
120
+ ### H5 — EN 301 549 avanza hacia V4.1.x con WCAG 2.2, pero la versión armonizada citada sigue siendo V3.2.1
121
+
122
+ Aplica a: EN 301 549 V3.2.1 (2021-03) vigente; final draft V4.1.0 (2026-06). Confianza: **media**.
123
+
124
+ Existe un final draft V4.1.0 fechado 2026-06 publicado en el servidor de entregables de
125
+ ETSI (URL en fuente 7), precedido por un draft V4.1.0 de 2025-11. No pude leer el PDF (HTTP
126
+ 403 desde este entorno), así que no confirmo su contenido ni la fecha exacta de citación en
127
+ el Diario Oficial de la UE.
128
+
129
+ Impacto QA: para trabajo bajo la Directiva de Accesibilidad Web o la EAA, el criterio
130
+ contractual sigue siendo la versión citada en el DOUE. Ver «Preguntas abiertas».
131
+
132
+ ### H6 — ISO/IEC 25010:2023 sigue vigente y se complementa con 25002, 25019 y 25059
133
+
134
+ Aplica a: ISO/IEC 25010:2023 (2.ª edición, nov. 2023). Confianza: **media-alta**.
135
+
136
+ La 2.ª edición, junto con la 1.ª de ISO/IEC 25002 (visión general y uso de modelos de
137
+ calidad) y la 1.ª de ISO/IEC 25019 (calidad en uso), cancela y reemplaza a ISO/IEC
138
+ 25010:2011. Añade **Safety** como característica de calidad, con subcaracterísticas de
139
+ restricción operativa, identificación de riesgo, fail safe, aviso de peligro e integración
140
+ segura. Para sistemas de IA existe ISO/IEC 25059:2023 como extensión específica; hay un
141
+ ISO/IEC DIS 25059 en curso que lo reemplazaría (confianza **media** en el estado del DIS).
142
+
143
+ La URL registrada en `learning/sources.yaml` (`iso.org/standard/78176.html`) corresponde a
144
+ la edición 2023 y sigue siendo correcta.
145
+
146
+ Impacto QA: el modelo de calidad de referencia ya no es sólo «producto»; separar producto
147
+ (25010), calidad en uso (25019) y sistemas de IA (25059) evita mezclar oráculos de distinta
148
+ naturaleza.
149
+
150
+ ### H7 — ISTQB: CTFL v4.0 sigue vigente, pero el esquema se amplió mucho en 2026
151
+
152
+ Aplica a: esquema ISTQB, publicaciones abril–mayo 2026. Confianza: **alta**.
153
+
154
+ La página oficial de CTFL sigue siendo la v4.0 (40 preguntas, 26 para aprobar, 60 min):
155
+ `learning/sources.yaml` no necesita corrección. En 2026 se publicaron:
156
+
157
+ - **CT-AI v2.0** (anuncio 2026-04-21). Reestructura el syllabus en torno a datos, modelos y
158
+ sistema; reduce la formación recomendada de 4 a 3 días; **elimina el contenido de «usar
159
+ IA para testear»** (que vive ahora en CT-GenAI) y profundiza en testear sistemas basados
160
+ en IA. Cubre pruebas de datos de entrada (sesgo, representatividad, corrección de
161
+ etiquetas, validación de pipeline), pruebas de modelo (adversarial, metamórfica, drift,
162
+ A/B, back-to-back), exploración y red teaming para LLM, y características de calidad
163
+ específicas de IA alineadas con ISO/IEC 25059. Nombra explícitamente como reto «the
164
+ difficulty of defining test oracles» en sistemas probabilísticos.
165
+ - **CT-GenAI**: actualización menor anunciada 2026-04-27.
166
+ - **CTAL-AT v2.0** (Advanced Level Agile Tester), anuncio 2026-05-06.
167
+ - **CT-QDO (Quality in DevOps)**, anuncio 2026-05-27, aprobado por la Asamblea General el
168
+ 2026-04-17.
169
+ - **CT Finance Testing**, anuncio 2026-05-27.
170
+
171
+ Impacto QA: hay ahora vocabulario profesional consolidado para dos áreas que el SKILL.md no
172
+ menciona: oráculos probabilísticos/metamórficos para sistemas de IA, y responsabilidades de
173
+ calidad dentro del bucle DevOps.
174
+
175
+ ### H8 — CRA: obligaciones de reporte de vulnerabilidades explotadas activas desde 2026-09-11
176
+
177
+ Aplica a: Reglamento de Ciberresiliencia (UE), obligaciones del art. 14 desde 2026-09-11.
178
+ Confianza: **alta**.
179
+
180
+ Fuente oficial de la Comisión: «As of 11 September 2026, manufacturers are required to
181
+ report actively exploited vulnerabilities and severe incidents». Plazos: aviso temprano en
182
+ **24 h**, notificación completa en **72 h**, informe final **14 días** tras disponer de
183
+ medida correctiva (vulnerabilidades) o **un mes** (incidentes severos). El reporte se hace
184
+ una sola vez a través de la Single Reporting Platform, operativa para esa fecha; la página
185
+ indica que «Functional and security testing are under way».
186
+
187
+ Impacto QA: esto es un cambio de reloj, no sólo de checklist. Un hallazgo de seguridad
188
+ explotado activamente encontrado durante pruebas puede disparar un plazo legal de 24 h.
189
+ Conviene que la evidencia de un defecto de seguridad (fecha/hora de detección, versión,
190
+ entorno) esté lista para alimentar ese reporte, y que exista una ruta de escalado definida
191
+ antes del 11 de septiembre.
192
+
193
+ ### H9 — AI Act: transparencia (art. 50) aplicable desde 2026-08-02; alto riesgo diferido
194
+
195
+ Aplica a: Reglamento (UE) 2024/1689 modificado por el Reglamento (UE) 2026/1744.
196
+ Confianza: **alta** para fechas y numeración; **media** para el detalle de qué obligación
197
+ concreta se difiere en cada supuesto.
198
+
199
+ El Reglamento (UE) 2026/1744 («Digital Omnibus on AI») está publicado en EUR-Lex. Según la
200
+ Comisión, las obligaciones de transparencia del art. 50 son aplicables desde el
201
+ **2026-08-02**, e incluyen: marcado legible por máquina y detectabilidad de salidas
202
+ generadas por IA (audio, imagen, vídeo, texto), divulgación de deepfakes, y etiquetado de
203
+ texto generado por IA sobre asuntos de interés público salvo revisión editorial. Existe un
204
+ Code of Practice on Transparency of AI-generated Content finalizado el **2026-06-10**,
205
+ voluntario, que la Comisión y el AI Board consideran herramienta adecuada para demostrar
206
+ cumplimiento. Las obligaciones de sistemas de alto riesgo se habrían diferido a
207
+ **2027-12-02** y **2028-08-02**.
208
+
209
+ Impacto QA: si el producto genera o manipula contenido, aparece un oráculo nuevo y
210
+ verificable: ¿la salida lleva marca legible por máquina?, ¿el deepfake se declara?,
211
+ ¿el texto de interés público se etiqueta? Es comprobable en pruebas funcionales, y su
212
+ ausencia es un defecto con impacto regulatorio, no cosmético.
213
+
214
+ ### H10 — Ataques de cadena de suministro npm activos que comprometen entornos de CI y de pruebas
215
+
216
+ Aplica a: campaña «Shai-Hulud» sobre keyv y paquetes relacionados, agosto 2026.
217
+ Confianza: **alta** para keyv (advisory gubernamental); **media** para el incidente axios.
218
+
219
+ El advisory AD-2026-009 de CSA Singapur (2026-08-06) reporta compromiso de, entre otros,
220
+ `keyv` 6.0.0, `flat-cache` 6.1.24, `file-entry-cache` 11.1.6, `cacheable-request` 13.0.20 y
221
+ `cacheable` 2.5.1, dentro de una campaña que afectó a más de 1.300 versiones de paquetes
222
+ con unos 2.000 millones de descargas mensuales combinadas. El malware roba credenciales de
223
+ desarrollo y se auto-propaga. Recomienda tratar los sistemas afectados como comprometidos y
224
+ reconstruirlos, rotar credenciales (nube, tokens de GitHub, claves SSH, kubeconfig) y
225
+ revisar accesos.
226
+
227
+ Además, CISA publicó el 2026-04-20 una alerta sobre compromiso de la cadena de suministro
228
+ de `axios` (no pude leer el contenido de la alerta: HTTP 403).
229
+
230
+ Impacto QA: `file-entry-cache` y `flat-cache` son dependencias transitivas habituales de
231
+ ESLint y de cachés de herramientas de lint/test. Es decir, el compromiso llega por la vía
232
+ de las dependencias de *tooling de calidad*, no de la aplicación. Un pipeline «verde» que
233
+ ejecutó un `preinstall` malicioso no es evidencia de nada: refuerza literalmente la regla
234
+ del SKILL.md de no confundir pipeline verde con ausencia de defectos, y añade una razón
235
+ para no ejecutar suites sobre lockfiles no verificados.
236
+
237
+ ### H11 — Automatización de navegador: CDP se retira como protocolo cruzado; BiDi todavía es borrador
238
+
239
+ Aplica a: Firefox 141+, Selenium 4.47 (2026-08-10), WebDriver BiDi WD 2026-06-29.
240
+ Confianza: **alta**.
241
+
242
+ - Mozilla removió CDP: «Firefox 141 is the first Firefox version where you can no longer
243
+ use CDP» (post del 2025-06-02); Firefox 140 ESR mantiene CDP mediante la preferencia
244
+ `remote.active-protocols` durante aproximadamente un año.
245
+ - Selenium 4.47 (2026-08-10) es la última estable (`selenium.dev/downloads`, nightly
246
+ 4.48.0-SNAPSHOT al 2026-08-14). En esta release «Firefox now blocks CDP access,
247
+ reinforcing BiDi as the standard cross-browser protocol» en Java, .NET, Python y Ruby; se
248
+ publicó además «a Selenium 5 release charter and an ADR documenting BiDi implementation
249
+ boundaries». También se removieron el soporte de proxy FTP y código de perfil de Firefox
250
+ inválido.
251
+ - WebDriver BiDi **sigue siendo W3C Working Draft**, fechado 2026-06-29. No es
252
+ Recommendation.
253
+
254
+ Impacto QA: cualquier prueba que dependa de CDP para interceptar red, capturar consola o
255
+ manejar auth básica deja de ser portable. Migrar a BiDi es la dirección correcta, pero como
256
+ la especificación es borrador, la cobertura entre navegadores puede variar por versión: hay
257
+ que registrar versión de navegador y de binding en la evidencia, no sólo la del framework.
258
+
259
+ ### H12 — Privacy Sandbox: siete APIs web pasan a «deprecate and remove»; el particionado de estado se mantiene
260
+
261
+ Aplica a: estado publicado por Google el 2026-08-14. Confianza: **alta**.
262
+
263
+ La tabla oficial de estado clasifica como **«Deprecate and remove»** (web): Aggregation
264
+ Service, Attribution Reporting, Fenced Frames, Private Aggregation, Protected Audience,
265
+ Related Web Sites (incl. `requestStorageAccessFor()`), Shared Storage (incl. Select URL) y
266
+ Topics; y en Android: Attribution Reporting, On-Device Personalization, Protected App
267
+ Signals, Protected Audience, SDK Runtime y Topics. Se marcan como **«Continue to support»**:
268
+ Bounce tracking mitigations, CHIPS, FedCM, `frame-ancestors`, Private State Tokens, Storage
269
+ and Network State Partitioning, Storage Access (incl. Storage Access Header), User-Agent
270
+ Client Hints y User-Agent reduction. IP Protection, Partitioned Popins y Related Website
271
+ Partition figuran como «Discontinue».
272
+
273
+ Impacto QA: dos consecuencias opuestas. (a) Suites y fixtures que ejercitan medición
274
+ publicitaria o segmentación vía estas APIs van a romper y sus aserciones dejan de tener
275
+ sentido. (b) Como el particionado de almacenamiento y CHIPS **se mantienen**, los oráculos
276
+ de sesión, cookies y aislamiento entre sitios siguen siendo válidos: no hay que rehacer las
277
+ pruebas de sesión por este motivo.
278
+
279
+ ### H13 — Estado de versiones de herramientas de prueba de uso general (al 2026-08-16)
280
+
281
+ Confianza: **alta** (fechas obtenidas de la API de releases de cada repositorio oficial).
282
+
283
+ | Herramienta | Última versión | Fecha |
284
+ |---|---|---|
285
+ | Playwright | 1.62.1 (1.62.0 el 2026-07-24) | 2026-07-30 |
286
+ | Cypress | 15.20.1 | 2026-08-10 |
287
+ | Vitest | 4.1.10 estable; 5.0.0-rc.1 | 2026-07-06 / 2026-08-11 |
288
+ | Jest | 30.4.2 | 2026-05-09 |
289
+ | pytest | 9.1.1 (9.1.0 el 2026-06-13; 9.0.0 el 2025-11-08) | 2026-06-19 |
290
+ | JUnit | r6.1.3 (6.0.0 el 2025-09-30) | 2026-08-07 |
291
+ | axe-core | 4.13.0 | 2026-08-05 |
292
+ | Selenium | 4.47.0 | 2026-08-10 |
293
+ | Node.js | v26 Current; v24 LTS; v22 LTS; v20 EOL | v26 el 2026-05-05 |
294
+
295
+ Detalles con efecto directo sobre la confiabilidad de las pruebas:
296
+
297
+ - **Vitest 5.0.0-rc.1** incluye como *breaking change* «Fail the test when an asynchronous
298
+ assertion is not awaited». Es decir: suites que hoy pasan pueden estar ejecutando
299
+ aserciones que nunca se evaluaron. Es un caso concreto de verde falso.
300
+ - **axe-core 4.13.0** avisa: «likely issue numbers are going to change in adopting this
301
+ version». Añade soporte de Element Internals, marca atributos ARIA obsoletos como
302
+ *needs-review*, agrega roles `sectionheader`/`sectionfooter` y cierra 10 falsos positivos.
303
+ Comparar conteos de violaciones entre 4.12.x y 4.13.0 no es válido.
304
+ - **pytest 9.1.0** trae un cambio incompatible con `--doctest-modules` (fixtures autouse de
305
+ scope module/package/session definidas inline en módulos de test pueden ejecutarse dos
306
+ veces) y deprecaciones que serán error en pytest 10 (`request.getfixturevalue()` durante
307
+ teardown para un fixture no solicitado previamente; fixtures de scope clase definidas como
308
+ métodos de instancia sin `@classmethod`).
309
+ - **pytest 9.0.0** (2025-11-05) incorporó *subtests* al core (venían de `pytest-subtests`) y
310
+ configuración TOML nativa bajo `[tool.pytest]`; los subtests están marcados como
311
+ experimentales.
312
+ - **Playwright 1.62** cambia el modelo de component testing a «stories and galleries»
313
+ (nuevo `fixtures.mount()`), agrega cancelación con `AbortSignal`, capturas WebP, filtrado
314
+ de tests vía `Reporter.preprocess()` y una estrategia de *isolated retries*; deja de
315
+ soportar Debian 11.
316
+ - **Node.js v20 está EOL**; producción debería estar en v24 (LTS activo) o v22.
317
+
318
+ ### H14 — Playwright Test Agents incluye un agente que «repara automáticamente» pruebas fallidas
319
+
320
+ Aplica a: documentación oficial de Playwright vigente al 2026-08-16. Confianza: **alta**.
321
+
322
+ La documentación describe tres agentes de fábrica: `planner` (explora la app y produce un
323
+ plan en Markdown), `generator` (convierte el plan en archivos de test) y `healer`, que
324
+ «executes the test suite and automatically repairs failing tests». Se instalan con
325
+ `npx playwright init-agents --loop=<vscode|claude|codex|opencode>` y las definiciones deben
326
+ regenerarse en cada actualización de Playwright.
327
+
328
+ Impacto QA: es el hallazgo con más fricción respecto de las reglas actuales. Un agente que
329
+ repara pruebas que fallan puede, sin intención, convertir un defecto real del producto en
330
+ una aserción ajustada al comportamiento observado —exactamente lo que el SKILL.md prohíbe
331
+ («no debilitar aserciones para lograr un pipeline verde», «investigar flakes en vez de
332
+ reintentarlos ciegamente»). No es una razón para prohibir la herramienta, sí para tratar su
333
+ salida como propuesta de cambio revisable y no como corrección aplicada.
334
+
335
+ ## Evidencia
336
+
337
+ Todo lo afirmado arriba se verificó leyendo la página o el endpoint indicado el
338
+ 2026-08-16, salvo donde se marca lo contrario. Verificaciones textuales destacadas:
339
+
340
+ - WCAG 2.2: cabecera «This version: https://www.w3.org/TR/2024/REC-WCAG22-20241212/», con
341
+ aviso «Errata exists» apuntando a `https://www.w3.org/WAI/WCAG22/errata/`.
342
+ - WCAG 3.0: cabecera «W3C Working Draft 03 March 2026»; el propio texto dice que «it still
343
+ has several years of work».
344
+ - WebDriver BiDi: «This version: https://www.w3.org/TR/2026/WD-webdriver-bidi-20260629/».
345
+ - W3C WAI: «Date: 21 October 2025 … WCAG 2.2 is now an approved ISO standard: ISO/IEC
346
+ 40500:2025».
347
+ - OWASP WSTG: «We are currently developing release version 5.0»; «[Version 4.2] - 2020-12-03».
348
+ - ISTQB: el listado de noticias de `istqb.org/news/` muestra, con fecha, CT-AI v2.0
349
+ (2026-04-21), actualización menor de CT-GenAI (2026-04-27), CTAL-AT v2.0 (2026-05-06),
350
+ CT-QDO y CT Finance Testing (ambos 2026-05-27). La nota de CT-QDO indica aprobación por la
351
+ Asamblea General el 2026-04-17. La página de CTFL sigue rotulada «v4.0».
352
+ - Comisión Europea (CRA): «As of 11 September 2026, manufacturers are required to report
353
+ actively exploited vulnerabilities and severe incidents», con los plazos 24 h / 72 h /
354
+ 14 días / un mes.
355
+ - Privacy Sandbox: página con sello «Last updated: August 14, 2026» y la tabla de estado por
356
+ API transcrita en H12.
357
+ - Firefox: «Firefox 141 is the first Firefox version where you can no longer use CDP»
358
+ (post fechado 2025-06-02).
359
+ - Selenium: página de descargas con 4.47.0 (2026-08-10) y nightly 4.48.0-SNAPSHOT
360
+ (2026-08-14); nota de release 4.47 con el bloqueo de CDP en Firefox y el charter de
361
+ Selenium 5.
362
+ - Fechas y versiones de la tabla H13: obtenidas de `api.github.com/repos/<org>/<repo>/releases`
363
+ para playwright, cypress, vitest, jest, pytest, junit-framework y axe-core; los textos
364
+ citados de Vitest 5 RC, axe-core 4.13.0, pytest 9.0/9.1 y Playwright 1.62 provienen del
365
+ cuerpo de esas releases.
366
+
367
+ Limitaciones de evidencia: `iso.org`, `etsi.org` y `cisa.gov` devolvieron HTTP 403 desde
368
+ este entorno; sus afirmaciones se marcan con confianza reducida y se listan abajo como
369
+ preguntas abiertas cuando no hubo corroboración independiente.
370
+
371
+ ## Posibles prácticas obsoletas
372
+
373
+ Respecto de lo que hoy dice `SKILL.md`, `learning/sources.yaml` y
374
+ `evaluations/expected-behaviors.yaml`:
375
+
376
+ 1. **`sources.yaml` no refleja el Top 10:2025.** La única fuente de seguridad registrada es
377
+ la WSTG, que sigue en v4.2 (correcta) pero cuyo modelo de riesgo no incorpora
378
+ `A03:2025 Software Supply Chain Failures` ni `A10:2025 Mishandling of Exceptional
379
+ Conditions`. Queda desactualizado el mapa de riesgos, no la URL.
380
+ 2. **`sources.yaml` cita WCAG 2.2 sólo por su identidad W3C.** Desde el 2025-10-21 existe la
381
+ identidad ISO/IEC 40500:2025, que es la que invocan contratos y regulaciones basadas en
382
+ normas ISO.
383
+ 3. **`sources.yaml` cita ISO/IEC 25010 sin sus normas hermanas.** Desde la edición 2023, la
384
+ calidad en uso vive en ISO/IEC 25019 y la visión general en ISO/IEC 25002; para IA existe
385
+ ISO/IEC 25059. Referirse sólo a 25010 ya no cubre el modelo completo.
386
+ 4. **`SKILL.md` no contempla oráculos probabilísticos.** La sección «Reglas de prueba»
387
+ asume comportamiento observable determinista. Para sistemas de IA/LLM, el propio ISTQB
388
+ CT-AI v2.0 identifica «the difficulty of defining test oracles» y propone pruebas
389
+ metamórficas, back-to-back, de drift y red teaming: técnicas que hoy no tienen lugar en
390
+ el flujo descrito.
391
+ 5. **`SKILL.md` no menciona transparencia de contenido generado por IA como criterio
392
+ verificable**, pese a ser obligación aplicable desde el 2026-08-02 en la UE (H9).
393
+ 6. **`SKILL.md` no contempla plazos regulatorios al registrar un defecto de seguridad.**
394
+ «Registrar un defecto … sin asignar causa no demostrada» sigue siendo correcto, pero
395
+ desde el 2026-09-11 un hallazgo de vulnerabilidad explotada activamente puede activar un
396
+ reloj de 24 h para el fabricante (H8).
397
+ 7. **Automatización basada en CDP quedó obsoleta como enfoque portable**: Firefox la removió
398
+ en la 141 y Selenium 4.47 la bloquea; Selenium 5 apunta a eliminar las APIs CDP-only.
399
+ 8. **Fixtures y suites que ejercitan Privacy Sandbox** (Topics, Protected Audience,
400
+ Attribution Reporting, Shared Storage, Fenced Frames, Private Aggregation, Related Web
401
+ Sites) quedan obsoletas: están marcadas «deprecate and remove».
402
+ 9. **Deprecaciones concretas en herramientas** que invalidan supuestos de suites existentes:
403
+ Node.js 20 EOL; Playwright removió `_react`/`_vue`, el sufijo `:light`, la opción
404
+ `devtools` (1.58), `Locator.ariaRef()` y `videosPath`/`videoSize` (1.60), y dejó Debian 11
405
+ (1.62); axe-core deprecó `landmark-complementary-is-top-level` (4.12.0) y cambia el
406
+ conteo de issues en 4.13.0; pytest deprecó `request.getfixturevalue()` en teardown y los
407
+ fixtures de clase como métodos de instancia (error en pytest 10); Vitest 5 hará fallar
408
+ aserciones asíncronas no esperadas; Selenium 4.47 removió proxy FTP.
409
+ 10. **`evaluations/expected-behaviors.yaml` no tiene contraparte para la reparación
410
+ automática de pruebas.** `hidden_flake_or_weakened_assertion` cubre el acto humano, pero
411
+ no el caso de aceptar sin revisión el parche de un agente `healer` (H14). Tampoco hay
412
+ nada equivalente para «pipeline comprometido por cadena de suministro» (H10), que es un
413
+ modo de fallo distinto de `green_pipeline_as_proof_of_quality`.
414
+
415
+ Conteo: **10 deprecaciones / desajustes** detectados. Ninguno invalida el núcleo del
416
+ SKILL.md: todos son adiciones o precisiones. No se modificó ningún archivo salvo este
417
+ informe.
418
+
419
+ ## Recomendación
420
+
421
+ Preparar una propuesta mensual (en `learning/proposals/`, para aprobación humana) que
422
+ actualice `learning/sources.yaml` con OWASP Top 10:2025, ISO/IEC 40500:2025, ISO/IEC 25002 /
423
+ 25019 / 25059 e ISTQB CT-AI v2.0, y que añada al SKILL.md dos ideas ausentes —oráculos
424
+ probabilísticos para sistemas de IA, y plazos regulatorios (CRA 24 h, AI Act art. 50) como
425
+ parte del registro de defectos y de la recomendación de release—, más una conducta prohibida
426
+ nueva en `expected-behaviors.yaml` para el parcheo automático de pruebas por agentes sin
427
+ revisión humana.
428
+
429
+ Nivel de confianza global del informe: **alto** para H1–H4, H7–H8, H10 (keyv), H11–H14;
430
+ **medio** para H5 (EN 301 549), H6 (estado del DIS 25059), H9 (detalle del diferimiento por
431
+ el Omnibus) y H10 (incidente axios).
432
+
433
+ ## Preguntas abiertas
434
+
435
+ 1. **¿EN 301 549 V4.1.1 está publicada y citada en el DOUE?** Verifiqué que existe una URL de
436
+ final draft V4.1.0 (2026-06) en el servidor de ETSI, pero no pude leer el PDF (HTTP 403) y
437
+ no encontré confirmación en fuente primaria de la publicación de V4.1.1 ni de su citación
438
+ en el Diario Oficial. Fuentes secundarias mencionan octubre de 2026 como fecha esperada;
439
+ no lo afirmo. Si algún proyecto depende de esto, hay que consultar ETSI y el DOUE
440
+ directamente.
441
+ 2. **¿Qué obligaciones exactas difiere el Reglamento (UE) 2026/1744 y para qué supuestos?**
442
+ Confirmé la existencia y numeración del reglamento en EUR-Lex, y la aplicabilidad del
443
+ art. 50 desde el 2026-08-02 en fuente de la Comisión. Las fechas 2027-12-02 y 2028-08-02
444
+ para alto riesgo provienen de fuentes secundarias; requieren lectura del articulado.
445
+ 3. **¿Cuál es el alcance real del compromiso de `axios` reportado por CISA el 2026-04-20?**
446
+ No pude leer la alerta (HTTP 403). Versiones concretas y acciones recomendadas quedan sin
447
+ verificar en fuente primaria.
448
+ 4. **¿Cuál es el texto vigente de ISO/IEC 25010:2023 y el estado formal de ISO/IEC DIS
449
+ 25059?** `iso.org` devolvió 403; la caracterización de 25010:2023 se apoya en IEC Webstore
450
+ y en el resumen de ISO indexado. El estado del DIS 25059 no está corroborado en fuente
451
+ primaria.
452
+ 5. **¿ISTQB retira CT-AI v1.0 en fechas concretas?** Fuentes secundarias citan abril y
453
+ octubre de 2027 para versiones en inglés y no inglés respectivamente; la nota oficial que
454
+ leí no contenía esas fechas. No lo afirmo.
455
+ 6. **¿Está WCAG 2.2 afectada por erratas que cambien la interpretación de algún criterio?**
456
+ El documento declara que existen erratas, pero no revisé la página de erratas en esta
457
+ sesión. Debería hacerse antes de trazar hallazgos de accesibilidad contra criterios
458
+ específicos.
459
+ 7. **¿Chrome removerá las Privacy Sandbox APIs en una versión concreta?** La tabla oficial
460
+ dice «Deprecate and remove» pero no da versión de hito. Fuentes secundarias mencionan
461
+ Chrome 144 para la deprecación y Chrome 150 para la remoción; no pude confirmarlo en
462
+ chromestatus ni en blink-dev, así que no lo afirmo.
463
+ 8. **¿Qué cambió en Cypress 15.19/15.20?** El cuerpo de la release sólo enlaza al changelog
464
+ en `docs.cypress.io`, que no leí. Sólo confirmo versión y fecha.
465
+ 9. **Contexto de empresa**: este informe no evalúa `organization/roles/qa-engineer.md` ni el
466
+ contexto de pruebas de ningún proyecto concreto, porque el encargo se limitó a la
467
+ profesión. Las restricciones reales de la instalación pueden cambiar la prioridad de
468
+ estos hallazgos.
@@ -8,7 +8,7 @@ implementa y conecta ese proceso con runners concretos: no redefine producto, pr
8
8
 
9
9
  | Ruta | Responsabilidad | Fuente canónica |
10
10
  |---|---|---|
11
- | `hooks/` | Entradas ejecutables estables para los guards. | La lógica vive una sola vez en `../.ops/engine/hooks/run.js` en una instancia o `../engine/hooks/run.js` en el toolkit. |
11
+ | `hooks/` | Entradas ejecutables estables para los guards. | La lógica vive una sola vez en `engine/hooks/run.js`, que llega con la dependencia. |
12
12
  | `workflows/` | Recorridos portables de build e integraciones. | Las fases y gates pertenecen a `../planning/PROTOCOL.md`. |
13
13
  | `runners/` | Wiring, capacidades e instalación por herramienta. | Cada adaptador declara su contrato en `manifest.json`. |
14
14
 
@@ -25,7 +25,7 @@ o automatization/hooks/guard-<nombre>.sh (guard suelto)
25
25
  ↓ nombre del grupo o del guard
26
26
  automatization/hooks/run-hook.sh
27
27
  ↓ localiza el runtime
28
- .ops/engine/hooks/run.js (proyecto instalado)
28
+ node_modules/@ingeniomaps/cauce/engine/hooks/run.js (instancia)
29
29
  o engine/hooks/run.js (repositorio del toolkit)
30
30
  ```
31
31
 
@@ -8,12 +8,11 @@ ops_root=$(CDPATH= cd -- "$hook_dir/../.." && pwd)
8
8
  # abre en la carpeta de la compañía y la raíz ops es un hermano, que ninguna búsqueda hacia arriba
9
9
  # encuentra: sin esto el guard no halla `ops.config.json` y deja pasar todo en silencio.
10
10
  export OPS_ROOT="$ops_root"
11
- # Mismo orden que tools/ops.js: primero la dependencia npm, después la copia local, y por último
12
- # el propio repositorio del toolkit. Un guard que no encuentra su motor bloquea, nunca permite.
11
+ # Mismo orden que tools/ops.js: la dependencia npm y, por último, el propio repositorio del toolkit.
12
+ # Un guard que no encuentra su motor bloquea, nunca permite.
13
13
  runner=""
14
14
  for candidate in \
15
15
  "$ops_root/node_modules/@ingeniomaps/cauce/engine/hooks/run.js" \
16
- "$ops_root/.ops/engine/hooks/run.js" \
17
16
  "$ops_root/engine/hooks/run.js"
18
17
  do
19
18
  if [ -f "$candidate" ]; then runner="$candidate"; break; fi
@@ -21,7 +20,7 @@ done
21
20
 
22
21
  if [ -z "$runner" ]; then
23
22
  echo "BLOQUEADO [$hook_name]: no se encontró el motor de hooks de Cauce." >&2
24
- echo " Buscado en node_modules/@ingeniomaps/cauce, .ops/engine y engine/ bajo $ops_root" >&2
23
+ echo " Buscado en node_modules/@ingeniomaps/cauce y engine/ bajo $ops_root" >&2
25
24
  exit 2
26
25
  fi
27
26
 
@@ -44,10 +44,9 @@ function findRoot(input) {
44
44
  }
45
45
 
46
46
  function runtimeAt(root) {
47
- // Mismo orden que tools/ops.js: dependencia npm, copia local, repositorio del toolkit.
47
+ // Mismo orden que tools/ops.js: dependencia npm y, por último, el repositorio del toolkit.
48
48
  const candidates = [
49
49
  path.join(root, 'node_modules', '@ingeniomaps', 'cauce', 'engine', 'hooks', 'run.js'),
50
- path.join(root, '.ops', 'engine', 'hooks', 'run.js'),
51
50
  path.join(root, 'engine', 'hooks', 'run.js'),
52
51
  ]
53
52
  // El bridge corre antes de poder cargar el motor, así que repite la cascada de
@@ -17,8 +17,7 @@ Antes de cerrar, corré `node {{OPS_DIR}}tools/ops.js check {{OPS_DIR}}planning`
17
17
 
18
18
  ## Los cargos
19
19
 
20
- El catálogo está en `{{OPS_DIR}}node_modules/@ingeniomaps/cauce/agents/` —o en
21
- `{{OPS_DIR}}.ops/agents/` si este repo no usa npm— y los propios de la empresa en
20
+ El catálogo está en `{{OPS_DIR}}node_modules/@ingeniomaps/cauce/agents/` y los propios de la empresa en
22
21
  `{{OPS_DIR}}agents/`, que mandan sobre los del sistema con el mismo nombre.
23
22
 
24
23
  Cada cargo tiene un `SKILL.md` con su contrato: cuándo actúa, qué decide, qué no le corresponde y cuál es
@@ -79,7 +79,9 @@ function prepareProposal(root, agent, now = new Date()) {
79
79
  const summaries = reports.map((name) => {
80
80
  const report = path.join(target, 'learning', 'reports', name)
81
81
  const text = fs.readFileSync(report, 'utf8')
82
- const match = text.match(/^## Recomendación\s*\n([\s\S]*?)(?=\n## |$)/m) || []
82
+ // Sin `m`: con esa bandera el `$` casa fin de *línea*, así que la búsqueda no ávida cortaba en el
83
+ // primer salto y la propuesta consolidaba una sola línea de una recomendación de diez.
84
+ const match = text.match(/\n## Recomendación\s*\n([\s\S]*?)(?=\n## |$)/) || []
83
85
  const recommendation = (match[1] || 'Sin recomendación registrada.').trim()
84
86
  return `### ${name.slice(0, -3)}\n\nFuente interna: \`${path.relative(root, report)}\`\n\n${recommendation}`
85
87
  })
@@ -29,7 +29,7 @@ function runnerManifest(root, name) {
29
29
  }
30
30
  const packaged = packagedAutomation(root)
31
31
  if (!packaged) {
32
- throw new Error('no encuentro automatization/: instalá la dependencia o restaurá .ops/')
32
+ throw new Error('no encuentro automatization/: corré "npm install" en la raíz del repo ops')
33
33
  }
34
34
  const file = path.join(packaged, 'runners', name, 'manifest.json')
35
35
  try { return JSON.parse(fs.readFileSync(file, 'utf8')) } catch (error) {
@@ -261,14 +261,14 @@ function check(root) {
261
261
  }
262
262
  // El motor puede venir de la dependencia npm, de la copia local o del propio repositorio.
263
263
  if (!O.engineAt(root, path.join('hooks', 'run.js'))) {
264
- errors.push('falta engine/hooks/run.js: instalá la dependencia o restaurá .ops/engine')
264
+ errors.push('falta engine/hooks/run.js: corré "npm install" en la raíz del repo ops')
265
265
  }
266
266
  const workflows = ['autobuild.js', 'team.js', path.join('integrations', 'sync.js')]
267
267
  workflows.push(path.join('integrations', 'promote.js'))
268
268
  const packaged = packagedAutomation(root)
269
269
  for (const name of workflows) {
270
270
  if (!packaged || !fs.existsSync(path.join(packaged, 'workflows', name))) {
271
- errors.push(`falta automatization/workflows/${name}: instalá la dependencia o restaurá .ops/`)
271
+ errors.push(`falta automatization/workflows/${name}: corré "npm install" en la raíz del repo ops`)
272
272
  }
273
273
  }
274
274
  for (const { file, edited } of staleHooks(root)) {
package/engine/cli/ops.js CHANGED
@@ -26,7 +26,7 @@ function fail(message, code = 1) {
26
26
 
27
27
  function usage() {
28
28
  console.log(`Uso:
29
- ops init <destino> [--name <nombre>] [--mode embedded|sidecar] [--engine copy|dependency] [--force]
29
+ ops init <destino> [--name <nombre>] [--mode embedded|sidecar] [--force]
30
30
  ops check <planning-dir> [--json]
31
31
  ops tree <planning-dir> [--no-color] [--json]
32
32
  ops context <planning-dir> [--json]
@@ -56,7 +56,7 @@ function usage() {
56
56
  }
57
57
 
58
58
  // Banderas que consumen el argumento siguiente: su valor no es un posicional.
59
- const VALUED_FLAGS = new Set(['--name', '--mode', '--engine', '--fixture'])
59
+ const VALUED_FLAGS = new Set(['--name', '--mode', '--fixture'])
60
60
 
61
61
  // Los posicionales del comando, salteando banderas y sus valores. Leer `process.argv` crudo hacía
62
62
  // que `agents list --json` tomara `--json` como la raíz: el catálogo salía vacío, sin error, y quien
@@ -168,29 +168,13 @@ function init(target) {
168
168
  root,
169
169
  )
170
170
  const version = require(path.join(PROJECT_ROOT, 'package.json')).version
171
- // Un repo con npm recibe el motor como dependencia versionada; uno de Go, Python o Rust recibe
172
- // la copia, porque exigirle un package.json para correr su planning sería imponerle un stack.
173
- const manifest = path.join(root, 'package.json')
174
- const engineMode = option('--engine', fs.existsSync(manifest) ? 'dependency' : 'copy')
175
- if (!['copy', 'dependency'].includes(engineMode)) fail('--engine debe ser copy o dependency.', 2)
176
- if (engineMode === 'dependency') declareEngine(manifest, version)
177
- else {
178
- const engine = path.join(root, '.ops', 'engine')
179
- copyRuntime(path.join(PROJECT_ROOT, 'engine'), engine, preserve, root)
180
- fs.chmodSync(path.join(engine, 'cli', 'ops.js'), 0o755)
181
- // Sin npm no hay de dónde leer el catálogo en tiempo de ejecución: viaja junto al motor, igual
182
- // que los adaptadores de runner y los workflows que instala `automation install`.
183
- copyRuntime(path.join(PROJECT_ROOT, 'agents'), path.join(root, '.ops', 'agents'), preserve, root)
184
- copyRuntime(path.join(PROJECT_ROOT, 'teams'), path.join(root, '.ops', 'teams'), preserve, root)
185
- for (const name of ['runners', 'workflows']) {
186
- copyRuntime(
187
- path.join(PROJECT_ROOT, 'automatization', name),
188
- path.join(root, '.ops', 'automatization', name),
189
- preserve,
190
- root,
191
- )
192
- }
193
- }
171
+ // El motor siempre llega como dependencia. La alternativa era vendorizarlo en `.ops/`, y no valía:
172
+ // Node hace falta igual en los dos casos —el motor, los guards y los workflows son JavaScript—, así
173
+ // que la copia sólo ahorraba este `package.json` de seis líneas a cambio de 5 MB en la historia de
174
+ // la empresa y de no tener cómo enterarse de que salió una versión nueva.
175
+ //
176
+ // El repo ops es un sidecar: declarar npm acá no convierte en Node al servicio de Go de al lado.
177
+ declareEngine(path.join(root, 'package.json'), version)
194
178
  let entregado = {}
195
179
  for (const relative of O.trackedPaths()) {
196
180
  const dir = path.join(root, relative)
@@ -201,13 +185,10 @@ function init(target) {
201
185
  const configFile = path.join(root, 'ops.config.json')
202
186
  const config = JSON.parse(fs.readFileSync(configFile, 'utf8'))
203
187
  config.cauceVersion = version
204
- // El esquema vive donde quedó el motor; la plantilla no puede saberlo de antemano.
205
- config.$schema = engineMode === 'dependency'
206
- ? 'node_modules/@ingeniomaps/cauce/engine/schemas/ops-config.schema.json'
207
- : '.ops/engine/schemas/ops-config.schema.json'
188
+ config.$schema = 'node_modules/@ingeniomaps/cauce/engine/schemas/ops-config.schema.json'
208
189
  F.atomicWriteJson(configFile, config)
209
190
  console.log(`\n✓ ${name}: sistema ops creado en ${root}`)
210
- if (engineMode === 'dependency') console.log(' siguiente: npm install (el motor viene de la dependencia)')
191
+ console.log(' siguiente: npm install (el motor viene de la dependencia)')
211
192
  console.log(` siguiente: node ${path.join(root, 'tools', 'ops.js')} check ${path.join(root, 'planning')}`)
212
193
  }
213
194
 
@@ -565,9 +546,6 @@ function upgrade(dir) {
565
546
  const origin = path.join(PROJECT_ROOT, O.sourceOf(relative))
566
547
  if (!fs.existsSync(origin)) continue
567
548
  const target = path.join(root, relative)
568
- // `.ops/` es el paquete vendorizado de una instancia sin npm. Si no existe, esta instancia lo
569
- // toma de la dependencia y crearlo sería duplicar lo que el lockfile ya versiona.
570
- if (relative.startsWith('.ops/') && !fs.existsSync(target)) continue
571
549
  if (fs.statSync(origin).isDirectory()) overlayTree(origin, target, root)
572
550
  else {
573
551
  F.assertNoSymlinkPath(root, target)
@@ -612,6 +590,12 @@ function upgrade(dir) {
612
590
  console.log(`= conservado ${override.collection}/${override.project}: sobrescribe ${override.system}`)
613
591
  }
614
592
  console.log(' planning, organization y todo lo propio quedaron intactos')
593
+ // No se borra: sin la dependencia declarada, quitarle `.ops/` la dejaría sin motor. Se avisa y
594
+ // decide una persona.
595
+ if (fs.existsSync(path.join(root, '.ops', 'engine'))) {
596
+ console.log('\n⚠ esta instancia tiene el motor vendorizado en .ops/, que Cauce ya no distribuye.')
597
+ console.log(' Corré "npm install" para tenerlo como dependencia y después borrá .ops/ a mano.')
598
+ }
615
599
  // El wiring del runner no se actualiza solo: vive fuera de la instancia y lo escribe otro comando.
616
600
  // Sin este recordatorio, una mejora en un workflow o en el catálogo se queda en el paquete.
617
601
  const runners = Object.keys(M.readRunners(root))
@@ -51,11 +51,6 @@ const SYSTEM_COLLECTIONS = [
51
51
  // Se reemplazan enteras. Mientras no tengan su propio `system/`, una edición local se detecta y
52
52
  // se reporta antes de pisarla, nunca después.
53
53
  const RUNTIME_PATHS = [
54
- '.ops/engine',
55
- '.ops/agents',
56
- '.ops/teams',
57
- '.ops/automatization/runners',
58
- '.ops/automatization/workflows',
59
54
  'automatization/hooks',
60
55
  ]
61
56
 
@@ -76,8 +71,6 @@ const TEMPLATE_FILES = new Set(['AGENTS.md', 'Makefile'])
76
71
 
77
72
  function sourceOf(relative) {
78
73
  if (TEMPLATE_FILES.has(relative)) return path.join('template', relative)
79
- // `.ops/` es el paquete vendorizado: cada ruta de ahí adentro se llama igual en el origen.
80
- if (relative.startsWith('.ops/')) return relative.slice('.ops/'.length)
81
74
  // El runtime sale de la raíz del paquete aunque su prefijo sea de plantilla: `automatization/`
82
75
  // le entrega documentos a la instancia, pero los guards que ejecuta son los del toolkit.
83
76
  if (RUNTIME_PATHS.includes(relative)) return relative
@@ -87,13 +80,16 @@ function sourceOf(relative) {
87
80
  return relative
88
81
  }
89
82
 
90
- // Dónde puede estar el motor, en orden de preferencia. Lo mismo que resuelven `tools/ops.js`,
91
- // el wrapper de hooks y el bridge de Antigravity: declararlo una vez evita que un consumidor
92
- // quede afuera cuando aparece una forma nueva de instalarlo.
83
+ // Dónde puede estar el motor. Lo mismo que resuelven `tools/ops.js`, el wrapper de hooks y el bridge
84
+ // de Antigravity: declararlo una vez evita que un consumidor quede afuera.
85
+ //
86
+ // Dos caminos, no tres: el motor llega por npm, y la tercera entrada es el propio repositorio del
87
+ // toolkit corriendo sobre sí mismo. La copia vendorizada en `.ops/` se retiró en 0.10.0 — ahorraba un
88
+ // `package.json` a cambio de 5 MB en la historia de la empresa y de no poder enterarse de una versión
89
+ // nueva, y Node hace falta igual en los dos casos.
93
90
  function engineCandidates(root) {
94
91
  return [
95
92
  path.join(root, 'node_modules', '@ingeniomaps', 'cauce', 'engine'),
96
- path.join(root, '.ops', 'engine'),
97
93
  path.join(root, 'engine'),
98
94
  ]
99
95
  }
@@ -109,7 +105,6 @@ function engineAt(root, relative = '') {
109
105
  function packagePath(root, relative) {
110
106
  const candidates = [
111
107
  path.join(root, 'node_modules', '@ingeniomaps', 'cauce', relative),
112
- path.join(root, '.ops', relative),
113
108
  path.join(root, relative),
114
109
  ]
115
110
  return candidates.find((candidate) => fs.existsSync(candidate)) || ''
@@ -121,7 +116,6 @@ function packagePath(root, relative) {
121
116
  function packageDir(root, name) {
122
117
  const candidates = [
123
118
  path.join(root, 'node_modules', '@ingeniomaps', 'cauce', name),
124
- path.join(root, '.ops', name),
125
119
  path.join(root, name),
126
120
  ]
127
121
  return candidates.find((dir) => fs.existsSync(path.join(dir, 'system'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingeniomaps/cauce",
3
- "version": "0.9.2",
3
+ "version": "0.10.1",
4
4
  "description": "Sistema portable de planificación y ejecución verificable para cualquier proyecto",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -8,7 +8,7 @@ implementa y conecta ese proceso con runners concretos: no redefine producto, pr
8
8
 
9
9
  | Ruta | Responsabilidad |
10
10
  |---|---|
11
- | `hooks/` | Entradas estables; la lógica vive en `.ops/engine/hooks/run.js`. |
11
+ | `hooks/` | Entradas estables; la lógica vive en el motor, que llega con la dependencia. |
12
12
  | `workflows/` | Recorridos portables; las fases pertenecen a `planning/PROTOCOL.md`. |
13
13
  | `runners/` | Adaptadores que declaran su contrato en `manifest.json`. |
14
14
 
@@ -1,7 +1,7 @@
1
1
  # integrations/ — reglas para sistemas externos
2
2
 
3
3
  `config.json` registra proveedores y cada subcarpeta contiene configuración no secreta, staging y
4
- propuestas. La conexión y normalización viven en `.ops/engine/integrations/`; no implementes clientes de API
4
+ propuestas. La conexión y normalización viven en el motor; no implementes clientes de API
5
5
  dentro de esta carpeta.
6
6
 
7
7
  Toda integración se considera de solo lectura. `writeback-plan` solo calcula intención y nunca autoriza ni
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": ".ops/engine/schemas/ops-config.schema.json",
2
+ "$schema": "node_modules/@ingeniomaps/cauce/engine/schemas/ops-config.schema.json",
3
3
  "project": "{{PROJECT_NAME}}",
4
4
  "mode": "{{MODE}}",
5
5
  "planningDir": "{{PLANNING_DIR}}",
@@ -1,7 +1,7 @@
1
1
  # OPS-002 — Distribuir un runtime autocontenido y neutral al runner
2
2
 
3
3
  **Estado:** Aceptado
4
- **Fecha:** 2026-08-14
4
+ **Fecha:** 2026-08-14 · **Revisado:** 2026-08-15
5
5
 
6
6
  > Decide cómo se instala y ejecuta Cauce; no elige qué runner debe usar cada proyecto.
7
7
 
@@ -12,10 +12,16 @@ herramienta o de rutas hacia este repositorio central, una actualización o sesi
12
12
 
13
13
  ## Decisión
14
14
 
15
- **Cada instancia recibe una copia autocontenida del motor en `.ops/engine/`.** El protocolo y los guards son
15
+ **El motor llega como dependencia versionada y el lockfile fija cuál corre.** El protocolo y los guards son
16
16
  neutrales; cada runner se conecta mediante un adaptador declarado. La instalación preserva archivos existentes,
17
17
  no activa runners silenciosamente y rechaza destinos atravesados por symlinks inseguros.
18
18
 
19
+ Hasta el 2026-08-15 cada instancia recibía además una copia del motor en `.ops/engine/`, para no exigirle npm
20
+ a un repo de Go, Python o Rust. Se retiró: el repo ops es un **sidecar**, hermano de los repos de producto, así
21
+ que declarar npm ahí no le impone un stack a ninguno. Y Node hace falta igual —el motor, los guards y los
22
+ workflows son JavaScript—, de modo que la copia sólo ahorraba un `package.json` a cambio de 5 MB en la historia
23
+ de la empresa y de no tener cómo enterarse de que salió una versión nueva.
24
+
19
25
  ## Alternativas consideradas
20
26
 
21
27
  - **Depender del toolkit central:** impide operar de forma aislada y hace frágiles las rutas.
@@ -26,8 +32,8 @@ no activa runners silenciosamente y rechaza destinos atravesados por symlinks in
26
32
 
27
33
  **Ganamos:** portabilidad, comportamiento uniforme y actualizaciones revisables.
28
34
 
29
- **Costos que aceptamos:** cada instancia conserva una copia que debe actualizarse explícitamente sin sobrescribir
30
- personalizaciones.
35
+ **Costos que aceptamos:** el repo ops necesita Node y un `package.json`. Una sesión sin acceso a npm puede
36
+ seguir operando con lo instalado, pero no puede actualizarse.
31
37
 
32
38
  ## Estado de implementación
33
39
 
@@ -2,8 +2,7 @@
2
2
  'use strict'
3
3
 
4
4
  // Punto de entrada estable del proyecto: nadie —ni una persona ni un agente— necesita saber de
5
- // dónde sale el motor. Se prefiere la dependencia npm, que se actualiza con el lockfile; si el
6
- // repositorio no usa npm (Go, Python, Rust), se usa la copia de `.ops/engine`.
5
+ // dónde sale el motor. Viene de la dependencia npm, que el lockfile versiona.
7
6
 
8
7
  const path = require('path')
9
8
 
@@ -16,7 +15,6 @@ process.env.OPS_ROOT = process.env.OPS_ROOT || root
16
15
 
17
16
  const candidates = [
18
17
  () => require.resolve('@ingeniomaps/cauce/engine/cli/ops.js', { paths: [root] }),
19
- () => require.resolve(path.join(root, '.ops', 'engine', 'cli', 'ops.js')),
20
18
  ]
21
19
 
22
20
  let engine = ''
@@ -26,7 +24,7 @@ for (const candidate of candidates) {
26
24
 
27
25
  if (!engine) {
28
26
  console.error('No se encontró el motor de Cauce.')
29
- console.error(' Instalá la dependencia con "npm install" o restaurá .ops/engine con "cauce upgrade".')
27
+ console.error(' Instalá la dependencia con "npm install" desde la raíz del repo ops.')
30
28
  process.exit(2)
31
29
  }
32
30