xonecode 0.3.0 → 0.5.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/README.md +50 -8
- package/THIRD_PARTY_NOTICES.md +160 -0
- package/apps/web/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/apps/web/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/apps/web/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/apps/web/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/apps/web/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/apps/web/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/apps/web/dist/assets/c-BIGW1oBm.js +1 -0
- package/apps/web/dist/assets/cpp-DddhVWhK.js +1 -0
- package/apps/web/dist/assets/csharp-DSvCPggb.js +1 -0
- package/apps/web/dist/assets/css-CLj8gQPS.js +1 -0
- package/apps/web/dist/assets/go-C27-OAKa.js +1 -0
- package/apps/web/dist/assets/html-CfGypltT.js +1 -0
- package/apps/web/dist/assets/index-BB3SamhR.css +1 -0
- package/apps/web/dist/assets/index-CFYAoHdw.js +477 -0
- package/apps/web/dist/assets/ini-BEwlwnbL.js +1 -0
- package/apps/web/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/apps/web/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/apps/web/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/apps/web/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/apps/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/apps/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/apps/web/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/apps/web/dist/assets/java-CylS5w8V.js +1 -0
- package/apps/web/dist/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/apps/web/dist/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/apps/web/dist/assets/kotlin-BdnUsdx6.js +1 -0
- package/apps/web/dist/assets/less-B1dDrJ26.js +1 -0
- package/apps/web/dist/assets/lua-BaeVxFsk.js +1 -0
- package/apps/web/dist/assets/markdown-Cvjx9yec.js +1 -0
- package/apps/web/dist/assets/mdx-Cmh6b_Ma.js +1 -0
- package/apps/web/dist/assets/php-D_2--9WK.js +1 -0
- package/apps/web/dist/assets/python-B6aJPvgy.js +1 -0
- package/apps/web/dist/assets/ruby-DSHSDbk1.js +1 -0
- package/apps/web/dist/assets/rust-B1yitclQ.js +1 -0
- package/apps/web/dist/assets/scss-D5BDwBP9.js +1 -0
- package/apps/web/dist/assets/sql-CRqJ_cUM.js +1 -0
- package/apps/web/dist/assets/swift-C2oV4EkX.js +1 -0
- package/apps/web/dist/assets/toml-vGWfd6FD.js +1 -0
- package/apps/web/dist/assets/xml-sdJ4AIDG.js +1 -0
- package/apps/web/dist/assets/yaml-Buea-lGh.js +1 -0
- package/apps/web/dist/iconos/xonecode.png +0 -0
- package/apps/web/dist/index.html +20 -0
- package/dist/agent/agentesEnDisco.js +539 -0
- package/dist/agent/agentesEnDisco.js.map +1 -0
- package/dist/agent/arbolDeProyecto.js +245 -0
- package/dist/agent/arbolDeProyecto.js.map +1 -0
- package/dist/agent/artefactosEnDisco.js +139 -0
- package/dist/agent/artefactosEnDisco.js.map +1 -0
- package/dist/agent/aumentador.js +175 -0
- package/dist/agent/aumentador.js.map +1 -0
- package/dist/agent/authEnDisco.js +76 -1
- package/dist/agent/authEnDisco.js.map +1 -1
- package/dist/agent/busquedaRegex.js +92 -0
- package/dist/agent/busquedaRegex.js.map +1 -0
- package/dist/agent/catalogoModelos.js +345 -0
- package/dist/agent/catalogoModelos.js.map +1 -0
- package/dist/agent/checkpointer.js +127 -0
- package/dist/agent/checkpointer.js.map +1 -0
- package/dist/agent/cloudstudioClient.js +194 -0
- package/dist/agent/cloudstudioClient.js.map +1 -0
- package/dist/agent/cloudstudioMcp.js +722 -0
- package/dist/agent/cloudstudioMcp.js.map +1 -0
- package/dist/agent/configEnDisco.js +309 -11
- package/dist/agent/configEnDisco.js.map +1 -1
- package/dist/agent/consumoExterno.js +99 -0
- package/dist/agent/consumoExterno.js.map +1 -0
- package/dist/agent/descarga.js +149 -0
- package/dist/agent/descarga.js.map +1 -0
- package/dist/agent/diagnosticoDeTools.js +51 -0
- package/dist/agent/diagnosticoDeTools.js.map +1 -0
- package/dist/agent/dispositivosEnMaquina.js +596 -0
- package/dist/agent/dispositivosEnMaquina.js.map +1 -0
- package/dist/agent/escrituraDeCodex.js +134 -0
- package/dist/agent/escrituraDeCodex.js.map +1 -0
- package/dist/agent/escrituraDeOpencode.js +80 -0
- package/dist/agent/escrituraDeOpencode.js.map +1 -0
- package/dist/agent/escrituraExterna.js +742 -0
- package/dist/agent/escrituraExterna.js.map +1 -0
- package/dist/agent/gemini.js +81 -0
- package/dist/agent/gemini.js.map +1 -0
- package/dist/agent/git.js +83 -0
- package/dist/agent/git.js.map +1 -0
- package/dist/agent/gitSync.js +441 -0
- package/dist/agent/gitSync.js.map +1 -0
- package/dist/agent/hotswap.js +448 -0
- package/dist/agent/hotswap.js.map +1 -0
- package/dist/agent/instalacionEnMaquina.js +252 -0
- package/dist/agent/instalacionEnMaquina.js.map +1 -0
- package/dist/agent/instantanea.js +7 -10
- package/dist/agent/instantanea.js.map +1 -1
- package/dist/agent/interrupts.js +11 -2
- package/dist/agent/interrupts.js.map +1 -1
- package/dist/agent/juezDeTarea.js +345 -0
- package/dist/agent/juezDeTarea.js.map +1 -0
- package/dist/agent/lanzamientoEnMaquina.js +377 -0
- package/dist/agent/lanzamientoEnMaquina.js.map +1 -0
- package/dist/agent/manifiesto.js +59 -0
- package/dist/agent/manifiesto.js.map +1 -0
- package/dist/agent/memoriaDeProyecto.js +60 -0
- package/dist/agent/memoriaDeProyecto.js.map +1 -0
- package/dist/agent/modelos.js +105 -17
- package/dist/agent/modelos.js.map +1 -1
- package/dist/agent/modelosDeMotor.js +204 -0
- package/dist/agent/modelosDeMotor.js.map +1 -0
- package/dist/agent/paqueteDelProyecto.js +181 -0
- package/dist/agent/paqueteDelProyecto.js.map +1 -0
- package/dist/agent/perfiles.js +92 -31
- package/dist/agent/perfiles.js.map +1 -1
- package/dist/agent/persona.js +40 -0
- package/dist/agent/persona.js.map +1 -0
- package/dist/agent/procesosEnMaquina.js +204 -0
- package/dist/agent/procesosEnMaquina.js.map +1 -0
- package/dist/agent/proyecto.js +311 -13
- package/dist/agent/proyecto.js.map +1 -1
- package/dist/agent/puente.js +63 -6
- package/dist/agent/puente.js.map +1 -1
- package/dist/agent/resumenDeContexto.js +30 -0
- package/dist/agent/resumenDeContexto.js.map +1 -0
- package/dist/agent/resumenDeTool.js +64 -18
- package/dist/agent/resumenDeTool.js.map +1 -1
- package/dist/agent/sesionGit.js +481 -0
- package/dist/agent/sesionGit.js.map +1 -0
- package/dist/agent/settingsEnDisco.js +189 -0
- package/dist/agent/settingsEnDisco.js.map +1 -0
- package/dist/agent/subagenteCodex.js +368 -0
- package/dist/agent/subagenteCodex.js.map +1 -0
- package/dist/agent/subagenteExterno.js +423 -0
- package/dist/agent/subagenteExterno.js.map +1 -0
- package/dist/agent/subagenteOpencode.js +389 -0
- package/dist/agent/subagenteOpencode.js.map +1 -0
- package/dist/agent/subida.js +202 -0
- package/dist/agent/subida.js.map +1 -0
- package/dist/agent/tareasEnDisco.js +466 -0
- package/dist/agent/tareasEnDisco.js.map +1 -0
- package/dist/agent/turnoReal.js +663 -50
- package/dist/agent/turnoReal.js.map +1 -1
- package/dist/agent/versionEnDisco.js +48 -0
- package/dist/agent/versionEnDisco.js.map +1 -0
- package/dist/agent/xoneAgent.js +290 -49
- package/dist/agent/xoneAgent.js.map +1 -1
- package/dist/agent/zip.js +52 -0
- package/dist/agent/zip.js.map +1 -0
- package/dist/cli/acuseDeModelo.js +30 -0
- package/dist/cli/acuseDeModelo.js.map +1 -0
- package/dist/cli/aprobar.js +55 -2
- package/dist/cli/aprobar.js.map +1 -1
- package/dist/cli/config.js +9 -13
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/consola.js +750 -19
- package/dist/cli/consola.js.map +1 -1
- package/dist/cli/main.js +740 -81
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/markdown.js +188 -2
- package/dist/cli/markdown.js.map +1 -1
- package/dist/cli/run.js +32 -4
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/stdio.js +46 -19
- package/dist/cli/stdio.js.map +1 -1
- package/dist/cli/tema.js +96 -8
- package/dist/cli/tema.js.map +1 -1
- package/dist/cli/tokens.js +29 -0
- package/dist/cli/tokens.js.map +1 -0
- package/dist/cli/tui/app.js +171 -0
- package/dist/cli/tui/app.js.map +1 -0
- package/dist/cli/tui/aprobarTui.js +80 -0
- package/dist/cli/tui/aprobarTui.js.map +1 -0
- package/dist/cli/tui/barra.js +37 -0
- package/dist/cli/tui/barra.js.map +1 -0
- package/dist/cli/tui/correrTui.js +478 -0
- package/dist/cli/tui/correrTui.js.map +1 -0
- package/dist/cli/tui/entrada.js +166 -0
- package/dist/cli/tui/entrada.js.map +1 -0
- package/dist/cli/tui/filas.js +24 -0
- package/dist/cli/tui/filas.js.map +1 -0
- package/dist/cli/tui/logo.js +49 -0
- package/dist/cli/tui/logo.js.map +1 -0
- package/dist/cli/tui/pielTui.js +14 -0
- package/dist/cli/tui/pielTui.js.map +1 -0
- package/dist/cli/tui/raton.js +126 -0
- package/dist/cli/tui/raton.js.map +1 -0
- package/dist/cli/tui/sidebar.js +86 -0
- package/dist/cli/tui/sidebar.js.map +1 -0
- package/dist/cli/tui/store.js +143 -0
- package/dist/cli/tui/store.js.map +1 -0
- package/dist/cli/tui/tarjeta.js +19 -0
- package/dist/cli/tui/tarjeta.js.map +1 -0
- package/dist/cli/tui/temaInk.js +114 -0
- package/dist/cli/tui/temaInk.js.map +1 -0
- package/dist/cli/tui/transcript.js +254 -0
- package/dist/cli/tui/transcript.js.map +1 -0
- package/dist/cli/wizardInicial.js +240 -0
- package/dist/cli/wizardInicial.js.map +1 -0
- package/dist/core/actos.js +113 -0
- package/dist/core/actos.js.map +1 -0
- package/dist/core/adjuntos.js +97 -0
- package/dist/core/adjuntos.js.map +1 -0
- package/dist/core/agentes.js +227 -0
- package/dist/core/agentes.js.map +1 -0
- package/dist/core/artefactos.js +149 -0
- package/dist/core/artefactos.js.map +1 -0
- package/dist/core/cloudstudio.js +7 -0
- package/dist/core/cloudstudio.js.map +1 -0
- package/dist/core/config.js +212 -5
- package/dist/core/config.js.map +1 -1
- package/dist/core/contextos.js +53 -1
- package/dist/core/contextos.js.map +1 -1
- package/dist/core/descargas.js +106 -0
- package/dist/core/descargas.js.map +1 -0
- package/dist/core/descriptoresDeApp.js +279 -0
- package/dist/core/descriptoresDeApp.js.map +1 -0
- package/dist/core/dispositivos.js +466 -0
- package/dist/core/dispositivos.js.map +1 -0
- package/dist/core/entrega.js +141 -0
- package/dist/core/entrega.js.map +1 -0
- package/dist/core/entrelazar.js +90 -0
- package/dist/core/entrelazar.js.map +1 -0
- package/dist/core/esqueleto.js +10 -0
- package/dist/core/esqueleto.js.map +1 -1
- package/dist/core/modelos.js +235 -3
- package/dist/core/modelos.js.map +1 -1
- package/dist/core/notify.js +27 -9
- package/dist/core/notify.js.map +1 -1
- package/dist/core/planDeSubida.js +127 -0
- package/dist/core/planDeSubida.js.map +1 -0
- package/dist/core/ports.js +189 -1
- package/dist/core/ports.js.map +1 -1
- package/dist/core/puedeLanzarse.js +239 -0
- package/dist/core/puedeLanzarse.js.map +1 -0
- package/dist/core/rutaVirtual.js +42 -0
- package/dist/core/rutaVirtual.js.map +1 -0
- package/dist/core/settings.js +246 -0
- package/dist/core/settings.js.map +1 -0
- package/dist/core/tareas.js +230 -0
- package/dist/core/tareas.js.map +1 -0
- package/dist/core/textos.js +36 -0
- package/dist/core/textos.js.map +1 -0
- package/dist/core/turno.js +56 -8
- package/dist/core/turno.js.map +1 -1
- package/dist/core/version.js +31 -0
- package/dist/core/version.js.map +1 -0
- package/dist/vendor/sqliteSaver.js +389 -0
- package/dist/vendor/sqliteSaver.js.map +1 -0
- package/dist/vendor/tokenTracking.js +22 -1
- package/dist/vendor/tokenTracking.js.map +1 -1
- package/dist/web/servidor/arranque.js +3964 -0
- package/dist/web/servidor/arranque.js.map +1 -0
- package/dist/web/servidor/consolaDeTarea.js +161 -0
- package/dist/web/servidor/consolaDeTarea.js.map +1 -0
- package/dist/web/servidor/consolaWeb.js +389 -0
- package/dist/web/servidor/consolaWeb.js.map +1 -0
- package/dist/web/servidor/corredorDeTareas.js +1119 -0
- package/dist/web/servidor/corredorDeTareas.js.map +1 -0
- package/dist/web/servidor/pielWeb.js +269 -0
- package/dist/web/servidor/pielWeb.js.map +1 -0
- package/dist/web/servidor/servidor.js +257 -0
- package/dist/web/servidor/servidor.js.map +1 -0
- package/dist/web/servidor/sesiones.js +440 -0
- package/dist/web/servidor/sesiones.js.map +1 -0
- package/dist/web/servidor/transporte.js +169 -0
- package/dist/web/servidor/transporte.js.map +1 -0
- package/dist/web/servidor/vestibulo.js +1276 -0
- package/dist/web/servidor/vestibulo.js.map +1 -0
- package/package.json +33 -9
- package/skills/archify/LICENSE +22 -0
- package/skills/archify/SKILL.md +109 -0
- package/skills/archify/THIRD_PARTY_NOTICES.md +56 -0
- package/skills/archify/assets/template.html +14787 -0
- package/skills/archify/bin/archify.mjs +1990 -0
- package/skills/archify/bin/open-artifact.mjs +86 -0
- package/skills/archify/bin/preview.mjs +648 -0
- package/skills/archify/bin/visual-check.mjs +829 -0
- package/skills/archify/brand-marks/README.md +31 -0
- package/skills/archify/brand-marks/catalog.json +131 -0
- package/skills/archify/delta/architecture-delta.mjs +1214 -0
- package/skills/archify/examples/agent-run.lifecycle.json +71 -0
- package/skills/archify/examples/agent-tool-call.workflow.json +94 -0
- package/skills/archify/examples/async-job-roundtrip.sequence.json +61 -0
- package/skills/archify/examples/brand-aware-delivery.architecture.json +47 -0
- package/skills/archify/examples/cache-miss-request.sequence.json +81 -0
- package/skills/archify/examples/checkout-platform.base.architecture.json +31 -0
- package/skills/archify/examples/checkout-platform.head.architecture.json +31 -0
- package/skills/archify/examples/dataflow-product-analytics.html +14898 -0
- package/skills/archify/examples/deployment-release.lifecycle.json +49 -0
- package/skills/archify/examples/event-stream.dataflow.json +57 -0
- package/skills/archify/examples/incident-response.workflow.json +64 -0
- package/skills/archify/examples/lifecycle-agent-run.html +14847 -0
- package/skills/archify/examples/product-analytics.dataflow.json +76 -0
- package/skills/archify/examples/production-deployment.architecture.json +71 -0
- package/skills/archify/examples/release-delivery.workflow.json +62 -0
- package/skills/archify/examples/sequence-cache-miss-request.html +14913 -0
- package/skills/archify/examples/web-app-rendered.html +14862 -0
- package/skills/archify/examples/web-app.architecture.json +46 -0
- package/skills/archify/examples/workflow-agent-tool-call-rendered.html +14904 -0
- package/skills/archify/migrations/workflow-v2.mjs +279 -0
- package/skills/archify/package.json +17 -0
- package/skills/archify/recipes/scenarios.mjs +391 -0
- package/skills/archify/references/authoring-contract.md +198 -0
- package/skills/archify/references/brand-marks.md +69 -0
- package/skills/archify/references/delivery-contract.md +116 -0
- package/skills/archify/references/viewer-runtime.md +45 -0
- package/skills/archify/renderers/architecture/grid.mjs +62 -0
- package/skills/archify/renderers/architecture/render-architecture.mjs +1078 -0
- package/skills/archify/renderers/dataflow/README.md +104 -0
- package/skills/archify/renderers/dataflow/render-dataflow.mjs +483 -0
- package/skills/archify/renderers/lifecycle/README.md +115 -0
- package/skills/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
- package/skills/archify/renderers/sequence/README.md +114 -0
- package/skills/archify/renderers/sequence/render-sequence.mjs +453 -0
- package/skills/archify/renderers/shared/brand-marks.mjs +563 -0
- package/skills/archify/renderers/shared/cli.mjs +218 -0
- package/skills/archify/renderers/shared/desktop-readability.mjs +26 -0
- package/skills/archify/renderers/shared/diagnostics.mjs +127 -0
- package/skills/archify/renderers/shared/engineering-profiles.mjs +157 -0
- package/skills/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
- package/skills/archify/renderers/shared/generated-validators.mjs +13 -0
- package/skills/archify/renderers/shared/geometry.mjs +1423 -0
- package/skills/archify/renderers/shared/i18n.mjs +594 -0
- package/skills/archify/renderers/shared/layout-report.mjs +40 -0
- package/skills/archify/renderers/shared/legend.mjs +217 -0
- package/skills/archify/renderers/shared/output-path.mjs +321 -0
- package/skills/archify/renderers/shared/repository-evidence.mjs +235 -0
- package/skills/archify/renderers/shared/text-fit.mjs +49 -0
- package/skills/archify/renderers/shared/utils.mjs +232 -0
- package/skills/archify/renderers/shared/validator.mjs +86 -0
- package/skills/archify/renderers/workflow/README.md +223 -0
- package/skills/archify/renderers/workflow/render-workflow.mjs +35 -0
- package/skills/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/skills/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
- package/skills/archify/schemas/README.md +211 -0
- package/skills/archify/schemas/architecture.schema.json +176 -0
- package/skills/archify/schemas/common.schema.json +115 -0
- package/skills/archify/schemas/dataflow.schema.json +243 -0
- package/skills/archify/schemas/lifecycle.schema.json +266 -0
- package/skills/archify/schemas/sequence.schema.json +223 -0
- package/skills/archify/schemas/workflow.schema.json +428 -0
- package/skills/archify/scripts/check-render-output.mjs +835 -0
- package/skills/archify/scripts/check-update.mjs +1667 -0
- package/skills/archify/scripts/render-examples.mjs +26 -0
- package/skills/archify/scripts/update-contract.mjs +182 -0
- package/skills/archify/skill-release.json +10 -0
- package/skills/artifacts-builder/SKILL.md +120 -0
- package/skills/artifacts-builder/reference/diagramas.md +123 -0
- package/skills/artifacts-builder/reference/estilo.md +123 -0
- package/skills/artifacts-builder/reference/exportar-pdf.md +56 -0
- package/skills/artifacts-builder/reference/graficas.md +22 -0
- package/skills/artifacts-builder/scripts/bundle_artifact.py +109 -0
- package/skills/artifacts-builder/scripts/validate_artifact.py +345 -0
- package/skills/xone-hotswap/SKILL.md +185 -0
- package/skills/xone-hotswap/references/comandos.md +706 -0
- package/skills/xone-hotswap/references/conexion-y-despliegue.md +226 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Sequence Renderer
|
|
2
|
+
|
|
3
|
+
Render `diagram_type: "sequence"` JSON files into the standard Archify HTML
|
|
4
|
+
template.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
node archify/renderers/sequence/render-sequence.mjs input.sequence.json output.html
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The renderer validates input against `archify/schemas/sequence.schema.json`
|
|
11
|
+
with the bundled standalone validator. No dependency installation is required.
|
|
12
|
+
|
|
13
|
+
If `output.html` is omitted, the renderer uses `meta.output` from the JSON file
|
|
14
|
+
or falls back to `sequence.html` in the current working directory.
|
|
15
|
+
|
|
16
|
+
## Input
|
|
17
|
+
|
|
18
|
+
Sequence JSON files must set:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"schema_version": 1,
|
|
23
|
+
"diagram_type": "sequence",
|
|
24
|
+
"meta": {
|
|
25
|
+
"title": "Cache Miss Request Sequence",
|
|
26
|
+
"viewBox": [920, 760]
|
|
27
|
+
},
|
|
28
|
+
"participants": [],
|
|
29
|
+
"segments": [],
|
|
30
|
+
"messages": [],
|
|
31
|
+
"activations": [],
|
|
32
|
+
"cards": []
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The timeline scales with the viewBox height: a taller `meta.viewBox` buys more
|
|
37
|
+
message room, a shorter one shrinks the readable band instead of clipping. A
|
|
38
|
+
complete worked example lives at
|
|
39
|
+
`archify/examples/cache-miss-request.sequence.json`.
|
|
40
|
+
|
|
41
|
+
The schema lives at:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
archify/schemas/sequence.schema.json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Legend
|
|
48
|
+
|
|
49
|
+
The default visual legend derives kinds from `messages[].variant` (omitting
|
|
50
|
+
`variant` means `default`). Supported `meta.legend.entries` keys, in stable
|
|
51
|
+
order, are `emphasis`, `return`, `security`, `dashed`, and `default`. These are
|
|
52
|
+
visual message keys, not Semantic Lens controls; label/visibility overrides do
|
|
53
|
+
not create edge facts.
|
|
54
|
+
|
|
55
|
+
## Layout budget
|
|
56
|
+
|
|
57
|
+
| Constant | Value |
|
|
58
|
+
|----------|-------|
|
|
59
|
+
| viewBox | default `[920, 760]`; schema minimum `[480, 480]` |
|
|
60
|
+
| Participant boxes | `fixed` (default): 86×54 at y 72; `spread`: viewBox-relative width from 86px up to 190px |
|
|
61
|
+
| Participant columns | `fixed`: centers at x = 62 + index×108; `spread`: columns distribute across the available viewBox width |
|
|
62
|
+
| Participant count | the last box must end at or before width − 40; layouts that cannot fit fail closed |
|
|
63
|
+
| Lifelines | from y 142 down to height − 65; band must be ≥120px tall |
|
|
64
|
+
| Message `y` range | `[160, height − 83]` |
|
|
65
|
+
| Message spacing | ≥28px vertical between messages that share horizontal space |
|
|
66
|
+
| Arrow span | ≥60px horizontal between the two participants |
|
|
67
|
+
| Segments | y pixel ranges with `to > from`, inside `[72, lifeline bottom + 20]` |
|
|
68
|
+
| Legend row | y = height − 54 |
|
|
69
|
+
|
|
70
|
+
`segments[].from/to` and `activations[].from/to` are y pixel coordinates, not
|
|
71
|
+
participant ids; activations also require `to > from`.
|
|
72
|
+
|
|
73
|
+
### Column fit
|
|
74
|
+
|
|
75
|
+
Sequence diagrams use `meta.column_fit: "fixed"` by default so existing
|
|
76
|
+
documents keep their historical coordinates. Use `"spread"` when a wide
|
|
77
|
+
viewBox would otherwise leave empty space on the right or when meaningful
|
|
78
|
+
participant labels do not fit the fixed 86px boxes. Spread derives box width
|
|
79
|
+
and column distance from the viewBox while preserving participant order,
|
|
80
|
+
lifelines, and message semantics.
|
|
81
|
+
|
|
82
|
+
## Design Rules
|
|
83
|
+
|
|
84
|
+
- Put participants across the top, ordered by the story the reader should
|
|
85
|
+
follow.
|
|
86
|
+
- Time moves downward.
|
|
87
|
+
- Use `emphasis` for the main request path.
|
|
88
|
+
- Use `security` for auth, consent, permission, and policy calls.
|
|
89
|
+
- Use `return` for quiet response messages.
|
|
90
|
+
- Use `dashed` for async trace, event, logging, and non-blocking work.
|
|
91
|
+
- Use segments as light background guides; keep segment labels short.
|
|
92
|
+
- Keep labels concise, but try `meta.column_fit: "spread"` before shortening a
|
|
93
|
+
meaningful participant label just to fit the fixed boxes.
|
|
94
|
+
|
|
95
|
+
Schema violations exit non-zero with path-prefixed messages annotated with the
|
|
96
|
+
element's id or label. The renderer additionally fails when it can detect
|
|
97
|
+
layout problems, including missing participants, duplicate participant IDs,
|
|
98
|
+
participant labels wider than their box, unknown message endpoints, messages
|
|
99
|
+
outside the readable timeline, overly tight vertical spacing between messages
|
|
100
|
+
that overlap horizontally, invalid segment or activation ranges, or
|
|
101
|
+
participants that exceed the viewBox. The shared Clean Flow contract treats
|
|
102
|
+
participant headers as semantic boxes while explicitly allowing messages to
|
|
103
|
+
cross intermediate lifelines, activation bars, and segment frames. Text width is estimated CJK-aware:
|
|
104
|
+
fullwidth glyphs count as two units.
|
|
105
|
+
|
|
106
|
+
Set `meta.quality_profile` to `showcase` for polished delivery. Unrelated proper
|
|
107
|
+
message X crossings then fail with `composition/proper-crossing`; default
|
|
108
|
+
`standard` keeps them as artifact-receipt warnings. Messages may still cross
|
|
109
|
+
intermediate lifelines. Collinear corridors remain outside the proper-X rule,
|
|
110
|
+
but a separate gate warns in `standard` and fails in `showcase` when unrelated
|
|
111
|
+
messages overlap for at least 8px. Shared semantic endpoints, point touches,
|
|
112
|
+
and shorter overlaps remain valid. Showcase also rejects any route segment
|
|
113
|
+
below 8px and any interior turn segment below 16px; ordinary 8–15px endpoint
|
|
114
|
+
stubs remain valid.
|
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { esc, renderDefinitions, renderSemanticSigil, textUnits } from '../shared/utils.mjs';
|
|
4
|
+
import { animateAttr, focusEdgeAttrs, focusNodeAttrs, focusNodeTitle, loadDiagramWithBrandMarks, writeDiagram, svgAccessibleText, svgRootAttrs } from '../shared/cli.mjs';
|
|
5
|
+
import { throwDiagnosticProblems } from '../shared/diagnostics.mjs';
|
|
6
|
+
import { resolveLegend, renderLegend as renderResolvedLegend } from '../shared/legend.mjs';
|
|
7
|
+
import { componentFill, arrowClassMap, rectsOverlap, cleanFlowProblems, cleanCrossingProblems, cleanAmbiguousCorridorProblems, cleanBorderRunProblems, cleanRouteRhythmProblems, cleanLabelRouteClearanceProblems, routePointsValue, asArray, isFinitePoint } from '../shared/geometry.mjs';
|
|
8
|
+
import { availableNodeTextWidth, fittedNodeFontSize, minimumNodeTextWidth } from '../shared/text-fit.mjs';
|
|
9
|
+
import { brandLabelFitWidth, brandMetadataFor, brandTopRailProblem, renderBrandMark } from '../shared/brand-marks.mjs';
|
|
10
|
+
import { translateMessage as i18nText } from '../shared/i18n.mjs';
|
|
11
|
+
|
|
12
|
+
const participantTextFit = {
|
|
13
|
+
sublabelPreferred: 7,
|
|
14
|
+
sublabelMinimum: 6,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
const { diagram: sequence, template, outPath } = await loadDiagramWithBrandMarks({
|
|
19
|
+
rendererDir: __dirname,
|
|
20
|
+
diagramType: 'sequence',
|
|
21
|
+
defaultExample: 'cache-miss-request.sequence.json'
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const viewBox = sequence.meta?.viewBox || [920, 760];
|
|
25
|
+
// The timeline scales with viewBox height: a taller viewBox gains message room,
|
|
26
|
+
// a shorter one shrinks the readable band (validated below) instead of clipping.
|
|
27
|
+
// `column_fit: "spread"` widens the lanes with the viewBox instead of keeping
|
|
28
|
+
// the fixed 108px gap, so a wide canvas gains column distance and label room
|
|
29
|
+
// rather than dead space on the right. The default stays "fixed" so existing
|
|
30
|
+
// diagrams keep their coordinates.
|
|
31
|
+
const columnFit = sequence.meta?.column_fit === 'spread' ? 'spread' : 'fixed';
|
|
32
|
+
const participantCount = Math.max(1, asArray(sequence.participants).length);
|
|
33
|
+
const sideMargin = 62;
|
|
34
|
+
const participantW = columnFit === 'spread'
|
|
35
|
+
? Math.max(86, Math.min(190, Math.round((viewBox[0] - sideMargin * 2) / participantCount) - 24))
|
|
36
|
+
: 86;
|
|
37
|
+
const colGap = columnFit === 'spread' && participantCount > 1
|
|
38
|
+
? Math.max(108, (viewBox[0] - 40 - sideMargin - participantW) / (participantCount - 1))
|
|
39
|
+
: 108;
|
|
40
|
+
|
|
41
|
+
const layout = {
|
|
42
|
+
topY: 72,
|
|
43
|
+
participantW,
|
|
44
|
+
participantH: 54,
|
|
45
|
+
lifelineTop: 142,
|
|
46
|
+
lifelineBottom: viewBox[1] - 65,
|
|
47
|
+
legendY: viewBox[1] - 54,
|
|
48
|
+
leftX: columnFit === 'spread' ? sideMargin + participantW / 2 : sideMargin,
|
|
49
|
+
colGap,
|
|
50
|
+
labelH: 16
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const participantBoxWidthNote = columnFit === 'spread'
|
|
54
|
+
? `participant boxes are ${participantW}px for this viewBox width and ${participantCount} participants`
|
|
55
|
+
: `participant boxes are a fixed ${participantW}px unless meta.column_fit is "spread"`;
|
|
56
|
+
|
|
57
|
+
const arrowClass = {
|
|
58
|
+
...arrowClassMap,
|
|
59
|
+
return: ['a-default', 'arrowhead']
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function participantX(index) {
|
|
63
|
+
return layout.leftX + index * layout.colGap;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const participants = new Map(asArray(sequence.participants).map((participant, index) => [
|
|
67
|
+
participant.id,
|
|
68
|
+
{
|
|
69
|
+
...participant,
|
|
70
|
+
index,
|
|
71
|
+
cx: participantX(index),
|
|
72
|
+
x: participantX(index) - layout.participantW / 2,
|
|
73
|
+
y: layout.topY,
|
|
74
|
+
width: layout.participantW,
|
|
75
|
+
height: layout.participantH,
|
|
76
|
+
cy: layout.topY + layout.participantH / 2
|
|
77
|
+
}
|
|
78
|
+
]));
|
|
79
|
+
|
|
80
|
+
function messageGeometry(message) {
|
|
81
|
+
const from = participants.get(message.from);
|
|
82
|
+
const to = participants.get(message.to);
|
|
83
|
+
if (!from || !to || typeof message.y !== 'number') return null;
|
|
84
|
+
const direction = to.cx > from.cx ? 1 : -1;
|
|
85
|
+
const start = from.cx + direction * 7;
|
|
86
|
+
const end = to.cx - direction * 7;
|
|
87
|
+
return { start, end, center: (start + end) / 2 };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function messageLabelBox(message, relationIndex = null) {
|
|
91
|
+
const geometry = messageGeometry(message);
|
|
92
|
+
if (!geometry) return null;
|
|
93
|
+
const width = Math.max(34, textUnits(message.label) * 5.2 + 12);
|
|
94
|
+
return {
|
|
95
|
+
relation: message,
|
|
96
|
+
relationIndex,
|
|
97
|
+
label: message.label,
|
|
98
|
+
x: geometry.center - width / 2,
|
|
99
|
+
y: message.y - 20,
|
|
100
|
+
width,
|
|
101
|
+
height: layout.labelH,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function messageRouteBox(message) {
|
|
106
|
+
const geometry = messageGeometry(message);
|
|
107
|
+
if (!geometry) return null;
|
|
108
|
+
return {
|
|
109
|
+
x: Math.min(geometry.start, geometry.end),
|
|
110
|
+
y: message.y - 2,
|
|
111
|
+
width: Math.abs(geometry.end - geometry.start),
|
|
112
|
+
height: 4,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const compositionFrames = asArray(sequence.segments).map((segment, index) => ({
|
|
117
|
+
id: index,
|
|
118
|
+
label: segment.label,
|
|
119
|
+
kind: 'segment',
|
|
120
|
+
x: 48,
|
|
121
|
+
y: segment.from,
|
|
122
|
+
width: viewBox[0] - 96,
|
|
123
|
+
height: segment.to - segment.from,
|
|
124
|
+
radius: 10,
|
|
125
|
+
}));
|
|
126
|
+
|
|
127
|
+
function messagePath(message) {
|
|
128
|
+
return {
|
|
129
|
+
points: participants.has(message.from) && participants.has(message.to)
|
|
130
|
+
? [[participants.get(message.from).cx, message.y], [participants.get(message.to).cx, message.y]]
|
|
131
|
+
: []
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function validateSequence() {
|
|
136
|
+
const problems = [];
|
|
137
|
+
if (participants.size !== asArray(sequence.participants).length) problems.push('Participant ids must be unique.');
|
|
138
|
+
|
|
139
|
+
if (layout.lifelineBottom - layout.lifelineTop < 120) {
|
|
140
|
+
problems.push(`viewBox height ${viewBox[1]} leaves under 120px of timeline — set meta.viewBox[1] to at least ${layout.lifelineTop + 120 + 65}.`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
for (const participant of participants.values()) {
|
|
144
|
+
const estLabelW = textUnits(participant.label) * 6.8;
|
|
145
|
+
if (estLabelW > layout.participantW + 6) {
|
|
146
|
+
problems.push(`Label "${participant.label}" (~${Math.round(estLabelW)}px) is wider than the ${layout.participantW}px participant box — shorten it.`);
|
|
147
|
+
}
|
|
148
|
+
const brandRailProblem = brandTopRailProblem(participant, layout.participantW, 8, 'Participant');
|
|
149
|
+
if (brandRailProblem) problems.push(brandRailProblem);
|
|
150
|
+
// sublabel renders as a single unwrapped <text>; shrink-to-fit handles the
|
|
151
|
+
// ordinary case, this rejects what it cannot rescue.
|
|
152
|
+
if (participant.sublabel) {
|
|
153
|
+
const availableTextW = availableNodeTextWidth(layout.participantW);
|
|
154
|
+
const minimumW = minimumNodeTextWidth(participant.sublabel, participantTextFit.sublabelMinimum);
|
|
155
|
+
if (minimumW > availableTextW) {
|
|
156
|
+
problems.push(`Sublabel "${participant.sublabel}" needs ~${Math.ceil(minimumW)}px at the ${participantTextFit.sublabelMinimum}px legible minimum, but participant "${participant.id}" provides ${availableTextW}px — shorten the sublabel (${participantBoxWidthNote}).`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (const message of asArray(sequence.messages)) {
|
|
162
|
+
if (!participants.has(message.from)) problems.push(`Message "${message.label}" references unknown source "${message.from}".`);
|
|
163
|
+
if (!participants.has(message.to)) problems.push(`Message "${message.label}" references unknown target "${message.to}".`);
|
|
164
|
+
if (typeof message.y !== 'number') problems.push(`Message "${message.label}" must provide a numeric y.`);
|
|
165
|
+
if (message.y < layout.lifelineTop + 18 || message.y > layout.lifelineBottom - 18) {
|
|
166
|
+
problems.push(`Message "${message.label}" sits outside the readable timeline — keep y between ${layout.lifelineTop + 18} and ${layout.lifelineBottom - 18}.`);
|
|
167
|
+
}
|
|
168
|
+
if (participants.has(message.from) && participants.has(message.to)) {
|
|
169
|
+
const distance = Math.abs(participants.get(message.to).cx - participants.get(message.from).cx);
|
|
170
|
+
if (distance < 60) problems.push(`Message "${message.label}" spans ${Math.round(distance)}px (minimum 60px) — give its participants more column distance.`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Participant headers are opaque nodes. Lifelines, activation bars, and
|
|
175
|
+
// segment bands remain intentional pass-through geometry and are excluded.
|
|
176
|
+
problems.push(...cleanFlowProblems({
|
|
177
|
+
relations: sequence.messages,
|
|
178
|
+
obstacles: participants.values(),
|
|
179
|
+
pathFor: messagePath,
|
|
180
|
+
diagramType: 'sequence',
|
|
181
|
+
relationCollection: 'messages',
|
|
182
|
+
obstacleKind: 'participant header',
|
|
183
|
+
clearance: 0,
|
|
184
|
+
routeHint: 'move the message y below the participant headers or reorder participants'
|
|
185
|
+
}));
|
|
186
|
+
problems.push(...cleanCrossingProblems({
|
|
187
|
+
relations: sequence.messages,
|
|
188
|
+
endpointIds: new Set(participants.keys()),
|
|
189
|
+
pathFor: messagePath,
|
|
190
|
+
diagramType: 'sequence',
|
|
191
|
+
relationCollection: 'messages',
|
|
192
|
+
profile: sequence.meta?.quality_profile,
|
|
193
|
+
routeHint: 'separate the message y values; lifeline crossings remain allowed'
|
|
194
|
+
}));
|
|
195
|
+
problems.push(...cleanAmbiguousCorridorProblems({
|
|
196
|
+
relations: sequence.messages,
|
|
197
|
+
endpointIds: new Set(participants.keys()),
|
|
198
|
+
pathFor: messagePath,
|
|
199
|
+
diagramType: 'sequence',
|
|
200
|
+
relationCollection: 'messages',
|
|
201
|
+
profile: sequence.meta?.quality_profile,
|
|
202
|
+
routeHint: 'separate the message y values so unrelated messages do not visually merge'
|
|
203
|
+
}));
|
|
204
|
+
problems.push(...cleanBorderRunProblems({
|
|
205
|
+
relations: sequence.messages,
|
|
206
|
+
endpointIds: new Set(participants.keys()),
|
|
207
|
+
frames: compositionFrames,
|
|
208
|
+
pathFor: messagePath,
|
|
209
|
+
diagramType: 'sequence',
|
|
210
|
+
relationCollection: 'messages',
|
|
211
|
+
profile: sequence.meta?.quality_profile,
|
|
212
|
+
routeHint: 'move the message y so it crosses a segment boundary perpendicularly or stays clearly inside the segment'
|
|
213
|
+
}));
|
|
214
|
+
problems.push(...cleanRouteRhythmProblems({
|
|
215
|
+
relations: sequence.messages,
|
|
216
|
+
endpointIds: new Set(participants.keys()),
|
|
217
|
+
pathFor: messagePath,
|
|
218
|
+
diagramType: 'sequence',
|
|
219
|
+
relationCollection: 'messages',
|
|
220
|
+
profile: sequence.meta?.quality_profile,
|
|
221
|
+
routeHint: 'increase participant spacing or simplify message routing so every turn has room to read'
|
|
222
|
+
}));
|
|
223
|
+
|
|
224
|
+
// Vertical crowding only matters when the arrows share horizontal space;
|
|
225
|
+
// disjoint arrows may legitimately run in parallel rows.
|
|
226
|
+
const placed = asArray(sequence.messages)
|
|
227
|
+
.filter((m) => participants.has(m.from) && participants.has(m.to))
|
|
228
|
+
.map((m) => ({
|
|
229
|
+
label: m.label,
|
|
230
|
+
y: m.y,
|
|
231
|
+
x1: Math.min(participants.get(m.from).cx, participants.get(m.to).cx),
|
|
232
|
+
x2: Math.max(participants.get(m.from).cx, participants.get(m.to).cx)
|
|
233
|
+
}))
|
|
234
|
+
.sort((a, b) => a.y - b.y);
|
|
235
|
+
for (let i = 0; i < placed.length; i += 1) {
|
|
236
|
+
for (let j = i + 1; j < placed.length && placed[j].y - placed[i].y < 28; j += 1) {
|
|
237
|
+
if (placed[i].x1 < placed[j].x2 && placed[j].x1 < placed[i].x2) {
|
|
238
|
+
problems.push(`Messages "${placed[i].label}" and "${placed[j].label}" are less than 28px apart and share horizontal space — spread their y values.`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Label masks can extend well past the arrow span, so check the actual
|
|
244
|
+
// label rectangles too — tangent arrows with long labels still collide.
|
|
245
|
+
const labelRects = asArray(sequence.messages)
|
|
246
|
+
.map((m, messageIndex) => messageLabelBox(m, messageIndex))
|
|
247
|
+
.filter(Boolean);
|
|
248
|
+
for (let i = 0; i < labelRects.length; i += 1) {
|
|
249
|
+
for (let j = i + 1; j < labelRects.length; j += 1) {
|
|
250
|
+
if (rectsOverlap(labelRects[i], labelRects[j], -2)) {
|
|
251
|
+
problems.push(`Labels "${labelRects[i].label}" and "${labelRects[j].label}" overlap — spread their message y values or shorten the labels.`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
problems.push(...cleanLabelRouteClearanceProblems({
|
|
256
|
+
relations: sequence.messages,
|
|
257
|
+
labels: labelRects,
|
|
258
|
+
endpointIds: new Set(participants.keys()),
|
|
259
|
+
pathFor: messagePath,
|
|
260
|
+
diagramType: 'sequence',
|
|
261
|
+
relationCollection: 'messages',
|
|
262
|
+
profile: sequence.meta?.quality_profile,
|
|
263
|
+
routeHint: 'spread the message y values, shorten the label, or reorder participants so the adjacent route stays visible'
|
|
264
|
+
}));
|
|
265
|
+
|
|
266
|
+
for (const segment of asArray(sequence.segments)) {
|
|
267
|
+
if (segment.to <= segment.from) {
|
|
268
|
+
problems.push(`Segment "${segment.label}" has invalid y range (from ${segment.from} to ${segment.to}) — "to" must be greater than "from".`);
|
|
269
|
+
}
|
|
270
|
+
if (segment.from < layout.topY || segment.to > layout.lifelineBottom + 20) {
|
|
271
|
+
problems.push(`Segment "${segment.label}" extends outside the canvas — keep its y range between ${layout.topY} and ${layout.lifelineBottom + 20}.`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
for (const activation of asArray(sequence.activations)) {
|
|
276
|
+
if (!participants.has(activation.participant)) problems.push(`Activation references unknown participant "${activation.participant}".`);
|
|
277
|
+
if (activation.to <= activation.from) problems.push(`Activation for "${activation.participant}" has invalid time range — "to" must be greater than "from".`);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const lastParticipant = asArray(sequence.participants)[asArray(sequence.participants).length - 1];
|
|
281
|
+
if (lastParticipant && participants.get(lastParticipant.id).cx + layout.participantW / 2 > viewBox[0] - 40) {
|
|
282
|
+
const requiredWidth = Math.ceil(participants.get(lastParticipant.id).cx + layout.participantW / 2 + 40);
|
|
283
|
+
problems.push(`Participants exceed viewBox width — set meta.viewBox[0] to at least ${requiredWidth} or remove a participant.`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (problems.length) {
|
|
287
|
+
throwDiagnosticProblems('Sequence layout validation failed', problems, {
|
|
288
|
+
subject: { diagramType: 'sequence' },
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function renderParticipant(participant) {
|
|
294
|
+
const fill = componentFill[participant.type] || 'c-external';
|
|
295
|
+
const hasSub = participant.sublabel != null && participant.sublabel !== '';
|
|
296
|
+
const sub = hasSub
|
|
297
|
+
? `\n <text data-detail="context" x="${participant.cx}" y="${layout.topY + 39}" class="t-muted" font-size="${fittedNodeFontSize(participant.sublabel, layout.participantW, participantTextFit.sublabelPreferred, participantTextFit.sublabelMinimum)}" text-anchor="middle">${esc(participant.sublabel)}</text>`
|
|
298
|
+
: '';
|
|
299
|
+
const brand = renderBrandMark(participant, { x: participant.x + layout.participantW - 22, y: layout.topY + 6 });
|
|
300
|
+
const labelFontSize = fittedNodeFontSize(participant.label, brandLabelFitWidth(participant, layout.participantW), 11, 8);
|
|
301
|
+
const passport = {
|
|
302
|
+
kind: participant.type,
|
|
303
|
+
sublabel: participant.sublabel,
|
|
304
|
+
context: i18nText(sequence.meta.locale, 'node.context.sequence'),
|
|
305
|
+
...brandMetadataFor(participant),
|
|
306
|
+
};
|
|
307
|
+
return ` <g ${focusNodeAttrs(participant.id, participant.label, passport, sequence.meta.locale)}>
|
|
308
|
+
${focusNodeTitle(participant.label, passport)}
|
|
309
|
+
<rect x="${participant.x}" y="${layout.topY}" width="${layout.participantW}" height="${layout.participantH}" rx="6" class="c-mask"/>
|
|
310
|
+
<rect x="${participant.x}" y="${layout.topY}" width="${layout.participantW}" height="${layout.participantH}" rx="6" class="${fill}"${animateAttr(sequence.meta, 'node', participant.index)} stroke-width="1.5"/>
|
|
311
|
+
${renderSemanticSigil(participant.type, { x: participant.x + 6, y: layout.topY + 6 })}${brand ? `\n ${brand}` : ''}
|
|
312
|
+
<text data-node-label=""${hasSub ? ' data-detail-anchor=""' : ''} x="${participant.cx}" y="${layout.topY + 22}" class="t-primary" font-size="${labelFontSize}" font-weight="600" text-anchor="middle">${esc(participant.label)}</text>${sub}
|
|
313
|
+
</g>`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function renderLifeline(participant) {
|
|
317
|
+
return ` <path d="M ${participant.cx} ${layout.lifelineTop} L ${participant.cx} ${layout.lifelineBottom}" class="a-default" stroke-width="0.8" stroke-dasharray="3,7"/>`;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function renderSegment(segment, index) {
|
|
321
|
+
return ` <rect data-graph-role="structural-frame" data-composition-frame-kind="segment" data-composition-frame-id="${index}" x="48" y="${segment.from}" width="${viewBox[0] - 96}" height="${segment.to - segment.from}" rx="10" class="c-lane" stroke-width="1"/>`;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function renderSegmentLabel(segment, index) {
|
|
325
|
+
const labelW = Math.max(42, textUnits(segment.label) * 5.2 + 14);
|
|
326
|
+
const occupied = asArray(sequence.messages)
|
|
327
|
+
.flatMap((message) => [messageLabelBox(message), messageRouteBox(message)])
|
|
328
|
+
.filter(Boolean);
|
|
329
|
+
const label = { x: 56, y: segment.from - 22, width: labelW, height: 18 };
|
|
330
|
+
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
331
|
+
if (!occupied.some((rect) => rectsOverlap(label, rect, 2))) break;
|
|
332
|
+
label.y -= 22;
|
|
333
|
+
}
|
|
334
|
+
return ` <g data-graph-role="segment-label" data-segment-id="${index}">
|
|
335
|
+
<rect x="${label.x}" y="${label.y}" width="${label.width}" height="${label.height}" rx="3" class="c-mask"/>
|
|
336
|
+
<text x="${label.x + 6}" y="${label.y + 13}" class="t-dim" font-size="9" font-weight="600">${esc(segment.label)}</text>
|
|
337
|
+
</g>`;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function renderActivation(activation) {
|
|
341
|
+
const participant = participants.get(activation.participant);
|
|
342
|
+
const fill = componentFill[activation.type] || componentFill[participant.type] || 'c-external';
|
|
343
|
+
const x = participant.cx - 5;
|
|
344
|
+
const height = activation.to - activation.from;
|
|
345
|
+
return ` <rect x="${x}" y="${activation.from}" width="10" height="${height}" rx="3" class="c-mask"/>
|
|
346
|
+
<rect x="${x}" y="${activation.from}" width="10" height="${height}" rx="3" class="${fill}" stroke-width="1"/>`;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function messageLabel(message, x1, x2) {
|
|
350
|
+
const box = messageLabelBox(message);
|
|
351
|
+
const center = box ? box.x + box.width / 2 : (x1 + x2) / 2;
|
|
352
|
+
const y = message.y - 10;
|
|
353
|
+
const labelW = box?.width || Math.max(34, textUnits(message.label) * 5.2 + 12);
|
|
354
|
+
const accent = message.variant === 'security'
|
|
355
|
+
? 't-security'
|
|
356
|
+
: message.variant === 'dashed'
|
|
357
|
+
? 't-messagebus'
|
|
358
|
+
: message.variant === 'return'
|
|
359
|
+
? 't-muted'
|
|
360
|
+
: 't-backend';
|
|
361
|
+
return ` <g data-detail="context">
|
|
362
|
+
<rect x="${center - labelW / 2}" y="${y - 10}" width="${labelW}" height="${layout.labelH}" rx="3" class="c-mask"/>
|
|
363
|
+
<text x="${center}" y="${y}" class="${accent}" font-size="9" text-anchor="middle">${esc(message.label)}</text>
|
|
364
|
+
</g>`;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function renderMessage(message, index) {
|
|
368
|
+
const { start, end } = messageGeometry(message);
|
|
369
|
+
const [cls, marker] = arrowClass[message.variant || 'default'] || arrowClass.default;
|
|
370
|
+
const strokeWidth = message.variant === 'emphasis' ? 1.8 : 1.4;
|
|
371
|
+
const dash = message.variant === 'return' ? ' stroke-dasharray="3,5"' : '';
|
|
372
|
+
const note = message.note
|
|
373
|
+
? `\n <text data-detail="fine" x="${Math.min(start, end) + 12}" y="${message.y + 18}" class="t-dim" font-size="7">${esc(message.note)}</text>`
|
|
374
|
+
: '';
|
|
375
|
+
return ` <g ${focusEdgeAttrs(message.from, message.to, message.label, index, message.id)}>
|
|
376
|
+
<path data-composition-edge-from="${esc(message.from)}" data-composition-edge-to="${esc(message.to)}"${message.id ? ` data-composition-edge-id="${esc(message.id)}"` : ''} data-composition-points="${routePointsValue([[start, message.y], [end, message.y]])}" d="M ${start} ${message.y} L ${end} ${message.y}" class="${cls}"${animateAttr(sequence.meta, 'edge', index)} stroke-width="${strokeWidth}"${dash} marker-end="url(#${marker})"/>
|
|
377
|
+
${messageLabel(message, start, end)}${note}
|
|
378
|
+
</g>`;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const LEGEND_CATALOG = [
|
|
382
|
+
{ kind: 'emphasis', className: 'a-emphasis', marker: 'arrowhead-emphasis', strokeWidth: 1.8 },
|
|
383
|
+
{ kind: 'return', className: 'a-default', marker: 'arrowhead', dash: '3,5' },
|
|
384
|
+
{ kind: 'security', className: 'a-security', marker: 'arrowhead-security' },
|
|
385
|
+
{ kind: 'dashed', className: 'a-dashed', marker: 'arrowhead-dashed' },
|
|
386
|
+
{ kind: 'default', className: 'a-default', marker: 'arrowhead' },
|
|
387
|
+
].map((entry) => ({
|
|
388
|
+
...entry,
|
|
389
|
+
interactive: false,
|
|
390
|
+
swatchWidth: 34,
|
|
391
|
+
swatchGap: 9,
|
|
392
|
+
label: i18nText(sequence.meta.locale, `legend.sequence.${entry.kind}`),
|
|
393
|
+
}));
|
|
394
|
+
|
|
395
|
+
function renderLegend() {
|
|
396
|
+
const presentKinds = new Set(asArray(sequence.messages).map((message) => message.variant || 'default'));
|
|
397
|
+
const entries = resolveLegend(sequence.meta?.legend, LEGEND_CATALOG, presentKinds);
|
|
398
|
+
return renderResolvedLegend({
|
|
399
|
+
entries,
|
|
400
|
+
locale: sequence.meta.locale,
|
|
401
|
+
layout: {
|
|
402
|
+
x: 40,
|
|
403
|
+
baselineY: layout.legendY,
|
|
404
|
+
width: viewBox[0] - 80,
|
|
405
|
+
minTitleY: layout.legendY - 30,
|
|
406
|
+
unfit: sequence.meta?.legend === undefined ? 'hide' : 'error',
|
|
407
|
+
diagramType: 'sequence',
|
|
408
|
+
},
|
|
409
|
+
renderSwatch: (entry) => `<path d="M ${entry.x} ${entry.baseline - 3} L ${entry.x + 34} ${entry.baseline - 3}" class="${entry.className}" stroke-width="${entry.strokeWidth || 1.4}"${entry.dash ? ` stroke-dasharray="${entry.dash}"` : ''} marker-end="url(#${entry.marker})"/>`,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function renderSvg() {
|
|
414
|
+
const participantList = [...participants.values()];
|
|
415
|
+
return ` <svg viewBox="0 0 ${viewBox[0]} ${viewBox[1]}" ${svgRootAttrs(sequence.meta)}>
|
|
416
|
+
${svgAccessibleText(sequence.meta, 'sequence')}
|
|
417
|
+
${renderDefinitions()}
|
|
418
|
+
|
|
419
|
+
<!-- Background Grid -->
|
|
420
|
+
<rect width="100%" height="100%" fill="url(#grid)" />
|
|
421
|
+
|
|
422
|
+
<!-- Time Segments -->
|
|
423
|
+
${asArray(sequence.segments).map(renderSegment).join('\n\n')}
|
|
424
|
+
|
|
425
|
+
<!-- Lifelines -->
|
|
426
|
+
${participantList.map(renderLifeline).join('\n')}
|
|
427
|
+
|
|
428
|
+
<!-- Activations -->
|
|
429
|
+
${asArray(sequence.activations).map(renderActivation).join('\n')}
|
|
430
|
+
|
|
431
|
+
<!-- Messages -->
|
|
432
|
+
${asArray(sequence.messages).map(renderMessage).join('\n\n')}
|
|
433
|
+
|
|
434
|
+
<!-- Segment Labels -->
|
|
435
|
+
${asArray(sequence.segments).map(renderSegmentLabel).join('\n')}
|
|
436
|
+
|
|
437
|
+
<!-- Participants -->
|
|
438
|
+
${participantList.map(renderParticipant).join('\n\n')}
|
|
439
|
+
|
|
440
|
+
<!-- Legend -->
|
|
441
|
+
${renderLegend()}
|
|
442
|
+
</svg>`;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
validateSequence();
|
|
446
|
+
writeDiagram({
|
|
447
|
+
outPath,
|
|
448
|
+
template,
|
|
449
|
+
diagramType: 'sequence',
|
|
450
|
+
meta: sequence.meta,
|
|
451
|
+
svg: renderSvg(),
|
|
452
|
+
cards: sequence.cards,
|
|
453
|
+
});
|