docviz-builder 0.1.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 (233) hide show
  1. package/AGENTS.md +371 -0
  2. package/LICENSE +21 -0
  3. package/README.md +837 -0
  4. package/bin/docviz-mcp.mjs +10 -0
  5. package/bin/docviz.mjs +11 -0
  6. package/dist/build/builder.d.ts +62 -0
  7. package/dist/build/builder.d.ts.map +1 -0
  8. package/dist/build/builder.js +337 -0
  9. package/dist/build/builder.js.map +1 -0
  10. package/dist/build/diff.d.ts +64 -0
  11. package/dist/build/diff.d.ts.map +1 -0
  12. package/dist/build/diff.js +156 -0
  13. package/dist/build/diff.js.map +1 -0
  14. package/dist/build/doctor.d.ts +39 -0
  15. package/dist/build/doctor.d.ts.map +1 -0
  16. package/dist/build/doctor.js +190 -0
  17. package/dist/build/doctor.js.map +1 -0
  18. package/dist/build/init.d.ts +28 -0
  19. package/dist/build/init.d.ts.map +1 -0
  20. package/dist/build/init.js +274 -0
  21. package/dist/build/init.js.map +1 -0
  22. package/dist/build/preview.d.ts +13 -0
  23. package/dist/build/preview.d.ts.map +1 -0
  24. package/dist/build/preview.js +277 -0
  25. package/dist/build/preview.js.map +1 -0
  26. package/dist/build/skill.d.ts +41 -0
  27. package/dist/build/skill.d.ts.map +1 -0
  28. package/dist/build/skill.js +63 -0
  29. package/dist/build/skill.js.map +1 -0
  30. package/dist/build/verify.d.ts +26 -0
  31. package/dist/build/verify.d.ts.map +1 -0
  32. package/dist/build/verify.js +99 -0
  33. package/dist/build/verify.js.map +1 -0
  34. package/dist/cli.d.ts +20 -0
  35. package/dist/cli.d.ts.map +1 -0
  36. package/dist/cli.js +427 -0
  37. package/dist/cli.js.map +1 -0
  38. package/dist/config/load.d.ts +32 -0
  39. package/dist/config/load.d.ts.map +1 -0
  40. package/dist/config/load.js +279 -0
  41. package/dist/config/load.js.map +1 -0
  42. package/dist/config/types.d.ts +89 -0
  43. package/dist/config/types.d.ts.map +1 -0
  44. package/dist/config/types.js +5 -0
  45. package/dist/config/types.js.map +1 -0
  46. package/dist/core/cache.d.ts +32 -0
  47. package/dist/core/cache.d.ts.map +1 -0
  48. package/dist/core/cache.js +69 -0
  49. package/dist/core/cache.js.map +1 -0
  50. package/dist/core/errors.d.ts +115 -0
  51. package/dist/core/errors.d.ts.map +1 -0
  52. package/dist/core/errors.js +164 -0
  53. package/dist/core/errors.js.map +1 -0
  54. package/dist/core/hash.d.ts +57 -0
  55. package/dist/core/hash.d.ts.map +1 -0
  56. package/dist/core/hash.js +0 -0
  57. package/dist/core/hash.js.map +1 -0
  58. package/dist/core/package-version.d.ts +9 -0
  59. package/dist/core/package-version.d.ts.map +1 -0
  60. package/dist/core/package-version.js +44 -0
  61. package/dist/core/package-version.js.map +1 -0
  62. package/dist/core/paths.d.ts +46 -0
  63. package/dist/core/paths.d.ts.map +1 -0
  64. package/dist/core/paths.js +105 -0
  65. package/dist/core/paths.js.map +1 -0
  66. package/dist/core/registry.d.ts +24 -0
  67. package/dist/core/registry.d.ts.map +1 -0
  68. package/dist/core/registry.js +72 -0
  69. package/dist/core/registry.js.map +1 -0
  70. package/dist/core/types.d.ts +78 -0
  71. package/dist/core/types.d.ts.map +1 -0
  72. package/dist/core/types.js +11 -0
  73. package/dist/core/types.js.map +1 -0
  74. package/dist/dsl/architecture.d.ts +15 -0
  75. package/dist/dsl/architecture.d.ts.map +1 -0
  76. package/dist/dsl/architecture.js +242 -0
  77. package/dist/dsl/architecture.js.map +1 -0
  78. package/dist/dsl/catalog.d.ts +62 -0
  79. package/dist/dsl/catalog.d.ts.map +1 -0
  80. package/dist/dsl/catalog.en.d.ts +18 -0
  81. package/dist/dsl/catalog.en.d.ts.map +1 -0
  82. package/dist/dsl/catalog.en.js +299 -0
  83. package/dist/dsl/catalog.en.js.map +1 -0
  84. package/dist/dsl/catalog.js +1082 -0
  85. package/dist/dsl/catalog.js.map +1 -0
  86. package/dist/dsl/chart.d.ts +14 -0
  87. package/dist/dsl/chart.d.ts.map +1 -0
  88. package/dist/dsl/chart.js +435 -0
  89. package/dist/dsl/chart.js.map +1 -0
  90. package/dist/dsl/compile.d.ts +31 -0
  91. package/dist/dsl/compile.d.ts.map +1 -0
  92. package/dist/dsl/compile.js +120 -0
  93. package/dist/dsl/compile.js.map +1 -0
  94. package/dist/dsl/diagram-bpmn.d.ts +13 -0
  95. package/dist/dsl/diagram-bpmn.d.ts.map +1 -0
  96. package/dist/dsl/diagram-bpmn.js +215 -0
  97. package/dist/dsl/diagram-bpmn.js.map +1 -0
  98. package/dist/dsl/diagram-product.d.ts +15 -0
  99. package/dist/dsl/diagram-product.d.ts.map +1 -0
  100. package/dist/dsl/diagram-product.js +291 -0
  101. package/dist/dsl/diagram-product.js.map +1 -0
  102. package/dist/dsl/diagram-technical.d.ts +28 -0
  103. package/dist/dsl/diagram-technical.d.ts.map +1 -0
  104. package/dist/dsl/diagram-technical.js +365 -0
  105. package/dist/dsl/diagram-technical.js.map +1 -0
  106. package/dist/dsl/diagram.d.ts +22 -0
  107. package/dist/dsl/diagram.d.ts.map +1 -0
  108. package/dist/dsl/diagram.js +542 -0
  109. package/dist/dsl/diagram.js.map +1 -0
  110. package/dist/dsl/fallbacks-d2.d.ts +27 -0
  111. package/dist/dsl/fallbacks-d2.d.ts.map +1 -0
  112. package/dist/dsl/fallbacks-d2.js +265 -0
  113. package/dist/dsl/fallbacks-d2.js.map +1 -0
  114. package/dist/dsl/fallbacks.d.ts +25 -0
  115. package/dist/dsl/fallbacks.d.ts.map +1 -0
  116. package/dist/dsl/fallbacks.js +264 -0
  117. package/dist/dsl/fallbacks.js.map +1 -0
  118. package/dist/dsl/fields.d.ts +93 -0
  119. package/dist/dsl/fields.d.ts.map +1 -0
  120. package/dist/dsl/fields.js +233 -0
  121. package/dist/dsl/fields.js.map +1 -0
  122. package/dist/dsl/index.d.ts +50 -0
  123. package/dist/dsl/index.d.ts.map +1 -0
  124. package/dist/dsl/index.js +114 -0
  125. package/dist/dsl/index.js.map +1 -0
  126. package/dist/dsl/util.d.ts +105 -0
  127. package/dist/dsl/util.d.ts.map +1 -0
  128. package/dist/dsl/util.js +261 -0
  129. package/dist/dsl/util.js.map +1 -0
  130. package/dist/index.d.ts +27 -0
  131. package/dist/index.d.ts.map +1 -0
  132. package/dist/index.js +21 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/markdown/scan.d.ts +73 -0
  135. package/dist/markdown/scan.d.ts.map +1 -0
  136. package/dist/markdown/scan.js +150 -0
  137. package/dist/markdown/scan.js.map +1 -0
  138. package/dist/markdown/transform.d.ts +28 -0
  139. package/dist/markdown/transform.d.ts.map +1 -0
  140. package/dist/markdown/transform.js +38 -0
  141. package/dist/markdown/transform.js.map +1 -0
  142. package/dist/mcp/server.d.ts +18 -0
  143. package/dist/mcp/server.d.ts.map +1 -0
  144. package/dist/mcp/server.js +118 -0
  145. package/dist/mcp/server.js.map +1 -0
  146. package/dist/mcp/tools.d.ts +118 -0
  147. package/dist/mcp/tools.d.ts.map +1 -0
  148. package/dist/mcp/tools.js +573 -0
  149. package/dist/mcp/tools.js.map +1 -0
  150. package/dist/renderers/base.d.ts +18 -0
  151. package/dist/renderers/base.d.ts.map +1 -0
  152. package/dist/renderers/base.js +59 -0
  153. package/dist/renderers/base.js.map +1 -0
  154. package/dist/renderers/bpmn.d.ts +68 -0
  155. package/dist/renderers/bpmn.d.ts.map +1 -0
  156. package/dist/renderers/bpmn.js +158 -0
  157. package/dist/renderers/bpmn.js.map +1 -0
  158. package/dist/renderers/browser.d.ts +30 -0
  159. package/dist/renderers/browser.d.ts.map +1 -0
  160. package/dist/renderers/browser.js +143 -0
  161. package/dist/renderers/browser.js.map +1 -0
  162. package/dist/renderers/color-scheme.d.ts +40 -0
  163. package/dist/renderers/color-scheme.d.ts.map +1 -0
  164. package/dist/renderers/color-scheme.js +122 -0
  165. package/dist/renderers/color-scheme.js.map +1 -0
  166. package/dist/renderers/d2.d.ts +37 -0
  167. package/dist/renderers/d2.d.ts.map +1 -0
  168. package/dist/renderers/d2.js +108 -0
  169. package/dist/renderers/d2.js.map +1 -0
  170. package/dist/renderers/graphviz.d.ts +33 -0
  171. package/dist/renderers/graphviz.d.ts.map +1 -0
  172. package/dist/renderers/graphviz.js +88 -0
  173. package/dist/renderers/graphviz.js.map +1 -0
  174. package/dist/renderers/in-page.d.ts +33 -0
  175. package/dist/renderers/in-page.d.ts.map +1 -0
  176. package/dist/renderers/in-page.js +76 -0
  177. package/dist/renderers/in-page.js.map +1 -0
  178. package/dist/renderers/index.d.ts +20 -0
  179. package/dist/renderers/index.d.ts.map +1 -0
  180. package/dist/renderers/index.js +94 -0
  181. package/dist/renderers/index.js.map +1 -0
  182. package/dist/renderers/kroki.d.ts +38 -0
  183. package/dist/renderers/kroki.d.ts.map +1 -0
  184. package/dist/renderers/kroki.js +151 -0
  185. package/dist/renderers/kroki.js.map +1 -0
  186. package/dist/renderers/likec4-svg.d.ts +82 -0
  187. package/dist/renderers/likec4-svg.d.ts.map +1 -0
  188. package/dist/renderers/likec4-svg.js +435 -0
  189. package/dist/renderers/likec4-svg.js.map +1 -0
  190. package/dist/renderers/likec4.d.ts +22 -0
  191. package/dist/renderers/likec4.d.ts.map +1 -0
  192. package/dist/renderers/likec4.js +77 -0
  193. package/dist/renderers/likec4.js.map +1 -0
  194. package/dist/renderers/mermaid.d.ts +64 -0
  195. package/dist/renderers/mermaid.d.ts.map +1 -0
  196. package/dist/renderers/mermaid.js +196 -0
  197. package/dist/renderers/mermaid.js.map +1 -0
  198. package/dist/renderers/plantuml.d.ts +56 -0
  199. package/dist/renderers/plantuml.d.ts.map +1 -0
  200. package/dist/renderers/plantuml.js +195 -0
  201. package/dist/renderers/plantuml.js.map +1 -0
  202. package/dist/renderers/svg-utils.d.ts +46 -0
  203. package/dist/renderers/svg-utils.d.ts.map +1 -0
  204. package/dist/renderers/svg-utils.js +439 -0
  205. package/dist/renderers/svg-utils.js.map +1 -0
  206. package/dist/renderers/svgbob.d.ts +26 -0
  207. package/dist/renderers/svgbob.d.ts.map +1 -0
  208. package/dist/renderers/svgbob.js +70 -0
  209. package/dist/renderers/svgbob.js.map +1 -0
  210. package/dist/renderers/vega-lite.d.ts +18 -0
  211. package/dist/renderers/vega-lite.d.ts.map +1 -0
  212. package/dist/renderers/vega-lite.js +94 -0
  213. package/dist/renderers/vega-lite.js.map +1 -0
  214. package/dist/themes/index.d.ts +17 -0
  215. package/dist/themes/index.d.ts.map +1 -0
  216. package/dist/themes/index.js +419 -0
  217. package/dist/themes/index.js.map +1 -0
  218. package/dist/themes/types.d.ts +99 -0
  219. package/dist/themes/types.d.ts.map +1 -0
  220. package/dist/themes/types.js +9 -0
  221. package/dist/themes/types.js.map +1 -0
  222. package/eval/casos.json +513 -0
  223. package/package.json +114 -0
  224. package/scripts/capture-preview.mjs +101 -0
  225. package/scripts/check-github.mjs +128 -0
  226. package/scripts/eval.d.mts +8 -0
  227. package/scripts/eval.mjs +284 -0
  228. package/scripts/fetch-plantuml.mjs +122 -0
  229. package/scripts/generate-catalog-doc.mjs +106 -0
  230. package/scripts/rasterize.mjs +68 -0
  231. package/scripts/sync-docs.mjs +158 -0
  232. package/skills/docviz/SKILL.md +111 -0
  233. package/vendor/.gitkeep +0 -0
package/README.md ADDED
@@ -0,0 +1,837 @@
1
+ # DocViz Builder
2
+
3
+ Compila bloques declarativos de diagramas escritos dentro de Markdown y devuelve
4
+ **Markdown estándar y portable**: el visor final no necesita conocer PlantUML,
5
+ Mermaid, D2, Vega-Lite, Graphviz ni LikeC4, solo saber mostrar una imagen.
6
+
7
+ ```md
8
+ ## Flujo de autenticación
9
+
10
+ ```plantuml
11
+ @startuml
12
+ Usuario -> API: Login
13
+ API --> Usuario: Token
14
+ @enduml
15
+ ```
16
+ ```
17
+
18
+ se convierte en
19
+
20
+ ```md
21
+ ## Flujo de autenticación
22
+
23
+ ![Flujo de autenticación](./assets/generated/flujo-de-autenticacion-a4f93d12c7b1.svg)
24
+ ```
25
+
26
+ Todo ocurre **en local**: sin servicios externos, sin claves y sin enviar
27
+ documentación confidencial a ningún sitio.
28
+
29
+ ---
30
+
31
+ ## Índice
32
+
33
+ - [Instalación](#instalación)
34
+ - [Uso](#uso)
35
+ - [El DSL de alto nivel](#el-dsl-de-alto-nivel)
36
+ - [Lenguajes nativos](#lenguajes-nativos)
37
+ - [Configuración](#configuración)
38
+ - [Temas](#temas)
39
+ - [Caché y determinismo](#caché-y-determinismo)
40
+ - [Qué cambió entre dos versiones](#qué-cambió-entre-dos-versiones)
41
+ - [Errores](#errores)
42
+ - [Seguridad](#seguridad)
43
+ - [Servidor MCP](#servidor-mcp)
44
+ - [Que tu agente sepa que existe](#que-tu-agente-sepa-que-existe)
45
+ - [Cómo sabemos que un modelo lo sabe usar](#cómo-sabemos-que-un-modelo-lo-sabe-usar)
46
+ - [Desarrollo](#desarrollo)
47
+
48
+ ---
49
+
50
+ ## Instalación
51
+
52
+ Requisitos:
53
+
54
+ | Requisito | Para qué | Obligatorio |
55
+ |---|---|---|
56
+ | Node.js ≥ 20.11 | Todo | Sí |
57
+ | Java ≥ 8 | PlantUML (UML, ERD, C4 alternativo, wireframes) | Solo si usas esos tipos |
58
+ | Chrome o Chromium ya instalado | Mermaid y BPMN | Solo si usas esos tipos |
59
+
60
+ D2, Graphviz, Vega-Lite, LikeC4 y svgbob no necesitan nada más: van embebidos
61
+ como WebAssembly o JavaScript puro.
62
+
63
+ Varios tipos declaran un motor alternativo, así que una máquina sin navegador o
64
+ sin Java sigue compilando lo que pueda en lugar de fallar entera.
65
+
66
+ ### En tu proyecto
67
+
68
+ ```bash
69
+ npm install -D docviz-builder
70
+ npx docviz setup # descarga plantuml.jar desde Maven Central
71
+ npx docviz init # docviz.config.yaml, AGENTS.md, docs-src/ y un ejemplo
72
+ npx docviz doctor # qué motores puede usar esta máquina
73
+ ```
74
+
75
+ `docviz setup` es la única operación que usa la red, y solo una vez. No se
76
+ ejecuta en el `postinstall` a propósito: una herramienta pensada para
77
+ documentación confidencial no descarga nada por su cuenta sin que se lo pidas.
78
+ Si tu organización ya distribuye el jar, apúntalo con `renderers.plantuml.jar`
79
+ en la configuración y omite ese paso.
80
+
81
+ ### Desde el repositorio
82
+
83
+ ```bash
84
+ git clone https://github.com/TilsonF/docviz-builder.git
85
+ cd docviz-builder
86
+ npm install
87
+ npm run setup
88
+ npm run build
89
+ ```
90
+
91
+ DocViz **no descarga navegadores**. Usa el Chrome del sistema o el Chromium que
92
+ ya tengan cacheado Playwright o Puppeteer. Si no encuentra ninguno, lo dice y
93
+ explica cómo indicárselo.
94
+
95
+ ---
96
+
97
+ ## Uso
98
+
99
+ ```bash
100
+ docviz build <source> --output <target>
101
+ ```
102
+
103
+ | Comando | Qué hace |
104
+ |---|---|
105
+ | `docviz build` | Compila los documentos y genera los recursos |
106
+ | `docviz check` | Valida los bloques sin renderizar (rápido) |
107
+ | `docviz diff` | Compara los diagramas de dos versiones de la documentación |
108
+ | `docviz fix` | Corrige las erratas de un bloque que no compila |
109
+ | `docviz verify` | Comprueba que el resultado no tenga imágenes rotas |
110
+ | `docviz preview` | Sirve el resultado en un visor local |
111
+ | `docviz types` | Lista los tipos del DSL y los temas |
112
+ | `docviz setup` | Descarga `plantuml.jar` dentro del paquete |
113
+ | `docviz skill` | Instala el contrato de DocViz como skill de tu agente |
114
+ | `docviz suggest "..."` | Recomienda un tipo a partir de una frase |
115
+ | `npm run docs:sync` | Regenera las tablas de tipos de la documentación |
116
+ | `npm run check:github` | Comprueba cómo renderizaría GitHub la salida |
117
+
118
+ Opciones de `build`:
119
+
120
+ ```bash
121
+ docviz build ./docs-src \
122
+ --output ./docs \
123
+ --theme corporate \
124
+ --clean \
125
+ --verbose \
126
+ --no-cache \
127
+ --renderer-url http://localhost:8000 \
128
+ --continue-on-error
129
+ ```
130
+
131
+ Flujo recomendado, ya cableado como scripts de npm:
132
+
133
+ ```bash
134
+ npm run docs:check # ¿la documentación está al día y los bloques son válidos?
135
+ npm run docs:build # docs-src/ -> docs/
136
+ npm run docs:test # verifica la salida y corre las pruebas de integración
137
+ npm run docs:preview # revisión visual en el navegador
138
+ ```
139
+
140
+ `docs:check` y `docs:build` terminan con código distinto de cero si algo falla,
141
+ así que encajan directamente en un pipeline de CI.
142
+
143
+ ### La documentación no puede desfasarse
144
+
145
+ Las tablas de tipos de este README, de `AGENTS.md` y de `docs-src/dsl.md` se
146
+ generan desde el catálogo entre marcas `<!-- docviz:... -->`. `docs:check`
147
+ verifica que estén al día y falla si no lo están, así que un tipo nuevo no puede
148
+ publicarse con la documentación vieja. Para regenerarlas:
149
+
150
+ ```bash
151
+ npm run docs:sync
152
+ ```
153
+
154
+ ### Cómo se verá en GitHub
155
+
156
+ ```bash
157
+ npm run check:github
158
+ ```
159
+
160
+ Pide a GitHub que renderice el Markdown compilado con su propia API y comprueba
161
+ sobre el HTML resultante que cada imagen aparece, conserva su texto alternativo
162
+ y sigue apuntando a una ruta relativa. No necesita publicar el repositorio.
163
+
164
+ ---
165
+
166
+ ## El DSL de alto nivel
167
+
168
+ Un autor —humano o agente— no debería memorizar seis sintaxis. DocViz ofrece
169
+ tres vallas y elige el motor por ti:
170
+
171
+ | Valla | Para qué |
172
+ |---|---|
173
+ | `diagram` | Interacción, flujo, estados, dependencias, análisis estratégico |
174
+ | `chart` | Comparación cuantitativa, tendencia, distribución |
175
+ | `architecture` | Modelo C4 |
176
+
177
+ ````md
178
+ ```diagram
179
+ type: sequence
180
+ title: Autenticación de usuario
181
+
182
+ participants:
183
+ - Usuario
184
+ - Frontend
185
+ - Entra ID
186
+ - API
187
+
188
+ flow:
189
+ - Usuario -> Frontend: Login
190
+ - Frontend -> Entra ID: Authenticate
191
+ - Entra ID --> Frontend: Token
192
+ - Frontend -> API: Request + Token
193
+ ```
194
+ ````
195
+
196
+ ````md
197
+ ```chart
198
+ type: bar
199
+ title: Defectos por sprint
200
+
201
+ data:
202
+ - label: SP1
203
+ value: 42
204
+ - label: SP2
205
+ value: 28
206
+ - label: SP3
207
+ value: 15
208
+ ```
209
+ ````
210
+
211
+ ````md
212
+ ```architecture
213
+ type: c4-context
214
+ title: Contexto
215
+
216
+ elements:
217
+ - id: usuario
218
+ kind: person
219
+ name: Usuario
220
+ - id: core
221
+ kind: system
222
+ name: Plataforma
223
+
224
+ relations:
225
+ - from: usuario
226
+ to: core
227
+ label: Utiliza
228
+ ```
229
+ ````
230
+
231
+ El catálogo cubre <!-- docviz:tipos-total -->57<!-- /docviz:tipos-total --> tipos.
232
+ `docviz types` los lista siempre actualizados, con su propósito y un ejemplo;
233
+ `docviz suggest` recomienda uno a partir de una frase.
234
+
235
+ <!-- docviz:tipos-resumen -->
236
+ | Motor | Tipos |
237
+ |---|---|
238
+ | vega-lite | 17 |
239
+ | plantuml | 12 |
240
+ | d2 | 11 |
241
+ | mermaid | 11 |
242
+ | likec4 | 3 |
243
+ | bpmn | 1 |
244
+ | graphviz | 1 |
245
+ | svgbob | 1 |
246
+ <!-- /docviz:tipos-resumen -->
247
+
248
+ <!-- docviz:tipos-tablas-4 -->
249
+ #### Diagramas — bloque `diagram`
250
+
251
+ | Necesidad | `type` | Motor |
252
+ |---|---|---|
253
+ | Quien habla con quien y en que orden | `sequence` | plantuml (o d2) |
254
+ | Estructura de clases o entidades y sus relaciones | `class` | plantuml (o d2) |
255
+ | Estados de una entidad y las transiciones entre ellos | `state` | plantuml (o d2) |
256
+ | Proceso con decisiones y ramas paralelas | `activity` | plantuml |
257
+ | Entidades de datos, sus campos y su cardinalidad | `erd` | plantuml (o mermaid) |
258
+ | Que puede hacer cada actor con el sistema | `use-case` | plantuml (o d2) |
259
+ | Componentes de software agrupados y como se conectan | `component` | plantuml (o d2) |
260
+ | Donde se ejecuta cada pieza y sobre que infraestructura | `deployment` | plantuml (o d2) |
261
+ | Boceto de una pantalla: campos, botones y disposicion | `wireframe` | plantuml |
262
+ | Estructura de un JSON dibujada como arbol | `json` | plantuml |
263
+ | Estructura de un YAML dibujada como arbol | `yaml` | plantuml |
264
+ | Descomposicion jerarquica del trabajo de un proyecto | `wbs` | plantuml (o d2) |
265
+ | Flujo sencillo de extremo a extremo | `flow` | mermaid (o d2) |
266
+ | Tareas situadas en el calendario | `gantt` | mermaid (o plantuml) |
267
+ | Recorrido de una persona por un proceso, con su nivel de satisfaccion | `journey` | mermaid |
268
+ | Historia de ramas, commits y fusiones | `git-graph` | mermaid |
269
+ | Tarjetas repartidas por columna de estado | `kanban` | mermaid |
270
+ | Elementos situados en dos ejes continuos | `quadrant` | mermaid |
271
+ | Como se reparte una cantidad al pasar de un estado a otro | `sankey` | mermaid |
272
+ | Composicion de un total por area proporcional | `treemap` | mermaid |
273
+ | Perfil de varias dimensiones a la vez | `radar` | mermaid |
274
+ | Exploracion de un tema en ramas libres | `mindmap` | mermaid (o plantuml) |
275
+ | Bloques dispuestos en rejilla, sin semantica de flujo | `block` | mermaid |
276
+ | Descomposicion de un objetivo en lineas de accion | `strategy-tree` | d2 |
277
+ | Descomposicion de un problema en sus causas | `issue-tree` | d2 |
278
+ | Alternativas de una decision y sus ramas | `decision-tree` | d2 |
279
+ | Pilares que sostienen un objetivo, con su contenido | `strategy-pillars` | d2 |
280
+ | Capacidades agrupadas por dominio | `capability-map` | d2 |
281
+ | Capas de un modelo operativo, de negocio a infraestructura | `operating-model` | d2 |
282
+ | Etapas encadenadas que generan valor | `value-chain` | d2 |
283
+ | Comparacion de dos escenarios | `before-after` | d2 |
284
+ | Cuatro cuadrantes con su contenido, sin coordenadas | `matrix-2x2` | d2 |
285
+ | Hitos en orden cronologico | `timeline` | d2 (o mermaid) |
286
+ | Fases futuras con su contenido | `roadmap` | d2 |
287
+ | Quien depende de quien | `dependency-map` | graphviz |
288
+ | Proceso de negocio en notacion BPMN estandar | `bpmn` | bpmn |
289
+ | Dibujo hecho con caracteres, convertido a SVG limpio | `ascii` | svgbob |
290
+
291
+ #### Gráficos — bloque `chart`
292
+
293
+ | Necesidad | `type` | Motor |
294
+ |---|---|---|
295
+ | Comparacion entre categorias | `bar` | vega-lite |
296
+ | Comparacion entre categorias con etiquetas largas | `horizontal-bar` | vega-lite |
297
+ | Composicion de un total por categoria | `stacked-bar` | vega-lite |
298
+ | Comparacion de varias series por categoria | `grouped-bar` | vega-lite |
299
+ | Evolucion de una magnitud en el tiempo | `line` | vega-lite |
300
+ | Evolucion con enfasis en el volumen acumulado | `area` | vega-lite |
301
+ | Evolucion de la composicion de un total | `stacked-area` | vega-lite |
302
+ | Relacion entre dos magnitudes | `scatter` | vega-lite |
303
+ | Densidad de una magnitud en dos dimensiones categoricas | `heatmap` | vega-lite |
304
+ | Distribucion de una variable continua | `histogram` | vega-lite |
305
+ | Mediana, dispersion y valores atipicos por grupo | `box-plot` | vega-lite |
306
+ | Valor real frente a su objetivo | `bullet` | vega-lite |
307
+ | Cambio entre dos momentos, elemento a elemento | `slope` | vega-lite |
308
+ | Caida de volumen a lo largo de etapas sucesivas | `funnel` | vega-lite |
309
+ | Reparto de un total entre pocas partes | `pie` | vega-lite |
310
+ | Reparto de un total, con el centro libre para un dato o un titulo | `donut` | vega-lite |
311
+ | Como se llega de un valor inicial a uno final, paso a paso | `waterfall` | vega-lite |
312
+
313
+ #### Arquitectura — bloque `architecture`
314
+
315
+ | Necesidad | `type` | Motor |
316
+ |---|---|---|
317
+ | El sistema, sus usuarios y los sistemas con los que habla | `c4-context` | likec4 (o plantuml-c4) |
318
+ | Las piezas desplegables del sistema y su tecnologia | `c4-container` | likec4 (o plantuml-c4) |
319
+ | Componentes internos de un contenedor | `c4-component` | likec4 (o plantuml-c4) |
320
+ <!-- /docviz:tipos-tablas-4 -->
321
+
322
+ Cuando un tipo declara un motor alternativo, DocViz lo usa automáticamente si el
323
+ preferido no está disponible: así se puede compilar en una máquina sin navegador
324
+ o sin Java sin que el build se caiga.
325
+
326
+ ### Sintaxis de las relaciones
327
+
328
+ ```yaml
329
+ flow:
330
+ - A -> B: mensaje # línea sólida
331
+ - A --> B: respuesta # línea discontinua
332
+ - B <- A: equivale a A -> B
333
+ - from: A # forma explícita
334
+ to: B
335
+ label: mensaje
336
+ ```
337
+
338
+ ---
339
+
340
+ ## Lenguajes nativos
341
+
342
+ Los seis lenguajes siguen disponibles como vía de escape:
343
+
344
+ | Valla | Alias | Motor |
345
+ |---|---|---|
346
+ | `plantuml` | `puml`, `uml` | PlantUML local (JVM) |
347
+ | `mermaid` | `mmd` | Mermaid en Chromium headless |
348
+ | `d2` | — | D2 WebAssembly |
349
+ | `graphviz` | `dot` | Graphviz WebAssembly |
350
+ | `vega-lite` | `vegalite`, `vl` | Vega-Lite + Vega en proceso |
351
+ | `likec4` | `c4` | LikeC4 + emisor SVG propio |
352
+ | `svgbob` | `ascii-art` | svgbob WebAssembly (arte ASCII) |
353
+ | `bpmn` | — | bpmn-js en Chromium headless |
354
+
355
+ PlantUML incluye su biblioteca estándar dentro del jar, así que `!include <C4/C4_Context>`
356
+ y el resto de bibliotecas empaquetadas funcionan sin red. Cualquier otra forma
357
+ de `!include` sigue bloqueada.
358
+
359
+ Cualquier otro lenguaje (`typescript`, `bash`, `json`, vallas sin lenguaje) se
360
+ deja intacto.
361
+
362
+ ### Opciones en la valla
363
+
364
+ ````md
365
+ ```plantuml title="Flujo de autenticación" format=png
366
+ ````
367
+
368
+ | Opción | Efecto |
369
+ |---|---|
370
+ | `title="..."` (o `alt="..."`) | Texto alternativo y nombre del archivo |
371
+ | `format=svg\|png` | Formato de salida de ese bloque |
372
+
373
+ Sin `title`, DocViz usa el campo `title:` del DSL o el encabezado anterior.
374
+
375
+ ---
376
+
377
+ ## Configuración
378
+
379
+ `docviz.config.yaml`, todo opcional:
380
+
381
+ ```yaml
382
+ source: docs-src
383
+
384
+ output:
385
+ dir: docs
386
+ assetsDir: assets/generated
387
+
388
+ theme:
389
+ name: corporate
390
+
391
+ formats:
392
+ plantuml: svg
393
+ mermaid: svg
394
+ d2: svg
395
+ graphviz: svg
396
+ vega-lite: svg
397
+ likec4: svg
398
+
399
+ cache:
400
+ enabled: true
401
+ dir: .docviz-cache
402
+
403
+ hash:
404
+ length: 12
405
+
406
+ renderers:
407
+ backend: local # local | kroki
408
+ timeoutMs: 60000
409
+ maxOutputBytes: 8388608
410
+
411
+ kroki:
412
+ url: http://localhost:8000
413
+ allowPublicService: false
414
+ allowRemoteHost: false
415
+
416
+ plantuml:
417
+ jar: vendor/plantuml.jar
418
+ java: java
419
+ maxHeap: 1024m
420
+
421
+ mermaid:
422
+ browserPath: /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
423
+
424
+ d2:
425
+ layout: dagre # dagre | elk
426
+
427
+ graphviz:
428
+ engine: dot
429
+ ```
430
+
431
+ ### Kroki self-hosted
432
+
433
+ Si prefieres centralizar el render en una instancia propia:
434
+
435
+ ```yaml
436
+ renderers:
437
+ backend: kroki
438
+ kroki:
439
+ url: http://kroki.interno:8000
440
+ allowRemoteHost: true
441
+ ```
442
+
443
+ LikeC4 no pasa por Kroki: siempre usa el renderer especializado.
444
+
445
+ ---
446
+
447
+ ## Temas
448
+
449
+ `default`, `corporate`, `executive` y `dark`. Un tema define la misma identidad
450
+ visual en el dialecto de cada motor —`skinparam` de PlantUML, `themeVariables`
451
+ de Mermaid, `themeID` de D2, atributos de Graphviz, `config` de Vega-Lite y la
452
+ paleta del emisor de LikeC4— para que diagramas de motores distintos parezcan
453
+ del mismo documento.
454
+
455
+ ```bash
456
+ docviz build docs-src --output docs --theme executive
457
+ ```
458
+
459
+ ### Una imagen, dos modos
460
+
461
+ Los tres temas claros declaran además su contraparte oscura, y el SVG generado
462
+ lleva las dos: los colores se emiten como variables CSS que se redefinen bajo
463
+ `@media (prefers-color-scheme: dark)`.
464
+
465
+ Un SVG referenciado desde `<img>` se renderiza como su propio documento, así que
466
+ el navegador le aplica la preferencia del lector. El resultado es **un solo
467
+ archivo** que se lee bien en GitHub en modo claro y en un portal en modo oscuro,
468
+ sin duplicar recursos ni escribir `<picture>` a mano.
469
+
470
+ | Motor | Cómo obtiene su variante oscura |
471
+ |---|---|
472
+ | PlantUML, Mermaid, Graphviz, Vega-Lite | Los colores del tema se reescriben como variables CSS |
473
+ | LikeC4 | El emisor propio calcula cada color con las dos paletas |
474
+ | D2 | Trae su propio par de temas (`themeID` / `darkThemeID`) |
475
+
476
+ El tema `dark` es de un solo modo: quien lo elige quiere oscuro siempre.
477
+
478
+ ---
479
+
480
+ ## Caché y determinismo
481
+
482
+ El nombre de cada recurso es `<slug>-<hash>.<ext>`, donde el hash es
483
+
484
+ ```
485
+ SHA256(tipo + fuente + tema + huella del tema + versión del motor + formato)
486
+ ```
487
+
488
+ truncado a 12 caracteres (configurable entre 8 y 16). En consecuencia:
489
+
490
+ - un diagrama sin cambios nunca se vuelve a renderizar;
491
+ - cambiar un color del tema invalida solo lo afectado;
492
+ - actualizar PlantUML invalida solo los diagramas de PlantUML;
493
+ - dos documentos con el mismo diagrama comparten un único archivo.
494
+
495
+ El truncado es seguro porque el build detecta colisiones: si dos fuentes
496
+ distintas comparten prefijo, aborta en lugar de sobrescribir.
497
+
498
+ ```bash
499
+ docviz build docs-src --output docs # 12 regenerados, 0 cache hits
500
+ docviz build docs-src --output docs # 0 regenerados, 12 cache hits
501
+ ```
502
+
503
+ El caché vive fuera del directorio de salida, así que `--clean` borra la salida
504
+ sin perder los aciertos.
505
+
506
+ ---
507
+
508
+ ## Qué cambió entre dos versiones
509
+
510
+ El diff de un `.md` dice que se tocó un bloque YAML, pero no si el dibujo
511
+ resultante es distinto. `docviz diff` compara dos árboles de documentos y
512
+ responde en términos de diagramas:
513
+
514
+ ```bash
515
+ docviz diff ./docs-src-anterior ./docs-src
516
+ ```
517
+
518
+ ```
519
+ base: docs-src-anterior
520
+ head: docs-src
521
+
522
+ ~ arquitectura.md:12 "Autenticación" (diagram, plantuml)
523
+ + arquitectura.md:96 "Métricas" (chart, vega-lite)
524
+ - antiguo.md:5 "Modelo viejo" (diagram, d2)
525
+
526
+ resumen: 1 nuevo(s), 1 eliminado(s), 1 modificado(s), 12 igual(es)
527
+ ```
528
+
529
+ Lo que se compara es el **contenido efectivo** —motor más fuente compilada—, no
530
+ el recurso generado. En consecuencia:
531
+
532
+ - cambiar de tema no aparece como cambio de diagrama;
533
+ - actualizar la versión de un motor tampoco;
534
+ - reordenar el YAML sin alterar el resultado tampoco;
535
+ - insertar un párrafo delante no convierte en nuevos a los diagramas que
536
+ quedaron desplazados: la identidad es `archivo + título`, no la línea.
537
+
538
+ No renderiza nada, así que es tan rápido como `check`. Un lado inválido no
539
+ aborta la comparación —la versión antigua puede estar rota y aun así interesa
540
+ saber qué cambió— pero sus bloques se reportan como aviso.
541
+
542
+ Opciones: `--all` incluye también los diagramas que no cambiaron, `--json`
543
+ devuelve la estructura completa y `--exit-code` termina con código 1 si algo
544
+ cambió, igual que `git diff`. En un pipeline:
545
+
546
+ ```bash
547
+ git worktree add /tmp/base origin/main
548
+ docviz diff /tmp/base/docs-src ./docs-src --exit-code || echo "revisar los diagramas"
549
+ ```
550
+
551
+ ---
552
+
553
+ ## Errores
554
+
555
+ Un fallo de render **nunca** produce un documento incorrecto en silencio: el
556
+ build termina con código distinto de cero y reporta dónde está el problema.
557
+
558
+ ```
559
+ ERROR
560
+ codigo: DV002
561
+ archivo: docs-src/arquitectura.md
562
+ linea: 74
563
+ renderer: plantuml
564
+ motivo: Syntax Error? (Assumed diagram type: sequence)
565
+ detalle:
566
+ ERROR
567
+ 2
568
+ Syntax Error?
569
+ ```
570
+
571
+ `--continue-on-error` compila el resto y deja intacto el bloque que falló, para
572
+ que el documento no mienta sobre lo que contiene. No es el comportamiento por
573
+ defecto.
574
+
575
+ ### El código de regla
576
+
577
+ Todo error lleva un código estable. El destinatario habitual del reporte es un
578
+ agente reintentando, y decidir la corrección analizando un mensaje escrito en
579
+ castellano es frágil: la redacción puede cambiar, el código no.
580
+
581
+ | Código | Qué pasó |
582
+ |---|---|
583
+ | `DV001` | El lenguaje de la valla no tiene renderer registrado |
584
+ | `DV002` | El motor falló al dibujar |
585
+ | `DV003` | Una ruta intentó salirse del directorio de salida |
586
+ | `DV004` | Configuración inválida |
587
+ | `DV005` | El motor que necesita el tipo no está disponible en esta máquina |
588
+ | `DV006` | El renderer no puede producir ese formato |
589
+ | `DV007` | Colisión de hash truncado |
590
+ | `DV100` | DSL inválido, sin clasificar |
591
+ | `DV101` | Falta un campo obligatorio |
592
+ | `DV102` | El campo existe pero su valor no tiene la forma esperada |
593
+ | `DV103` | El valor no pertenece al conjunto admitido |
594
+ | `DV104` | El bloque declara un campo que el tipo no usa |
595
+ | `DV105` | El bloque no es YAML válido |
596
+ | `DV106` | El `type` no existe o no pertenece a esa valla |
597
+
598
+ Los códigos son parte del contrato: se añaden códigos nuevos en lugar de
599
+ reutilizar los existentes.
600
+
601
+ ### Un bloque roto no esconde a los siguientes
602
+
603
+ El escaneo no se detiene en el primer error: un documento con tres bloques
604
+ inválidos los reporta los tres, cada uno con su línea. Corregirlos de uno en
605
+ uno, con un build completo entre cada corrección, es un ciclo caro.
606
+
607
+ ```
608
+ documentos: 1
609
+ bloques: 1 (2 invalido(s))
610
+ avisos: 0
611
+ errores: 2
612
+ ```
613
+
614
+ ### Erratas y campos ignorados
615
+
616
+ Escribir `steps:` donde el tipo espera `flow:` no rompe nada: simplemente el
617
+ contenido no se dibuja. Ese silencio es peor que un error, porque el documento
618
+ sale y nadie se entera de que le falta la mitad.
619
+
620
+ DocViz detecta los campos que el tipo no usa y, si se parecen a uno válido, dice
621
+ cuál:
622
+
623
+ ```
624
+ ERROR
625
+ codigo: DV101
626
+ archivo: docs-src/login.md
627
+ linea: 5
628
+ motivo: diagram.participants debe ser una lista con al menos un elemento
629
+ detalle:
630
+ valor recibido: undefined
631
+ campos no reconocidos:
632
+ - el campo "particpants" no existe en el tipo sequence; quiza querias "participants"
633
+ - el campo "steps" no existe en el tipo sequence y se ha ignorado
634
+ campos del ejemplo de sequence: flow, participants, title, type
635
+ ficha completa: docviz types sequence
636
+ ```
637
+
638
+ Cuando el bloque **sí** compila, el campo ignorado se reporta como aviso
639
+ (`AVISO archivo:linea [DV104] ...`) en stderr y no cambia el código de salida:
640
+ el documento es válido, solo incompleto respecto a lo que su autor escribió.
641
+
642
+ La lista de campos válidos no se mantiene a mano —serían 57 listas que acabarían
643
+ divergiendo— sino que se deduce de dos fuentes que ya existen: las claves del
644
+ ejemplo canónico del catálogo, que las pruebas de integración dibujan de verdad,
645
+ y las claves que el compilador leyó realmente. Un campo que no está en ninguna
646
+ de las dos no hizo nada; eso es un hecho, no una heurística.
647
+
648
+ ---
649
+
650
+ ## Seguridad
651
+
652
+ 1. Motores locales por defecto; ninguna petición de red durante el build.
653
+ 2. `kroki.io` bloqueado salvo autorización explícita.
654
+ 3. Límite de tiempo y de tamaño por diagrama.
655
+ 4. `!include`, `!includeurl`, `!import` y `!theme … from` de PlantUML
656
+ deshabilitados: son lectura de disco arbitraria y SSRF.
657
+ 5. `data.url` de Vega-Lite rechazado a cualquier profundidad.
658
+ 6. Toda ruta de escritura queda contenida en el directorio de salida, y el
659
+ servidor de previsualización resuelve los enlaces simbólicos antes de servir.
660
+ 7. Ningún contenido del documento se usa como ruta ni se pasa a un shell: los
661
+ motores se invocan con un array de argumentos, nunca con una cadena.
662
+ 8. El CI audita el árbol de dependencias de producción en cada commit y falla a
663
+ partir de severidad moderada. Dependabot abre los pull requests de
664
+ actualización sin que nadie tenga que acordarse.
665
+
666
+ ### El SVG que sale de aquí es inerte
667
+
668
+ Vía `![](...)` el navegador carga el SVG como imagen y no ejecuta nada. Pero en
669
+ cuanto alguien lo **incrusta dentro de un HTML** —que es lo natural para
670
+ conservar el tema claro/oscuro— el SVG pasa a ser markup vivo. Por eso todo SVG
671
+ se sanea con una **lista de permitidos**: 49 elementos y 104 atributos medidos
672
+ sobre lo que emiten de verdad los seis motores en los 57 tipos del catálogo.
673
+
674
+ Lo que no está en la lista se cae, incluido lo que no se nos haya ocurrido.
675
+ Además se eliminan los comentarios XML, se escapan `<` y `>` dentro de los
676
+ valores de atributo, se rechaza cualquier esquema de URL que no sea `http(s)` o
677
+ un fragmento interno —resolviendo antes las entidades, porque
678
+ `java&#115;cript:` se lee igual que `javascript:`— y el CSS pierde `@import`,
679
+ `expression(` y las `url()` ejecutables.
680
+
681
+ `tests/unit/svg-seguridad.test.ts` mantiene un banco de 23 vectores conocidos y
682
+ comprueba, además, que sanear los 69 diagramas del catálogo no quita nada más
683
+ que comentarios. La versión anterior del saneador era una lista de prohibidos y
684
+ dejaba pasar nueve de esos vectores.
685
+
686
+ ### Chromium con sandbox
687
+
688
+ Mermaid y BPMN dibujan dentro de un Chromium local, y el contenido del diagrama
689
+ puede venir del documento de otra persona. El sandbox **está activo por
690
+ defecto**: se desactiva solo como root —donde Chromium no arranca de otra
691
+ forma—, o si se pide con `renderers.noSandbox: true` o `DOCVIZ_NO_SANDBOX=1`.
692
+ Mermaid además se configura con `securityLevel: 'strict'` y sin etiquetas HTML.
693
+
694
+ ### El único descargable se verifica
695
+
696
+ `docviz setup` es lo único que trae bytes de fuera. Se comprueba contra un
697
+ digest SHA-256 fijado en el repositorio y verificado contra el checksum
698
+ publicado en Maven Central; si no coincide, **no se escribe nada**. Para una
699
+ versión de PlantUML sin digest conocido hay que pasarlo con `--sha256`, o pedir
700
+ explícitamente `--sin-verificar`.
701
+
702
+ ---
703
+
704
+ ## Servidor MCP
705
+
706
+ DocViz se expone como herramientas MCP para que un agente no tenga que ejecutar
707
+ comandos:
708
+
709
+ | Herramienta | Qué hace |
710
+ |---|---|
711
+ | `docviz_suggest` | Recomienda el tipo a partir de una frase y devuelve el bloque |
712
+ | `docviz_types` | Catálogo de tipos con propósito, cuándo usarlos y ejemplo |
713
+ | `docviz_validate_document` | Valida bloques sin renderizar |
714
+ | `docviz_render_diagram` | Renderiza un diagrama suelto |
715
+ | `docviz_build_document` | Compila y verifica la documentación |
716
+ | `docviz_diff` | Qué diagramas cambiaron entre dos versiones |
717
+ | `docviz_fix` | Devuelve corregido un bloque que no compila |
718
+ | `docviz_preview` | Devuelve el Markdown compilado y sus incidencias |
719
+
720
+ Registro en un cliente MCP:
721
+
722
+ ```json
723
+ {
724
+ "mcpServers": {
725
+ "docviz": {
726
+ "command": "node",
727
+ "args": ["/ruta/a/docviz-builder/bin/docviz-mcp.mjs"],
728
+ "cwd": "/ruta/a/tu/proyecto"
729
+ }
730
+ }
731
+ }
732
+ ```
733
+
734
+ ---
735
+
736
+ ## Que tu agente sepa que existe
737
+
738
+ `docviz init` deja un `AGENTS.md` en el proyecto, y con eso basta para los
739
+ agentes que lo leen solos. Pero un agente solo abre `AGENTS.md` si ya está
740
+ trabajando en ese repositorio: no hay forma de que sepa que DocViz existe antes
741
+ de eso.
742
+
743
+ ```bash
744
+ npx docviz skill # lo instala en .claude/skills/ del proyecto
745
+ npx docviz skill --global # o en tu perfil, para todos tus proyectos
746
+ npx docviz skill --dir .config/opencode/skills # otro agente
747
+ ```
748
+
749
+ El skill es un resumen corto: las tres vallas, cómo preguntar el tipo, el flujo
750
+ de trabajo y la tabla de códigos de error. El catálogo completo de los 57 tipos
751
+ sigue en `AGENTS.md`, al que el skill apunta.
752
+
753
+ ---
754
+
755
+ ## Cómo sabemos que un modelo lo sabe usar
756
+
757
+ Que un LLM acierte no es una intuición: se mide. `eval/casos.json` contiene 45
758
+ necesidades escritas como las escribiría una persona —sin nombrar el tipo— con
759
+ el tipo que debería elegir.
760
+
761
+ ```bash
762
+ npm run eval # sin red y sin coste: mide si el catálogo guía bien
763
+ npm run eval:modelo # la medida real, con un modelo de verdad
764
+ ```
765
+
766
+ El **modo catálogo** pregunta a `docviz suggest` qué tipo usaría para cada
767
+ necesidad. No usa ningún modelo, pero mide justo lo que un modelo lee para
768
+ decidir: los `keywords`, el `purpose` y el `whenToUse`. Es determinista, dura un
769
+ segundo y por eso es una compuerta de CI (`npm run eval -- --minimo 0.85`).
770
+
771
+ El **modo modelo** es la medida real: se le entrega el mismo `AGENTS.md` que
772
+ recibiría en un proyecto, se le pide el bloque y se compila. Si falla, se le
773
+ devuelve el error tal cual —con su código y su errata señalada— y se le deja
774
+ reintentar. Lo que se mide entonces no es solo si acierta, sino si los mensajes
775
+ de error le permiten recuperarse. Requiere `ANTHROPIC_API_KEY` y gasta dinero.
776
+
777
+ Medida actual del modo catálogo: **80,0 %** de acierto en la primera propuesta y
778
+ **88,9 %** entre las tres primeras. Los fallos conocidos están en gráficos cuyo
779
+ nombre nadie usa al describir la necesidad (`histogram`, `funnel`,
780
+ `stacked-bar`, `horizontal-bar`): el término de dominio aparece en el catálogo,
781
+ pero lo ahogan las coincidencias de prosa genérica. Es el primer objetivo de
782
+ mejora, y hay que hacerlo con una partición de casos aparte para que el número
783
+ siga siendo honesto.
784
+
785
+ ---
786
+
787
+ ## Desarrollo
788
+
789
+ ```bash
790
+ npm run build # compila TypeScript
791
+ npm run typecheck
792
+ npm test # 752 pruebas
793
+ npm run test:unit
794
+ npm run test:integration
795
+ npx vitest run --coverage
796
+ npm run showcase # compila examples/showcase.md
797
+ ```
798
+
799
+ Estructura:
800
+
801
+ ```
802
+ src/
803
+ ├── core/ tipos, registry, hash, caché, rutas, errores
804
+ ├── config/ carga y validación de docviz.config.yaml
805
+ ├── markdown/ detección (mdast) y sustitución por posición
806
+ ├── dsl/ diagram, chart y architecture
807
+ ├── renderers/ los seis motores + backend Kroki + utilidades SVG
808
+ ├── themes/ default, corporate, executive, dark
809
+ ├── build/ orquestador, verificador y servidor de previsualización
810
+ ├── mcp/ herramientas y servidor MCP
811
+ └── cli.ts
812
+ ```
813
+
814
+ La cobertura exigida es 90 % de líneas, sentencias y funciones, y 85 % de ramas;
815
+ el umbral está configurado en `vitest.config.ts` y falla el build si baja.
816
+
817
+ Las pruebas de integración **dibujan de verdad el ejemplo de cada tipo del
818
+ catálogo** con su motor real. No basta con comprobar que el compilador genera el
819
+ texto: varios tipos se apoyan en notaciones que sus motores marcan como beta, y
820
+ si una cambia de sintaxis el compilador seguiría produciendo su texto sin
821
+ enterarse. Renderizarlos es lo que convierte esa rotura en un fallo inmediato en
822
+ lugar de en una sorpresa semanas después.
823
+
824
+ ---
825
+
826
+ ## Compatibilidad
827
+
828
+ DocViz está en `0.x`. [COMPATIBILIDAD.md](./COMPATIBILIDAD.md) describe qué se
829
+ considera contrato público —el DSL, los códigos de error, los nombres de las
830
+ herramientas MCP, los comandos y el formato de salida— y qué es detalle interno
831
+ que puede cambiar. Conviene fijar la versión hasta la 1.0.
832
+
833
+ ---
834
+
835
+ ## Licencia
836
+
837
+ MIT.