Claude Cursor Skill

archify

Create polished, validated architecture, workflow, sequence, data-flow, and lifecycle/state diagrams as explorable standalone HTML with inline SVG, dark/light themes, optional trace motion, and PNG/JPEG/WebP/SVG/WebM export. Accept plain-language requirements or pasted Mermaid fl

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download runkids-my-skills-archify-7f33dbc.zip · 2557 KB
Part of runkids/my-skills — 13 skills

Install

skills CLI npx skills add https://github.com/runkids/my-skills/tree/main/archify
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install runkids-my-skills@llmmart
Git git clone https://github.com/runkids/my-skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole runkids/my-skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Archify

Create an interactive HTML diagram from typed JSON. Static output is the default; enable motion only when requested.

Run commands from your working directory. Unless the user names another location, give each new diagram request its own folder .archify/<type>-<slug>-<YYYYMMDD-HHMMSS>/ there (local time, chosen once when the request starts): keep candidate.json and <slug>.html in it, set meta.output to that relative HTML path, and reuse the folder for every repair rerun. A later request gets a new folder, so earlier versions stay intact. Replace bin/archify.mjs in the commands below with the installed package's absolute path, or its path relative to your working directory; input and output paths resolve from that working directory.

For a real codebase, read Repository authoring while tracing the requested behavior. A system description uses the steps below; an existing JSON uses the handoff path.

Existing candidate handoff

When the user supplies a frozen candidate, run finalize first as one CLI invocation. Its passing receipt completes the automated gates; follow any visual review recommendation under Delivery before claiming visual quality. For repair, follow step 5.

finalize includes a bounded update check in its delivery receipt; see Update awareness.

Fast authoring path

Use this path for ordinary generation. Read branch references only when their stated trigger applies.

  1. Choose architecture, workflow, sequence, dataflow, or lifecycle from the question.

  2. Use the exact schema and example paths in the Type router without listing their directories. Read Authoring defaults and the mode's example in a bounded batch separate from project documents and complete schemas so neither is truncated; recover any missing section before writing. For Architecture, use the matching showcase example. For Sequence, Dataflow, and Lifecycle, also read the mode and common schemas. Read the relevant schema definition before choosing any new field, enum, or constrained text, especially boundary kinds. Examples teach shape, not facts. Use fresh IDs, wording, and layout. Go directly to the candidate without preliminary help, doctor, starter validation, temporary diagrams, or output-path listing. Query brands only for an explicitly requested mark; read Brand marks for an unknown mark with a user-provided URL.

  3. Once the requested scope and, for a real codebase, source evidence are covered, write the complete candidate directly without planning coordinates in prose. Choose Architecture abstraction and connected placement using Authoring defaults before coordinates: show the main user journey and necessary branches, preserve control roles and behavior-changing conditions, and leave enough room for actual relationship labels. No node, relationship, source, view, card, or boundary count is a target or ceiling. Use automatic routes first; add explicit routing only for necessary branch, return, supplied geometry, or measured repair. Set meta.quality_profile to "showcase" unless the user requests dense standard.

  4. Once the complete first candidate is written, run finalize directly. Its first gate is showcase validation; successful first drafts need no separate pre-validation. Keep the candidate unchanged while the command runs:

    node bin/archify.mjs finalize <type> <candidate.json> <output.html> --quality showcase --json
    

    For a repository-backed candidate, include evidence on the first draft and use the complete first command: node bin/archify.mjs finalize <type> <candidate.json> <output.html> --repo-root <repo-root> --quality showcase --json.

    A passing receipt proves the included validate, deliver, strict check, and real-browser browser-check gates passed. Use its compact summary; run standalone commands only for a separate request or focused failure diagnosis.

  5. A non-zero exit is never success. Read compact stdout or evidence.summaryReceipt, then repair the failed gate, including its repair limit. Preserve requested meaning and source evidence. For several tangled Architecture routes, read Architecture layout repair; for measured field or geometry failures, read Authoring contract. Edit the connected neighborhood and rerun the complete finalize command from step 4.

Update awareness

finalize and standalone deliver include update in their receipts. Do not run a separate check for the same delivery. If update.noticeRequired is true, read references/update-awareness.md and keep one update line in your final response to the user, even after a quality gate fails. For a task with several diagrams, mention the update once in the final response. Snooze or ignore a reminder only when the user explicitly asks; never install or update on your own initiative.

Before the first candidate, use the authoring references and relevant repository source, not Archify implementation or tests. Inspect Archify implementation if diagnostics remain unactionable after focused repairs.

Type router

Type Use for Schema Example
architecture Components, services, cloud/security boundaries, infrastructure schemas/architecture.schema.json System descriptions, services, libraries, and CLI repos: examples/web-app.architecture.json; deployment repos: examples/production-deployment.architecture.json
workflow Processes, approval gates, tool calls, runbooks, CI/CD schemas/workflow.schema.json examples/agent-tool-call.workflow.json
sequence API call chains, request lifecycles, async traces, returns schemas/sequence.schema.json examples/cache-miss-request.sequence.json
dataflow Pipelines, ETL/ELT, lineage, governance, consumers schemas/dataflow.schema.json examples/product-analytics.dataflow.json
lifecycle State/status transitions, retries, waiting and terminal states schemas/lifecycle.schema.json examples/deployment-release.lifecycle.json

When ambiguous, run node bin/archify.mjs guide "<scenario>" --json. Scenario proof examples are structural references, not facts to copy.

Mermaid input

Read Mermaid for topology and meaning, then author fresh Archify JSON; do not mechanically render Mermaid styling.

  • flowchart / graph → workflow, or architecture for a component map.
  • sequenceDiagram → sequence; participants become semantic participants and arrows become messages.
  • stateDiagram → lifecycle; states and transitions retain meaning, not Mermaid style.

Delivery

Use the finalize command above for the first candidate and after a repair.

finalize stops at the first non-passing gate. Its compact stdout and <output-stem>.finalize-summary.json are ordinary evidence. A passing run creates no screenshots and reports visualReview: "not-requested".

When a passing Architecture receipt reports visualReviewRecommendation.signals.resolvedCrossovers, copy the candidate aside and apply the hints in one edit that changes only node positions and sizes: every node, relationship (including its from and to), label, and source stays as it was. Rerun the complete finalize once with --out-dir <folder>/review-2, because the previous HTML already owns its browser evidence. If that run fails or reports more crossings, restore the copy and finalize it with --out-dir <folder>/review-3. Do not start a second placement round. Hints about extra bends alone are optional.

When layoutReviewRecommendation.action is inspect-sequence-width, follow Sequence width review before handing off a newly authored Sequence.

Perceptual review is optional for ordinary generation, including a newly positioned Architecture. Use Optional capture evidence, with --out-dir <folder>/visual-check, when the user requests visual review, during development audits, or for a concrete route/browser concern. visualReviewRecommendation is advisory. Inspect captures before claiming visual quality; otherwise report automated checks only.

Read Delivery contract for failed gates, standalone commands, provenance/recovery, repeated delivery, exports, or opening. Recovery follows deliver → strict provenance check → browser-check; captures require strict provenance.

For workflow viewport overflow, read Workflow viewport repair before the next layout edit.

Report artifact checks, browser evidence, captures, and actual perceptual review as distinct results. For an explicitly requested immediate preview or active desktop loop, see Optional opening.

Optional viewer capabilities

meta.animation: "trace" is opt-in.

Read references/viewer-runtime.md only when the user explicitly asks for Share Cards, Route/Reach cards, motion, deep links, presentation, search/focus, or another Viewer Runtime feature.

Setup and fallback

No install is required inside the skill package. For setup diagnosis, verify with:

node bin/archify.mjs doctor
node bin/archify.mjs demo <output-directory>

When shell access is unavailable, hand-place architecture SVG into assets/template.html, use CSS semantic classes rather than inline colors, and follow the visual review contract in references/delivery-contract.md.

Output

Return the checked HTML as an absolute path, diagram type, validation summary, specification/artifact receipt, browser-evidence status, and truthful visual-review status. Do not claim success for a non-zero command or claim visual inspection you did not perform.

Files (my-skills)
  • assets
    • JetBrainsMono-OFL.txt 4.3 KB
      Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
      
      This Font Software is licensed under the SIL Open Font License, Version 1.1.
      This license is copied below, and is also available with a FAQ at:
      https://openfontlicense.org
      
      
      -----------------------------------------------------------
      SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
      -----------------------------------------------------------
      
      PREAMBLE
      The goals of the Open Font License (OFL) are to stimulate worldwide
      development of collaborative font projects, to support the font creation
      efforts of academic and linguistic communities, and to provide a free and
      open framework in which fonts may be shared and improved in partnership
      with others.
      
      The OFL allows the licensed fonts to be used, studied, modified and
      redistributed freely as long as they are not sold by themselves. The
      fonts, including any derivative works, can be bundled, embedded,
      redistributed and/or sold with any software provided that any reserved
      names are not used by derivative works. The fonts and derivatives,
      however, cannot be released under any other type of license. The
      requirement for fonts to remain under this license does not apply
      to any document created using the fonts or their derivatives.
      
      DEFINITIONS
      "Font Software" refers to the set of files released by the Copyright
      Holder(s) under this license and clearly marked as such. This may
      include source files, build scripts and documentation.
      
      "Reserved Font Name" refers to any names specified as such after the
      copyright statement(s).
      
      "Original Version" refers to the collection of Font Software components as
      distributed by the Copyright Holder(s).
      
      "Modified Version" refers to any derivative made by adding to, deleting,
      or substituting -- in part or in whole -- any of the components of the
      Original Version, by changing formats or by porting the Font Software to a
      new environment.
      
      "Author" refers to any designer, engineer, programmer, technical
      writer or other person who contributed to the Font Software.
      
      PERMISSION & CONDITIONS
      Permission is hereby granted, free of charge, to any person obtaining
      a copy of the Font Software, to use, study, copy, merge, embed, modify,
      redistribute, and sell modified and unmodified copies of the Font
      Software, subject to the following conditions:
      
      1) Neither the Font Software nor any of its individual components,
      in Original or Modified Versions, may be sold by itself.
      
      2) Original or Modified Versions of the Font Software may be bundled,
      redistributed and/or sold with any software, provided that each copy
      contains the above copyright notice and this license. These can be
      included either as stand-alone text files, human-readable headers or
      in the appropriate machine-readable metadata fields within text or
      binary files as long as those fields can be easily viewed by the user.
      
      3) No Modified Version of the Font Software may use the Reserved Font
      Name(s) unless explicit written permission is granted by the corresponding
      Copyright Holder. This restriction only applies to the primary font name as
      presented to the users.
      
      4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
      Software shall not be used to promote, endorse or advertise any
      Modified Version, except to acknowledge the contribution(s) of the
      Copyright Holder(s) and the Author(s) or with their explicit written
      permission.
      
      5) The Font Software, modified or unmodified, in part or in whole,
      must be distributed entirely under this license, and must not be
      distributed under any other license. The requirement for fonts to
      remain under this license does not apply to any document created
      using the Font Software.
      
      TERMINATION
      This license becomes null and void if any of the above conditions are
      not met.
      
      DISCLAIMER
      THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
      OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
      COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
      DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
      OTHER DEALINGS IN THE FONT SOFTWARE.
      
    • template.html 710.9 KB · in bundle
  • bin
    • archify.mjs 260.8 KB · in bundle
    • delivery-update.mjs 3.6 KB · in bundle
    • finalize.mjs 39.4 KB · in bundle
    • open-artifact.mjs 4 KB · in bundle
    • preview.mjs 35.7 KB · in bundle
    • recover-output.mjs 1.3 KB · in bundle
    • visual-check.mjs 110.3 KB · in bundle
  • brand-marks
    • catalog.json 13.8 KB
      {
        "schemaVersion": 1,
        "marks": [
          {
            "id": "openai",
            "title": "OpenAI",
            "category": "ai",
            "aliases": ["chatgpt", "gpt", "codex"],
            "domains": ["openai.com", "chatgpt.com"],
            "custom": {
              "viewBox": 20,
              "hex": "000000",
              "path": "M11.248 18.25q-.825 0-1.568-.314a4.3 4.3 0 0 1-1.32-.874 4 4 0 0 1-1.304.214 4 4 0 0 1-2.046-.544 4.27 4.27 0 0 1-1.518-1.485 4 4 0 0 1-.56-2.095q0-.48.131-1.04A4.4 4.4 0 0 1 2.04 10.71a4.07 4.07 0 0 1 .017-3.4 4.2 4.2 0 0 1 1.056-1.418 3.8 3.8 0 0 1 1.6-.842 3.9 3.9 0 0 1 .76-1.683q.593-.759 1.451-1.188a4.04 4.04 0 0 1 1.832-.429q.825 0 1.567.313.742.314 1.32.875a4 4 0 0 1 1.304-.215q1.106 0 2.046.545a4.14 4.14 0 0 1 1.501 1.485q.578.941.578 2.095 0 .48-.132 1.04.66.61 1.023 1.419.363.792.363 1.666 0 .892-.38 1.717a4.3 4.3 0 0 1-1.072 1.435 3.8 3.8 0 0 1-1.584.825 3.8 3.8 0 0 1-.775 1.683 4.06 4.06 0 0 1-1.436 1.188 4.04 4.04 0 0 1-1.832.429m-4.076-2.062q.825 0 1.435-.347l3.103-1.782a.36.36 0 0 0 .164-.313v-1.42L7.881 14.62a.67.67 0 0 1-.726 0l-3.118-1.798a.5.5 0 0 1-.017.115v.198q0 .841.396 1.551.413.693 1.139 1.089a3.2 3.2 0 0 0 1.617.412m.165-2.69a.4.4 0 0 0 .181.05q.083 0 .165-.05l1.238-.71-3.977-2.31a.7.7 0 0 1-.363-.643v-3.58q-.825.362-1.32 1.122a2.9 2.9 0 0 0-.495 1.65q0 .809.413 1.55.412.743 1.072 1.123zm3.91 3.663q.875 0 1.585-.396a2.96 2.96 0 0 0 1.534-2.64v-3.564a.32.32 0 0 0-.165-.297l-1.254-.726v4.604a.7.7 0 0 1-.363.643l-3.119 1.799a3 3 0 0 0 1.783.577m.627-6.039V8.878L10.01 7.822 8.129 8.878v2.244l1.881 1.056zM7.057 5.859a.7.7 0 0 1 .363-.644l3.119-1.798a3 3 0 0 0-1.782-.578q-.874 0-1.584.396A2.96 2.96 0 0 0 6.05 4.324a3.07 3.07 0 0 0-.396 1.551v3.547q0 .199.165.314l1.237.726zm8.383 7.887q.825-.364 1.303-1.123.495-.758.495-1.65a3.15 3.15 0 0 0-.412-1.55q-.413-.743-1.073-1.123l-3.086-1.782q-.099-.065-.181-.049a.3.3 0 0 0-.165.05l-1.238.692 3.993 2.327a.6.6 0 0 1 .264.264.64.64 0 0 1 .1.363zm-3.317-8.382a.63.63 0 0 1 .726 0l3.135 1.831v-.297q0-.792-.396-1.501a2.86 2.86 0 0 0-1.105-1.155q-.71-.43-1.65-.43-.825 0-1.436.347L8.294 5.941a.36.36 0 0 0-.165.314v1.418z",
              "source": "https://openai.com/brand/",
              "guidelines": "https://openai.com/brand/"
            }
          },
          { "id": "claude", "category": "ai", "simpleIcon": "claude", "aliases": ["claude-ai"], "domains": ["claude.ai"] },
          { "id": "anthropic", "category": "ai", "simpleIcon": "anthropic", "domains": ["anthropic.com"] },
          { "id": "google-gemini", "category": "ai", "simpleIcon": "googlegemini", "aliases": ["gemini"], "domains": ["gemini.google.com"] },
          { "id": "deepseek", "category": "ai", "simpleIcon": "deepseek", "domains": ["deepseek.com"] },
          { "id": "qwen", "category": "ai", "simpleIcon": "qwen", "domains": ["qwen.ai"] },
          { "id": "meta", "category": "ai", "simpleIcon": "meta", "aliases": ["llama"], "domains": ["meta.com"] },
          { "id": "mistral-ai", "category": "ai", "simpleIcon": "mistralai", "aliases": ["mistral"], "domains": ["mistral.ai"] },
          { "id": "hugging-face", "category": "ai", "simpleIcon": "huggingface", "aliases": ["huggingface"], "domains": ["huggingface.co"] },
          { "id": "ollama", "category": "ai", "simpleIcon": "ollama", "domains": ["ollama.com"] },
          { "id": "openrouter", "category": "ai", "simpleIcon": "openrouter", "aliases": ["open-router"], "domains": ["openrouter.ai"] },
          { "id": "perplexity", "category": "ai", "simpleIcon": "perplexity", "domains": ["perplexity.ai"] },
          { "id": "replicate", "category": "ai", "simpleIcon": "replicate", "domains": ["replicate.com"] },
      
          { "id": "google-cloud", "category": "cloud", "simpleIcon": "googlecloud", "aliases": ["gcp", "googlecloud"], "domains": ["cloud.google.com"] },
          { "id": "cloudflare", "category": "cloud", "simpleIcon": "cloudflare", "domains": ["cloudflare.com"] },
          { "id": "vercel", "category": "cloud", "simpleIcon": "vercel", "domains": ["vercel.com"] },
          { "id": "netlify", "category": "cloud", "simpleIcon": "netlify", "domains": ["netlify.com"] },
          { "id": "digitalocean", "category": "cloud", "simpleIcon": "digitalocean", "aliases": ["digital-ocean"], "domains": ["digitalocean.com"] },
          { "id": "render", "category": "cloud", "simpleIcon": "render", "domains": ["render.com"] },
          { "id": "railway", "category": "cloud", "simpleIcon": "railway", "domains": ["railway.com", "railway.app"] },
          { "id": "fly-io", "category": "cloud", "simpleIcon": "flydotio", "aliases": ["fly.io"], "domains": ["fly.io"] },
          { "id": "cloudinary", "category": "cloud", "simpleIcon": "cloudinary", "domains": ["cloudinary.com"] },
          { "id": "alibaba-cloud", "category": "cloud", "simpleIcon": "alibabacloud", "aliases": ["aliyun"], "domains": ["alibabacloud.com", "aliyun.com"] },
          { "id": "firebase", "category": "cloud", "simpleIcon": "firebase", "domains": ["firebase.google.com"] },
          { "id": "supabase", "category": "cloud", "simpleIcon": "supabase", "domains": ["supabase.com"] },
          { "id": "neon", "category": "cloud", "simpleIcon": "neon", "domains": ["neon.tech"] },
      
          { "id": "github", "category": "engineering", "simpleIcon": "github", "domains": ["github.com"] },
          { "id": "gitlab", "category": "engineering", "simpleIcon": "gitlab", "domains": ["gitlab.com"] },
          { "id": "bitbucket", "category": "engineering", "simpleIcon": "bitbucket", "domains": ["bitbucket.org"] },
          { "id": "docker", "category": "engineering", "simpleIcon": "docker", "domains": ["docker.com"] },
          { "id": "kubernetes", "category": "engineering", "simpleIcon": "kubernetes", "aliases": ["k8s"], "domains": ["kubernetes.io"] },
          { "id": "terraform", "category": "engineering", "simpleIcon": "terraform", "domains": ["terraform.io"] },
          { "id": "pulumi", "category": "engineering", "simpleIcon": "pulumi", "domains": ["pulumi.com"] },
          { "id": "ansible", "category": "engineering", "simpleIcon": "ansible", "domains": ["ansible.com"] },
          { "id": "jenkins", "category": "engineering", "simpleIcon": "jenkins", "domains": ["jenkins.io"] },
          { "id": "circleci", "category": "engineering", "simpleIcon": "circleci", "aliases": ["circle-ci"], "domains": ["circleci.com"] },
          { "id": "github-actions", "category": "engineering", "simpleIcon": "githubactions" },
          { "id": "argo", "category": "engineering", "simpleIcon": "argo", "aliases": ["argocd", "argo-cd"], "domains": ["argoproj.github.io"] },
          { "id": "helm", "category": "engineering", "simpleIcon": "helm", "domains": ["helm.sh"] },
          { "id": "grafana", "category": "engineering", "simpleIcon": "grafana", "domains": ["grafana.com"] },
          { "id": "prometheus", "category": "engineering", "simpleIcon": "prometheus", "domains": ["prometheus.io"] },
          { "id": "sentry", "category": "engineering", "simpleIcon": "sentry", "domains": ["sentry.io"] },
          { "id": "datadog", "category": "engineering", "simpleIcon": "datadog", "domains": ["datadoghq.com"] },
          { "id": "pagerduty", "category": "engineering", "simpleIcon": "pagerduty", "aliases": ["pager-duty"], "domains": ["pagerduty.com"] },
      
          { "id": "postgresql", "category": "data", "simpleIcon": "postgresql", "aliases": ["postgres"], "domains": ["postgresql.org"] },
          { "id": "mysql", "category": "data", "simpleIcon": "mysql", "domains": ["mysql.com"] },
          { "id": "mongodb", "category": "data", "simpleIcon": "mongodb", "aliases": ["mongo"], "domains": ["mongodb.com"] },
          { "id": "redis", "category": "data", "simpleIcon": "redis", "domains": ["redis.io"] },
          { "id": "apache-kafka", "category": "data", "simpleIcon": "apachekafka", "aliases": ["kafka"], "domains": ["kafka.apache.org"] },
          { "id": "rabbitmq", "category": "data", "simpleIcon": "rabbitmq", "aliases": ["rabbit-mq"], "domains": ["rabbitmq.com"] },
          { "id": "clickhouse", "category": "data", "simpleIcon": "clickhouse", "domains": ["clickhouse.com"] },
          { "id": "elasticsearch", "category": "data", "simpleIcon": "elasticsearch", "aliases": ["elastic"], "domains": ["elastic.co"] },
          { "id": "opensearch", "category": "data", "simpleIcon": "opensearch", "aliases": ["open-search"], "domains": ["opensearch.org"] },
          { "id": "snowflake", "category": "data", "simpleIcon": "snowflake", "domains": ["snowflake.com"] },
          { "id": "databricks", "category": "data", "simpleIcon": "databricks", "domains": ["databricks.com"] },
          { "id": "planetscale", "category": "data", "simpleIcon": "planetscale", "aliases": ["planet-scale"], "domains": ["planetscale.com"] },
          { "id": "prisma", "category": "data", "simpleIcon": "prisma", "domains": ["prisma.io"] },
          { "id": "sqlite", "category": "data", "simpleIcon": "sqlite", "domains": ["sqlite.org"] },
          { "id": "mariadb", "category": "data", "simpleIcon": "mariadb", "aliases": ["maria-db"], "domains": ["mariadb.org"] },
          { "id": "influxdb", "category": "data", "simpleIcon": "influxdb", "aliases": ["influx-db"], "domains": ["influxdata.com"] },
          { "id": "apache-airflow", "category": "data", "simpleIcon": "apacheairflow", "aliases": ["airflow"], "domains": ["airflow.apache.org"] },
      
          { "id": "notion", "category": "collaboration", "simpleIcon": "notion", "domains": ["notion.so"] },
          { "id": "figma", "category": "collaboration", "simpleIcon": "figma", "domains": ["figma.com"] },
          { "id": "jira", "category": "collaboration", "simpleIcon": "jira", "domains": ["atlassian.com"] },
          { "id": "linear", "category": "collaboration", "simpleIcon": "linear", "domains": ["linear.app"] },
          { "id": "discord", "category": "collaboration", "simpleIcon": "discord", "domains": ["discord.com"] },
          { "id": "zoom", "category": "collaboration", "simpleIcon": "zoom", "domains": ["zoom.us"] },
          { "id": "trello", "category": "collaboration", "simpleIcon": "trello", "domains": ["trello.com"] },
          { "id": "asana", "category": "collaboration", "simpleIcon": "asana", "domains": ["asana.com"] },
          { "id": "airtable", "category": "collaboration", "simpleIcon": "airtable", "domains": ["airtable.com"] },
          { "id": "miro", "category": "collaboration", "simpleIcon": "miro", "domains": ["miro.com"] },
          { "id": "stripe", "category": "business", "simpleIcon": "stripe", "domains": ["stripe.com"] },
          { "id": "shopify", "category": "business", "simpleIcon": "shopify", "domains": ["shopify.com"] },
          { "id": "hubspot", "category": "business", "simpleIcon": "hubspot", "domains": ["hubspot.com"] },
          { "id": "paypal", "category": "business", "simpleIcon": "paypal", "domains": ["paypal.com"] },
          { "id": "intercom", "category": "business", "simpleIcon": "intercom", "domains": ["intercom.com"] },
          { "id": "zendesk", "category": "business", "simpleIcon": "zendesk", "domains": ["zendesk.com"] },
          { "id": "wordpress", "category": "business", "simpleIcon": "wordpress", "domains": ["wordpress.org", "wordpress.com"] },
          { "id": "woocommerce", "category": "business", "simpleIcon": "woocommerce", "aliases": ["woo-commerce"], "domains": ["woocommerce.com"] },
      
          { "id": "wechat", "category": "channel", "simpleIcon": "wechat", "aliases": ["weixin", "微信"], "domains": ["weixin.qq.com"] },
          { "id": "youtube", "category": "channel", "simpleIcon": "youtube", "domains": ["youtube.com", "youtu.be"] },
          { "id": "tiktok", "category": "channel", "simpleIcon": "tiktok", "aliases": ["douyin", "抖音"], "domains": ["tiktok.com", "douyin.com"] },
          { "id": "x", "category": "channel", "simpleIcon": "x", "aliases": ["twitter"], "domains": ["x.com", "twitter.com"] },
          { "id": "instagram", "category": "channel", "simpleIcon": "instagram", "domains": ["instagram.com"] },
          { "id": "facebook", "category": "channel", "simpleIcon": "facebook", "domains": ["facebook.com"] },
          { "id": "reddit", "category": "channel", "simpleIcon": "reddit", "domains": ["reddit.com"] },
          { "id": "telegram", "category": "channel", "simpleIcon": "telegram", "domains": ["telegram.org", "t.me"] },
          { "id": "whatsapp", "category": "channel", "simpleIcon": "whatsapp", "domains": ["whatsapp.com"] },
          { "id": "pinterest", "category": "channel", "simpleIcon": "pinterest", "domains": ["pinterest.com"] },
      
          { "id": "python", "category": "language", "simpleIcon": "python", "domains": ["python.org"] },
          { "id": "typescript", "category": "language", "simpleIcon": "typescript", "aliases": ["ts"], "domains": ["typescriptlang.org"] },
          { "id": "javascript", "category": "language", "simpleIcon": "javascript", "aliases": ["js"] },
          { "id": "go", "category": "language", "simpleIcon": "go", "aliases": ["golang"], "domains": ["go.dev"] },
          { "id": "rust", "category": "language", "simpleIcon": "rust", "domains": ["rust-lang.org"] },
          { "id": "node-js", "category": "framework", "simpleIcon": "nodedotjs", "aliases": ["node", "nodejs"], "domains": ["nodejs.org"] },
          { "id": "react", "category": "framework", "simpleIcon": "react", "aliases": ["reactjs"], "domains": ["react.dev"] },
          { "id": "vue", "category": "framework", "simpleIcon": "vuedotjs", "aliases": ["vuejs", "vue.js"], "domains": ["vuejs.org"] },
          { "id": "next-js", "category": "framework", "simpleIcon": "nextdotjs", "aliases": ["nextjs", "next.js"], "domains": ["nextjs.org"] },
          { "id": "pytorch", "category": "framework", "simpleIcon": "pytorch", "domains": ["pytorch.org"] },
          { "id": "tensorflow", "category": "framework", "simpleIcon": "tensorflow", "domains": ["tensorflow.org"] },
          { "id": "angular", "category": "framework", "simpleIcon": "angular", "domains": ["angular.dev"] },
          { "id": "svelte", "category": "framework", "simpleIcon": "svelte", "domains": ["svelte.dev"] },
          { "id": "django", "category": "framework", "simpleIcon": "django", "domains": ["djangoproject.com"] },
          { "id": "flask", "category": "framework", "simpleIcon": "flask", "domains": ["palletsprojects.com"] },
          { "id": "fastapi", "category": "framework", "simpleIcon": "fastapi", "domains": ["fastapi.tiangolo.com"] },
          { "id": "spring", "category": "framework", "simpleIcon": "spring", "aliases": ["spring-boot"], "domains": ["spring.io"] },
          { "id": "dotnet", "category": "framework", "simpleIcon": "dotnet", "aliases": [".net"], "domains": ["dotnet.microsoft.com"] }
        ]
      }
      
    • README.md 1.4 KB
      # Built-in brand marks
      
      Archify ships a bounded catalogue of 107 commonly used brands for architecture,
      workflow, sequence, data-flow, and lifecycle nodes. The mark is optional authored
      identity: it never replaces the node's semantic `type`, color, label, or
      relationships.
      
      Unknown sites are handled by an explicit two-stage workflow. Run
      `node bin/archify.mjs brands capture <url> --json`, then author the returned
      digest-pinned `brand` value. Normal render and validate commands do not perform
      an unpinned capture, and changed or unavailable content fails closed.
      
      Most vector paths and brand metadata are generated from Simple Icons 16.28.0.
      The OpenAI mark is traced to OpenAI's official brand guidelines. Every generated
      entry records its source and, when available upstream, its guidelines and license
      metadata in `renderers/shared/generated-brand-marks.mjs`.
      
      Brand names and logos may be trademarks of their respective owners. Simple
      Icons' CC0 license covers its collection work, not every underlying trademark or
      artwork. Contributors must review the recorded source, current brand guidelines,
      and intended referential use before adding or updating a mark. Archify does not
      imply sponsorship, endorsement, or partnership.
      
      Edit `catalog.json`, then regenerate the committed zero-runtime-dependency bundle:
      
      ```bash
      npm run generate:brand-marks
      npm run check:brand-marks
      ```
      
      Do not hand-edit `renderers/shared/generated-brand-marks.mjs`.
      
  • delta
    • architecture-delta.mjs 76.7 KB · in bundle
  • examples
    • locales
      • de.json 25.9 KB
        {
          "page.title": "{title} Diagramm",
          "diagram.description.architecture": "Ein von Archify erstelltes Architekturdiagramm.",
          "diagram.description.workflow": "Ein von Archify erstelltes Workflow-Diagramm.",
          "diagram.description.sequence": "Ein von Archify erstelltes Sequenzdiagramm.",
          "diagram.description.dataflow": "Ein von Archify erstelltes Datenfluss-Diagramm.",
          "diagram.description.lifecycle": "Ein von Archify erstelltes Lifecycle-Diagramm.",
          "node.focus": "{label} fokussieren",
          "node.focus.detail": "{label} fokussieren, {detail}",
          "node.context.architecture": "Architekturkomponente",
          "node.context.workflow": "Workflow-Knoten",
          "node.context.sequence": "Sequenzteilnehmer",
          "node.context.dataflow": "Datenfluss-Knoten",
          "node.context.lifecycle": "Lifecycle-Status",
          "legend.title": "Legende",
          "legend.architecture.frontend": "Frontend",
          "legend.architecture.backend": "Backend",
          "legend.architecture.database": "Datenbank",
          "legend.architecture.cloud": "Cloud",
          "legend.architecture.security": "Sicherheit",
          "legend.architecture.messagebus": "Nachrichtenbus",
          "legend.architecture.external": "Extern",
          "legend.workflow.frontend": "Benutzeroberfläche",
          "legend.workflow.backend": "Agentenlogik",
          "legend.workflow.security": "Richtlinie",
          "legend.workflow.messagebus": "Werkzeugaktion",
          "legend.workflow.database": "Kontext / Trace",
          "legend.workflow.cloud": "Cloud-Dienst",
          "legend.workflow.external": "Externes System",
          "legend.sequence.emphasis": "Hauptanfrage",
          "legend.sequence.return": "Rückgabe",
          "legend.sequence.security": "Sicherheit",
          "legend.sequence.dashed": "asynchroner Trace",
          "legend.sequence.default": "Nachricht",
          "legend.dataflow.emphasis": "Primärdaten",
          "legend.dataflow.security": "Richtlinie / PII",
          "legend.dataflow.dashed": "asynchroner Batch",
          "legend.dataflow.database": "Datenspeicher",
          "legend.dataflow.default": "Datenfluss",
          "legend.lifecycle.start": "Startzustand",
          "legend.lifecycle.active": "aktiv",
          "legend.lifecycle.waiting": "Wartend",
          "legend.lifecycle.decision": "Entscheidung",
          "legend.lifecycle.success": "Erfolg",
          "legend.lifecycle.failure": "Fehler / Abbruch",
          "legend.lifecycle.neutral": "neutral",
          "legend.lifecycle.external": "extern",
          "legend.lifecycle.final": "Endzustand",
          "viewer.kind.frontend": "Frontend",
          "viewer.kind.backend": "Backend",
          "viewer.kind.database": "Datenbank",
          "viewer.kind.cloud": "Cloud",
          "viewer.kind.security": "Sicherheit",
          "viewer.kind.messagebus": "Nachrichtenbus",
          "viewer.kind.external": "Extern",
          "viewer.kind.neutral": "Neutral",
          "viewer.kind.node": "Knoten",
          "viewer.kind.start": "Start",
          "viewer.kind.active": "Aktiv",
          "viewer.kind.waiting": "Wartend",
          "viewer.kind.decision": "Entscheidung",
          "viewer.kind.success": "Erfolg",
          "viewer.kind.failure": "Fehler",
          "viewer.toolbar.actions": "Diagrammaktionen",
          "viewer.theme.toggle.title": "Design wechseln (T)",
          "viewer.theme.toggle": "Farbdesign wechseln",
          "viewer.theme.dark": "Dunkel",
          "viewer.theme.light": "Hell",
          "viewer.preset.choose.title": "Visuellen Stil wählen (S wechselt durch)",
          "viewer.preset.choose": "Visuellen Stil wählen",
          "viewer.preset.style": "Stil",
          "viewer.preset.menu": "Visueller Stil",
          "viewer.preset.identity": "Visuelle Identität",
          "viewer.preset.cycles": "S wechselt durch",
          "viewer.preset.classic": "Klassisch",
          "viewer.preset.classic.short": "Klassisch",
          "viewer.preset.classic.hint": "Stabiler technischer Standard",
          "viewer.preset.flow": "Signalfluss",
          "viewer.preset.flow.short": "Fluss",
          "viewer.preset.flow.hint": "Bewegungsbetonte Präsentation",
          "viewer.preset.blueprint": "Bauplan",
          "viewer.preset.blueprint.hint": "Technisches Review",
          "viewer.preset.editorial": "Editorial",
          "viewer.preset.editorial.hint": "Für Veröffentlichungen und Launch-Notizen",
          "viewer.preset.badge.signalFlow": "SIGNALFLUSS",
          "viewer.preset.badge.blueprint": "BAUPLAN / REV. 01",
          "viewer.preset.badge.editorial": "EDITORIAL / FELDNOTIZ",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / TAFEL 04",
          "viewer.preset.current": "Visueller Stil: {style}. Visuellen Stil wählen",
          "viewer.motion.live": "Live",
          "viewer.motion.still": "Statisch",
          "viewer.motion.pause": "Bewegung pausieren",
          "viewer.motion.resume": "Bewegung fortsetzen",
          "viewer.motion.reduced": "Bewegung wegen reduzierter Bewegungseinstellung pausiert",
          "viewer.motion.hidden": "Bewegung pausiert, während diese Seite ausgeblendet ist",
          "viewer.motion.yielding": "Bewegung pausieren; derzeit an {owner} abgegeben",
          "viewer.motion.yielding.title": "Live-Vorschau aktiv · an {owner} abgegeben",
          "viewer.owner.route": "Routensonde",
          "viewer.owner.lens": "Semantische Linse",
          "viewer.owner.relationship": "Beziehungsvorschau",
          "viewer.owner.intent": "Intent Trace",
          "viewer.owner.focus": "semantischer Fokus",
          "viewer.owner.legend": "Legendenvorschau",
          "viewer.owner.reader": "Leserinteraktion",
          "viewer.present.enter": "Präsentationsmodus starten",
          "viewer.present.enter.title": "Präsentationsmodus (F)",
          "viewer.present.exit": "Präsentationsmodus beenden",
          "viewer.present.exit.title": "Präsentationsmodus beenden (F oder Escape)",
          "viewer.present.present": "Präsentieren",
          "viewer.present.exit.label": "Beenden",
          "viewer.export.button": "Exportieren",
          "viewer.export.button.title": "Diagramm exportieren (E)",
          "viewer.export.diagram": "Diagramm exportieren",
          "viewer.export.menu": "Exportieren",
          "viewer.export.subtitle": "Portable, saubere Ausgaben",
          "viewer.export.share": "Teilen",
          "viewer.export.shareCard": "Freigabekarte",
          "viewer.export.routeShareCard": "Routen-Freigabekarte",
          "viewer.export.reachShareCard": "Reichweiten-Freigabekarte",
          "viewer.export.copyDiagram": "Diagramm kopieren",
          "viewer.export.clipboardPng": "PNG in Zwischenablage",
          "viewer.export.raster": "Rasterbilder",
          "viewer.export.image": "Bild",
          "viewer.export.lossless": "Verlustfreies Bild",
          "viewer.export.compact": "Kompaktes Bild",
          "viewer.export.modern": "Modernes Bild",
          "viewer.export.vectorMotion": "Vektor und Bewegung",
          "viewer.export.vectorMotion.heading": "Vektor & Bewegung",
          "viewer.export.editable": "Editierbarer Vektor",
          "viewer.export.motion6s": "6-Sekunden-Bewegung",
          "viewer.export.unsupported": "Von diesem Browser nicht unterstützt",
          "viewer.export.clipboardUnsupported": "Bild-Zwischenablage wird von diesem Browser nicht unterstützt",
          "viewer.export.clipboardUnsupported.short": "Dieser Browser unterstützt keine Bild-Zwischenablage.",
          "viewer.export.motionUnavailable": "Bewegungsaufnahme in diesem Browser nicht verfügbar",
          "viewer.export.webmUnavailable": "WebM in diesem Browser nicht verfügbar",
          "viewer.export.failed": "Export fehlgeschlagen: {message}",
          "viewer.export.unknownVariant": "Unbekannter Freigabekarten-Typ: {variant}",
          "viewer.export.routeRequired": "Route verfolgen, bevor eine Routen-Freigabekarte exportiert wird",
          "viewer.export.reachRequired": "Verfasste Reichweite verfolgen, bevor eine Reichweiten-Freigabekarte exportiert wird",
          "viewer.export.unknown": "unbekannt",
          "viewer.export.routeFailed": "Export der Routen-Freigabekarte fehlgeschlagen: {message}",
          "viewer.export.reachFailed": "Export der Reichweiten-Freigabekarte fehlgeschlagen: {message}",
          "viewer.export.copyFailed": "Kopieren fehlgeschlagen: {message}",
          "viewer.export.copiedPng": "PNG in Zwischenablage kopiert",
          "viewer.export.downloadedRoute": "Routen-Freigabekarte heruntergeladen",
          "viewer.export.downloadedReach": "Reichweiten-Freigabekarte heruntergeladen",
          "viewer.export.downloadedWebm": "WebM heruntergeladen",
          "viewer.export.recording": "6 Sekunden Bewegung werden aufgezeichnet …",
          "viewer.export.card.routeSummary.one": "Route: {source} → {target} · {count} gerichteter Hop",
          "viewer.export.card.routeSummary.other": "Route: {source} → {target} · {count} gerichtete Hops",
          "viewer.export.card.reachSummary": "Verfasst {direction} von {origin} · {nodes} · {links} · max. {hops}",
          "viewer.export.card.node.one": "{count} Knoten",
          "viewer.export.card.node.other": "{count} Knoten",
          "viewer.export.card.link.one": "{count} Verbindung",
          "viewer.export.card.link.other": "{count} Verbindungen",
          "viewer.export.card.hop.one": "{count} Hop",
          "viewer.export.card.hop.other": "{count} Hops",
          "viewer.export.card.routeBadge": "ARCHIFY · ROUTE · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · {direction} REICHWEITE",
          "viewer.export.direction.upstream": "Vorgelagert",
          "viewer.export.direction.downstream": "Nachgelagert",
          "viewer.export.error.canvasUnavailable": "Canvas für {label} nicht verfügbar",
          "viewer.export.error.contextUnavailable": "2D-Canvas-Kontext für {label} nicht verfügbar",
          "viewer.export.error.toBlobUnavailable": "canvas.toBlob für {label} nicht verfügbar",
          "viewer.export.error.toBlobNull": "canvas.toBlob lieferte keine Daten für {label}",
          "viewer.export.error.variantsCombined": "Freigabekarten-Typen können nicht kombiniert werden",
          "viewer.export.error.viewerState": "Beim Export der Freigabekarte konnte der temporäre Viewer-Zustand nicht entfernt werden",
          "viewer.export.error.routeState": "Beim Export der Routenkarte konnte die aufgelöste Route nicht sicher erhalten werden",
          "viewer.export.error.reachState": "Beim Export der Reichweitenkarte konnte die verfasste Reichweite nicht sicher erhalten werden",
          "viewer.export.error.webmRequirements": "Der WebM-Bewegungsexport erfordert eine Trace-Animation und Browser-Unterstützung für MediaRecorder",
          "viewer.export.error.mediaRecorder": "MediaRecorder fehlgeschlagen",
          "viewer.export.error.emptyWebm": "MediaRecorder hat ein leeres WebM erzeugt",
          "viewer.export.error.webmBackground": "SVG-Hintergrund konnte für den WebM-Export nicht geladen werden",
          "viewer.guide.eyebrow": "Diagrammleitfaden",
          "viewer.guide.close": "Diagrammleitfaden schließen",
          "viewer.guide.inspecting": "Kompilierte Semantik wird geprüft",
          "viewer.guide.actions": "Diagramm-Erkundungsaktionen",
          "viewer.guide.find": "Beliebigen Knoten finden",
          "viewer.guide.find.hint": "Labels, Zuständigkeiten, Arten und stabile IDs durchsuchen.",
          "viewer.guide.route": "Eine Route verfolgen",
          "viewer.guide.route.aria": "Eine gerichtete Route verfolgen",
          "viewer.guide.route.hint": "Herausfinden, wie zwei semantische Knoten in verfasster Richtung verbunden sind.",
          "viewer.guide.map": "Das gesamte System sehen",
          "viewer.guide.map.hint": "Semantisches Radar mit Live-Ansicht und stabilen Knoten öffnen.",
          "viewer.guide.lens": "Semantische Arten vergleichen",
          "viewer.guide.lens.hint": "Rollen zählen, ihren Verkehr sichtbar machen und direkte verfasste Verbindungen vergleichen.",
          "viewer.guide.present": "Präsentationsmodus starten",
          "viewer.guide.present.hint": "Dem Live-Diagramm die gesamte Ansicht geben, ohne den Export zu verändern.",
          "viewer.guide.shortcuts": "Weitere Tastenkombinationen",
          "viewer.guide.shortcut.export": "Exportieren",
          "viewer.guide.shortcut.theme": "Design",
          "viewer.guide.shortcut.style": "Stil",
          "viewer.guide.shortcut.reset": "Zurücksetzen",
          "viewer.guide.shortcut.zoomIn": "Vergrößern",
          "viewer.guide.shortcut.zoomOut": "Verkleinern",
          "viewer.guide.shortcut.close": "Schließen",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} semantischer Knoten",
          "viewer.guide.fact.node.other": "{count} semantische Knoten",
          "viewer.guide.fact.relationship.one": "{count} Beziehung",
          "viewer.guide.fact.relationship.other": "{count} Beziehungen",
          "viewer.guide.open": "Diagrammleitfaden öffnen",
          "viewer.finder.title": "Knoten finden",
          "viewer.finder.close": "Knotensuche schließen",
          "viewer.finder.placeholder": "Labels oder IDs suchen",
          "viewer.finder.search": "Diagrammknoten durchsuchen",
          "viewer.finder.results": "Diagrammknoten",
          "viewer.finder.empty": "Keine passenden Knoten",
          "viewer.finder.result.focus": "{label} fokussieren",
          "viewer.finder.result.routeStart": "{label} als Routenstart wählen",
          "viewer.finder.result.routeTarget": "{label} als Routenziel wählen, {links}",
          "viewer.finder.status.empty": "Keine passenden Knoten",
          "viewer.finder.status.count.one": "{count} passender Knoten",
          "viewer.finder.status.count.other": "{count} passende Knoten",
          "viewer.finder.noun.nodes": "Knoten",
          "viewer.finder.link.one": "{count} Verbindung",
          "viewer.finder.link.other": "{count} Verbindungen",
          "viewer.finder.result.focus.one": "{label} fokussieren, {count} zugehörige Verbindung",
          "viewer.finder.result.focus.other": "{label} fokussieren, {count} zugehörige Verbindungen",
          "viewer.finder.status.filtered": "{visible} von {available} {noun}",
          "viewer.finder.status.all": "{available} {noun}",
          "viewer.passport.eyebrow": "Semantischer Pass",
          "viewer.passport.metadata": "Knoten-Metadaten",
          "viewer.passport.evidence": "Verifizierter Quellnachweis",
          "viewer.passport.verified": "Verifizierte Quelle",
          "viewer.passport.verificationScope": "Verifiziert gegen lokales Git zur fixierten Revision. Remote-Zugriff wurde nicht geprüft.",
          "viewer.passport.reach": "Verfasste Reichweite",
          "viewer.passport.reach.trace": "Verfasste Erreichbarkeit verfolgen",
          "viewer.passport.upstream": "Vorgelagert",
          "viewer.passport.downstream": "Nachgelagert",
          "viewer.passport.upstream.trace": "Vorgelagerte verfasste Erreichbarkeit verfolgen",
          "viewer.passport.downstream.trace": "Nachgelagerte verfasste Erreichbarkeit verfolgen",
          "viewer.passport.close": "Semantischen Pass schließen",
          "viewer.passport.copy": "Link kopieren",
          "viewer.passport.copy.focus": "Link zum fokussierten Knoten kopieren",
          "viewer.passport.relations": "Beziehungen",
          "viewer.passport.relations.show": "Verbundene Beziehungen anzeigen",
          "viewer.passport.relations.hide": "Verbundene Beziehungen ausblenden",
          "viewer.passport.relations.list": "Verbundene Beziehungen",
          "viewer.passport.copyRelation": "Beziehung kopieren",
          "viewer.passport.copyNode": "Knoten kopieren",
          "viewer.passport.copyPinned": "Link zur angehefteten Beziehung kopieren",
          "viewer.passport.copySource": "Link zum Quellknoten kopieren",
          "viewer.passport.copy.focused.success": "Link des fokussierten Knotens kopiert",
          "viewer.passport.copy.pinned.success": "Link der angehefteten Beziehung kopiert",
          "viewer.passport.copy.focused.failed": "Link des fokussierten Knotens konnte nicht kopiert werden",
          "viewer.passport.copy.pinned.failed": "Link der angehefteten Beziehung konnte nicht kopiert werden",
          "viewer.passport.relationship.none": "Keine verbundenen Beziehungen",
          "viewer.passport.relationship.count.one": "{count} Beziehung",
          "viewer.passport.relationship.count.other": "{count} Beziehungen",
          "viewer.passport.relationship.show.one": "{count} verbundene Beziehung anzeigen",
          "viewer.passport.relationship.show.other": "{count} verbundene Beziehungen anzeigen",
          "viewer.passport.relationship.summary": "{out} ausgehend · {in} eingehend{loops}",
          "viewer.passport.relationship.loops": " · {count} Selbstschleife",
          "viewer.passport.relationship.explorer": "Direkter Beziehungs-Explorer",
          "viewer.passport.relationship.help": "Pfeiltasten zum Erkunden der Beziehungen verwenden. Enter oder Leertaste heftet Details an; Escape hebt die Auswahl auf.",
          "viewer.passport.relationship.loopsBack": "schleift zurück",
          "viewer.passport.relationship.connectsTo": "verbindet zu",
          "viewer.passport.relationship.connectsFrom": "verbindet von",
          "viewer.passport.relationship.pinned": "Angeheftete Beziehung · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "Beziehung {index} von {total} prüfen: {from} zu {to}, {label}. Enter für Details drücken.",
          "viewer.passport.relationship.group.out": "Ausgehend",
          "viewer.passport.relationship.group.in": "Eingehend",
          "viewer.passport.relationship.group.loop": "Selbstschleifen",
          "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "AUS →",
          "viewer.passport.relationship.direction.in": "← EIN",
          "viewer.passport.relationship.direction.loop": "SCHLEIFE",
          "viewer.passport.sourceCount.one": "{count} verifizierte Quellenreferenz",
          "viewer.passport.sourceCount.other": "{count} verifizierte Quellenreferenzen",
          "viewer.passport.sourceMarker": "QUELLE",
          "viewer.passport.beacon.one": "{count} verifizierte Quelle; diesen Knoten fokussieren, um sie zu prüfen",
          "viewer.passport.beacon.other": "{count} verifizierte Quellen; diesen Knoten fokussieren, um sie zu prüfen",
          "viewer.passport.repository.open": "Verifizierte Repository-Revision {revision} öffnen",
          "viewer.passport.source.open": "Verifizierte Quelle {path} bei Revision {revision} öffnen",
          "viewer.passport.source.openLink": "Öffnen ↗",
          "viewer.passport.reach.upstream.one": "{count} vorgelagerten verfassten Knoten verfolgen",
          "viewer.passport.reach.upstream.other": "{count} vorgelagerte verfasste Knoten verfolgen",
          "viewer.passport.reach.downstream.one": "{count} nachgelagerten verfassten Knoten verfolgen",
          "viewer.passport.reach.downstream.other": "{count} nachgelagerte verfasste Knoten verfolgen",
          "viewer.passport.reach.noUpstream": "Keine vorgelagerten verfassten Knoten",
          "viewer.passport.reach.noDownstream": "Keine nachgelagerten verfassten Knoten",
          "viewer.passport.reach.status": "{direction} · {nodes} Knoten · {links} Verbindungen · max. {hops} Hops",
          "viewer.route.eyebrow": "Routensonde",
          "viewer.route.start": "Startknoten wählen",
          "viewer.route.start.find": "Start finden",
          "viewer.route.start.find.aria": "Einen Routenstart finden",
          "viewer.route.copy": "Link kopieren",
          "viewer.route.copy.aria": "Link zur verfolgten Route kopieren",
          "viewer.route.clear": "Löschen",
          "viewer.route.clear.aria": "Routensonde löschen",
          "viewer.route.traced": "Verfolgte Route",
          "viewer.route.pickTwo": "Zwei semantische Knoten im Diagramm auswählen",
          "viewer.route.pickOne": "Einen semantischen Knoten im Diagramm auswählen",
          "viewer.route.controls": "Routen-Verlaufssteuerung",
          "viewer.route.previous": "Vorherige Routenposition",
          "viewer.route.play": "Routenverlauf abspielen",
          "viewer.route.pause": "Routenverlauf pausieren",
          "viewer.route.replay": "Routenverlauf erneut abspielen",
          "viewer.route.next": "Nächste Routenposition",
          "viewer.route.journey": "Verlauf",
          "viewer.route.pause.label": "Pausieren",
          "viewer.route.replay.label": "Erneut abspielen",
          "viewer.route.overview": "Übersicht",
          "viewer.route.overview.aria": "Vollständige Routenübersicht anzeigen",
          "viewer.route.instructions": "Quelle wählen, dann das Ziel. Die Richtung ist entscheidend.",
          "viewer.route.destination": "Ziel ausgehend von {label} wählen",
          "viewer.route.destination.find": "Ziel finden",
          "viewer.route.destination.find.aria": "Ein erreichbares Routenziel finden",
          "viewer.route.differentDestination": "Anderes Ziel wählen",
          "viewer.route.distinct": "Eine Route benötigt zwei unterschiedliche semantische Knoten.",
          "viewer.route.unreachable": "Keine gerichtete Route zu {label}",
          "viewer.route.unreachable.detail": "{target} ist von {source} aus nicht erreichbar. Ein hervorgehobenes Ziel wählen.",
          "viewer.route.start.instructions": "Quelle auswählen. Im nächsten Schritt werden nur gerichtete Ziele angezeigt.",
          "viewer.route.copy.success": "Link zur verfolgten Route kopiert",
          "viewer.route.copy.failed": "Link zur verfolgten Route konnte nicht kopiert werden",
          "viewer.route.position": "Routenposition {index} von {total}: {label}",
          "viewer.route.step": "Schritt {index} von {total} · {phase} · {label}",
          "viewer.route.motionRequired": "Automatischer Verlauf erfordert Live-Bewegung",
          "viewer.route.trigger.clear": "Verfolgte Route löschen",
          "viewer.route.overview.status": "{nodes} · {hops} · kürzeste verfasste Route",
          "viewer.route.overview.node.one": "{count} Knoten",
          "viewer.route.overview.node.other": "{count} Knoten",
          "viewer.route.overview.hop.one": "{count} gerichteter Hop",
          "viewer.route.overview.hop.other": "{count} gerichtete Hops",
          "viewer.route.phase.playing": "Läuft",
          "viewer.route.phase.complete": "Abgeschlossen",
          "viewer.route.phase.inspecting": "Wird geprüft",
          "viewer.route.destination.count.one": "{count} gerichtetes Ziel verfügbar. Einen hervorgehobenen Knoten wählen.",
          "viewer.route.destination.count.other": "{count} gerichtete Ziele verfügbar. Einen hervorgehobenen Knoten wählen.",
          "viewer.route.noOutgoing": "Hier startet keine ausgehende Route. Löschen und eine andere Quelle wählen.",
          "viewer.route.result.title": "{source} nach {target}",
          "viewer.route.finder.source.title": "Routenstart wählen",
          "viewer.route.finder.source.placeholder": "Routenquellen suchen",
          "viewer.route.finder.source.empty": "Keine passenden Routenquellen",
          "viewer.route.finder.source.results": "Knoten, die eine Route starten können",
          "viewer.route.finder.source.noun": "Routenquellen",
          "viewer.route.finder.source.badge": "Start",
          "viewer.route.finder.target.title": "Ziel ausgehend von {label}",
          "viewer.route.finder.target.placeholder": "Erreichbare Ziele suchen",
          "viewer.route.finder.target.empty": "Keine passenden erreichbaren Ziele",
          "viewer.route.finder.target.results": "Erreichbare Routenziele",
          "viewer.route.finder.target.noun": "erreichbare Ziele",
          "viewer.route.hop.one": "{count} Hop",
          "viewer.route.hop.other": "{count} Hops",
          "viewer.lens.eyebrow": "Semantische Linse",
          "viewer.lens.title": "Systemrollen vergleichen",
          "viewer.lens.close": "Semantische Linse schließen",
          "viewer.lens.instruction": "Bis zu zwei semantische Arten wählen. Eine zeigt ihren echten Verkehr; zwei vergleichen nur direkte verfasste Beziehungen.",
          "viewer.lens.kinds": "Semantische Arten",
          "viewer.lens.choose": "Eine Art wählen, um ihre Knoten und berührenden Beziehungen zu prüfen.",
          "viewer.lens.copy": "Link zur semantischen Linse kopieren",
          "viewer.lens.clear": "Semantische Linse löschen",
          "viewer.lens.open": "Semantische Linse öffnen",
          "viewer.lens.openActive": "Aktive semantische Linse öffnen",
          "viewer.lens.legend": "Semantische Legende",
          "viewer.lens.legend.inspect.one": "{label} prüfen, {count} Knoten",
          "viewer.lens.legend.inspect.other": "{label} prüfen, {count} Knoten",
          "viewer.lens.kind.count.one": "{label}, {count} Knoten",
          "viewer.lens.kind.count.other": "{label}, {count} Knoten",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} direkte Beziehung",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} direkte Beziehungen",
          "viewer.lens.single": "{nodes} · {relationships} · verbundene Nachbarn bleiben sichtbar",
          "viewer.lens.node.one": "{count} {label}-Knoten",
          "viewer.lens.node.other": "{count} {label}-Knoten",
          "viewer.lens.relationship.one": "{count} berührende Beziehung",
          "viewer.lens.relationship.other": "{count} berührende Beziehungen",
          "viewer.radar.title": "Semantisches Radar",
          "viewer.radar.building": "Übersicht wird erstellt",
          "viewer.radar.openFull": "Vollständiges semantisches Radar öffnen",
          "viewer.radar.open": "Radar öffnen",
          "viewer.radar.close": "Semantisches Radar schließen",
          "viewer.radar.surface": "Diagrammübersicht. Auf einen Knoten klicken, um ihn zu fokussieren, oder mit den Pfeiltasten schwenken.",
          "viewer.radar.click": "Knoten anklicken",
          "viewer.radar.drag": "Ziehen zum Schwenken",
          "viewer.radar.space": "Semantisches Radar benötigt mehr MAP-Platz.",
          "viewer.radar.nodes": "Semantische Diagramm-Radarknoten",
          "viewer.radar.focus": "{label} vom semantischen Radar fokussieren",
          "viewer.radar.status": "{count} Knoten · {viewport}",
          "viewer.radar.fullMap": "{count} Knoten · vollständige Karte",
          "viewer.radar.compacted": "Radar verkleinert, um den semantischen Pass oder die MAP-Steuerung nicht zu verdecken.",
          "viewer.radar.cancelWaiting": "Wartendes semantisches Radar auf mehr MAP-Platz abbrechen",
          "viewer.radar.needsSpace": "Semantisches Radar benötigt mehr sichtbaren MAP-Platz",
          "viewer.radar.viewport.full": "vollständige Karte",
          "viewer.radar.viewport.width": "{percent}% Breite",
          "viewer.radar.viewport.scale": "{percent}% Ansicht",
          "viewer.nav.controls": "Diagrammansicht-Steuerung",
          "viewer.nav.route": "Eine gerichtete Route verfolgen",
          "viewer.nav.route.title": "Route verfolgen (R)",
          "viewer.nav.route.short": "PFAD",
          "viewer.nav.radar": "Semantisches Radar öffnen",
          "viewer.nav.radar.title": "Semantisches Radar (M)",
          "viewer.nav.radar.short": "KARTE",
          "viewer.nav.lens": "Semantische Linse öffnen",
          "viewer.nav.lens.title": "Semantische Linse (L)",
          "viewer.nav.lens.short": "LINSE",
          "viewer.nav.find": "Knoten finden",
          "viewer.nav.find.title": "Knoten finden (/)",
          "viewer.nav.guide": "Diagrammleitfaden öffnen",
          "viewer.nav.guide.title": "Diagrammleitfaden (?)",
          "viewer.nav.zoomOut": "Verkleinern",
          "viewer.nav.zoomOut.title": "Verkleinern (-)",
          "viewer.nav.reset": "Diagrammansicht zurücksetzen",
          "viewer.nav.reset.title": "Ansicht zurücksetzen (0)",
          "viewer.nav.read": "LESEN",
          "viewer.nav.zoomIn": "Vergrößern",
          "viewer.nav.zoomIn.title": "Vergrößern (+)",
          "viewer.nav.camera": "{hint}. Diagrammansicht zurücksetzen",
          "viewer.nav.camera.title": "{semantic}{hint} · Ansicht zurücksetzen (0)",
          "viewer.nav.camera.semantic": "Semantische Kamera aktiv · ",
          "viewer.nav.level.map": "KARTE",
          "viewer.nav.level.read": "LESEN",
          "viewer.nav.level.full": "VOLL",
          "viewer.nav.level.auto": "AUTO",
          "viewer.nav.detail.map": "Vergrößern, um Beziehungslabels und Knotenkontext anzuzeigen",
          "viewer.nav.detail.read": "Erneut vergrößern, um Tags und Anmerkungen anzuzeigen",
          "viewer.nav.detail.full": "Vollständige Diagrammdetails",
          "viewer.intent.summary": "{label}. {out} ausgehend, {in} eingehend{loops}. {total} Verbindungen. Enter für Details drücken.",
          "viewer.intent.loops": ", {count} Selbstschleife",
          "viewer.common.copied": "Kopiert",
          "viewer.common.copyFailed": "Kopieren fehlgeschlagen",
          "viewer.common.copyLink": "Link kopieren",
          "viewer.common.clear": "Löschen",
          "viewer.common.close": "Schließen"
        }
        
      • es.json 26.6 KB
        {
          "page.title": "{title} · Diagrama",
          "diagram.description.architecture": "Un diagrama de arquitectura generado por Archify.",
          "diagram.description.workflow": "Un diagrama de flujo de trabajo generado por Archify.",
          "diagram.description.sequence": "Un diagrama de secuencia generado por Archify.",
          "diagram.description.dataflow": "Un diagrama de flujo de datos generado por Archify.",
          "diagram.description.lifecycle": "Un diagrama de ciclo de vida generado por Archify.",
          "node.focus": "Enfocar {label}",
          "node.focus.detail": "Enfocar {label}, {detail}",
          "node.context.architecture": "Componente de arquitectura",
          "node.context.workflow": "Nodo de flujo de trabajo",
          "node.context.sequence": "Participante de secuencia",
          "node.context.dataflow": "Nodo de flujo de datos",
          "node.context.lifecycle": "Estado del ciclo de vida",
          "legend.title": "Leyenda",
          "legend.architecture.frontend": "Frontend",
          "legend.architecture.backend": "Backend",
          "legend.architecture.database": "Base de datos",
          "legend.architecture.cloud": "Nube",
          "legend.architecture.security": "Seguridad",
          "legend.architecture.messagebus": "Bus de mensajes",
          "legend.architecture.external": "Externo",
          "legend.workflow.frontend": "Interfaz de usuario",
          "legend.workflow.backend": "Lógica del agente",
          "legend.workflow.security": "Política",
          "legend.workflow.messagebus": "Acción de herramienta",
          "legend.workflow.database": "Contexto / traza",
          "legend.workflow.cloud": "Servicio en la nube",
          "legend.workflow.external": "Sistema externo",
          "legend.sequence.emphasis": "solicitud principal",
          "legend.sequence.return": "respuesta",
          "legend.sequence.security": "seguridad",
          "legend.sequence.dashed": "traza asíncrona",
          "legend.sequence.default": "mensaje",
          "legend.dataflow.emphasis": "datos primarios",
          "legend.dataflow.security": "política / PII",
          "legend.dataflow.dashed": "lote asíncrono",
          "legend.dataflow.database": "almacén de datos",
          "legend.dataflow.default": "flujo de datos",
          "legend.lifecycle.start": "estado inicial",
          "legend.lifecycle.active": "activo",
          "legend.lifecycle.waiting": "en espera",
          "legend.lifecycle.decision": "decisión",
          "legend.lifecycle.success": "éxito",
          "legend.lifecycle.failure": "fallo / salida",
          "legend.lifecycle.neutral": "neutral",
          "legend.lifecycle.external": "externo",
          "legend.lifecycle.final": "estado final",
          "viewer.kind.frontend": "Frontend",
          "viewer.kind.backend": "Backend",
          "viewer.kind.database": "Base de datos",
          "viewer.kind.cloud": "Nube",
          "viewer.kind.security": "Seguridad",
          "viewer.kind.messagebus": "Bus de mensajes",
          "viewer.kind.external": "Externo",
          "viewer.kind.neutral": "Neutral",
          "viewer.kind.node": "Nodo",
          "viewer.kind.start": "Inicio",
          "viewer.kind.active": "Activo",
          "viewer.kind.waiting": "En espera",
          "viewer.kind.decision": "Decisión",
          "viewer.kind.success": "Éxito",
          "viewer.kind.failure": "Fallo",
          "viewer.toolbar.actions": "Acciones del diagrama",
          "viewer.theme.toggle.title": "Cambiar tema (T)",
          "viewer.theme.toggle": "Cambiar tema de color",
          "viewer.theme.dark": "Oscuro",
          "viewer.theme.light": "Claro",
          "viewer.preset.choose.title": "Elegir estilo visual (S alterna)",
          "viewer.preset.choose": "Elegir estilo visual",
          "viewer.preset.style": "Estilo",
          "viewer.preset.menu": "Estilo visual",
          "viewer.preset.identity": "Identidad visual",
          "viewer.preset.cycles": "alterna",
          "viewer.preset.classic": "Clásico",
          "viewer.preset.classic.short": "Clásico",
          "viewer.preset.classic.hint": "Predeterminado técnico estable",
          "viewer.preset.flow": "Flujo de señal",
          "viewer.preset.flow.short": "Flujo",
          "viewer.preset.flow.hint": "Presentación con énfasis en el movimiento",
          "viewer.preset.blueprint": "Plano",
          "viewer.preset.blueprint.hint": "Revisión de ingeniería",
          "viewer.preset.editorial": "Editorial",
          "viewer.preset.editorial.hint": "Notas de publicación y lanzamiento",
          "viewer.preset.badge.signalFlow": "FLUJO DE SEÑAL",
          "viewer.preset.badge.blueprint": "PLANO / REV 01",
          "viewer.preset.badge.editorial": "EDITORIAL / NOTA DE CAMPO",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / LÁMINA 04",
          "viewer.preset.current": "Estilo visual: {style}. Elegir estilo visual",
          "viewer.motion.live": "Activa",
          "viewer.motion.still": "Fija",
          "viewer.motion.pause": "Pausar animación",
          "viewer.motion.resume": "Reanudar animación",
          "viewer.motion.reduced": "Animación pausada por la preferencia de movimiento reducido",
          "viewer.motion.hidden": "Animación pausada mientras esta página está oculta",
          "viewer.motion.yielding": "Pausar animación; cediendo a {owner}",
          "viewer.motion.yielding.title": "Vista previa en vivo activada · cediendo a {owner}",
          "viewer.owner.route": "Sonda de ruta",
          "viewer.owner.lens": "Lente semántico",
          "viewer.owner.relationship": "Vista previa de relación",
          "viewer.owner.intent": "Traza de intención",
          "viewer.owner.focus": "enfoque semántico",
          "viewer.owner.legend": "vista previa de la leyenda",
          "viewer.owner.reader": "interacción del lector",
          "viewer.present.enter": "Entrar al modo presentación",
          "viewer.present.enter.title": "Modo presentación (F)",
          "viewer.present.exit": "Salir del modo presentación",
          "viewer.present.exit.title": "Salir del modo presentación (F o Escape)",
          "viewer.present.present": "Presentar",
          "viewer.present.exit.label": "Salir",
          "viewer.export.button": "Exportar",
          "viewer.export.button.title": "Exportar diagrama (E)",
          "viewer.export.diagram": "Exportar diagrama",
          "viewer.export.menu": "Exportar",
          "viewer.export.subtitle": "Salidas portables y limpias",
          "viewer.export.share": "Compartir",
          "viewer.export.shareCard": "Tarjeta para compartir",
          "viewer.export.routeShareCard": "Tarjeta de ruta para compartir",
          "viewer.export.reachShareCard": "Tarjeta de alcance para compartir",
          "viewer.export.copyDiagram": "Copiar diagrama",
          "viewer.export.clipboardPng": "PNG al portapapeles",
          "viewer.export.raster": "Imágenes rasterizadas",
          "viewer.export.image": "Imagen",
          "viewer.export.lossless": "Imagen sin pérdida",
          "viewer.export.compact": "Imagen compacta",
          "viewer.export.modern": "Imagen moderna",
          "viewer.export.vectorMotion": "Vector y movimiento",
          "viewer.export.vectorMotion.heading": "Vector y movimiento",
          "viewer.export.editable": "Vector editable",
          "viewer.export.svg.auto": "SVG · Auto",
          "viewer.export.svg.auto.hint": "Coincide con el tema del host",
          "viewer.export.svg.light": "SVG · Claro",
          "viewer.export.svg.light.hint": "Siempre claro",
          "viewer.export.svg.dark": "SVG · Oscuro",
          "viewer.export.svg.dark.hint": "Siempre oscuro",
          "viewer.export.motion6s": "Movimiento de 6 s",
          "viewer.export.unsupported": "No compatible con este navegador",
          "viewer.export.clipboardUnsupported": "Este navegador no admite escribir imágenes en el portapapeles",
          "viewer.export.clipboardUnsupported.short": "Escritura de imágenes en el portapapeles no admitida en este navegador.",
          "viewer.export.motionUnavailable": "Captura de movimiento no disponible en este navegador",
          "viewer.export.webmUnavailable": "WebM no disponible en este navegador",
          "viewer.export.failed": "Falló la exportación: {message}",
          "viewer.export.unknownVariant": "Variante de tarjeta para compartir desconocida: {variant}",
          "viewer.export.routeRequired": "Traza una ruta antes de exportar una tarjeta de ruta para compartir",
          "viewer.export.reachRequired": "Traza el alcance definido antes de exportar una tarjeta de alcance para compartir",
          "viewer.export.unknown": "desconocido",
          "viewer.export.routeFailed": "Falló la exportación de la tarjeta de ruta para compartir: {message}",
          "viewer.export.reachFailed": "Falló la exportación de la tarjeta de alcance para compartir: {message}",
          "viewer.export.copyFailed": "Error al copiar: {message}",
          "viewer.export.copiedPng": "PNG copiado al portapapeles",
          "viewer.export.downloadedRoute": "Tarjeta de ruta para compartir descargada",
          "viewer.export.downloadedReach": "Tarjeta de alcance para compartir descargada",
          "viewer.export.downloadedWebm": "WebM descargado",
          "viewer.export.recording": "Grabando 6 segundos de movimiento…",
          "viewer.export.card.routeSummary.one": "Ruta: {source} → {target} · {count} paso",
          "viewer.export.card.routeSummary.other": "Ruta: {source} → {target} · {count} pasos",
          "viewer.export.card.reachSummary": "Alcance definido {direction} desde {origin} · {nodes} · {links} · máx {hops}",
          "viewer.export.card.node.one": "{count} nodo",
          "viewer.export.card.node.other": "{count} nodos",
          "viewer.export.card.link.one": "{count} enlace",
          "viewer.export.card.link.other": "{count} enlaces",
          "viewer.export.card.hop.one": "{count} salto",
          "viewer.export.card.hop.other": "{count} saltos",
          "viewer.export.card.routeBadge": "ARCHIFY · RUTA · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · ALCANCE {direction}",
          "viewer.export.direction.upstream": "Ascendente",
          "viewer.export.direction.downstream": "Descendente",
          "viewer.export.error.canvasUnavailable": "Lienzo no disponible para {label}",
          "viewer.export.error.contextUnavailable": "Contexto de lienzo 2D no disponible para {label}",
          "viewer.export.error.toBlobUnavailable": "canvas.toBlob no disponible para {label}",
          "viewer.export.error.toBlobNull": "canvas.toBlob no devolvió datos para {label}",
          "viewer.export.error.variantsCombined": "Las variantes de tarjeta para compartir no se pueden combinar",
          "viewer.export.error.viewerState": "La exportación de la tarjeta para compartir no pudo quitar el estado temporal del visor",
          "viewer.export.error.routeState": "La exportación de la tarjeta de ruta no pudo preservar la ruta resuelta de forma segura",
          "viewer.export.error.reachState": "La exportación de la tarjeta de alcance no pudo preservar el alcance definido de forma segura",
          "viewer.export.error.webmRequirements": "La exportación de movimiento WebM requiere una animación de traza y compatibilidad del navegador con MediaRecorder",
          "viewer.export.error.mediaRecorder": "MediaRecorder falló",
          "viewer.export.error.emptyWebm": "MediaRecorder produjo un WebM vacío",
          "viewer.export.error.webmBackground": "No se pudo cargar el fondo SVG para la exportación WebM",
          "viewer.guide.title": "Explorar este sistema",
          "viewer.focus.selectedNodes": "{count} nodos seleccionados",
          "viewer.guide.eyebrow": "Guía del diagrama",
          "viewer.guide.close": "Cerrar la guía del diagrama",
          "viewer.guide.inspecting": "Inspeccionando la semántica compilada",
          "viewer.guide.actions": "Acciones de exploración del diagrama",
          "viewer.guide.find": "Buscar cualquier nodo",
          "viewer.guide.find.hint": "Busca por etiquetas, responsabilidades, tipos e IDs estables.",
          "viewer.guide.route": "Trazar una ruta",
          "viewer.guide.route.aria": "Trazar una ruta dirigida",
          "viewer.guide.route.hint": "Pregunta cómo se conectan dos nodos semánticos en el sentido definido.",
          "viewer.guide.map": "Ver todo el sistema",
          "viewer.guide.map.hint": "Abre el Radar semántico con un viewport en vivo y nodos estables.",
          "viewer.guide.lens": "Comparar tipos semánticos",
          "viewer.guide.lens.hint": "Cuenta roles, revela su tráfico y compara enlaces directos definidos.",
          "viewer.guide.present": "Entrar al modo presentación",
          "viewer.guide.present.hint": "Dale al diagrama en vivo todo el viewport sin cambiar la exportación.",
          "viewer.guide.shortcuts": "Atajos de teclado adicionales",
          "viewer.guide.shortcut.export": "Exportar",
          "viewer.guide.shortcut.theme": "Tema",
          "viewer.guide.shortcut.style": "Estilo",
          "viewer.guide.shortcut.reset": "Restablecer",
          "viewer.guide.shortcut.zoomIn": "Acercar",
          "viewer.guide.shortcut.zoomOut": "Alejar",
          "viewer.guide.shortcut.close": "Cerrar",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} nodo semántico",
          "viewer.guide.fact.node.other": "{count} nodos semánticos",
          "viewer.guide.fact.relationship.one": "{count} relación",
          "viewer.guide.fact.relationship.other": "{count} relaciones",
          "viewer.guide.open": "Abrir la guía del diagrama",
          "viewer.finder.title": "Buscar un nodo",
          "viewer.finder.close": "Cerrar el buscador de nodos",
          "viewer.finder.placeholder": "Buscar etiquetas o IDs",
          "viewer.finder.search": "Buscar nodos del diagrama",
          "viewer.finder.results": "Nodos del diagrama",
          "viewer.finder.empty": "No hay nodos coincidentes",
          "viewer.finder.result.focus": "Enfocar {label}",
          "viewer.finder.result.routeStart": "Elegir {label} como inicio de la ruta",
          "viewer.finder.result.routeTarget": "Elegir {label} como destino de la ruta, {links}",
          "viewer.finder.status.empty": "No hay nodos coincidentes",
          "viewer.finder.status.count.one": "{count} nodo coincidente",
          "viewer.finder.status.count.other": "{count} nodos coincidentes",
          "viewer.finder.noun.nodes": "nodos",
          "viewer.finder.link.one": "{count} enlace",
          "viewer.finder.link.other": "{count} enlaces",
          "viewer.finder.result.focus.one": "Enfocar {label}, {count} conexión relacionada",
          "viewer.finder.result.focus.other": "Enfocar {label}, {count} conexiones relacionadas",
          "viewer.finder.status.filtered": "{visible} de {available} {noun}",
          "viewer.finder.status.all": "{available} {noun}",
          "viewer.passport.eyebrow": "Pasaporte semántico",
          "viewer.passport.metadata": "Metadatos del nodo",
          "viewer.passport.evidence": "Evidencia de fuente verificada",
          "viewer.passport.verified": "Fuente verificada",
          "viewer.passport.verificationScope": "Verificado contra el Git local en la revisión fijada. No se ha comprobado el acceso remoto.",
          "viewer.passport.reach": "Alcance definido",
          "viewer.passport.reach.trace": "Trazar la alcanzabilidad definida",
          "viewer.passport.upstream": "Ascendente",
          "viewer.passport.downstream": "Descendente",
          "viewer.passport.upstream.trace": "Trazar la alcanzabilidad definida ascendente",
          "viewer.passport.downstream.trace": "Trazar la alcanzabilidad definida descendente",
          "viewer.passport.close": "Cerrar el pasaporte semántico",
          "viewer.passport.move": "Mover el pasaporte semántico. Arrastra, usa las flechas o pulsa Inicio para restablecer.",
          "viewer.passport.copy": "Copiar enlace",
          "viewer.passport.copy.focus": "Copiar enlace al nodo enfocado",
          "viewer.passport.relations": "Relaciones",
          "viewer.passport.relations.show": "Mostrar relaciones conectadas",
          "viewer.passport.relations.hide": "Ocultar relaciones conectadas",
          "viewer.passport.relations.list": "Relaciones conectadas",
          "viewer.passport.copyRelation": "Copiar relación",
          "viewer.passport.copyNode": "Copiar nodo",
          "viewer.passport.copyPinned": "Copiar enlace a la relación fijada",
          "viewer.passport.copySource": "Copiar enlace al nodo de origen",
          "viewer.passport.copy.focused.success": "Enlace del nodo enfocado copiado",
          "viewer.passport.copy.pinned.success": "Enlace de la relación fijada copiado",
          "viewer.passport.copy.focused.failed": "No se pudo copiar el enlace del nodo enfocado",
          "viewer.passport.copy.pinned.failed": "No se pudo copiar el enlace de la relación fijada",
          "viewer.passport.relationship.none": "No hay relaciones conectadas",
          "viewer.passport.relationship.count.one": "{count} relación",
          "viewer.passport.relationship.count.other": "{count} relaciones",
          "viewer.passport.relationship.show.one": "Mostrar {count} relación conectada",
          "viewer.passport.relationship.show.other": "Mostrar {count} relaciones conectadas",
          "viewer.passport.relationship.summary": "{out} salientes · {in} entrantes{loops}",
          "viewer.passport.relationship.loops": " · {count} bucle",
          "viewer.passport.relationship.explorer": "Explorador de relaciones directas",
          "viewer.passport.relationship.help": "Usa las flechas para explorar las relaciones. Pulsa Enter o Espacio para fijar detalles; Escape las borra.",
          "viewer.passport.relationship.loopsBack": "vuelve sobre sí mismo",
          "viewer.passport.relationship.connectsTo": "conecta a",
          "viewer.passport.relationship.connectsFrom": "conecta desde",
          "viewer.passport.relationship.pinned": "Relación fijada · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "Inspeccionar relación {index} de {total}: {from} a {to}, {label}. Pulsa Enter para ver detalles.",
          "viewer.passport.relationship.group.out": "Salientes",
          "viewer.passport.relationship.group.in": "Entrantes",
          "viewer.passport.relationship.group.loop": "Bucles propios",
          "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "SAL →",
          "viewer.passport.relationship.direction.in": "← ENT",
          "viewer.passport.relationship.direction.loop": "BUCLE",
          "viewer.passport.sourceCount.one": "{count} referencia de fuente verificada",
          "viewer.passport.sourceCount.other": "{count} referencias de fuente verificadas",
          "viewer.passport.sourceMarker": "SRC",
          "viewer.passport.beacon.one": "{count} fuente verificada; enfoca este nodo para inspeccionar",
          "viewer.passport.beacon.other": "{count} fuentes verificadas; enfoca este nodo para inspeccionar",
          "viewer.passport.repository.open": "Abrir la revisión verificada del repositorio {revision}",
          "viewer.passport.source.open": "Abrir la fuente verificada {path} en la revisión {revision}",
          "viewer.passport.source.openLink": "Abrir ↗",
          "viewer.passport.reach.upstream.one": "Trazar {count} nodo definido ascendente",
          "viewer.passport.reach.upstream.other": "Trazar {count} nodos definidos ascendentes",
          "viewer.passport.reach.downstream.one": "Trazar {count} nodo definido descendente",
          "viewer.passport.reach.downstream.other": "Trazar {count} nodos definidos descendentes",
          "viewer.passport.reach.noUpstream": "No hay nodos definidos ascendentes",
          "viewer.passport.reach.noDownstream": "No hay nodos definidos descendentes",
          "viewer.passport.reach.status": "{direction} · {nodes} nodos · {links} enlaces · máx {hops} saltos",
          "viewer.route.eyebrow": "Ruta",
          "viewer.route.start": "Haz clic donde empieza la ruta",
          "viewer.route.start.find": "Buscar inicio",
          "viewer.route.start.find.aria": "Buscar un inicio de ruta",
          "viewer.route.copy": "Copiar enlace",
          "viewer.route.copy.aria": "Copiar enlace a la ruta trazada",
          "viewer.route.clear": "Borrar",
          "viewer.route.clear.aria": "Borrar la sonda de ruta",
          "viewer.route.traced": "Ruta",
          "viewer.route.pickTwo": "Haz clic en dos nodos del diagrama",
          "viewer.route.pickOne": "Haz clic en un nodo del diagrama",
          "viewer.route.controls": "Controles del recorrido de la ruta",
          "viewer.route.previous": "Posición anterior de la ruta",
          "viewer.route.play": "Reproducir el recorrido de la ruta",
          "viewer.route.pause": "Pausar el recorrido de la ruta",
          "viewer.route.replay": "Repetir el recorrido de la ruta",
          "viewer.route.next": "Posición siguiente de la ruta",
          "viewer.route.journey": "Recorrido",
          "viewer.route.pause.label": "Pausar",
          "viewer.route.replay.label": "Repetir",
          "viewer.route.overview": "Vista general",
          "viewer.route.overview.aria": "Mostrar la vista general completa de la ruta",
          "viewer.route.instructions": "Haz clic en un inicio y luego en un final. La ruta sigue las flechas.",
          "viewer.route.destination": "¿Dónde termina la ruta desde {label}?",
          "viewer.route.destination.find": "Buscar destino",
          "viewer.route.destination.find.aria": "Buscar un destino de ruta alcanzable",
          "viewer.route.differentDestination": "Elige un destino diferente",
          "viewer.route.distinct": "Elige dos nodos distintos.",
          "viewer.route.unreachable": "No se llega a {label} desde aquí",
          "viewer.route.unreachable.detail": "No se llega a {target} desde {source} siguiendo las flechas. Elige un nodo resaltado.",
          "viewer.route.start.instructions": "Luego elige el final. Solo se iluminan los nodos alcanzables.",
          "viewer.route.copy.success": "Enlace de la ruta trazada copiado",
          "viewer.route.copy.failed": "No se pudo copiar el enlace de la ruta trazada",
          "viewer.route.position": "Posición de la ruta {index} de {total}: {label}",
          "viewer.route.step": "Paso {index} de {total} · {phase} · {label}",
          "viewer.route.motionRequired": "El recorrido automático requiere la animación Activa",
          "viewer.route.trigger.clear": "Borrar la ruta trazada",
          "viewer.route.overview.status": "{nodes} · {hops} · ruta más corta",
          "viewer.route.overview.node.one": "{count} nodo",
          "viewer.route.overview.node.other": "{count} nodos",
          "viewer.route.overview.hop.one": "{count} paso",
          "viewer.route.overview.hop.other": "{count} pasos",
          "viewer.route.phase.playing": "Reproduciendo",
          "viewer.route.phase.complete": "Completo",
          "viewer.route.phase.inspecting": "Inspeccionando",
          "viewer.route.destination.count.one": "{count} nodo alcanzable está resaltado. Haz clic en él.",
          "viewer.route.destination.count.other": "{count} nodos alcanzables están resaltados. Haz clic en uno.",
          "viewer.route.noOutgoing": "Ninguna flecha sale de este nodo. Bórralo y elige otro inicio.",
          "viewer.route.result.title": "{source} a {target}",
          "viewer.route.finder.source.title": "Elegir el inicio de la ruta",
          "viewer.route.finder.source.placeholder": "Buscar orígenes de ruta",
          "viewer.route.finder.source.empty": "No hay orígenes de ruta coincidentes",
          "viewer.route.finder.source.results": "Nodos que pueden iniciar una ruta",
          "viewer.route.finder.source.noun": "orígenes de ruta",
          "viewer.route.finder.source.badge": "inicio",
          "viewer.route.finder.target.title": "Destino desde {label}",
          "viewer.route.finder.target.placeholder": "Buscar destinos alcanzables",
          "viewer.route.finder.target.empty": "No hay destinos alcanzables coincidentes",
          "viewer.route.finder.target.results": "Destinos de ruta alcanzables",
          "viewer.route.finder.target.noun": "destinos alcanzables",
          "viewer.route.hop.one": "{count} salto",
          "viewer.route.hop.other": "{count} saltos",
          "viewer.lens.eyebrow": "Lente semántico",
          "viewer.lens.title": "Comparar roles del sistema",
          "viewer.lens.close": "Cerrar el lente semántico",
          "viewer.lens.instruction": "Elige hasta dos tipos semánticos. Uno revela su tráfico real; dos comparan solo las relaciones directas definidas.",
          "viewer.lens.kinds": "Tipos semánticos",
          "viewer.lens.choose": "Elige un tipo para inspeccionar sus nodos y las relaciones que lo tocan.",
          "viewer.lens.copy": "Copiar enlace al lente semántico",
          "viewer.lens.clear": "Borrar el lente semántico",
          "viewer.lens.open": "Abrir el lente semántico",
          "viewer.lens.openActive": "Abrir el lente semántico activo",
          "viewer.lens.legend": "Leyenda semántica",
          "viewer.lens.legend.inspect.one": "Inspeccionar {label}, {count} nodo",
          "viewer.lens.legend.inspect.other": "Inspeccionar {label}, {count} nodos",
          "viewer.lens.kind.count.one": "{label}, {count} nodo",
          "viewer.lens.kind.count.other": "{label}, {count} nodos",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} relación directa",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} relaciones directas",
          "viewer.lens.single": "{nodes} · {relationships} · los pares conectados permanecen visibles",
          "viewer.lens.node.one": "{count} nodo {label}",
          "viewer.lens.node.other": "{count} nodos {label}",
          "viewer.lens.relationship.one": "{count} relación en contacto",
          "viewer.lens.relationship.other": "{count} relaciones en contacto",
          "viewer.radar.title": "Radar semántico",
          "viewer.radar.building": "Construyendo la vista general",
          "viewer.radar.openFull": "Abrir el radar semántico completo",
          "viewer.radar.open": "Abrir el radar",
          "viewer.radar.close": "Cerrar el radar semántico",
          "viewer.radar.surface": "Vista general del diagrama. Haz clic en un nodo para enfocarlo, o usa las flechas para desplazarte.",
          "viewer.radar.click": "Clic en el nodo",
          "viewer.radar.drag": "Arrastra para desplazar",
          "viewer.radar.space": "El radar semántico necesita más espacio de MAPA.",
          "viewer.radar.nodes": "Nodos del radar del diagrama semántico",
          "viewer.radar.focus": "Enfocar {label} desde el Radar semántico",
          "viewer.radar.status": "{count} nodos · {viewport}",
          "viewer.radar.fullMap": "{count} nodos · mapa completo",
          "viewer.radar.compacted": "Radar compactado para no tapar el Pasaporte semántico ni los controles de MAPA.",
          "viewer.radar.cancelWaiting": "Cancelar la espera del radar semántico por más espacio de MAPA",
          "viewer.radar.needsSpace": "El radar semántico necesita más espacio de MAPA visible",
          "viewer.radar.viewport.full": "mapa completo",
          "viewer.radar.viewport.width": "{percent}% de ancho",
          "viewer.radar.viewport.scale": "{percent}% del viewport",
          "viewer.nav.controls": "Controles de vista del diagrama",
          "viewer.nav.route": "Trazar una ruta dirigida",
          "viewer.nav.route.title": "Trazar ruta (R)",
          "viewer.nav.route.short": "RUTA",
          "viewer.nav.radar": "Abrir el radar semántico",
          "viewer.nav.radar.title": "Radar semántico (M)",
          "viewer.nav.radar.short": "MAPA",
          "viewer.nav.lens": "Abrir el lente semántico",
          "viewer.nav.lens.title": "Lente semántico (L)",
          "viewer.nav.lens.short": "LENTE",
          "viewer.nav.find": "Buscar un nodo",
          "viewer.nav.find.title": "Buscar un nodo (/)",
          "viewer.outline.title": "Índice de nodos",
          "viewer.rail.show": "Notas e índice",
          "viewer.rail.controls": "Panel lateral",
          "viewer.rail.collapse": "Contraer panel lateral",
          "viewer.rail.bottom": "Mover el panel debajo",
          "viewer.rail.right": "Mover el panel al lado",
          "viewer.nav.guide": "Abrir la guía del diagrama",
          "viewer.nav.guide.title": "Guía del diagrama (?)",
          "viewer.nav.zoomOut": "Alejar",
          "viewer.nav.zoomOut.title": "Alejar (-)",
          "viewer.nav.reset": "Restablecer la vista del diagrama",
          "viewer.nav.reset.title": "Restablecer vista (0)",
          "viewer.nav.read": "LEER",
          "viewer.nav.zoomIn": "Acercar",
          "viewer.nav.zoomIn.title": "Acercar (+)",
          "viewer.nav.camera": "{hint}. Restablecer la vista del diagrama",
          "viewer.nav.camera.title": "{semantic}{hint} · restablecer vista (0)",
          "viewer.nav.camera.semantic": "Cámara semántica activa · ",
          "viewer.nav.level.map": "MAPA",
          "viewer.nav.level.read": "LEER",
          "viewer.nav.level.full": "COMPLETO",
          "viewer.nav.level.auto": "AUTO",
          "viewer.nav.detail.map": "Acerca para revelar las etiquetas de relación y el contexto de los nodos",
          "viewer.nav.detail.read": "Acerca de nuevo para revelar etiquetas y anotaciones",
          "viewer.nav.detail.full": "Detalle completo del diagrama",
          "viewer.intent.summary": "{label}. {out} salientes, {in} entrantes{loops}. {total} conexiones. Pulsa Enter para ver detalles.",
          "viewer.intent.loops": ", {count} bucle propio",
          "viewer.common.copied": "Copiado",
          "viewer.common.copyFailed": "Error al copiar",
          "viewer.common.copyLink": "Copiar enlace",
          "viewer.common.clear": "Borrar",
          "viewer.common.close": "Cerrar"
        }
        
      • fr.json 26.7 KB
        {
          "page.title": "Diagramme {title}",
          "diagram.description.architecture": "Un diagramme d'architecture généré par Archify.",
          "diagram.description.workflow": "Un diagramme de workflow généré par Archify.",
          "diagram.description.sequence": "Un diagramme de séquence généré par Archify.",
          "diagram.description.dataflow": "Un diagramme de flux de données généré par Archify.",
          "diagram.description.lifecycle": "Un diagramme de cycle de vie généré par Archify.",
          "node.focus": "Centrer sur {label}",
          "node.focus.detail": "Centrer sur {label}, {detail}",
          "node.context.architecture": "Composant d'architecture",
          "node.context.workflow": "Nœud de workflow",
          "node.context.sequence": "Participant de séquence",
          "node.context.dataflow": "Nœud de flux de données",
          "node.context.lifecycle": "État de cycle de vie",
          "legend.title": "Légende",
          "legend.architecture.frontend": "Frontend",
          "legend.architecture.backend": "Backend",
          "legend.architecture.database": "Base de données",
          "legend.architecture.cloud": "Cloud",
          "legend.architecture.security": "Sécurité",
          "legend.architecture.messagebus": "Bus de messages",
          "legend.architecture.external": "Externe",
          "legend.workflow.frontend": "Interface utilisateur",
          "legend.workflow.backend": "Logique de l'agent",
          "legend.workflow.security": "Politique",
          "legend.workflow.messagebus": "Action d'outil",
          "legend.workflow.database": "Contexte / trace",
          "legend.workflow.cloud": "Service cloud",
          "legend.workflow.external": "Système externe",
          "legend.sequence.emphasis": "requête principale",
          "legend.sequence.return": "retour",
          "legend.sequence.security": "sécurité",
          "legend.sequence.dashed": "trace asynchrone",
          "legend.sequence.default": "message",
          "legend.dataflow.emphasis": "donnée principale",
          "legend.dataflow.security": "politique / PII",
          "legend.dataflow.dashed": "lot asynchrone",
          "legend.dataflow.database": "entrepôt de données",
          "legend.dataflow.default": "flux de données",
          "legend.lifecycle.start": "état initial",
          "legend.lifecycle.active": "actif",
          "legend.lifecycle.waiting": "attente",
          "legend.lifecycle.decision": "décision",
          "legend.lifecycle.success": "succès",
          "legend.lifecycle.failure": "échec / sortie",
          "legend.lifecycle.neutral": "neutre",
          "legend.lifecycle.external": "externe",
          "legend.lifecycle.final": "état final",
          "viewer.kind.frontend": "Frontend",
          "viewer.kind.backend": "Backend",
          "viewer.kind.database": "Base de données",
          "viewer.kind.cloud": "Cloud",
          "viewer.kind.security": "Sécurité",
          "viewer.kind.messagebus": "Bus de messages",
          "viewer.kind.external": "Externe",
          "viewer.kind.neutral": "Neutre",
          "viewer.kind.node": "Nœud",
          "viewer.kind.start": "Début",
          "viewer.kind.active": "Actif",
          "viewer.kind.waiting": "En attente",
          "viewer.kind.decision": "Décision",
          "viewer.kind.success": "Succès",
          "viewer.kind.failure": "Échec",
          "viewer.toolbar.actions": "Actions du diagramme",
          "viewer.theme.toggle.title": "Changer de thème (T)",
          "viewer.theme.toggle": "Changer le thème de couleur",
          "viewer.theme.dark": "Sombre",
          "viewer.theme.light": "Clair",
          "viewer.preset.choose.title": "Choisir le style visuel (S pour changer)",
          "viewer.preset.choose": "Choisir le style visuel",
          "viewer.preset.style": "Style",
          "viewer.preset.menu": "Style visuel",
          "viewer.preset.identity": "Identité visuelle",
          "viewer.preset.cycles": "S pour changer",
          "viewer.preset.classic": "Classic",
          "viewer.preset.classic.short": "Classic",
          "viewer.preset.classic.hint": "Style technique stable par défaut",
          "viewer.preset.flow": "Flux de signal",
          "viewer.preset.flow.short": "Flux",
          "viewer.preset.flow.hint": "Présentation animée et dynamique",
          "viewer.preset.blueprint": "Plan",
          "viewer.preset.blueprint.hint": "Revue technique",
          "viewer.preset.editorial": "Éditorial",
          "viewer.preset.editorial.hint": "Notes de publication et de lancement",
          "viewer.preset.badge.signalFlow": "FLUX DE SIGNAL",
          "viewer.preset.badge.blueprint": "PLAN / RÉV. 01",
          "viewer.preset.badge.editorial": "ÉDITORIAL / NOTE DE TERRAIN",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / PLANCHE 04",
          "viewer.preset.current": "Style visuel : {style}. Choisir le style visuel",
          "viewer.motion.live": "Animé",
          "viewer.motion.still": "Statique",
          "viewer.motion.pause": "Mettre l'animation en pause",
          "viewer.motion.resume": "Reprendre l'animation",
          "viewer.motion.reduced": "Animation suspendue en raison de la préférence de mouvement réduit",
          "viewer.motion.hidden": "Animation suspendue pendant que la page est masquée",
          "viewer.motion.yielding": "Mettre l'animation en pause ; cède actuellement la place à {owner}",
          "viewer.motion.yielding.title": "Aperçu en direct activé · cède la place à {owner}",
          "viewer.owner.route": "Sonde d'itinéraire",
          "viewer.owner.lens": "Lentille sémantique",
          "viewer.owner.relationship": "Aperçu de relation",
          "viewer.owner.intent": "Trace d'intention",
          "viewer.owner.focus": "le focus sémantique",
          "viewer.owner.legend": "l'aperçu de la légende",
          "viewer.owner.reader": "l'interaction du lecteur",
          "viewer.present.enter": "Entrer en mode présentation",
          "viewer.present.enter.title": "Mode présentation (F)",
          "viewer.present.exit": "Quitter le mode présentation",
          "viewer.present.exit.title": "Quitter le mode présentation (F ou Échap)",
          "viewer.present.present": "Présenter",
          "viewer.present.exit.label": "Quitter",
          "viewer.export.button": "Exporter",
          "viewer.export.button.title": "Exporter le diagramme (E)",
          "viewer.export.diagram": "Exporter le diagramme",
          "viewer.export.menu": "Exporter",
          "viewer.export.subtitle": "Des exports portables et soignés",
          "viewer.export.share": "Partager",
          "viewer.export.shareCard": "Carte de partage",
          "viewer.export.routeShareCard": "Carte de partage d'itinéraire",
          "viewer.export.reachShareCard": "Carte de partage de portée",
          "viewer.export.copyDiagram": "Copier le diagramme",
          "viewer.export.clipboardPng": "PNG vers le presse-papiers",
          "viewer.export.raster": "Images matricielles",
          "viewer.export.image": "Image",
          "viewer.export.lossless": "Image sans perte",
          "viewer.export.compact": "Image compacte",
          "viewer.export.modern": "Image au format moderne",
          "viewer.export.vectorMotion": "Vecteur et animation",
          "viewer.export.vectorMotion.heading": "Vecteur et animation",
          "viewer.export.editable": "Vecteur modifiable",
          "viewer.export.motion6s": "Animation de 6 s",
          "viewer.export.unsupported": "Non pris en charge par ce navigateur",
          "viewer.export.clipboardUnsupported": "L'écriture d'image dans le presse-papiers n'est pas prise en charge par ce navigateur",
          "viewer.export.clipboardUnsupported.short": "L'écriture d'image dans le presse-papiers n'est pas prise en charge par ce navigateur.",
          "viewer.export.motionUnavailable": "Capture d'animation indisponible dans ce navigateur",
          "viewer.export.webmUnavailable": "WebM indisponible dans ce navigateur",
          "viewer.export.failed": "Échec de l'export : {message}",
          "viewer.export.unknownVariant": "Variante de carte de partage inconnue : {variant}",
          "viewer.export.routeRequired": "Tracez un itinéraire avant d'exporter une carte de partage d'itinéraire",
          "viewer.export.reachRequired": "Tracez une portée éditée avant d'exporter une carte de partage de portée",
          "viewer.export.unknown": "inconnu",
          "viewer.export.routeFailed": "Échec de l'export de la carte de partage d'itinéraire : {message}",
          "viewer.export.reachFailed": "Échec de l'export de la carte de partage de portée : {message}",
          "viewer.export.copyFailed": "Échec de la copie : {message}",
          "viewer.export.copiedPng": "PNG copié dans le presse-papiers",
          "viewer.export.downloadedRoute": "Carte de partage d'itinéraire téléchargée",
          "viewer.export.downloadedReach": "Carte de partage de portée téléchargée",
          "viewer.export.downloadedWebm": "WebM téléchargé",
          "viewer.export.recording": "Enregistrement de 6 secondes d'animation…",
          "viewer.export.card.routeSummary.one": "Itinéraire : {source} → {target} · {count} saut orienté",
          "viewer.export.card.routeSummary.other": "Itinéraire : {source} → {target} · {count} sauts orientés",
          "viewer.export.card.reachSummary": "Portée {direction} éditée depuis {origin} · {nodes} · {links} · max {hops}",
          "viewer.export.card.node.one": "{count} nœud",
          "viewer.export.card.node.other": "{count} nœuds",
          "viewer.export.card.link.one": "{count} lien",
          "viewer.export.card.link.other": "{count} liens",
          "viewer.export.card.hop.one": "{count} saut",
          "viewer.export.card.hop.other": "{count} sauts",
          "viewer.export.card.routeBadge": "ARCHIFY · ITINÉRAIRE · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · PORTÉE {direction}",
          "viewer.export.direction.upstream": "Amont",
          "viewer.export.direction.downstream": "Aval",
          "viewer.export.error.canvasUnavailable": "Canevas indisponible pour {label}",
          "viewer.export.error.contextUnavailable": "Contexte de canevas 2D indisponible pour {label}",
          "viewer.export.error.toBlobUnavailable": "canvas.toBlob indisponible pour {label}",
          "viewer.export.error.toBlobNull": "canvas.toBlob n'a renvoyé aucune donnée pour {label}",
          "viewer.export.error.variantsCombined": "Les variantes de carte de partage ne peuvent pas être combinées",
          "viewer.export.error.viewerState": "L'export de la carte de partage n'a pas pu supprimer l'état temporaire du visualiseur",
          "viewer.export.error.routeState": "L'export de la carte d'itinéraire n'a pas pu préserver l'itinéraire résolu en toute sécurité",
          "viewer.export.error.reachState": "L'export de la carte de portée n'a pas pu préserver la portée éditée en toute sécurité",
          "viewer.export.error.webmRequirements": "L'export d'animation WebM nécessite une animation de trace et la prise en charge de MediaRecorder par le navigateur",
          "viewer.export.error.mediaRecorder": "Échec de MediaRecorder",
          "viewer.export.error.emptyWebm": "MediaRecorder a produit un fichier WebM vide",
          "viewer.export.error.webmBackground": "L'arrière-plan SVG n'a pas pu être chargé pour l'export WebM",
          "viewer.guide.eyebrow": "Guide du diagramme",
          "viewer.guide.close": "Fermer le guide du diagramme",
          "viewer.guide.inspecting": "Inspection de la sémantique compilée",
          "viewer.guide.actions": "Actions d'exploration du diagramme",
          "viewer.guide.find": "Trouver un nœud",
          "viewer.guide.find.hint": "Rechercher par libellés, responsabilités, types et identifiants stables.",
          "viewer.guide.route": "Tracer un itinéraire",
          "viewer.guide.route.aria": "Tracer un itinéraire orienté",
          "viewer.guide.route.hint": "Découvrez comment deux nœuds sémantiques sont reliés dans le sens édité.",
          "viewer.guide.map": "Voir tout le système",
          "viewer.guide.map.hint": "Ouvrir le radar sémantique avec un viewport en direct et des nœuds stables.",
          "viewer.guide.lens": "Comparer les types sémantiques",
          "viewer.guide.lens.hint": "Comptez les rôles, révélez leur trafic et comparez les liens édités directs.",
          "viewer.guide.present": "Entrer en mode présentation",
          "viewer.guide.present.hint": "Donnez tout le viewport au diagramme en direct sans modifier l'export.",
          "viewer.guide.shortcuts": "Raccourcis clavier supplémentaires",
          "viewer.guide.shortcut.export": "Exporter",
          "viewer.guide.shortcut.theme": "Thème",
          "viewer.guide.shortcut.style": "Style",
          "viewer.guide.shortcut.reset": "Réinitialiser",
          "viewer.guide.shortcut.zoomIn": "Zoom avant",
          "viewer.guide.shortcut.zoomOut": "Zoom arrière",
          "viewer.guide.shortcut.close": "Fermer",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} nœud sémantique",
          "viewer.guide.fact.node.other": "{count} nœuds sémantiques",
          "viewer.guide.fact.relationship.one": "{count} relation",
          "viewer.guide.fact.relationship.other": "{count} relations",
          "viewer.guide.open": "Ouvrir le guide du diagramme",
          "viewer.finder.title": "Trouver un nœud",
          "viewer.finder.close": "Fermer le chercheur de nœuds",
          "viewer.finder.placeholder": "Rechercher par libellé ou identifiant",
          "viewer.finder.search": "Rechercher les nœuds du diagramme",
          "viewer.finder.results": "Nœuds du diagramme",
          "viewer.finder.empty": "Aucun nœud correspondant",
          "viewer.finder.result.focus": "Centrer sur {label}",
          "viewer.finder.result.routeStart": "Choisir {label} comme point de départ de l'itinéraire",
          "viewer.finder.result.routeTarget": "Choisir {label} comme destination de l'itinéraire, {links}",
          "viewer.finder.status.empty": "Aucun nœud correspondant",
          "viewer.finder.status.count.one": "{count} nœud correspondant",
          "viewer.finder.status.count.other": "{count} nœuds correspondants",
          "viewer.finder.noun.nodes": "nœuds",
          "viewer.finder.link.one": "{count} lien",
          "viewer.finder.link.other": "{count} liens",
          "viewer.finder.result.focus.one": "Centrer sur {label}, {count} connexion associée",
          "viewer.finder.result.focus.other": "Centrer sur {label}, {count} connexions associées",
          "viewer.finder.status.filtered": "{visible} sur {available} {noun}",
          "viewer.finder.status.all": "{available} {noun}",
          "viewer.passport.eyebrow": "Passeport sémantique",
          "viewer.passport.metadata": "Métadonnées du nœud",
          "viewer.passport.evidence": "Preuve de source vérifiée",
          "viewer.passport.verified": "Source vérifiée",
          "viewer.passport.verificationScope": "Vérifié par rapport au Git local à la révision épinglée. L'accès distant n'a pas été vérifié.",
          "viewer.passport.reach": "Portée éditée",
          "viewer.passport.reach.trace": "Tracer l'accessibilité éditée",
          "viewer.passport.upstream": "Amont",
          "viewer.passport.downstream": "Aval",
          "viewer.passport.upstream.trace": "Tracer l'accessibilité éditée en amont",
          "viewer.passport.downstream.trace": "Tracer l'accessibilité éditée en aval",
          "viewer.passport.close": "Fermer le passeport sémantique",
          "viewer.passport.copy": "Copier le lien",
          "viewer.passport.copy.focus": "Copier le lien du nœud centré",
          "viewer.passport.relations": "Relations",
          "viewer.passport.relations.show": "Afficher les relations connectées",
          "viewer.passport.relations.hide": "Masquer les relations connectées",
          "viewer.passport.relations.list": "Relations connectées",
          "viewer.passport.copyRelation": "Copier la relation",
          "viewer.passport.copyNode": "Copier le nœud",
          "viewer.passport.copyPinned": "Copier le lien de la relation épinglée",
          "viewer.passport.copySource": "Copier le lien du nœud source",
          "viewer.passport.copy.focused.success": "Lien du nœud centré copié",
          "viewer.passport.copy.pinned.success": "Lien de la relation épinglée copié",
          "viewer.passport.copy.focused.failed": "Impossible de copier le lien du nœud centré",
          "viewer.passport.copy.pinned.failed": "Impossible de copier le lien de la relation épinglée",
          "viewer.passport.relationship.none": "Aucune relation connectée",
          "viewer.passport.relationship.count.one": "{count} relation",
          "viewer.passport.relationship.count.other": "{count} relations",
          "viewer.passport.relationship.show.one": "Afficher {count} relation connectée",
          "viewer.passport.relationship.show.other": "Afficher {count} relations connectées",
          "viewer.passport.relationship.summary": "{out} sortantes · {in} entrantes{loops}",
          "viewer.passport.relationship.loops": " · {count} boucle",
          "viewer.passport.relationship.explorer": "Explorateur de relations directes",
          "viewer.passport.relationship.help": "Utilisez les flèches pour explorer les relations. Appuyez sur Entrée ou Espace pour épingler les détails ; Échap efface.",
          "viewer.passport.relationship.loopsBack": "boucle vers",
          "viewer.passport.relationship.connectsTo": "se connecte à",
          "viewer.passport.relationship.connectsFrom": "se connecte depuis",
          "viewer.passport.relationship.pinned": "Relation épinglée · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "Inspecter la relation {index} sur {total} : {from} vers {to}, {label}. Appuyez sur Entrée pour les détails.",
          "viewer.passport.relationship.group.out": "Sortantes",
          "viewer.passport.relationship.group.in": "Entrantes",
          "viewer.passport.relationship.group.loop": "Boucles propres",
          "viewer.passport.relationship.row": "{group} : {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "SORT →",
          "viewer.passport.relationship.direction.in": "← ENTRE",
          "viewer.passport.relationship.direction.loop": "BOUCLE",
          "viewer.passport.sourceCount.one": "{count} référence de source vérifiée",
          "viewer.passport.sourceCount.other": "{count} références de source vérifiées",
          "viewer.passport.sourceMarker": "SOURCE",
          "viewer.passport.beacon.one": "{count} source vérifiée ; centrez ce nœud pour l'inspecter",
          "viewer.passport.beacon.other": "{count} sources vérifiées ; centrez ce nœud pour l'inspecter",
          "viewer.passport.repository.open": "Ouvrir la révision {revision} du dépôt vérifié",
          "viewer.passport.source.open": "Ouvrir la source vérifiée {path} à la révision {revision}",
          "viewer.passport.source.openLink": "Ouvrir ↗",
          "viewer.passport.reach.upstream.one": "Tracer {count} nœud édité en amont",
          "viewer.passport.reach.upstream.other": "Tracer {count} nœuds édités en amont",
          "viewer.passport.reach.downstream.one": "Tracer {count} nœud édité en aval",
          "viewer.passport.reach.downstream.other": "Tracer {count} nœuds édités en aval",
          "viewer.passport.reach.noUpstream": "Aucun nœud édité en amont",
          "viewer.passport.reach.noDownstream": "Aucun nœud édité en aval",
          "viewer.passport.reach.status": "{direction} · {nodes} nœuds · {links} liens · max {hops} sauts",
          "viewer.route.eyebrow": "Sonde d'itinéraire",
          "viewer.route.start": "Choisir un nœud de départ",
          "viewer.route.start.find": "Trouver le départ",
          "viewer.route.start.find.aria": "Trouver un départ d'itinéraire",
          "viewer.route.copy": "Copier le lien",
          "viewer.route.copy.aria": "Copier le lien de l'itinéraire tracé",
          "viewer.route.clear": "Effacer",
          "viewer.route.clear.aria": "Effacer la sonde d'itinéraire",
          "viewer.route.traced": "Itinéraire tracé",
          "viewer.route.pickTwo": "Choisissez deux nœuds sémantiques sur le diagramme",
          "viewer.route.pickOne": "Choisissez un nœud sémantique sur le diagramme",
          "viewer.route.controls": "Contrôles du parcours d'itinéraire",
          "viewer.route.previous": "Position précédente de l'itinéraire",
          "viewer.route.play": "Lire le parcours de l'itinéraire",
          "viewer.route.pause": "Mettre le parcours de l'itinéraire en pause",
          "viewer.route.replay": "Rejouer le parcours de l'itinéraire",
          "viewer.route.next": "Position suivante de l'itinéraire",
          "viewer.route.journey": "Parcours",
          "viewer.route.pause.label": "Pause",
          "viewer.route.replay.label": "Rejouer",
          "viewer.route.overview": "Vue d'ensemble",
          "viewer.route.overview.aria": "Afficher la vue d'ensemble complète de l'itinéraire",
          "viewer.route.instructions": "Choisissez la source, puis la destination. Le sens compte.",
          "viewer.route.destination": "Choisir une destination depuis {label}",
          "viewer.route.destination.find": "Trouver une cible",
          "viewer.route.destination.find.aria": "Trouver une destination d'itinéraire accessible",
          "viewer.route.differentDestination": "Choisir une autre destination",
          "viewer.route.distinct": "Un itinéraire nécessite deux nœuds sémantiques distincts.",
          "viewer.route.unreachable": "Aucun itinéraire orienté vers {label}",
          "viewer.route.unreachable.detail": "{target} n'est pas accessible depuis {source}. Choisissez une destination surlignée.",
          "viewer.route.start.instructions": "Sélectionnez la source. L'étape suivante ne révélera que les destinations orientées.",
          "viewer.route.copy.success": "Lien de l'itinéraire tracé copié",
          "viewer.route.copy.failed": "Impossible de copier le lien de l'itinéraire tracé",
          "viewer.route.position": "Position {index} sur {total} de l'itinéraire : {label}",
          "viewer.route.step": "Étape {index} sur {total} · {phase} · {label}",
          "viewer.route.motionRequired": "Le parcours automatique nécessite le mode Animé",
          "viewer.route.trigger.clear": "Effacer l'itinéraire tracé",
          "viewer.route.overview.status": "{nodes} · {hops} · itinéraire édité le plus court",
          "viewer.route.overview.node.one": "{count} nœud",
          "viewer.route.overview.node.other": "{count} nœuds",
          "viewer.route.overview.hop.one": "{count} saut orienté",
          "viewer.route.overview.hop.other": "{count} sauts orientés",
          "viewer.route.phase.playing": "En lecture",
          "viewer.route.phase.complete": "Terminé",
          "viewer.route.phase.inspecting": "Inspection",
          "viewer.route.destination.count.one": "{count} destination orientée disponible. Choisissez un nœud surligné.",
          "viewer.route.destination.count.other": "{count} destinations orientées disponibles. Choisissez un nœud surligné.",
          "viewer.route.noOutgoing": "Aucun itinéraire sortant ne débute ici. Effacez et choisissez une autre source.",
          "viewer.route.result.title": "{source} vers {target}",
          "viewer.route.finder.source.title": "Choisir le départ de l'itinéraire",
          "viewer.route.finder.source.placeholder": "Rechercher des sources d'itinéraire",
          "viewer.route.finder.source.empty": "Aucune source d'itinéraire correspondante",
          "viewer.route.finder.source.results": "Nœuds pouvant débuter un itinéraire",
          "viewer.route.finder.source.noun": "sources d'itinéraire",
          "viewer.route.finder.source.badge": "départ",
          "viewer.route.finder.target.title": "Destination depuis {label}",
          "viewer.route.finder.target.placeholder": "Rechercher des destinations accessibles",
          "viewer.route.finder.target.empty": "Aucune destination accessible correspondante",
          "viewer.route.finder.target.results": "Destinations d'itinéraire accessibles",
          "viewer.route.finder.target.noun": "destinations accessibles",
          "viewer.route.hop.one": "{count} saut",
          "viewer.route.hop.other": "{count} sauts",
          "viewer.lens.eyebrow": "Lentille sémantique",
          "viewer.lens.title": "Comparer les rôles du système",
          "viewer.lens.close": "Fermer la lentille sémantique",
          "viewer.lens.instruction": "Choisissez jusqu'à deux types sémantiques. Un seul révèle son trafic réel ; deux comparent uniquement les relations éditées directes.",
          "viewer.lens.kinds": "Types sémantiques",
          "viewer.lens.choose": "Choisissez un type pour inspecter ses nœuds et relations associées.",
          "viewer.lens.copy": "Copier le lien de la lentille sémantique",
          "viewer.lens.clear": "Effacer la lentille sémantique",
          "viewer.lens.open": "Ouvrir la lentille sémantique",
          "viewer.lens.openActive": "Ouvrir la lentille sémantique active",
          "viewer.lens.legend": "Légende sémantique",
          "viewer.lens.legend.inspect.one": "Inspecter {label}, {count} nœud",
          "viewer.lens.legend.inspect.other": "Inspecter {label}, {count} nœuds",
          "viewer.lens.kind.count.one": "{label}, {count} nœud",
          "viewer.lens.kind.count.other": "{label}, {count} nœuds",
          "viewer.lens.compare.one": "{first} → {second} : {forward} · {second} → {first} : {reverse} · {count} relation directe",
          "viewer.lens.compare.other": "{first} → {second} : {forward} · {second} → {first} : {reverse} · {count} relations directes",
          "viewer.lens.single": "{nodes} · {relationships} · les nœuds connectés restent visibles",
          "viewer.lens.node.one": "{count} nœud {label}",
          "viewer.lens.node.other": "{count} nœuds {label}",
          "viewer.lens.relationship.one": "{count} relation associée",
          "viewer.lens.relationship.other": "{count} relations associées",
          "viewer.radar.title": "Radar sémantique",
          "viewer.radar.building": "Construction de la vue d'ensemble",
          "viewer.radar.openFull": "Ouvrir le radar sémantique complet",
          "viewer.radar.open": "Ouvrir le radar",
          "viewer.radar.close": "Fermer le radar sémantique",
          "viewer.radar.surface": "Vue d'ensemble du diagramme. Cliquez sur un nœud pour le centrer, ou utilisez les flèches pour vous déplacer.",
          "viewer.radar.click": "Cliquer sur le nœud",
          "viewer.radar.drag": "Glisser pour se déplacer",
          "viewer.radar.space": "Le radar sémantique a besoin de plus d'espace MAP.",
          "viewer.radar.nodes": "Nœuds du radar du diagramme sémantique",
          "viewer.radar.focus": "Centrer sur {label} depuis le radar sémantique",
          "viewer.radar.status": "{count} nœuds · {viewport}",
          "viewer.radar.fullMap": "{count} nœuds · carte complète",
          "viewer.radar.compacted": "Radar compacté pour éviter de masquer le passeport sémantique ou les contrôles MAP.",
          "viewer.radar.cancelWaiting": "Annuler l'attente du radar sémantique pour plus d'espace MAP",
          "viewer.radar.needsSpace": "Le radar sémantique a besoin de plus d'espace MAP visible",
          "viewer.radar.viewport.full": "carte complète",
          "viewer.radar.viewport.width": "{percent} % de largeur",
          "viewer.radar.viewport.scale": "{percent} % du viewport",
          "viewer.nav.controls": "Contrôles de la vue du diagramme",
          "viewer.nav.route": "Tracer un itinéraire orienté",
          "viewer.nav.route.title": "Tracer l'itinéraire (R)",
          "viewer.nav.route.short": "ROUTE",
          "viewer.nav.radar": "Ouvrir le radar sémantique",
          "viewer.nav.radar.title": "Radar sémantique (M)",
          "viewer.nav.radar.short": "CARTE",
          "viewer.nav.lens": "Ouvrir la lentille sémantique",
          "viewer.nav.lens.title": "Lentille sémantique (L)",
          "viewer.nav.lens.short": "LENTILLE",
          "viewer.nav.find": "Trouver un nœud",
          "viewer.nav.find.title": "Trouver un nœud (/)",
          "viewer.nav.guide": "Ouvrir le guide du diagramme",
          "viewer.nav.guide.title": "Guide du diagramme (?)",
          "viewer.nav.zoomOut": "Zoom arrière",
          "viewer.nav.zoomOut.title": "Zoom arrière (-)",
          "viewer.nav.reset": "Réinitialiser la vue du diagramme",
          "viewer.nav.reset.title": "Réinitialiser la vue (0)",
          "viewer.nav.read": "LIRE",
          "viewer.nav.zoomIn": "Zoom avant",
          "viewer.nav.zoomIn.title": "Zoom avant (+)",
          "viewer.nav.camera": "{hint}. Réinitialiser la vue du diagramme",
          "viewer.nav.camera.title": "{semantic}{hint} · réinitialiser la vue (0)",
          "viewer.nav.camera.semantic": "Caméra sémantique active · ",
          "viewer.nav.level.map": "CARTE",
          "viewer.nav.level.read": "LIRE",
          "viewer.nav.level.full": "COMPLET",
          "viewer.nav.level.auto": "AUTO",
          "viewer.nav.detail.map": "Zoomez pour révéler les libellés des relations et le contexte des nœuds",
          "viewer.nav.detail.read": "Zoomez à nouveau pour révéler les étiquettes et annotations",
          "viewer.nav.detail.full": "Détail complet du diagramme",
          "viewer.intent.summary": "{label}. {out} sortantes, {in} entrantes{loops}. {total} connexions. Appuyez sur Entrée pour les détails.",
          "viewer.intent.loops": ", {count} boucle propre",
          "viewer.common.copied": "Copié",
          "viewer.common.copyFailed": "Échec de la copie",
          "viewer.common.copyLink": "Copier le lien",
          "viewer.common.clear": "Effacer",
          "viewer.common.close": "Fermer"
        }
        
      • fr.partial.json 959 B
        {
          "page.title": "Diagramme {title}",
          "diagram.description.architecture": "Un diagramme d'architecture généré par Archify.",
          "legend.title": "Légende",
          "node.focus": "Focus {label}",
          "node.context.architecture": "Composant d'architecture",
          "viewer.kind.frontend": "Frontend",
          "viewer.kind.backend": "Backend",
          "viewer.export.button": "Exporter",
          "viewer.export.button.title": "Exporter le diagramme (E)",
          "viewer.export.diagram": "Exporter le diagramme",
          "viewer.finder.title": "Rechercher un nœud",
          "viewer.route.eyebrow": "Sonde d'itinéraire",
          "viewer.route.overview.node.one": "{count} nœud",
          "viewer.route.overview.node.other": "{count} nœuds",
          "viewer.guide.eyebrow": "Guide du diagramme",
          "viewer.nav.controls": "Contrôles de vue du diagramme",
          "viewer.theme.toggle": "Changer de thème",
          "viewer.preset.classic": "Classique",
          "viewer.common.close": "Fermer",
          "viewer.common.copyLink": "Copier le lien"
        }
        
      • it.json 26.3 KB
        {
          "page.title": "{title} · Diagramma",
          "diagram.description.architecture": "Un diagramma di architettura generato da Archify.",
          "diagram.description.workflow": "Un diagramma di flusso di lavoro generato da Archify.",
          "diagram.description.sequence": "Un diagramma di sequenza generato da Archify.",
          "diagram.description.dataflow": "Un diagramma di flusso dati generato da Archify.",
          "diagram.description.lifecycle": "Un diagramma di ciclo di vita generato da Archify.",
          "node.focus": "Metti a fuoco {label}",
          "node.focus.detail": "Metti a fuoco {label}, {detail}",
          "node.context.architecture": "Componente di architettura",
          "node.context.workflow": "Nodo del flusso di lavoro",
          "node.context.sequence": "Partecipante alla sequenza",
          "node.context.dataflow": "Nodo del flusso dati",
          "node.context.lifecycle": "Stato del ciclo di vita",
          "legend.title": "Legenda",
          "legend.architecture.frontend": "Frontend",
          "legend.architecture.backend": "Backend",
          "legend.architecture.database": "Database",
          "legend.architecture.cloud": "Cloud",
          "legend.architecture.security": "Sicurezza",
          "legend.architecture.messagebus": "Bus di messaggi",
          "legend.architecture.external": "Esterno",
          "legend.workflow.frontend": "Interfaccia utente",
          "legend.workflow.backend": "Logica dell'agente",
          "legend.workflow.security": "Criterio",
          "legend.workflow.messagebus": "Azione dello strumento",
          "legend.workflow.database": "Contesto / traccia",
          "legend.workflow.cloud": "Servizio cloud",
          "legend.workflow.external": "Sistema esterno",
          "legend.sequence.emphasis": "richiesta principale",
          "legend.sequence.return": "risposta",
          "legend.sequence.security": "sicurezza",
          "legend.sequence.dashed": "traccia asincrona",
          "legend.sequence.default": "messaggio",
          "legend.dataflow.emphasis": "dati primari",
          "legend.dataflow.security": "criterio / PII",
          "legend.dataflow.dashed": "batch asincrono",
          "legend.dataflow.database": "archivio dati",
          "legend.dataflow.default": "flusso dati",
          "legend.lifecycle.start": "stato iniziale",
          "legend.lifecycle.active": "attivo",
          "legend.lifecycle.waiting": "attesa",
          "legend.lifecycle.decision": "decisione",
          "legend.lifecycle.success": "successo",
          "legend.lifecycle.failure": "errore / uscita",
          "legend.lifecycle.neutral": "neutro",
          "legend.lifecycle.external": "esterno",
          "legend.lifecycle.final": "stato finale",
          "viewer.kind.frontend": "Frontend",
          "viewer.kind.backend": "Backend",
          "viewer.kind.database": "Database",
          "viewer.kind.cloud": "Cloud",
          "viewer.kind.security": "Sicurezza",
          "viewer.kind.messagebus": "Bus di messaggi",
          "viewer.kind.external": "Esterno",
          "viewer.kind.neutral": "Neutro",
          "viewer.kind.node": "Nodo",
          "viewer.kind.start": "Inizio",
          "viewer.kind.active": "Attivo",
          "viewer.kind.waiting": "In attesa",
          "viewer.kind.decision": "Decisione",
          "viewer.kind.success": "Successo",
          "viewer.kind.failure": "Errore",
          "viewer.toolbar.actions": "Azioni del diagramma",
          "viewer.theme.toggle.title": "Cambia tema (T)",
          "viewer.theme.toggle": "Cambia tema colore",
          "viewer.theme.dark": "Scuro",
          "viewer.theme.light": "Chiaro",
          "viewer.preset.choose.title": "Scegli lo stile visivo (S per scorrere)",
          "viewer.preset.choose": "Scegli lo stile visivo",
          "viewer.preset.style": "Stile",
          "viewer.preset.menu": "Stile visivo",
          "viewer.preset.identity": "Identità visiva",
          "viewer.preset.cycles": "S per scorrere",
          "viewer.preset.classic": "Classico",
          "viewer.preset.classic.short": "Classico",
          "viewer.preset.classic.hint": "Predefinito tecnico stabile",
          "viewer.preset.flow": "Flusso di segnale",
          "viewer.preset.flow.short": "Flusso",
          "viewer.preset.flow.hint": "Presentazione dinamica",
          "viewer.preset.blueprint": "Progetto",
          "viewer.preset.blueprint.hint": "Revisione tecnica",
          "viewer.preset.editorial": "Editoriale",
          "viewer.preset.editorial.hint": "Note di pubblicazione e lancio",
          "viewer.preset.badge.signalFlow": "FLUSSO DI SEGNALE",
          "viewer.preset.badge.blueprint": "PROGETTO / REV. 01",
          "viewer.preset.badge.editorial": "EDITORIALE / NOTA SUL CAMPO",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / TAVOLA 04",
          "viewer.preset.current": "Stile visivo: {style}. Scegli lo stile visivo",
          "viewer.motion.live": "Attiva",
          "viewer.motion.still": "Statica",
          "viewer.motion.pause": "Metti in pausa l'animazione",
          "viewer.motion.resume": "Riprendi l'animazione",
          "viewer.motion.reduced": "Animazione in pausa per preferenza di movimento ridotto",
          "viewer.motion.hidden": "Animazione in pausa mentre la pagina è nascosta",
          "viewer.motion.yielding": "Metti in pausa l'animazione; attualmente cede il posto a {owner}",
          "viewer.motion.yielding.title": "Anteprima dinamica attiva · cede il posto a {owner}",
          "viewer.owner.route": "Esplora percorso",
          "viewer.owner.lens": "Lente semantica",
          "viewer.owner.relationship": "Anteprima relazione",
          "viewer.owner.intent": "Traccia intento",
          "viewer.owner.focus": "focus semantico",
          "viewer.owner.legend": "anteprima legenda",
          "viewer.owner.reader": "interazione del lettore",
          "viewer.present.enter": "Entra in modalità presentazione",
          "viewer.present.enter.title": "Modalità presentazione (F)",
          "viewer.present.exit": "Esci dalla modalità presentazione",
          "viewer.present.exit.title": "Esci dalla modalità presentazione (F o Esc)",
          "viewer.present.present": "Presenta",
          "viewer.present.exit.label": "Esci",
          "viewer.export.button": "Esporta",
          "viewer.export.button.title": "Esporta diagramma (E)",
          "viewer.export.diagram": "Esporta diagramma",
          "viewer.export.menu": "Esporta",
          "viewer.export.subtitle": "Output portatili e puliti",
          "viewer.export.share": "Condividi",
          "viewer.export.shareCard": "Scheda di condivisione",
          "viewer.export.routeShareCard": "Scheda di condivisione del percorso",
          "viewer.export.reachShareCard": "Scheda di condivisione della raggiungibilità",
          "viewer.export.copyDiagram": "Copia diagramma",
          "viewer.export.clipboardPng": "PNG negli appunti",
          "viewer.export.raster": "Immagini raster",
          "viewer.export.image": "Immagine",
          "viewer.export.lossless": "Immagine senza perdita",
          "viewer.export.compact": "Immagine compatta",
          "viewer.export.modern": "Immagine moderna",
          "viewer.export.vectorMotion": "Vettoriale e animazione",
          "viewer.export.vectorMotion.heading": "Vettoriale e animazione",
          "viewer.export.editable": "Vettoriale modificabile",
          "viewer.export.motion6s": "Animazione di 6s",
          "viewer.export.unsupported": "Non supportato da questo browser",
          "viewer.export.clipboardUnsupported": "La scrittura di immagini negli appunti non è supportata da questo browser",
          "viewer.export.clipboardUnsupported.short": "La scrittura di immagini negli appunti non è supportata in questo browser.",
          "viewer.export.motionUnavailable": "Cattura dell'animazione non disponibile in questo browser",
          "viewer.export.webmUnavailable": "WebM non disponibile in questo browser",
          "viewer.export.failed": "Esportazione non riuscita: {message}",
          "viewer.export.unknownVariant": "Variante scheda di condivisione sconosciuta: {variant}",
          "viewer.export.routeRequired": "Traccia un percorso prima di esportare una scheda di condivisione del percorso",
          "viewer.export.reachRequired": "Traccia la raggiungibilità prima di esportare una scheda di condivisione della raggiungibilità",
          "viewer.export.unknown": "sconosciuto",
          "viewer.export.routeFailed": "Esportazione della scheda di condivisione del percorso non riuscita: {message}",
          "viewer.export.reachFailed": "Esportazione della scheda di condivisione della raggiungibilità non riuscita: {message}",
          "viewer.export.copyFailed": "Copia non riuscita: {message}",
          "viewer.export.copiedPng": "PNG copiato negli appunti",
          "viewer.export.downloadedRoute": "Scheda di condivisione del percorso scaricata",
          "viewer.export.downloadedReach": "Scheda di condivisione della raggiungibilità scaricata",
          "viewer.export.downloadedWebm": "WebM scaricato",
          "viewer.export.recording": "Registrazione di 6 secondi di animazione…",
          "viewer.export.card.routeSummary.one": "Percorso: {source} → {target} · {count} salto diretto",
          "viewer.export.card.routeSummary.other": "Percorso: {source} → {target} · {count} salti diretti",
          "viewer.export.card.reachSummary": "{direction} generata da {origin} · {nodes} · {links} · max {hops}",
          "viewer.export.card.node.one": "{count} nodo",
          "viewer.export.card.node.other": "{count} nodi",
          "viewer.export.card.link.one": "{count} collegamento",
          "viewer.export.card.link.other": "{count} collegamenti",
          "viewer.export.card.hop.one": "{count} salto",
          "viewer.export.card.hop.other": "{count} salti",
          "viewer.export.card.routeBadge": "ARCHIFY · PERCORSO · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · RAGGIUNGIBILITÀ {direction}",
          "viewer.export.direction.upstream": "A monte",
          "viewer.export.direction.downstream": "A valle",
          "viewer.export.error.canvasUnavailable": "Canvas non disponibile per {label}",
          "viewer.export.error.contextUnavailable": "Contesto canvas 2D non disponibile per {label}",
          "viewer.export.error.toBlobUnavailable": "canvas.toBlob non disponibile per {label}",
          "viewer.export.error.toBlobNull": "canvas.toBlob non ha restituito dati per {label}",
          "viewer.export.error.variantsCombined": "Le varianti della scheda di condivisione non possono essere combinate",
          "viewer.export.error.viewerState": "L'esportazione della scheda di condivisione non è riuscita a rimuovere lo stato temporaneo del visualizzatore",
          "viewer.export.error.routeState": "L'esportazione della scheda del percorso non è riuscita a preservare in modo sicuro il percorso risolto",
          "viewer.export.error.reachState": "L'esportazione della scheda di raggiungibilità non è riuscita a preservare in modo sicuro la raggiungibilità generata",
          "viewer.export.error.webmRequirements": "L'esportazione dell'animazione WebM richiede un'animazione di traccia e il supporto MediaRecorder del browser",
          "viewer.export.error.mediaRecorder": "MediaRecorder non riuscito",
          "viewer.export.error.emptyWebm": "MediaRecorder ha prodotto un WebM vuoto",
          "viewer.export.error.webmBackground": "Impossibile caricare lo sfondo SVG per l'esportazione WebM",
          "viewer.guide.eyebrow": "Guida al diagramma",
          "viewer.guide.close": "Chiudi la guida al diagramma",
          "viewer.guide.inspecting": "Analisi della semantica compilata",
          "viewer.guide.actions": "Azioni di esplorazione del diagramma",
          "viewer.guide.find": "Trova un nodo qualsiasi",
          "viewer.guide.find.hint": "Cerca etichette, responsabilità, tipi e ID stabili.",
          "viewer.guide.route": "Traccia un percorso",
          "viewer.guide.route.aria": "Traccia un percorso diretto",
          "viewer.guide.route.hint": "Chiedi come si collegano due nodi semantici nella direzione generata.",
          "viewer.guide.map": "Guarda l'intero sistema",
          "viewer.guide.map.hint": "Apri il Radar semantico con un viewport dal vivo e nodi stabili.",
          "viewer.guide.lens": "Confronta i tipi semantici",
          "viewer.guide.lens.hint": "Conta i ruoli, mostra il loro traffico e confronta i collegamenti diretti generati.",
          "viewer.guide.present": "Entra in modalità presentazione",
          "viewer.guide.present.hint": "Assegna il viewport al diagramma dal vivo senza modificare l'esportazione.",
          "viewer.guide.shortcuts": "Altre scorciatoie da tastiera",
          "viewer.guide.shortcut.export": "Esporta",
          "viewer.guide.shortcut.theme": "Tema",
          "viewer.guide.shortcut.style": "Stile",
          "viewer.guide.shortcut.reset": "Ripristina",
          "viewer.guide.shortcut.zoomIn": "Zoom avanti",
          "viewer.guide.shortcut.zoomOut": "Zoom indietro",
          "viewer.guide.shortcut.close": "Chiudi",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} nodo semantico",
          "viewer.guide.fact.node.other": "{count} nodi semantici",
          "viewer.guide.fact.relationship.one": "{count} relazione",
          "viewer.guide.fact.relationship.other": "{count} relazioni",
          "viewer.guide.open": "Apri la guida al diagramma",
          "viewer.finder.title": "Trova un nodo",
          "viewer.finder.close": "Chiudi il cercatore di nodi",
          "viewer.finder.placeholder": "Cerca etichette o ID",
          "viewer.finder.search": "Cerca nodi del diagramma",
          "viewer.finder.results": "Nodi del diagramma",
          "viewer.finder.empty": "Nessun nodo corrispondente",
          "viewer.finder.result.focus": "Metti a fuoco {label}",
          "viewer.finder.result.routeStart": "Scegli {label} come inizio del percorso",
          "viewer.finder.result.routeTarget": "Scegli {label} come destinazione del percorso, {links}",
          "viewer.finder.status.empty": "Nessun nodo corrispondente",
          "viewer.finder.status.count.one": "{count} nodo corrispondente",
          "viewer.finder.status.count.other": "{count} nodi corrispondenti",
          "viewer.finder.noun.nodes": "nodi",
          "viewer.finder.link.one": "{count} collegamento",
          "viewer.finder.link.other": "{count} collegamenti",
          "viewer.finder.result.focus.one": "Metti a fuoco {label}, {count} connessione correlata",
          "viewer.finder.result.focus.other": "Metti a fuoco {label}, {count} connessioni correlate",
          "viewer.finder.status.filtered": "{visible} di {available} {noun}",
          "viewer.finder.status.all": "{available} {noun}",
          "viewer.passport.eyebrow": "Passaporto semantico",
          "viewer.passport.metadata": "Metadati del nodo",
          "viewer.passport.evidence": "Fonte verificata",
          "viewer.passport.verified": "Fonte verificata",
          "viewer.passport.verificationScope": "Verificato rispetto al Git locale alla revisione fissata. L'accesso remoto non è stato verificato.",
          "viewer.passport.reach": "Raggiungibilità generata",
          "viewer.passport.reach.trace": "Traccia la raggiungibilità generata",
          "viewer.passport.upstream": "A monte",
          "viewer.passport.downstream": "A valle",
          "viewer.passport.upstream.trace": "Traccia la raggiungibilità generata a monte",
          "viewer.passport.downstream.trace": "Traccia la raggiungibilità generata a valle",
          "viewer.passport.close": "Chiudi il passaporto semantico",
          "viewer.passport.copy": "Copia link",
          "viewer.passport.copy.focus": "Copia il link al nodo in focus",
          "viewer.passport.relations": "Relazioni",
          "viewer.passport.relations.show": "Mostra le relazioni collegate",
          "viewer.passport.relations.hide": "Nascondi le relazioni collegate",
          "viewer.passport.relations.list": "Relazioni collegate",
          "viewer.passport.copyRelation": "Copia relazione",
          "viewer.passport.copyNode": "Copia nodo",
          "viewer.passport.copyPinned": "Copia il link alla relazione fissata",
          "viewer.passport.copySource": "Copia il link al nodo di origine",
          "viewer.passport.copy.focused.success": "Link del nodo in focus copiato",
          "viewer.passport.copy.pinned.success": "Link della relazione fissata copiato",
          "viewer.passport.copy.focused.failed": "Impossibile copiare il link del nodo in focus",
          "viewer.passport.copy.pinned.failed": "Impossibile copiare il link della relazione fissata",
          "viewer.passport.relationship.none": "Nessuna relazione collegata",
          "viewer.passport.relationship.count.one": "{count} relazione",
          "viewer.passport.relationship.count.other": "{count} relazioni",
          "viewer.passport.relationship.show.one": "Mostra {count} relazione collegata",
          "viewer.passport.relationship.show.other": "Mostra {count} relazioni collegate",
          "viewer.passport.relationship.summary": "{out} in uscita · {in} in entrata{loops}",
          "viewer.passport.relationship.loops": " · {count} autoanello",
          "viewer.passport.relationship.explorer": "Esploratore delle relazioni dirette",
          "viewer.passport.relationship.help": "Usa i tasti freccia per esplorare le relazioni. Premi Invio o Spazio per fissare i dettagli; Esc per annullare.",
          "viewer.passport.relationship.loopsBack": "torna su se stesso",
          "viewer.passport.relationship.connectsTo": "si collega a",
          "viewer.passport.relationship.connectsFrom": "si collega da",
          "viewer.passport.relationship.pinned": "Relazione fissata · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "Analizza la relazione {index} di {total}: da {from} a {to}, {label}. Premi Invio per i dettagli.",
          "viewer.passport.relationship.group.out": "In uscita",
          "viewer.passport.relationship.group.in": "In entrata",
          "viewer.passport.relationship.group.loop": "Autoanelli",
          "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "USCITA →",
          "viewer.passport.relationship.direction.in": "← ENTRATA",
          "viewer.passport.relationship.direction.loop": "ANELLO",
          "viewer.passport.sourceCount.one": "{count} riferimento a fonte verificata",
          "viewer.passport.sourceCount.other": "{count} riferimenti a fonti verificate",
          "viewer.passport.sourceMarker": "FONTE",
          "viewer.passport.beacon.one": "{count} fonte verificata; metti a fuoco questo nodo per analizzarla",
          "viewer.passport.beacon.other": "{count} fonti verificate; metti a fuoco questo nodo per analizzarle",
          "viewer.passport.repository.open": "Apri la revisione {revision} del repository verificato",
          "viewer.passport.source.open": "Apri la fonte verificata {path} alla revisione {revision}",
          "viewer.passport.source.openLink": "Apri ↗",
          "viewer.passport.reach.upstream.one": "Traccia {count} nodo generato a monte",
          "viewer.passport.reach.upstream.other": "Traccia {count} nodi generati a monte",
          "viewer.passport.reach.downstream.one": "Traccia {count} nodo generato a valle",
          "viewer.passport.reach.downstream.other": "Traccia {count} nodi generati a valle",
          "viewer.passport.reach.noUpstream": "Nessun nodo generato a monte",
          "viewer.passport.reach.noDownstream": "Nessun nodo generato a valle",
          "viewer.passport.reach.status": "{direction} · {nodes} nodi · {links} collegamenti · max {hops} salti",
          "viewer.route.eyebrow": "Esplora percorso",
          "viewer.route.start": "Scegli un nodo di partenza",
          "viewer.route.start.find": "Trova partenza",
          "viewer.route.start.find.aria": "Trova una partenza del percorso",
          "viewer.route.copy": "Copia link",
          "viewer.route.copy.aria": "Copia il link al percorso tracciato",
          "viewer.route.clear": "Cancella",
          "viewer.route.clear.aria": "Cancella l'esplorazione del percorso",
          "viewer.route.traced": "Percorso tracciato",
          "viewer.route.pickTwo": "Scegli due nodi semantici sul diagramma",
          "viewer.route.pickOne": "Scegli un nodo semantico sul diagramma",
          "viewer.route.controls": "Controlli del tragitto del percorso",
          "viewer.route.previous": "Posizione precedente nel percorso",
          "viewer.route.play": "Riproduci il tragitto del percorso",
          "viewer.route.pause": "Metti in pausa il tragitto del percorso",
          "viewer.route.replay": "Riavvia il tragitto del percorso",
          "viewer.route.next": "Posizione successiva nel percorso",
          "viewer.route.journey": "Tragitto",
          "viewer.route.pause.label": "Pausa",
          "viewer.route.replay.label": "Riavvia",
          "viewer.route.overview": "Panoramica",
          "viewer.route.overview.aria": "Mostra la panoramica completa del percorso",
          "viewer.route.instructions": "Scegli prima l'origine, poi la destinazione. La direzione è importante.",
          "viewer.route.destination": "Scegli una destinazione da {label}",
          "viewer.route.destination.find": "Trova destinazione",
          "viewer.route.destination.find.aria": "Trova una destinazione raggiungibile del percorso",
          "viewer.route.differentDestination": "Scegli una destinazione diversa",
          "viewer.route.distinct": "Un percorso richiede due nodi semantici distinti.",
          "viewer.route.unreachable": "Nessun percorso diretto verso {label}",
          "viewer.route.unreachable.detail": "{target} non è raggiungibile da {source}. Scegli una destinazione evidenziata.",
          "viewer.route.start.instructions": "Seleziona l'origine. Il passo successivo mostrerà solo le destinazioni dirette.",
          "viewer.route.copy.success": "Link del percorso tracciato copiato",
          "viewer.route.copy.failed": "Impossibile copiare il link del percorso tracciato",
          "viewer.route.position": "Posizione {index} di {total} nel percorso: {label}",
          "viewer.route.step": "Passo {index} di {total} · {phase} · {label}",
          "viewer.route.motionRequired": "Il tragitto automatico richiede l'animazione attiva",
          "viewer.route.trigger.clear": "Cancella il percorso tracciato",
          "viewer.route.overview.status": "{nodes} · {hops} · percorso generato più breve",
          "viewer.route.overview.node.one": "{count} nodo",
          "viewer.route.overview.node.other": "{count} nodi",
          "viewer.route.overview.hop.one": "{count} salto diretto",
          "viewer.route.overview.hop.other": "{count} salti diretti",
          "viewer.route.phase.playing": "In riproduzione",
          "viewer.route.phase.complete": "Completato",
          "viewer.route.phase.inspecting": "Analisi in corso",
          "viewer.route.destination.count.one": "{count} destinazione diretta disponibile. Scegli un nodo evidenziato.",
          "viewer.route.destination.count.other": "{count} destinazioni dirette disponibili. Scegli un nodo evidenziato.",
          "viewer.route.noOutgoing": "Nessun percorso in uscita da qui. Cancella e scegli un'altra origine.",
          "viewer.route.result.title": "{source} verso {target}",
          "viewer.route.finder.source.title": "Scegli l'inizio del percorso",
          "viewer.route.finder.source.placeholder": "Cerca origini del percorso",
          "viewer.route.finder.source.empty": "Nessuna origine del percorso corrispondente",
          "viewer.route.finder.source.results": "Nodi che possono avviare un percorso",
          "viewer.route.finder.source.noun": "origini del percorso",
          "viewer.route.finder.source.badge": "inizio",
          "viewer.route.finder.target.title": "Destinazione da {label}",
          "viewer.route.finder.target.placeholder": "Cerca destinazioni raggiungibili",
          "viewer.route.finder.target.empty": "Nessuna destinazione raggiungibile corrispondente",
          "viewer.route.finder.target.results": "Destinazioni raggiungibili del percorso",
          "viewer.route.finder.target.noun": "destinazioni raggiungibili",
          "viewer.route.hop.one": "{count} salto",
          "viewer.route.hop.other": "{count} salti",
          "viewer.lens.eyebrow": "Lente semantica",
          "viewer.lens.title": "Confronta i ruoli del sistema",
          "viewer.lens.close": "Chiudi la lente semantica",
          "viewer.lens.instruction": "Scegli fino a due tipi semantici. Uno mostra il traffico reale; due confrontano solo le relazioni dirette generate.",
          "viewer.lens.kinds": "Tipi semantici",
          "viewer.lens.choose": "Scegli un tipo per analizzarne i nodi e le relazioni collegate.",
          "viewer.lens.copy": "Copia il link alla lente semantica",
          "viewer.lens.clear": "Cancella la lente semantica",
          "viewer.lens.open": "Apri la lente semantica",
          "viewer.lens.openActive": "Apri la lente semantica attiva",
          "viewer.lens.legend": "Legenda semantica",
          "viewer.lens.legend.inspect.one": "Analizza {label}, {count} nodo",
          "viewer.lens.legend.inspect.other": "Analizza {label}, {count} nodi",
          "viewer.lens.kind.count.one": "{label}, {count} nodo",
          "viewer.lens.kind.count.other": "{label}, {count} nodi",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} relazione diretta",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} relazioni dirette",
          "viewer.lens.single": "{nodes} · {relationships} · i nodi collegati restano visibili",
          "viewer.lens.node.one": "{count} nodo {label}",
          "viewer.lens.node.other": "{count} nodi {label}",
          "viewer.lens.relationship.one": "{count} relazione a contatto",
          "viewer.lens.relationship.other": "{count} relazioni a contatto",
          "viewer.radar.title": "Radar semantico",
          "viewer.radar.building": "Costruzione della panoramica",
          "viewer.radar.openFull": "Apri il radar semantico completo",
          "viewer.radar.open": "Apri radar",
          "viewer.radar.close": "Chiudi il radar semantico",
          "viewer.radar.surface": "Panoramica del diagramma. Clicca su un nodo per metterlo a fuoco, oppure usa i tasti freccia per scorrere.",
          "viewer.radar.click": "Clicca sul nodo",
          "viewer.radar.drag": "Trascina per scorrere",
          "viewer.radar.space": "Il radar semantico richiede più spazio nella MAPPA.",
          "viewer.radar.nodes": "Nodi del radar semantico del diagramma",
          "viewer.radar.focus": "Metti a fuoco {label} dal radar semantico",
          "viewer.radar.status": "{count} nodi · {viewport}",
          "viewer.radar.fullMap": "{count} nodi · mappa completa",
          "viewer.radar.compacted": "Radar compattato per evitare di coprire il passaporto semantico o i controlli della MAPPA.",
          "viewer.radar.cancelWaiting": "Annulla l'attesa del radar semantico per più spazio nella MAPPA",
          "viewer.radar.needsSpace": "Il radar semantico richiede più spazio visibile nella MAPPA",
          "viewer.radar.viewport.full": "mappa completa",
          "viewer.radar.viewport.width": "{percent}% di larghezza",
          "viewer.radar.viewport.scale": "{percent}% del viewport",
          "viewer.nav.controls": "Controlli della vista del diagramma",
          "viewer.nav.route": "Traccia un percorso diretto",
          "viewer.nav.route.title": "Traccia percorso (R)",
          "viewer.nav.route.short": "PERCORSO",
          "viewer.nav.radar": "Apri il radar semantico",
          "viewer.nav.radar.title": "Radar semantico (M)",
          "viewer.nav.radar.short": "MAPPA",
          "viewer.nav.lens": "Apri la lente semantica",
          "viewer.nav.lens.title": "Lente semantica (L)",
          "viewer.nav.lens.short": "LENTE",
          "viewer.nav.find": "Trova un nodo",
          "viewer.nav.find.title": "Trova un nodo (/)",
          "viewer.nav.guide": "Apri la guida al diagramma",
          "viewer.nav.guide.title": "Guida al diagramma (?)",
          "viewer.nav.zoomOut": "Zoom indietro",
          "viewer.nav.zoomOut.title": "Zoom indietro (-)",
          "viewer.nav.reset": "Ripristina la vista del diagramma",
          "viewer.nav.reset.title": "Ripristina vista (0)",
          "viewer.nav.read": "LEGGI",
          "viewer.nav.zoomIn": "Zoom avanti",
          "viewer.nav.zoomIn.title": "Zoom avanti (+)",
          "viewer.nav.camera": "{hint}. Ripristina la vista del diagramma",
          "viewer.nav.camera.title": "{semantic}{hint} · ripristina vista (0)",
          "viewer.nav.camera.semantic": "Camera semantica attiva · ",
          "viewer.nav.level.map": "MAPPA",
          "viewer.nav.level.read": "LEGGI",
          "viewer.nav.level.full": "COMPLETO",
          "viewer.nav.level.auto": "AUTO",
          "viewer.nav.detail.map": "Ingrandisci per mostrare le etichette delle relazioni e il contesto dei nodi",
          "viewer.nav.detail.read": "Ingrandisci ancora per mostrare tag e annotazioni",
          "viewer.nav.detail.full": "Dettaglio completo del diagramma",
          "viewer.intent.summary": "{label}. {out} in uscita, {in} in entrata{loops}. {total} connessioni. Premi Invio per i dettagli.",
          "viewer.intent.loops": ", {count} autoanello",
          "viewer.common.copied": "Copiato",
          "viewer.common.copyFailed": "Copia non riuscita",
          "viewer.common.copyLink": "Copia link",
          "viewer.common.clear": "Cancella",
          "viewer.common.close": "Chiudi"
        }
        
      • ja.json 29.8 KB
        {
          "page.title": "{title} ダイアグラム",
          "diagram.description.architecture": "Archifyで生成されたアーキテクチャ図です。",
          "diagram.description.workflow": "Archifyで生成されたワークフロー図です。",
          "diagram.description.sequence": "Archifyで生成されたシーケンス図です。",
          "diagram.description.dataflow": "Archifyで生成されたデータフロー図です。",
          "diagram.description.lifecycle": "Archifyで生成されたライフサイクル図です。",
          "node.focus": "{label} にフォーカス",
          "node.focus.detail": "{label} にフォーカス、{detail}",
          "node.context.architecture": "アーキテクチャコンポーネント",
          "node.context.workflow": "ワークフローノード",
          "node.context.sequence": "シーケンス参加者",
          "node.context.dataflow": "データフローノード",
          "node.context.lifecycle": "ライフサイクル状態",
          "legend.title": "凡例",
          "legend.architecture.frontend": "フロントエンド",
          "legend.architecture.backend": "バックエンド",
          "legend.architecture.database": "データベース",
          "legend.architecture.cloud": "クラウド",
          "legend.architecture.security": "セキュリティ",
          "legend.architecture.messagebus": "メッセージバス",
          "legend.architecture.external": "外部",
          "legend.workflow.frontend": "ユーザーUI",
          "legend.workflow.backend": "エージェントロジック",
          "legend.workflow.security": "ポリシー",
          "legend.workflow.messagebus": "ツール実行",
          "legend.workflow.database": "コンテキスト / トレース",
          "legend.workflow.cloud": "クラウドサービス",
          "legend.workflow.external": "外部システム",
          "legend.sequence.emphasis": "主要リクエスト",
          "legend.sequence.return": "戻り値",
          "legend.sequence.security": "セキュリティ",
          "legend.sequence.dashed": "非同期トレース",
          "legend.sequence.default": "メッセージ",
          "legend.dataflow.emphasis": "主要データ",
          "legend.dataflow.security": "ポリシー / PII",
          "legend.dataflow.dashed": "非同期バッチ",
          "legend.dataflow.database": "データストア",
          "legend.dataflow.default": "データフロー",
          "legend.lifecycle.start": "初期状態",
          "legend.lifecycle.active": "アクティブ",
          "legend.lifecycle.waiting": "待機",
          "legend.lifecycle.decision": "判断",
          "legend.lifecycle.success": "成功",
          "legend.lifecycle.failure": "失敗 / 終了",
          "legend.lifecycle.neutral": "中立",
          "legend.lifecycle.external": "外部",
          "legend.lifecycle.final": "終了状態",
          "viewer.kind.frontend": "フロントエンド",
          "viewer.kind.backend": "バックエンド",
          "viewer.kind.database": "データベース",
          "viewer.kind.cloud": "クラウド",
          "viewer.kind.security": "セキュリティ",
          "viewer.kind.messagebus": "メッセージバス",
          "viewer.kind.external": "外部",
          "viewer.kind.neutral": "中立",
          "viewer.kind.node": "ノード",
          "viewer.kind.start": "開始",
          "viewer.kind.active": "アクティブ",
          "viewer.kind.waiting": "待機",
          "viewer.kind.decision": "判断",
          "viewer.kind.success": "成功",
          "viewer.kind.failure": "失敗",
          "viewer.toolbar.actions": "ダイアグラム操作",
          "viewer.theme.toggle.title": "テーマ切替 (T)",
          "viewer.theme.toggle": "カラーテーマを切替",
          "viewer.theme.dark": "ダーク",
          "viewer.theme.light": "ライト",
          "viewer.preset.choose.title": "ビジュアルスタイルを選択 (Sで循環)",
          "viewer.preset.choose": "ビジュアルスタイルを選択",
          "viewer.preset.style": "スタイル",
          "viewer.preset.menu": "ビジュアルスタイル",
          "viewer.preset.identity": "ビジュアルアイデンティティ",
          "viewer.preset.cycles": "Sで循環",
          "viewer.preset.classic": "クラシック",
          "viewer.preset.classic.short": "クラシック",
          "viewer.preset.classic.hint": "安定した技術標準",
          "viewer.preset.flow": "シグナルフロー",
          "viewer.preset.flow.short": "フロー",
          "viewer.preset.flow.hint": "動きを強調した表現",
          "viewer.preset.blueprint": "ブループリント",
          "viewer.preset.blueprint.hint": "エンジニアリングレビュー向け",
          "viewer.preset.editorial": "エディトリアル",
          "viewer.preset.editorial.hint": "発行・公開ノート向け",
          "viewer.preset.badge.signalFlow": "シグナルフロー",
          "viewer.preset.badge.blueprint": "ブループリント / 改訂01",
          "viewer.preset.badge.editorial": "エディトリアル / フィールドノート",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / プレート04",
          "viewer.preset.current": "ビジュアルスタイル: {style}。ビジュアルスタイルを選択",
          "viewer.motion.live": "ライブ",
          "viewer.motion.still": "静止",
          "viewer.motion.pause": "動きを一時停止",
          "viewer.motion.resume": "動きを再開",
          "viewer.motion.reduced": "「視差効果を減らす」設定により動きを一時停止しました",
          "viewer.motion.hidden": "このページが非表示のため動きを一時停止しました",
          "viewer.motion.yielding": "動きを一時停止、現在 {owner} に譲っています",
          "viewer.motion.yielding.title": "ライブプレビュー有効 · {owner} に譲っています",
          "viewer.owner.route": "ルートプローブ",
          "viewer.owner.lens": "セマンティックレンズ",
          "viewer.owner.relationship": "関係性プレビュー",
          "viewer.owner.intent": "インテントトレース",
          "viewer.owner.focus": "セマンティックフォーカス",
          "viewer.owner.legend": "凡例プレビュー",
          "viewer.owner.reader": "読者の操作",
          "viewer.present.enter": "プレゼンテーションステージに入る",
          "viewer.present.enter.title": "プレゼンテーションステージ (F)",
          "viewer.present.exit": "プレゼンテーションステージを終了",
          "viewer.present.exit.title": "プレゼンテーションステージを終了 (F または Escape)",
          "viewer.present.present": "プレゼンテーション",
          "viewer.present.exit.label": "終了",
          "viewer.export.button": "エクスポート",
          "viewer.export.button.title": "ダイアグラムをエクスポート (E)",
          "viewer.export.diagram": "ダイアグラムをエクスポート",
          "viewer.export.menu": "エクスポート",
          "viewer.export.subtitle": "持ち運びやすくクリーンな出力",
          "viewer.export.share": "共有",
          "viewer.export.shareCard": "シェアカード",
          "viewer.export.routeShareCard": "ルートシェアカード",
          "viewer.export.reachShareCard": "到達範囲シェアカード",
          "viewer.export.copyDiagram": "ダイアグラムをコピー",
          "viewer.export.clipboardPng": "PNGをクリップボードへ",
          "viewer.export.raster": "ラスター画像",
          "viewer.export.image": "画像",
          "viewer.export.lossless": "無劣化画像",
          "viewer.export.compact": "コンパクト画像",
          "viewer.export.modern": "モダン画像",
          "viewer.export.vectorMotion": "ベクターとモーション",
          "viewer.export.vectorMotion.heading": "ベクター & モーション",
          "viewer.export.editable": "編集可能なベクター",
          "viewer.export.motion6s": "6秒のモーション",
          "viewer.export.unsupported": "このブラウザではサポートされていません",
          "viewer.export.clipboardUnsupported": "このブラウザはクリップボードへの画像書き込みに対応していません",
          "viewer.export.clipboardUnsupported.short": "このブラウザはクリップボードへの画像書き込みに対応していません。",
          "viewer.export.motionUnavailable": "このブラウザではモーションキャプチャを利用できません",
          "viewer.export.webmUnavailable": "このブラウザではWebMを利用できません",
          "viewer.export.failed": "エクスポートに失敗しました: {message}",
          "viewer.export.unknownVariant": "不明なシェアカードの種類です: {variant}",
          "viewer.export.routeRequired": "ルートシェアカードをエクスポートする前にルートをトレースしてください",
          "viewer.export.reachRequired": "到達範囲シェアカードをエクスポートする前に編集済みの到達範囲をトレースしてください",
          "viewer.export.unknown": "不明",
          "viewer.export.routeFailed": "ルートシェアカードのエクスポートに失敗しました: {message}",
          "viewer.export.reachFailed": "到達範囲シェアカードのエクスポートに失敗しました: {message}",
          "viewer.export.copyFailed": "コピーに失敗しました: {message}",
          "viewer.export.copiedPng": "PNGをクリップボードにコピーしました",
          "viewer.export.downloadedRoute": "ルートシェアカードをダウンロードしました",
          "viewer.export.downloadedReach": "到達範囲シェアカードをダウンロードしました",
          "viewer.export.downloadedWebm": "WebMをダウンロードしました",
          "viewer.export.recording": "6秒間のモーションを録画中…",
          "viewer.export.card.routeSummary.one": "ルート: {source} → {target} · {count} 個の有向ホップ",
          "viewer.export.card.routeSummary.other": "ルート: {source} → {target} · {count} 個の有向ホップ",
          "viewer.export.card.reachSummary": "{origin} からの編集済み{direction} · {nodes} · {links} · 最大{hops}",
          "viewer.export.card.node.one": "{count} 個のノード",
          "viewer.export.card.node.other": "{count} 個のノード",
          "viewer.export.card.link.one": "{count} 個の接続",
          "viewer.export.card.link.other": "{count} 個の接続",
          "viewer.export.card.hop.one": "{count} ホップ",
          "viewer.export.card.hop.other": "{count} ホップ",
          "viewer.export.card.routeBadge": "ARCHIFY · ROUTE · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · {direction} REACH",
          "viewer.export.direction.upstream": "アップストリーム",
          "viewer.export.direction.downstream": "ダウンストリーム",
          "viewer.export.error.canvasUnavailable": "{label} のキャンバスを利用できません",
          "viewer.export.error.contextUnavailable": "{label} の2Dキャンバスコンテキストを利用できません",
          "viewer.export.error.toBlobUnavailable": "{label} でcanvas.toBlobを利用できません",
          "viewer.export.error.toBlobNull": "{label} のcanvas.toBlobがデータを返しませんでした",
          "viewer.export.error.variantsCombined": "シェアカードの種類は組み合わせられません",
          "viewer.export.error.viewerState": "シェアカードのエクスポートで一時的なビューアー状態を削除できませんでした",
          "viewer.export.error.routeState": "ルートカードのエクスポートで解決済みルートを安全に保持できませんでした",
          "viewer.export.error.reachState": "到達範囲カードのエクスポートで編集済み到達範囲を安全に保持できませんでした",
          "viewer.export.error.webmRequirements": "WebMモーションのエクスポートにはトレースアニメーションとブラウザのMediaRecorder対応が必要です",
          "viewer.export.error.mediaRecorder": "MediaRecorderが失敗しました",
          "viewer.export.error.emptyWebm": "MediaRecorderが空のWebMを生成しました",
          "viewer.export.error.webmBackground": "WebMエクスポート用のSVG背景を読み込めませんでした",
          "viewer.guide.eyebrow": "ダイアグラムガイド",
          "viewer.guide.close": "ダイアグラムガイドを閉じる",
          "viewer.guide.inspecting": "コンパイル済みセマンティクスを検査中",
          "viewer.guide.actions": "ダイアグラム探索アクション",
          "viewer.guide.find": "任意のノードを検索",
          "viewer.guide.find.hint": "ラベル、役割、種類、固定IDで検索します。",
          "viewer.guide.route": "ルートをトレース",
          "viewer.guide.route.aria": "有向ルートをトレース",
          "viewer.guide.route.hint": "2つのセマンティックノードが編集済みの方向でどう接続されているかを確認します。",
          "viewer.guide.map": "システム全体を表示",
          "viewer.guide.map.hint": "ライブビューポートと固定ノードを持つセマンティックレーダーを開きます。",
          "viewer.guide.lens": "セマンティックな種類を比較",
          "viewer.guide.lens.hint": "役割を数え、そのトラフィックを表示し、直接編集されたリンクを比較します。",
          "viewer.guide.present": "プレゼンテーションステージに入る",
          "viewer.guide.present.hint": "エクスポートを変更せずに、ライブダイアグラムにビューポート全体を割り当てます。",
          "viewer.guide.shortcuts": "その他のキーボードショートカット",
          "viewer.guide.shortcut.export": "エクスポート",
          "viewer.guide.shortcut.theme": "テーマ",
          "viewer.guide.shortcut.style": "スタイル",
          "viewer.guide.shortcut.reset": "リセット",
          "viewer.guide.shortcut.zoomIn": "拡大",
          "viewer.guide.shortcut.zoomOut": "縮小",
          "viewer.guide.shortcut.close": "閉じる",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} 個のセマンティックノード",
          "viewer.guide.fact.node.other": "{count} 個のセマンティックノード",
          "viewer.guide.fact.relationship.one": "{count} 件の関係",
          "viewer.guide.fact.relationship.other": "{count} 件の関係",
          "viewer.guide.open": "ダイアグラムガイドを開く",
          "viewer.finder.title": "ノードを検索",
          "viewer.finder.close": "ノード検索を閉じる",
          "viewer.finder.placeholder": "ラベルまたはIDで検索",
          "viewer.finder.search": "ダイアグラムノードを検索",
          "viewer.finder.results": "ダイアグラムノード",
          "viewer.finder.empty": "一致するノードがありません",
          "viewer.finder.result.focus": "{label} にフォーカス",
          "viewer.finder.result.routeStart": "{label} をルートの起点として選択",
          "viewer.finder.result.routeTarget": "{label} をルートの終点として選択、{links}",
          "viewer.finder.status.empty": "一致するノードがありません",
          "viewer.finder.status.count.one": "一致するノード {count} 個",
          "viewer.finder.status.count.other": "一致するノード {count} 個",
          "viewer.finder.noun.nodes": "ノード",
          "viewer.finder.link.one": "{count} 件の接続",
          "viewer.finder.link.other": "{count} 件の接続",
          "viewer.finder.result.focus.one": "{label} にフォーカス、関連する接続 {count} 件",
          "viewer.finder.result.focus.other": "{label} にフォーカス、関連する接続 {count} 件",
          "viewer.finder.status.filtered": "{available} 件の{noun}中 {visible} 件",
          "viewer.finder.status.all": "{available} 件の{noun}",
          "viewer.passport.eyebrow": "セマンティックパスポート",
          "viewer.passport.metadata": "ノードメタデータ",
          "viewer.passport.evidence": "検証済みソースの根拠",
          "viewer.passport.verified": "検証済みソース",
          "viewer.passport.verificationScope": "固定されたリビジョン時点のローカルGitに対して検証済みです。リモートアクセスは確認していません。",
          "viewer.passport.reach": "編集済みの到達範囲",
          "viewer.passport.reach.trace": "編集済みの到達可能性をトレース",
          "viewer.passport.upstream": "アップストリーム",
          "viewer.passport.downstream": "ダウンストリーム",
          "viewer.passport.upstream.trace": "アップストリームの編集済み到達可能性をトレース",
          "viewer.passport.downstream.trace": "ダウンストリームの編集済み到達可能性をトレース",
          "viewer.passport.close": "セマンティックパスポートを閉じる",
          "viewer.passport.copy": "リンクをコピー",
          "viewer.passport.copy.focus": "フォーカス中のノードへのリンクをコピー",
          "viewer.passport.relations": "関係",
          "viewer.passport.relations.show": "関連する関係を表示",
          "viewer.passport.relations.hide": "関連する関係を非表示",
          "viewer.passport.relations.list": "関連する関係",
          "viewer.passport.copyRelation": "関係をコピー",
          "viewer.passport.copyNode": "ノードをコピー",
          "viewer.passport.copyPinned": "固定された関係へのリンクをコピー",
          "viewer.passport.copySource": "ソースノードへのリンクをコピー",
          "viewer.passport.copy.focused.success": "フォーカス中のノードのリンクをコピーしました",
          "viewer.passport.copy.pinned.success": "固定された関係のリンクをコピーしました",
          "viewer.passport.copy.focused.failed": "フォーカス中のノードのリンクをコピーできませんでした",
          "viewer.passport.copy.pinned.failed": "固定された関係のリンクをコピーできませんでした",
          "viewer.passport.relationship.none": "関連する関係がありません",
          "viewer.passport.relationship.count.one": "{count} 件の関係",
          "viewer.passport.relationship.count.other": "{count} 件の関係",
          "viewer.passport.relationship.show.one": "関連する関係 {count} 件を表示",
          "viewer.passport.relationship.show.other": "関連する関係 {count} 件を表示",
          "viewer.passport.relationship.summary": "出向 {out} · 入向 {in}{loops}",
          "viewer.passport.relationship.loops": " · 自己ループ {count} 件",
          "viewer.passport.relationship.explorer": "直接関係エクスプローラー",
          "viewer.passport.relationship.help": "矢印キーで関係を探索します。EnterまたはSpaceで詳細を固定し、Escapeで解除します。",
          "viewer.passport.relationship.loopsBack": "ループして戻る",
          "viewer.passport.relationship.connectsTo": "接続先",
          "viewer.passport.relationship.connectsFrom": "接続元",
          "viewer.passport.relationship.pinned": "固定された関係 · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "第 {index}/{total} 件の関係を検査: {from} から {to} へ、{label}。詳細はEnterを押してください。",
          "viewer.passport.relationship.group.out": "出向",
          "viewer.passport.relationship.group.in": "入向",
          "viewer.passport.relationship.group.loop": "自己ループ",
          "viewer.passport.relationship.row": "{group}: {relationship}、{neighbor}",
          "viewer.passport.relationship.direction.out": "出 →",
          "viewer.passport.relationship.direction.in": "← 入",
          "viewer.passport.relationship.direction.loop": "ループ",
          "viewer.passport.sourceCount.one": "検証済みソース参照 {count} 件",
          "viewer.passport.sourceCount.other": "検証済みソース参照 {count} 件",
          "viewer.passport.sourceMarker": "出典",
          "viewer.passport.beacon.one": "検証済みソース {count} 件。このノードにフォーカスして確認",
          "viewer.passport.beacon.other": "検証済みソース {count} 件。このノードにフォーカスして確認",
          "viewer.passport.repository.open": "検証済みリポジトリのリビジョン {revision} を開く",
          "viewer.passport.source.open": "リビジョン {revision} の検証済みソース {path} を開く",
          "viewer.passport.source.openLink": "開く ↗",
          "viewer.passport.reach.upstream.one": "アップストリームの編集済みノード {count} 件をトレース",
          "viewer.passport.reach.upstream.other": "アップストリームの編集済みノード {count} 件をトレース",
          "viewer.passport.reach.downstream.one": "ダウンストリームの編集済みノード {count} 件をトレース",
          "viewer.passport.reach.downstream.other": "ダウンストリームの編集済みノード {count} 件をトレース",
          "viewer.passport.reach.noUpstream": "アップストリームの編集済みノードがありません",
          "viewer.passport.reach.noDownstream": "ダウンストリームの編集済みノードがありません",
          "viewer.passport.reach.status": "{direction} · ノード {nodes} 件 · 接続 {links} 件 · 最大 {hops} ホップ",
          "viewer.route.eyebrow": "ルートプローブ",
          "viewer.route.start": "開始ノードを選択",
          "viewer.route.start.find": "開始点を検索",
          "viewer.route.start.find.aria": "ルートの開始点を検索",
          "viewer.route.copy": "リンクをコピー",
          "viewer.route.copy.aria": "トレース済みルートへのリンクをコピー",
          "viewer.route.clear": "クリア",
          "viewer.route.clear.aria": "ルートプローブをクリア",
          "viewer.route.traced": "トレース済みルート",
          "viewer.route.pickTwo": "ダイアグラム上で2つのセマンティックノードを選択してください",
          "viewer.route.pickOne": "ダイアグラム上でセマンティックノードを1つ選択してください",
          "viewer.route.controls": "ルートジャーニーのコントロール",
          "viewer.route.previous": "前のルート位置",
          "viewer.route.play": "ルートジャーニーを再生",
          "viewer.route.pause": "ルートジャーニーを一時停止",
          "viewer.route.replay": "ルートジャーニーをリプレイ",
          "viewer.route.next": "次のルート位置",
          "viewer.route.journey": "ジャーニー",
          "viewer.route.pause.label": "一時停止",
          "viewer.route.replay.label": "リプレイ",
          "viewer.route.overview": "概要",
          "viewer.route.overview.aria": "ルート全体の概要を表示",
          "viewer.route.instructions": "起点を選択してから終点を選択してください。方向が重要です。",
          "viewer.route.destination": "{label} からの終点を選択",
          "viewer.route.destination.find": "終点を検索",
          "viewer.route.destination.find.aria": "到達可能なルートの終点を検索",
          "viewer.route.differentDestination": "別の終点を選択",
          "viewer.route.distinct": "ルートには2つの異なるセマンティックノードが必要です。",
          "viewer.route.unreachable": "{label} への有向ルートがありません",
          "viewer.route.unreachable.detail": "{source} から {target} には到達できません。ハイライトされた終点を選択してください。",
          "viewer.route.start.instructions": "起点を選択してください。次のステップでは有向の終点のみが表示されます。",
          "viewer.route.copy.success": "トレース済みルートのリンクをコピーしました",
          "viewer.route.copy.failed": "ルートのリンクをコピーできませんでした",
          "viewer.route.position": "ルート位置 {index}/{total}: {label}",
          "viewer.route.step": "ステップ {index}/{total} · {phase} · {label}",
          "viewer.route.motionRequired": "自動ジャーニーにはライブモーションが必要です",
          "viewer.route.trigger.clear": "トレース済みルートをクリア",
          "viewer.route.overview.status": "{nodes} · {hops} · 最短の編集済みルート",
          "viewer.route.overview.node.one": "{count} 個のノード",
          "viewer.route.overview.node.other": "{count} 個のノード",
          "viewer.route.overview.hop.one": "{count} 有向ホップ",
          "viewer.route.overview.hop.other": "{count} 有向ホップ",
          "viewer.route.phase.playing": "再生中",
          "viewer.route.phase.complete": "完了",
          "viewer.route.phase.inspecting": "検査中",
          "viewer.route.destination.count.one": "利用可能な有向終点 {count} 件。ハイライトされたノードを選択してください。",
          "viewer.route.destination.count.other": "利用可能な有向終点 {count} 件。ハイライトされたノードを選択してください。",
          "viewer.route.noOutgoing": "ここから始まる出向ルートはありません。クリアして別の起点を選択してください。",
          "viewer.route.result.title": "{source} から {target}",
          "viewer.route.finder.source.title": "ルートの開始点を選択",
          "viewer.route.finder.source.placeholder": "ルートの起点を検索",
          "viewer.route.finder.source.empty": "一致するルートの起点がありません",
          "viewer.route.finder.source.results": "ルートを開始できるノード",
          "viewer.route.finder.source.noun": "ルートの起点",
          "viewer.route.finder.source.badge": "起点",
          "viewer.route.finder.target.title": "{label} からの終点",
          "viewer.route.finder.target.placeholder": "到達可能な終点を検索",
          "viewer.route.finder.target.empty": "一致する到達可能な終点がありません",
          "viewer.route.finder.target.results": "到達可能なルートの終点",
          "viewer.route.finder.target.noun": "到達可能な終点",
          "viewer.route.hop.one": "{count} ホップ",
          "viewer.route.hop.other": "{count} ホップ",
          "viewer.lens.eyebrow": "セマンティックレンズ",
          "viewer.lens.title": "システムの役割を比較",
          "viewer.lens.close": "セマンティックレンズを閉じる",
          "viewer.lens.instruction": "セマンティックな種類を最大2つ選択してください。1つ選ぶと実際のトラフィックが表示され、2つ選ぶと直接の編集済み関係のみを比較します。",
          "viewer.lens.kinds": "セマンティックな種類",
          "viewer.lens.choose": "種類を選択すると、そのノードと接する関係を検査できます。",
          "viewer.lens.copy": "セマンティックレンズへのリンクをコピー",
          "viewer.lens.clear": "セマンティックレンズをクリア",
          "viewer.lens.open": "セマンティックレンズを開く",
          "viewer.lens.openActive": "アクティブなセマンティックレンズを開く",
          "viewer.lens.legend": "セマンティック凡例",
          "viewer.lens.legend.inspect.one": "{label} を検査、{count} 個のノード",
          "viewer.lens.legend.inspect.other": "{label} を検査、{count} 個のノード",
          "viewer.lens.kind.count.one": "{label}、{count} 個のノード",
          "viewer.lens.kind.count.other": "{label}、{count} 個のノード",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 直接関係 {count} 件",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 直接関係 {count} 件",
          "viewer.lens.single": "{nodes} · {relationships} · 接続された周辺ノードは表示されたままです",
          "viewer.lens.node.one": "{label} ノード {count} 個",
          "viewer.lens.node.other": "{label} ノード {count} 個",
          "viewer.lens.relationship.one": "接する関係 {count} 件",
          "viewer.lens.relationship.other": "接する関係 {count} 件",
          "viewer.radar.title": "セマンティックレーダー",
          "viewer.radar.building": "概要を構築中",
          "viewer.radar.openFull": "完全なセマンティックレーダーを開く",
          "viewer.radar.open": "レーダーを開く",
          "viewer.radar.close": "セマンティックレーダーを閉じる",
          "viewer.radar.surface": "ダイアグラムの概要です。ノードをクリックしてフォーカスするか、矢印キーでパンできます。",
          "viewer.radar.click": "ノードをクリック",
          "viewer.radar.drag": "ドラッグしてパン",
          "viewer.radar.space": "セマンティックレーダーにはさらにMAPスペースが必要です。",
          "viewer.radar.nodes": "セマンティックダイアグラムのレーダーノード",
          "viewer.radar.focus": "セマンティックレーダーから {label} にフォーカス",
          "viewer.radar.status": "{count} 個のノード · {viewport}",
          "viewer.radar.fullMap": "{count} 個のノード · 全体マップ",
          "viewer.radar.compacted": "セマンティックパスポートやMAPコントロールを覆わないよう、レーダーを縮小しました。",
          "viewer.radar.cancelWaiting": "MAPスペースの確保待ちのセマンティックレーダーをキャンセル",
          "viewer.radar.needsSpace": "セマンティックレーダーには表示可能なMAPスペースがさらに必要です",
          "viewer.radar.viewport.full": "全体マップ",
          "viewer.radar.viewport.width": "幅 {percent}%",
          "viewer.radar.viewport.scale": "ビューポート {percent}%",
          "viewer.nav.controls": "ダイアグラム表示コントロール",
          "viewer.nav.route": "有向ルートをトレース",
          "viewer.nav.route.title": "ルートをトレース (R)",
          "viewer.nav.route.short": "パス",
          "viewer.nav.radar": "セマンティックレーダーを開く",
          "viewer.nav.radar.title": "セマンティックレーダー (M)",
          "viewer.nav.radar.short": "マップ",
          "viewer.nav.lens": "セマンティックレンズを開く",
          "viewer.nav.lens.title": "セマンティックレンズ (L)",
          "viewer.nav.lens.short": "レンズ",
          "viewer.nav.find": "ノードを検索",
          "viewer.nav.find.title": "ノードを検索 (/)",
          "viewer.nav.guide": "ダイアグラムガイドを開く",
          "viewer.nav.guide.title": "ダイアグラムガイド (?)",
          "viewer.nav.zoomOut": "縮小",
          "viewer.nav.zoomOut.title": "縮小 (-)",
          "viewer.nav.reset": "ダイアグラム表示をリセット",
          "viewer.nav.reset.title": "表示をリセット (0)",
          "viewer.nav.read": "閲覧",
          "viewer.nav.zoomIn": "拡大",
          "viewer.nav.zoomIn.title": "拡大 (+)",
          "viewer.nav.camera": "{hint}。ダイアグラム表示をリセット",
          "viewer.nav.camera.title": "{semantic}{hint} · 表示をリセット (0)",
          "viewer.nav.camera.semantic": "セマンティックカメラ有効 · ",
          "viewer.nav.level.map": "マップ",
          "viewer.nav.level.read": "閲覧",
          "viewer.nav.level.full": "全体",
          "viewer.nav.level.auto": "自動",
          "viewer.nav.detail.map": "拡大すると関係ラベルとノードのコンテキストが表示されます",
          "viewer.nav.detail.read": "さらに拡大するとタグと注釈が表示されます",
          "viewer.nav.detail.full": "ダイアグラムの完全な詳細",
          "viewer.intent.summary": "{label}。出向 {out} 件、入向 {in} 件{loops}。合計 {total} 件の接続。詳細はEnterを押してください。",
          "viewer.intent.loops": "、自己ループ {count} 件",
          "viewer.common.copied": "コピーしました",
          "viewer.common.copyFailed": "コピーに失敗しました",
          "viewer.common.copyLink": "リンクをコピー",
          "viewer.common.clear": "クリア",
          "viewer.common.close": "閉じる"
        }
        
      • ko.json 27.9 KB
        {
          "page.title": "{title} 다이어그램",
          "diagram.description.architecture": "Archify로 생성한 아키텍처 다이어그램입니다.",
          "diagram.description.workflow": "Archify로 생성한 워크플로우 다이어그램입니다.",
          "diagram.description.sequence": "Archify로 생성한 시퀀스 다이어그램입니다.",
          "diagram.description.dataflow": "Archify로 생성한 데이터플로우 다이어그램입니다.",
          "diagram.description.lifecycle": "Archify로 생성한 라이프사이클 다이어그램입니다.",
          "node.focus": "{label} 포커스",
          "node.focus.detail": "{label} 포커스, {detail}",
          "node.context.architecture": "아키텍처 구성요소",
          "node.context.workflow": "워크플로우 노드",
          "node.context.sequence": "시퀀스 참가자",
          "node.context.dataflow": "데이터플로우 노드",
          "node.context.lifecycle": "라이프사이클 상태",
          "legend.title": "범례",
          "legend.architecture.frontend": "프런트엔드",
          "legend.architecture.backend": "백엔드",
          "legend.architecture.database": "데이터베이스",
          "legend.architecture.cloud": "클라우드",
          "legend.architecture.security": "보안",
          "legend.architecture.messagebus": "메시지 버스",
          "legend.architecture.external": "외부",
          "legend.workflow.frontend": "사용자 UI",
          "legend.workflow.backend": "Agent 로직",
          "legend.workflow.security": "정책",
          "legend.workflow.messagebus": "도구 실행",
          "legend.workflow.database": "컨텍스트 / 추적",
          "legend.workflow.cloud": "클라우드 서비스",
          "legend.workflow.external": "외부 시스템",
          "legend.sequence.emphasis": "주요 요청",
          "legend.sequence.return": "반환",
          "legend.sequence.security": "보안",
          "legend.sequence.dashed": "비동기 추적",
          "legend.sequence.default": "메시지",
          "legend.dataflow.emphasis": "주요 데이터",
          "legend.dataflow.security": "정책 / PII",
          "legend.dataflow.dashed": "비동기 배치",
          "legend.dataflow.database": "데이터 저장소",
          "legend.dataflow.default": "데이터 흐름",
          "legend.lifecycle.start": "초기 상태",
          "legend.lifecycle.active": "활성",
          "legend.lifecycle.waiting": "대기",
          "legend.lifecycle.decision": "판단",
          "legend.lifecycle.success": "성공",
          "legend.lifecycle.failure": "실패 / 종료",
          "legend.lifecycle.neutral": "중립 상태",
          "legend.lifecycle.external": "외부 상태",
          "legend.lifecycle.final": "종료 상태",
          "viewer.kind.frontend": "프런트엔드",
          "viewer.kind.backend": "백엔드",
          "viewer.kind.database": "데이터베이스",
          "viewer.kind.cloud": "클라우드",
          "viewer.kind.security": "보안",
          "viewer.kind.messagebus": "메시지 버스",
          "viewer.kind.external": "외부",
          "viewer.kind.neutral": "중립",
          "viewer.kind.node": "노드",
          "viewer.kind.start": "시작",
          "viewer.kind.active": "활성",
          "viewer.kind.waiting": "대기",
          "viewer.kind.decision": "판단",
          "viewer.kind.success": "성공",
          "viewer.kind.failure": "실패",
          "viewer.toolbar.actions": "다이어그램 동작",
          "viewer.theme.toggle.title": "테마 전환 (T)",
          "viewer.theme.toggle": "색상 테마 전환",
          "viewer.theme.dark": "다크",
          "viewer.theme.light": "라이트",
          "viewer.preset.choose.title": "시각 스타일 선택 (S로 순환)",
          "viewer.preset.choose": "시각 스타일 선택",
          "viewer.preset.style": "스타일",
          "viewer.preset.menu": "시각 스타일",
          "viewer.preset.identity": "시각적 정체성",
          "viewer.preset.cycles": "S로 순환",
          "viewer.preset.classic": "클래식",
          "viewer.preset.classic.short": "클래식",
          "viewer.preset.classic.hint": "안정적인 기술 기본 스타일",
          "viewer.preset.flow": "시그널 플로우",
          "viewer.preset.flow.short": "플로우",
          "viewer.preset.flow.hint": "동적 흐름을 강조하는 프레젠테이션",
          "viewer.preset.blueprint": "블루프린트",
          "viewer.preset.blueprint.hint": "엔지니어링 리뷰용",
          "viewer.preset.editorial": "에디토리얼",
          "viewer.preset.editorial.hint": "발행 및 출시 노트에 적합",
          "viewer.preset.badge.signalFlow": "시그널 플로우",
          "viewer.preset.badge.blueprint": "블루프린트 / 개정 01",
          "viewer.preset.badge.editorial": "에디토리얼 / 현장 노트",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / 도판 04",
          "viewer.preset.current": "현재 시각 스타일: {style}. 시각 스타일 선택",
          "viewer.motion.live": "동적",
          "viewer.motion.still": "정적",
          "viewer.motion.pause": "동작 일시정지",
          "viewer.motion.resume": "동작 재개",
          "viewer.motion.reduced": "동작 최소화 설정으로 인해 동작이 일시정지되었습니다",
          "viewer.motion.hidden": "페이지가 보이지 않는 동안 동작이 일시정지되었습니다",
          "viewer.motion.yielding": "동작 일시정지; 현재 {owner}에 양보 중",
          "viewer.motion.yielding.title": "실시간 미리보기 활성화 · {owner}에 양보 중",
          "viewer.owner.route": "경로 탐색",
          "viewer.owner.lens": "시맨틱 렌즈",
          "viewer.owner.relationship": "관계 미리보기",
          "viewer.owner.intent": "의도 추적",
          "viewer.owner.focus": "시맨틱 포커스",
          "viewer.owner.legend": "범례 미리보기",
          "viewer.owner.reader": "읽는 이의 상호작용",
          "viewer.present.enter": "프레젠테이션 모드 진입",
          "viewer.present.enter.title": "프레젠테이션 모드 (F)",
          "viewer.present.exit": "프레젠테이션 모드 종료",
          "viewer.present.exit.title": "프레젠테이션 모드 종료 (F 또는 Escape)",
          "viewer.present.present": "프레젠테이션",
          "viewer.present.exit.label": "종료",
          "viewer.export.button": "내보내기",
          "viewer.export.button.title": "다이어그램 내보내기 (E)",
          "viewer.export.diagram": "다이어그램 내보내기",
          "viewer.export.menu": "내보내기",
          "viewer.export.subtitle": "가볍고 깔끔한 출력물",
          "viewer.export.share": "공유",
          "viewer.export.shareCard": "공유 카드",
          "viewer.export.routeShareCard": "경로 공유 카드",
          "viewer.export.reachShareCard": "도달범위 공유 카드",
          "viewer.export.copyDiagram": "다이어그램 복사",
          "viewer.export.clipboardPng": "PNG를 클립보드로",
          "viewer.export.raster": "래스터 이미지",
          "viewer.export.image": "이미지",
          "viewer.export.lossless": "무손실 이미지",
          "viewer.export.compact": "압축 이미지",
          "viewer.export.modern": "최신 이미지 포맷",
          "viewer.export.vectorMotion": "벡터 및 동작",
          "viewer.export.vectorMotion.heading": "벡터 및 동작",
          "viewer.export.editable": "편집 가능한 벡터",
          "viewer.export.motion6s": "6초 동작",
          "viewer.export.unsupported": "이 브라우저에서 지원하지 않습니다",
          "viewer.export.clipboardUnsupported": "이 브라우저는 이미지 클립보드 쓰기를 지원하지 않습니다",
          "viewer.export.clipboardUnsupported.short": "이 브라우저는 이미지 클립보드 쓰기를 지원하지 않습니다.",
          "viewer.export.motionUnavailable": "이 브라우저에서는 동작을 캡처할 수 없습니다",
          "viewer.export.webmUnavailable": "이 브라우저에서는 WebM을 사용할 수 없습니다",
          "viewer.export.failed": "내보내기 실패: {message}",
          "viewer.export.unknownVariant": "알 수 없는 공유 카드 유형: {variant}",
          "viewer.export.routeRequired": "경로 공유 카드를 내보내려면 먼저 경로를 추적하세요",
          "viewer.export.reachRequired": "도달범위 공유 카드를 내보내려면 먼저 편집된 도달범위를 추적하세요",
          "viewer.export.unknown": "알 수 없음",
          "viewer.export.routeFailed": "경로 공유 카드 내보내기 실패: {message}",
          "viewer.export.reachFailed": "도달범위 공유 카드 내보내기 실패: {message}",
          "viewer.export.copyFailed": "복사 실패: {message}",
          "viewer.export.copiedPng": "PNG를 클립보드에 복사했습니다",
          "viewer.export.downloadedRoute": "경로 공유 카드를 다운로드했습니다",
          "viewer.export.downloadedReach": "도달범위 공유 카드를 다운로드했습니다",
          "viewer.export.downloadedWebm": "WebM을 다운로드했습니다",
          "viewer.export.recording": "6초 분량 동작을 녹화 중…",
          "viewer.export.card.routeSummary.one": "경로: {source} → {target} · 방향성 홉 {count}개",
          "viewer.export.card.routeSummary.other": "경로: {source} → {target} · 방향성 홉 {count}개",
          "viewer.export.card.reachSummary": "{origin}에서 시작한 편집된 {direction} · {nodes} · {links} · 최대 {hops}",
          "viewer.export.card.node.one": "노드 {count}개",
          "viewer.export.card.node.other": "노드 {count}개",
          "viewer.export.card.link.one": "연결 {count}개",
          "viewer.export.card.link.other": "연결 {count}개",
          "viewer.export.card.hop.one": "홉 {count}개",
          "viewer.export.card.hop.other": "홉 {count}개",
          "viewer.export.card.routeBadge": "ARCHIFY · 경로 · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · {direction} 도달범위",
          "viewer.export.direction.upstream": "업스트림",
          "viewer.export.direction.downstream": "다운스트림",
          "viewer.export.error.canvasUnavailable": "{label}에 캔버스를 사용할 수 없습니다",
          "viewer.export.error.contextUnavailable": "{label}에 2D 캔버스 컨텍스트를 만들 수 없습니다",
          "viewer.export.error.toBlobUnavailable": "{label}에서 canvas.toBlob을 사용할 수 없습니다",
          "viewer.export.error.toBlobNull": "{label}의 canvas.toBlob이 데이터를 반환하지 않았습니다",
          "viewer.export.error.variantsCombined": "공유 카드 유형을 함께 조합할 수 없습니다",
          "viewer.export.error.viewerState": "공유 카드 내보내기가 임시 뷰어 상태를 제거하지 못했습니다",
          "viewer.export.error.routeState": "경로 카드 내보내기가 해석된 경로를 안전하게 보존하지 못했습니다",
          "viewer.export.error.reachState": "도달범위 카드 내보내기가 편집된 도달범위를 안전하게 보존하지 못했습니다",
          "viewer.export.error.webmRequirements": "WebM 동작 내보내기는 추적 애니메이션과 브라우저의 MediaRecorder 지원이 필요합니다",
          "viewer.export.error.mediaRecorder": "MediaRecorder 실패",
          "viewer.export.error.emptyWebm": "MediaRecorder가 빈 WebM을 생성했습니다",
          "viewer.export.error.webmBackground": "WebM 내보내기용 SVG 배경을 불러오지 못했습니다",
          "viewer.guide.eyebrow": "다이어그램 가이드",
          "viewer.guide.close": "다이어그램 가이드 닫기",
          "viewer.guide.inspecting": "컴파일된 시맨틱 구조 검사 중",
          "viewer.guide.actions": "다이어그램 탐색 동작",
          "viewer.guide.find": "아무 노드나 찾기",
          "viewer.guide.find.hint": "라벨, 역할, 유형, 고정 ID로 검색합니다.",
          "viewer.guide.route": "경로 추적",
          "viewer.guide.route.aria": "방향성 경로 추적",
          "viewer.guide.route.hint": "두 시맨틱 노드가 편집된 방향으로 어떻게 연결되는지 확인합니다.",
          "viewer.guide.map": "전체 시스템 보기",
          "viewer.guide.map.hint": "실시간 뷰포트와 고정 노드가 있는 시맨틱 레이더를 엽니다.",
          "viewer.guide.lens": "시맨틱 유형 비교",
          "viewer.guide.lens.hint": "역할 수를 세고, 트래픽을 표시하고, 직접 편집된 연결을 비교합니다.",
          "viewer.guide.present": "프레젠테이션 모드 진입",
          "viewer.guide.present.hint": "내보내기는 그대로 두고 실시간 다이어그램에 뷰포트 전체를 할애합니다.",
          "viewer.guide.shortcuts": "추가 키보드 단축키",
          "viewer.guide.shortcut.export": "내보내기",
          "viewer.guide.shortcut.theme": "테마",
          "viewer.guide.shortcut.style": "스타일",
          "viewer.guide.shortcut.reset": "초기화",
          "viewer.guide.shortcut.zoomIn": "확대",
          "viewer.guide.shortcut.zoomOut": "축소",
          "viewer.guide.shortcut.close": "닫기",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "시맨틱 노드 {count}개",
          "viewer.guide.fact.node.other": "시맨틱 노드 {count}개",
          "viewer.guide.fact.relationship.one": "관계 {count}개",
          "viewer.guide.fact.relationship.other": "관계 {count}개",
          "viewer.guide.open": "다이어그램 가이드 열기",
          "viewer.finder.title": "노드 찾기",
          "viewer.finder.close": "노드 찾기 닫기",
          "viewer.finder.placeholder": "라벨 또는 ID로 검색",
          "viewer.finder.search": "다이어그램 노드 검색",
          "viewer.finder.results": "다이어그램 노드",
          "viewer.finder.empty": "일치하는 노드가 없습니다",
          "viewer.finder.result.focus": "{label} 포커스",
          "viewer.finder.result.routeStart": "{label}을(를) 경로 시작점으로 선택",
          "viewer.finder.result.routeTarget": "{label}을(를) 경로 도착점으로 선택, {links}",
          "viewer.finder.status.empty": "일치하는 노드가 없습니다",
          "viewer.finder.status.count.one": "일치하는 노드 {count}개",
          "viewer.finder.status.count.other": "일치하는 노드 {count}개",
          "viewer.finder.noun.nodes": "노드",
          "viewer.finder.link.one": "연결 {count}개",
          "viewer.finder.link.other": "연결 {count}개",
          "viewer.finder.result.focus.one": "{label} 포커스, 관련 연결 {count}개",
          "viewer.finder.result.focus.other": "{label} 포커스, 관련 연결 {count}개",
          "viewer.finder.status.filtered": "{noun} {available}개 중 {visible}개",
          "viewer.finder.status.all": "{noun} {available}개",
          "viewer.passport.eyebrow": "시맨틱 패스포트",
          "viewer.passport.metadata": "노드 메타데이터",
          "viewer.passport.evidence": "검증된 소스 근거",
          "viewer.passport.verified": "검증된 소스",
          "viewer.passport.verificationScope": "고정된 리비전 기준 로컬 Git으로 검증했습니다. 원격 접근 권한은 확인하지 않았습니다.",
          "viewer.passport.reach": "편집된 도달범위",
          "viewer.passport.reach.trace": "편집된 도달가능성 추적",
          "viewer.passport.upstream": "업스트림",
          "viewer.passport.downstream": "다운스트림",
          "viewer.passport.upstream.trace": "업스트림 편집 도달가능성 추적",
          "viewer.passport.downstream.trace": "다운스트림 편집 도달가능성 추적",
          "viewer.passport.close": "시맨틱 패스포트 닫기",
          "viewer.passport.copy": "링크 복사",
          "viewer.passport.copy.focus": "포커스된 노드의 링크 복사",
          "viewer.passport.relations": "관계",
          "viewer.passport.relations.show": "연결된 관계 표시",
          "viewer.passport.relations.hide": "연결된 관계 숨기기",
          "viewer.passport.relations.list": "연결된 관계",
          "viewer.passport.copyRelation": "관계 복사",
          "viewer.passport.copyNode": "노드 복사",
          "viewer.passport.copyPinned": "고정된 관계의 링크 복사",
          "viewer.passport.copySource": "소스 노드의 링크 복사",
          "viewer.passport.copy.focused.success": "포커스된 노드 링크를 복사했습니다",
          "viewer.passport.copy.pinned.success": "고정된 관계 링크를 복사했습니다",
          "viewer.passport.copy.focused.failed": "포커스된 노드 링크를 복사할 수 없습니다",
          "viewer.passport.copy.pinned.failed": "고정된 관계 링크를 복사할 수 없습니다",
          "viewer.passport.relationship.none": "연결된 관계가 없습니다",
          "viewer.passport.relationship.count.one": "관계 {count}개",
          "viewer.passport.relationship.count.other": "관계 {count}개",
          "viewer.passport.relationship.show.one": "연결된 관계 {count}개 표시",
          "viewer.passport.relationship.show.other": "연결된 관계 {count}개 표시",
          "viewer.passport.relationship.summary": "출향 {out}개 · 입향 {in}개{loops}",
          "viewer.passport.relationship.loops": " · 자기순환 {count}개",
          "viewer.passport.relationship.explorer": "직접 관계 탐색기",
          "viewer.passport.relationship.help": "방향키로 관계를 탐색하세요. Enter 또는 Space로 상세정보를 고정하고, Escape로 지웁니다.",
          "viewer.passport.relationship.loopsBack": "되돌아옴",
          "viewer.passport.relationship.connectsTo": "연결 대상",
          "viewer.passport.relationship.connectsFrom": "연결 출처",
          "viewer.passport.relationship.pinned": "고정된 관계 · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "{total}개 중 {index}번 관계 검사: {from}에서 {to}로, {label}. Enter로 상세정보 확인.",
          "viewer.passport.relationship.group.out": "출향",
          "viewer.passport.relationship.group.in": "입향",
          "viewer.passport.relationship.group.loop": "자기순환",
          "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "출 →",
          "viewer.passport.relationship.direction.in": "← 입",
          "viewer.passport.relationship.direction.loop": "순환",
          "viewer.passport.sourceCount.one": "검증된 소스 참조 {count}개",
          "viewer.passport.sourceCount.other": "검증된 소스 참조 {count}개",
          "viewer.passport.sourceMarker": "출처",
          "viewer.passport.beacon.one": "검증된 소스 {count}개; 이 노드를 포커스하여 확인",
          "viewer.passport.beacon.other": "검증된 소스 {count}개; 이 노드를 포커스하여 확인",
          "viewer.passport.repository.open": "검증된 저장소 리비전 {revision} 열기",
          "viewer.passport.source.open": "리비전 {revision}의 검증된 소스 {path} 열기",
          "viewer.passport.source.openLink": "열기 ↗",
          "viewer.passport.reach.upstream.one": "업스트림 편집 노드 {count}개 추적",
          "viewer.passport.reach.upstream.other": "업스트림 편집 노드 {count}개 추적",
          "viewer.passport.reach.downstream.one": "다운스트림 편집 노드 {count}개 추적",
          "viewer.passport.reach.downstream.other": "다운스트림 편집 노드 {count}개 추적",
          "viewer.passport.reach.noUpstream": "업스트림 편집 노드가 없습니다",
          "viewer.passport.reach.noDownstream": "다운스트림 편집 노드가 없습니다",
          "viewer.passport.reach.status": "{direction} · 노드 {nodes}개 · 연결 {links}개 · 최대 {hops}홉",
          "viewer.route.eyebrow": "경로 탐색",
          "viewer.route.start": "시작 노드 선택",
          "viewer.route.start.find": "시작점 찾기",
          "viewer.route.start.find.aria": "경로 시작점 찾기",
          "viewer.route.copy": "링크 복사",
          "viewer.route.copy.aria": "추적된 경로의 링크 복사",
          "viewer.route.clear": "지우기",
          "viewer.route.clear.aria": "경로 탐색 지우기",
          "viewer.route.traced": "추적된 경로",
          "viewer.route.pickTwo": "다이어그램에서 시맨틱 노드 두 개를 선택하세요",
          "viewer.route.pickOne": "다이어그램에서 시맨틱 노드 하나를 선택하세요",
          "viewer.route.controls": "경로 이동 제어",
          "viewer.route.previous": "이전 경로 위치",
          "viewer.route.play": "경로 이동 재생",
          "viewer.route.pause": "경로 이동 일시정지",
          "viewer.route.replay": "경로 이동 다시 재생",
          "viewer.route.next": "다음 경로 위치",
          "viewer.route.journey": "이동 경로",
          "viewer.route.pause.label": "일시정지",
          "viewer.route.replay.label": "다시 재생",
          "viewer.route.overview": "개요",
          "viewer.route.overview.aria": "전체 경로 개요 표시",
          "viewer.route.instructions": "출발지를 먼저 선택한 뒤 도착지를 선택하세요. 방향이 중요합니다.",
          "viewer.route.destination": "{label}에서 출발할 도착지 선택",
          "viewer.route.destination.find": "도착지 찾기",
          "viewer.route.destination.find.aria": "도달 가능한 경로 도착지 찾기",
          "viewer.route.differentDestination": "다른 도착지 선택",
          "viewer.route.distinct": "경로에는 서로 다른 시맨틱 노드 두 개가 필요합니다.",
          "viewer.route.unreachable": "{label}(으)로 가는 방향성 경로가 없습니다",
          "viewer.route.unreachable.detail": "{source}에서 {target}에 도달할 수 없습니다. 강조 표시된 도착지를 선택하세요.",
          "viewer.route.start.instructions": "출발지를 선택하세요. 다음 단계에서는 방향성으로 도달 가능한 도착지만 표시됩니다.",
          "viewer.route.copy.success": "추적된 경로 링크를 복사했습니다",
          "viewer.route.copy.failed": "경로 링크를 복사할 수 없습니다",
          "viewer.route.position": "경로 위치 {total}개 중 {index}번: {label}",
          "viewer.route.step": "{total}단계 중 {index}단계 · {phase} · {label}",
          "viewer.route.motionRequired": "자동 이동에는 동적 모드가 필요합니다",
          "viewer.route.trigger.clear": "추적된 경로 지우기",
          "viewer.route.overview.status": "{nodes} · {hops} · 최단 편집 경로",
          "viewer.route.overview.node.one": "노드 {count}개",
          "viewer.route.overview.node.other": "노드 {count}개",
          "viewer.route.overview.hop.one": "방향성 홉 {count}개",
          "viewer.route.overview.hop.other": "방향성 홉 {count}개",
          "viewer.route.phase.playing": "재생 중",
          "viewer.route.phase.complete": "완료됨",
          "viewer.route.phase.inspecting": "검사 중",
          "viewer.route.destination.count.one": "방향성 도착지 {count}개 사용 가능. 강조 표시된 노드를 선택하세요.",
          "viewer.route.destination.count.other": "방향성 도착지 {count}개 사용 가능. 강조 표시된 노드를 선택하세요.",
          "viewer.route.noOutgoing": "여기서 시작하는 출향 경로가 없습니다. 지우고 다른 출발지를 선택하세요.",
          "viewer.route.result.title": "{source}에서 {target}까지",
          "viewer.route.finder.source.title": "경로 시작점 선택",
          "viewer.route.finder.source.placeholder": "경로 출발지 검색",
          "viewer.route.finder.source.empty": "일치하는 경로 출발지가 없습니다",
          "viewer.route.finder.source.results": "경로를 시작할 수 있는 노드",
          "viewer.route.finder.source.noun": "경로 출발지",
          "viewer.route.finder.source.badge": "시작",
          "viewer.route.finder.target.title": "{label}에서 출발할 도착지",
          "viewer.route.finder.target.placeholder": "도달 가능한 도착지 검색",
          "viewer.route.finder.target.empty": "일치하는 도달 가능한 도착지가 없습니다",
          "viewer.route.finder.target.results": "도달 가능한 경로 도착지",
          "viewer.route.finder.target.noun": "도달 가능한 도착지",
          "viewer.route.hop.one": "홉 {count}개",
          "viewer.route.hop.other": "홉 {count}개",
          "viewer.lens.eyebrow": "시맨틱 렌즈",
          "viewer.lens.title": "시스템 역할 비교",
          "viewer.lens.close": "시맨틱 렌즈 닫기",
          "viewer.lens.instruction": "시맨틱 유형을 최대 두 개까지 선택하세요. 하나를 선택하면 실제 트래픽을 표시하고, 두 개를 선택하면 직접 편집된 관계만 비교합니다.",
          "viewer.lens.kinds": "시맨틱 유형",
          "viewer.lens.choose": "유형을 선택해 해당 노드와 연결된 관계를 확인하세요.",
          "viewer.lens.copy": "시맨틱 렌즈 링크 복사",
          "viewer.lens.clear": "시맨틱 렌즈 지우기",
          "viewer.lens.open": "시맨틱 렌즈 열기",
          "viewer.lens.openActive": "활성 시맨틱 렌즈 열기",
          "viewer.lens.legend": "시맨틱 범례",
          "viewer.lens.legend.inspect.one": "{label} 검사, 노드 {count}개",
          "viewer.lens.legend.inspect.other": "{label} 검사, 노드 {count}개",
          "viewer.lens.kind.count.one": "{label}, 노드 {count}개",
          "viewer.lens.kind.count.other": "{label}, 노드 {count}개",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 직접 관계 {count}개",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 직접 관계 {count}개",
          "viewer.lens.single": "{nodes} · {relationships} · 연결된 주변 노드는 계속 표시됩니다",
          "viewer.lens.node.one": "{label} 노드 {count}개",
          "viewer.lens.node.other": "{label} 노드 {count}개",
          "viewer.lens.relationship.one": "연결된 관계 {count}개",
          "viewer.lens.relationship.other": "연결된 관계 {count}개",
          "viewer.radar.title": "시맨틱 레이더",
          "viewer.radar.building": "개요 구성 중",
          "viewer.radar.openFull": "전체 시맨틱 레이더 열기",
          "viewer.radar.open": "레이더 열기",
          "viewer.radar.close": "시맨틱 레이더 닫기",
          "viewer.radar.surface": "다이어그램 개요입니다. 노드를 클릭해 포커스하거나 방향키로 이동하세요.",
          "viewer.radar.click": "노드 클릭",
          "viewer.radar.drag": "드래그로 이동",
          "viewer.radar.space": "시맨틱 레이더를 표시하려면 지도 공간이 더 필요합니다.",
          "viewer.radar.nodes": "시맨틱 다이어그램 레이더 노드",
          "viewer.radar.focus": "시맨틱 레이더에서 {label} 포커스",
          "viewer.radar.status": "노드 {count}개 · {viewport}",
          "viewer.radar.fullMap": "노드 {count}개 · 전체 지도",
          "viewer.radar.compacted": "시맨틱 패스포트나 지도 컨트롤을 가리지 않도록 레이더를 축소했습니다.",
          "viewer.radar.cancelWaiting": "지도 공간 확보를 기다리는 시맨틱 레이더 취소",
          "viewer.radar.needsSpace": "시맨틱 레이더를 표시하려면 지도 공간이 더 필요합니다",
          "viewer.radar.viewport.full": "전체 지도",
          "viewer.radar.viewport.width": "너비 {percent}%",
          "viewer.radar.viewport.scale": "뷰포트 {percent}%",
          "viewer.nav.controls": "다이어그램 보기 제어",
          "viewer.nav.route": "방향성 경로 추적",
          "viewer.nav.route.title": "경로 추적 (R)",
          "viewer.nav.route.short": "경로",
          "viewer.nav.radar": "시맨틱 레이더 열기",
          "viewer.nav.radar.title": "시맨틱 레이더 (M)",
          "viewer.nav.radar.short": "지도",
          "viewer.nav.lens": "시맨틱 렌즈 열기",
          "viewer.nav.lens.title": "시맨틱 렌즈 (L)",
          "viewer.nav.lens.short": "렌즈",
          "viewer.nav.find": "노드 찾기",
          "viewer.nav.find.title": "노드 찾기 (/)",
          "viewer.nav.guide": "다이어그램 가이드 열기",
          "viewer.nav.guide.title": "다이어그램 가이드 (?)",
          "viewer.nav.zoomOut": "축소",
          "viewer.nav.zoomOut.title": "축소 (-)",
          "viewer.nav.reset": "다이어그램 보기 초기화",
          "viewer.nav.reset.title": "보기 초기화 (0)",
          "viewer.nav.read": "읽기",
          "viewer.nav.zoomIn": "확대",
          "viewer.nav.zoomIn.title": "확대 (+)",
          "viewer.nav.camera": "{hint}. 다이어그램 보기 초기화",
          "viewer.nav.camera.title": "{semantic}{hint} · 보기 초기화 (0)",
          "viewer.nav.camera.semantic": "시맨틱 카메라 활성 · ",
          "viewer.nav.level.map": "개요",
          "viewer.nav.level.read": "읽기",
          "viewer.nav.level.full": "전체",
          "viewer.nav.level.auto": "자동",
          "viewer.nav.detail.map": "확대하면 관계 라벨과 노드 컨텍스트가 표시됩니다",
          "viewer.nav.detail.read": "다시 확대하면 태그와 주석이 표시됩니다",
          "viewer.nav.detail.full": "다이어그램 전체 상세정보",
          "viewer.intent.summary": "{label}. 출향 {out}개, 입향 {in}개{loops}. 연결 총 {total}개. Enter로 상세정보 확인.",
          "viewer.intent.loops": ", 자기순환 {count}개",
          "viewer.common.copied": "복사됨",
          "viewer.common.copyFailed": "복사 실패",
          "viewer.common.copyLink": "링크 복사",
          "viewer.common.clear": "지우기",
          "viewer.common.close": "닫기",
          "viewer.export.svg.auto": "SVG · 자동",
          "viewer.export.svg.auto.hint": "호스트 테마에 맞춤",
          "viewer.export.svg.light": "SVG · 라이트",
          "viewer.export.svg.light.hint": "항상 라이트 테마",
          "viewer.export.svg.dark": "SVG · 다크",
          "viewer.export.svg.dark.hint": "항상 다크 테마",
          "viewer.guide.title": "이 시스템 살펴보기",
          "viewer.focus.selectedNodes": "선택한 노드 {count}개",
          "viewer.passport.move": "의미 정보 패널 이동. 드래그하거나 화살표 키를 사용하고, Home 키로 초기화하세요.",
          "viewer.outline.title": "노드 목록",
          "viewer.rail.show": "설명 및 목록",
          "viewer.rail.controls": "측면 패널",
          "viewer.rail.collapse": "측면 패널 접기",
          "viewer.rail.bottom": "패널을 다이어그램 아래로 이동",
          "viewer.rail.right": "패널을 다이어그램 옆으로 이동"
        }
        
      • pt.json 25.9 KB
        {
          "page.title": "Diagrama {title}",
          "diagram.description.architecture": "Um diagrama de arquitetura gerado pelo Archify.",
          "diagram.description.workflow": "Um diagrama de fluxo de trabalho gerado pelo Archify.",
          "diagram.description.sequence": "Um diagrama de sequência gerado pelo Archify.",
          "diagram.description.dataflow": "Um diagrama de fluxo de dados gerado pelo Archify.",
          "diagram.description.lifecycle": "Um diagrama de ciclo de vida gerado pelo Archify.",
          "node.focus": "Focar {label}",
          "node.focus.detail": "Focar {label}, {detail}",
          "node.context.architecture": "Componente de arquitetura",
          "node.context.workflow": "Nó de fluxo de trabalho",
          "node.context.sequence": "Participante da sequência",
          "node.context.dataflow": "Nó de fluxo de dados",
          "node.context.lifecycle": "Estado do ciclo de vida",
          "legend.title": "Legenda",
          "legend.architecture.frontend": "Frontend",
          "legend.architecture.backend": "Backend",
          "legend.architecture.database": "Banco de dados",
          "legend.architecture.cloud": "Nuvem",
          "legend.architecture.security": "Segurança",
          "legend.architecture.messagebus": "Barramento de mensagens",
          "legend.architecture.external": "Externo",
          "legend.workflow.frontend": "UI do usuário",
          "legend.workflow.backend": "Lógica do agente",
          "legend.workflow.security": "Política",
          "legend.workflow.messagebus": "Ação de ferramenta",
          "legend.workflow.database": "Contexto / rastreamento",
          "legend.workflow.cloud": "Serviço de nuvem",
          "legend.workflow.external": "Sistema externo",
          "legend.sequence.emphasis": "solicitação principal",
          "legend.sequence.return": "retorno",
          "legend.sequence.security": "segurança",
          "legend.sequence.dashed": "rastreamento assíncrono",
          "legend.sequence.default": "mensagem",
          "legend.dataflow.emphasis": "dado principal",
          "legend.dataflow.security": "política / PII",
          "legend.dataflow.dashed": "lote assíncrono",
          "legend.dataflow.database": "armazenamento de dados",
          "legend.dataflow.default": "fluxo de dados",
          "legend.lifecycle.start": "estado inicial",
          "legend.lifecycle.active": "ativo",
          "legend.lifecycle.waiting": "aguardando",
          "legend.lifecycle.decision": "decisão",
          "legend.lifecycle.success": "sucesso",
          "legend.lifecycle.failure": "falha / saída",
          "legend.lifecycle.neutral": "neutro",
          "legend.lifecycle.external": "externo",
          "legend.lifecycle.final": "estado final",
          "viewer.kind.frontend": "Frontend",
          "viewer.kind.backend": "Backend",
          "viewer.kind.database": "Banco de dados",
          "viewer.kind.cloud": "Nuvem",
          "viewer.kind.security": "Segurança",
          "viewer.kind.messagebus": "Barramento de mensagens",
          "viewer.kind.external": "Externo",
          "viewer.kind.neutral": "Neutro",
          "viewer.kind.node": "Nó",
          "viewer.kind.start": "Início",
          "viewer.kind.active": "Ativo",
          "viewer.kind.waiting": "Aguardando",
          "viewer.kind.decision": "Decisão",
          "viewer.kind.success": "Sucesso",
          "viewer.kind.failure": "Falha",
          "viewer.toolbar.actions": "Ações do diagrama",
          "viewer.theme.toggle.title": "Alternar tema (T)",
          "viewer.theme.toggle": "Alternar tema de cores",
          "viewer.theme.dark": "Escuro",
          "viewer.theme.light": "Claro",
          "viewer.preset.choose.title": "Escolher estilo visual (S alterna)",
          "viewer.preset.choose": "Escolher estilo visual",
          "viewer.preset.style": "Estilo",
          "viewer.preset.menu": "Estilo visual",
          "viewer.preset.identity": "Identidade visual",
          "viewer.preset.cycles": "S alterna",
          "viewer.preset.classic": "Clássico",
          "viewer.preset.classic.short": "Clássico",
          "viewer.preset.classic.hint": "Padrão técnico estável",
          "viewer.preset.flow": "Fluxo de Sinal",
          "viewer.preset.flow.short": "Fluxo",
          "viewer.preset.flow.hint": "Apresentação com foco em movimento",
          "viewer.preset.blueprint": "Planta",
          "viewer.preset.blueprint.hint": "Revisão de engenharia",
          "viewer.preset.editorial": "Editorial",
          "viewer.preset.editorial.hint": "Notas de publicação e lançamento",
          "viewer.preset.badge.signalFlow": "FLUXO DE SINAL",
          "viewer.preset.badge.blueprint": "PLANTA / REV 01",
          "viewer.preset.badge.editorial": "EDITORIAL / NOTA DE CAMPO",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / PLACA 04",
          "viewer.preset.current": "Estilo visual: {style}. Escolher estilo visual",
          "viewer.motion.live": "Ao vivo",
          "viewer.motion.still": "Estático",
          "viewer.motion.pause": "Pausar movimento",
          "viewer.motion.resume": "Retomar movimento",
          "viewer.motion.reduced": "Movimento pausado pela preferência de movimento reduzido",
          "viewer.motion.hidden": "Movimento pausado enquanto esta página está oculta",
          "viewer.motion.yielding": "Pausar movimento; cedendo atualmente a {owner}",
          "viewer.motion.yielding.title": "Pré-visualização ao vivo ativada · cedendo a {owner}",
          "viewer.owner.route": "Sonda de Rota",
          "viewer.owner.lens": "Lente Semântica",
          "viewer.owner.relationship": "Pré-visualização de Relação",
          "viewer.owner.intent": "Rastreamento de Intenção",
          "viewer.owner.focus": "foco semântico",
          "viewer.owner.legend": "pré-visualização da legenda",
          "viewer.owner.reader": "interação do leitor",
          "viewer.present.enter": "Entrar no palco de apresentação",
          "viewer.present.enter.title": "Palco de apresentação (F)",
          "viewer.present.exit": "Sair do palco de apresentação",
          "viewer.present.exit.title": "Sair do palco de apresentação (F ou Escape)",
          "viewer.present.present": "Apresentar",
          "viewer.present.exit.label": "Sair",
          "viewer.export.button": "Exportar",
          "viewer.export.button.title": "Exportar diagrama (E)",
          "viewer.export.diagram": "Exportar diagrama",
          "viewer.export.menu": "Exportar",
          "viewer.export.subtitle": "Saídas portáteis e limpas",
          "viewer.export.share": "Compartilhar",
          "viewer.export.shareCard": "Cartão de Compartilhamento",
          "viewer.export.routeShareCard": "Cartão de Compartilhamento de Rota",
          "viewer.export.reachShareCard": "Cartão de Compartilhamento de Alcance",
          "viewer.export.copyDiagram": "Copiar diagrama",
          "viewer.export.clipboardPng": "PNG para a área de transferência",
          "viewer.export.raster": "Imagens raster",
          "viewer.export.image": "Imagem",
          "viewer.export.lossless": "Imagem sem perdas",
          "viewer.export.compact": "Imagem compacta",
          "viewer.export.modern": "Imagem moderna",
          "viewer.export.vectorMotion": "Vetor e movimento",
          "viewer.export.vectorMotion.heading": "Vetor e movimento",
          "viewer.export.editable": "Vetor editável",
          "viewer.export.motion6s": "Movimento de 6s",
          "viewer.export.unsupported": "Não suportado por este navegador",
          "viewer.export.clipboardUnsupported": "Este navegador não suporta gravação de imagem na área de transferência",
          "viewer.export.clipboardUnsupported.short": "Gravação de imagem na área de transferência não suportada neste navegador.",
          "viewer.export.motionUnavailable": "Captura de movimento indisponível neste navegador",
          "viewer.export.webmUnavailable": "WebM indisponível neste navegador",
          "viewer.export.failed": "Falha na exportação: {message}",
          "viewer.export.unknownVariant": "Variante de Cartão de Compartilhamento desconhecida: {variant}",
          "viewer.export.routeRequired": "Trace uma rota antes de exportar um Cartão de Compartilhamento de Rota",
          "viewer.export.reachRequired": "Trace o alcance definido antes de exportar um Cartão de Compartilhamento de Alcance",
          "viewer.export.unknown": "desconhecido",
          "viewer.export.routeFailed": "Falha ao exportar o Cartão de Compartilhamento de Rota: {message}",
          "viewer.export.reachFailed": "Falha ao exportar o Cartão de Compartilhamento de Alcance: {message}",
          "viewer.export.copyFailed": "Falha ao copiar: {message}",
          "viewer.export.copiedPng": "PNG copiado para a área de transferência",
          "viewer.export.downloadedRoute": "Cartão de Compartilhamento de Rota baixado",
          "viewer.export.downloadedReach": "Cartão de Compartilhamento de Alcance baixado",
          "viewer.export.downloadedWebm": "WebM baixado",
          "viewer.export.recording": "Gravando 6 segundos de movimento…",
          "viewer.export.card.routeSummary.one": "Rota: {source} → {target} · {count} salto direcionado",
          "viewer.export.card.routeSummary.other": "Rota: {source} → {target} · {count} saltos direcionados",
          "viewer.export.card.reachSummary": "{direction} definido a partir de {origin} · {nodes} · {links} · máx {hops}",
          "viewer.export.card.node.one": "{count} nó",
          "viewer.export.card.node.other": "{count} nós",
          "viewer.export.card.link.one": "{count} conexão",
          "viewer.export.card.link.other": "{count} conexões",
          "viewer.export.card.hop.one": "{count} salto",
          "viewer.export.card.hop.other": "{count} saltos",
          "viewer.export.card.routeBadge": "ARCHIFY · ROTA · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · ALCANCE {direction}",
          "viewer.export.direction.upstream": "Upstream",
          "viewer.export.direction.downstream": "Downstream",
          "viewer.export.error.canvasUnavailable": "Canvas indisponível para {label}",
          "viewer.export.error.contextUnavailable": "Contexto de canvas 2D indisponível para {label}",
          "viewer.export.error.toBlobUnavailable": "canvas.toBlob indisponível para {label}",
          "viewer.export.error.toBlobNull": "canvas.toBlob não retornou dados para {label}",
          "viewer.export.error.variantsCombined": "As variantes do Cartão de Compartilhamento não podem ser combinadas",
          "viewer.export.error.viewerState": "A exportação do Cartão de Compartilhamento não conseguiu remover o estado temporário do visualizador",
          "viewer.export.error.routeState": "A exportação do Cartão de Rota não conseguiu preservar a rota resolvida com segurança",
          "viewer.export.error.reachState": "A exportação do Cartão de Alcance não conseguiu preservar o alcance definido com segurança",
          "viewer.export.error.webmRequirements": "A exportação de movimento em WebM requer uma animação de rastreamento e suporte a MediaRecorder no navegador",
          "viewer.export.error.mediaRecorder": "Falha no MediaRecorder",
          "viewer.export.error.emptyWebm": "O MediaRecorder produziu um WebM vazio",
          "viewer.export.error.webmBackground": "Não foi possível carregar o plano de fundo SVG para a exportação em WebM",
          "viewer.guide.eyebrow": "Guia do diagrama",
          "viewer.guide.close": "Fechar guia do diagrama",
          "viewer.guide.inspecting": "Inspecionando semântica compilada",
          "viewer.guide.actions": "Ações de exploração do diagrama",
          "viewer.guide.find": "Encontrar qualquer nó",
          "viewer.guide.find.hint": "Pesquise rótulos, responsabilidades, tipos e IDs estáveis.",
          "viewer.guide.route": "Traçar uma rota",
          "viewer.guide.route.aria": "Traçar uma rota direcionada",
          "viewer.guide.route.hint": "Descubra como dois nós semânticos se conectam na direção definida.",
          "viewer.guide.map": "Ver o sistema inteiro",
          "viewer.guide.map.hint": "Abra o Radar Semântico com uma janela de visualização ativa e nós estáveis.",
          "viewer.guide.lens": "Comparar tipos semânticos",
          "viewer.guide.lens.hint": "Conte papéis, revele seu tráfego e compare links diretos definidos.",
          "viewer.guide.present": "Entrar no Palco de Apresentação",
          "viewer.guide.present.hint": "Dê ao diagrama ao vivo a janela de visualização inteira sem alterar a exportação.",
          "viewer.guide.shortcuts": "Atalhos de teclado adicionais",
          "viewer.guide.shortcut.export": "Exportar",
          "viewer.guide.shortcut.theme": "Tema",
          "viewer.guide.shortcut.style": "Estilo",
          "viewer.guide.shortcut.reset": "Redefinir",
          "viewer.guide.shortcut.zoomIn": "Ampliar",
          "viewer.guide.shortcut.zoomOut": "Reduzir",
          "viewer.guide.shortcut.close": "Fechar",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} nó semântico",
          "viewer.guide.fact.node.other": "{count} nós semânticos",
          "viewer.guide.fact.relationship.one": "{count} relação",
          "viewer.guide.fact.relationship.other": "{count} relações",
          "viewer.guide.open": "Abrir guia do diagrama",
          "viewer.finder.title": "Encontrar um nó",
          "viewer.finder.close": "Fechar buscador de nós",
          "viewer.finder.placeholder": "Pesquisar rótulos ou IDs",
          "viewer.finder.search": "Pesquisar nós do diagrama",
          "viewer.finder.results": "Nós do diagrama",
          "viewer.finder.empty": "Nenhum nó correspondente",
          "viewer.finder.result.focus": "Focar {label}",
          "viewer.finder.result.routeStart": "Escolher {label} como início da rota",
          "viewer.finder.result.routeTarget": "Escolher {label} como destino da rota, {links}",
          "viewer.finder.status.empty": "Nenhum nó correspondente",
          "viewer.finder.status.count.one": "{count} nó correspondente",
          "viewer.finder.status.count.other": "{count} nós correspondentes",
          "viewer.finder.noun.nodes": "nós",
          "viewer.finder.link.one": "{count} conexão",
          "viewer.finder.link.other": "{count} conexões",
          "viewer.finder.result.focus.one": "Focar {label}, {count} conexão relacionada",
          "viewer.finder.result.focus.other": "Focar {label}, {count} conexões relacionadas",
          "viewer.finder.status.filtered": "{visible} de {available} {noun}",
          "viewer.finder.status.all": "{available} {noun}",
          "viewer.passport.eyebrow": "Passaporte semântico",
          "viewer.passport.metadata": "Metadados do nó",
          "viewer.passport.evidence": "Evidência de origem verificada",
          "viewer.passport.verified": "Origem verificada",
          "viewer.passport.verificationScope": "Verificado com o Git local na revisão fixada. O acesso remoto não foi verificado.",
          "viewer.passport.reach": "Alcance definido",
          "viewer.passport.reach.trace": "Traçar alcançabilidade definida",
          "viewer.passport.upstream": "Upstream",
          "viewer.passport.downstream": "Downstream",
          "viewer.passport.upstream.trace": "Traçar alcançabilidade definida upstream",
          "viewer.passport.downstream.trace": "Traçar alcançabilidade definida downstream",
          "viewer.passport.close": "Fechar passaporte semântico",
          "viewer.passport.copy": "Copiar link",
          "viewer.passport.copy.focus": "Copiar link do nó em foco",
          "viewer.passport.relations": "Relações",
          "viewer.passport.relations.show": "Mostrar relações conectadas",
          "viewer.passport.relations.hide": "Ocultar relações conectadas",
          "viewer.passport.relations.list": "Relações conectadas",
          "viewer.passport.copyRelation": "Copiar relação",
          "viewer.passport.copyNode": "Copiar nó",
          "viewer.passport.copyPinned": "Copiar link da relação fixada",
          "viewer.passport.copySource": "Copiar link do nó de origem",
          "viewer.passport.copy.focused.success": "Link do nó em foco copiado",
          "viewer.passport.copy.pinned.success": "Link da relação fixada copiado",
          "viewer.passport.copy.focused.failed": "Não foi possível copiar o link do nó em foco",
          "viewer.passport.copy.pinned.failed": "Não foi possível copiar o link da relação fixada",
          "viewer.passport.relationship.none": "Nenhuma relação conectada",
          "viewer.passport.relationship.count.one": "{count} relação",
          "viewer.passport.relationship.count.other": "{count} relações",
          "viewer.passport.relationship.show.one": "Mostrar {count} relação conectada",
          "viewer.passport.relationship.show.other": "Mostrar {count} relações conectadas",
          "viewer.passport.relationship.summary": "{out} de saída · {in} de entrada{loops}",
          "viewer.passport.relationship.loops": " · {count} laço",
          "viewer.passport.relationship.explorer": "Explorador de relações diretas",
          "viewer.passport.relationship.help": "Use as setas para explorar relações. Pressione Enter ou Espaço para fixar detalhes; Escape limpa.",
          "viewer.passport.relationship.loopsBack": "retorna em laço",
          "viewer.passport.relationship.connectsTo": "conecta-se a",
          "viewer.passport.relationship.connectsFrom": "conecta-se de",
          "viewer.passport.relationship.pinned": "Relação fixada · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "Inspecionar relação {index} de {total}: {from} para {to}, {label}. Pressione Enter para detalhes.",
          "viewer.passport.relationship.group.out": "Saída",
          "viewer.passport.relationship.group.in": "Entrada",
          "viewer.passport.relationship.group.loop": "Laços próprios",
          "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "SAÍDA →",
          "viewer.passport.relationship.direction.in": "← ENTRADA",
          "viewer.passport.relationship.direction.loop": "LAÇO",
          "viewer.passport.sourceCount.one": "{count} referência de origem verificada",
          "viewer.passport.sourceCount.other": "{count} referências de origem verificadas",
          "viewer.passport.sourceMarker": "ORIG",
          "viewer.passport.beacon.one": "{count} origem verificada; foque este nó para inspecionar",
          "viewer.passport.beacon.other": "{count} origens verificadas; foque este nó para inspecionar",
          "viewer.passport.repository.open": "Abrir revisão verificada do repositório {revision}",
          "viewer.passport.source.open": "Abrir origem verificada {path} na revisão {revision}",
          "viewer.passport.source.openLink": "Abrir ↗",
          "viewer.passport.reach.upstream.one": "Traçar {count} nó definido upstream",
          "viewer.passport.reach.upstream.other": "Traçar {count} nós definidos upstream",
          "viewer.passport.reach.downstream.one": "Traçar {count} nó definido downstream",
          "viewer.passport.reach.downstream.other": "Traçar {count} nós definidos downstream",
          "viewer.passport.reach.noUpstream": "Nenhum nó definido upstream",
          "viewer.passport.reach.noDownstream": "Nenhum nó definido downstream",
          "viewer.passport.reach.status": "{direction} · {nodes} nós · {links} conexões · máx {hops} saltos",
          "viewer.route.eyebrow": "Sonda de rota",
          "viewer.route.start": "Escolher um nó inicial",
          "viewer.route.start.find": "Encontrar início",
          "viewer.route.start.find.aria": "Encontrar um início de rota",
          "viewer.route.copy": "Copiar link",
          "viewer.route.copy.aria": "Copiar link da rota traçada",
          "viewer.route.clear": "Limpar",
          "viewer.route.clear.aria": "Limpar sonda de rota",
          "viewer.route.traced": "Rota traçada",
          "viewer.route.pickTwo": "Escolha dois nós semânticos no diagrama",
          "viewer.route.pickOne": "Escolha um nó semântico no diagrama",
          "viewer.route.controls": "Controles da jornada de rota",
          "viewer.route.previous": "Posição anterior da rota",
          "viewer.route.play": "Reproduzir jornada de rota",
          "viewer.route.pause": "Pausar jornada de rota",
          "viewer.route.replay": "Reproduzir jornada de rota novamente",
          "viewer.route.next": "Próxima posição da rota",
          "viewer.route.journey": "Jornada",
          "viewer.route.pause.label": "Pausar",
          "viewer.route.replay.label": "Repetir",
          "viewer.route.overview": "Visão geral",
          "viewer.route.overview.aria": "Mostrar visão geral completa da rota",
          "viewer.route.instructions": "Escolha a origem e depois o destino. A direção importa.",
          "viewer.route.destination": "Escolher um destino a partir de {label}",
          "viewer.route.destination.find": "Encontrar destino",
          "viewer.route.destination.find.aria": "Encontrar um destino de rota alcançável",
          "viewer.route.differentDestination": "Escolher um destino diferente",
          "viewer.route.distinct": "Uma rota precisa de dois nós semânticos distintos.",
          "viewer.route.unreachable": "Nenhuma rota direcionada para {label}",
          "viewer.route.unreachable.detail": "{target} não é alcançável a partir de {source}. Escolha um destino destacado.",
          "viewer.route.start.instructions": "Selecione a origem. O próximo passo revelará apenas destinos direcionados.",
          "viewer.route.copy.success": "Link da rota traçada copiado",
          "viewer.route.copy.failed": "Não foi possível copiar o link da rota traçada",
          "viewer.route.position": "Posição {index} de {total} na rota: {label}",
          "viewer.route.step": "Passo {index} de {total} · {phase} · {label}",
          "viewer.route.motionRequired": "A jornada automática requer movimento Ao vivo",
          "viewer.route.trigger.clear": "Limpar rota traçada",
          "viewer.route.overview.status": "{nodes} · {hops} · rota mais curta definida",
          "viewer.route.overview.node.one": "{count} nó",
          "viewer.route.overview.node.other": "{count} nós",
          "viewer.route.overview.hop.one": "{count} salto direcionado",
          "viewer.route.overview.hop.other": "{count} saltos direcionados",
          "viewer.route.phase.playing": "Reproduzindo",
          "viewer.route.phase.complete": "Concluído",
          "viewer.route.phase.inspecting": "Inspecionando",
          "viewer.route.destination.count.one": "{count} destino direcionado disponível. Escolha um nó destacado.",
          "viewer.route.destination.count.other": "{count} destinos direcionados disponíveis. Escolha um nó destacado.",
          "viewer.route.noOutgoing": "Nenhuma rota de saída começa aqui. Limpe e escolha outra origem.",
          "viewer.route.result.title": "{source} até {target}",
          "viewer.route.finder.source.title": "Escolher início da rota",
          "viewer.route.finder.source.placeholder": "Pesquisar origens de rota",
          "viewer.route.finder.source.empty": "Nenhuma origem de rota correspondente",
          "viewer.route.finder.source.results": "Nós que podem iniciar uma rota",
          "viewer.route.finder.source.noun": "origens de rota",
          "viewer.route.finder.source.badge": "início",
          "viewer.route.finder.target.title": "Destino a partir de {label}",
          "viewer.route.finder.target.placeholder": "Pesquisar destinos alcançáveis",
          "viewer.route.finder.target.empty": "Nenhum destino alcançável correspondente",
          "viewer.route.finder.target.results": "Destinos de rota alcançáveis",
          "viewer.route.finder.target.noun": "destinos alcançáveis",
          "viewer.route.hop.one": "{count} salto",
          "viewer.route.hop.other": "{count} saltos",
          "viewer.lens.eyebrow": "Lente semântica",
          "viewer.lens.title": "Comparar papéis do sistema",
          "viewer.lens.close": "Fechar lente semântica",
          "viewer.lens.instruction": "Escolha até dois tipos semânticos. Um revela seu tráfego real; dois comparam apenas relações diretas definidas.",
          "viewer.lens.kinds": "Tipos semânticos",
          "viewer.lens.choose": "Escolha um tipo para inspecionar seus nós e relações que o tocam.",
          "viewer.lens.copy": "Copiar link da lente semântica",
          "viewer.lens.clear": "Limpar lente semântica",
          "viewer.lens.open": "Abrir lente semântica",
          "viewer.lens.openActive": "Abrir lente semântica ativa",
          "viewer.lens.legend": "Legenda semântica",
          "viewer.lens.legend.inspect.one": "Inspecionar {label}, {count} nó",
          "viewer.lens.legend.inspect.other": "Inspecionar {label}, {count} nós",
          "viewer.lens.kind.count.one": "{label}, {count} nó",
          "viewer.lens.kind.count.other": "{label}, {count} nós",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} relação direta",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} relações diretas",
          "viewer.lens.single": "{nodes} · {relationships} · nós conectados permanecem visíveis",
          "viewer.lens.node.one": "{count} nó {label}",
          "viewer.lens.node.other": "{count} nós {label}",
          "viewer.lens.relationship.one": "{count} relação que toca",
          "viewer.lens.relationship.other": "{count} relações que tocam",
          "viewer.radar.title": "Radar semântico",
          "viewer.radar.building": "Construindo visão geral",
          "viewer.radar.openFull": "Abrir radar semântico completo",
          "viewer.radar.open": "Abrir radar",
          "viewer.radar.close": "Fechar radar semântico",
          "viewer.radar.surface": "Visão geral do diagrama. Clique em um nó para focá-lo, ou use as setas para navegar.",
          "viewer.radar.click": "Clicar no nó",
          "viewer.radar.drag": "Arrastar para navegar",
          "viewer.radar.space": "O radar semântico precisa de mais espaço no MAPA.",
          "viewer.radar.nodes": "Nós do radar do diagrama semântico",
          "viewer.radar.focus": "Focar {label} a partir do Radar Semântico",
          "viewer.radar.status": "{count} nós · {viewport}",
          "viewer.radar.fullMap": "{count} nós · mapa completo",
          "viewer.radar.compacted": "Radar compactado para não cobrir o Passaporte Semântico ou os controles do MAPA.",
          "viewer.radar.cancelWaiting": "Cancelar radar semântico aguardando mais espaço no MAPA",
          "viewer.radar.needsSpace": "O radar semântico precisa de mais espaço visível no MAPA",
          "viewer.radar.viewport.full": "mapa completo",
          "viewer.radar.viewport.width": "{percent}% de largura",
          "viewer.radar.viewport.scale": "{percent}% da janela de visualização",
          "viewer.nav.controls": "Controles de visualização do diagrama",
          "viewer.nav.route": "Traçar uma rota direcionada",
          "viewer.nav.route.title": "Traçar rota (R)",
          "viewer.nav.route.short": "ROTA",
          "viewer.nav.radar": "Abrir radar semântico",
          "viewer.nav.radar.title": "Radar semântico (M)",
          "viewer.nav.radar.short": "MAPA",
          "viewer.nav.lens": "Abrir lente semântica",
          "viewer.nav.lens.title": "Lente semântica (L)",
          "viewer.nav.lens.short": "LENTE",
          "viewer.nav.find": "Encontrar um nó",
          "viewer.nav.find.title": "Encontrar um nó (/)",
          "viewer.nav.guide": "Abrir guia do diagrama",
          "viewer.nav.guide.title": "Guia do diagrama (?)",
          "viewer.nav.zoomOut": "Reduzir",
          "viewer.nav.zoomOut.title": "Reduzir (-)",
          "viewer.nav.reset": "Redefinir visualização do diagrama",
          "viewer.nav.reset.title": "Redefinir visualização (0)",
          "viewer.nav.read": "LEITURA",
          "viewer.nav.zoomIn": "Ampliar",
          "viewer.nav.zoomIn.title": "Ampliar (+)",
          "viewer.nav.camera": "{hint}. Redefinir visualização do diagrama",
          "viewer.nav.camera.title": "{semantic}{hint} · redefinir visualização (0)",
          "viewer.nav.camera.semantic": "Câmera semântica ativa · ",
          "viewer.nav.level.map": "MAPA",
          "viewer.nav.level.read": "LEITURA",
          "viewer.nav.level.full": "COMPLETO",
          "viewer.nav.level.auto": "AUTO",
          "viewer.nav.detail.map": "Amplie para revelar rótulos de relações e contexto do nó",
          "viewer.nav.detail.read": "Amplie novamente para revelar tags e anotações",
          "viewer.nav.detail.full": "Detalhe completo do diagrama",
          "viewer.intent.summary": "{label}. {out} de saída, {in} de entrada{loops}. {total} conexões. Pressione Enter para detalhes.",
          "viewer.intent.loops": ", {count} laço próprio",
          "viewer.common.copied": "Copiado",
          "viewer.common.copyFailed": "Falha ao copiar",
          "viewer.common.copyLink": "Copiar link",
          "viewer.common.clear": "Limpar",
          "viewer.common.close": "Fechar"
        }
        
      • ru.json 33.7 KB
        {
          "page.title": "{title} — диаграмма",
          "diagram.description.architecture": "Диаграмма архитектуры, созданная в Archify.",
          "diagram.description.workflow": "Диаграмма рабочего процесса, созданная в Archify.",
          "diagram.description.sequence": "Диаграмма последовательности, созданная в Archify.",
          "diagram.description.dataflow": "Диаграмма потока данных, созданная в Archify.",
          "diagram.description.lifecycle": "Диаграмма жизненного цикла, созданная в Archify.",
          "node.focus": "Фокус: {label}",
          "node.focus.detail": "Фокус: {label}, {detail}",
          "node.context.architecture": "Компонент архитектуры",
          "node.context.workflow": "Узел рабочего процесса",
          "node.context.sequence": "Участник последовательности",
          "node.context.dataflow": "Узел потока данных",
          "node.context.lifecycle": "Состояние жизненного цикла",
          "legend.title": "Легенда",
          "legend.architecture.frontend": "Фронтенд",
          "legend.architecture.backend": "Бэкенд",
          "legend.architecture.database": "База данных",
          "legend.architecture.cloud": "Облако",
          "legend.architecture.security": "Безопасность",
          "legend.architecture.messagebus": "Шина сообщений",
          "legend.architecture.external": "Внешний",
          "legend.workflow.frontend": "Интерфейс пользователя",
          "legend.workflow.backend": "Логика агента",
          "legend.workflow.security": "Политика",
          "legend.workflow.messagebus": "Действие инструмента",
          "legend.workflow.database": "Контекст / трассировка",
          "legend.workflow.cloud": "Облачный сервис",
          "legend.workflow.external": "Внешняя система",
          "legend.sequence.emphasis": "основной запрос",
          "legend.sequence.return": "возврат",
          "legend.sequence.security": "безопасность",
          "legend.sequence.dashed": "асинхронная трассировка",
          "legend.sequence.default": "сообщение",
          "legend.dataflow.emphasis": "основные данные",
          "legend.dataflow.security": "политика / ПДн",
          "legend.dataflow.dashed": "асинхронный пакет",
          "legend.dataflow.database": "хранилище данных",
          "legend.dataflow.default": "поток данных",
          "legend.lifecycle.start": "начальное состояние",
          "legend.lifecycle.active": "активно",
          "legend.lifecycle.waiting": "ожидание",
          "legend.lifecycle.decision": "решение",
          "legend.lifecycle.success": "успех",
          "legend.lifecycle.failure": "ошибка / выход",
          "legend.lifecycle.neutral": "нейтральное",
          "legend.lifecycle.external": "внешнее",
          "legend.lifecycle.final": "конечное состояние",
          "viewer.kind.frontend": "Фронтенд",
          "viewer.kind.backend": "Бэкенд",
          "viewer.kind.database": "База данных",
          "viewer.kind.cloud": "Облако",
          "viewer.kind.security": "Безопасность",
          "viewer.kind.messagebus": "Шина сообщений",
          "viewer.kind.external": "Внешний",
          "viewer.kind.neutral": "Нейтральный",
          "viewer.kind.node": "Узел",
          "viewer.kind.start": "Начало",
          "viewer.kind.active": "Активно",
          "viewer.kind.waiting": "Ожидание",
          "viewer.kind.decision": "Решение",
          "viewer.kind.success": "Успех",
          "viewer.kind.failure": "Ошибка",
          "viewer.toolbar.actions": "Действия с диаграммой",
          "viewer.theme.toggle.title": "Переключить тему (T)",
          "viewer.theme.toggle": "Переключить цветовую тему",
          "viewer.theme.dark": "Тёмная",
          "viewer.theme.light": "Светлая",
          "viewer.preset.choose.title": "Выбрать визуальный стиль (S — переключение)",
          "viewer.preset.choose": "Выбрать визуальный стиль",
          "viewer.preset.style": "Стиль",
          "viewer.preset.menu": "Визуальный стиль",
          "viewer.preset.identity": "Визуальная идентичность",
          "viewer.preset.cycles": "S — переключение",
          "viewer.preset.classic": "Классический",
          "viewer.preset.classic.short": "Классика",
          "viewer.preset.classic.hint": "Стабильный технический стиль по умолчанию",
          "viewer.preset.flow": "Поток сигналов",
          "viewer.preset.flow.short": "Поток",
          "viewer.preset.flow.hint": "Презентация с акцентом на анимацию",
          "viewer.preset.blueprint": "Чертёж",
          "viewer.preset.blueprint.hint": "Для инженерного обзора",
          "viewer.preset.editorial": "Редакционный",
          "viewer.preset.editorial.hint": "Для публикаций и анонсов",
          "viewer.preset.badge.signalFlow": "ПОТОК СИГНАЛОВ",
          "viewer.preset.badge.blueprint": "ЧЕРТЁЖ / РЕД. 01",
          "viewer.preset.badge.editorial": "РЕДАКЦИЯ / ЗАМЕТКА",
          "viewer.preset.badge.editorialPlate": "ARCHIFY / ПЛАСТИНА 04",
          "viewer.preset.current": "Визуальный стиль: {style}. Выбрать визуальный стиль",
          "viewer.motion.live": "Динамика",
          "viewer.motion.still": "Статика",
          "viewer.motion.pause": "Приостановить анимацию",
          "viewer.motion.resume": "Возобновить анимацию",
          "viewer.motion.reduced": "Анимация приостановлена из-за настройки сниженного движения",
          "viewer.motion.hidden": "Анимация приостановлена, пока страница скрыта",
          "viewer.motion.yielding": "Приостановить анимацию; сейчас уступает место: {owner}",
          "viewer.motion.yielding.title": "Динамический просмотр включён · уступает место: {owner}",
          "viewer.owner.route": "Зонд маршрута",
          "viewer.owner.lens": "Семантическая линза",
          "viewer.owner.relationship": "Предпросмотр связи",
          "viewer.owner.intent": "Трассировка намерения",
          "viewer.owner.focus": "семантический фокус",
          "viewer.owner.legend": "предпросмотр легенды",
          "viewer.owner.reader": "взаимодействие читателя",
          "viewer.present.enter": "Войти в режим презентации",
          "viewer.present.enter.title": "Режим презентации (F)",
          "viewer.present.exit": "Выйти из режима презентации",
          "viewer.present.exit.title": "Выйти из режима презентации (F или Escape)",
          "viewer.present.present": "Презентация",
          "viewer.present.exit.label": "Выход",
          "viewer.export.button": "Экспорт",
          "viewer.export.button.title": "Экспортировать диаграмму (E)",
          "viewer.export.diagram": "Экспортировать диаграмму",
          "viewer.export.menu": "Экспорт",
          "viewer.export.subtitle": "Портативные, аккуратные файлы",
          "viewer.export.share": "Поделиться",
          "viewer.export.shareCard": "Карточка для публикации",
          "viewer.export.routeShareCard": "Карточка маршрута",
          "viewer.export.reachShareCard": "Карточка достижимости",
          "viewer.export.copyDiagram": "Копировать диаграмму",
          "viewer.export.clipboardPng": "PNG в буфер обмена",
          "viewer.export.raster": "Растровые изображения",
          "viewer.export.image": "Изображение",
          "viewer.export.lossless": "Изображение без потерь",
          "viewer.export.compact": "Компактное изображение",
          "viewer.export.modern": "Современный формат изображения",
          "viewer.export.vectorMotion": "Вектор и анимация",
          "viewer.export.vectorMotion.heading": "Вектор и анимация",
          "viewer.export.editable": "Редактируемый вектор",
          "viewer.export.motion6s": "Анимация 6 с",
          "viewer.export.unsupported": "Не поддерживается этим браузером",
          "viewer.export.clipboardUnsupported": "Этот браузер не поддерживает запись изображений в буфер обмена",
          "viewer.export.clipboardUnsupported.short": "Запись изображений в буфер обмена не поддерживается в этом браузере.",
          "viewer.export.motionUnavailable": "Запись анимации недоступна в этом браузере",
          "viewer.export.webmUnavailable": "WebM недоступен в этом браузере",
          "viewer.export.failed": "Ошибка экспорта: {message}",
          "viewer.export.unknownVariant": "Неизвестный тип карточки: {variant}",
          "viewer.export.routeRequired": "Постройте маршрут перед экспортом карточки маршрута",
          "viewer.export.reachRequired": "Постройте заданную достижимость перед экспортом карточки достижимости",
          "viewer.export.unknown": "неизвестно",
          "viewer.export.routeFailed": "Не удалось экспортировать карточку маршрута: {message}",
          "viewer.export.reachFailed": "Не удалось экспортировать карточку достижимости: {message}",
          "viewer.export.copyFailed": "Не удалось скопировать: {message}",
          "viewer.export.copiedPng": "PNG скопирован в буфер обмена",
          "viewer.export.downloadedRoute": "Карточка маршрута загружена",
          "viewer.export.downloadedReach": "Карточка достижимости загружена",
          "viewer.export.downloadedWebm": "WebM загружен",
          "viewer.export.recording": "Запись анимации, 6 секунд…",
          "viewer.export.card.routeSummary.one": "Маршрут: {source} → {target} · {count} направленный переход",
          "viewer.export.card.routeSummary.other": "Маршрут: {source} → {target} · {count} направленных переходов",
          "viewer.export.card.reachSummary": "Заданная достижимость ({direction}) от {origin} · {nodes} · {links} · макс. {hops}",
          "viewer.export.card.node.one": "{count} узел",
          "viewer.export.card.node.other": "{count} узлов",
          "viewer.export.card.link.one": "{count} связь",
          "viewer.export.card.link.other": "{count} связей",
          "viewer.export.card.hop.one": "{count} переход",
          "viewer.export.card.hop.other": "{count} переходов",
          "viewer.export.card.routeBadge": "ARCHIFY · МАРШРУТ · {hops}",
          "viewer.export.card.reachBadge": "ARCHIFY · ДОСТИЖИМОСТЬ ({direction})",
          "viewer.export.direction.upstream": "Восходящий",
          "viewer.export.direction.downstream": "Нисходящий",
          "viewer.export.error.canvasUnavailable": "Canvas недоступен для {label}",
          "viewer.export.error.contextUnavailable": "2D-контекст canvas недоступен для {label}",
          "viewer.export.error.toBlobUnavailable": "canvas.toBlob недоступен для {label}",
          "viewer.export.error.toBlobNull": "canvas.toBlob не вернул данные для {label}",
          "viewer.export.error.variantsCombined": "Типы карточек нельзя комбинировать",
          "viewer.export.error.viewerState": "Не удалось удалить временное состояние просмотра при экспорте карточки",
          "viewer.export.error.routeState": "Не удалось безопасно сохранить построенный маршрут при экспорте карточки",
          "viewer.export.error.reachState": "Не удалось безопасно сохранить заданную достижимость при экспорте карточки",
          "viewer.export.error.webmRequirements": "Экспорт анимации в WebM требует анимации трассировки и поддержки MediaRecorder в браузере",
          "viewer.export.error.mediaRecorder": "Ошибка MediaRecorder",
          "viewer.export.error.emptyWebm": "MediaRecorder создал пустой файл WebM",
          "viewer.export.error.webmBackground": "Не удалось загрузить фон SVG для экспорта WebM",
          "viewer.guide.eyebrow": "Гид по диаграмме",
          "viewer.guide.close": "Закрыть гид по диаграмме",
          "viewer.guide.inspecting": "Анализ скомпилированной семантики",
          "viewer.guide.actions": "Действия для изучения диаграммы",
          "viewer.guide.find": "Найти любой узел",
          "viewer.guide.find.hint": "Поиск по меткам, ролям, типам и постоянным ID.",
          "viewer.guide.route": "Построить маршрут",
          "viewer.guide.route.aria": "Построить направленный маршрут",
          "viewer.guide.route.hint": "Узнайте, как два семантических узла связаны в заданном направлении.",
          "viewer.guide.map": "Просмотреть всю систему",
          "viewer.guide.map.hint": "Откройте семантический радар с живым видом и постоянными узлами.",
          "viewer.guide.lens": "Сравнить семантические типы",
          "viewer.guide.lens.hint": "Подсчитайте роли, покажите их связи и сравните прямые заданные связи.",
          "viewer.guide.present": "Войти в режим презентации",
          "viewer.guide.present.hint": "Отдать весь экран живой диаграмме без изменения экспорта.",
          "viewer.guide.shortcuts": "Дополнительные горячие клавиши",
          "viewer.guide.shortcut.export": "Экспорт",
          "viewer.guide.shortcut.theme": "Тема",
          "viewer.guide.shortcut.style": "Стиль",
          "viewer.guide.shortcut.reset": "Сброс",
          "viewer.guide.shortcut.zoomIn": "Увеличить",
          "viewer.guide.shortcut.zoomOut": "Уменьшить",
          "viewer.guide.shortcut.close": "Закрыть",
          "viewer.guide.facts": "{nodes} · {relationships}",
          "viewer.guide.fact.node.one": "{count} семантический узел",
          "viewer.guide.fact.node.other": "{count} семантических узлов",
          "viewer.guide.fact.relationship.one": "{count} связь",
          "viewer.guide.fact.relationship.other": "{count} связей",
          "viewer.guide.open": "Открыть гид по диаграмме",
          "viewer.finder.title": "Найти узел",
          "viewer.finder.close": "Закрыть поиск узлов",
          "viewer.finder.placeholder": "Поиск по меткам или ID",
          "viewer.finder.search": "Поиск узлов диаграммы",
          "viewer.finder.results": "Узлы диаграммы",
          "viewer.finder.empty": "Совпадений не найдено",
          "viewer.finder.result.focus": "Фокус: {label}",
          "viewer.finder.result.routeStart": "Выбрать {label} как начало маршрута",
          "viewer.finder.result.routeTarget": "Выбрать {label} как конец маршрута, {links}",
          "viewer.finder.status.empty": "Совпадений не найдено",
          "viewer.finder.status.count.one": "{count} совпадающий узел",
          "viewer.finder.status.count.other": "{count} совпадающих узлов",
          "viewer.finder.noun.nodes": "узлов",
          "viewer.finder.link.one": "{count} связь",
          "viewer.finder.link.other": "{count} связей",
          "viewer.finder.result.focus.one": "Фокус: {label}, {count} связанное соединение",
          "viewer.finder.result.focus.other": "Фокус: {label}, {count} связанных соединений",
          "viewer.finder.status.filtered": "{visible} из {available} {noun}",
          "viewer.finder.status.all": "{available} {noun}",
          "viewer.passport.eyebrow": "Семантический паспорт",
          "viewer.passport.metadata": "Метаданные узла",
          "viewer.passport.evidence": "Проверенные источники",
          "viewer.passport.verified": "Проверенный источник",
          "viewer.passport.verificationScope": "Проверено по локальному Git на фиксированной ревизии. Удалённый доступ не проверялся.",
          "viewer.passport.reach": "Заданная достижимость",
          "viewer.passport.reach.trace": "Отследить заданную достижимость",
          "viewer.passport.upstream": "Восходящий",
          "viewer.passport.downstream": "Нисходящий",
          "viewer.passport.upstream.trace": "Отследить восходящую заданную достижимость",
          "viewer.passport.downstream.trace": "Отследить нисходящую заданную достижимость",
          "viewer.passport.close": "Закрыть семантический паспорт",
          "viewer.passport.copy": "Скопировать ссылку",
          "viewer.passport.copy.focus": "Скопировать ссылку на выделенный узел",
          "viewer.passport.relations": "Связи",
          "viewer.passport.relations.show": "Показать связанные отношения",
          "viewer.passport.relations.hide": "Скрыть связанные отношения",
          "viewer.passport.relations.list": "Связанные отношения",
          "viewer.passport.copyRelation": "Копировать связь",
          "viewer.passport.copyNode": "Копировать узел",
          "viewer.passport.copyPinned": "Скопировать ссылку на закреплённую связь",
          "viewer.passport.copySource": "Скопировать ссылку на исходный узел",
          "viewer.passport.copy.focused.success": "Ссылка на выделенный узел скопирована",
          "viewer.passport.copy.pinned.success": "Ссылка на закреплённую связь скопирована",
          "viewer.passport.copy.focused.failed": "Не удалось скопировать ссылку на выделенный узел",
          "viewer.passport.copy.pinned.failed": "Не удалось скопировать ссылку на закреплённую связь",
          "viewer.passport.relationship.none": "Нет связанных отношений",
          "viewer.passport.relationship.count.one": "{count} связь",
          "viewer.passport.relationship.count.other": "{count} связей",
          "viewer.passport.relationship.show.one": "Показать {count} связанное отношение",
          "viewer.passport.relationship.show.other": "Показать {count} связанных отношений",
          "viewer.passport.relationship.summary": "{out} исходящих · {in} входящих{loops}",
          "viewer.passport.relationship.loops": " · {count} петля",
          "viewer.passport.relationship.explorer": "Обзор прямых связей",
          "viewer.passport.relationship.help": "Используйте стрелки для просмотра связей. Enter или пробел — закрепить детали; Escape — очистить.",
          "viewer.passport.relationship.loopsBack": "замыкается",
          "viewer.passport.relationship.connectsTo": "соединяется с",
          "viewer.passport.relationship.connectsFrom": "соединяется от",
          "viewer.passport.relationship.pinned": "Закреплённая связь · {from} → {to} · {label}",
          "viewer.passport.relationship.inspect": "Просмотр связи {index} из {total}: {from} → {to}, {label}. Enter — подробности.",
          "viewer.passport.relationship.group.out": "Исходящие",
          "viewer.passport.relationship.group.in": "Входящие",
          "viewer.passport.relationship.group.loop": "Петли",
          "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
          "viewer.passport.relationship.direction.out": "ИСХ →",
          "viewer.passport.relationship.direction.in": "← ВХ",
          "viewer.passport.relationship.direction.loop": "ПЕТЛЯ",
          "viewer.passport.sourceCount.one": "{count} проверенная ссылка на источник",
          "viewer.passport.sourceCount.other": "{count} проверенных ссылок на источники",
          "viewer.passport.sourceMarker": "ИСТ",
          "viewer.passport.beacon.one": "{count} проверенный источник; выделите узел для просмотра",
          "viewer.passport.beacon.other": "{count} проверенных источников; выделите узел для просмотра",
          "viewer.passport.repository.open": "Открыть проверенную ревизию репозитория {revision}",
          "viewer.passport.source.open": "Открыть проверенный источник {path} на ревизии {revision}",
          "viewer.passport.source.openLink": "Открыть ↗",
          "viewer.passport.reach.upstream.one": "Отследить {count} восходящий заданный узел",
          "viewer.passport.reach.upstream.other": "Отследить {count} восходящих заданных узлов",
          "viewer.passport.reach.downstream.one": "Отследить {count} нисходящий заданный узел",
          "viewer.passport.reach.downstream.other": "Отследить {count} нисходящих заданных узлов",
          "viewer.passport.reach.noUpstream": "Нет восходящих заданных узлов",
          "viewer.passport.reach.noDownstream": "Нет нисходящих заданных узлов",
          "viewer.passport.reach.status": "{direction} · узлов: {nodes} · связей: {links} · макс. переходов: {hops}",
          "viewer.route.eyebrow": "Зонд маршрута",
          "viewer.route.start": "Выбрать начальный узел",
          "viewer.route.start.find": "Найти начало",
          "viewer.route.start.find.aria": "Найти начало маршрута",
          "viewer.route.copy": "Скопировать ссылку",
          "viewer.route.copy.aria": "Скопировать ссылку на построенный маршрут",
          "viewer.route.clear": "Очистить",
          "viewer.route.clear.aria": "Очистить зонд маршрута",
          "viewer.route.traced": "Построенный маршрут",
          "viewer.route.pickTwo": "Выберите два семантических узла на диаграмме",
          "viewer.route.pickOne": "Выберите семантический узел на диаграмме",
          "viewer.route.controls": "Управление воспроизведением маршрута",
          "viewer.route.previous": "Предыдущая позиция маршрута",
          "viewer.route.play": "Воспроизвести маршрут",
          "viewer.route.pause": "Приостановить маршрут",
          "viewer.route.replay": "Повторить маршрут",
          "viewer.route.next": "Следующая позиция маршрута",
          "viewer.route.journey": "Путь",
          "viewer.route.pause.label": "Пауза",
          "viewer.route.replay.label": "Повтор",
          "viewer.route.overview": "Обзор",
          "viewer.route.overview.aria": "Показать полный обзор маршрута",
          "viewer.route.instructions": "Сначала выберите источник, затем цель. Направление важно.",
          "viewer.route.destination": "Выбрать цель от {label}",
          "viewer.route.destination.find": "Найти цель",
          "viewer.route.destination.find.aria": "Найти достижимую цель маршрута",
          "viewer.route.differentDestination": "Выбрать другую цель",
          "viewer.route.distinct": "Для маршрута нужны два разных семантических узла.",
          "viewer.route.unreachable": "Нет направленного маршрута к {label}",
          "viewer.route.unreachable.detail": "{target} недостижим из {source}. Выберите подсвеченную цель.",
          "viewer.route.start.instructions": "Выберите источник. На следующем шаге будут показаны только направленно достижимые цели.",
          "viewer.route.copy.success": "Ссылка на построенный маршрут скопирована",
          "viewer.route.copy.failed": "Не удалось скопировать ссылку на маршрут",
          "viewer.route.position": "Позиция маршрута {index} из {total}: {label}",
          "viewer.route.step": "Шаг {index} из {total} · {phase} · {label}",
          "viewer.route.motionRequired": "Автоматическое воспроизведение требует режима «Динамика»",
          "viewer.route.trigger.clear": "Очистить построенный маршрут",
          "viewer.route.overview.status": "{nodes} · {hops} · кратчайший заданный маршрут",
          "viewer.route.overview.node.one": "{count} узел",
          "viewer.route.overview.node.other": "{count} узлов",
          "viewer.route.overview.hop.one": "{count} направленный переход",
          "viewer.route.overview.hop.other": "{count} направленных переходов",
          "viewer.route.phase.playing": "Воспроизведение",
          "viewer.route.phase.complete": "Завершено",
          "viewer.route.phase.inspecting": "Просмотр",
          "viewer.route.destination.count.one": "Доступна {count} направленная цель. Выберите подсвеченный узел.",
          "viewer.route.destination.count.other": "Доступно {count} направленных целей. Выберите подсвеченный узел.",
          "viewer.route.noOutgoing": "Отсюда не начинается ни один исходящий маршрут. Очистите и выберите другой источник.",
          "viewer.route.result.title": "{source} → {target}",
          "viewer.route.finder.source.title": "Выбрать начало маршрута",
          "viewer.route.finder.source.placeholder": "Поиск источников маршрута",
          "viewer.route.finder.source.empty": "Совпадающих источников маршрута не найдено",
          "viewer.route.finder.source.results": "Узлы, с которых можно начать маршрут",
          "viewer.route.finder.source.noun": "источников маршрута",
          "viewer.route.finder.source.badge": "начало",
          "viewer.route.finder.target.title": "Цель от {label}",
          "viewer.route.finder.target.placeholder": "Поиск достижимых целей",
          "viewer.route.finder.target.empty": "Совпадающих достижимых целей не найдено",
          "viewer.route.finder.target.results": "Достижимые цели маршрута",
          "viewer.route.finder.target.noun": "достижимых целей",
          "viewer.route.hop.one": "{count} переход",
          "viewer.route.hop.other": "{count} переходов",
          "viewer.lens.eyebrow": "Семантическая линза",
          "viewer.lens.title": "Сравнить роли системы",
          "viewer.lens.close": "Закрыть семантическую линзу",
          "viewer.lens.instruction": "Выберите до двух семантических типов. Один тип показывает реальные связи; два — сравнивают только прямые заданные связи.",
          "viewer.lens.kinds": "Семантические типы",
          "viewer.lens.choose": "Выберите тип, чтобы просмотреть его узлы и смежные связи.",
          "viewer.lens.copy": "Скопировать ссылку на семантическую линзу",
          "viewer.lens.clear": "Очистить семантическую линзу",
          "viewer.lens.open": "Открыть семантическую линзу",
          "viewer.lens.openActive": "Открыть активную семантическую линзу",
          "viewer.lens.legend": "Семантическая легенда",
          "viewer.lens.legend.inspect.one": "Просмотр {label}, {count} узел",
          "viewer.lens.legend.inspect.other": "Просмотр {label}, {count} узлов",
          "viewer.lens.kind.count.one": "{label}, {count} узел",
          "viewer.lens.kind.count.other": "{label}, {count} узлов",
          "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} прямая связь",
          "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · {count} прямых связей",
          "viewer.lens.single": "{nodes} · {relationships} · связанные узлы остаются видимыми",
          "viewer.lens.node.one": "{count} узел типа {label}",
          "viewer.lens.node.other": "{count} узлов типа {label}",
          "viewer.lens.relationship.one": "{count} смежная связь",
          "viewer.lens.relationship.other": "{count} смежных связей",
          "viewer.radar.title": "Семантический радар",
          "viewer.radar.building": "Построение обзора",
          "viewer.radar.openFull": "Открыть полный семантический радар",
          "viewer.radar.open": "Открыть радар",
          "viewer.radar.close": "Закрыть семантический радар",
          "viewer.radar.surface": "Обзор диаграммы. Щёлкните узел, чтобы выделить его, или используйте стрелки для панорамирования.",
          "viewer.radar.click": "Щёлкнуть узел",
          "viewer.radar.drag": "Перетащите для панорамирования",
          "viewer.radar.space": "Семантическому радару нужно больше места на карте.",
          "viewer.radar.nodes": "Узлы семантического радара диаграммы",
          "viewer.radar.focus": "Фокус: {label} (из семантического радара)",
          "viewer.radar.status": "Узлов: {count} · {viewport}",
          "viewer.radar.fullMap": "Узлов: {count} · полная карта",
          "viewer.radar.compacted": "Радар уменьшен, чтобы не перекрывать семантический паспорт или элементы управления картой.",
          "viewer.radar.cancelWaiting": "Отменить ожидание семантическим радаром дополнительного места",
          "viewer.radar.needsSpace": "Семантическому радару нужно больше видимого места на карте",
          "viewer.radar.viewport.full": "полная карта",
          "viewer.radar.viewport.width": "ширина {percent}%",
          "viewer.radar.viewport.scale": "масштаб {percent}%",
          "viewer.nav.controls": "Управление видом диаграммы",
          "viewer.nav.route": "Построить направленный маршрут",
          "viewer.nav.route.title": "Построить маршрут (R)",
          "viewer.nav.route.short": "ПУТЬ",
          "viewer.nav.radar": "Открыть семантический радар",
          "viewer.nav.radar.title": "Семантический радар (M)",
          "viewer.nav.radar.short": "КАРТА",
          "viewer.nav.lens": "Открыть семантическую линзу",
          "viewer.nav.lens.title": "Семантическая линза (L)",
          "viewer.nav.lens.short": "ЛИНЗА",
          "viewer.nav.find": "Найти узел",
          "viewer.nav.find.title": "Найти узел (/)",
          "viewer.nav.guide": "Открыть гид по диаграмме",
          "viewer.nav.guide.title": "Гид по диаграмме (?)",
          "viewer.nav.zoomOut": "Уменьшить",
          "viewer.nav.zoomOut.title": "Уменьшить (-)",
          "viewer.nav.reset": "Сбросить вид диаграммы",
          "viewer.nav.reset.title": "Сбросить вид (0)",
          "viewer.nav.read": "ЧТЕНИЕ",
          "viewer.nav.zoomIn": "Увеличить",
          "viewer.nav.zoomIn.title": "Увеличить (+)",
          "viewer.nav.camera": "{hint}. Сбросить вид диаграммы",
          "viewer.nav.camera.title": "{semantic}{hint} · сбросить вид (0)",
          "viewer.nav.camera.semantic": "Семантическая камера активна · ",
          "viewer.nav.level.map": "КАРТА",
          "viewer.nav.level.read": "ЧТЕНИЕ",
          "viewer.nav.level.full": "ПОЛНЫЙ",
          "viewer.nav.level.auto": "АВТО",
          "viewer.nav.detail.map": "Увеличьте, чтобы увидеть подписи связей и контекст узлов",
          "viewer.nav.detail.read": "Увеличьте ещё, чтобы увидеть теги и аннотации",
          "viewer.nav.detail.full": "Полная детализация диаграммы",
          "viewer.intent.summary": "{label}. {out} исходящих, {in} входящих{loops}. Всего связей: {total}. Enter — подробности.",
          "viewer.intent.loops": ", {count} петля",
          "viewer.common.copied": "Скопировано",
          "viewer.common.copyFailed": "Не удалось скопировать",
          "viewer.common.copyLink": "Скопировать ссылку",
          "viewer.common.clear": "Очистить",
          "viewer.common.close": "Закрыть"
        }
        
    • agent-run.lifecycle.json 3.3 KB
      {
        "schema_version": 1,
        "diagram_type": "lifecycle",
        "meta": {
          "title": "Agent Run Lifecycle",
          "output": "examples/lifecycle-agent-run.html",
          "viewBox": [1030, 630],
          "animation": "trace",
          "quality_profile": "showcase"
        },
        "lanes": [
          { "id": "main", "label": "Lifecycle phases" },
          { "id": "waiting", "label": "Interruptions" },
          { "id": "exceptions", "label": "Recovery loop" },
          { "id": "terminal", "label": "Terminal exits" }
        ],
        "states": [
          { "id": "queued", "type": "start", "label": "Queued", "sublabel": "request accepted", "lane": "main", "col": 0, "step": "01", "tag": "entry" },
          { "id": "planning", "type": "active", "label": "Planning", "sublabel": "build task graph", "lane": "main", "col": 1, "step": "02", "tag": "model" },
          { "id": "executing", "type": "active", "label": "Executing", "sublabel": "tool calls", "lane": "main", "col": 2, "step": "03", "tag": "work" },
          { "id": "reviewing", "type": "decision", "label": "Reviewing", "sublabel": "quality gate", "lane": "main", "col": 3, "step": "04", "tag": "check" },
          { "id": "completed", "type": "success", "label": "Completed", "sublabel": "final response", "lane": "main", "col": 4, "step": "05", "tag": "done" },
          { "id": "approval", "type": "waiting", "label": "Needs Approval", "sublabel": "human gate", "lane": "waiting", "col": 0, "tag": "pause" },
          { "id": "blocked", "type": "waiting", "label": "Blocked", "sublabel": "missing input", "lane": "waiting", "col": 1, "tag": "wait" },
          { "id": "failed", "type": "failure", "label": "Failed", "sublabel": "recoverable error", "lane": "exceptions", "col": 0, "yOffset": 78, "tag": "retryable" },
          { "id": "cancelled", "type": "failure", "label": "Cancelled", "sublabel": "user stopped", "lane": "terminal", "col": 0, "tag": "terminal" },
          { "id": "expired", "type": "failure", "label": "Expired", "sublabel": "timeout", "lane": "terminal", "col": 1, "tag": "terminal" }
        ],
        "transitions": [
          { "id": "approval-needed", "from": "executing", "to": "approval", "variant": "security", "fromSide": "bottom", "toSide": "top", "route": "straight" },
          { "id": "review-blocked", "from": "reviewing", "to": "blocked", "variant": "default", "route": "drop" },
          { "id": "execution-failed", "from": "executing", "to": "failed", "variant": "security", "fromSide": "left", "toSide": "left", "via": [[320, 157], [320, 385]] },
          { "id": "failed-retry", "from": "failed", "to": "executing", "variant": "emphasis", "fromSide": "left", "toSide": "top", "via": [[20, 385], [20, 80], [402, 80]] },
          { "id": "block-expired", "from": "blocked", "to": "expired", "variant": "security", "fromSide": "bottom", "toSide": "top", "route": "straight" },
          { "id": "approval-cancelled", "from": "approval", "to": "cancelled", "variant": "security", "fromSide": "bottom", "toSide": "top", "via": [[480, 336], [480, 432], [402, 432]] }
        ],
        "cards": [
          {
            "dot": "emerald",
            "title": "Main Path + Waits",
            "items": [
              "The run has five ordered phases from queue to completion",
              "Approval and missing input pause the run without ending it"
            ]
          },
          {
            "dot": "rose",
            "title": "Recovery + Terminal Exits",
            "items": [
              "Failed loops back while retry budget remains",
              "Cancelled and Expired are terminal exits with no return path"
            ]
          }
        ]
      }
      
    • agent-tool-call.workflow.json 4.8 KB
      {
        "schema_version": 2,
        "diagram_type": "workflow",
        "meta": {
          "title": "Agent Tool Call Workflow",
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase",
          "output": "examples/workflow-agent-tool-call-rendered.html"
        },
        "lanes": [
          { "id": "ui", "label": "User Interface" },
          { "id": "agent", "label": "Agent Runtime" },
          { "id": "policy", "label": "Policy & Recovery", "variant": "exception" },
          { "id": "tools", "label": "Tool Execution & Evidence" }
        ],
        "phases": [
          { "id": "intake", "label": "Intake", "fromCol": 0, "toCol": 1 },
          { "id": "reasoning", "label": "Plan + route", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
          { "id": "execution", "label": "Execute + report", "fromCol": 4, "toCol": 5, "variant": "dashed" }
        ],
        "groups": [
          { "id": "agent_loop", "label": "Planning loop", "lane": "agent", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
          { "id": "exception_path", "label": "Human or policy stop", "lane": "policy", "fromCol": 3, "toCol": 5, "variant": "security" },
          { "id": "evidence_path", "label": "Evidence path", "lane": "tools", "fromCol": 1, "toCol": 2, "variant": "dashed" },
          { "id": "tool_work", "label": "Tool work", "lane": "tools", "fromCol": 4, "toCol": 5, "variant": "dashed" }
        ],
        "mainPath": ["user", "chat", "planner", "router", "approval", "tool", "external", "final"],
        "nodes": [
          { "id": "user", "lane": "ui", "col": 0, "type": "external", "label": "User", "sublabel": "asks for work", "width": 132 },
          { "id": "chat", "lane": "ui", "col": 1, "type": "frontend", "label": "Chat Surface", "sublabel": "thread + files", "width": 132 },
          { "id": "final", "lane": "ui", "col": 5, "type": "backend", "label": "Final Reply", "sublabel": "answer + changes", "width": 132 },
          { "id": "planner", "lane": "agent", "col": 2, "type": "backend", "label": "Agent Planner", "sublabel": "plan next step", "tag": "context aware", "width": 132 },
          { "id": "router", "lane": "agent", "col": 3, "type": "backend", "label": "Tool Router", "sublabel": "choose capability", "width": 132 },
          { "id": "approval", "lane": "policy", "col": 3, "type": "security", "label": "Approval Gate", "sublabel": "scope + consent", "tag": "block risky ops", "width": 132 },
          { "id": "blocked", "lane": "policy", "col": 4, "type": "security", "label": "Blocked", "sublabel": "wait or reject", "width": 132 },
          { "id": "retry", "lane": "policy", "col": 5, "type": "messagebus", "label": "Retry Path", "sublabel": "revise request", "width": 132 },
          { "id": "tool", "lane": "tools", "col": 4, "type": "messagebus", "label": "Tool Call", "sublabel": "shell / browser / MCP", "tag": "structured result", "width": 132 },
          { "id": "external", "lane": "tools", "col": 5, "type": "cloud", "label": "External API", "sublabel": "network service", "width": 132 },
          { "id": "store", "lane": "tools", "col": 1, "type": "database", "label": "Context Store", "sublabel": "repo + memory", "width": 132 },
          { "id": "trace", "lane": "tools", "col": 2, "type": "database", "label": "Trace Log", "sublabel": "events + output", "width": 132 }
        ],
        "edges": [
          { "id": "request-chat", "from": "user", "to": "chat", "variant": "default" },
          { "id": "plan-request", "from": "chat", "to": "planner", "label": "plan", "variant": "emphasis" },
          { "id": "planner-route", "from": "planner", "to": "router", "variant": "default" },
          { "id": "approval-check", "from": "router", "to": "approval", "label": "needs approval?", "variant": "security" },
          { "id": "approved-tool", "from": "approval", "to": "tool", "variant": "emphasis" },
          { "id": "approval-denied", "from": "approval", "to": "blocked", "label": "denied", "variant": "security", "role": "error" },
          { "id": "retry-request", "from": "blocked", "to": "retry", "variant": "dashed", "role": "branch" },
          { "id": "tool-external-call", "from": "tool", "to": "external", "variant": "default" },
          { "id": "external-reply", "from": "external", "to": "final", "variant": "emphasis", "role": "return", "fromSide": "right", "toSide": "right", "route": "outside-right", "width": 1.2 },
          { "id": "record-result", "from": "external", "to": "trace", "label": "record result", "variant": "dashed", "fromSide": "bottom", "toSide": "bottom", "route": "bottom-channel", "labelSegment": 1 },
          { "id": "write-trace-memory", "from": "store", "to": "trace", "label": "trace + memory", "variant": "dashed" }
        ],
        "cards": [
          {
            "dot": "cyan",
            "title": "Compiler Contract",
            "items": [
              "Lanes and columns determine node placement",
              "Labels reserve clearance; routes stay orthogonal"
            ]
          },
          {
            "dot": "rose",
            "title": "Runtime Semantics",
            "items": [
              "Approval gates risky work before tool execution",
              "Evidence returns through isolated trace and memory"
            ]
          }
        ]
      }
      
    • async-job-roundtrip.sequence.json 3.7 KB
      {
        "schema_version": 1,
        "diagram_type": "sequence",
        "meta": {
          "title": "Async Job Roundtrip",
          "output": "examples/async-job-roundtrip.html",
          "viewBox": [820, 920],
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase"
        },
        "participants": [
          { "id": "client", "type": "external", "label": "Client", "sublabel": "mobile app" },
          { "id": "api", "type": "backend", "label": "Jobs API", "sublabel": "request edge" },
          { "id": "queue", "type": "messagebus", "label": "Queue", "sublabel": "durable work" },
          { "id": "worker", "type": "backend", "label": "Worker", "sublabel": "background" },
          { "id": "provider", "type": "cloud", "label": "Provider", "sublabel": "external API" },
          { "id": "store", "type": "database", "label": "Job Store", "sublabel": "source of truth" },
          { "id": "notify", "type": "messagebus", "label": "Notifier", "sublabel": "webhook" }
        ],
        "segments": [
          { "from": 150, "to": 288, "label": "Accept" },
          { "from": 306, "to": 538, "label": "Background work" },
          { "from": 554, "to": 800, "label": "Notify + reconcile" }
        ],
        "messages": [
          { "from": "client", "to": "api", "y": 180, "label": "POST /jobs", "variant": "emphasis" },
          { "from": "api", "to": "queue", "y": 222, "label": "enqueue job", "variant": "emphasis" },
          { "from": "api", "to": "client", "y": 264, "label": "202 + job id", "variant": "return" },
          { "from": "queue", "to": "worker", "y": 326, "label": "deliver", "variant": "emphasis" },
          { "from": "worker", "to": "provider", "y": 368, "label": "perform work", "variant": "default" },
          { "from": "provider", "to": "worker", "y": 410, "label": "result / timeout", "variant": "return" },
          { "from": "worker", "to": "queue", "y": 452, "label": "retry if timeout", "variant": "dashed" },
          { "from": "worker", "to": "store", "y": 494, "label": "persist final state", "variant": "emphasis" },
          { "from": "worker", "to": "notify", "y": 566, "label": "job.completed", "variant": "dashed" },
          { "from": "notify", "to": "client", "y": 608, "label": "signed webhook", "variant": "dashed" },
          { "from": "client", "to": "api", "y": 650, "label": "GET /jobs/:id", "variant": "default" },
          { "from": "api", "to": "store", "y": 692, "label": "read status", "variant": "default" },
          { "from": "store", "to": "api", "y": 734, "label": "completed", "variant": "return" },
          { "from": "api", "to": "client", "y": 776, "label": "200 final result", "variant": "return" }
        ],
        "activations": [
          { "participant": "api", "from": 174, "to": 272, "type": "backend" },
          { "participant": "queue", "from": 216, "to": 334, "type": "messagebus" },
          { "participant": "worker", "from": 320, "to": 574, "type": "backend" },
          { "participant": "provider", "from": 362, "to": 416, "type": "cloud" },
          { "participant": "store", "from": 488, "to": 742, "type": "database" },
          { "participant": "notify", "from": 560, "to": 616, "type": "messagebus" },
          { "participant": "api", "from": 644, "to": 784, "type": "backend" }
        ],
        "cards": [
          { "dot": "cyan", "title": "Fast Acknowledgement", "items": ["The caller receives a durable job id before work begins", "Queue ownership is visible in the acceptance contract", "The original connection does not wait for provider latency"] },
          { "dot": "orange", "title": "Bounded Recovery", "items": ["Timeouts re-enter the queue with a retry policy", "Final state is persisted before notification", "The job store remains the source of truth"] },
          { "dot": "emerald", "title": "Two Observation Paths", "items": ["A signed webhook announces completion", "Status polling is a fallback, not a second workflow", "Both paths converge on the same final state"] }
        ]
      }
      
    • brand-aware-delivery.architecture.json 2.7 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Brand-aware AI delivery",
          "output": "brand-aware-delivery.html",
          "quality_profile": "showcase",
          "viewBox": [1120, 640]
        },
        "components": [
          { "id": "request", "type": "external", "label": "Product request", "sublabel": "Owner brief", "pos": [38, 260], "size": [138, 68] },
          { "id": "claude", "type": "frontend", "label": "Claude", "sublabel": "Plan and author", "brand": "claude", "pos": [220, 260], "size": [138, 68] },
          { "id": "github", "type": "messagebus", "label": "GitHub", "sublabel": "Review and merge", "brand": "github", "pos": [402, 260], "size": [138, 68] },
          { "id": "container", "type": "backend", "label": "Docker service", "sublabel": "Build and run", "brand": "docker", "pos": [584, 260], "size": [138, 68] },
          { "id": "edge", "type": "cloud", "label": "Cloudflare", "sublabel": "Global delivery", "brand": "cloudflare", "pos": [766, 260], "size": [138, 68] },
          { "id": "customer", "type": "external", "label": "Customers", "sublabel": "Web and mobile", "pos": [948, 260], "size": [138, 68] },
          { "id": "database", "type": "database", "label": "PostgreSQL", "sublabel": "Durable state", "brand": "postgresql", "pos": [584, 420], "size": [138, 68] },
          { "id": "billing", "type": "external", "label": "Stripe", "sublabel": "Billing events", "brand": "stripe", "pos": [766, 420], "size": [138, 68] }
        ],
        "connections": [
          { "id": "brief-to-claude", "from": "request", "to": "claude", "label": "brief", "variant": "emphasis" },
          { "id": "claude-to-github", "from": "claude", "to": "github", "label": "change set", "labelDy": -28 },
          { "id": "github-to-container", "from": "github", "to": "container", "label": "approved build", "labelDy": -28 },
          { "id": "container-to-edge", "from": "container", "to": "edge", "label": "deploy" },
          { "id": "edge-to-customer", "from": "edge", "to": "customer", "label": "HTTPS", "variant": "emphasis" },
          { "id": "container-to-database", "from": "container", "to": "database", "label": "SQL", "fromSide": "bottom", "toSide": "top", "labelAt": [625, 370] },
          { "id": "container-to-billing", "from": "container", "to": "billing", "label": "create charge", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "via": [[653, 374], [835, 374]] },
          { "id": "billing-to-database", "from": "billing", "to": "database", "label": "webhook", "variant": "dashed" }
        ],
        "cards": [
          { "dot": "cyan", "title": "Identity at a glance", "items": ["Semantic color still explains technical role", "Brand badges identify the actual products"] },
          { "dot": "amber", "title": "Portable by default", "items": ["Preset marks ship inside Archify", "Every visual export keeps the same badge"] }
        ]
      }
      
    • cache-miss-request.sequence.json 3.7 KB
      {
        "schema_version": 1,
        "diagram_type": "sequence",
        "meta": {
          "title": "Cache Miss Request Sequence",
          "output": "examples/sequence-cache-miss-request.html",
          "viewBox": [1080, 580],
          "column_fit": "spread",
          "animation": "trace",
          "quality_profile": "showcase"
        },
        "participants": [
          { "id": "user", "type": "external", "label": "User", "sublabel": "browser session" },
          { "id": "web", "type": "frontend", "label": "Web App", "sublabel": "React UI" },
          { "id": "api", "type": "backend", "label": "API", "sublabel": "request handler" },
          { "id": "auth", "type": "security", "label": "Auth", "sublabel": "JWT verify" },
          { "id": "redis", "type": "database", "label": "Redis", "sublabel": "cache" },
          { "id": "db", "type": "database", "label": "Postgres", "sublabel": "source of truth" },
          { "id": "trace", "type": "messagebus", "label": "Trace", "sublabel": "async event" }
        ],
        "segments": [
          { "from": 150, "to": 250, "label": "Request" },
          { "from": 260, "to": 370, "label": "Fallback" },
          { "from": 380, "to": 480, "label": "Response + trace" }
        ],
        "messages": [
          { "id": "open-page", "from": "user", "to": "web", "y": 160, "label": "open page", "variant": "default" },
          { "id": "dashboard-request", "from": "web", "to": "api", "y": 185, "label": "GET /dashboard", "variant": "emphasis" },
          { "id": "verify-jwt", "from": "api", "to": "auth", "y": 210, "label": "verify JWT", "variant": "security" },
          { "id": "auth-claims", "from": "auth", "to": "api", "y": 238, "label": "claims ok", "variant": "return" },
          { "id": "cache-read", "from": "api", "to": "redis", "y": 270, "label": "read cache", "variant": "default" },
          { "id": "cache-miss", "from": "redis", "to": "api", "y": 298, "label": "miss", "variant": "return" },
          { "id": "profile-query", "from": "api", "to": "db", "y": 330, "label": "query profile + metrics", "variant": "emphasis" },
          { "id": "profile-rows", "from": "db", "to": "api", "y": 358, "label": "rows", "variant": "return" },
          { "id": "cache-write", "from": "api", "to": "redis", "y": 390, "label": "set cache", "variant": "dashed" },
          { "id": "trace-emit", "from": "api", "to": "trace", "y": 418, "label": "emit trace", "variant": "dashed" },
          { "id": "dashboard-response", "from": "api", "to": "web", "y": 443, "label": "200 JSON", "variant": "return" },
          { "id": "page-render", "from": "web", "to": "user", "y": 468, "label": "render", "variant": "return" }
        ],
        "activations": [
          { "participant": "web", "from": 180, "to": 474, "type": "frontend" },
          { "participant": "api", "from": 185, "to": 450, "type": "backend" },
          { "participant": "auth", "from": 205, "to": 244, "type": "security" },
          { "participant": "redis", "from": 265, "to": 304, "type": "database" },
          { "participant": "db", "from": 325, "to": 364, "type": "database" },
          { "participant": "trace", "from": 413, "to": 449, "type": "messagebus" }
        ],
        "cards": [
          {
            "dot": "emerald",
            "title": "Happy Path",
            "items": [
              "The main request is Web App -> API -> data source -> response",
              "Return messages are quieter than forward calls",
              "Activation bars make ownership duration visible"
            ]
          },
          {
            "dot": "rose",
            "title": "Policy + Fallback",
            "items": [
              "JWT verification is colored as a security interaction",
              "Cache miss is visible without overpowering the main path",
              "Database access only appears after cache fallback"
            ]
          },
          {
            "dot": "orange",
            "title": "Async Trace",
            "items": [
              "Trace emission is dashed and secondary",
              "It does not block the response path",
              "The diagram separates user-facing latency from observability"
            ]
          }
        ]
      }
      
    • checkout-platform.base.architecture.json 2.2 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Checkout Platform — Baseline",
          "output": "checkout-platform.base.html",
          "visual_preset": "signal-flow"
        },
        "components": [
          { "id": "buyers", "type": "external", "label": "Buyers", "sublabel": "Web + mobile", "pos": [40, 250], "size": [120, 60] },
          { "id": "edge", "type": "cloud", "label": "Edge Gateway", "sublabel": "TLS + routing", "pos": [220, 250], "size": [130, 60] },
          { "id": "checkout", "type": "backend", "label": "Checkout API", "sublabel": "v1 service", "pos": [430, 250], "size": [130, 60] },
          { "id": "cache", "type": "database", "label": "Session Cache", "sublabel": "Redis", "pos": [430, 100], "size": [130, 60] },
          { "id": "orders", "type": "database", "label": "Orders", "sublabel": "PostgreSQL", "pos": [640, 250], "size": [130, 60] },
          { "id": "queue", "type": "messagebus", "label": "Order Events", "sublabel": "durable queue", "pos": [430, 400], "size": [130, 60] },
          { "id": "worker", "type": "backend", "label": "Fulfilment", "sublabel": "async worker", "pos": [640, 400], "size": [130, 60] },
          { "id": "payments", "type": "external", "label": "Payment Rail", "sublabel": "external", "pos": [850, 250], "size": [130, 60] }
        ],
        "boundaries": [
          { "kind": "region", "label": "Production region", "wraps": ["edge", "checkout", "cache", "orders", "queue", "worker"] },
          { "kind": "security-group", "label": "Checkout trust zone", "wraps": ["checkout", "orders"] }
        ],
        "connections": [
          { "id": "buyer-request", "from": "buyers", "to": "edge", "label": "HTTPS", "variant": "emphasis" },
          { "id": "edge-checkout", "from": "edge", "to": "checkout" },
          { "id": "session-read", "from": "checkout", "to": "cache", "label": "session", "fromSide": "top", "toSide": "bottom", "labelDy": -66 },
          { "id": "persist-order", "from": "checkout", "to": "orders", "label": "SQL" },
          { "id": "publish-order", "from": "checkout", "to": "queue", "label": "accepted", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 66 },
          { "id": "consume-order", "from": "queue", "to": "worker" },
          { "id": "authorize-payment", "from": "orders", "to": "payments", "label": "authorize", "variant": "security" }
        ]
      }
      
    • checkout-platform.head.architecture.json 2.4 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Checkout Platform — Fraud Gate",
          "output": "checkout-platform.head.html",
          "visual_preset": "signal-flow"
        },
        "components": [
          { "id": "buyers", "type": "external", "label": "Buyers", "sublabel": "Web + mobile", "pos": [40, 250], "size": [120, 60] },
          { "id": "edge", "type": "cloud", "label": "Edge Gateway", "sublabel": "TLS + routing", "pos": [220, 250], "size": [130, 60] },
          { "id": "checkout", "type": "backend", "label": "Checkout API", "sublabel": "v2 idempotent", "pos": [430, 250], "size": [130, 60] },
          { "id": "fraud", "type": "security", "label": "Fraud Gate", "sublabel": "policy scoring", "pos": [640, 100], "size": [130, 60], "tag": "new owner" },
          { "id": "orders", "type": "database", "label": "Orders", "sublabel": "PostgreSQL", "pos": [640, 250], "size": [130, 60] },
          { "id": "queue", "type": "messagebus", "label": "Order Events", "sublabel": "durable queue", "pos": [430, 420], "size": [130, 60] },
          { "id": "worker", "type": "backend", "label": "Fulfilment", "sublabel": "async worker", "pos": [640, 400], "size": [130, 60] },
          { "id": "payments", "type": "external", "label": "Payment Rail", "sublabel": "external", "pos": [850, 250], "size": [130, 60] }
        ],
        "boundaries": [
          { "kind": "region", "label": "Production region", "wraps": ["edge", "checkout", "fraud", "orders", "queue", "worker"] },
          { "kind": "security-group", "label": "Checkout trust zone", "wraps": ["checkout", "fraud", "orders"] }
        ],
        "connections": [
          { "id": "buyer-request", "from": "buyers", "to": "edge", "label": "HTTPS", "variant": "emphasis" },
          { "id": "edge-checkout", "from": "edge", "to": "checkout" },
          { "id": "fraud-check", "from": "checkout", "to": "fraud", "label": "screen", "variant": "security", "fromSide": "top", "toSide": "bottom", "labelDy": -66 },
          { "id": "persist-order", "from": "checkout", "to": "orders", "label": "SQL tx" },
          { "id": "publish-order", "from": "checkout", "to": "queue", "label": "accepted", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 76 },
          { "id": "consume-order", "from": "queue", "to": "worker" },
          { "id": "authorize-payment", "from": "fraud", "to": "payments", "label": "authorize", "variant": "security", "fromSide": "right", "toSide": "top", "via": [[820, 130], [915, 130]] }
        ]
      }
      
    • dataflow-product-analytics.html 746.7 KB · in bundle
    • deployment-release.lifecycle.json 3.4 KB
      {
        "schema_version": 2,
        "diagram_type": "lifecycle",
        "meta": {
          "title": "Deployment Release Lifecycle",
          "output": "examples/deployment-release.html",
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase"
        },
        "lanes": [
          { "id": "main", "label": "Release phases" },
          { "id": "waiting", "label": "Approval + health wait" },
          { "id": "recovery", "label": "Rollback controller" },
          { "id": "terminal", "label": "Terminal exits" }
        ],
        "states": [
          { "id": "queued", "type": "start", "label": "Queued", "sublabel": "change accepted", "lane": "main", "col": 0, "step": "01", "tag": "pending" },
          { "id": "building", "type": "active", "label": "Building", "sublabel": "immutable image", "lane": "main", "col": 1, "step": "02", "tag": "running" },
          { "id": "verifying", "type": "decision", "label": "Verifying", "sublabel": "tests + policy", "lane": "main", "col": 2, "step": "03", "tag": "gate" },
          { "id": "ready", "type": "waiting", "label": "Ready", "sublabel": "promotion pending", "lane": "main", "col": 3, "step": "04", "tag": "approved" },
          { "id": "live", "type": "success", "label": "Live", "sublabel": "production healthy", "lane": "main", "col": 4, "step": "05", "tag": "success" },
          { "id": "approval", "type": "waiting", "label": "Needs Approval", "sublabel": "release owner", "lane": "waiting", "col": 2, "tag": "pause" },
          { "id": "rollback", "type": "active", "label": "Rolling Back", "sublabel": "last good image", "lane": "recovery", "col": 3, "tag": "automatic" },
          { "id": "paused", "type": "waiting", "label": "Health Paused", "sublabel": "SLO regression", "lane": "waiting", "col": 4, "tag": "observe" },
          { "id": "cancelled", "type": "failure", "label": "Cancelled", "sublabel": "approval denied", "lane": "terminal", "col": 2, "tag": "terminal" },
          { "id": "failed", "type": "failure", "label": "Failed", "sublabel": "rollback failed", "lane": "terminal", "col": 3, "tag": "terminal" },
          { "id": "rolled_back", "type": "success", "label": "Rolled Back", "sublabel": "service restored", "lane": "terminal", "col": 4, "tag": "terminal" }
        ],
        "transitions": [
          { "from": "queued", "to": "building" },
          { "from": "building", "to": "verifying" },
          { "from": "verifying", "to": "ready" },
          { "from": "ready", "to": "live" },
          { "from": "verifying", "to": "approval", "variant": "security", "label": "needs sign-off" },
          { "from": "approval", "to": "ready", "label": "approved" },
          { "from": "approval", "to": "cancelled", "variant": "security" },
          { "from": "ready", "to": "rollback", "variant": "security" },
          { "from": "rollback", "to": "failed", "variant": "security" },
          { "from": "live", "to": "paused", "variant": "dashed" },
          { "from": "paused", "to": "rolled_back", "variant": "emphasis" }
        ],
        "cards": [
          { "dot": "cyan", "title": "Promotion Rail", "items": ["The release object moves through five ordered phases", "Verification and approval remain distinct states", "Live means production health is currently proven"] },
          { "dot": "amber", "title": "Wait States", "items": ["Human approval can pause without consuming a worker", "A health regression pauses further rollout", "Every wait exposes the event required to continue"] },
          { "dot": "rose", "title": "Explicit Endings", "items": ["Denied approval ends as Cancelled", "Rollback controller failure ends as Failed", "Successful rollback is a terminal restored outcome"] }
        ]
      }
      
    • event-stream.dataflow.json 4.7 KB
      {
        "schema_version": 1,
        "diagram_type": "dataflow",
        "meta": {
          "title": "Order Event-stream Topology",
          "output": "examples/event-stream.html",
          "viewBox": [1080, 780],
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase"
        },
        "stages": [
          { "label": "Producers" },
          { "label": "Transit" },
          { "label": "Processors" },
          { "label": "State + recovery" },
          { "label": "Consumers" }
        ],
        "nodes": [
          { "id": "checkout", "type": "frontend", "label": "Checkout API", "sublabel": "order producer", "stage": 0, "row": 0, "tag": "team commerce" },
          { "id": "billing", "type": "backend", "label": "Billing API", "sublabel": "payment producer", "stage": 0, "row": 2, "tag": "team money" },
          { "id": "orders", "type": "messagebus", "label": "orders.v1", "sublabel": "12 partitions", "stage": 1, "row": 0, "tag": "key: order_id" },
          { "id": "payments", "type": "messagebus", "label": "payments.v2", "sublabel": "8 partitions", "stage": 1, "row": 2, "tag": "key: order_id" },
          { "id": "validate", "type": "backend", "label": "Order Validate", "sublabel": "group fulfillment", "stage": 2, "row": 0, "tag": "ordered" },
          { "id": "enrich", "type": "backend", "label": "Payment Enrich", "sublabel": "group analytics", "stage": 2, "row": 2, "tag": "at-least-once" },
          { "id": "state", "type": "database", "label": "Order State", "sublabel": "materialized view", "stage": 3, "row": 1, "tag": "idempotent" },
          { "id": "dlq", "type": "messagebus", "label": "events.dlq", "sublabel": "poison events", "stage": 3, "row": 4, "tag": "7-day retention" },
          { "id": "fulfillment", "type": "backend", "label": "Fulfillment", "sublabel": "shipping workflow", "stage": 4, "row": 0, "tag": "consumer" },
          { "id": "analytics", "type": "database", "label": "Analytics", "sublabel": "streaming facts", "stage": 4, "row": 2, "tag": "consumer" },
          { "id": "replay", "type": "security", "label": "Replay Tool", "sublabel": "approved batch", "stage": 4, "row": 4, "tag": "operator gate" },
          { "id": "ops", "type": "external", "label": "On-call", "sublabel": "DLQ owner", "stage": 4, "row": 3, "yOffset": -18, "tag": "SRE" }
        ],
        "flows": [
          { "from": "checkout", "to": "orders", "label": "OrderPlaced", "classification": "schema v1", "variant": "emphasis", "route": "straight" },
          { "from": "billing", "to": "payments", "label": "PaymentCaptured", "classification": "schema v2", "variant": "emphasis", "route": "straight" },
          { "from": "orders", "to": "validate", "label": "ordered orders", "classification": "consumer group", "variant": "emphasis", "route": "straight" },
          { "from": "payments", "to": "enrich", "label": "payment facts", "classification": "at-least-once", "variant": "emphasis", "route": "straight" },
          { "from": "validate", "to": "state", "label": "valid order", "classification": "idempotent", "variant": "emphasis", "route": "vertical-channel" },
          { "from": "enrich", "to": "state", "label": "enriched payment", "classification": "idempotent", "variant": "default", "route": "vertical-channel" },
          { "from": "state", "to": "fulfillment", "label": "ready orders", "classification": "read model", "variant": "emphasis", "route": "vertical-channel" },
          { "from": "state", "to": "analytics", "label": "order facts", "classification": "non-PII", "variant": "default", "route": "vertical-channel" },
          { "from": "validate", "to": "dlq", "label": "invalid event", "classification": "dead letter", "variant": "security", "fromSide": "top", "toSide": "top", "via": [[530, 80], [20, 80], [20, 550], [745, 550]], "labelAt": [300, 550] },
          { "from": "enrich", "to": "dlq", "label": "poison event", "classification": "dead letter", "variant": "security", "route": "bottom-channel", "labelDy": 30 },
          { "from": "dlq", "to": "ops", "label": "failure sample", "classification": "restricted", "variant": "security", "route": "vertical-channel" },
          { "from": "dlq", "to": "replay", "label": "approved replay", "classification": "audited batch", "variant": "dashed", "route": "straight", "labelDy": 30 }
        ],
        "cards": [
          { "dot": "amber", "title": "Transit Contract", "items": ["Every event and topic is named", "Partition keys preserve per-order ordering", "Consumer groups expose processing ownership"] },
          { "dot": "emerald", "title": "State + Delivery", "items": ["Processors write an idempotent materialized view", "Fulfillment and analytics consume distinct assets", "At-least-once delivery never implies duplicate business effects"] },
          { "dot": "rose", "title": "Failure Ownership", "items": ["Poison events land in a retained dead-letter topic", "On-call inspects samples before replay", "Replay is gated, batched, and auditable"] }
        ]
      }
      
    • holiday-planning.workflow.json 2.9 KB
      {
        "schema_version": 2,
        "diagram_type": "workflow",
        "meta": {
          "title": "2026年剩余假期安排",
          "locale": "zh-CN",
          "quality_profile": "showcase",
          "legend": {
            "entries": {
              "backend": {
                "label": "假期"
              },
              "security": {
                "label": "补班"
              },
              "external": {
                "label": "时间节点"
              }
            }
          },
          "output": "holiday-planning.html"
        },
        "lanes": [
          {
            "id": "calendar",
            "label": "时间线"
          },
          {
            "id": "makeup",
            "label": "调休"
          }
        ],
        "mainPath": [
          "today",
          "mid_autumn",
          "national_day",
          "year_end"
        ],
        "nodes": [
          {
            "id": "today",
            "lane": "calendar",
            "col": 0,
            "type": "external",
            "label": "今天 9月22日",
            "sublabel": "周二 · 距中秋3天",
            "icon": "clock"
          },
          {
            "id": "mid_autumn",
            "lane": "calendar",
            "col": 1,
            "type": "backend",
            "label": "中秋节",
            "sublabel": "9月25日–27日 · 3天",
            "tag": "无需调休",
            "icon": "moon"
          },
          {
            "id": "national_day",
            "lane": "calendar",
            "col": 3,
            "type": "backend",
            "label": "国庆节",
            "sublabel": "10月1日–7日 · 7天",
            "tag": "连休",
            "icon": "calendar"
          },
          {
            "id": "year_end",
            "lane": "calendar",
            "col": 5,
            "type": "external",
            "label": "此后至年底",
            "sublabel": "无法定节假日",
            "icon": "flag"
          },
          {
            "id": "makeup_work",
            "lane": "makeup",
            "col": 3,
            "type": "security",
            "label": "调休上班",
            "sublabel": "10月10日(周六)",
            "tag": "补班",
            "icon": "briefcase"
          }
        ],
        "edges": [
          {
            "id": "to_mid_autumn",
            "from": "today",
            "to": "mid_autumn",
            "label": "3天后连休"
          },
          {
            "id": "mid_to_national",
            "from": "mid_autumn",
            "to": "national_day",
            "label": "节后上班3天"
          },
          {
            "id": "to_year_end",
            "from": "national_day",
            "to": "year_end",
            "label": "假期结束"
          },
          {
            "id": "makeup_branch",
            "from": "national_day",
            "to": "makeup_work",
            "label": "国庆调休",
            "role": "branch",
            "variant": "security"
          }
        ],
        "cards": [
          {
            "dot": "emerald",
            "title": "中秋节",
            "items": [
              "9月25日(周五)至27日(周日)放假,共3天",
              "与周末自然相连,无需额外调休上班"
            ]
          },
          {
            "dot": "amber",
            "title": "国庆节",
            "items": [
              "10月1日(周四)至7日(周三)放假调休,共7天",
              "9月20日(周日)上班日已过",
              "10月10日(周六)需补班"
            ]
          },
          {
            "dot": "slate",
            "title": "年底前",
            "items": [
              "国庆假期结束后,到2026年底不再有法定节假日安排"
            ]
          }
        ]
      }
      
    • incident-response.workflow.json 4.6 KB
      {
        "schema_version": 1,
        "diagram_type": "workflow",
        "meta": {
          "title": "Incident Response Runbook",
          "output": "examples/incident-response.html",
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase"
        },
        "lanes": [
          { "id": "signals", "label": "Signals" },
          { "id": "responders", "label": "Incident Command" },
          { "id": "mitigation", "label": "Service Mitigation" },
          { "id": "recovery", "label": "Recovery Evidence" },
          { "id": "communication", "label": "Stakeholder Communication" },
          { "id": "exceptions", "label": "Escalation + Rollback", "variant": "exception" }
        ],
        "phases": [
          { "id": "detect", "label": "Detect", "fromCol": 0, "toCol": 1 },
          { "id": "respond", "label": "Triage + mitigate", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
          { "id": "recover", "label": "Verify + close", "fromCol": 4, "toCol": 5, "variant": "dashed" }
        ],
        "groups": [
          { "id": "command", "label": "Incident command", "lane": "responders", "fromCol": 1, "toCol": 3, "variant": "emphasis" },
          { "id": "exception_actions", "label": "If impact persists", "lane": "exceptions", "fromCol": 3, "toCol": 5, "variant": "security" }
        ],
        "mainPath": ["alert", "page", "triage", "contain", "recover", "verify", "close"],
        "nodes": [
          { "id": "alert", "lane": "signals", "col": 0, "type": "messagebus", "label": "SLO Alert", "sublabel": "burn rate" },
          { "id": "page", "lane": "responders", "col": 1, "width": 76, "type": "external", "label": "Page On-call", "sublabel": "acknowledge" },
          { "id": "triage", "lane": "responders", "col": 2, "width": 64, "type": "backend", "label": "Triage", "sublabel": "scope impact" },
          { "id": "declare", "lane": "responders", "col": 3, "type": "security", "label": "Declare", "sublabel": "assign commander", "tag": "SEV-1/2" },
          { "id": "contain", "lane": "mitigation", "col": 3, "width": 72, "type": "backend", "label": "Contain", "sublabel": "stop growth" },
          { "id": "recover", "lane": "mitigation", "col": 4, "width": 52, "type": "cloud", "label": "Recover", "sublabel": "restore" },
          { "id": "verify", "lane": "recovery", "col": 5, "type": "database", "label": "Verify", "sublabel": "SLO + traces", "tag": "15 min stable" },
          { "id": "close", "lane": "communication", "col": 5, "type": "external", "label": "Resolve", "sublabel": "final update" },
          { "id": "update", "lane": "communication", "col": 3, "type": "frontend", "label": "Status Update", "sublabel": "impact + ETA" },
          { "id": "escalate", "lane": "exceptions", "col": 3, "width": 72, "type": "security", "label": "Escalate", "sublabel": "specialist" },
          { "id": "rollback", "lane": "exceptions", "col": 5, "type": "messagebus", "label": "Rollback", "sublabel": "last good" }
        ],
        "edges": [
          { "from": "alert", "to": "page", "label": "page", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "page", "to": "triage", "route": "bottom-channel", "fromSide": "bottom", "toSide": "bottom" },
          { "from": "triage", "to": "contain", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "contain", "to": "recover", "route": "bottom-channel", "fromSide": "bottom", "toSide": "bottom" },
          { "from": "recover", "to": "verify", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "verify", "to": "close", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "triage", "to": "declare", "variant": "security" },
          { "from": "declare", "to": "update", "variant": "dashed", "fromSide": "top", "toSide": "left", "via": [[430, 16], [20, 16], [20, 615]] },
          { "from": "update", "to": "escalate", "variant": "security", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "verify", "to": "rollback", "variant": "security", "role": "error", "route": "outside-right", "fromSide": "right", "toSide": "right" }
        ],
        "cards": [
          { "dot": "rose", "title": "Ownership First", "items": ["A page is not an incident until someone owns command", "Severity and scope are explicit before mitigation spreads", "Escalation names the missing expertise"] },
          { "dot": "emerald", "title": "Recovery Is Evidence", "items": ["Mitigation can reduce impact without proving recovery", "SLOs and traces must stay healthy for a fixed window", "The final update follows verification, not optimism"] },
          { "dot": "cyan", "title": "Communication Contract", "items": ["Stakeholders receive impact, action, and next update time", "Rollback remains visible as a deliberate response", "Every branch has an owner and observable exit"] }
        ]
      }
      
    • lifecycle-agent-run.html 741.1 KB · in bundle
    • product-analytics.dataflow.json 4.9 KB
      {
        "schema_version": 1,
        "diagram_type": "dataflow",
        "meta": {
          "title": "Product Analytics Data Flow",
          "output": "examples/dataflow-product-analytics.html",
          "viewBox": [1080, 520],
          "animation": "trace",
          "quality_profile": "showcase"
        },
        "stages": [
          { "label": "Sources" },
          { "label": "Ingest" },
          { "label": "Process" },
          { "label": "Store" },
          { "label": "Consume" }
        ],
        "nodes": [
          { "id": "web", "type": "frontend", "label": "Web App", "sublabel": "browser SDK", "stage": 0, "row": 0, "tag": "events" },
          { "id": "mobile", "type": "frontend", "label": "Mobile", "sublabel": "iOS / Android", "stage": 0, "row": 2, "tag": "events" },
          { "id": "edge", "type": "cloud", "label": "Edge API", "sublabel": "collector", "stage": 1, "row": 1, "tag": "TLS" },
          { "id": "consent", "type": "security", "label": "Consent Gate", "sublabel": "policy filter", "stage": 2, "row": 0, "tag": "PII guard" },
          { "id": "stream", "type": "messagebus", "label": "Event Stream", "sublabel": "Kafka topic", "stage": 2, "row": 2, "tag": "ordered" },
          { "id": "pii", "type": "security", "label": "PII Vault", "sublabel": "encrypted", "stage": 3, "row": 0, "tag": "restricted" },
          { "id": "warehouse", "type": "database", "label": "Warehouse", "sublabel": "analytics tables", "stage": 3, "row": 1, "tag": "curated" },
          { "id": "features", "type": "database", "label": "Feature Store", "sublabel": "daily batch", "stage": 3, "row": 2, "tag": "derived" },
          { "id": "dashboard", "type": "backend", "label": "Dashboards", "sublabel": "product metrics", "stage": 4, "row": 0, "tag": "SQL" },
          { "id": "model", "type": "backend", "label": "ML Model", "sublabel": "ranking job", "stage": 4, "row": 2, "tag": "features" }
        ],
        "flows": [
          { "id": "web-clickstream", "from": "web", "to": "edge", "label": "clickstream", "classification": "user events", "variant": "emphasis", "fromSide": "right", "toSide": "left", "via": [[205, 157], [205, 271]], "labelAt": [204, 190] },
          { "id": "mobile-events", "from": "mobile", "to": "edge", "label": "app events", "classification": "device events", "variant": "default", "fromSide": "right", "toSide": "left", "via": [[222, 385], [222, 271]], "labelAt": [220, 342] },
          { "id": "consent-enrichment", "from": "edge", "to": "consent", "label": "identity + consent", "classification": "PII touch", "variant": "security", "fromSide": "top", "toSide": "left", "via": [[315, 112], [450, 112], [450, 157]], "labelAt": [382, 100] },
          { "id": "accepted-events", "from": "edge", "to": "stream", "label": "accepted events", "classification": "append-only", "variant": "emphasis", "fromSide": "right", "toSide": "left", "via": [[420, 271], [420, 385]], "labelAt": [438, 324] },
          { "id": "identity-map", "from": "consent", "to": "pii", "label": "identity map", "classification": "encrypted PII", "variant": "security", "route": "straight", "labelAt": [638, 144] },
          { "id": "normalized-facts", "from": "stream", "to": "warehouse", "label": "normalized facts", "classification": "non-PII", "variant": "emphasis", "fromSide": "right", "toSide": "left", "via": [[638, 385], [638, 271]], "labelAt": [638, 326] },
          { "id": "daily-aggregates", "from": "warehouse", "to": "features", "label": "daily aggregates", "classification": "batch", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "route": "straight", "labelAt": [745, 326] },
          { "id": "metrics-query", "from": "warehouse", "to": "dashboard", "label": "metrics SQL", "classification": "read-only", "variant": "default", "fromSide": "right", "toSide": "bottom", "via": [[852, 271], [960, 271]], "labelAt": [876, 258] },
          { "id": "feature-vectors", "from": "features", "to": "model", "label": "feature vectors", "classification": "derived", "variant": "dashed", "route": "straight", "labelAt": [852, 372] },
          { "id": "restricted-join", "from": "pii", "to": "dashboard", "label": "restricted join", "classification": "approved only", "variant": "security", "route": "straight", "labelAt": [852, 144] }
        ],
        "cards": [
          {
            "dot": "emerald",
            "title": "Primary Data Path",
            "items": [
              "Events move left to right through source, ingest, process, store, and consume stages",
              "The hot path stays visually clear even with secondary batch flows",
              "Labels name data assets instead of generic API verbs"
            ]
          },
          {
            "dot": "rose",
            "title": "Sensitive Boundary",
            "items": [
              "Consent and PII paths are styled as security flows",
              "PII lands in a restricted vault, separate from the analytics warehouse",
              "Restricted joins are visible without implying default access"
            ]
          },
          {
            "dot": "orange",
            "title": "Derived Consumers",
            "items": [
              "Dashboards read curated facts from the warehouse",
              "Feature vectors are derived by batch from analytics tables",
              "Consumption paths stay distinct from collection and consent handling"
            ]
          }
        ]
      }
      
    • production-deployment.architecture.json 4.6 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Production Deployment Ownership",
          "output": "examples/production-deployment.html",
          "visual_preset": "blueprint",
          "animation": "trace",
          "quality_profile": "showcase",
          "engineering_profile": "deployment-ownership"
        },
        "components": [
          { "id": "clients", "type": "external", "label": "Customers", "sublabel": "web + mobile", "pos": [38, 300], "size": [122, 60] },
          { "id": "edge", "type": "cloud", "label": "Global Edge", "sublabel": "CDN + WAF", "pos": [230, 300], "size": [126, 60], "tag": "edge team" },
          { "id": "gateway", "type": "security", "label": "API Gateway", "sublabel": "public :443", "pos": [430, 300], "size": [128, 60], "tag": "platform" },
          { "id": "api_a", "type": "backend", "label": "API Pods / AZ-a", "sublabel": "private subnet", "pos": [630, 195], "size": [136, 62], "tag": "app team" },
          { "id": "api_b", "type": "backend", "label": "API Pods / AZ-b", "sublabel": "private subnet", "pos": [630, 405], "size": [136, 62], "tag": "app team" },
          { "id": "redis", "type": "database", "label": "Redis", "sublabel": "multi-AZ cache", "pos": [840, 195], "size": [126, 62], "tag": "platform" },
          { "id": "postgres", "type": "database", "label": "PostgreSQL", "sublabel": "primary / encrypted", "pos": [840, 405], "size": [126, 62], "tag": "data team" },
          { "id": "events", "type": "messagebus", "label": "Event Bus", "sublabel": "orders.v1", "pos": [1040, 300], "size": [126, 60], "tag": "platform" },
          { "id": "worker", "type": "backend", "label": "Workers", "sublabel": "private workload", "pos": [1190, 300], "size": [126, 60], "tag": "app team" },
          { "id": "replica", "type": "database", "label": "DR Replica", "sublabel": "eu-west-1", "pos": [1040, 578], "size": [126, 62], "tag": "data team" },
          { "id": "audit", "type": "cloud", "label": "Audit Archive", "sublabel": "immutable objects", "pos": [1190, 450], "size": [126, 62], "tag": "security" },
          { "id": "observability", "type": "external", "label": "Observability", "sublabel": "metrics + traces", "pos": [1190, 85], "size": [126, 62], "tag": "SRE" }
        ],
        "boundaries": [
          { "kind": "region", "label": "AWS us-east-1 / production", "wraps": ["edge", "gateway", "api_a", "api_b", "redis", "postgres", "events", "worker", "audit"], "pad": 20 },
          { "kind": "security-group", "label": "private application network", "wraps": ["api_a", "api_b", "redis", "postgres", "events", "worker"], "pad": 14 },
          { "kind": "region", "label": "AWS eu-west-1 / disaster recovery", "wraps": ["replica"] },
          { "kind": "security-group", "label": "DR private subnet", "wraps": ["replica"], "pad": 14 }
        ],
        "connections": [
          { "from": "clients", "to": "edge", "label": "HTTPS", "variant": "emphasis" },
          { "from": "edge", "to": "gateway", "label": "mTLS", "variant": "security" },
          { "from": "gateway", "to": "api_a", "label": "VPC route", "variant": "emphasis", "route": "orthogonal-h", "labelAt": [594, 275] },
          { "from": "gateway", "to": "api_b", "label": "VPC route", "variant": "emphasis", "route": "orthogonal-h", "labelAt": [594, 385] },
          { "from": "api_a", "to": "redis", "label": "cache", "route": "straight" },
          { "from": "api_b", "to": "postgres", "label": "SQL", "route": "straight" },
          { "from": "api_a", "to": "events", "label": "publish", "variant": "dashed", "fromSide": "top", "toSide": "top", "via": [[698, 170], [1103, 170]] },
          { "from": "api_b", "to": "events", "variant": "dashed", "fromSide": "top", "toSide": "bottom", "via": [[698, 380], [1103, 380]] },
          { "from": "events", "to": "worker", "variant": "emphasis" },
          { "from": "postgres", "to": "replica", "label": "cross-region WAL", "variant": "security", "route": "orthogonal-v", "labelAt": [1003, 529] },
          { "from": "worker", "to": "audit", "label": "evidence", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 58 },
          { "from": "worker", "to": "observability", "label": "OTLP", "variant": "dashed", "route": "orthogonal-v" }
        ],
        "cards": [
          { "dot": "cyan", "title": "Runtime Ownership", "items": ["Platform owns the edge, gateway, cache, and event bus", "Application teams own API pods and workers", "Data owns primary and disaster-recovery state"] },
          { "dot": "rose", "title": "Named Crossings", "items": ["Public HTTPS terminates at the managed edge", "mTLS crosses into the application network", "Cross-region WAL is explicit and encrypted"] },
          { "dot": "emerald", "title": "Operational Evidence", "items": ["Workers emit traces to SRE-owned observability", "Audit evidence lands in immutable storage", "Unknown placement should remain marked, never invented"] }
        ]
      }
      
    • release-delivery.workflow.json 4.4 KB
      {
        "schema_version": 1,
        "diagram_type": "workflow",
        "meta": {
          "title": "Release Delivery Workflow",
          "output": "examples/release-delivery.html",
          "animation": "trace",
          "quality_profile": "showcase"
        },
        "lanes": [
          { "id": "dev", "label": "Developer" },
          { "id": "ci", "label": "Continuous Integration" },
          { "id": "approval", "label": "Release Governance" },
          { "id": "environment", "label": "Production Environment" },
          { "id": "communication", "label": "Release Communication" },
          { "id": "exceptions", "label": "Failure + Rollback", "variant": "exception" }
        ],
        "phases": [
          { "id": "change", "label": "Change", "fromCol": 0, "toCol": 1 },
          { "id": "verify", "label": "Build + verify", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
          { "id": "promote", "label": "Promote + observe", "fromCol": 4, "toCol": 5, "variant": "dashed" }
        ],
        "groups": [
          { "id": "blocking_checks", "label": "Blocking checks", "lane": "ci", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
          { "id": "rollback_work", "label": "Recovery path", "lane": "exceptions", "fromCol": 3, "toCol": 5, "variant": "security" }
        ],
        "mainPath": ["commit", "pull_request", "build", "checks", "approval", "deploy", "verify_prod", "announce"],
        "nodes": [
          { "id": "commit", "lane": "dev", "col": 0, "type": "frontend", "label": "Commit", "sublabel": "signed change" },
          { "id": "pull_request", "lane": "dev", "col": 1, "type": "frontend", "label": "Pull Request", "sublabel": "reviewed diff" },
          { "id": "build", "lane": "ci", "col": 2, "type": "backend", "label": "Build", "sublabel": "locked inputs", "tag": "reproducible" },
          { "id": "checks", "lane": "ci", "col": 3, "type": "security", "label": "Quality Gates", "sublabel": "test + scan", "tag": "blocking" },
          { "id": "approval", "lane": "approval", "col": 4, "type": "security", "label": "Approve", "sublabel": "release owner", "tag": "human gate" },
          { "id": "deploy", "lane": "environment", "col": 4, "type": "cloud", "label": "Deploy", "sublabel": "canary 10%", "tag": "production" },
          { "id": "verify_prod", "lane": "environment", "col": 5, "type": "backend", "label": "Verify", "sublabel": "smoke + SLO" },
          { "id": "announce", "lane": "communication", "col": 5, "type": "external", "label": "Announce", "sublabel": "status + notes" },
          { "id": "failed", "lane": "exceptions", "col": 2, "type": "security", "label": "Stop Release", "sublabel": "gate failed" },
          { "id": "rollback", "lane": "exceptions", "col": 4, "width": 64, "type": "messagebus", "label": "Rollback", "sublabel": "last good image", "tag": "owner: on-call" }
        ],
        "edges": [
          { "from": "commit", "to": "pull_request" },
          { "from": "pull_request", "to": "build", "label": "merge", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "build", "to": "checks" },
          { "from": "checks", "to": "approval", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "approval", "to": "deploy", "variant": "security", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "deploy", "to": "verify_prod" },
          { "from": "verify_prod", "to": "announce", "label": "healthy", "variant": "emphasis", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "checks", "to": "failed", "label": "red", "variant": "security", "role": "error", "route": "drop", "fromSide": "bottom", "toSide": "top" },
          { "from": "verify_prod", "to": "rollback", "variant": "security", "role": "error", "route": "outside-right", "fromSide": "right", "toSide": "right" },
          { "from": "rollback", "to": "deploy", "label": "restore", "variant": "dashed", "role": "return", "route": "return-left", "fromSide": "left", "toSide": "left" }
        ],
        "cards": [
          { "dot": "emerald", "title": "One Happy Path", "items": ["Every change is reviewed before a reproducible build", "Blocking checks must be green before human approval", "Production is complete only after smoke and SLO verification"] },
          { "dot": "rose", "title": "Stop Conditions", "items": ["Test or security failure stops promotion", "Production health can reverse a release", "Rollback ownership is visible before an incident"] },
          { "dot": "cyan", "title": "Release Evidence", "items": ["Approval, immutable image, and check results are retained", "The release announcement follows verification", "The main path remains readable without hiding failure"] }
        ]
      }
      
    • sequence-cache-miss-request.html 744.4 KB · in bundle
    • web-app-rendered.html 744.4 KB · in bundle
    • web-app.architecture.json 3.1 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Sample Web App",
          "output": "web-app-rendered.html",
          "quality_profile": "showcase"
        },
        "components": [
          { "id": "users", "type": "external", "label": "Users", "sublabel": "Browser / Mobile", "pos": [40, 300], "size": [120, 60] },
          { "id": "auth", "type": "security", "label": "Auth Provider", "sublabel": "OAuth 2.0", "pos": [40, 110], "size": [120, 64], "tag": "JWT + PKCE" },
          { "id": "cdn", "type": "cloud", "label": "CloudFront", "sublabel": "CDN", "pos": [250, 300], "size": [130, 60] },
          { "id": "lb", "type": "cloud", "label": "Load Balancer", "sublabel": "HTTPS :443", "pos": [460, 300], "size": [130, 60] },
          { "id": "api", "type": "backend", "label": "API Server", "sublabel": "FastAPI :8000", "pos": [670, 300], "size": [130, 60] },
          { "id": "cache", "type": "database", "label": "Redis", "sublabel": "cache :6379", "pos": [670, 150], "size": [130, 60] },
          { "id": "db", "type": "database", "label": "PostgreSQL", "sublabel": "primary :5432", "pos": [880, 300], "size": [130, 60] },
          { "id": "s3", "type": "cloud", "label": "S3", "sublabel": "static assets", "pos": [250, 440], "size": [130, 60], "tag": "OAI protected" },
          { "id": "queue", "type": "messagebus", "label": "SQS", "sublabel": "job queue", "pos": [670, 440], "size": [130, 60] },
          { "id": "worker", "type": "backend", "label": "Worker", "sublabel": "async jobs", "pos": [880, 440], "size": [130, 60] }
        ],
        "boundaries": [
          { "kind": "region", "label": "AWS Region: us-west-2", "wraps": ["cdn", "lb", "api", "cache", "db", "s3", "queue", "worker"] },
          { "kind": "security-group", "label": "sg-api :443/:8000", "wraps": ["lb", "api"] }
        ],
        "connections": [
          { "id": "users-to-cdn", "from": "users", "to": "cdn", "label": "HTTPS", "variant": "emphasis" },
          { "id": "jwt-verification", "from": "auth", "to": "api", "label": "verify JWT", "variant": "security", "fromSide": "right", "toSide": "top", "via": [[620, 142], [620, 246], [735, 246]] },
          { "id": "cdn-to-lb", "from": "cdn", "to": "lb" },
          { "id": "static-assets", "from": "cdn", "to": "s3", "label": "static", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 58 },
          { "id": "lb-to-api", "from": "lb", "to": "api" },
          { "id": "cache-read-through", "from": "api", "to": "cache", "label": "read-through", "fromSide": "top", "toSide": "bottom", "labelDy": -68 },
          { "id": "api-sql", "from": "api", "to": "db", "label": "SQL" },
          { "id": "enqueue-job", "from": "api", "to": "queue", "label": "enqueue", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 58 },
          { "id": "queue-to-worker", "from": "queue", "to": "worker" }
        ],
        "cards": [
          { "dot": "cyan", "title": "Edge", "items": ["CloudFront CDN fronts all traffic", "S3 serves static assets via OAI"] },
          { "dot": "emerald", "title": "Application", "items": ["FastAPI behind an HTTPS load balancer", "Redis read-through cache", "Async work drained from SQS by a worker"] },
          { "dot": "rose", "title": "Security", "items": ["OAuth 2.0 with JWT + PKCE", "API + LB isolated in a security group"] }
        ]
      }
      
    • workflow-agent-tool-call-rendered.html 749.8 KB · in bundle
  • migrations
    • workflow-v2.mjs 9 KB · in bundle
  • recipes
    • scenarios.mjs 37.3 KB · in bundle
  • references
    • architecture-layout-repair.md 4.3 KB
      # Architecture layout repair
      
      Use this after actual visual review finds several tangled routes. A successful machine receipt does not settle composition. Work on the existing candidate, retaining all required components, relationships, labels, evidence, boundaries, and node sizes.
      
      ## Choose the repair scope
      
      If the main and secondary chains already read clearly, repair the isolated defect locally. If a main chain is blocked, several routes tangle, or a local fix moves the defect onto another route, reflow the connected scene in one edit. Preserve all semantics and user-fixed geometry; agent-generated positions and route controls may change. After moving nodes, remove stale generated route overrides so automatic routing can use the new placement.
      
      The receipt's `directCorridorBlockers`, when present, names nodes between an edge's aligned endpoints. This is geometric evidence, not proof that the edge is the main path or a new validation failure. Trace the reader's actual main path first. When a listed blocker interrupts that path, reposition the connected group instead of adding another detour.
      
      ## One coherent repair
      
      1. Trace the affected relationships and their endpoints in the JSON. Before choosing coordinates, write the reader’s main path as an ordered list of existing edges, then identify shared state and real feedback cycles. Every neighboring pair in that main path must have the relationship being explained; place other components on branches beside their actual owner. Use `validate architecture <candidate.json> --layout-json --repo-root <root>` once if the compact receipt and screenshot do not reveal the needed route or label geometry; omit `--repo-root` only for a design without repository evidence. Do not guess repeated waypoint coordinates.
      2. Place those connected main-path neighbors in reading order. Put shared state between its readers/writers, on an adjacent row if necessary, so one writer does not need a line across the whole execution area. Arrange a feedback cycle in its actual edge order around an open rectangle, with other consumers beside their owner. For example, if the edges are `client → API → dispatcher → worker → collector → runner → dispatcher`, put the first four on the upper row, collector below worker, and runner below dispatcher: the return then uses the lower row and a short upward edge. This illustrates adjacency, not a graph or set of coordinates to copy; use only relationships present in the candidate. Preserve every edge and its actual direction.
      3. Keep automatic endpoints for the new placement. Constrain a side only when a branch or return needs a specific corridor; check that corridor against every affected relationship, including storage branches. If that local constraint introduces another conflict, return to the connected placement instead of cycling through side combinations. Only use detailed `via` or label coordinates for a remaining measured defect. Keep external actors outside the resolved boundary rectangle, including its padding; not listing a node in `wraps` does not visually exclude it. Keep an internal relationship and its label inside the shared boundary unless crossing it conveys a real fact; do not imply an external hop merely to avoid another route.
      4. When `composition/label-gap` reports a measured minimum, enlarge that clear gap or move the connected group onto another readable row. Keep the full label beside its own route; placing it in distant empty space does not repair the relationship. Compact unused gaps while preserving measured label space and the previous text size. Keep the main interaction and all required nodes readable in the default desktop view; do not trade crossings for a large blank canvas, tiny text, or a chain that doubles back without a semantic reason.
      
      Run the complete `finalize` once after the edit, then `visual-check` on the successful artifact and inspect its desktop captures. When replacing an already reviewed artifact, use one fresh `--out-dir` for both commands as described in [the delivery contract](delivery-contract.md#a-new-candidate-at-an-existing-output-path). Trace the main path, each secondary chain, and every affected arrow and label. A bounded second repair may address a remaining specific defect. If it still fails visual acceptance, retain the candidate and report the concrete gap; do not count it as a successful repair or continue blind coordinate changes.
      
    • authoring-contract.md 26.5 KB
      # Authoring contract
      
      Read this reference only after the Fast authoring path calls for more detail. The schemas and examples remain authoritative.
      
      ## Composition repair
      
      When correcting an authored overview's abstraction, map every affected role, relationship direction, protocol, boundary, condition, and source reference to its surviving node or relationship before regrouping. A startup citation does not prove a message protocol. Preserve each claim's inspected evidence. Keep user-supplied or agreed topology fixed; fewer routes alone do not justify merging. A boundary around one node requires an explicit isolation fact and must not merely repeat its label.
      
      ## Label repair
      
      When a relationship label collides, move the label, adjust the route or spacing, then shorten the wording while preserving meaning. Omit wording only when both endpoints fully imply it and it conveys no protocol, action, direction, synchronous or asynchronous behavior, or cross-boundary mechanism. Spacing means clear gap rather than center distance; measured mask width takes precedence. The first-draft gap budget is in [Layout and routing](authoring-defaults.md#layout-and-routing).
      
      For a disproportionate sublabel, keep its exact role or protocol concise and place the supplementary fact in a note or card. Preserve every required responsibility, protocol, and boundary fact. Use the first-draft node-width budget in [Layout and routing](authoring-defaults.md#layout-and-routing).
      
      ## Schema lookup
      
      Read both the mode schema and `schemas/common.schema.json`. The mode schemas use `$ref`, so the common file is where shared enums live.
      
      - `componentType`: `frontend`, `backend`, `database`, `cloud`, `security`, `messagebus`, `external`
      - `variant`: `default`, `emphasis`, `security`, `dashed`
      - Relationship IDs use the shared identifier pattern and must be unique in their collection.
      
      Do not invent fields. Before writing any new field, enum, or constrained text, read its schema definition, including common `$ref` targets. In particular, check boundary kinds, repository identity, and source-reference shapes. An example demonstrates structure; it does not enumerate every valid value. Author fresh IDs, wording, facts, and layout.
      
      ## Workflow layout contracts
      
      Use schema v2 for new workflows and keep schema v1 when an existing source must
      retain fixed geometry. In both versions, `col` stays in `0..5` and semantic
      edge labels are never deleted as a spacing repair. Do not change only
      `schema_version` when absolute coordinates exist: follow the canonical
      [migration and layout-receipt contract](../renderers/workflow/README.md#migration-and-layout-receipt).
      The complete normative invariants live in the workflow renderer's
      [layout contracts](../renderers/workflow/README.md#layout-contracts).
      For sequential stages stacked in one container, use one v2 lane and group,
      omit `meta.viewBox`, and center nodes around the lane content with symmetric
      `yOffset` values such as `-90 / 0 / 90`. Keep semantic edge labels and act on
      compiler diagnostics.
      
      ## Legend contract
      
      Omit `meta.legend` for the truthful default: `auto` lists only semantic kinds
      present in typed IR. Use `mode: "all"` for a renderer reference or
      `mode: "hidden"` to remove the full legend. Under `entries`, only keys listed
      by the selected mode schema are valid; each key accepts `label`, `visible`, or
      both. `visible: true` may show an unused supported convention, while
      `visible: false` hides it. `hidden` cannot be overridden.
      
      A label override changes reader wording only. Never infer a kind from prose or
      use the legend to compensate for missing nodes, states, messages, or flows.
      Long labels are measured and wrap into deterministic rows. Architecture's
      implicit automatic viewBox grows from that same measured footprint. For
      backwards compatibility, a legacy document with no `meta.legend` may omit an
      implicit auto legend that cannot fit its explicit viewBox; this never changes
      its typed topology. Adding `meta.legend` makes the presentation intentional and
      strict: if its resolved labels cannot fit the authored viewBox, shorten or hide
      them, or widen the viewBox using the emitted diagnostic.
      
      ## Language consistency
      
      Choose one primary authored language. An explicit user choice wins; otherwise
      use the language of the request, or the conversation's dominant language when
      the request itself is language-neutral. Separately choose the Viewer locale.
      Always write the matching `meta.locale` as a well-formed language tag: `"en"`
      for English, `"zh-CN"` for Simplified Chinese, `"es"` for Spanish, or any
      other tag for another language. The renderer consumes the authored locale without inferring language
      from diagram strings. Documents that omit it remain valid and default to
      English.
      
      `meta.locale` controls only renderer-owned reader surfaces: `<html lang>`, the
      document-title suffix, default SVG description and focus labels, default legend
      labels, and fixed Viewer controls, statuses, accessibility names, and errors.
      It never translates authored content. Apply the primary language separately to
      titles, subtitles, node and relationship copy, boundaries, lanes, groups,
      legend label overrides, and cards. A bilingual diagram still
      chooses one primary locale for the Viewer; follow an explicit primary-language
      request, then prompt order or conversation dominance.
      
      `en` and `zh-CN` are built-in Viewer catalogs and need nothing further. For
      every other `meta.locale`, also set `meta.translations`: an object mapping the
      renderer's canonical message keys (`catalogKeys()` in
      `renderers/shared/i18n.mjs`) to translated strings whose `{placeholder}` tokens
      match the English source exactly. Reuse suitable translations from `examples/locales/` or a previously reviewed
      catalog; Spanish uses `examples/locales/es.json`. Translate missing keys or adapt terminology when the diagram needs it;
      use the English source to check keys and placeholders. Example catalogs may
      lag new Viewer keys; validation reports those gaps and uses English for them. A key that is missing, unrecognized, or has mismatched
      placeholders falls back to its English string — `validate`/`render`/`deliver`
      report the resulting coverage to stderr — rather than breaking the render or
      silently shipping an untranslated string as if it were translated.
      
      For older dev inputs using only `meta.locale: "es"`, copy the Spanish catalog
      into `meta.translations` before rendering again. Existing standalone HTML
      keeps its embedded translations.
      
      For a requested language you cannot supply `meta.translations` for, do not
      write a `meta.locale` with no built-in catalog and no translations. Keep every
      reader-facing authored string in the requested language, omit `meta.locale` so
      the renderer safely uses English, and explicitly tell the user that fixed
      Viewer UI and `<html lang>` remain English and the artifact is not fully localized.
      The fallback applies only to renderer-owned surfaces; it never
      permits authored copy to fall back to English. Do not silently substitute
      `zh-CN` for another language or Chinese locale, and do not machine-translate
      `meta.translations` values without disclosing that they are unreviewed.
      
      Keep exact product names, code identifiers, commands, protocols, API paths, and
      environment names intact. Those terms may remain English inside localized copy,
      but surrounding explanatory prose must still use the selected language.
      Renderer-owned default legend labels follow `meta.locale`; author a
      `meta.legend.entries.*.label` override only when the diagram needs different
      domain wording, and keep that authored override in the primary language.
      
      ## Visual preset default
      
      Omit `meta.visual_preset` by default. The renderer then opens the diagram in
      `classic` for both light and dark color modes. Color mode and visual preset are
      independent viewer state: switching Light / Dark must preserve the current
      preset. Author `signal-flow`, `blueprint`, or `editorial` only when the user
      explicitly requests that visual style.
      
      ## Engineering profile default
      
      Omit `meta.engineering_profile` for an ordinary system architecture. Region,
      cluster, and security boundary wording do not by themselves enable an
      engineering profile. Enable `deployment-ownership` only when the user
      explicitly asks for a production deployment topology, ownership handoff, or
      fail-closed deployment review and the source facts are known. Once enabled,
      do not remove the engineering profile merely to pass validation; repair the
      authored facts or report the diagnostics truthfully.
      
      ## Title hierarchy
      
      Use one concise title and let the diagram carry the explanation. Omit
      `meta.subtitle` by default, and never use it to restate the title, nodes, edges,
      or cards. Include one short supporting line only when the user explicitly asks
      for a subtitle; an omitted or blank subtitle must not leave an empty visual row
      in the generated viewer.
      
      ## Executable geometry rules
      
      Generate one responsive artifact for laptops and external displays, preserving the authored SVG/viewBox, proportions, semantic geometry, and normal document flow. Use meaningful content rows and the Reader-declared readable page-scroll behavior when the complete diagram needs more height; viewport fitting does not authorize alternate topology or smaller typography.
      
      - Node anchors start at side midpoints. `left`/`right` change the horizontal endpoint; `top`/`bottom` change the vertical endpoint. For an automatic Architecture relationship, unobstructed facing ports whose axis offset is under 16px may share one horizontal or vertical axis when both endpoints retain the 16px corner gutter. If exactly one endpoint belongs to a spread group, only its unshared counterpart moves; relationships spread at both endpoints keep their distinct ports and outside bridge unless a reciprocal facing pair can jointly use separate straight lanes while preserving endpoint spacing, labels, and all surrounding route and obstacle clearances.
      - A side is a direction contract. The first and final route segment must be perpendicular and outward/inward in the named direction.
      - In architecture, data-flow, and lifecycle diagrams, explicit `route: "straight"` requests one direct segment, which may be diagonal when endpoint sides are not pinned. The artifact checker preserves this intent; explicit sides, opaque-node clearance, and other quality gates still apply. `via` takes precedence and retains existing rules, including data-flow's requirement for orthogonal via segments.
      - Automatic Port Spread is a default renderer behavior for architecture, workflow, data-flow, and lifecycle diagrams. Shared automatic endpoints spread deterministically and symmetrically with a 16px corner gutter. It does not apply to sequence messages, single relationships, or explicit `via`, `channelX`, `channelY`, `labelAt`, or non-`auto` routes.
      - Showcase route rhythm: every nonzero segment must be at least 8px; every interior segment must be at least 16px. When spread ports are nearly parallel, the router uses a 24px endpoint stub and a 16px outside bridge instead of manufacturing a tiny dogleg.
      - Showcase route compactness: an explicit Architecture route fails with `composition/excessive-route-detour` when its orthogonal length is at least 2.5 times an obstacle-aware legal route, adds at least 200px, and sends a control point at least 96px beyond the content envelope. The evidence records both lengths, ratio, excess, bounds, and excursion. Remove an unnecessary `via` or move the diagnosed corridor inward instead of enlarging the canvas. Related relationships that overlap on the same outer corridor by at least 32px are treated as an intentional bus and remain valid.
      - Shared endpoint corridors are allowed only when they remain semantically unambiguous. Unrelated collinear overlap of 8px or more fails showcase.
      - Container borders are intentional pass-through geometry, but a long edge running along a structural border is not.
      - An edge crossing an unrelated opaque node is always a hard failure, independent of quality profile.
      
      ### Explicit `via` coordinates
      
      Use the resolved departure anchor `S = [sx, sy]` and arrival anchor
      `T = [tx, ty]`. Anchors start at side midpoints, but automatic routing and
      Port Spread can move them as described above; do not assume an anchor copied
      from an automatic route is the anchor of a newly authored explicit route.
      Explicit `via` routes do not receive automatic Port Spread.
      
      For the first waypoint `F = via[0]` and last waypoint `L = via[via.length - 1]`,
      use these alignments and directions (SVG y increases downward):
      
      | Side | Departure (`fromSide`): `S` → `F` | Arrival (`toSide`): `L` → `T` |
      | --- | --- | --- |
      | `top` | `F[0] === sx`, `F[1] < sy` | `L[0] === tx`, `L[1] < ty` |
      | `bottom` | `F[0] === sx`, `F[1] > sy` | `L[0] === tx`, `L[1] > ty` |
      | `left` | `F[1] === sy`, `F[0] < sx` | `L[1] === ty`, `L[0] < tx` |
      | `right` | `F[1] === sy`, `F[0] > sx` | `L[1] === ty`, `L[0] > tx` |
      
      For example, given a bottom departure anchor `S = [180, 160]` and a left
      arrival anchor `T = [360, 260]`, this relationship fragment leaves downward
      and enters the target rightward:
      
      ```json
      {
        "from": "source",
        "to": "target",
        "fromSide": "bottom",
        "toSide": "left",
        "via": [[180, 200], [300, 200], [300, 260]]
      }
      ```
      
      The full path is `[180, 160] → [180, 200] → [300, 200] → [300, 260] → [360, 260]`.
      Changing only the first waypoint to `[200, 200]` makes the departure diagonal;
      changing it to `[180, 120]` keeps its x aligned but leaves upward through the
      source instead of outward from its bottom. Both violate `fromSide: "bottom"`
      and produce `clean-flow/endpoint-side-direction`. The example establishes
      endpoint direction only: keep the full route clear of unrelated nodes and
      apply the other geometry rules above.
      
      ### Spacing and labels
      
      In showcase Architecture, an unpinned connection label keeps its default position
      when clear. If it collides, the renderer tries a bounded set of nearby positions
      along the existing route, avoiding nodes, boundary titles, other labels and
      other routes within the resolved canvas. Explicit `labelAt`, `labelDx`, `labelDy`
      or `labelSegment` (including zero) disables this fallback. Routes and topology
      stay unchanged; if no nearby position is clear, validation reports the original
      collision. Inspect resolved labels with `--layout-json` before adding controls.
      Standard placement retains its existing behavior.
      
      Spacing recommendations mean clear gap between boxes, not center distance. A 200px center distance between 165px-wide nodes leaves only 35px of clear gap.
      
      For a relationship label, require:
      
      ```text
      clear gap > label mask width + 8px breathing room
      label mask width ≈ 6.5px × ASCII units + 13px
      CJK characters count as two units
      ```
      
      Relationship labels are semantic data. If the gap is too small, move the label,
      adjust the route or spacing, then shorten the wording while preserving meaning.
      Omit only wording already fully implied by both endpoints and carrying no
      protocol, action, direction, synchronous/asynchronous behavior, or
      cross-boundary mechanism. Preserve every meaningful label.
      Deleting it is not a spacing repair. If a relationship starts unlabeled because
      its endpoints fully imply it, explain why the wording is redundant; this is a
      semantic authoring choice, not a spacing repair. In workflow v2, let the compiler
      allocate its measured mask before applying a diagnosed `labelAt`,
      `labelDx`/`labelDy`, or `labelSegment`. Apply one diagnosed geometry control at
      a time unless several edges share a constrained channel. In that case, plan the smallest coupled change from measured geometry and
      validate it together. Architecture/workflow provide layout evidence through
      `validate <type> <candidate.json> --layout-json`; for other types, use validation
      diagnostics and the rendered SVG geometry.
      Before adding manual routes, check whether unnecessary agent-added controls
      disable automatic port spread; preserve user-required route intent. Use the
      measured clearance rules above rather than guessing coordinates.
      
      ### Repair evidence
      
      For architecture, `validate architecture <input.json> --layout-json` exposes the
      resolved component boxes, boundary frames, connection points, and label positions.
      A measurable rejected layout also returns these fields, with `ok: false`,
      `contract: "archify-architecture-layout-v1"`, diagnostics, and exit 1. This is
      repair evidence, not artifact acceptance; it writes no HTML. Malformed input or
      an implementation failure retains the ordinary failure receipt without layout.
      
      Use the measured failing side for `layout/boundary-out-of-bounds`. Left/top
      negative coordinates need an inward move; increasing viewBox width/height only
      addresses right/bottom overflow. Boundaries may wrap members across rows. Keep
      real membership intact and recheck connected routes after moving members.
      
      Automatic architecture canvases include route points as well as nodes, frames,
      and labels. An authored viewBox remains authoritative. In showcase,
      `layout/route-out-of-bounds` identifies clipped route points; negative coordinates
      need an inward route, while right/bottom overflow can also use a larger authored
      canvas. Recheck desktop readability after enlarging a canvas.
      
      When several crossing/corridor diagnoses involve the same nodes, consider their
      placement together before adding route controls. Apply one coherent repair and
      validate it; independent label nudges cannot fix a shared layout bottleneck.
      Compare diagnostics by code, subject, and stage instead of total count alone.
      
      ### Repair order
      
      1. Fix missing/invalid `meta.quality_profile` and schema errors.
      2. Fix node overlap or out-of-range placement.
      3. Fix edge-through-node and endpoint-direction errors.
      4. Fix crossings, ambiguous corridors, border runs, excessive detours, and route rhythm.
      5. Fix label-to-node, label-to-label, then label-to-route clearance.
      6. Fix labels that leave the canvas: move the label with `labelAt`/`labelDx`/`labelDy`/`labelSegment`, or widen `meta.viewBox`. Suggested `labelDx`/`labelDy` values replace the authored field; they are not added to it.
      
      Run `validate` after every edit. Consume `diagnostics[]` by stable `code`, exact `subject`, measured `evidence`, and `supportedFixes`. If the diagnostic gives `labelAt`, use that point instead of estimating another offset.
      
      ## Mode placement
      
      ### Architecture
      
      Choose overview or mechanism detail using [Composition and meaning](authoring-defaults.md#composition-and-meaning). Use one obvious primary reading path, which may step across meaningful rows when the requested topology needs room. Keep the overview readable at its chosen abstraction; expand implementation details when they answer the reader's question. Group only real ownership, trust, process, or deployment boundaries. Boundaries do not replace relationships.
      
      Grid placement is preferred when the schema supports it. Free positions are appropriate for a bounded exception, not for prose-level coordinate planning. Keep external actors outside the system boundary when that is factually true.
      
      ### Workflow
      
      Lanes express responsibility or phase. Columns `0..5` express logical
      progression. Start new workflows on `readable-v2`; retain `fixed-v1` only for
      legacy geometry compatibility. Keep the happy path monotonic, preserve semantic
      edge labels, and route retries and exception returns outside the main lane
      corridor.
      
      #### Workflow viewport repair
      
      When `viewer/viewport-overflow` includes `workflowLanes`, inspect the tallest
      rendered frames and their node span before changing the source. Measurements
      are CSS pixels; space above/below nodes includes lane titles and routing, so it
      is not a removable-space budget. Frame IDs identify rendered lane indices.
      
      Run `validate workflow <source.json> --layout-json` and match those frames to
      source lanes and nodes. Check whether many steps share the last logical column
      and use large `yOffset` values. Readable-v2 currently reserves symmetric space
      around offsets and shares the base content height between lanes, so increasing
      one offset can enlarge otherwise sparse lanes.
      
      Where the source's ownership and explicit geometry permit, redistribute steps
      across logical columns and meaningful lanes, keeping the main path monotonic.
      Preserve every required node, relationship, label and semantic check. If ownership
      or absolute pins prevent reflow, report that constraint instead of merging lanes
      or moving pins automatically. Validate the changed JSON, deliver a fresh HTML,
      then rerun browser checks and inspect the first screen; a static pass alone does
      not settle viewport fit. These are repair directions, not guaranteed coordinates.
      
      ### Sequence
      
      Participants are ordered by conversation role. Messages own their vertical order. Use return/async/security variants for meaning, not decoration; sequence does not use Automatic Port Spread.
      
      ### Dataflow
      
      Stages express transformation or custody. Rows separate parallel streams. Label only data contracts, classifications, or cross-boundary movement that is not obvious.
      
      ### Lifecycle
      
      Schema v2 (new diagrams): each populated lane is one row, `main` first,
      `terminal` last, others in `lanes[]` order. `col` `0..4` is one shared x grid,
      so a state placed in the column of the state it leaves gets a straight vertical
      transition. Every transition, including the main path, is authored; there is no
      implied rail. The renderer sizes the canvas, widens a column gap for a
      same-row label, and routes automatic transitions orthogonally through row gaps.
      Keep labels short: a gap carrying several parallel lines has little room.
      
      Schema v1 (legacy): main phases use columns `0..4`; event and terminal bands
      use columns `0..2`, and event/terminal column `N` aligns with main column
      `N + 2`. Every lane other than `main` and `terminal` shares one middle band;
      states in the same column there need distinct `yOffset` values.
      
      In both versions a recoverable failure needs a real transition back to an
      active state. A card saying “retry” is not topology.
      
      ## Repository evidence
      
      When the diagram must reflect real code, inspect repository entrypoints,
      runtime boundaries, storage, transports, and deployment configuration before
      authoring. Record only evidence you actually verified. `--repo-root <path>` is
      accepted by `render`, `validate`, `deliver`, and `preview` for every diagram
      type, by architecture `compare`, and by workflow `migrate`; every mode verifies `meta.repository` and
      node `sources` the same way. Migrating a source-backed workflow requires the same
      `--repo-root` so its candidate is verified before replacing the destination.
      Never infer runtime causality from file proximity
      or naming alone.
      
      Declare `meta.repository.url` and one full 40-character `revision`, then attach
      `sources` to the mode's node collection (Architecture `components[]`, Workflow
      and Data Flow `nodes[]`, Sequence `participants[]`, Lifecycle `states[]`) with
      repository-relative `path`, optional `line`, `end_line`, and `label`.
      Verification reads blobs at that commit, independently of working-tree edits.
      Verification ignores local Git replacement refs, including those selected by
      `GIT_REPLACE_REF_BASE`, and always reads the original objects at the pinned SHA.
      It does not change repository configuration or delete replacement refs.
      A matching local origin, available commit, bounded path,
      blob, and valid line range are required in every link mode. Verification is
      local and makes no remote requests; it establishes neither public availability
      nor the current reader's access rights.
      
      `link_mode` defaults to `web`. GitHub and Gitee HTTPS repository URLs generate
      revision-pinned links; their public hosts select the provider automatically.
      Optional `provider: "github"` or `"gitee"` must agree with the host. Existing
      GitHub declarations and default delivery receipt fields remain compatible.
      
      ```json
      {
        "url": "https://gitee.com/team/service",
        "revision": "0123456789abcdef0123456789abcdef01234567",
        "provider": "gitee"
      }
      ```
      
      For an internal or unsupported forge, select `link_mode: "local-only"`. The
      Viewer retains SRC markers, searchable file paths, line ranges, and revision
      labels without repository or source hyperlinks. The evidence receipt adds
      `linkMode: "local-only"`. `url` remains required as the expected origin identity;
      local-only disables links, not identity verification. A repository without an
      origin is not supported.
      
      ```json
      {
        "url": "http://git.internal:3000/Platform/Services/service",
        "revision": "0123456789abcdef0123456789abcdef01234567",
        "link_mode": "local-only"
      }
      ```
      
      Local-only accepts HTTP(S), `git@host:path`, and `ssh://git@host[:port]/path`
      addresses, including nested namespaces. Declare a credential-free address;
      HTTP(S) credentials on the checkout's origin are ignored for identity and
      redacted from diagnostics. Hostnames compare case-insensitively; repository
      paths retain case except for the existing GitHub behavior. A trailing slash
      normalizes away. Only GitHub and Gitee normalize a terminal `.git` and match
      standard HTTPS/443 with Git SSH/22. For other hosts, use the actual clone address:
      transport, port, `.git` suffix, and remote-relative versus absolute paths must
      match. For example, `git@host:Team/repo` differs from
      `ssh://git@host/Team/repo`; `git@host:/Team/repo` matches the latter. SCP-style
      paths preserve literal percent escapes, while URI paths decode them. SSH host
      aliases and forge-specific browse/clone prefixes are not guessed.
      GitLab/Gitea/Forgejo/Bitbucket web links are not implemented in this version;
      use local-only until a tested link provider is available. Unknown web providers
      fail with a diagnostic rather than emitting a guessed link.
      
      ## Hand-placed fallback
      
      Use only when no renderer can run. Start from `assets/template.html`, keep semantic CSS classes, preserve the inline SVG/accessibility structure, and run the delivery visual checklist. Never introduce inline literal colors that break dark/light parity.
      
      ## Node icons
      
      For domain-specific diagrams, set an optional `icon` on architecture components,
      workflow/dataflow nodes, sequence participants, or lifecycle states. Choose
      `calendar`, `clock`, `person`, `briefcase`, `flag`, or `moon` for everyday concepts;
      the complete catalog (including existing technical and lifecycle symbols) is
      `common.schema.json#/$defs/nodeIcon`. Use `icon: "none"` to hide the corner symbol.
      Omitting `icon` keeps the type-based default. These inline SVG symbols are
      renderer-owned and export with the diagram; URLs and raw SVG are not accepted.
      
      Icon selection changes only the corner symbol. The node's type still determines
      color and semantic grouping; brand marks remain independent. For a holiday
      workflow, pair `type: "backend", icon: "calendar"` with
      `meta.legend.entries.backend.label: "假期"`, and use `icon: "briefcase"` plus
      an appropriate legend label for make-up work. Keep the node label meaningful:
      icons are decorative and are hidden from assistive technology.
      
      See [holiday planning](../examples/holiday-planning.workflow.json) for a complete workflow example.
      
    • authoring-defaults.md 7.6 KB
      # Authoring defaults
      
      Read once before writing a fresh candidate. An existing frozen candidate going straight to `finalize` needs this only if repair changes its authorship.
      
      ## Composition and meaning
      
      For Architecture, default to a system overview led by the main user journey unless the user asks for a narrower mechanism, module map, or deployment topology. Group cooperating roles in accurately named subsystems when that still explains the requested interaction. Separate roles when grouping would hide control ownership, a trust or persistence boundary, lifecycle behavior, or another distinction the reader asked about. Keep secondary and opt-in capabilities in concise sourced notes unless their path matters to the requested question. Name a deliberately narrower scope in the title.
      
      Preserve every requested responsibility, relationship direction, protocol, and behavior-changing condition. Show approval, authorization, and state-transition gates on the affected node or relationship; a card alone cannot qualify an otherwise unconditional arrow. Keep source evidence with each asserted claim. Boundaries express real isolation, ownership, runtime, or persistence facts. Cards answer additional reader questions; they do not replace required topology. There is no node, edge, source, card, or boundary quota. If an authored overview needs regrouping after failure, use [Composition repair](authoring-contract.md#composition-repair); user-supplied or agreed topology remains fixed.
      
      Relationship labels carry meaning. Give them clear space and preserve action, protocol, direction, async behavior, or cross-boundary meaning. A label may start absent only when both endpoints already fully imply it; a collision calls for spacing or routing repair. See [Label repair](authoring-contract.md#label-repair) when measured evidence reports a collision.
      
      ## Layout and routing
      
      Place Architecture nodes by their actual connections before assigning coordinates; the router cannot rearrange boxes, so placement decides whether lines stay straight. Classify each relationship first, then place:
      
      - **Main path**: the reader's main journey, neighbors adjacent in reading order. Let a medium path step through meaningful rows instead of making a shallow horizontal strip.
      - **Branch or store**: directly above or below the node that owns, reads, or writes it, centered on that node so the edge is one straight segment. Keep all stores and branches of one row on the same side of it.
      - **Return** (back to an earlier main-path node): put its source on the side of the main path with no branches or stores, so it runs through an empty corridor instead of crossing them.
      - **Second entrance** into a node that already has an incoming edge: place the new source so it reaches that node from another side, usually directly below or above it.
      - **Fan-out**: a side with k relationships needs at least `32 + 14 × (k − 1)`px (four need 74px). Spread a hub's counterparts over two or three sides, or enlarge the hub. Center a parent on its children and align a child with its only parent.
      
      Before writing positions, trace each non-main relationship: its straight or one-bend corridor must not pass another node or cross another relationship. If it does, move the endpoint that is off the main path. Start the main actor and its first connected step together near the canvas origin; use content rows for vertical rhythm. Omit `meta.viewBox` for a fresh Architecture so the Reader measures intrinsic height. Keep supplied fixed geometry authoritative.
      
      Start with automatic routes and endpoint sides. Pin a side only for a necessary branch, return, or supplied geometry. Reserve `via`, `channelX`, `channelY`, and label coordinates for measured defects. Before writing positions, budget each labeled main-path edge at `6.5px × ASCII units + 21px` of clear gap, counting CJK as two units; use its own label length, not a row-wide fixed gap. Size Architecture sublabels for their preferred 9px text at `5.4px × text units + 8px`, with CJK counting twice; keep supporting copy concise without dropping required facts. Do not trade readability or meaning for fewer crossings. The [Geometry reference](authoring-contract.md#executable-geometry-rules) has measured spacing, port, canvas, and route rules for a diagnosed layout problem.
      
      ## Evidence and schema
      
      For a real repository, follow [Repository authoring](repository-authoring.md) while inspecting source. Freeze its credential-free origin and 40-character commit in `meta.repository`, attach inspected repository-relative `sources` to each key semantic node, and pass `--repo-root` to the first `finalize`. Each reference proves only the fact visible at that location. Follow material relationships and conditions to their actual source; do not reuse a startup citation as protocol or persistence evidence.
      
      Examples show field shape, not legal values or source facts. Read the mode schema and shared definition before adding a field, enum, or constrained text. In particular, inspect Architecture boundary kinds. Keep longer evidence in a card while retaining the fact. See [Schema lookup](authoring-contract.md#schema-lookup) for details.
      
      ## Presentation and modes
      
      Use one primary authored language from the user's choice or the request/conversation. Set `meta.locale` for built-in English (`en`) or Simplified Chinese (`zh-CN`); for other languages, including Spanish (`es`), supply `meta.translations` with reusable UI translations, or disclose the fixed Viewer UI and `<html lang>` English fallback. Keep exact product, code, protocol, command, API, and environment names while localizing surrounding explanation. See [Language consistency](authoring-contract.md#language-consistency) for bilingual cases.
      
      Omit `meta.visual_preset` for classic, `meta.subtitle` for a title-only header, `meta.legend` for truthful auto, and `meta.engineering_profile` for an ordinary system overview. Explicit styles and a subtitle require a user request. Use legend or deployment ownership under the [legend](authoring-contract.md#legend-contract) or [engineering profile](authoring-contract.md#engineering-profile-default) contracts. Branding is optional and explicit when a node names a real product; [Brand marks](brand-marks.md) gives lookup and capture rules for that branch. Never let a badge replace semantic type, label, or relationship facts. Set required `meta.output` to a portable POSIX-relative `.html` path within the working directory; see [Output path contracts](delivery-contract.md#output-path-contracts) for native path exceptions.
      
      For new Workflow use schema v2, preserving v1 for a fixed legacy source; use its [layout contracts](../renderers/workflow/README.md#layout-contracts) when lane or group geometry needs detail. For Sequence start with fixed columns; use `spread` when a wide viewBox leaves unused horizontal space or meaningful labels need width. For new Lifecycle use schema v2: every lane is its own row (`main` first, `terminal` last) and `col` `0..4` is the same x in every row, so place an interruption or exit in the column of the state it leaves; author the main path as transitions, omit `viewBox`, and keep transition labels short; a recoverable failure needs a real transition back. Read [Mode placement](authoring-contract.md#mode-placement) when a mode-specific placement or viewport problem needs more detail.
      
      `finalize` performs the browser gate. Keep the complete drawing comfortably readable on desktop, with zero horizontal overflow. Use meaningful vertical rows and intrinsic-height page scroll when necessary. The 6px projected-text check is a failure floor; at 1440px, aim for ordinary context text around 7.5px or larger. See [Automated browser evidence](delivery-contract.md#automated-browser-evidence) when viewport evidence fails.
      
    • brand-marks.md 3.3 KB
      # Brand marks
      
      Use a brand mark only when a real product, provider, model family, channel, or
      service identity helps the reader. Semantic `type` still explains what the node
      does; `brand` explains whose product it is.
      
      ## Agent decision path
      
      1. Search the built-in catalogue when the request names a recognizable brand:
      
         ```bash
         node bin/archify.mjs brands "Claude" --json
         ```
      
      2. Put the returned canonical ID in the node, participant, or state:
      
         ```json
         {
           "id": "planner",
           "type": "backend",
           "label": "Claude",
           "brand": "claude"
         }
         ```
      
      3. If there is no catalogue match and the user supplied the official website,
         capture its icon explicitly:
      
         ```bash
         node bin/archify.mjs brands capture "https://partner.example.com" --json
         ```
      
         Put the command's digest-pinned `brand` value in the authored node:
      
         ```json
         {
           "id": "partner",
           "type": "external",
           "label": "Partner portal",
           "brand": {
             "url": "https://partner.example.com",
             "sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
           }
         }
         ```
      
      4. If there is no match and no user-provided URL, omit `brand`. Do not invent a
         URL or silently assign a visually similar company.
      
      Known-brand URLs resolve to the bundled vector instead of using the network.
      For discovered icon `href` attributes, capture decodes the basic named references
      `amp`, `quot`, `apos`, `lt`, `gt` (and their defined uppercase aliases), plus
      decimal and hexadecimal numeric references, once before URL resolution. Thus
      `/icon.png?v=1&amp;size=32` requests `/icon.png?v=1&size=32`. URL percent escapes
      remain intact; nested escapes are not decoded recursively. This bounded decoder
      does not add a general HTML parser or support every named HTML entity.
      HTML reads stop at an explicit head ending outside comments, raw-text elements
      and quoted attributes, including when those tokens span network chunks. The
      256 KiB head limit and capture deadline still apply; a larger body after the
      head is not read for icon discovery.
      Unknown URL capture accepts only bounded raster image formats, blocks
      credentials, nonstandard public ports, and private or link-local destinations,
      uses bounded concurrency and one total deadline, and returns the captured
      content digest. Later render and validate operations require that exact digest;
      blocked, unavailable, changed, oversized, or unsafe content fails closed instead
      of silently changing the artifact.
      
      Page, icon and redirect requests send `Accept-Encoding: identity`. Capture does
      not decompress response bodies: a successful response declaring another content
      coding is closed and rejected explicitly. This keeps the existing byte limits
      and pinned digest tied to the unencoded representation. A later usable icon may
      still succeed; otherwise an encoding error is retained instead of being hidden
      by an unrelated favicon 404.
      
      The final artifact never fetches a brand asset when opened. Preset vectors and
      digest-verified captured site icons remain embedded in SVG, PNG, WebP, JPEG,
      Share Card, and WebM exports.
      
      Use `node bin/archify.mjs brands --json` to inspect all canonical IDs, aliases,
      categories, domains, and provenance. Current categories cover AI, cloud,
      engineering, data, collaboration, business systems, channels, languages, and
      frameworks.
      
    • delivery-contract.md 41.4 KB
      # Delivery contract
      
      ## Failed finalize and candidate repair
      
      `finalize` stops at the first non-passing gate. Use compact stdout or `evidence.summaryReceipt`; read its full sidecar only when the summary lacks evidence needed for a coherent repair. A receipt with four artifact checks is basic validation, not showcase acceptance: require all nine checks, zero composition errors, and zero warnings. Fix `meta.quality_profile` and schema errors before geometry.
      
      For a validation failure, edit the existing JSON in the connected neighborhood named by diagnostics before rerunning a command. Preserve requested semantics, meaningful labels, source evidence, and fixed or agreed topology. Several routes sharing nodes call for one placement repair; read [Architecture layout repair](architecture-layout-repair.md) for that case. Reflow a blocked main path rather than nudging unrelated labels. Keep unrelated geometry when its composition already reads clearly. Use `--layout-json` before editing only when compact evidence lacks needed measurements. Workflow v2 uses its stable compiler receipt, not solver internals, as authoring evidence.
      
      After the edit, rerun the complete `finalize` command with `--quality showcase` and, for repository-backed work, `--repo-root <repo-root>`. If the output path already has browser evidence from another candidate, use a fresh `--out-dir <output-stem>.review-<revision>` for both the new `finalize` and any `visual-check`. Omit an earlier `--candidate-sha256` after editing because it binds the previous candidate. Compare diagnostics by code, subject, stage, and evidence, never by declining error count alone. If an issue survives two focused repairs, inspect measured geometry or the relevant contract; after one evidence-based retry, report the concrete gap.
      
      Use standalone `validate` only for focused diagnosis, passing `--repo-root` for repository-backed work. Its passing receipt marks `candidateFrozen: true`; run `nextAction.arguments`, replacing only `<output.html>`, without editing, revalidating, or rereading the candidate. Retry later environmental or evidence failures against those frozen bytes. A measured reason to edit creates a new candidate and calls for the complete `finalize` without the old hash.
      
      ## Validate and deliver
      
      `render` and direct renderer entry points print classified authoring failures
      to stderr as readable diagnostics and exit 1. Input read/JSON parse failures
      use `input/read` or `input/json-parse`; output filesystem failures use
      `output/write` and identify the output path. Schema and layout failures keep
      their existing rule codes. Use the advertised `validate --json` or
      `deliver --json` interface for a machine receipt; `render` has no `--json` flag.
      Unexpected implementation failures retain debugging information in human
      mode and remain `internal/unclassified` in machine receipts.
      
      Each delivered output has two artifact-specific metadata paths. When an output
      stem is too long for those derived filenames, Archify shortens it and appends a
      stable hash:
      
      - `<output-stem>.delivery.json` records the latest completed attempt.
      - `<output-stem>.delivery-pending.json` is the recovery journal for an attempt
        in progress.
      
      For a literal artifact stem that already matches Archify's reserved bounded-name
      marker, a pre-namespace raw provenance sidecar remains a read fallback when the
      encoded sidecar is absent. A pre-namespace raw pending journal is an independent
      fail-closed barrier: it blocks checks and redelivery even when an encoded pending
      journal also exists, and neither journal is silently replaced.
      
      One directory-wide `.archify-delivery-lock.json` serializes every delivery that
      resolves into the same physical output directory. This deliberately prevents
      case, Unicode-normalization, Windows short-name, and symbolic-link aliases from
      creating independent owners for one filesystem location. The tradeoff is that
      deliveries to different artifact names in one directory also run serially;
      provenance and pending journals remain artifact-specific.
      
      For migration safety, Archify also detects and preserves a legacy
      `<output-stem>.delivery-lock.json` beside the requested artifact. An existing
      legacy entry is a fail-closed recovery barrier. While a new delivery owns the
      directory mutex, it also holds temporary legacy-format fences for the requested
      spelling and an existing artifact's physical target spelling. It acquires the
      directory lock first, then all required compatibility fences before writing a
      journal or artifact, and removes the directory lock before those fences during
      release. This blocks an older Archify binary using
      either known spelling from entering the delivery. A legacy fence whose raw
      HEAD-era filename exceeds the host component limit is omitted because the old
      binary could not create that lock or deliver that artifact on the host either.
      
      `deliver` acquires the lock by exclusive `open(..., "wx")` before creating or
      replacing the recovery journal. A successful exclusive create yields an
      internal opaque ownership capability bound to that attempt. Journal creation,
      failed-provenance recording, pair commit, rollback, journal finalization, and
      lock release each verify the current capability inside the operation that
      would mutate shared state. A rejected contender does not create a journal or
      write failed provenance.
      
      An existing directory or legacy lock is handled without automatic recovery:
      
      | Observed lock state | Required `deliver` result |
      | --- | --- |
      | No directory entry | Attempt exclusive creation; only its success grants ownership. |
      | Valid schema-v1 lock whose PID is running, or whose death cannot be established | Exit 1 with `delivery/concurrent-attempt`; preserve every shared path. |
      | Valid schema-v1 lock whose PID is known to have exited | Exit 1 with `delivery/lock-stale`; preserve the lock, artifact, journal, and current provenance exactly. |
      | Unreadable, malformed, symlink, dangling symlink, directory, or other non-regular lock entry | Exit 1 with `delivery/lock-invalid`; preserve the entry and every other shared path. |
      | An acquired capability no longer matches the current lock or journal | Exit 1 with `delivery/ownership-lost`; stop all shared-path mutation. |
      | The matching owner cannot remove its lock | Exit 1 with `delivery/lock-release`; preserve the lock. |
      
      A `delivery/lock-stale` diagnostic identifies the absolute output and lock
      paths plus the original PID and receipt ID. Recovery is deliberately explicit
      and serial: stop all delivery attempts for that physical output directory,
      confirm that no active delivery owns it and that the reported stale entry has
      not been replaced, remove only the reported lock, then rerun `deliver`. Do not
      remove an artifact, current provenance, or pending journal as part of
      stale-lock recovery.
      
      The lock protocol targets Node.js 18 or later on a local filesystem with
      cooperating Archify processes. PID, receipt, and file-identity comparisons are
      defensive checks, not an atomic compare-and-swap. Compatibility fences cover
      the requested spelling and an existing physical-target spelling; they cannot
      enumerate arbitrary hard-link names or previously unknown filesystem aliases,
      so mixed-version delivery through such aliases remains out of scope. This
      contract does not claim distributed-lock correctness on NFS, SMB, or other
      network filesystems, and it cannot prevent an external process that ignores
      the protocol from replacing shared paths.
      
      Every no-clobber HTML publisher (`render`, `deliver`, `compare`, and `preview`)
      captures the requested directory entry, canonical write slot, physical parent,
      and existing target type, device/inode identity, and mode before staging, then
      revalidates that snapshot immediately before replacement. An existing write
      target must be a regular file with exactly one hard-link name. A target with
      multiple hard-link names fails closed with `output/target-hardlinked`: replacing
      the requested name cannot update unknown sibling names as one publication.
      Hard links remain supported for read identity and input/alias collision checks;
      they are unsupported only as write targets. A symbolic link to a single-link regular
      file remains supported: publication preserves the symbolic-link entry and
      applies the same protocol to its resolved target. Directory, FIFO, socket,
      device, changing mode, new claimant, and indeterminate identity cases fail
      before replacement.
      
      Publication is no-clobber and recoverable, not crash-atomic replacement of an
      existing target. To avoid overwriting a claimant that appears after the last
      identity check, Archify first retains the bound old file in a private recovery
      backup, removes the public name through identity-bound quarantine, and then
      creates the new public name with an exclusive hard link. A caught failure rolls
      back when the public slot and recovery binding still permit it. A process
      interruption between those namespace operations can instead leave the public
      path absent while the verified previous bytes remain in an adjacent private
      recovery backup. Single-artifact publication records the original slot/alias
      identity and backup inode, mode, SHA-256, and byte count in private
      `.archify-remove-*/publication-recovery-v1.json`, beside `previous`. To make a
      specific interrupted publication visible again, stop concurrent writers and run:
      
      ```bash
      node bin/recover-output.mjs /absolute/path/to/.archify-remove-<id> --json
      ```
      
      This is explicit recovery, not a directory scanner. Before linking, the helper
      checks for a changed parent or alias, an altered/hardlinked record or backup,
      digest or inode mismatch, and any existing public target. It restores only by
      no-clobber hard link, so a new claimant is preserved rather than overwritten;
      it never recursively removes unknown entries. A completed recovery is
      idempotent. The record is evidence to be independently verified, not an
      authority to restore arbitrary private bytes: the helper accepts it only from
      the recorded generated child of the original physical target parent, with the
      same directory identity. Name the exact directory reported by the interrupted
      process and inspect an uncertain record manually. A non-cooperating process can
      still swap pathnames after those checks and before Node.js `linkSync`; Node does
      not expose a descriptor-bound link operation. Post-link identity verification
      then fails closed and retains recovery evidence, rather than claiming recovery
      or deleting an uncertain name. If recovery itself is interrupted after the
      link, the old public bytes and private backup can both remain; a later recovery
      run preserves the public target and needs explicit operator resolution. The
      record is fsynced before the old public name is retired on platforms supporting
      directory sync, and the tested guarantee is recovery after a killed process;
      this is not a claim of power-loss, storage-controller, NFS, or SMB durability.
      Paired flows retain their backup in private transaction staging. For `deliver`,
      the pending journal and lock keep strict checkers fail-closed. The portable
      Node.js filesystem API has no pathname
      compare-and-swap that both replaces an existing name atomically and refuses to
      overwrite a late claimant: `rename` would close the visibility gap only by
      overwriting that claimant.
      
      After ownership is established, `deliver` creates the journal before rendering
      and keeps it through the recoverable HTML/sidecar pair commit. It removes the
      journal only after that commit completes. A validation, render, or pair-commit
      failure, or a process interruption, may therefore leave a journal. The journal
      is a safety barrier: `check`, `browser-check`, and `visual-check` fail closed when any directory
      entry exists at the journal or lock path, including an unreadable file,
      symlink, or dangling symlink. Run deliveries targeting the same physical output
      directory serially; one attempt must finish or be recovered before another
      begins.
      
      A successful sidecar has `schemaVersion: 1`, `status: "current"`,
      `command: "deliver"`, a unique `receiptId`, the diagram `type`, an absolute
      `input` path, an absolute `output` path matching the inspected
      artifact, and specification/artifact SHA-256 and byte counts. Checkers treat a
      missing, malformed, unsupported, or inconsistent field as invalid. They also
      reject a sidecar symlink, including a dangling one. A checker binds provenance
      to the artifact bytes it actually checks and verifies that binding again before
      reporting success; a concurrent byte change fails. The provenance directory
      entry itself must be a single-link regular file: `deliver` and strict check fail
      closed with `delivery/provenance-hardlink-unsupported` when it has another hard
      link, without scanning for or guessing the sibling name.
      
      If a currently verified owner fails after an older HTML exists, Archify writes
      a new `status: "failed"` sidecar and leaves the journal until recovery is
      complete. An unreadable old HTML does not prevent that marker; its artifact hash
      and byte count may be absent. If the sidecar is locked or otherwise unwritable,
      Archify keeps the prior sidecar rather than deleting evidence, and the journal
      prevents checkers from trusting it. A rejected concurrent, stale, or invalid
      lock attempt does not write failed provenance. If ownership is lost, Archify
      reports `delivery/ownership-lost`, does not overwrite or remove the successor's
      artifact, provenance, journal, or lock, and does not claim recorded failed
      provenance; a failure receipt may report `provenance: "unrecorded"`. If every
      metadata path is unavailable, the same unrecorded status applies; no tool can
      preserve that fact across processes. Restore metadata-path access and complete
      a successful `deliver` before trusting the output.
      
      Artifacts with no sidecar, journal, or lock remain supported for backward
      compatibility and for the lower-level `render` command. Their checker receipts
      report `provenance: "unknown"`; use `--require-provenance` to turn that state
      into a non-zero failure when the workflow requires a successfully delivered
      artifact:
      
      ```bash
      node bin/archify.mjs check <output.html> --require-provenance
      node bin/archify.mjs browser-check <output.html> --json --require-provenance
      ```
      
      ## Output path contracts
      
      Archify intentionally separates durable authored paths from command-line paths:
      
      - Required authored `meta.output` is a portable POSIX-relative path such as
        `reports/diagram.html`. It uses `/`, ends in a non-empty `.html` basename,
        and cannot contain an absolute or drive-relative prefix, URI, backslash,
        empty or dot segment, control character, unpaired UTF-16 surrogate, Windows
        alternate-data-stream separator or invalid filename character, trailing dot
        or space, DOS device name, or a component over either the 255-byte UTF-8 or
        255-code-unit UTF-16 limit. It resolves from the current working directory
        and must remain physically inside that directory, with an `.html` target,
        after symbolic links are followed. The durable output/archive profile also
        conservatively rejects a Windows 8.3 short-name shape such as `PROGRA~1`;
        descriptive repo/Git POSIX paths use a separate profile and are exempt.
      - Explicit CLI output arguments use the active host's native syntax. They may
        be relative or absolute, use native separators, and resolve outside the
        current working directory. On Windows, ordinary drive-absolute, UNC, and
        relative paths (including ordinary `.` and `..` navigation) are supported.
        A system-resolved 8.3 spelling of an existing file or directory is accepted
        when Archify can prove its physical identity; this native alias support does
        not relax the durable output/archive profile's 8.3-shaped-name rejection.
        Extended-length paths are limited to raw backslash-only `\\?\C:\...` and
        `\\?\UNC\server\share\...` forms without dot segments; device namespaces,
        malformed roots, drive-relative paths such as `C:file.html`, current-drive
        roots such as `\file.html`, alternate data streams, reserved device names,
        invalid or trailing filename characters, and overlong components fail
        closed. POSIX CLI paths retain POSIX filename rules rather than inheriting
        Windows spelling restrictions. Every host rejects NUL, unpaired surrogates,
        and components that exceed its supported bound.
      
      These contracts are not interchangeable: an explicit CLI output does not hide
      an invalid durable `meta.output` (including a missing value), and `validate`
      checks the authored output even when it does not publish to that path. A
      workflow v1-to-v2 migration may explicitly receive a portable durable
      replacement through `migrate workflow old.json new.json --to-schema 2 --output
      reports/diagram.html`; that value is written only to its separate verified v2
      destination. This migration-candidate exception does not repair the source or
      bypass any non-output schema or compiler error. For every other repair, add a
      portable POSIX-relative `.html` path to `meta.output`; no schema-version change
      is otherwise required.
      
      Run `finalize` directly on a complete first candidate and after every repair edit. Its embedded validation checks the candidate before delivery; use standalone `validate` only for focused diagnosis. After an edit, omit any earlier `--candidate-sha256`, which binds the previous candidate. CLI HTML output paths must end in
      `.html`, including after symbolic-link resolution. Compare receipt paths must
      end in `.json`. A type mismatch fails before writing with
      `output/cli-extension` or `output/cli-resolved-extension`. These checks prevent
      accidental file-type overwrites; they do not sandbox explicit CLI directories
      or prevent replacement of an existing artifact of the expected type.
      
      Use final verified delivery only after the candidate is frozen:
      
      ```bash
      node bin/archify.mjs deliver <type> <candidate.json> <output.html> --quality showcase --json
      ```
      
      Deliver reads the specification once, writes those exact bytes to a private same-directory candidate snapshot, renders that snapshot, runs the complete artifact checker, and only replaces the target after all artifact checks pass. The JSON receipt includes SHA-256 and byte counts for both `specification` and `artifact`.
      
      For the ordinary agent handoff path, prefer the finalizer:
      
      ```bash
      node bin/archify.mjs finalize <type> <candidate.json> <output.html> --quality showcase --json
      ```
      
      `finalize` invokes verified `deliver` once, reuses its embedded showcase
      validation result, then runs strict `check --require-provenance` and
      `browser-check --require-provenance`. It stops at the first failed or skipped stage
      and preserves that stage's full receipt. Its stdout is one compact JSON
      object with gate statuses, bounded actionable diagnostics, artifact identity,
      and evidence paths. The same compact object is written atomically to
      `<output-stem>.finalize-summary.json`; use that file for normal failure repair.
      Complete stage receipts and timings remain available for auditing in
      `<output-stem>.finalize.json`. With `--out-dir`, both files are written there;
      `--receipt <path.json>` overrides the full receipt path and derives a distinct
      `<path>-summary.json`. Read the full receipt only when the compact summary is
      truncated and its shown subjects and evidence cannot identify a coherent local
      repair, or when complete audit evidence was explicitly requested. The compact
      receipt reports `visualReview: "not-requested"`; the automated gate does not create images or require a perceptual reviewer. A compact `visualReviewRecommendation` retains positive crossover and route-detour metrics from the strict check so the author can apply the review escalation below without reading the full receipt. A recommendation does not change the machine exit code or claim that review happened. Its `affectedRoutes` identifies crossing pairs and detours (up to eight of each, with a truncation flag); the full strict-check `composition.routeReview` retains all affected relationships. Use these IDs to trace the routes in the captured default viewport. Detours may include `directCorridorBlockers`, identifying nodes between aligned endpoints. These are geometric review clues, not new validation failures or inferred main-path semantics. For a blocked main path or several tangled routes, follow [Architecture layout repair](architecture-layout-repair.md) and reflow the connected scene before tuning individual sides or labels. Preserve every semantic fact; retain unrelated positions only when their surrounding composition is already accepted.
      
      For a measured automatic Architecture with a large unused leading area, the
      compact receipt may include `layoutReviewRecommendation`. Its
      `composition.leadingSpace` evidence accounts for nodes, boundary titles,
      routes and labels. Check whether that space is intentional; if not, reposition
      the connected scene while preserving meaning and user-fixed geometry, then
      finalize again. This suggestion changes no gate or exit status and requires
      no screenshot. A fixed canvas or uncertain measurement receives no suggestion.
      
      A passing finalizer receipt is sufficient evidence for all four gates. Merely
      naming the gates or requiring each one to pass does not require replaying their
      standalone commands. Replay an individual command only when the request
      explicitly requires separate executions or focused failure diagnosis needs it.
      
      The individual commands remain authoritative and backward compatible. Use
      them directly for focused diagnosis, recovery, or when only one gate is
      required. A finalize failure does not relax any gate and does not turn a
      preserved older artifact into a current successful delivery.
      
      `finalize` overlaps private Chrome startup with delivery and strict checking.
      It loads the artifact only after those gates pass and current provenance is
      verified. The browser gate retains every viewport, theme, and stability check;
      the browser closes at completion or an earlier failure. Its full stage receipt
      records `execution: "in-process"` and the equivalent standalone `command` for
      replay. Use total finalize duration to compare performance because Chrome
      startup overlaps the earlier stages.
      
      The pair commit is recoverable, not a claim that two filesystem paths change
      atomically or are durable across power loss. Journal finalization is part of
      that commit: a caught failure while verifying or removing the journal rolls
      back the replaced files when possible and while ownership remains current. If
      ownership is lost, the old attempt immediately stops renaming, rolling back,
      finalizing the journal, recording failure provenance, or cleaning up shared
      paths. Any private staging or recoverable backups remain available and are
      identified by the failure diagnostic. If restoration fails for another reason,
      the failure receipt likewise identifies retained backups for recovery. A
      process interruption can leave the journal, backups, or private staging behind;
      checkers then fail closed. Follow the reported recovery evidence before rerunning
      `deliver` serially on the same output. A failed attempt exits non-zero and never invokes an opener; it never
      authorizes visual evidence collection.
      
      If exclusive creation succeeds but lock initialization fails, Archify may
      record failed provenance and remove the incomplete lock only while its
      capability still identifies that exact entry. A replacement is preserved.
      Filesystem and cleanup errors are reported separately from an active concurrent
      delivery. An active, stale, unrecognized, or otherwise preserved lock
      independently prevents checkers from accepting the prior artifact. Fix the
      reported filesystem error before retrying, and use another physical output
      directory if the lock path contains unrelated data.
      
      Lock release is part of delivery completion. If the artifact/provenance pair
      has committed and the journal has finalized but the matching lock cannot be
      removed, `deliver` exits 1 with `delivery/lock-release`, preserves the lock,
      does not print a success receipt, and does not invoke an opener. The preserved
      lock keeps strict checkers fail-closed. Only after pair commit, journal
      finalization, and lock release all succeed may `deliver` exit zero, print its
      success receipt, or run `--open`.
      
      Run strict `check` after `deliver` exits zero. Run `browser-check` or optional
      `visual-check` only after that strict check exits zero. A failed marker,
      recovery journal, or delivery lock makes every checker fail before accepting
      the preserved HTML; report the diagnostics and complete a successful recovery
      delivery before collecting new browser evidence.
      
      The delivery interface exposes four separate claims:
      
      1. `deliver` proves deterministic artifact checks and byte identity.
      2. `browser-check` collects required automated browser evidence from the exact artifact without capturing images.
      3. `visual-check` optionally adds artifact-bound screenshots and a contact sheet.
      4. Perceptual visual review records a human or image-capable reviewer's judgment.
      
      Passing one claim never implies the others. Never claim that the deterministic receipt includes browser or perceptual review evidence.
      
      ## Recovering a failed comparison
      
      `compare` commits an HTML artifact and its JSON receipt as a pair. If that commit
      fails, it attempts to restore the previous files. A complete rollback removes
      the temporary directory as usual.
      
      If a previous file cannot be restored, compare exits non-zero with
      `delta/commit-rollback-failed` and retains the recovery directory. In the JSON
      failure receipt, `diagnostics[].evidence.recoveryDirectory` identifies that
      directory and `recoveryFiles` lists `{ backup, target }` paths for the files whose
      restoration failed. Human-readable diagnostics also print the recovery paths.
      
      Resolve the filesystem error, inspect the current targets, and restore each
      listed backup to its corresponding target before retrying. Keep the recovery
      directory until both previous files have been recovered and verified; it can
      also contain rejected candidate files, which must not be mistaken for backups.
      Successful comparisons and failures before commit retain their normal cleanup.
      
      ## Automated browser evidence
      
      `finalize` runs the required browser gate against the exact trusted HTML without
      rerendering or modifying it. For focused diagnosis, the equivalent standalone
      command is:
      
      ```bash
      node bin/archify.mjs browser-check <output.html> --json --require-provenance
      ```
      
      The zero-dependency command uses Chrome/Chromium through the DevTools pipe. It
      measures light-theme containment at 1440×900, 1600×1000, 1920×1080, and
      2048×1320, and verifies the requested light theme at all four viewports, the dark
      theme at both endpoints, and READ/Still runtime states. A requested theme that
      resolves to a different theme fails with measured evidence. It creates one
      `<output-stem>.browser-check.json` receipt and no screenshots or contact sheet.
      Pass `--out-dir <dir>` to place the receipt in a separate evidence directory.
      The receipt binds the artifact SHA-256 and byte count, identifies
      `evidenceKind: "automated-browser"`, and reports
      `visualReview: "not-requested"`.
      
      Horizontal overflow always fails. Normal document-level vertical scrolling is
      accepted only with a renderer-declared contract and measured readable text.
      Automatic canvases declare `data-reader-fit="intrinsic-height"`; their adaptive
      Reader must reach its readable width and expose `data-reader-overflow="authored"`.
      Architecture with an explicit `meta.viewBox` instead declares
      `data-diagram-type="architecture"` and `data-reader-fit="authored-height"`:
      its SVG coordinates, aspect ratio and existing Reader width behavior stay
      unchanged. Its full SVG must remain inside the diagram panel without internal
      scrolling or clipping, and the document must permit vertical scrolling.
      The receipt records `verticalScrollAccepted: true` and
      `overflowDisposition: "readable-vertical-scroll"`. Missing or unknown declarations,
      explicit viewBoxes in other modes, unreadable text, horizontal overflow,
      clipping and Viewer chrome collisions remain failures. Do not add an internal
      diagram scroller or hide overflow.
      
      `browser_evidence` in the handoff records only the outcome of this automated
      command:
      
      - `passed` maps from exit 0 and receipt `status: "pass"` after every required measurement completes and passes.
      - `failed` maps from exit 1 and receipt `status: "fail"` when the inspection finds a defect, the command fails, or a runtime error leaves the evidence incomplete.
      - `skipped` maps only from exit 2 and receipt `status: "skipped"` when Chrome/Chromium is unavailable and the inspection does not run.
      
      Runtime failures leave incomplete evidence and must not be normalized to
      `skipped`. They do not invalidate an already successful deterministic delivery.
      Retry an environmental failure in a browser-capable execution context when
      practical. Keep the packaged transport unchanged unless the failure reproduces
      through that seam in a capable environment.
      
      A provenance failure exits before browser inspection and persists a failed
      browser-check receipt bound to the attempted artifact. If the failure receipt
      cannot be written, the diagnostic names that incomplete evidence.
      
      Both browser commands inspect the exact delivered HTML without modifying or rerendering it.
      
      ## Sequence width review
      
      A passing `finalize` may report `layoutReviewRecommendation.action: "inspect-sequence-width"`. Its `evidence` measures the fixed participant columns' unused right-hand space after accounting for message labels, notes and segment titles. This advice adds no warning, failure, screenshot requirement or automatic geometry change.
      
      For a newly authored candidate with omitted `meta.column_fit` and no user-fixed column geometry, save the candidate, set only `meta.column_fit` to `"spread"`, and rerun the complete `finalize` once with `--out-dir <folder>/width-review`. Keep participant order, messages and their y positions, labels, notes, sources and canvas dimensions. If that attempt fails, restore the candidate and finalize it with `--out-dir <folder>/width-restore`; report the remaining layout suggestion rather than iterating. Preserve an explicitly fixed layout or a supplied legacy candidate and disclose the suggestion without changing it. This review is about horizontal composition; a passing receipt still does not claim perceptual approval.
      
      ## Optional capture evidence
      
      `visual-check` remains backward compatible for a requested or escalated
      perceptual review:
      
      ```bash
      node bin/archify.mjs visual-check <output.html> --summary --require-provenance
      ```
      
      `--summary` returns compact JSON with all diagnostics and absolute paths to the complete receipt, contact sheet, and every screenshot. For a chosen visual review, inspect the relevant captures; capture success is not perceptual approval. `--json` retains the full receipt output for existing consumers. Both modes run the same checks and keep the same exit status. If cleanup fails after publication, the summary retains the final failure diagnostics and `publication` recovery details; the linked receipt records the earlier committed evidence.
      
      It performs the same automated browser measurements, captures light/dark
      screenshots at 1440×900 and 2048×1320, and writes four viewport PNG sidecars,
      one relative-path HTML contact sheet, and one JSON receipt. `--out-dir <dir>` moves all of these sidecars together.
      Open the HTML contact sheet in a browser or inspect the viewport PNGs with an image reader. Its receipt reports `visualReview: "pending"` because captures do not themselves
      make a perceptual judgment. Capture and provenance failures follow the ownership rules below.
      
      The receipt, contact sheet, and four PNGs form one owned evidence set. Before
      capture, `visual-check` freezes every requested directory entry, its
      canonical write slot and physical parent, and the target's absent/file state,
      type, device/inode identity, and mode. Hard-linked evidence targets are not safe
      write targets. All candidate files are created exclusively inside one random,
      private staging directory beneath the physical evidence directory; the receipt
      is published last. Each staged candidate must have exactly one hard-link name
      before publication. The no-clobber publish link temporarily gives the staged
      and final names a link count of two; unlinking the verified staged name must
      leave the final entry with a link count of one. An unexpected external hard
      link fails closed and its alias is never removed.
      
      Chrome inspects one identity- and content-checked copy of the captured artifact
      in a private local temporary directory, so browser file loading does not depend
      on UNC or long-path support. The six publication candidates remain on the
      evidence volume. Both temporary directories are cleaned without recursively
      deleting unknown contents; retained entries include their recovery locations.
      
      Immediately before committing anything, `visual-check` re-resolves and verifies
      the complete six-path set. An absent-path claimant, existing-path replacement,
      symbolic-link or dangling-link retarget, parent-topology change, hard link, or
      indeterminate identity fails closed with `viewer/evidence-path-conflict`. The
      claimant and every other final evidence path remain untouched. Cleanup removes
      only this run's staged or published entries after rechecking their captured
      identities; a changed or unknown entry is preserved.
      
      An existing visual evidence set is replaceable only when a regular
      `visual-check` receipt proves ownership of the same artifact and evidence
      directory, and its exact sidecar manifest matches every existing contact-sheet
      or PNG byte count and SHA-256 digest. A missing, malformed, unknown, mismatched,
      or incomplete ownership record never authorizes deletion. Failed and skipped
      runs retire prior screenshots/contact sheets only as part of the same verified
      transaction when that ownership proof succeeds; otherwise they preserve all
      unknown evidence and report `viewer/evidence-path-conflict`.
      
      This rule also applies when Chrome is unavailable or provenance fails before
      browser inspection: neither path may blindly delete stale-looking evidence. A
      verified owned set may be recoverably retired before publishing a skipped or
      failed receipt; unowned evidence remains intact. These outcomes do not invalidate an already
      successful deterministic delivery and do not turn a perceptual visual review
      into passed or failed. Retry an environmental failure through the supported
      command in a browser-capable execution context when practical. Keep the
      packaged transport unchanged unless the failure reproduces through that seam in
      a capable environment.
      
      `browser-check` applies the same private-snapshot, identity, ownership, and no-clobber rules to its single JSON receipt. Its namespace is separate from `visual-check`, so a browser-only rerun cannot remove capture evidence.
      
      ## A new candidate at an existing output path
      
      Browser evidence belongs to exact artifact bytes. After editing a candidate whose previous HTML already has browser evidence, choose a fresh evidence directory before running the next `finalize`; this preserves the old receipts and captures without an avoidable ownership-conflict retry:
      
      ```bash
      node bin/archify.mjs finalize architecture candidate.json diagram.html --quality showcase --repo-root <root> --out-dir diagram.review-2 --json
      node bin/archify.mjs visual-check diagram.html --out-dir diagram.review-2 --summary --require-provenance
      ```
      
      Keep the requested HTML path stable. Use a new revision directory for each changed candidate, and retain the same directory for retries of unchanged bytes. For a diagram without repository evidence, omit `--repo-root`. Let the commands create their output directory. A prior validation failure that produced no HTML or browser evidence needs no new directory. Never remove unknown evidence to make a retry pass.
      
      ## Optional opening
      
      Add `--open` only when the user wants an immediate local preview. It runs after
      the verified pair commit has completed, its recovery journal has been removed,
      and the delivery lock has been released successfully. It uses one argument-array
      OS opener with a five-second bound on macOS and Linux, and a fifteen-second bound
      for PowerShell startup on Windows. The receipt records `open.status`; failed or
      unavailable launch attempts also include normalized `open.failure` details.
      Keep it off for CI, unattended agents, and non-interactive environments.
      Failure or unsupported opening does not invalidate delivery; its
      status proves only whether the local opener invocation succeeded.
      
      ## Last-Good Live Preview
      
      For an active desktop authoring loop only:
      
      ```bash
      node bin/archify.mjs preview <type> <input>.json <output>.html --quality showcase
      ```
      
      Preview watches one explicit input on loopback, binds each stable digest to a private snapshot, and advances only after the existing verified delivery pipeline passes. Invalid, half-written, deleted, or superseded input leaves the previous verified revision on screen and on disk. Identical bytes do not rebuild or reload.
      
      The preview runtime ships inside the zero-dependency Skill ZIP and must work without `node_modules`.
      
      Never start it by default. Do not use it for CI, unattended agents, remote sharing, or mobile use. `--no-open` is only for a user who will open the printed local URL or for loop testing. Stop it with Ctrl-C before handoff. The first Ctrl-C drains the active delivery without publishing it; a second Ctrl-C forces shutdown of both delivery processes and HTTP connections, including incomplete requests. Shutdown preserves the last verified artifact and removes only staging files whose ownership can be verified. If delivery is interrupted before its receipt reaches Preview, unconfirmed files and recovery material may remain in the private staging directory; shutdown does not recursively delete unknown contents. Server state, port, source path, diagnostics, error text, and reload tokens must never enter the generated artifact or any export.
      
      ## Perceptual review
      
      The automated path ends with the deterministic browser gate and reports
      `visual_review: not_requested`. Ordinary generation does not require screenshots
      or an image-reading step, including newly authored or repositioned Architecture.
      Perceptual review is optional; use it for an explicit request or a concrete visual
      investigation. Possible reasons include:
      
      - the compact finalizer includes `visualReviewRecommendation` for crossings or detours (advisory, not a delivery gate);
      - the user explicitly requests an aesthetic or visual review;
      - a template, renderer, or Viewer change needs visual regression evidence;
      - a novel layout or browser diagnostic leaves low confidence;
      - the run is selected for sampled audit or dogfood.
      
      For the default standalone desktop viewer, measure 1440×900, 1600×1000, 1920×1080, and 2048×1320. Require `document.documentElement.scrollWidth <= window.innerWidth` at every checked size. Prefer `scrollHeight <= window.innerHeight`; accept page-level vertical scrolling only through the Reader-declared readable exception defined above. At the largest checked viewport, inspect the rendered composition for a conspicuous empty lower band: the main panel and necessary conclusion cards should use the available height as a balanced whole, not collapse into a shallow strip. For unexpected overflow, repair the authored composition by removing only genuinely redundant content or compacting spacing before shrinking nodes, labels, or the main panel. Do not hide overflow, clip content, introduce an internal diagram scroller, or reduce node/label typography to make the measurement pass. Narrow/mobile containment may retain vertical page scrolling.
      
      For an escalation, run `visual-check` on the current finalized artifact, inspect
      its contact sheet with a capable image reader or human, and check both endpoint
      themes, the default READ view, line crossings/corridors, label masks, node/card
      fit, focus/search/passport closure, and export cleanliness. This review is
      supplementary and never changes `browser_evidence`. An unconstrained browser
      glance can support perceptual review only.
      
      Report one truthful optional-review status:
      
      - `visual_review: not_requested` — no review trigger applies; this is not a visual acceptance claim.
      - `visual_review: passed` — only after inspecting the rendered artifact.
      - `visual_review: skipped (image reader unavailable)` — a requested or triggered review could not run.
      - `visual_review: failed` — with the concrete visible defect.
      
      For an escalated review, use `correction_rounds: 0`, `correction_rounds: 1`, or
      `correction_rounds: 2`; never exceed two focused correction rounds. When review
      is not requested, use `correction_rounds: 0`. Never report
      `visual_review: passed` without inspecting the artifact. If perceptual review
      changes the candidate, rerun `finalize` because the previous specification and
      artifact receipts are no longer current.
      
      ## Handoff receipt
      
      Return:
      
      ```text
      diagram_type: architecture|workflow|sequence|dataflow|lifecycle
      output: /absolute/path/to/file.html
      specification_sha256: <receipt value>
      artifact_sha256: <receipt value>
      validation: 9/9 showcase, 0 errors, 0 warnings
      browser_evidence: passed|failed|skipped
      visual_review: not_requested|passed|skipped (image reader unavailable)|failed
      correction_rounds: 0|1|2
      ```
      
      Derive `browser_evidence` only from the latest artifact-bound `browser-check`
      receipt, normally the stage embedded by `finalize`. Record optional capture or
      manual browser work separately with its artifact binding, viewport/theme scope,
      and observations; never use it or `visual_review` to overwrite the automated
      status.
      
      Opening, preview status, Share Cards, and other viewer exports are not validation claims.
      
      Finalize receipt publication uses the same identity-bound, no-clobber publisher and explicit recovery records described above. The full and summary receipts must be distinct from the candidate, artifact, delivery metadata, and browser receipt. Their targets must be absent or single-link regular files; symlink receipt entries and hardlinked targets fail closed. A later claimant or changed parent stops publication and remains untouched. Default receipt names share the physical artifact namespace and are bounded for the host filename limit. The two receipts are published individually, not as a crash-atomic pair; only a completed passing command is a successful handoff.
      
    • repository-authoring.md 6.4 KB
      # Repository-backed architecture authoring
      
      Use this reference when a diagram must explain a real repository. The source is
      the authority for responsibilities, calls, boundaries, and persistence. The
      diagram is complete when the requested meaning is covered and every asserted
      fact has supporting source evidence.
      
      ## Explore on demand
      
      1. **Freeze identity.** From the target repository, record `git rev-parse
         HEAD`, `git remote get-url origin`, and `git status --short`. Remove HTTP(S)
         userinfo (including usernames, passwords, and tokens) before recording the
         origin or placing it in the candidate. Preserve its transport, port, path and
         `.git` suffix; do not rewrite an internal SSH origin as HTTPS. Pin the credential-free URL and
         forty-character revision in `meta.repository`. Use `link_mode: "local-only"`
         for an SSH origin, unsupported forge, intentionally local-only source links,
         or a local fixture whose HTTPS URL is only a repository identity; retain the
         URL and revision. Web links require a supported GitHub or Gitee HTTPS origin. If the
         worktree is dirty, record the changed paths. Repository evidence is verified
         against committed bytes at the pinned revision, not working-tree edits:
         inspect a clean checkout at that revision for any cited changed path. Do not
         present uncommitted bytes as evidence for `HEAD`; `local-only` does not record
         a verifiable snapshot of those bytes.
      
      2. **Map the slice.** Use project instructions, manifests, entry points,
         registrations, and deployment configuration to locate candidate runtime
         units. Read the entry, configuration, and modules relevant to the request.
         Follow imports and call sites
         until the requested responsibility reaches its actual input, output, or
         side effect. Read a small connected slice instead of scanning the repository
         for a convenient label.
      
      3. **Trace ownership.** Derive runtime and I/O relationships from the observed
         actor, operation, and target at their call sites; deployment and trust
         relationships use the corresponding configuration or enforcement evidence. Distinguish the controller requesting
         an operation from the runtime that executes it and the store receiving bytes.
         For a file or database edge, the source must identify its actual reader or
         writer; a responsibility statement such as “maintains tasks” does not prove
         direct I/O. Keep these facts with the source locations while reading, without
         a separate planning artifact. Choose which distinctions need separate
         nodes using [Composition and meaning](authoring-defaults.md#composition-and-meaning);
         discovering an implementation role does not automatically add it to the overview.
         A configured provider, an injected adapter, a local stub, and a durable
         service are different claims; label the one the source supports.
      
      4. **Record evidence while reading.** Keep exact repository-relative paths and
         inclusive line ranges for each component and meaningful relationship. Follow
         actual branches, retries, fallbacks, and error handling. A function that is
         exported or configured but never called by the normal path is an optional
         capability, not a required runtime edge. For a claim about authoritative
         state change or control ownership, trace to the actual write or execution
         site and the conditions that permit it; an upstream caller alone does not
         establish those conditions.
      
      5. **Name uncertainty.** Write unresolved questions beside the claim they
         affect: for example, “`writeFile` is called here; durability is unknown.”
         Resolve a question by reading the next relevant source range or preserve it
         as an explicit unknown. Never turn a label, package description, or config
         value into an unobserved service or behavior.
      
      Stop exploring when every requested responsibility, relationship, and boundary
      has supporting source entailment and the remaining unknowns cannot change that
      coverage. There is no node, edge, citation, view, card, or boundary count to
      hit. Do not add a summary step merely to signal completion.
      
      Batch independent relevant files when known. Each additional read should answer
      an unresolved question that can change the diagram. Reuse concise facts and
      their source ranges already verified in this task; across revisions, recheck
      the affected entry points, configuration, dependencies, and evidence.
      
      ## Choose an example by structure
      
      Select the main example in the [Type router](../SKILL.md#type-router) before
      loading its content, using the request and repository metadata already needed
      for source inspection. Selection fits the existing read batch and needs no extra
      message, command, or repository-wide scan. For mixed or unclear tasks, use the
      requested responsibilities and entry points as they become known in normal
      inspection; keep their actual roles. Read another example when a necessary
      capability remains unexplained. Examples teach shape, not facts: a library need
      not acquire filesystem nodes, and finished showcases still follow the
      first-draft automatic-routing rule.
      
      ## Author from evidence
      
      Use the mode's complete JSON shape, including repository identity,
      components, and connections; every repository-backed component needs supporting source
      references, while boundaries or cards are added only when they
      answer a real reader question. Let automatic routes and automatic
      viewBox sizing work first. Keep the primary path readable, put exception paths
      beside their owner, and leave filesystem stores outside a control boundary when
      the source shows a separate responsibility.
      
      An existing example teaches field shape, not facts or arbitrary values. It does
      not authorize a new boundary kind, a long note, a viewBox size, or a route
      control. Consult the specific mode schema and `schemas/common.schema.json`
      whether or not the selected example already contains the field; use the
      schema's enum, length, identifier, and repository rules. Architecture
      boundaries currently use `kind: "region"` or `kind: "security-group"`; source
      references use `path`, `line`, and optional `end_line`.
      
      Repository-backed components need concise, truthful `sources` references. Preserve
      control ownership when summarizing filesystem I/O: the code that reads or writes
      a file owns that action, while a pure in-memory transform receives and returns
      values. This fact-check does not require a separate overview node for every helper. Use the existing examples for valid field shape, then replace all
      identifiers, wording, source paths, and claims with inspected repository facts.
      
    • update-awareness.md 1.3 KB
      # Update awareness
      
      Read this file when a `finalize` or standalone `deliver` receipt has `update.noticeRequired: true`.
      
      Keep one compact line in the final response, in the user's language, with `installedVersion`, `availableVersion`, and the official `releaseNotes` link. Say that the installed Skill has not changed and that the user can ask to snooze or ignore the reminder. If `source` is `cache`, say that a previous check at `checkedAt` found the update. A process message or tool output does not replace this final line.
      For `severity: "security"`, label it as a security update without making installation automatic or urgent by default.
      
      You may translate the fixed local `noticeText`. Never quote, summarize, or translate the remote manifest's summary.
      
      When the user explicitly asks to pause or stop this reminder, run `node scripts/check-update.mjs --snooze "<eventKey>"` (seven days) or `--ignore "<eventKey>"` (this exact release only) from the Skill directory with the receipt's `update.eventKey`, then report the returned status. Never run them on your own initiative; `--ack` is a no-op. These commands do not install an update, and a newer release notifies again.
      
      The notice is information, not permission. Keep the installed version unchanged. This workflow never downloads, installs, or executes an update, and silence is never consent.
      
    • viewer-runtime.md 3.2 KB
      # Viewer Runtime reference
      
      Read this only when the user asks for a reader-facing capability. Ordinary generation does not require implementing or re-documenting these features; they are already in the generated HTML.
      
      ## Exploration
      
      - Diagram Guide lists current actions and shortcuts.
      - Reading Depth starts at READ at the default 100% scale, reveals FULL detail at 175%, and falls back to MAP only below 100%. Focus, route, and semantic interactions reveal their exact facts at any scale.
      - Semantic Lens summarizes selected node/relationship kinds without changing authored geometry.
      - Intent Trace previews a fine-pointer or keyboard target before committed focus.
      - Node Finder searches labels and stable IDs.
      - Semantic Passport opens on focus, shows authored upstream/downstream facts, supports a copyable deep link, has an explicit close action, closes on true outside activation and Escape, and never enters canonical export.
      - Semantic Radar mirrors the visible viewport and authored graph without becoming a second source of truth.
      - Direct Relationship Pin makes a unique compiled relationship operable while preserving the authored line and stable relationship identity. It must fail closed on conflicting source/target/label/ID metadata.
      - Route Probe resolves exactly two endpoints over authored directed relationships. It never infers a route from geometry.
      
      ## Motion and presentation
      
      `meta.animation: "trace"` enables a finite reader-controlled Live/Still trace. Static is the default. Still, reduced motion, page hiding, print, and canonical export preserve complete static meaning. Presentation Stage changes viewer chrome and framing, never authored geometry. This is not a mobile product feature; narrow layouts get containment only.
      
      ## Canonical exports
      
      The export menu can copy/download full-diagram PNG, download JPEG/WebP, download a dual-theme SVG, and record a trace-enabled WebM. Viewer state—Guide, Lens, finder, focus, route, camera, radar, presentation, motion ownership, and temporary overlays—must be removed from canonical export.
      
      ### Route Share Card
      
      After a real directed Route Probe resolves, the reader may use **Export → Route Share Card**. It reuses the exact ordered route snapshot and the shared Share Card seam: `format=share-card`, `variant=route`. The isolated clone may use only static `data-share-route-*` decoration. It is download-only, fails closed for stale/unreachable/conflicting routes, and never becomes the canonical artifact.
      
      ### Reach Share Card
      
      After a non-empty authored reachability query, the reader may use **Export → Reach Share Card**. It consumes the already resolved upstream/downstream node and edge set without rerunning traversal: `format=share-card`, `variant=reach`. The isolated clone may use only static `data-share-reach-*` decoration. It is download-only. Call it authored reachability—not impact, blast radius, breakage, or runtime causality.
      
      ## Truth boundary
      
      Viewer exports are communication assets. They do not replace the checked HTML, the deterministic delivery receipt, or a real visual review. Do not add a hosted service, storage surface, dependency, schema branch, or mobile product surface for these viewer-only capabilities.
      
  • renderers
    • architecture
      • grid.mjs 2 KB · in bundle
      • labels.mjs 10.4 KB · in bundle
      • render-architecture.mjs 46.6 KB · in bundle
      • routing.mjs 53.5 KB · in bundle
    • dataflow
      • README.md 4.1 KB
        # Data Flow Renderer
        
        Render `diagram_type: "dataflow"` JSON files into the standard Archify HTML
        template.
        
        ```bash
        node archify/renderers/dataflow/render-dataflow.mjs input.dataflow.json output.html
        ```
        
        The renderer validates input against `archify/schemas/dataflow.schema.json`
        with the bundled standalone validator. No dependency installation is required.
        
        If `output.html` is omitted, the renderer uses the required `meta.output` value
        from the JSON file.
        
        ## Input
        
        Data-flow JSON files must set:
        
        ```json
        {
          "schema_version": 1,
          "diagram_type": "dataflow",
          "meta": {
            "title": "Product Analytics Data Flow",
            "output": "product-analytics-dataflow.html",
            "viewBox": [940, 720]
          },
          "stages": [],
          "nodes": [],
          "flows": [],
          "cards": []
        }
        ```
        
        A complete worked example lives at
        `archify/examples/product-analytics.dataflow.json`.
        
        The schema lives at:
        
        ```text
        archify/schemas/dataflow.schema.json
        ```
        
        ## Legend
        
        The default visual legend derives kinds from `flows[].variant` (omitting
        `variant` means `default`) and adds `database` only when a database node exists.
        Supported `meta.legend.entries` keys, in stable order, are `emphasis`,
        `security`, `dashed`, `database`, and `default`. Flow variants remain
        visual-only because Archify has no compiled edge-kind facts in this slice. A
        present `database` entry is different: it comes from exact
        `nodes[].type: "database"` facts, so it publishes the normal Semantic Legend
        count, accessible name, and keyboard interaction. Forcing `database` visible
        without a database node keeps it visual-only.
        
        ## Layout budget
        
        | Constant | Value |
        |----------|-------|
        | viewBox | default `[940, 720]`; schema minimum `[360, 360]` |
        | Stages (2–5) | centers at x = 100 + stage×215; stage band 168 wide, header at y 46 |
        | Row tops (`row` 0–4) | y = 128, 242, 356, 470, 584 (plus `yOffset`) |
        | Default node | 112×58 |
        | Node area | x within `[24, width − 24]`; y within `[104, height − 74]` |
        | Node spacing | ≥10px between any two nodes (checked across stages and rows) |
        | Flow length | ≥34px between endpoints |
        | Legend row | y = height − 36 |
        
        Route presets for flows: `straight`, `vertical-channel`, `bottom-channel`,
        `top-channel`, explicit `via` points, or the default `auto` (midpoint elbow).
        
        ## Design Rules
        
        - Use stages for data lifecycle boundaries: source, ingest, process, store,
          consume.
        - Place nodes by stage index and row index; do not hand-place raw SVG for the
          common case.
        - Use flow labels to name the data asset, not the transport primitive:
          `clickstream`, `identity map`, `normalized facts`, `feature vectors`.
        - Use `classification` for short sensitivity or governance context:
          `PII touch`, `non-PII`, `approved only`, `batch`, `read-only`.
        - Use `security` for PII, policy, consent, access-control, or restricted joins.
        - Use `emphasis` for the primary data path and `dashed` for async or batch
          derivations.
        - Keep labels short enough to fit in narrow previews.
        
        Schema violations exit non-zero with path-prefixed messages annotated with the
        element's id or label. The renderer additionally fails when it can detect
        layout problems, including missing stages, duplicate node IDs, nodes outside
        the readable diagram area, node overlap, labels colliding with nodes or other
        labels, labels wider than their node, unknown flow endpoints, missing flow
        labels, unreadably short flows, flows crossing unrelated nodes (2px Clean Flow
        clearance), or stages that exceed the viewBox. Stage frames remain intentional
        pass-through containers. Text width
        is estimated CJK-aware: fullwidth glyphs count as two units.
        
        Set `meta.quality_profile` to `showcase` for polished delivery. Unrelated proper
        X crossings then fail with `composition/proper-crossing`; default `standard`
        keeps them as artifact-receipt warnings. Collinear stage corridors are outside
        the proper-X rule, but a separate gate warns in `standard` and fails in
        `showcase` when unrelated flows overlap for at least 8px. Shared semantic
        endpoints, point touches, and shorter overlaps remain valid. Showcase also
        rejects any route segment below 8px and any interior turn segment below 16px;
        ordinary 8–15px endpoint stubs remain valid.
        
      • render-dataflow.mjs 24 KB · in bundle
    • lifecycle
      • grid-routing.mjs 20 KB · in bundle
      • README.md 8.6 KB
        # Lifecycle Renderer
        
        Render `diagram_type: "lifecycle"` JSON files into the standard Archify HTML
        template.
        
        ```bash
        node archify/renderers/lifecycle/render-lifecycle.mjs input.lifecycle.json output.html
        ```
        
        The renderer validates input against `archify/schemas/lifecycle.schema.json`
        with the bundled standalone validator. No dependency installation is required.
        
        If `output.html` is omitted, the renderer uses the required `meta.output` value
        from the JSON file.
        
        ## Input
        
        Lifecycle JSON files must set:
        
        ```json
        {
          "schema_version": 2,
          "diagram_type": "lifecycle",
          "meta": {
            "title": "Deployment Release Lifecycle",
            "output": "deployment-release-lifecycle.html"
          },
          "lanes": [],
          "states": [],
          "transitions": [],
          "cards": []
        }
        ```
        
        `schema_version` is `1` or `2`; author new diagrams as `2`. Lane ids `main`
        (required) and `terminal` are reserved in both versions.
        
        - **v2** renders one row per populated lane: `main` first, `terminal` last,
          other lanes in `lanes[]` order, each titled in the left gutter. A complete
          example lives at `archify/examples/deployment-release.lifecycle.json`.
        - **v1** keeps the fixed three bands: `main` is the top phase band,
          `terminal` the bottom outcome band, and every other lane shares the middle
          event band, whose header joins their labels with ` + `. A complete example
          lives at `archify/examples/agent-run.lifecycle.json`.
        
        The schema lives at:
        
        ```text
        archify/schemas/lifecycle.schema.json
        ```
        
        ## Legend and state marks
        
        State color follows `states[].type`: active and start are cyan, waiting amber,
        decision purple, success green, failure rose, neutral and external slate.
        Structure is drawn, not colored: every `start` state gets a UML initial marker
        (a dot and arrow into its left side), and a state with no outgoing transition
        gets a double border as a final state (in v1, a main state followed by
        another main column is not final, because the implied rail continues).
        
        The default legend derives kinds from `states[].type`; the `start` entry shows
        the initial marker, and a non-interactive `final` entry appears when a final
        state exists. Supported `meta.legend.entries` keys, in stable order, are
        `start`, `active`, `waiting`, `decision`, `success`, `failure`, `neutral`, and
        `external`. Labels and visibility may be overridden through the shared legend
        contract; only kinds backed by rendered states receive Semantic Legend
        controls.
        
        State decorations share one top rail: the type sigil and `step` on the left,
        the brand mark at the right corner, and the Viewer's runtime source badge just
        left of the brand. Label layout reserves the badge's width whenever the state
        has verified repository sources.
        
        ## Layout budget (v2)
        
        | Item | Value |
        |------|-------|
        | Columns | `col` 0–4, one x grid shared by every row |
        | Default state | 140×64 (text 11px label, 8px sublabel and tag) |
        | Column gap | 64px, widened until a labelled same-row neighbour transition fits beside its line; all gaps shrink toward 44px when the canvas would exceed the desktop readability budget of the smallest state text |
        | Row gap | at least 120px, opened further for the horizontal tracks its routes need |
        | Canvas | sized from the rows, columns, and measured legend when `meta.viewBox` is omitted; an authored `viewBox` is honored and validated |
        
        Transitions without `via`, a channel, or a non-`auto` route use the v2 grid
        router: neighbours in one row connect horizontally (a reciprocal pair runs as
        two parallel lines), rows connect through the facing top/bottom sides with one
        turn in a row gap, a state blocking a straight descent sends the route through
        the empty corridor between columns, and an unlabelled route blocked in an
        outer column loops around the outside of the grid. Each gap assigns tracks in
        the order that minimizes crossings. There is no implied rail; a forward
        transition between two `main` states without a `variant` renders as the
        emphasized primary path. Showcase labels are ranked beside their line, then on
        it, then outward past neighbouring parallels.
        
        Explicit `fromSide` / `toSide` values remain authoritative. Pins that match the
        grid router's chosen sides keep its routes and adaptive row gaps. If an automatic
        transition pins a different side, the scene uses the shared side-aware obstacle
        planner, retaining the v2 state grid and shared port spreading.
        
        ## Layout budget (v1)
        
        | Band | Lane id | Top y | Column centers | Default state |
        |------|---------|-------|----------------|---------------|
        | Phase | `main` (required) | 126 | `col` 0–4 → x = 94, 248, 402, 556, 710 | 118×62 |
        | Event | any other id | 278 | `col` 0–2 → x = 402, 556, 710 | 126×58 |
        | Outcome | `terminal` | 450 | `col` 0–2 → x = 402, 556, 710 | 118×58 |
        
        Event and terminal columns are intentionally offset from the main rail:
        event/terminal `col: N` uses the same x coordinate as main `col: N + 2`.
        For example, lower-band columns 0, 1, and 2 align beneath main columns 2, 3,
        and 4 respectively.
        
        | Constant | Value |
        |----------|-------|
        | viewBox | default `[980, 660]`; schema minimum `[420, 566]` |
        | State area | x within `[32, width − 32]`; state bottom at or above `height − 122` |
        | State spacing | ≥10px between any two states — checked across lanes, because all event lanes share one band; separate same-band states with `col` or `yOffset` |
        | Transition length | ≥32px between endpoints |
        | Legend row | final baseline y = height − 36; extra measured rows wrap upward |
        
        The primary lifecycle rail runs along the phase band and extends to the
        furthest occupied phase column. Route presets for transitions: `straight`,
        `drop` (bend at `channelY`, defaulting to the vertical midpoint),
        `bottom-channel`, `top-channel`, `right-channel`, `left-channel`, explicit
        `via` points, or the default `auto`. Multi-segment transitions get rounded
        corners; tune them with `cornerRadius` (default 10, `0` for sharp bends).
        
        Transition `label` and `note` are independently optional. A non-empty `note`
        renders even when `label` is omitted or empty, using its existing secondary
        text style on a single row and retaining the note's fine-detail visibility.
        With both fields present, the note stays below the label. Notes participate in
        automatic label placement, route-space reservation, and label collision checks;
        the existing `labelAt`, `labelDx`, `labelDy`, and
        `labelSegment` controls also position a note-only text block.
        
        ## Design Rules
        
        - Treat lifecycle diagrams as a phase map, not a dense state-transition graph.
        - Put the primary lifecycle on one horizontal row using the `main` lane; in v2,
          author each step of it as a transition.
        - In v2, place an interruption, recovery, or exit in the column of the state it
          leaves so its transition drops straight down.
        - Use `step` labels for ordered phases, such as `01`, `02`, and `03`.
        - Use lower lanes only for interruptions, recovery, and terminal exits.
        - Keep transition labels out of the main SVG unless the label is essential;
          prefer node labels, tags, legend entries, and summary cards.
        - Prefer axis-aligned lines and avoid crossings. Terminal exits should drop
          vertically from their source event whenever possible. Explicit `straight`
          routes remain supported; see the [authored routing contract](../../references/authoring-contract.md#executable-geometry-rules).
        - Use `success` for completion, `failure` for failure/terminal exits,
          `waiting` for pauses, and `decision` for quality gates.
        
        Schema violations exit non-zero with path-prefixed messages annotated with the
        element's id or label. The renderer additionally fails when it can detect
        layout problems, including a missing `main` lane, duplicate state IDs, unknown
        lanes, unknown transition endpoints, states outside the lifecycle area,
        overlapping states (including across lanes), labels colliding with states or
        other labels, labels wider than their state, unreadably short transitions, or
        transitions crossing unrelated states (2px Clean Flow clearance). Lifecycle
        bands remain intentional pass-through containers.
        Text width is estimated CJK-aware: fullwidth glyphs count as two units.
        
        Set `meta.quality_profile` to `showcase` for polished delivery. Unrelated proper
        X crossings then fail with `composition/proper-crossing`; default `standard`
        keeps them as artifact-receipt warnings. The final artifact check samples
        rounded `Q` corners. Collinear corridors remain outside the proper-X rule, but
        a separate gate warns in `standard` and fails in `showcase` when unrelated
        transitions overlap for at least 8px. Shared semantic endpoints, point touches,
        and shorter overlaps remain valid. Showcase also rejects any route segment
        below 8px and any interior turn segment below 16px; ordinary 8–15px endpoint
        stubs remain valid.
        
      • render-lifecycle.mjs 42.1 KB · in bundle
    • sequence
      • README.md 5.8 KB
        # Sequence Renderer
        
        Render `diagram_type: "sequence"` JSON files into the standard Archify HTML
        template.
        
        ```bash
        node archify/renderers/sequence/render-sequence.mjs input.sequence.json output.html
        ```
        
        The renderer validates input against `archify/schemas/sequence.schema.json`
        with the bundled standalone validator. No dependency installation is required.
        
        If `output.html` is omitted, the renderer uses the required `meta.output` value
        from the JSON file.
        
        ## Input
        
        Sequence JSON files must set:
        
        ```json
        {
          "schema_version": 1,
          "diagram_type": "sequence",
          "meta": {
            "title": "Cache Miss Request Sequence",
            "output": "cache-miss-request.html",
            "viewBox": [920, 760]
          },
          "participants": [],
          "segments": [],
          "messages": [],
          "activations": [],
          "cards": []
        }
        ```
        
        The timeline scales with the viewBox height: a taller `meta.viewBox` buys more
        message room, a shorter one shrinks the readable band instead of clipping. A
        complete worked example lives at
        `archify/examples/cache-miss-request.sequence.json`.
        
        The schema lives at:
        
        ```text
        archify/schemas/sequence.schema.json
        ```
        
        ## Legend
        
        The default visual legend derives kinds from `messages[].variant` (omitting
        `variant` means `default`). Supported `meta.legend.entries` keys, in stable
        order, are `emphasis`, `return`, `security`, `dashed`, and `default`. These are
        visual message keys, not Semantic Lens controls; label/visibility overrides do
        not create edge facts.
        
        The legend sits below all timeline content: the last message and its note,
        activation bars, and segment frames, with a 12px gap. Without `meta.viewBox`
        the canvas grows to keep that gap. With an authored `viewBox` that is too short,
        `showcase` fails with the exact height to set, and `standard` hides the implicit
        legend rather than drawing it over content. Lifelines stop above the legend.
        Message labels use their line's color; gray default and return lines keep the
        muted text color.
        
        ## Layout budget
        
        | Constant | Value |
        |----------|-------|
        | viewBox | default `[920, 760]`, taller when late content needs legend room; schema minimum `[480, 480]` |
        | Participant boxes | `fixed` (default): 86×54 at y 72; `spread`: viewBox-relative width from 86px up to 190px |
        | Participant columns | `fixed`: centers at x = 62 + index×108; `spread`: columns distribute across the available viewBox width |
        | Participant count | the last box must end at or before width − 40; layouts that cannot fit fail closed |
        | Lifelines | from y 142 down to height − 65 (drawn to just above the legend); band must be ≥120px tall |
        | Message `y` range | `[160, height − 83]` |
        | Message spacing | ≥28px vertical between messages that share horizontal space |
        | Arrow span | ≥60px horizontal between the two participants |
        | Segments | y pixel ranges with `to > from`, inside `[72, lifeline bottom + 20]` |
        | Legend | last row baseline at height − 54; extra rows wrap upward and stay 12px below the timeline content |
        
        `segments[].from/to` and `activations[].from/to` are y pixel coordinates, not
        participant ids; activations also require `to > from`.
        
        ### Column fit
        
        Sequence diagrams use `meta.column_fit: "fixed"` by default so existing
        documents keep their historical coordinates. Use `"spread"` when a wide
        viewBox would otherwise leave empty space on the right or when meaningful
        participant labels do not fit the fixed 86px boxes. Spread derives box width
        and column distance from the viewBox while preserving participant order,
        lifelines, and message semantics.
        
        The artifact checker reports `composition.sequenceColumnSpace` from the rendered
        participants, routes and text. A large unused right-hand region in a fixed layout
        can produce an `inspect-sequence-width` recommendation in `finalize`; it is advice,
        not a new warning or failure. See [Sequence width review](../../references/delivery-contract.md#sequence-width-review)
        for the bounded authoring repair and explicit-fixed/legacy preservation rules.
        
        ## Design Rules
        
        - Put participants across the top, ordered by the story the reader should
          follow.
        - Time moves downward.
        - Use `emphasis` for the main request path.
        - Use `security` for auth, consent, permission, and policy calls.
        - Use `return` for quiet response messages.
        - Use `dashed` for async trace, event, logging, and non-blocking work.
        - Use segments as light background guides; keep segment labels short.
        - Keep labels concise, but try `meta.column_fit: "spread"` before shortening a
          meaningful participant label just to fit the fixed boxes.
        
        Schema violations exit non-zero with path-prefixed messages annotated with the
        element's id or label. The renderer additionally fails when it can detect
        layout problems, including missing participants, duplicate participant IDs,
        participant labels wider than their box, unknown message endpoints, messages
        outside the readable timeline, overly tight vertical spacing between messages
        that overlap horizontally, invalid segment or activation ranges, or
        participants that exceed the viewBox. The shared Clean Flow contract treats
        participant headers as semantic boxes while explicitly allowing messages to
        cross intermediate lifelines, activation bars, and segment frames. Text width is estimated CJK-aware:
        fullwidth glyphs count as two units.
        
        Set `meta.quality_profile` to `showcase` for polished delivery. Unrelated proper
        message X crossings then fail with `composition/proper-crossing`; default
        `standard` keeps them as artifact-receipt warnings. Messages may still cross
        intermediate lifelines. Collinear corridors remain outside the proper-X rule,
        but a separate gate warns in `standard` and fails in `showcase` when unrelated
        messages overlap for at least 8px. Shared semantic endpoints, point touches,
        and shorter overlaps remain valid. Showcase also rejects any route segment
        below 8px and any interior turn segment below 16px; ordinary 8–15px endpoint
        stubs remain valid.
        
      • render-sequence.mjs 24.9 KB · in bundle
    • shared
      • atomic-output.mjs 68.7 KB · in bundle
      • brand-marks.mjs 26.6 KB · in bundle
      • cli.mjs 20.4 KB · in bundle
      • desktop-readability.mjs 6.7 KB · in bundle
      • diagnostics.mjs 6.7 KB · in bundle
      • engineering-profiles.mjs 6.8 KB · in bundle
      • generated-brand-marks.mjs 159.8 KB · in bundle
      • generated-validators.mjs 518.1 KB · in bundle
      • geometry.mjs 81.6 KB · in bundle
      • i18n.mjs 42.2 KB · in bundle
      • layout-report.mjs 1.1 KB · in bundle
      • legend.mjs 8.5 KB · in bundle
      • output-path.mjs 18.6 KB · in bundle
      • path-semantics.mjs 31.6 KB · in bundle
      • portable-path.mjs 12.2 KB · in bundle
      • repository-evidence.mjs 17.1 KB · in bundle
      • repository-location.mjs 3.5 KB · in bundle
      • route-quality.mjs 23 KB · in bundle
      • sidecar-path.mjs 1.2 KB · in bundle
      • spatial-grid.mjs 2.4 KB · in bundle
      • text-fit.mjs 5.1 KB · in bundle
      • utils.mjs 12.3 KB · in bundle
      • validator.mjs 3.4 KB · in bundle
    • workflow
      • README.md 14.9 KB
        # Workflow Renderer
        
        Render `diagram_type: "workflow"` JSON files into the standard Archify HTML
        template.
        
        ```bash
        node archify/renderers/workflow/render-workflow.mjs input.workflow.json output.html
        ```
        
        The renderer validates input against `archify/schemas/workflow.schema.json`
        with the bundled standalone validator. No dependency installation is required.
        
        If `output.html` is omitted, the renderer uses the required `meta.output` value
        from the JSON file.
        
        After rendering, run the artifact checker:
        
        ```bash
        node archify/scripts/check-render-output.mjs output.html
        ```
        
        It catches final-SVG issues that are easiest to see in a browser: non-finite
        SVG values, accidental two-point diagonal arrows, and arrows crossing the
        legend.
        
        ## Input
        
        Workflow JSON files must set:
        
        ```json
        {
          "schema_version": 2,
          "diagram_type": "workflow",
          "meta": {
            "title": "Agent Tool Call Workflow",
            "output": "agent-tool-call.html"
          },
          "lanes": [],
          "phases": [],
          "groups": [],
          "mainPath": [],
          "nodes": [],
          "edges": [],
          "cards": []
        }
        ```
        
        Use `schema_version: 2` for new workflows. Its readable layout compiler treats
        every `col` as a logical rank in `0..5` and derives geometry from the measured
        document. `schema_version: 1` remains the fixed legacy contract for existing
        sources; valid v1 output is preserved byte-for-byte and never silently
        reinterpreted as v2.
        
        Omit `meta.viewBox` for the common v2 case so the compiler can use intrinsic
        measured bounds. In v1, the omitted width remains fixed at 720 and height is
        derived from lane count. A complete worked example lives at
        `archify/examples/agent-tool-call.workflow.json`; its `schema_version` selects
        the applicable contract.
        
        The schema lives at:
        
        ```text
        archify/schemas/workflow.schema.json
        ```
        
        ## Migration and layout receipt
        
        Migrate an existing v1 source into a separate v2 file:
        
        ```bash
        node archify/bin/archify.mjs migrate workflow old.json new.json --to-schema 2 --json
        ```
        
        Running the command again with its schema-v2 output as the new source is an
        idempotent verification pass: the destination bytes and geometry stay unchanged.
        
        If a legacy v1 source is blocked solely because `meta.output` is missing or no
        longer portable, supply its replacement for the separate v2 destination:
        
        ```bash
        node archify/bin/archify.mjs migrate workflow old.json new.json --to-schema 2 --output reports/workflow.html --json
        ```
        
        `--output` must itself be a portable POSIX-relative `.html` path. It updates
        only the verified destination candidate; the source bytes remain unchanged and
        all non-output schema and compiler diagnostics still block migration.
        
        The command never overwrites the source by default. It maps absolute
        `via[*][0]`, `labelAt[0]`, and `channelX` values from legacy to solved rank
        space, preserves y coordinates unless a reported vertical constraint needs
        author input, expands an explicit viewBox only for an unambiguous containment
        repair, and writes the destination only after v2 compilation and artifact
        checks pass. Ambiguous explicit pins fail without producing the destination.
        
        Inspect the stable author-facing v2 plan with:
        
        ```bash
        node archify/bin/archify.mjs validate workflow input.workflow.json --layout-json
        ```
        
        The receipt reports the selected contract, measured `viewBox` and
        `requiredViewBox`, solved columns, nodes, edges, labels, and causal diagnostics.
        It deliberately omits solver iterations and candidate scores.
        
        ## Legend
        
        The default legend derives component kinds from `nodes[].type`. Supported
        `meta.legend.entries` keys, in stable order, are `frontend`, `backend`,
        `security`, `messagebus`, `database`, `cloud`, and `external`. Labels and
        visibility may be overridden through the shared legend contract; only kinds
        backed by rendered nodes receive Semantic Legend controls.
        
        ## Layout contracts
        
        ### Fixed v1
        
        | Constant | Value |
        |----------|-------|
        | viewBox | default `[720, auto]` — auto height = 52 + lanes×104 + (lanes−1)×20 + 124 |
        | Lane frame | x 40, width 640, height 104, gap 20; first lane top at y 52 |
        | Lane title strip | top 30px of each lane; node boxes must stay below it |
        | Column centers (`col` 0–5) | x = 88, 220, 300, 430, 500, 625 |
        | Phase headers | Optional `phases[]` render above the first lane, spanning `fromCol..toCol` |
        | Lane groups | Optional `groups[]` frame parallel work or branch work inside one lane |
        | Exception lanes | Set `lane.variant: "exception"` for retry, denial, fallback, or failure paths |
        | Main path lint | Optional `mainPath[]` checks that happy-path steps have matching edges and do not move backward |
        | Default node | 92×52 (height 68 when `tag` is set) |
        | Node spacing | ≥8px between nodes in the same lane |
        | Edge length | straight segments must span ≥28px |
        | Legend row | y = lane bottom + 44; viewBox height must be ≥ legend y + 18 |
        
        Column-center gaps are 132 / 80 / 130 / 70 / 125 px: columns 1↔2 (80px) and
        3↔4 (70px) cannot both hold default-width 92px nodes in the same lane. Such an
        invalid v1 source receives one causal `workflow/column-capacity` diagnostic and
        a verified migration-to-v2 repair; v1 never falls through to adaptive layout.
        
        ### Readable v2
        
        | Invariant | Contract |
        |----------|----------|
        | Logical columns | `col` is an integer in `0..5`; pixel centers are measured output |
        | Adjacent-rank baseline | 120px center distance before document-specific constraints |
        | Same-lane node clearance | ≥8px when vertical node intervals overlap |
        | Facing direct edge | clear gap ≥`max(28px, measured label mask width + 8px)` |
        | Automatic route rhythm | direct segment ≥28px; endpoint stub ≥8px; interior turn segment ≥16px |
        | Implicit viewBox | intrinsic content bounds plus contract padding |
        | Explicit viewBox | containment capacity; too-small input reports exact `requiredViewBox` and contributors |
        | Lane measurement | A same-column vertical stack (two or more distinct `yOffset` values) opts an implicit, unpinned workflow into per-lane measurement. Explicit `meta.viewBox`, `via`, `labelAt`, `channelX`, or `channelY`, and workflows without a stack retain shared-height v2 geometry for compatibility. |
        
        The compiler applies constraints only to actual related or overlapping
        same-lane nodes, so a wide node in an unrelated lane does not expand every
        rank. Legacy centers are a soft preference after correctness constraints, not
        a geometry promise. Phase and group frames derive from the solved rank bands.
        Automatic routes are normalized once and the same final scene drives
        validation and SVG serialization. Long automatic labels compare direct-gutter
        growth with a legal channel instead of widening every downstream rank. Measured
        multi-row legends participate in intrinsic height and explicit viewBox
        capacity.
        
        The Issue #250 shape already has a v2 representation without an authored lane
        size. Keep the three stages in one grouped lane, omit `meta.viewBox`, and center
        their offsets around zero:
        
        ```json
        {
          "schema_version": 2,
          "diagram_type": "workflow",
          "meta": { "title": "stack", "output": "stack.html" },
          "lanes": [{ "id": "cage", "label": "one cage" }],
          "groups": [{ "id": "g", "label": "cage", "lane": "cage", "fromCol": 1, "toCol": 3 }],
          "nodes": [
            { "id": "a", "lane": "cage", "col": 2, "type": "security", "label": "stageA", "yOffset": -90 },
            { "id": "b", "lane": "cage", "col": 2, "type": "security", "label": "stageB", "yOffset": 0 },
            { "id": "c", "lane": "cage", "col": 2, "type": "security", "label": "stageC", "yOffset": 90 }
          ],
          "edges": [
            { "from": "a", "to": "b", "fromSide": "bottom", "toSide": "top" },
            { "from": "b", "to": "c", "fromSide": "bottom", "toSide": "top" }
          ]
        }
        ```
        
        An implicit readable-v2 vertical stack whose measured lane height exceeds the
        104px baseline opts into the desktop Viewer's height budget. This decision
        comes from compiled geometry, not an authored sizing field. The Viewer changes only
        the outer reader width so the complete lane remains on screen; canonical SVG
        geometry and explicit `meta.viewBox` workflows retain their authored contracts.
        When necessary, the Viewer may scale below the intrinsic 1:1 width only as far
        as the 6px projected node-text floor. If the complete workflow still cannot fit
        at that readable scale, `visual-check` reports the remaining viewport overflow
        instead of clipping or introducing an internal scroller.
        
        Authored `via`, `labelAt`, `channelX`, and `channelY` are absolute hard pins in
        v2; an infeasible pin returns `workflow/explicit-pin-conflict` rather than being
        silently moved. `fromSide` and `toSide` remain direction constraints. A route
        preset restricts the automatic candidate family but is not itself an absolute
        coordinate pin. When either endpoint side is omitted, the v2 compiler chooses
        a feasible side; an authored side restricts that endpoint to the named port.
        
        ## Design Rules
        
        - Use lanes for ownership or runtime boundaries.
        - Use phase headers for high-level story beats such as Intake, Plan, Execute, and Report.
        - Use groups for parallel checks, branch handling, or bounded work within a lane; every group must contain at least one node.
        - For sequential stages stacked inside one container, use one v2 lane and one group, keep the stages in one column, and omit `meta.viewBox`. `yOffset` is relative to the center of the lane's content area, so center a three-stage stack with `-90 / 0 / 90` rather than `0 / 90 / 180`. With compiler-owned routes and canvas, the compiler expands only that lane.
        - Use `lane.variant: "exception"` for human wait, denial, retry, fallback, and failure lanes instead of mixing those paths into the happy path.
        - Set `mainPath` when the diagram has a clear happy path; the renderer validates that consecutive ids have matching edges and move left-to-right.
        - Place nodes with lane IDs and `col` indexes in `0..5`, not raw SVG coordinates.
        - Preserve semantic edge labels. Readable v2 allocates measured label clearance;
          when a label does not fit, repair the reported capacity or route constraint
          instead of deleting meaning.
        - Use labels for decisions, approvals, protocols, async traces, return paths,
          and any other relationship meaning not fully implied by its endpoints.
        - Prefer route presets — `drop` (bend between lanes; `bias` 0–1 picks where),
          `outside-right`, `return-left`, `bottom-channel`, and `up-channel` — before
          using raw `via` points. `straight` and the default `auto` cover the rest.
        - Keep workflow examples compact enough to render well in narrow chat/browser
          previews.
        
        ### Optional semantic checks
        
        Layout validation cannot infer domain truth from labels or cards. When source
        evidence establishes roots, terminals, mandatory direct relationships, or
        mandatory directed reachability, encode those facts in `semanticChecks`:
        
        ```json
        "semanticChecks": {
          "allowedRoots": ["request", "resource_catalog"],
          "allowedTerminals": ["reply", "audit_log"],
          "requiredEdges": [
            { "from": "dispatch", "to": "dispatch_ledger" }
          ],
          "requiredPaths": [
            { "from": "event_ledger", "to": "runtime_host" }
          ]
        }
        ```
        
        When `allowedRoots` or `allowedTerminals` is present, it is the complete allow
        list for zero-incoming or zero-outgoing nodes respectively. `requiredEdges`
        requires one exact authored direction; `requiredPaths` permits intermediate
        nodes but follows authored edge direction. These checks run before layout, do
        not alter SVG or receipt bytes, and must not be weakened merely to resolve a
        route or composition diagnostic. Omit fields whose domain facts are unknown.
        
        Schema violations exit non-zero with path-prefixed messages annotated with the
        element's id or label. The renderer additionally fails when it can detect
        layout problems, including node overlap, nodes outside their lanes, invalid
        phase/group column ranges, empty groups, broken `mainPath` steps, unknown edge
        targets, labels colliding with nodes or other labels, labels wider than their
        node, legends outside the viewBox, or straight arrows that are too short to
        read cleanly. The shared Clean Flow Gate also rejects edges crossing unrelated
        nodes with 2px clearance; lanes, phases, and groups remain intentional
        pass-through containers. Text width is estimated CJK-aware: fullwidth glyphs
        count as two units.
        
        Diagnostics are causal: a rank-capacity failure suppresses derivative short
        edge, endpoint-direction, and label-overlap findings. Every
        `supportedFixes[]` entry is verified by replanning the proposed edit, and a
        diagnostic never proposes removing a semantic label when label presence does
        not cause the failed invariant.
        
        Set `meta.quality_profile` to `showcase` for polished delivery. Unrelated proper
        X crossings then fail with `composition/proper-crossing`; default `standard`
        keeps them as artifact-receipt warnings. Collinear lane corridors are outside
        the proper-X rule, but a separate gate warns in `standard` and fails in
        `showcase` when unrelated edges overlap for at least 8px. V1 keeps its authored
        shared-endpoint contract. V2 also checks shared endpoints, including explicitly
        controlled routes: long or mixed-style trunks, counterflow, proper interior X
        crossings and overlapping independent arrowheads are not exempt. Pins are
        preserved, not silently repaired; unresolved v2 corridor/arrowhead collisions
        warn in `standard` and fail in `showcase`.
        
        V2 permits a same-direction shared terminal stub of at most 24 SVG units only
        when both relationships share the actual source or target port, effective
        variant, stroke width and role. A nonterminal overlap is never such a stub;
        forward-collinear waypoints do not split a long trunk into permitted pieces.
        Compatible short merges may share their terminal arrowhead. Automatic routes
        consider separate ports, reserve absolute routes at contested nodes, and prefer
        clear paths over shorter ambiguous ones. Crowded automatic corridors can use a
        bounded local adjustment without moving nodes or changing explicit coordinates.
        
        The SVG carries `data-layout-contract="readable-v2"` and each edge's role so
        artifact checks apply the same classification to actual visible path geometry,
        not stale composition-point metadata. These internal output attributes do not
        add authoring schema fields. Other diagram types retain their existing rules.
        V2 proper-crossing diagnostics retain the relationship IDs, intersection point,
        and supported fixes in both compiler/layout-JSON receipts and final HTML checks;
        `standard` reports warnings while `showcase` rejects the crossing. Both analyses
        merge forward-collinear waypoints without rewriting authored paths; real bends
        and reversals remain endpoint touches rather than being merged into an X.
        
        The older per-edge `data-composition-routing="workflow-v2-auto"` marker remains
        for compatibility with first-round exported HTML that has no root layout
        contract and with older artifact checkers. Marker-only artifacts retain their
        narrower automatic-pair crossing/counterflow policy; the root `readable-v2`
        contract is authoritative when present and also checks explicit routes. Do not
        remove the marker-only path as dead code without retiring that export format.
        Showcase also
        rejects any route segment below 8px and any interior turn segment below 16px;
        ordinary 8–15px endpoint stubs remain valid for fixed lane gaps.
        
      • render-workflow.mjs 1.2 KB · in bundle
      • workflow-compiler.mjs 191.1 KB · in bundle
      • workflow-migration-geometry.mjs 5.2 KB · in bundle
  • schemas
    • architecture.schema.json 5.9 KB
      {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://github.com/tt-a1i/archify/schemas/architecture.schema.json",
        "title": "Archify Architecture Diagram",
        "type": "object",
        "additionalProperties": false,
        "required": ["schema_version", "diagram_type", "meta", "components"],
        "properties": {
          "schema_version": { "const": 1 },
          "diagram_type": { "const": "architecture" },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": ["title", "output"],
            "properties": {
              "title": { "type": "string", "minLength": 1 },
              "locale": { "$ref": "common.schema.json#/$defs/locale" },
              "translations": { "$ref": "common.schema.json#/$defs/translations" },
              "subtitle": { "type": "string" },
              "output": { "$ref": "common.schema.json#/$defs/portableOutputPath" },
              "animation": { "$ref": "common.schema.json#/$defs/animation" },
              "visual_preset": { "$ref": "common.schema.json#/$defs/visualPreset" },
              "quality_profile": { "$ref": "common.schema.json#/$defs/qualityProfile" },
              "engineering_profile": { "enum": ["deployment-ownership"] },
              "repository": { "$ref": "common.schema.json#/$defs/repository" },
              "views": { "$ref": "common.schema.json#/$defs/guidedViews" },
              "legend": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": { "$ref": "common.schema.json#/$defs/legendMode" },
                  "entries": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "frontend": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "backend": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "database": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "cloud": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "security": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "messagebus": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "external": { "$ref": "common.schema.json#/$defs/legendEntry" }
                    }
                  }
                }
              },
              "viewBox": {
                "type": "array",
                "prefixItems": [
                  { "type": "number", "minimum": 320 },
                  { "type": "number", "minimum": 240 }
                ],
                "items": false,
                "minItems": 2,
                "maxItems": 2
              }
            }
          },
          "layout": {
            "type": "object",
            "additionalProperties": false,
            "required": ["mode"],
            "properties": {
              "mode": { "enum": ["grid"] },
              "origin": { "$ref": "common.schema.json#/$defs/point" },
              "cols": { "type": "integer", "minimum": 1, "maximum": 12 },
              "gapX": { "type": "number", "minimum": 0 },
              "gapY": { "type": "number", "minimum": 0 },
              "cellW": { "type": "number", "minimum": 40 },
              "cellH": { "type": "number", "minimum": 24 }
            }
          },
          "components": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["id", "type", "label"],
              "properties": {
                "id": { "$ref": "common.schema.json#/$defs/id" },
                "type": { "$ref": "common.schema.json#/$defs/componentType" },
                "label": { "type": "string", "minLength": 1 },
                "sublabel": { "type": "string" },
                "tag": { "type": "string" },
                "icon": { "$ref": "common.schema.json#/$defs/nodeIcon" },
                "brand": { "$ref": "common.schema.json#/$defs/brandMark" },
                "sources": { "$ref": "common.schema.json#/$defs/sourceReferences" },
                "row": { "type": "integer", "minimum": 0 },
                "col": { "type": "integer", "minimum": 0 },
                "pos": { "$ref": "common.schema.json#/$defs/point" },
                "size": {
                  "type": "array",
                  "prefixItems": [
                    { "type": "number", "exclusiveMinimum": 0 },
                    { "type": "number", "exclusiveMinimum": 0 }
                  ],
                  "items": false,
                  "minItems": 2,
                  "maxItems": 2
                }
              }
            }
          },
          "boundaries": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["kind", "label", "wraps"],
              "properties": {
                "kind": { "enum": ["region", "security-group"] },
                "label": { "type": "string", "minLength": 1 },
                "wraps": {
                  "type": "array",
                  "minItems": 1,
                  "items": { "$ref": "common.schema.json#/$defs/id" }
                },
                "pad": { "type": "number", "minimum": 0 }
              }
            }
          },
          "connections": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["from", "to"],
              "properties": {
                "id": { "$ref": "common.schema.json#/$defs/id" },
                "from": { "$ref": "common.schema.json#/$defs/id" },
                "to": { "$ref": "common.schema.json#/$defs/id" },
                "label": { "type": "string" },
                "variant": { "$ref": "common.schema.json#/$defs/variant" },
                "fromSide": { "$ref": "common.schema.json#/$defs/side" },
                "toSide": { "$ref": "common.schema.json#/$defs/side" },
                "route": { "enum": ["auto", "straight", "orthogonal-h", "orthogonal-v"] },
                "via": {
                  "type": "array",
                  "items": { "$ref": "common.schema.json#/$defs/point" }
                },
                "labelAt": { "$ref": "common.schema.json#/$defs/point" },
                "labelDx": { "type": "number" },
                "labelDy": { "type": "number" },
                "labelSegment": { "type": "integer", "minimum": 0 },
                "width": { "$ref": "common.schema.json#/$defs/relationshipWidth" }
              }
            }
          },
          "cards": { "$ref": "common.schema.json#/$defs/cards" }
        }
      }
      
    • common.schema.json 5.6 KB
      {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://github.com/tt-a1i/archify/schemas/common.schema.json",
        "title": "Archify Shared Definitions",
        "$defs": {
          "id": {
            "type": "string",
            "pattern": "^[a-zA-Z][a-zA-Z0-9_-]*$"
          },
          "locale": {
            "type": "string",
            "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$",
            "maxLength": 35
          },
          "translations": {
            "type": "object",
            "propertyNames": { "pattern": "^[a-z][a-zA-Z0-9]*(\\.[a-z][a-zA-Z0-9]*)*$" },
            "additionalProperties": { "type": "string", "minLength": 1, "maxLength": 400 },
            "maxProperties": 600
          },
          "animation": {
            "enum": ["trace", "none"]
          },
          "visualPreset": {
            "enum": ["classic", "signal-flow", "blueprint", "editorial"]
          },
          "qualityProfile": {
            "enum": ["standard", "showcase"]
          },
          "portableOutputPath": {
            "description": "A portable POSIX-relative HTML output path. It must be safe to interpret identically on every supported host filesystem.",
            "type": "string",
            "minLength": 1,
            "pattern": "^[^/]+(?:/[^/]+)*$",
            "allOf": [
              { "pattern": "(?:^|/)[^/]+[.][Hh][Tt][Mm][Ll]$" },
              { "not": { "pattern": "[\\\\<>:\"|?*\\u0000-\\u001F\\u007F-\\u009F]" } },
              { "not": { "pattern": "[\\uD800-\\uDFFF]" } },
              { "not": { "pattern": "(^|/)[.]{1,2}(/|$)" } },
              { "not": { "pattern": "[. ](/|$)" } },
              { "not": { "pattern": "(^|/)[^/]{256}" } },
              {
                "not": {
                  "pattern": "(^|/)(?:[Cc][Oo][Nn]|[Pp][Rr][Nn]|[Aa][Uu][Xx]|[Nn][Uu][Ll]|[Cc][Oo][Nn][Ii][Nn][$]|[Cc][Oo][Nn][Oo][Uu][Tt][$]|[Cc][Oo][Mm][1-9¹²³]|[Ll][Pp][Tt][1-9¹²³])(?:[.]|/|$)"
                }
              },
              {
                "not": {
                  "pattern": "(^|/)[^/]*~[1-9][0-9]*(?:[.]|/|$)"
                }
              }
            ]
          },
          "side": {
            "enum": ["left", "right", "top", "bottom"]
          },
          "relationshipWidth": {
            "type": "number",
            "minimum": 0.5
          },
          "point": {
            "type": "array",
            "prefixItems": [
              { "type": "number" },
              { "type": "number" }
            ],
            "items": false,
            "minItems": 2,
            "maxItems": 2
          },
          "componentType": {
            "enum": ["frontend", "backend", "database", "cloud", "security", "messagebus", "external"]
          },
          "nodeIcon": {
            "description": "Decorative corner icon. Omit the icon field for the type default; none hides it. Does not change type, color, or legend grouping.",
            "enum": ["calendar", "clock", "person", "briefcase", "flag", "moon", "frontend", "backend", "database", "cloud", "security", "messagebus", "external", "start", "active", "waiting", "success", "failure", "neutral", "none"]
          },
          "brandMark": {
            "oneOf": [
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 2048,
                "anyOf": [
                  { "maxLength": 80, "pattern": "^[^\\r\\n]+$" },
                  { "pattern": "^https?://" }
                ]
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": ["url", "sha256"],
                "properties": {
                  "url": { "type": "string", "minLength": 8, "maxLength": 2048, "pattern": "^https?://" },
                  "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" }
                }
              }
            ]
          },
          "variant": {
            "enum": ["default", "emphasis", "security", "dashed"]
          },
          "legendMode": {
            "enum": ["auto", "all", "hidden"]
          },
          "legendEntry": {
            "type": "object",
            "additionalProperties": false,
            "minProperties": 1,
            "properties": {
              "label": { "type": "string", "minLength": 1, "maxLength": 80 },
              "visible": { "type": "boolean" }
            }
          },
          "guidedViews": {
            "type": "array",
            "maxItems": 5,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["id", "label", "focus"],
              "properties": {
                "id": { "$ref": "#/$defs/id" },
                "label": { "type": "string", "minLength": 1, "maxLength": 48 },
                "focus": {
                  "type": "array",
                  "minItems": 1,
                  "items": { "$ref": "#/$defs/id" }
                },
                "note": { "type": "string", "maxLength": 140 }
              }
            }
          },
          "repository": {
            "type": "object",
            "additionalProperties": false,
            "required": ["url", "revision"],
            "properties": {
              "url": {
                "type": "string",
                "minLength": 1
              },
              "provider": { "enum": ["github", "gitee"] },
              "link_mode": { "enum": ["web", "local-only"] },
              "revision": { "type": "string", "pattern": "^[a-fA-F0-9]{40}$" }
            }
          },
          "sourceReferences": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["path"],
              "properties": {
                "path": { "type": "string", "minLength": 1, "maxLength": 240 },
                "line": { "type": "integer", "minimum": 1 },
                "end_line": { "type": "integer", "minimum": 1 },
                "label": { "type": "string", "minLength": 1, "maxLength": 48 }
              }
            }
          },
          "cards": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": ["dot", "title", "items"],
              "properties": {
                "dot": { "enum": ["cyan", "emerald", "violet", "amber", "rose", "orange", "slate"] },
                "title": { "type": "string", "minLength": 1 },
                "items": {
                  "type": "array",
                  "items": { "type": "string" }
                }
              }
            }
          }
        }
      }
      
    • dataflow.schema.json 6.2 KB
      {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://github.com/tt-a1i/archify/schemas/dataflow.schema.json",
        "title": "Archify Data Flow Diagram",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "diagram_type",
          "meta",
          "stages",
          "nodes",
          "flows"
        ],
        "properties": {
          "schema_version": {
            "const": 1
          },
          "diagram_type": {
            "const": "dataflow"
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "title",
              "output"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "translations": {
                "$ref": "common.schema.json#/$defs/translations"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "$ref": "common.schema.json#/$defs/portableOutputPath"
              },
              "animation": {
                "$ref": "common.schema.json#/$defs/animation"
              },
              "visual_preset": {
                "$ref": "common.schema.json#/$defs/visualPreset"
              },
              "quality_profile": {
                "$ref": "common.schema.json#/$defs/qualityProfile"
              },
              "repository": {
                "$ref": "common.schema.json#/$defs/repository"
              },
              "views": {
                "$ref": "common.schema.json#/$defs/guidedViews"
              },
              "legend": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": { "$ref": "common.schema.json#/$defs/legendMode" },
                  "entries": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "default": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "emphasis": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "security": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "dashed": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "database": { "$ref": "common.schema.json#/$defs/legendEntry" }
                    }
                  }
                }
              },
              "viewBox": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number",
                    "minimum": 360
                  },
                  {
                    "type": "number",
                    "minimum": 360
                  }
                ],
                "items": false,
                "minItems": 2,
                "maxItems": 2
              }
            }
          },
          "stages": {
            "type": "array",
            "minItems": 2,
            "maxItems": 5,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "label"
              ],
              "properties": {
                "label": {
                  "type": "string",
                  "minLength": 1
                }
              }
            }
          },
          "nodes": {
            "type": "array",
            "minItems": 2,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "type",
                "label",
                "stage",
                "row"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "type": {
                  "$ref": "common.schema.json#/$defs/componentType"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "sublabel": {
                  "type": "string"
                },
                "tag": {
                  "type": "string"
                },
                "icon": { "$ref": "common.schema.json#/$defs/nodeIcon" },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "sources": {
                  "$ref": "common.schema.json#/$defs/sourceReferences"
                },
                "stage": {
                  "type": "integer",
                  "minimum": 0
                },
                "row": {
                  "type": "integer",
                  "minimum": 0
                },
                "width": {
                  "type": "number",
                  "minimum": 48
                },
                "height": {
                  "type": "number",
                  "minimum": 36
                },
                "yOffset": {
                  "type": "number"
                }
              }
            }
          },
          "flows": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "from",
                "to",
                "label"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "from": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "to": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "classification": {
                  "type": "string"
                },
                "variant": {
                  "$ref": "common.schema.json#/$defs/variant"
                },
                "route": {
                  "enum": [
                    "auto",
                    "straight",
                    "vertical-channel",
                    "bottom-channel",
                    "top-channel"
                  ]
                },
                "fromSide": {
                  "$ref": "common.schema.json#/$defs/side"
                },
                "toSide": {
                  "$ref": "common.schema.json#/$defs/side"
                },
                "channelX": {
                  "type": "number"
                },
                "channelY": {
                  "type": "number"
                },
                "labelAt": {
                  "$ref": "common.schema.json#/$defs/point"
                },
                "labelDx": {
                  "type": "number"
                },
                "labelDy": {
                  "type": "number"
                },
                "labelSegment": {
                  "type": "integer",
                  "minimum": 0
                },
                "via": {
                  "type": "array",
                  "items": {
                    "$ref": "common.schema.json#/$defs/point"
                  }
                },
                "width": {
                  "$ref": "common.schema.json#/$defs/relationshipWidth"
                }
              }
            }
          },
          "cards": {
            "$ref": "common.schema.json#/$defs/cards"
          }
        }
      }
      
    • lifecycle.schema.json 6.9 KB
      {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://github.com/tt-a1i/archify/schemas/lifecycle.schema.json",
        "title": "Archify Lifecycle Diagram",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "diagram_type",
          "meta",
          "lanes",
          "states",
          "transitions"
        ],
        "properties": {
          "schema_version": {
            "enum": [
              1,
              2
            ]
          },
          "diagram_type": {
            "const": "lifecycle"
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "title",
              "output"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "translations": {
                "$ref": "common.schema.json#/$defs/translations"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "$ref": "common.schema.json#/$defs/portableOutputPath"
              },
              "animation": {
                "$ref": "common.schema.json#/$defs/animation"
              },
              "visual_preset": {
                "$ref": "common.schema.json#/$defs/visualPreset"
              },
              "quality_profile": {
                "$ref": "common.schema.json#/$defs/qualityProfile"
              },
              "repository": {
                "$ref": "common.schema.json#/$defs/repository"
              },
              "views": {
                "$ref": "common.schema.json#/$defs/guidedViews"
              },
              "legend": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": { "$ref": "common.schema.json#/$defs/legendMode" },
                  "entries": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "start": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "active": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "waiting": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "decision": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "success": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "failure": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "neutral": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "external": { "$ref": "common.schema.json#/$defs/legendEntry" }
                    }
                  }
                }
              },
              "viewBox": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number",
                    "minimum": 420
                  },
                  {
                    "type": "number",
                    "minimum": 300
                  }
                ],
                "items": false,
                "minItems": 2,
                "maxItems": 2
              }
            }
          },
          "lanes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 4,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "label"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                }
              }
            }
          },
          "states": {
            "type": "array",
            "minItems": 2,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "type",
                "label",
                "lane",
                "col"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "type": {
                  "enum": [
                    "start",
                    "active",
                    "waiting",
                    "decision",
                    "success",
                    "failure",
                    "neutral",
                    "external"
                  ]
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "sublabel": {
                  "type": "string"
                },
                "tag": {
                  "type": "string"
                },
                "icon": { "$ref": "common.schema.json#/$defs/nodeIcon" },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "sources": {
                  "$ref": "common.schema.json#/$defs/sourceReferences"
                },
                "step": {
                  "type": "string"
                },
                "lane": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "col": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 4
                },
                "width": {
                  "type": "number",
                  "minimum": 48
                },
                "height": {
                  "type": "number",
                  "minimum": 36
                },
                "yOffset": {
                  "type": "number"
                }
              }
            }
          },
          "transitions": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "from",
                "to"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "from": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "to": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                },
                "variant": {
                  "$ref": "common.schema.json#/$defs/variant"
                },
                "route": {
                  "enum": [
                    "auto",
                    "straight",
                    "drop",
                    "bottom-channel",
                    "top-channel",
                    "right-channel",
                    "left-channel"
                  ]
                },
                "fromSide": {
                  "$ref": "common.schema.json#/$defs/side"
                },
                "toSide": {
                  "$ref": "common.schema.json#/$defs/side"
                },
                "channelX": {
                  "type": "number"
                },
                "channelY": {
                  "type": "number"
                },
                "cornerRadius": {
                  "type": "number",
                  "minimum": 0
                },
                "labelAt": {
                  "$ref": "common.schema.json#/$defs/point"
                },
                "labelDx": {
                  "type": "number"
                },
                "labelDy": {
                  "type": "number"
                },
                "labelSegment": {
                  "type": "integer",
                  "minimum": 0
                },
                "via": {
                  "type": "array",
                  "items": {
                    "$ref": "common.schema.json#/$defs/point"
                  }
                },
                "width": {
                  "$ref": "common.schema.json#/$defs/relationshipWidth"
                }
              }
            }
          },
          "cards": {
            "$ref": "common.schema.json#/$defs/cards"
          }
        }
      }
      
    • README.md 14.4 KB
      # Archify JSON IR Schemas
      
      Each typed renderer consumes a JSON intermediate representation (IR) validated
      against one of the schemas in this folder before any layout work happens.
      
      ## Files
      
      | Schema | Governs | Structural arrays |
      |--------|---------|-------------------|
      | `workflow.schema.json` | `diagram_type: "workflow"` | `lanes`, `phases`, `groups`, `mainPath`, `nodes`, `edges` |
      | `sequence.schema.json` | `diagram_type: "sequence"` | `participants`, `segments`, `messages`, `activations` |
      | `dataflow.schema.json` | `diagram_type: "dataflow"` | `stages`, `nodes`, `flows` |
      | `lifecycle.schema.json` | `diagram_type: "lifecycle"` | `lanes`, `states`, `transitions` |
      | `architecture.schema.json` | `diagram_type: "architecture"` | `components`, `boundaries`, `connections` |
      | `common.schema.json` | shared `$defs` only (no top-level document) | — |
      
      Every diagram schema requires `schema_version`, `diagram_type`, `meta` (with
      `title` and a durable portable `output`), and its structural arrays — except `segments`, `activations`, and
      `cards`, which are optional — and sets `additionalProperties: false` at every
      level, so unknown fields are rejected rather than silently ignored.
      
      Every `meta` object also accepts `animation: "trace"` for opt-in SVG/CSS motion
      in generated HTML. Omit it, or set `"none"`, for the default static output.
      It also accepts `locale`, any well-formed language tag (schema pattern
      `^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$`). The field selects the fixed Viewer UI,
      renderer-owned default legend and accessibility copy, document-title suffix,
      and `<html lang>` value; it does not translate authored strings. `en` and
      `zh-CN` are built-in catalogs; any other tag needs a matching `translations`
      object (see below) or the renderer falls back to English and discloses it.
      Omitting `locale` preserves legacy behavior and resolves to English.
      Malformed locale tags fail schema validation instead of being guessed or
      silently rewritten.
      
      `meta.translations` supplies the Viewer message catalog for a `locale` with no
      built-in catalog, as data: an object mapping canonical message keys (see
      `catalogKeys()` in `renderers/shared/i18n.mjs`) to translated strings whose
      `{placeholder}` tokens match the English source. A key that is missing,
      unrecognized, or has mismatched placeholders falls back to English rather than
      failing the render; `validate`/`render`/`deliver` report the resulting
      coverage to stderr. Spanish uses the reusable `examples/locales/es.json`
      catalog; dev inputs that previously used only `locale: "es"` now need this
      object in `meta.translations` to retain Spanish UI.
      `visual_preset` accepts `classic` (the stable default), `signal-flow` (luminous
      motion-forward presentation), `blueprint` (high-contrast engineering review),
      or `editorial` (warm publication-style design review and documentation).
      Presets change only viewer styling; they do not alter semantic IDs or geometry.
      Sequence `meta` additionally accepts `column_fit`. The default `fixed` keeps
      the historical 108px column gap and 86px participant boxes, so an authored
      diagram renders at the same coordinates no matter how wide its viewBox is.
      `spread` derives the gap and box width from the viewBox instead, which turns a
      wide canvas into column distance and label room rather than empty space on the
      right. Lane order, IDs, and message semantics are unchanged either way.
      
      `meta.views` is retired. The schemas still accept the old guided-view shape so
      existing files keep validating, but renderers ignore it; do not author it.
      
      ### Legend presentation contract
      
      Every `meta` object accepts the same optional legend shape without changing
      the schema version already selected for that renderer:
      
      ```json
      "legend": {
        "mode": "auto",
        "entries": {
          "security": { "label": "restricted data", "visible": true }
        }
      }
      ```
      
      `mode` is `auto` (the default), `all`, or `hidden`. `auto` includes only kinds
      present in typed IR; `all` includes the renderer's full stable catalog;
      `hidden` removes the complete legend and takes precedence over entry overrides.
      Architecture documents that omit an explicit `viewBox` size that automatic
      viewBox from the same measured resolved legend footprint used for final SVG
      layout. Across all renderers, legacy documents that omit `meta.legend` use a
      compatibility-safe implicit `auto`: if the resolved legend cannot fit an
      explicit authored viewBox without overlap, Archify omits the complete legend
      instead of turning a previously valid schema-v1 document into a hard failure.
      Once an author adds `meta.legend` (including explicit `mode: "auto"`), the
      layout is intentional and unfit labels or bands fail with a path-prefixed
      diagnostic. An entry may set a non-empty, bounded `label`, boolean `visible`,
      or both.
      `visible: false` removes a resolved entry and `visible: true` forces a supported
      but unused kind into the visual legend. Unknown kinds and properties fail
      strict validation.
      
      Supported keys are renderer-owned:
      
      | Renderer | `meta.legend.entries` keys |
      |---|---|
      | Architecture | `frontend`, `backend`, `database`, `cloud`, `security`, `messagebus`, `external` |
      | Workflow | `frontend`, `backend`, `security`, `messagebus`, `database`, `cloud`, `external` |
      | Sequence | `emphasis`, `return`, `security`, `dashed`, `default` |
      | Dataflow | `emphasis`, `security`, `dashed`, `database`, `default` |
      | Lifecycle | `start`, `active`, `waiting`, `decision`, `success`, `failure`, `neutral`, `external` |
      
      Labels are presentation only: they do not rename the stable kind, change
      nodes/relationships, or create Semantic Lens edge facts. Sequence message and
      Dataflow flow-variant entries are visual keys. Component/state entries backed
      by exact compiled node facts receive the interactive Semantic Legend bridge;
      this includes Dataflow `database` when a real `nodes[].type: "database"` fact
      exists.
      
      Every relationship collection (`connections`, `edges`, `messages`, `flows`, and
      `transitions`) accepts an optional author-controlled `id` using the shared ID
      pattern. The renderer keeps its source-order runtime key separately, while the
      authored ID enables a stable `#relation=<id>` viewer link that survives array
      reordering. ID-less documents remain valid and their relationship pins stay
      local to the current page.
      
      Every semantic node collection (`components`, `nodes`, `participants`, and
      `states`) also accepts one optional `brand`: either a canonical string returned
      by `archify brands --json`, or a digest-pinned `{ "url", "sha256" }` object
      returned by `archify brands capture <url> --json`. Known IDs and known-brand
      domains use the bundled vector catalogue. Unknown URLs must be captured in that
      explicit command before authoring; render and validate never perform an
      unpinned network capture. Unsafe, unavailable, changed, or unsupported content
      fails closed with a brand diagnostic. Omitted `brand` preserves the prior
      output.
      
      ## schema_version policy
      
      Workflow supports schema versions 1 and 2. Version 1 remains the fixed-layout
      compatibility contract; version 2 opts into the readable workflow compiler and
      can be produced explicitly with `archify migrate workflow ... --to-schema 2`.
      Lifecycle also supports versions 1 and 2 with the same fields. Version 1 keeps
      the fixed three-band layout; version 2 renders one row per lane on a shared
      column grid (see the [lifecycle renderer](../renderers/lifecycle/README.md)).
      Lifecycle has no migration command: to adopt v2, set `schema_version: 2`,
      re-place lower-lane `col` values on the shared grid (v1 column `N` sat under
      main column `N + 2`), and drop coordinates authored for the v1 canvas
      (`viewBox`, `via`, `channelX`, `channelY`, `labelAt`).
      The other three diagram schemas keep `schema_version` pinned to `1`; they have
      no schema-version migration command. For any of the five diagram types, repair
      a legacy missing or nonportable `meta.output` in the source and run `validate`.
      For a workflow v1-to-v2 migration specifically, `migrate workflow` also accepts
      `--output reports/diagram.html` to put that portable value in the separate v2
      destination without changing the legacy source.
      
      Workflow also accepts optional `semanticChecks`. `allowedRoots` and
      `allowedTerminals` close the set of intentional graph sources and sinks;
      `requiredEdges` requires exact authored relationships; and `requiredPaths`
      requires directed reachability while allowing intermediate nodes. The compiler
      evaluates these facts before layout and returns typed `workflow/*` diagnostics.
      The field is additive and geometry-neutral: omitting it preserves existing
      workflow behavior and including a satisfied contract does not change SVG or
      layout-receipt bytes.
      
      A file that validates today must keep validating and rendering within its
      declared version throughout the 2.x release line. The explicitly reviewed
      portable-output hardening is the one exception: older v1 documents that omit
      `meta.output` must add a portable POSIX-relative `.html` path (for example,
      `reports/diagram.html`); ordinary explicit CLI output arguments do not replace
      this durable authored value. The workflow-only v1-to-v2 migration command may
      instead receive that value explicitly as `--output reports/diagram.html`; it
      writes the value only to its separate validated destination. Additive viewer,
      accessibility, and presentation improvements may enhance generated HTML, but
      they must not reinterpret authored IR or turn a previously valid profile-less
      v1 file into a new hard layout failure. Breaking IR changes require a new
      version; additive, backwards-compatible fields do not.
      
      ## Shared definitions (common.schema.json)
      
      The five diagram schemas reference `common.schema.json#/$defs/...`:
      
      - `id` — element identifiers, pattern `^[a-zA-Z][a-zA-Z0-9_-]*$`
      - `point` — an `[x, y]` pair of numbers (used by `via` and `labelAt`)
      - `componentType` — `frontend`, `backend`, `database`, `cloud`, `security`,
        `messagebus`, `external`
      - `locale` — a well-formed renderer locale tag (`en` and `zh-CN` are built in;
        any other tag needs a matching `translations` object)
      - `translations` — canonical message key → translated string, for a `locale`
        with no built-in catalog
      - `portableOutputPath` — the portable POSIX-relative `.html` path used by
        `meta.output`; see the two output-path boundaries in the
        [delivery contract](../references/delivery-contract.md#output-path-contracts)
      - `brandMark` — one optional built-in brand ID or explicit HTTP(S) site URL
      - `variant` — `default`, `emphasis`, `security`, `dashed` (sequence messages
        extend this list locally with `return`)
      - `legendMode` and `legendEntry` — the shared strict mode and label/visibility
        override shapes used by each renderer-owned key map
      - `guidedViews` — the retired `meta.views` shape, still accepted and ignored
      - `cards` — the summary-card blocks rendered below the SVG
      
      Lifecycle state `type` is mode-specific (`start`/`active`/`waiting`/...) and
      stays in `lifecycle.schema.json`.
      
      The JSON Schema definition is the portable contract's structurally expressible
      preflight. The shipped generated validator wrapper and CLI additionally enforce
      byte-based component limits and the complete runtime path contract; consumers
      that need the same cross-platform acceptance boundary should use that wrapper.
      
      ## Runtime validation
      
      At development time, `scripts/generate-validators.mjs` compiles all five
      schemas with ajv's draft 2020-12 standalone generator using `strict: true` and
      `allErrors: true`. The generated `renderers/shared/generated-validators.mjs`
      is committed and shipped with the skill, so runtime validation has no npm or
      network dependency. `renderers/shared/validator.mjs` applies the matching
      standalone validator before the renderer's own layout checks.
      The shared loader then checks cross-collection facts that JSON Schema cannot
      express cleanly here: duplicate view IDs, duplicate focus IDs, focus IDs that do
      not exist in the diagram's semantic collection, and duplicate authored
      relationship IDs within the mode's relationship collection.
      
      All five modes support opt-in, revision-pinned repository evidence.
      `meta.repository` names the repository URL and full commit SHA, with optional
      `provider` (`github` or `gitee`) and `link_mode` (`web` or `local-only`; see the
      authoring contract); a node may carry one to three `sources` with repo-relative POSIX paths, optional line
      ranges, and optional labels. Sources are authored on the mode's own node
      collection — Architecture `components`, Workflow and Data Flow `nodes`,
      Sequence `participants`, Lifecycle `states` — and the verified payload is keyed
      by node id. Shape is schema-checked, then the renderer requires
      `--repo-root`: the local Git origin must match, and Git must prove the commit,
      blobs, and requested lines. Verified evidence is embedded outside the canonical
      SVG for the Semantic Passport and Node Finder; ordinary documents and visual
      exports carry no repository evidence.
      
      ## Visual quality and engineering truth
      
      `meta.quality_profile` and `meta.engineering_profile` answer different
      questions. `quality_profile` is available in all five modes and controls how
      strictly Archify judges composition. `engineering_profile` is an optional
      Architecture-only semantic contract; omitting it preserves the ordinary v1
      behavior.
      
      The first engineering profile is `deployment-ownership`. Enable it only when
      the user wants a fail-closed deployment review and the source facts are known.
      It requires every non-external component to name an owner in `tag` and belong
      to exactly one `region`; the document must contain both `region` and
      `security-group` boundaries; every `database` must be inside a
      `security-group`; each security group must contain members from one shared
      region; and every connection whose region or security-group membership changes
      must name the real crossing mechanism in `label`.
      
      The profile validates only authored IR. It does not discover infrastructure,
      infer owners, or prove that a diagram matches a live environment. If a fact is
      unknown, leave the profile unset or obtain the fact instead of inventing it.
      
      `npm test` runs the generator in check mode and fails when the committed
      validators drift from their schemas.
      
      ## Error format
      
      Schema violations exit non-zero. Each ajv error is reported on its own line as
      the instance path — annotated with the nearest enclosing element's `id` or
      `label` — followed by the message and parameters:
      
      ```text
      workflow schema validation failed:
        /nodes/3 (id/label: "router") must NOT have additional properties {"additionalProperty":"colour"}
      ```
      
      Schemas catch shape errors (types, enums, ranges, unknown fields); geometry
      problems such as overlaps and label collisions are the renderers' job.
      
    • sequence.schema.json 5.9 KB
      {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://github.com/tt-a1i/archify/schemas/sequence.schema.json",
        "title": "Archify Sequence Diagram",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "diagram_type",
          "meta",
          "participants",
          "messages"
        ],
        "properties": {
          "schema_version": {
            "const": 1
          },
          "diagram_type": {
            "const": "sequence"
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "title",
              "output"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "translations": {
                "$ref": "common.schema.json#/$defs/translations"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "$ref": "common.schema.json#/$defs/portableOutputPath"
              },
              "animation": {
                "$ref": "common.schema.json#/$defs/animation"
              },
              "visual_preset": {
                "$ref": "common.schema.json#/$defs/visualPreset"
              },
              "quality_profile": {
                "$ref": "common.schema.json#/$defs/qualityProfile"
              },
              "column_fit": {
                "description": "Horizontal participant layout. Omit this field or use fixed for the stable 86px boxes and 108px gap. Use spread when a wide viewBox would leave unused horizontal space or meaningful participant labels do not fit the fixed boxes; spread derives wider boxes and gaps from the viewBox without changing participant order or message semantics.",
                "enum": ["fixed", "spread"]
              },
              "repository": {
                "$ref": "common.schema.json#/$defs/repository"
              },
              "views": {
                "$ref": "common.schema.json#/$defs/guidedViews"
              },
              "legend": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": { "$ref": "common.schema.json#/$defs/legendMode" },
                  "entries": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "default": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "emphasis": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "security": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "dashed": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "return": { "$ref": "common.schema.json#/$defs/legendEntry" }
                    }
                  }
                }
              },
              "viewBox": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number",
                    "minimum": 480
                  },
                  {
                    "type": "number",
                    "minimum": 480
                  }
                ],
                "items": false,
                "minItems": 2,
                "maxItems": 2
              }
            }
          },
          "participants": {
            "type": "array",
            "minItems": 2,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "type",
                "label"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "type": {
                  "$ref": "common.schema.json#/$defs/componentType"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "sublabel": {
                  "type": "string"
                },
                "icon": { "$ref": "common.schema.json#/$defs/nodeIcon" },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "sources": {
                  "$ref": "common.schema.json#/$defs/sourceReferences"
                }
              }
            }
          },
          "segments": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "from",
                "to",
                "label"
              ],
              "properties": {
                "from": {
                  "type": "number"
                },
                "to": {
                  "type": "number"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                }
              }
            }
          },
          "messages": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "from",
                "to",
                "y",
                "label"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "from": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "to": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "y": {
                  "type": "number",
                  "minimum": 160
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "variant": {
                  "enum": [
                    "default",
                    "emphasis",
                    "security",
                    "dashed",
                    "return"
                  ]
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "activations": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "participant",
                "from",
                "to"
              ],
              "properties": {
                "participant": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "from": {
                  "type": "number"
                },
                "to": {
                  "type": "number"
                },
                "type": {
                  "$ref": "common.schema.json#/$defs/componentType"
                }
              }
            }
          },
          "cards": {
            "$ref": "common.schema.json#/$defs/cards"
          }
        }
      }
      
    • workflow.schema.json 9.9 KB
      {
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "$id": "https://github.com/tt-a1i/archify/schemas/workflow.schema.json",
        "title": "Archify Workflow Diagram",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schema_version",
          "diagram_type",
          "meta",
          "lanes",
          "nodes",
          "edges"
        ],
        "properties": {
          "schema_version": {
            "enum": [
              1,
              2
            ]
          },
          "diagram_type": {
            "const": "workflow"
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "title",
              "output"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "translations": {
                "$ref": "common.schema.json#/$defs/translations"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "$ref": "common.schema.json#/$defs/portableOutputPath"
              },
              "animation": {
                "enum": [
                  "trace",
                  "none"
                ]
              },
              "visual_preset": {
                "enum": [
                  "classic",
                  "signal-flow",
                  "blueprint",
                  "editorial"
                ]
              },
              "quality_profile": {
                "enum": [
                  "standard",
                  "showcase"
                ]
              },
              "repository": {
                "$ref": "common.schema.json#/$defs/repository"
              },
              "views": {
                "$ref": "common.schema.json#/$defs/guidedViews"
              },
              "legend": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": { "$ref": "common.schema.json#/$defs/legendMode" },
                  "entries": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "frontend": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "backend": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "database": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "cloud": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "security": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "messagebus": { "$ref": "common.schema.json#/$defs/legendEntry" },
                      "external": { "$ref": "common.schema.json#/$defs/legendEntry" }
                    }
                  }
                }
              },
              "viewBox": {
                "type": "array",
                "prefixItems": [
                  {
                    "type": "number",
                    "minimum": 700
                  },
                  {
                    "type": "number",
                    "minimum": 240
                  }
                ],
                "items": false,
                "minItems": 2,
                "maxItems": 2
              }
            }
          },
          "lanes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "label"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "variant": {
                  "enum": [
                    "normal",
                    "exception"
                  ]
                }
              }
            }
          },
          "phases": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "label",
                "fromCol",
                "toCol"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "fromCol": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 5
                },
                "toCol": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 5
                },
                "variant": {
                  "enum": [
                    "default",
                    "emphasis",
                    "security",
                    "dashed"
                  ]
                }
              }
            }
          },
          "groups": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "label",
                "lane",
                "fromCol",
                "toCol"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "lane": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "fromCol": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 5
                },
                "toCol": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 5
                },
                "variant": {
                  "enum": [
                    "default",
                    "emphasis",
                    "security",
                    "dashed"
                  ]
                }
              }
            }
          },
          "mainPath": {
            "type": "array",
            "minItems": 2,
            "items": {
              "$ref": "common.schema.json#/$defs/id"
            }
          },
          "semanticChecks": {
            "type": "object",
            "additionalProperties": false,
            "minProperties": 1,
            "properties": {
              "allowedRoots": {
                "type": "array",
                "items": {
                  "$ref": "common.schema.json#/$defs/id"
                }
              },
              "allowedTerminals": {
                "type": "array",
                "items": {
                  "$ref": "common.schema.json#/$defs/id"
                }
              },
              "requiredEdges": {
                "type": "array",
                "items": {
                  "$ref": "#/$defs/semanticRelation"
                }
              },
              "requiredPaths": {
                "type": "array",
                "items": {
                  "$ref": "#/$defs/semanticRelation"
                }
              }
            }
          },
          "nodes": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "lane",
                "col",
                "type",
                "label"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "lane": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "col": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 5
                },
                "type": {
                  "$ref": "common.schema.json#/$defs/componentType"
                },
                "label": {
                  "type": "string",
                  "minLength": 1
                },
                "sublabel": {
                  "type": "string"
                },
                "tag": {
                  "type": "string"
                },
                "icon": { "$ref": "common.schema.json#/$defs/nodeIcon" },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "sources": {
                  "$ref": "common.schema.json#/$defs/sourceReferences"
                },
                "width": {
                  "type": "number",
                  "minimum": 32
                },
                "height": {
                  "type": "number",
                  "minimum": 32
                },
                "yOffset": {
                  "type": "number"
                }
              }
            }
          },
          "edges": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "from",
                "to"
              ],
              "properties": {
                "id": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "from": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "to": {
                  "$ref": "common.schema.json#/$defs/id"
                },
                "label": {
                  "type": "string"
                },
                "variant": {
                  "$ref": "common.schema.json#/$defs/variant"
                },
                "role": {
                  "enum": [
                    "main",
                    "branch",
                    "async",
                    "return",
                    "error"
                  ]
                },
                "fromSide": {
                  "$ref": "#/$defs/side"
                },
                "toSide": {
                  "$ref": "#/$defs/side"
                },
                "route": {
                  "enum": [
                    "auto",
                    "straight",
                    "drop",
                    "outside-right",
                    "return-left",
                    "bottom-channel",
                    "up-channel"
                  ]
                },
                "via": {
                  "type": "array",
                  "items": {
                    "$ref": "common.schema.json#/$defs/point"
                  }
                },
                "labelAt": {
                  "$ref": "common.schema.json#/$defs/point"
                },
                "labelDx": {
                  "type": "number"
                },
                "labelDy": {
                  "type": "number"
                },
                "labelSegment": {
                  "type": "integer",
                  "minimum": 0
                },
                "channelX": {
                  "type": "number"
                },
                "channelY": {
                  "type": "number"
                },
                "bias": {
                  "type": "number",
                  "minimum": 0,
                  "maximum": 1
                },
                "width": {
                  "type": "number",
                  "minimum": 0.5
                }
              }
            }
          },
          "cards": {
            "$ref": "common.schema.json#/$defs/cards"
          }
        },
        "$defs": {
          "semanticRelation": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "from",
              "to"
            ],
            "properties": {
              "from": {
                "$ref": "common.schema.json#/$defs/id"
              },
              "to": {
                "$ref": "common.schema.json#/$defs/id"
              }
            }
          },
          "side": {
            "enum": [
              "left",
              "right",
              "top",
              "bottom"
            ]
          }
        }
      }
      
  • scripts
    • check-render-output.mjs 60.2 KB · in bundle
    • check-update.mjs 57.6 KB · in bundle
    • delivery-update-child.mjs 1.1 KB · in bundle
    • generate-brand-marks.mjs 5 KB · in bundle
    • generate-validators.mjs 3.6 KB · in bundle
    • render-examples.mjs 1.2 KB · in bundle
    • update-contract.mjs 6.6 KB · in bundle
  • test
    • fixtures
      • architecture-first-draft
        • audit-luna.architecture.json 5.6 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "跨租户审计日志导出与脱敏编排服务(含异步导出、留存策略和人工复核边界)",
              "locale": "zh-CN",
              "quality_profile": "showcase",
              "output": "audit-luna.html"
            },
            "components": [
              {
                "id": "caller",
                "type": "external",
                "label": "调用方",
                "sublabel": "tenantId + range",
                "pos": [
                  40,
                  330
                ],
                "size": [
                  150,
                  66
                ]
              },
              {
                "id": "entry",
                "type": "backend",
                "label": "审计导出入口",
                "sublabel": "requestAuditExport",
                "pos": [
                  270,
                  330
                ],
                "size": [
                  170,
                  66
                ]
              },
              {
                "id": "policy",
                "type": "security",
                "label": "策略配置",
                "sublabel": "policy · 配置声明",
                "pos": [
                  275,
                  105
                ],
                "size": [
                  180,
                  70
                ],
                "tag": "180d / 10000 rows"
              },
              {
                "id": "scheduler",
                "type": "backend",
                "label": "导出计划器",
                "sublabel": "createExport().schedule",
                "pos": [
                  510,
                  330
                ],
                "size": [
                  190,
                  66
                ]
              },
              {
                "id": "query",
                "type": "database",
                "label": "审计日志查询",
                "sublabel": "queryAuditLog · 内存占位实现",
                "pos": [
                  750,
                  210
                ],
                "size": [
                  205,
                  70
                ],
                "tag": "source rows"
              },
              {
                "id": "redactor",
                "type": "security",
                "label": "脱敏处理",
                "sublabel": "redact(row, redactFields)",
                "pos": [
                  750,
                  390
                ],
                "size": [
                  205,
                  70
                ],
                "tag": "token / ipAddress"
              },
              {
                "id": "writer",
                "type": "cloud",
                "label": "对象结果写出",
                "sublabel": "writeObject · 路径返回",
                "pos": [
                  1010,
                  390
                ],
                "size": [
                  190,
                  70
                ],
                "tag": "audit-export-bucket"
              },
              {
                "id": "notifier",
                "type": "backend",
                "label": "完成通知器",
                "sublabel": "notifyReady",
                "pos": [
                  1260,
                  300
                ],
                "size": [
                  170,
                  66
                ]
              },
              {
                "id": "topic",
                "type": "messagebus",
                "label": "通知主题",
                "sublabel": "audit-export-ready · 配置通道",
                "pos": [
                  1480,
                  195
                ],
                "size": [
                  200,
                  70
                ]
              },
              {
                "id": "review",
                "type": "messagebus",
                "label": "人工复核队列",
                "sublabel": "requestReview · 可调用声明",
                "pos": [
                  1480,
                  400
                ],
                "size": [
                  200,
                  70
                ],
                "tag": "privacy-review"
              }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "导出编排运行时(已实现调用链)",
                "wraps": [
                  "entry",
                  "scheduler",
                  "query",
                  "redactor",
                  "writer",
                  "notifier"
                ],
                "pad": 26
              },
              {
                "kind": "security-group",
                "label": "配置驱动的数据边界",
                "wraps": [
                  "policy",
                  "redactor",
                  "writer"
                ],
                "pad": 18
              }
            ],
            "connections": [
              {
                "id": "request",
                "from": "caller",
                "to": "entry",
                "label": "requestAuditExport(request)",
                "variant": "emphasis"
              },
              {
                "id": "policy-entry",
                "from": "policy",
                "to": "entry",
                "label": "导入 policy"
              },
              {
                "id": "policy-schedule",
                "from": "policy",
                "to": "scheduler",
                "label": "maxRowsPerPart"
              },
              {
                "id": "schedule",
                "from": "entry",
                "to": "scheduler",
                "label": "schedule(job) → queued"
              },
              {
                "id": "plan-query",
                "from": "scheduler",
                "to": "query",
                "label": "run → queryAuditLog"
              },
              {
                "id": "query-redact",
                "from": "query",
                "to": "redactor",
                "label": "rows"
              },
              {
                "id": "redact-write",
                "from": "redactor",
                "to": "writer",
                "label": "redacted rows → writeObject"
              },
              {
                "id": "retention",
                "from": "policy",
                "to": "writer",
                "label": "objectStore + retentionDays"
              },
              {
                "id": "ready",
                "from": "writer",
                "to": "notifier",
                "label": "files → notifyReady"
              },
              {
                "id": "event",
                "from": "notifier",
                "to": "topic",
                "label": "audit-export-ready",
                "variant": "emphasis"
              },
              {
                "id": "review-declared",
                "from": "policy",
                "to": "review",
                "label": "reviewQueue 配置",
                "variant": "dashed"
              },
              {
                "id": "review-api",
                "from": "notifier",
                "to": "review",
                "label": "requestReview(job, reason, queue)",
                "variant": "dashed"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "实际执行链",
                "items": [
                  "入口校验 tenantId 与 range 后返回 queued 计划",
                  "run 异步查询、逐行脱敏、写对象并通知完成"
                ]
              },
              {
                "dot": "amber",
                "title": "配置驱动边界",
                "items": [
                  "脱敏字段、分段上限、对象存储名与 180 天留存来自 policy",
                  "queryAuditLog 与 writeObject 是受控 fixture 中的占位实现"
                ]
              },
              {
                "dot": "rose",
                "title": "人工复核状态",
                "items": [
                  "requestReview 只构造 manual-review 对象并未在主链路调用",
                  "reviewQueue 是配置声明,不能据此推断已有消费者或人工处理流程"
                ]
              }
            ]
          }
        • audit-terra.architecture.json 6.2 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "跨租户审计日志导出与脱敏编排服务(含异步导出、留存策略和人工复核边界)",
              "locale": "zh-CN",
              "quality_profile": "showcase",
              "output": "audit-terra.html"
            },
            "components": [
              {
                "id": "caller",
                "type": "external",
                "label": "导出请求调用方",
                "sublabel": "提供 tenantId 与 range",
                "pos": [
                  35,
                  235
                ],
                "size": [
                  150,
                  72
                ]
              },
              {
                "id": "entry",
                "type": "backend",
                "label": "请求入口 requestAuditExport",
                "sublabel": "缺 tenantId 或 range 返回 400",
                "pos": [
                  250,
                  235
                ],
                "size": [
                  190,
                  72
                ]
              },
              {
                "id": "plan",
                "type": "messagebus",
                "label": "导出计划(内存对象)",
                "sublabel": "queued、parts 与 run 闭包",
                "pos": [
                  510,
                  235
                ],
                "size": [
                  180,
                  72
                ]
              },
              {
                "id": "policy",
                "type": "security",
                "label": "策略配置 policy",
                "sublabel": "180 天、字段、分片、名称",
                "pos": [
                  505,
                  55
                ],
                "size": [
                  195,
                  72
                ]
              },
              {
                "id": "execution",
                "type": "backend",
                "label": "exportParts 执行函数",
                "sublabel": "仅由 run 闭包引用,调用者未展示",
                "pos": [
                  510,
                  440
                ],
                "size": [
                  205,
                  74
                ]
              },
              {
                "id": "query-stub",
                "type": "database",
                "label": "审计日志查询桩",
                "sublabel": "按 tenantId 与 part 返回本地示例行",
                "pos": [
                  790,
                  385
                ],
                "size": [
                  195,
                  72
                ]
              },
              {
                "id": "redactor",
                "type": "security",
                "label": "字段脱敏",
                "sublabel": "过滤 policy.redactFields",
                "pos": [
                  790,
                  530
                ],
                "size": [
                  180,
                  72
                ]
              },
              {
                "id": "writer-stub",
                "type": "cloud",
                "label": "结果对象写入桩",
                "sublabel": "返回 bucket/tenantId/行数 路径字符串",
                "pos": [
                  1040,
                  530
                ],
                "size": [
                  220,
                  72
                ]
              },
              {
                "id": "notifier",
                "type": "external",
                "label": "完成通知函数",
                "sublabel": "组装 audit-export-ready 返回对象",
                "pos": [
                  1035,
                  385
                ],
                "size": [
                  220,
                  72
                ]
              },
              {
                "id": "result",
                "type": "external",
                "label": "执行结果(若 run 被调用)",
                "sublabel": "files 与 expiresAfterDays",
                "pos": [
                  1040,
                  690
                ],
                "size": [
                  215,
                  72
                ]
              },
              {
                "id": "review-declaration",
                "type": "external",
                "label": "人工复核(仅声明)",
                "sublabel": "privacy-review 与 requestReview 未接入",
                "pos": [
                  255,
                  55
                ],
                "size": [
                  205,
                  72
                ]
              }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "入口与计划模块边界",
                "wraps": [
                  "entry",
                  "plan",
                  "policy"
                ],
                "pad": 24
              },
              {
                "kind": "region",
                "label": "条件执行中的租户数据处理",
                "wraps": [
                  "execution",
                  "query-stub",
                  "redactor",
                  "writer-stub",
                  "notifier",
                  "result"
                ],
                "pad": 24
              }
            ],
            "connections": [
              {
                "id": "request",
                "from": "caller",
                "to": "entry",
                "label": "导出请求:tenantId + range",
                "variant": "emphasis"
              },
              {
                "id": "schedule",
                "from": "entry",
                "to": "plan",
                "label": "schedule({ tenantId, range })",
                "variant": "emphasis"
              },
              {
                "id": "policy-to-plan",
                "from": "policy",
                "to": "plan",
                "label": "maxRowsPerPart 用于分片"
              },
              {
                "id": "policy-to-execution",
                "from": "policy",
                "to": "execution",
                "label": "脱敏、留存、对象与通知名称"
              },
              {
                "id": "run-reference",
                "from": "plan",
                "to": "execution",
                "label": "run 闭包引用(未见调用)",
                "variant": "dashed"
              },
              {
                "id": "query",
                "from": "execution",
                "to": "query-stub",
                "label": "queryAuditLog(tenantId, part)"
              },
              {
                "id": "redact",
                "from": "query-stub",
                "to": "redactor",
                "label": "示例行 → 移除 token、ipAddress",
                "variant": "security"
              },
              {
                "id": "write",
                "from": "redactor",
                "to": "writer-stub",
                "label": "writeObject(本地路径字符串)"
              },
              {
                "id": "notify",
                "from": "execution",
                "to": "notifier",
                "label": "notifyReady(job, files, topic)",
                "variant": "dashed"
              },
              {
                "id": "return",
                "from": "execution",
                "to": "result",
                "label": "返回 files + expiresAfterDays"
              },
              {
                "id": "review-declared",
                "from": "policy",
                "to": "review-declaration",
                "label": "reviewQueue 配置;无运行时调用",
                "variant": "dashed"
              }
            ],
            "cards": [
              {
                "dot": "emerald",
                "title": "实际入口行为",
                "items": [
                  "入口只校验 tenantId 与 range,然后返回 queued 导出计划。",
                  "计划保存 run 闭包;当前源码未展示任何执行器、队列消费者或调用点。"
                ]
              },
              {
                "dot": "cyan",
                "title": "条件执行时的数据边界",
                "items": [
                  "执行函数把 tenantId 传给查询桩,并按配置移除 token 与 ipAddress。",
                  "对象写入桩只返回路径字符串;未观察到真实对象存储 I/O。",
                  "留存策略只作为 expiresAfterDays 返回,未观察到删除或生命周期执行。"
                ]
              },
              {
                "dot": "amber",
                "title": "通知与复核的未实现边界",
                "items": [
                  "notifyReady 只构造通知对象,未观察到主题发布。",
                  "privacy-review 与 requestReview 存在声明,但未从导出路径调用或入队。"
                ]
              }
            ]
          }
        • queue-luna.architecture.json 5 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "Queue Gateway Architecture",
              "quality_profile": "showcase",
              "output": "queue-luna.html"
            },
            "components": [
              {
                "id": "tenant",
                "type": "external",
                "label": "Tenant Request",
                "sublabel": "tenant + payload",
                "pos": [
                  60,
                  330
                ],
                "size": [
                  150,
                  70
                ]
              },
              {
                "id": "gateway",
                "type": "backend",
                "label": "Job Gateway",
                "sublabel": "submitJob · 202 queued",
                "pos": [
                  280,
                  330
                ],
                "size": [
                  180,
                  70
                ]
              },
              {
                "id": "queue",
                "type": "messagebus",
                "label": "Waiting Queue",
                "sublabel": "in-memory · FIFO shift",
                "tag": "concurrency 3",
                "pos": [
                  535,
                  330
                ],
                "size": [
                  190,
                  70
                ]
              },
              {
                "id": "worker",
                "type": "backend",
                "label": "Worker Runtime",
                "sublabel": "runWorker · async attempts",
                "pos": [
                  805,
                  330
                ],
                "size": [
                  190,
                  70
                ]
              },
              {
                "id": "auth",
                "type": "security",
                "label": "Tenant Auth",
                "sublabel": "tenant-token-service",
                "pos": [
                  535,
                  115
                ],
                "size": [
                  190,
                  70
                ]
              },
              {
                "id": "billing",
                "type": "cloud",
                "label": "Billing Provider",
                "sublabel": "billing-provider",
                "pos": [
                  805,
                  115
                ],
                "size": [
                  190,
                  70
                ]
              },
              {
                "id": "result",
                "type": "database",
                "label": "Result Store",
                "sublabel": "job-result-store",
                "pos": [
                  1080,
                  330
                ],
                "size": [
                  190,
                  70
                ]
              },
              {
                "id": "dead-letter",
                "type": "messagebus",
                "label": "Dead-Letter Queue",
                "sublabel": "after 3",
                "pos": [
                  805,
                  545
                ],
                "size": [
                  190,
                  70
                ]
              }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "Gateway queue runtime",
                "wraps": [
                  "gateway",
                  "queue",
                  "worker"
                ],
                "pad": 32
              },
              {
                "kind": "security-group",
                "label": "Configured service boundaries",
                "wraps": [
                  "auth",
                  "billing",
                  "result"
                ],
                "pad": 28
              }
            ],
            "connections": [
              {
                "id": "submit",
                "from": "tenant",
                "to": "gateway",
                "label": "submitJob(request)",
                "variant": "emphasis"
              },
              {
                "id": "enqueue",
                "from": "gateway",
                "to": "queue",
                "label": "enqueue · 202 jobId",
                "variant": "emphasis"
              },
              {
                "id": "dispatch",
                "from": "queue",
                "to": "worker",
                "label": "dispatch when active < 3"
              },
              {
                "id": "authorize",
                "from": "worker",
                "to": "auth",
                "label": "authorizeTenant",
                "variant": "security",
                "fromSide": "top",
                "toSide": "bottom"
              },
              {
                "id": "token",
                "from": "auth",
                "to": "worker",
                "label": "tenant token",
                "variant": "security",
                "fromSide": "bottom",
                "toSide": "top"
              },
              {
                "id": "bill",
                "from": "worker",
                "to": "billing",
                "label": "callProvider(payload, token)",
                "variant": "emphasis",
                "fromSide": "top",
                "toSide": "bottom"
              },
              {
                "id": "save",
                "from": "worker",
                "to": "result",
                "label": "saveResult(job.id, result)"
              },
              {
                "id": "retry",
                "from": "worker",
                "to": "worker",
                "label": "retry until maxAttempts = 2",
                "variant": "dashed",
                "fromSide": "bottom",
                "toSide": "bottom"
              },
              {
                "id": "dead-letter",
                "from": "worker",
                "to": "dead-letter",
                "label": "final failure → dead-letter",
                "variant": "dashed",
                "fromSide": "bottom",
                "toSide": "top"
              },
              {
                "id": "complete",
                "from": "worker",
                "to": "queue",
                "label": "finally: active--, pump()",
                "variant": "dashed",
                "fromSide": "left",
                "toSide": "bottom"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "Request path",
                "items": [
                  "submitJob validates tenant and payload",
                  "Accepted jobs return status 202 with a jobId",
                  "Queue pump starts work while active < 3"
                ]
              },
              {
                "dot": "emerald",
                "title": "Worker contract",
                "items": [
                  "Each attempt authorizes the tenant",
                  "Billing provider receives payload and token",
                  "Successful results are saved to job-result-store"
                ]
              },
              {
                "dot": "rose",
                "title": "Failure path",
                "items": [
                  "The worker retries through maxAttempts = 2",
                  "After the final failed attempt it returns a dead-letter record with after = 3",
                  "Completion decrements active and pumps the next waiting job"
                ]
              }
            ]
          }
        • queue-sol.architecture.json 5.2 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "Queue Gateway Architecture",
              "locale": "en",
              "quality_profile": "showcase",
              "output": "queue-sol.html"
            },
            "components": [
              {
                "id": "tenant",
                "type": "external",
                "label": "Tenant request",
                "sublabel": "tenant + payload",
                "pos": [
                  40,
                  320
                ],
                "size": [
                  140,
                  64
                ]
              },
              {
                "id": "gateway",
                "type": "backend",
                "label": "Gateway",
                "sublabel": "validate · enqueue · 202",
                "pos": [
                  240,
                  320
                ],
                "size": [
                  160,
                  64
                ]
              },
              {
                "id": "waiting",
                "type": "messagebus",
                "label": "Waiting queue",
                "sublabel": "in-memory FIFO array",
                "pos": [
                  470,
                  320
                ],
                "size": [
                  165,
                  64
                ]
              },
              {
                "id": "queue-controller",
                "type": "backend",
                "label": "Queue controller",
                "sublabel": "pump · active < 3",
                "tag": "concurrency 3",
                "pos": [
                  470,
                  110
                ],
                "size": [
                  165,
                  68
                ]
              },
              {
                "id": "worker",
                "type": "backend",
                "label": "Worker attempt loop",
                "sublabel": "authorize · bill · save",
                "tag": "maxAttempts 2",
                "pos": [
                  710,
                  320
                ],
                "size": [
                  180,
                  68
                ]
              },
              {
                "id": "auth",
                "type": "security",
                "label": "Tenant auth boundary",
                "sublabel": "tenant-token-service",
                "pos": [
                  710,
                  110
                ],
                "size": [
                  180,
                  68
                ]
              },
              {
                "id": "billing",
                "type": "external",
                "label": "Billing boundary",
                "sublabel": "billing-provider",
                "pos": [
                  950,
                  110
                ],
                "size": [
                  170,
                  68
                ]
              },
              {
                "id": "result-store",
                "type": "database",
                "label": "Result boundary",
                "sublabel": "job-result-store",
                "pos": [
                  1190,
                  110
                ],
                "size": [
                  175,
                  68
                ]
              },
              {
                "id": "dead-letter",
                "type": "messagebus",
                "label": "Dead-letter result",
                "sublabel": "after marker: 3",
                "pos": [
                  950,
                  530
                ],
                "size": [
                  175,
                  68
                ]
              }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "Queue gateway process",
                "wraps": [
                  "gateway",
                  "waiting",
                  "queue-controller",
                  "worker"
                ]
              },
              {
                "kind": "region",
                "label": "Configured integration identifiers",
                "wraps": [
                  "auth",
                  "billing",
                  "result-store"
                ]
              }
            ],
            "connections": [
              {
                "id": "submit",
                "from": "tenant",
                "to": "gateway",
                "label": "submit tenant + payload",
                "variant": "emphasis"
              },
              {
                "id": "enqueue",
                "from": "gateway",
                "to": "waiting",
                "label": "enqueue; return 202 queued",
                "variant": "emphasis"
              },
              {
                "id": "queue-ready",
                "from": "waiting",
                "to": "queue-controller",
                "label": "shift next waiting job"
              },
              {
                "id": "dispatch",
                "from": "queue-controller",
                "to": "worker",
                "label": "dispatch while active < 3",
                "variant": "emphasis"
              },
              {
                "id": "authorize",
                "from": "worker",
                "to": "auth",
                "label": "authorize tenant"
              },
              {
                "id": "bill",
                "from": "auth",
                "to": "billing",
                "label": "call provider with token",
                "variant": "security"
              },
              {
                "id": "save",
                "from": "billing",
                "to": "result-store",
                "label": "save successful result",
                "variant": "emphasis"
              },
              {
                "id": "retry",
                "from": "worker",
                "to": "worker",
                "label": "caught error → retry attempt 2",
                "variant": "dashed"
              },
              {
                "id": "dead-letter-path",
                "from": "worker",
                "to": "dead-letter",
                "label": "second caught failure → dead letter",
                "variant": "dashed"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "Admission and waiting",
                "items": [
                  "Missing tenant or payload returns 400",
                  "Accepted jobs enter an in-memory FIFO and return 202 queued"
                ]
              },
              {
                "dot": "emerald",
                "title": "Bounded dispatch",
                "items": [
                  "pump() dispatches only while active < concurrency",
                  "finally decrements active and pumps the next waiting job"
                ]
              },
              {
                "dot": "violet",
                "title": "Configured boundaries",
                "items": [
                  "Every attempt authorizes before the billing provider call",
                  "Successful results are saved to the configured result-store identifier",
                  "The fixture implements these integrations as local functions; no network protocol is declared"
                ]
              },
              {
                "dot": "rose",
                "title": "Failure semantics",
                "items": [
                  "maxAttempts = 2 creates one retry after the first failure",
                  "The second failure moves to dead letter",
                  "deadLetterAfter = 3 is stored as an output marker; it does not create a third attempt"
                ]
              }
            ]
          }
      • architecture-label-repair
        • worldscope.json 2.7 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "WorldScope 系统架构",
              "output": "worldscope.html",
              "locale": "zh-CN",
              "quality_profile": "showcase"
            },
            "components": [
              { "id": "browser", "type": "frontend", "label": "React 工作台", "sublabel": "浏览器端交互界面", "pos": [60, 110], "size": [150, 64] },
              { "id": "api", "type": "backend", "label": "读取模型 API", "sublabel": "FastAPI", "pos": [290, 110], "size": [150, 64] },
              { "id": "agent", "type": "backend", "label": "地图 Agent", "sublabel": "Agent 编排", "pos": [530, 110], "size": [150, 64] },
              { "id": "llm", "type": "external", "label": "模型端点", "sublabel": "外部 LLM 服务", "pos": [790, 110], "size": [150, 64] },
              { "id": "sources", "type": "external", "label": "公开数据源", "sublabel": "外部公开数据", "pos": [60, 300], "size": [150, 64] },
              { "id": "worker", "type": "backend", "label": "采集 Worker", "sublabel": "定时采集任务", "pos": [410, 300], "size": [150, 64] },
              { "id": "cache", "type": "database", "label": "Redis", "sublabel": "缓存 / last-good", "pos": [290, 480], "size": [150, 64] },
              { "id": "context", "type": "database", "label": "World Context", "sublabel": "PostgreSQL + PostGIS", "pos": [560, 480], "size": [170, 64] }
            ],
            "boundaries": [
              { "kind": "region", "label": "后端服务", "wraps": ["api", "agent", "worker"] }
            ],
            "connections": [
              { "id": "browser-to-api", "from": "browser", "to": "api", "label": "REST / SSE" },
              { "id": "api-to-agent", "from": "api", "to": "agent", "label": "受信附件身份" },
              { "id": "agent-to-llm", "from": "agent", "to": "llm", "label": "流式回答" },
              { "id": "api-to-context", "from": "api", "to": "context", "label": "事实检索" },
              { "id": "agent-to-context", "from": "agent", "to": "context", "label": "证据检索" },
              { "id": "api-to-cache", "from": "api", "to": "cache", "label": "读取缓存" },
              { "id": "sources-to-worker", "from": "sources", "to": "worker", "label": "定时采集" },
              { "id": "worker-to-context", "from": "worker", "to": "context", "label": "写入证据" },
              { "id": "worker-to-cache", "from": "worker", "to": "cache", "label": "刷新 last-good" }
            ],
            "cards": [
              { "dot": "cyan", "title": "读取路径", "items": ["React 工作台经 REST / SSE 访问 FastAPI", "API 直查 World Context 事实库并读穿 Redis 缓存", "地图 Agent 携受信附件身份向模型端点流式提问"] },
              { "dot": "emerald", "title": "采集路径", "items": ["Worker 定时从公开数据源采集证据", "证据写入 PostgreSQL + PostGIS 持久事实库", "同时刷新 Redis 的 last-good 快照"] }
            ]
          }
          
      • architecture-viewport
        • portrait-cards.architecture.json 5.2 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "Tall showcase fixture",
              "output": "portrait-cards.html",
              "quality_profile": "showcase"
            },
            "components": [
              {
                "id": "n0",
                "type": "frontend",
                "label": "Service 0",
                "sublabel": "owns step 0",
                "pos": [
                  60,
                  60
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n1",
                "type": "frontend",
                "label": "Service 1",
                "sublabel": "owns step 1",
                "pos": [
                  360,
                  60
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n2",
                "type": "frontend",
                "label": "Service 2",
                "sublabel": "owns step 2",
                "pos": [
                  660,
                  60
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n3",
                "type": "backend",
                "label": "Service 3",
                "sublabel": "owns step 3",
                "pos": [
                  60,
                  210
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n4",
                "type": "backend",
                "label": "Service 4",
                "sublabel": "owns step 4",
                "pos": [
                  360,
                  210
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n5",
                "type": "backend",
                "label": "Service 5",
                "sublabel": "owns step 5",
                "pos": [
                  660,
                  210
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n6",
                "type": "database",
                "label": "Service 6",
                "sublabel": "owns step 6",
                "pos": [
                  60,
                  360
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n7",
                "type": "database",
                "label": "Service 7",
                "sublabel": "owns step 7",
                "pos": [
                  360,
                  360
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n8",
                "type": "database",
                "label": "Service 8",
                "sublabel": "owns step 8",
                "pos": [
                  660,
                  360
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n9",
                "type": "cloud",
                "label": "Service 9",
                "sublabel": "owns step 9",
                "pos": [
                  60,
                  510
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n10",
                "type": "cloud",
                "label": "Service 10",
                "sublabel": "owns step 10",
                "pos": [
                  360,
                  510
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n11",
                "type": "cloud",
                "label": "Service 11",
                "sublabel": "owns step 11",
                "pos": [
                  660,
                  510
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n12",
                "type": "security",
                "label": "Service 12",
                "sublabel": "owns step 12",
                "pos": [
                  60,
                  660
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n13",
                "type": "security",
                "label": "Service 13",
                "sublabel": "owns step 13",
                "pos": [
                  360,
                  660
                ],
                "size": [
                  180,
                  64
                ]
              },
              {
                "id": "n14",
                "type": "security",
                "label": "Service 14",
                "sublabel": "owns step 14",
                "pos": [
                  660,
                  660
                ],
                "size": [
                  180,
                  64
                ]
              }
            ],
            "connections": [
              {
                "from": "n0",
                "to": "n1",
                "label": "call 0"
              },
              {
                "from": "n1",
                "to": "n2",
                "label": "call 1"
              },
              {
                "from": "n0",
                "to": "n3",
                "label": "next row 0"
              },
              {
                "from": "n3",
                "to": "n4",
                "label": "call 3"
              },
              {
                "from": "n4",
                "to": "n5",
                "label": "call 4"
              },
              {
                "from": "n3",
                "to": "n6",
                "label": "next row 1"
              },
              {
                "from": "n6",
                "to": "n7",
                "label": "call 6"
              },
              {
                "from": "n7",
                "to": "n8",
                "label": "call 7"
              },
              {
                "from": "n6",
                "to": "n9",
                "label": "next row 2"
              },
              {
                "from": "n9",
                "to": "n10",
                "label": "call 9"
              },
              {
                "from": "n10",
                "to": "n11",
                "label": "call 10"
              },
              {
                "from": "n9",
                "to": "n12",
                "label": "next row 3"
              },
              {
                "from": "n12",
                "to": "n13",
                "label": "call 12"
              },
              {
                "from": "n13",
                "to": "n14",
                "label": "call 13"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "Card 0",
                "items": [
                  "Statement 0.1 about the system",
                  "Statement 0.2 with a bit more copy to wrap lines"
                ]
              },
              {
                "dot": "cyan",
                "title": "Card 1",
                "items": [
                  "Statement 1.1 about the system",
                  "Statement 1.2 with a bit more copy to wrap lines"
                ]
              },
              {
                "dot": "cyan",
                "title": "Card 2",
                "items": [
                  "Statement 2.1 about the system",
                  "Statement 2.2 with a bit more copy to wrap lines"
                ]
              },
              {
                "dot": "cyan",
                "title": "Card 3",
                "items": [
                  "Statement 3.1 about the system",
                  "Statement 3.2 with a bit more copy to wrap lines"
                ]
              }
            ]
          }
          
        • readable-scroll-worldscope.architecture.json 4.2 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "WorldScope 极高路线可读滚动",
              "output": "readable-scroll-worldscope.html",
              "locale": "zh-CN",
              "quality_profile": "showcase"
            },
            "components": [
              {
                "id": "browser",
                "type": "frontend",
                "label": "React 工作台",
                "sublabel": "浏览器端交互界面",
                "pos": [
                  60,
                  110
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "api",
                "type": "backend",
                "label": "读取模型 API",
                "sublabel": "FastAPI",
                "pos": [
                  290,
                  110
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "agent",
                "type": "backend",
                "label": "地图 Agent",
                "sublabel": "Agent 编排",
                "pos": [
                  530,
                  110
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "llm",
                "type": "external",
                "label": "模型端点",
                "sublabel": "外部 LLM 服务",
                "pos": [
                  790,
                  110
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "sources",
                "type": "external",
                "label": "公开数据源",
                "sublabel": "外部公开数据",
                "pos": [
                  60,
                  300
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "worker",
                "type": "backend",
                "label": "采集 Worker",
                "sublabel": "定时采集任务",
                "pos": [
                  410,
                  300
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "cache",
                "type": "database",
                "label": "Redis",
                "sublabel": "缓存 / last-good",
                "pos": [
                  290,
                  480
                ],
                "size": [
                  150,
                  64
                ]
              },
              {
                "id": "context",
                "type": "database",
                "label": "World Context",
                "sublabel": "PostgreSQL + PostGIS",
                "pos": [
                  560,
                  480
                ],
                "size": [
                  170,
                  64
                ]
              },
              {
                "id": "archive",
                "type": "database",
                "label": "历史证据归档",
                "sublabel": "大体量离线资料",
                "pos": [
                  790,
                  1056
                ],
                "size": [
                  150,
                  64
                ]
              }
            ],
            "connections": [
              {
                "id": "browser-to-api",
                "from": "browser",
                "to": "api",
                "label": "REST / SSE"
              },
              {
                "id": "api-to-agent",
                "from": "api",
                "to": "agent",
                "label": "受信附件身份"
              },
              {
                "id": "agent-to-llm",
                "from": "agent",
                "to": "llm",
                "label": "流式回答"
              },
              {
                "id": "api-to-context",
                "from": "api",
                "to": "context",
                "label": "事实检索"
              },
              {
                "id": "agent-to-context",
                "from": "agent",
                "to": "context",
                "label": "证据检索"
              },
              {
                "id": "api-to-cache",
                "from": "api",
                "to": "cache",
                "label": "读取缓存"
              },
              {
                "id": "sources-to-worker",
                "from": "sources",
                "to": "worker",
                "label": "定时采集",
                "fromSide": "bottom",
                "toSide": "bottom",
                "via": [
                  [
                    135,
                    610
                  ],
                  [
                    485,
                    610
                  ]
                ]
              },
              {
                "id": "worker-to-context",
                "from": "worker",
                "to": "context",
                "label": "写入证据"
              },
              {
                "id": "worker-to-cache",
                "from": "worker",
                "to": "cache",
                "label": "刷新 last-good"
              }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "后端服务",
                "wraps": [
                  "api",
                  "agent",
                  "worker"
                ]
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "读取路径",
                "items": [
                  "React 工作台经 REST / SSE 访问 FastAPI",
                  "API 直查 World Context 事实库并读穿 Redis 缓存",
                  "地图 Agent 携受信附件身份向模型端点流式提问"
                ]
              },
              {
                "dot": "emerald",
                "title": "采集路径",
                "items": [
                  "Worker 定时从公开数据源采集证据",
                  "证据写入 PostgreSQL + PostGIS 持久事实库",
                  "同时刷新 Redis 的 last-good 快照"
                ]
              }
            ]
          }
          
        • route-expanded-worldscope.architecture.json 3.3 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "WorldScope 系统架构",
              "output": "route-expanded-worldscope.html",
              "locale": "zh-CN",
              "quality_profile": "showcase"
            },
            "components": [
              {
                "id": "browser",
                "type": "frontend",
                "label": "React 工作台",
                "sublabel": "浏览器端交互界面",
                "pos": [60, 110],
                "size": [150, 64]
              },
              {
                "id": "api",
                "type": "backend",
                "label": "读取模型 API",
                "sublabel": "FastAPI",
                "pos": [290, 110],
                "size": [150, 64]
              },
              {
                "id": "agent",
                "type": "backend",
                "label": "地图 Agent",
                "sublabel": "Agent 编排",
                "pos": [530, 110],
                "size": [150, 64]
              },
              {
                "id": "llm",
                "type": "external",
                "label": "模型端点",
                "sublabel": "外部 LLM 服务",
                "pos": [790, 110],
                "size": [150, 64]
              },
              {
                "id": "sources",
                "type": "external",
                "label": "公开数据源",
                "sublabel": "外部公开数据",
                "pos": [60, 300],
                "size": [150, 64]
              },
              {
                "id": "worker",
                "type": "backend",
                "label": "采集 Worker",
                "sublabel": "定时采集任务",
                "pos": [410, 300],
                "size": [150, 64]
              },
              {
                "id": "cache",
                "type": "database",
                "label": "Redis",
                "sublabel": "缓存 / last-good",
                "pos": [290, 480],
                "size": [150, 64]
              },
              {
                "id": "context",
                "type": "database",
                "label": "World Context",
                "sublabel": "PostgreSQL + PostGIS",
                "pos": [560, 480],
                "size": [170, 64]
              }
            ],
            "connections": [
              { "id": "browser-to-api", "from": "browser", "to": "api", "label": "REST / SSE" },
              { "id": "api-to-agent", "from": "api", "to": "agent", "label": "受信附件身份" },
              { "id": "agent-to-llm", "from": "agent", "to": "llm", "label": "流式回答" },
              { "id": "api-to-context", "from": "api", "to": "context", "label": "事实检索" },
              { "id": "agent-to-context", "from": "agent", "to": "context", "label": "证据检索" },
              { "id": "api-to-cache", "from": "api", "to": "cache", "label": "读取缓存" },
              {
                "id": "sources-to-worker",
                "from": "sources",
                "to": "worker",
                "label": "定时采集",
                "fromSide": "bottom",
                "toSide": "bottom",
                "via": [[135, 610], [485, 610]]
              },
              { "id": "worker-to-context", "from": "worker", "to": "context", "label": "写入证据" },
              { "id": "worker-to-cache", "from": "worker", "to": "cache", "label": "刷新 last-good" }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "后端服务",
                "wraps": ["api", "agent", "worker"]
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "读取路径",
                "items": [
                  "React 工作台经 REST / SSE 访问 FastAPI",
                  "API 直查 World Context 事实库并读穿 Redis 缓存",
                  "地图 Agent 携受信附件身份向模型端点流式提问"
                ]
              },
              {
                "dot": "emerald",
                "title": "采集路径",
                "items": [
                  "Worker 定时从公开数据源采集证据",
                  "证据写入 PostgreSQL + PostGIS 持久事实库",
                  "同时刷新 Redis 的 last-good 快照"
                ]
              }
            ]
          }
          
      • issue-126
        • custom-widths.workflow.json 574 B
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "Sanitized custom widths",
              "output": "issue-126-custom-widths.html",
              "legend": { "mode": "hidden" }
            },
            "lanes": [
              { "id": "main", "label": "Main flow" }
            ],
            "nodes": [
              { "id": "compact", "lane": "main", "col": 1, "type": "frontend", "label": "In", "width": 32 },
              { "id": "wide", "lane": "main", "col": 2, "type": "database", "label": "Sanitized downstream service", "width": 240 }
            ],
            "edges": [
              { "id": "compact-wide", "from": "compact", "to": "wide" }
            ]
          }
          
        • explicit-route.workflow.json 750 B
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "Sanitized explicit route",
              "output": "issue-126-explicit-route.html",
              "viewBox": [900, 420],
              "legend": { "mode": "hidden" }
            },
            "lanes": [
              { "id": "source", "label": "Source" },
              { "id": "target", "label": "Target" }
            ],
            "nodes": [
              { "id": "producer", "lane": "source", "col": 1, "type": "backend", "label": "Producer" },
              { "id": "consumer", "lane": "target", "col": 1, "type": "backend", "label": "Consumer" }
            ],
            "edges": [
              {
                "id": "producer-consumer",
                "from": "producer",
                "to": "consumer",
                "fromSide": "right",
                "toSide": "right",
                "route": "outside-right",
                "channelX": 720
              }
            ]
          }
          
        • explicit-viewbox.workflow.json 582 B
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "Sanitized explicit viewBox",
              "output": "issue-126-explicit-viewbox.html",
              "viewBox": [1600, 520],
              "legend": { "mode": "hidden" }
            },
            "lanes": [
              { "id": "main", "label": "Main flow" }
            ],
            "nodes": [
              { "id": "start", "lane": "main", "col": 0, "type": "frontend", "label": "Start" },
              { "id": "finish", "lane": "main", "col": 5, "type": "backend", "label": "Finish" }
            ],
            "edges": [
              { "id": "start-finish", "from": "start", "to": "finish", "label": "complete" }
            ]
          }
          
        • labels.workflow.json 559 B
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "Sanitized semantic labels",
              "output": "issue-126-labels.html",
              "legend": { "mode": "hidden" }
            },
            "lanes": [
              { "id": "main", "label": "Main flow" }
            ],
            "nodes": [
              { "id": "request", "lane": "main", "col": 3, "type": "frontend", "label": "Request" },
              { "id": "result", "lane": "main", "col": 4, "type": "backend", "label": "Result" }
            ],
            "edges": [
              { "id": "request-result", "from": "request", "to": "result", "label": "同步 ✅ ready" }
            ]
          }
          
      • lifecycle-planner
        • approval.lifecycle.json 5.3 KB
          {
            "schema_version": 1,
            "diagram_type": "lifecycle",
            "meta": {
              "title": "Document Approval Lifecycle",
              "output": "approval.lifecycle.html",
              "locale": "en",
              "quality_profile": "showcase"
            },
            "lanes": [
              {
                "id": "main",
                "label": "Approval phases"
              },
              {
                "id": "held",
                "label": "Held states"
              },
              {
                "id": "terminal",
                "label": "Exits + retry"
              }
            ],
            "states": [
              {
                "id": "draft",
                "type": "start",
                "label": "Draft",
                "sublabel": "author editing",
                "lane": "main",
                "col": 0,
                "step": "01",
                "tag": "editable"
              },
              {
                "id": "submitted",
                "type": "waiting",
                "label": "Submitted",
                "sublabel": "awaiting reviewer, SLA 72h",
                "lane": "main",
                "col": 1,
                "step": "02",
                "tag": "timer"
              },
              {
                "id": "under_review",
                "type": "decision",
                "label": "Under Review",
                "sublabel": "reviewer decides",
                "lane": "main",
                "col": 2,
                "step": "03",
                "tag": "gate"
              },
              {
                "id": "approved",
                "type": "active",
                "label": "Approved",
                "sublabel": "ready to schedule",
                "lane": "main",
                "col": 3,
                "step": "04",
                "tag": "signed off"
              },
              {
                "id": "published",
                "type": "success",
                "label": "Published",
                "sublabel": "publicly visible",
                "lane": "main",
                "col": 4,
                "step": "05",
                "tag": "live"
              },
              {
                "id": "changes_requested",
                "type": "failure",
                "label": "Changes Requested",
                "sublabel": "reviewer feedback",
                "lane": "held",
                "col": 0,
                "tag": "rework"
              },
              {
                "id": "scheduled",
                "type": "waiting",
                "label": "Scheduled",
                "sublabel": "publish date set",
                "lane": "held",
                "col": 1,
                "tag": "timer"
              },
              {
                "id": "archived",
                "type": "neutral",
                "label": "Archived",
                "sublabel": "read-only record",
                "lane": "held",
                "col": 2,
                "tag": "terminal"
              },
              {
                "id": "rejected",
                "type": "failure",
                "label": "Rejected",
                "sublabel": "reviewer declined",
                "lane": "terminal",
                "col": 0,
                "tag": "terminal"
              },
              {
                "id": "withdrawn",
                "type": "neutral",
                "label": "Withdrawn",
                "sublabel": "author pulled back",
                "lane": "terminal",
                "col": 1,
                "tag": "terminal"
              },
              {
                "id": "publish_failed",
                "type": "failure",
                "label": "Publish Failed",
                "sublabel": "one automatic retry",
                "lane": "terminal",
                "col": 2,
                "tag": "retry"
              }
            ],
            "transitions": [
              {
                "id": "t-submit",
                "from": "draft",
                "to": "submitted",
                "label": "author submits"
              },
              {
                "id": "t-claim",
                "from": "submitted",
                "to": "under_review",
                "label": "reviewer claims within 72h"
              },
              {
                "id": "t-approve",
                "from": "under_review",
                "to": "approved",
                "label": "reviewer approves"
              },
              {
                "id": "t-schedule",
                "from": "approved",
                "to": "scheduled",
                "label": "publish date set"
              },
              {
                "id": "t-publish",
                "from": "scheduled",
                "to": "published",
                "label": "publish time reached"
              },
              {
                "id": "t-archive",
                "from": "published",
                "to": "archived",
                "label": "retention period ends"
              },
              {
                "id": "t-changes",
                "from": "under_review",
                "to": "changes_requested",
                "label": "reviewer requests changes",
                "variant": "dashed"
              },
              {
                "id": "t-rework",
                "from": "changes_requested",
                "to": "draft",
                "label": "author reopens draft",
                "variant": "dashed"
              },
              {
                "id": "t-fail",
                "from": "scheduled",
                "to": "publish_failed",
                "label": "publish job errors",
                "variant": "dashed"
              },
              {
                "id": "t-retry",
                "from": "publish_failed",
                "to": "scheduled",
                "label": "automatic retry (1x)",
                "variant": "dashed"
              },
              {
                "id": "t-reject",
                "from": "under_review",
                "to": "rejected",
                "label": "reviewer rejects",
                "variant": "security"
              },
              {
                "id": "t-withdraw-submitted",
                "from": "submitted",
                "to": "withdrawn",
                "label": "author withdraws",
                "variant": "security"
              },
              {
                "id": "t-withdraw-review",
                "from": "under_review",
                "to": "withdrawn",
                "label": "author withdraws",
                "variant": "security"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "Main Rail",
                "items": [
                  "Five ordered phases from Draft to Published",
                  "Under Review is the only decision point",
                  "Archived closes the record after the retention period"
                ]
              },
              {
                "dot": "amber",
                "title": "Wait States",
                "items": [
                  "Submitted waits for a reviewer under a 72h SLA",
                  "Scheduled holds an approved document until its publish time",
                  "A failed publish job gets exactly one automatic retry"
                ]
              },
              {
                "dot": "rose",
                "title": "Loops and Exits",
                "items": [
                  "Changes Requested returns the document to Draft for rework",
                  "Rejected is a reviewer decision; Withdrawn is an author decision",
                  "Withdrawn is reachable from Submitted or Under Review"
                ]
              }
            ]
          }
        • band-title-overlap.lifecycle.json 3.5 KB
          {
            "schema_version": 1,
            "diagram_type": "lifecycle",
            "meta": {
              "title": "线上书店订单生命周期",
              "locale": "zh-CN",
              "output": "diagram.html",
              "animation": "none",
              "quality_profile": "showcase"
            },
            "lanes": [
              { "id": "main", "label": "下单与履约" },
              { "id": "refund", "label": "退款申请" },
              { "id": "retry", "label": "可恢复失败" },
              { "id": "terminal", "label": "终态" }
            ],
            "states": [
              { "id": "created", "type": "start", "label": "已创建", "sublabel": "订单生成", "lane": "main", "col": 0, "step": "01" },
              { "id": "pending_payment", "type": "waiting", "label": "待支付", "sublabel": "等待付款事件", "lane": "main", "col": 1, "step": "02" },
              { "id": "paid", "type": "active", "label": "已支付", "sublabel": "付款成功", "lane": "main", "col": 2, "step": "03" },
              { "id": "preparing", "type": "active", "label": "备货中", "sublabel": "准备商品", "lane": "main", "col": 3, "step": "04" },
              { "id": "shipped", "type": "waiting", "label": "已发货", "sublabel": "等待确认收货", "lane": "main", "col": 4, "step": "05" },
              { "id": "refunding", "type": "active", "label": "退款处理中", "sublabel": "已申请退款", "lane": "refund", "col": 1 },
              { "id": "refund_failed", "type": "failure", "label": "退款失败", "sublabel": "保留失败状态·可重试", "lane": "retry", "col": 0, "yOffset": 85 },
              { "id": "cancelled", "type": "failure", "label": "已取消", "sublabel": "支付超时·释放库存", "lane": "terminal", "col": 0, "tag": "终态" },
              { "id": "refunded", "type": "success", "label": "已退款", "sublabel": "退款成功", "lane": "terminal", "col": 1, "tag": "终态" },
              { "id": "completed", "type": "success", "label": "已完成", "sublabel": "用户确认收货", "lane": "terminal", "col": 2, "tag": "终态" }
            ],
            "transitions": [
              { "from": "created", "to": "pending_payment", "label": "订单创建", "variant": "emphasis" },
              { "from": "pending_payment", "to": "paid", "label": "付款成功事件", "variant": "emphasis" },
              { "from": "pending_payment", "to": "pending_payment", "label": "付款失败·重试支付", "variant": "dashed" },
              { "from": "pending_payment", "to": "cancelled", "label": "超过付款期限·释放库存", "variant": "security" },
              { "from": "paid", "to": "preparing", "label": "开始备货" },
              { "from": "preparing", "to": "shipped", "label": "完成备货·发货", "variant": "emphasis" },
              { "from": "shipped", "to": "completed", "label": "用户确认收货", "variant": "emphasis" },
              { "from": "paid", "to": "refunding", "label": "申请退款" },
              { "from": "preparing", "to": "refunding", "label": "申请退款" },
              { "from": "refunding", "to": "refunded", "label": "退款成功" },
              { "from": "refunding", "to": "refund_failed", "label": "退款失败" },
              { "from": "refund_failed", "to": "refunding", "label": "重试退款", "variant": "dashed" }
            ],
            "cards": [
              { "dot": "cyan", "title": "主流程", "items": ["付款成功触发已支付;随后备货、发货", "用户确认收货后,订单进入已完成"] },
              { "dot": "amber", "title": "可恢复失败", "items": ["待支付时付款失败,可重试支付", "退款失败保留失败状态,可重试退款"] },
              { "dot": "rose", "title": "终态与限制", "items": ["待支付超时才取消,并释放库存", "已取消、已退款、已完成是终态", "已发货不能直接取消"] }
            ]
          }
          
        • review-hub.lifecycle.json 1.6 KB
          {
            "schema_version": 1,
            "diagram_type": "lifecycle",
            "meta": { "title": "Review hub fan-out", "output": "review-hub.html", "quality_profile": "showcase" },
            "lanes": [
              { "id": "main", "label": "Main" },
              { "id": "side", "label": "Side" },
              { "id": "terminal", "label": "Terminal" }
            ],
            "states": [
              { "id": "draft", "lane": "main", "col": 0, "type": "start", "label": "Draft" },
              { "id": "submitted", "lane": "main", "col": 1, "type": "active", "label": "Submitted" },
              { "id": "review", "lane": "main", "col": 2, "type": "active", "label": "Under review" },
              { "id": "approved", "lane": "main", "col": 3, "type": "success", "label": "Approved" },
              { "id": "sla", "lane": "side", "col": 0, "type": "waiting", "label": "SLA wait", "yOffset": -6 },
              { "id": "changes", "lane": "side", "col": 0, "type": "decision", "label": "Changes requested", "yOffset": 72 },
              { "id": "rejected", "lane": "terminal", "col": 1, "type": "failure", "label": "Rejected" }
            ],
            "transitions": [
              { "id": "submit", "from": "draft", "to": "submitted", "label": "submit" },
              { "id": "assign", "from": "submitted", "to": "review", "label": "assign" },
              { "id": "approve", "from": "review", "to": "approved", "label": "approve" },
              { "id": "wait", "from": "review", "to": "sla", "label": "clock" },
              { "id": "request", "from": "review", "to": "changes", "label": "request changes" },
              { "id": "reject", "from": "review", "to": "rejected", "label": "reject" },
              { "id": "reopen", "from": "changes", "to": "draft", "label": "reopen", "variant": "dashed" }
            ]
          }
          
      • reader-readability
        • synthetic-wide.architecture.json 5.4 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "Synthetic wide reader fixture",
              "output": "synthetic-wide-reader.html",
              "quality_profile": "showcase"
            },
            "components": [
              {
                "id": "caller",
                "type": "external",
                "label": "Client caller",
                "sublabel": "external request",
                "pos": [
                  10,
                  270
                ],
                "size": [
                  160,
                  78
                ]
              },
              {
                "id": "listener",
                "type": "backend",
                "label": "HTTP listener",
                "sublabel": "request bridge",
                "pos": [
                  260,
                  270
                ],
                "size": [
                  170,
                  78
                ]
              },
              {
                "id": "handler",
                "type": "backend",
                "label": "Request handler",
                "sublabel": "route and validation",
                "pos": [
                  530,
                  270
                ],
                "size": [
                  180,
                  84
                ]
              },
              {
                "id": "parser",
                "type": "backend",
                "label": "Input parser",
                "sublabel": "structured payload",
                "pos": [
                  740,
                  110
                ],
                "size": [
                  180,
                  78
                ]
              },
              {
                "id": "coordinator",
                "type": "backend",
                "label": "Work coordinator",
                "sublabel": "admit and poll",
                "pos": [
                  740,
                  300
                ],
                "size": [
                  160,
                  84
                ]
              },
              {
                "id": "store",
                "type": "database",
                "label": "State store",
                "sublabel": "in-memory records",
                "pos": [
                  930,
                  170
                ],
                "size": [
                  170,
                  82
                ]
              },
              {
                "id": "queue",
                "type": "messagebus",
                "label": "FIFO queue",
                "sublabel": "in-memory ids",
                "pos": [
                  920,
                  370
                ],
                "size": [
                  170,
                  82
                ]
              },
              {
                "id": "scheduler",
                "type": "backend",
                "label": "Tick scheduler",
                "sublabel": "periodic worker tick",
                "pos": [
                  720,
                  540
                ],
                "size": [
                  180,
                  78
                ]
              },
              {
                "id": "worker",
                "type": "backend",
                "label": "Work worker",
                "sublabel": "queued to complete",
                "pos": [
                  1195,
                  370
                ],
                "size": [
                  165,
                  84
                ]
              },
              {
                "id": "formatter",
                "type": "backend",
                "label": "Result formatter",
                "sublabel": "text transform",
                "pos": [
                  1195,
                  170
                ],
                "size": [
                  165,
                  78
                ]
              }
            ],
            "boundaries": [
              {
                "kind": "region",
                "label": "Application process",
                "wraps": [
                  "listener",
                  "handler",
                  "parser",
                  "coordinator",
                  "store",
                  "queue",
                  "scheduler",
                  "worker",
                  "formatter"
                ],
                "pad": 28
              }
            ],
            "connections": [
              {
                "id": "client-request",
                "from": "caller",
                "to": "listener",
                "label": "request",
                "variant": "emphasis"
              },
              {
                "id": "request-envelope",
                "from": "listener",
                "to": "handler",
                "label": "method and body"
              },
              {
                "id": "post-body",
                "from": "handler",
                "to": "parser",
                "label": "parse payload"
              },
              {
                "id": "validated-job",
                "from": "parser",
                "to": "coordinator",
                "label": "validated work"
              },
              {
                "id": "poll-request",
                "from": "handler",
                "to": "coordinator",
                "label": "poll status"
              },
              {
                "id": "state-admission",
                "from": "coordinator",
                "to": "store",
                "label": "read or write state"
              },
              {
                "id": "enqueue-id",
                "from": "coordinator",
                "to": "queue",
                "label": "enqueue id",
                "variant": "dashed"
              },
              {
                "id": "coordinator-result",
                "from": "coordinator",
                "to": "handler",
                "label": "status result"
              },
              {
                "id": "json-response",
                "from": "handler",
                "to": "listener",
                "label": "response body"
              },
              {
                "id": "server-response",
                "from": "listener",
                "to": "caller",
                "label": "HTTP response",
                "variant": "emphasis"
              },
              {
                "id": "timer-tick",
                "from": "scheduler",
                "to": "worker",
                "label": "tick every interval",
                "variant": "dashed"
              },
              {
                "id": "dequeue-id",
                "from": "queue",
                "to": "worker",
                "label": "dequeue next id"
              },
              {
                "id": "worker-state",
                "from": "worker",
                "to": "store",
                "label": "update state"
              },
              {
                "id": "format-call",
                "from": "worker",
                "to": "formatter",
                "label": "format text"
              },
              {
                "id": "format-result",
                "from": "formatter",
                "to": "worker",
                "label": "formatted result"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "Admission",
                "items": [
                  "The handler validates a request before coordinator work.",
                  "Malformed input stops before state changes.",
                  "Repeated ids are rejected without a second enqueue."
                ]
              },
              {
                "dot": "emerald",
                "title": "Execution",
                "items": [
                  "Accepted work enters the FIFO queue.",
                  "The worker advances one item through completion.",
                  "Formatting runs before the completed result is stored."
                ]
              },
              {
                "dot": "violet",
                "title": "Polling",
                "items": [
                  "Polling reads a cloned record.",
                  "Missing ids return a not-found result.",
                  "The runtime keeps state inside one process."
                ]
              }
            ]
          }
          
      • v1-baseline
        • agent-run.lifecycle.json 3.5 KB
          {
            "schema_version": 1,
            "diagram_type": "lifecycle",
            "meta": {
              "title": "Agent Run Lifecycle",
              "subtitle": "State machine for planning, tool execution, human approval, retries, and terminal outcomes",
              "output": "examples/lifecycle-agent-run.html",
              "viewBox": [980, 660]
            },
            "lanes": [
              { "id": "main", "label": "Lifecycle phases" },
              { "id": "waiting", "label": "Interruptions" },
              { "id": "exceptions", "label": "Recovery loop" },
              { "id": "terminal", "label": "Terminal exits" }
            ],
            "states": [
              { "id": "queued", "type": "start", "label": "Queued", "sublabel": "request accepted", "lane": "main", "col": 0, "step": "01", "tag": "entry" },
              { "id": "planning", "type": "active", "label": "Planning", "sublabel": "build task graph", "lane": "main", "col": 1, "step": "02", "tag": "model" },
              { "id": "executing", "type": "active", "label": "Executing", "sublabel": "tool calls", "lane": "main", "col": 2, "step": "03", "tag": "work" },
              { "id": "reviewing", "type": "decision", "label": "Reviewing", "sublabel": "quality gate", "lane": "main", "col": 3, "step": "04", "tag": "check" },
              { "id": "completed", "type": "success", "label": "Completed", "sublabel": "final response", "lane": "main", "col": 4, "step": "05", "tag": "done" },
              { "id": "approval", "type": "waiting", "label": "Needs Approval", "sublabel": "human gate", "lane": "waiting", "col": 0, "tag": "pause" },
              { "id": "blocked", "type": "waiting", "label": "Blocked", "sublabel": "missing input", "lane": "waiting", "col": 1, "tag": "wait" },
              { "id": "failed", "type": "failure", "label": "Failed", "sublabel": "recoverable error", "lane": "exceptions", "col": 0, "yOffset": 78, "tag": "retryable" },
              { "id": "cancelled", "type": "failure", "label": "Cancelled", "sublabel": "user stopped", "lane": "terminal", "col": 0, "tag": "terminal" },
              { "id": "expired", "type": "failure", "label": "Expired", "sublabel": "timeout", "lane": "terminal", "col": 1, "tag": "terminal" }
            ],
            "transitions": [
              { "from": "executing", "to": "approval", "variant": "security", "fromSide": "bottom", "toSide": "top", "route": "straight" },
              { "from": "reviewing", "to": "blocked", "variant": "default", "route": "drop" },
              { "from": "executing", "to": "failed", "variant": "security", "fromSide": "left", "toSide": "top", "via": [[320, 157], [320, 342], [402, 342]] },
              { "from": "blocked", "to": "expired", "variant": "security", "fromSide": "bottom", "toSide": "top", "route": "straight" },
              { "from": "approval", "to": "cancelled", "variant": "security", "fromSide": "bottom", "toSide": "top", "via": [[320, 336], [320, 430], [402, 430]] }
            ],
            "cards": [
              {
                "dot": "emerald",
                "title": "Main Path",
                "items": [
                  "The run has five ordered phases from queue to completion",
                  "The primary lifecycle is carried by one horizontal rail",
                  "Completion is a phase, not a detached side box"
                ]
              },
              {
                "dot": "amber",
                "title": "Human + Input Gates",
                "items": [
                  "Approval pauses execution without ending the run",
                  "Blocked waits for missing user input",
                  "Wait states can resume back into planning or execution"
                ]
              },
              {
                "dot": "rose",
                "title": "Terminal + Recovery",
                "items": [
                  "Failed loops back while retry budget remains",
                  "Cancelled and Expired are exits from the lifecycle",
                  "Terminal exits do not point back into active execution"
                ]
              }
            ]
          }
          
        • agent-tool-call.workflow.json 5.2 KB
          {
            "schema_version": 1,
            "diagram_type": "workflow",
            "meta": {
              "title": "Agent Tool Call Workflow",
              "subtitle": "Renderer-driven workflow prototype with lanes, anchored nodes, and orthogonal edges",
              "output": "examples/workflow-agent-tool-call-rendered.html",
              "viewBox": [720, 900]
            },
            "lanes": [
              { "id": "ui", "label": "User Interface" },
              { "id": "agent", "label": "Agent Runtime" },
              { "id": "policy", "label": "Policy Boundary" },
              { "id": "exceptions", "label": "Exception Handling", "variant": "exception" },
              { "id": "tools", "label": "Tool Execution" },
              { "id": "trace", "label": "Observability" }
            ],
            "phases": [
              { "id": "intake", "label": "Intake", "fromCol": 0, "toCol": 1 },
              { "id": "reasoning", "label": "Plan + route", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
              { "id": "execution", "label": "Execute + report", "fromCol": 4, "toCol": 5, "variant": "dashed" }
            ],
            "groups": [
              { "id": "agent_loop", "label": "Planning loop", "lane": "agent", "fromCol": 2, "toCol": 3, "variant": "emphasis" },
              { "id": "tool_work", "label": "Tool work", "lane": "tools", "fromCol": 4, "toCol": 5, "variant": "dashed" },
              { "id": "exception_path", "label": "Human or policy stop", "lane": "exceptions", "fromCol": 3, "toCol": 5, "variant": "security" }
            ],
            "mainPath": ["user", "chat", "planner", "router", "approval", "tool", "external", "final"],
            "nodes": [
              { "id": "user", "lane": "ui", "col": 0, "type": "external", "label": "User", "sublabel": "asks for work" },
              { "id": "chat", "lane": "ui", "col": 1, "type": "frontend", "label": "Chat Surface", "sublabel": "thread + files" },
              { "id": "final", "lane": "ui", "col": 5, "type": "backend", "label": "Final Reply", "sublabel": "answer + changes" },
              { "id": "planner", "lane": "agent", "col": 2, "type": "backend", "label": "Agent Planner", "sublabel": "plan next step", "tag": "context aware" },
              { "id": "router", "lane": "agent", "col": 3, "type": "backend", "label": "Tool Router", "sublabel": "choose capability" },
              { "id": "approval", "lane": "policy", "col": 3, "type": "security", "label": "Approval Gate", "sublabel": "scope + consent", "tag": "block risky ops" },
              { "id": "blocked", "lane": "exceptions", "col": 4, "type": "security", "label": "Blocked", "sublabel": "wait or reject" },
              { "id": "retry", "lane": "exceptions", "col": 5, "type": "messagebus", "label": "Retry Path", "sublabel": "revise request" },
              { "id": "tool", "lane": "tools", "col": 4, "type": "messagebus", "label": "Tool Call", "sublabel": "shell / browser / MCP", "tag": "structured result" },
              { "id": "external", "lane": "tools", "col": 5, "type": "cloud", "label": "External API", "sublabel": "network service" },
              { "id": "store", "lane": "trace", "col": 1, "type": "database", "label": "Context Store", "sublabel": "repo + memory" },
              { "id": "trace", "lane": "trace", "col": 4, "type": "database", "label": "Trace Log", "sublabel": "events + output" }
            ],
            "edges": [
              { "from": "user", "to": "chat", "variant": "default" },
              { "from": "chat", "to": "planner", "label": "plan", "variant": "emphasis", "fromSide": "bottom", "toSide": "top", "route": "drop", "labelSegment": 1 },
              { "from": "planner", "to": "router", "variant": "default" },
              { "from": "router", "to": "approval", "label": "needs approval?", "variant": "security", "fromSide": "bottom", "toSide": "top", "route": "drop", "labelSegment": 0, "labelDx": 34, "labelDy": 18 },
              { "from": "approval", "to": "tool", "variant": "emphasis", "fromSide": "left", "toSide": "left", "route": "return-left" },
              { "from": "approval", "to": "blocked", "label": "denied", "variant": "security", "role": "error", "fromSide": "bottom", "toSide": "top", "route": "drop", "labelSegment": 1, "labelDy": 12 },
              { "from": "blocked", "to": "retry", "variant": "dashed", "role": "branch" },
              { "from": "tool", "to": "external", "variant": "default" },
              { "from": "external", "to": "final", "variant": "emphasis", "role": "return", "fromSide": "right", "toSide": "right", "route": "outside-right", "width": 1.2 },
              { "from": "external", "to": "trace", "label": "record result", "variant": "dashed", "fromSide": "bottom", "toSide": "bottom", "route": "bottom-channel", "labelSegment": 1 },
              { "from": "store", "to": "trace", "label": "trace + memory", "variant": "dashed", "labelAt": [365, 735] }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "Renderer Rules",
                "items": [
                  "Lanes and columns determine node placement",
                  "Edges attach to explicit node anchors",
                  "Cross-lane paths use orthogonal routing",
                  "Short adjacent links stay unlabeled"
                ]
              },
              {
                "dot": "rose",
                "title": "Workflow Semantics",
                "items": [
                  "Approval is a first-class policy step",
                  "Consent gates are visible in the main path",
                  "External calls stay inside the tool lane",
                  "Trace writes are separate from the hot path"
                ]
              },
              {
                "dot": "emerald",
                "title": "Why It Matters",
                "items": [
                  "This is closer to a diagram_type renderer",
                  "The graph can be edited without SVG surgery",
                  "Layout rules can be tested and improved",
                  "A future IR can reuse this shape directly"
                ]
              }
            ]
          }
          
        • cache-miss-request.sequence.json 3.5 KB
          {
            "schema_version": 1,
            "diagram_type": "sequence",
            "meta": {
              "title": "Cache Miss Request Sequence",
              "subtitle": "Frontend request path with auth, cache fallback, persistence, and async trace",
              "output": "examples/sequence-cache-miss-request.html",
              "viewBox": [820, 760]
            },
            "participants": [
              { "id": "user", "type": "external", "label": "User", "sublabel": "browser session" },
              { "id": "web", "type": "frontend", "label": "Web App", "sublabel": "React UI" },
              { "id": "api", "type": "backend", "label": "API", "sublabel": "request handler" },
              { "id": "auth", "type": "security", "label": "Auth", "sublabel": "JWT verify" },
              { "id": "redis", "type": "database", "label": "Redis", "sublabel": "cache" },
              { "id": "db", "type": "database", "label": "Postgres", "sublabel": "source of truth" },
              { "id": "trace", "type": "messagebus", "label": "Trace", "sublabel": "async event" }
            ],
            "segments": [
              { "from": 150, "to": 295, "label": "Request" },
              { "from": 315, "to": 505, "label": "Fallback" },
              { "from": 525, "to": 665, "label": "Response + trace" }
            ],
            "messages": [
              { "from": "user", "to": "web", "y": 185, "label": "open page", "variant": "default" },
              { "from": "web", "to": "api", "y": 228, "label": "GET /dashboard", "variant": "emphasis" },
              { "from": "api", "to": "auth", "y": 270, "label": "verify JWT", "variant": "security" },
              { "from": "auth", "to": "api", "y": 305, "label": "claims ok", "variant": "return" },
              { "from": "api", "to": "redis", "y": 354, "label": "read cache", "variant": "default" },
              { "from": "redis", "to": "api", "y": 391, "label": "miss", "variant": "return" },
              { "from": "api", "to": "db", "y": 443, "label": "query profile + metrics", "variant": "emphasis" },
              { "from": "db", "to": "api", "y": 489, "label": "rows", "variant": "return" },
              { "from": "api", "to": "redis", "y": 536, "label": "set cache", "variant": "dashed" },
              { "from": "api", "to": "trace", "y": 580, "label": "emit trace", "variant": "dashed" },
              { "from": "api", "to": "web", "y": 625, "label": "200 JSON", "variant": "return" },
              { "from": "web", "to": "user", "y": 662, "label": "render", "variant": "return" }
            ],
            "activations": [
              { "participant": "web", "from": 220, "to": 668, "type": "frontend" },
              { "participant": "api", "from": 228, "to": 632, "type": "backend" },
              { "participant": "auth", "from": 265, "to": 310, "type": "security" },
              { "participant": "redis", "from": 349, "to": 398, "type": "database" },
              { "participant": "db", "from": 438, "to": 496, "type": "database" },
              { "participant": "trace", "from": 575, "to": 630, "type": "messagebus" }
            ],
            "cards": [
              {
                "dot": "emerald",
                "title": "Happy Path",
                "items": [
                  "The main request is Web App -> API -> data source -> response",
                  "Return messages are quieter than forward calls",
                  "Activation bars make ownership duration visible"
                ]
              },
              {
                "dot": "rose",
                "title": "Policy + Fallback",
                "items": [
                  "JWT verification is colored as a security interaction",
                  "Cache miss is visible without overpowering the main path",
                  "Database access only appears after cache fallback"
                ]
              },
              {
                "dot": "orange",
                "title": "Async Trace",
                "items": [
                  "Trace emission is dashed and secondary",
                  "It does not block the response path",
                  "The diagram separates user-facing latency from observability"
                ]
              }
            ]
          }
          
        • event-stream.dataflow.json 4.7 KB
          {
            "schema_version": 1,
            "diagram_type": "dataflow",
            "meta": {
              "title": "Order Event-stream Topology",
              "output": "examples/event-stream.html",
              "viewBox": [1080, 780],
              "animation": "trace",
              "visual_preset": "signal-flow",
              "quality_profile": "showcase"
            },
            "stages": [
              { "label": "Producers" },
              { "label": "Transit" },
              { "label": "Processors" },
              { "label": "State + recovery" },
              { "label": "Consumers" }
            ],
            "nodes": [
              { "id": "checkout", "type": "frontend", "label": "Checkout API", "sublabel": "order producer", "stage": 0, "row": 0, "tag": "team commerce" },
              { "id": "billing", "type": "backend", "label": "Billing API", "sublabel": "payment producer", "stage": 0, "row": 2, "tag": "team money" },
              { "id": "orders", "type": "messagebus", "label": "orders.v1", "sublabel": "12 partitions", "stage": 1, "row": 0, "tag": "key: order_id" },
              { "id": "payments", "type": "messagebus", "label": "payments.v2", "sublabel": "8 partitions", "stage": 1, "row": 2, "tag": "key: order_id" },
              { "id": "validate", "type": "backend", "label": "Order Validate", "sublabel": "group fulfillment", "stage": 2, "row": 0, "tag": "ordered" },
              { "id": "enrich", "type": "backend", "label": "Payment Enrich", "sublabel": "group analytics", "stage": 2, "row": 2, "tag": "at-least-once" },
              { "id": "state", "type": "database", "label": "Order State", "sublabel": "materialized view", "stage": 3, "row": 1, "tag": "idempotent" },
              { "id": "dlq", "type": "messagebus", "label": "events.dlq", "sublabel": "poison events", "stage": 3, "row": 4, "tag": "7-day retention" },
              { "id": "fulfillment", "type": "backend", "label": "Fulfillment", "sublabel": "shipping workflow", "stage": 4, "row": 0, "tag": "consumer" },
              { "id": "analytics", "type": "database", "label": "Analytics", "sublabel": "streaming facts", "stage": 4, "row": 2, "tag": "consumer" },
              { "id": "replay", "type": "security", "label": "Replay Tool", "sublabel": "approved batch", "stage": 4, "row": 4, "tag": "operator gate" },
              { "id": "ops", "type": "external", "label": "On-call", "sublabel": "DLQ owner", "stage": 4, "row": 3, "yOffset": -18, "tag": "SRE" }
            ],
            "flows": [
              { "from": "checkout", "to": "orders", "label": "OrderPlaced", "classification": "schema v1", "variant": "emphasis", "route": "straight" },
              { "from": "billing", "to": "payments", "label": "PaymentCaptured", "classification": "schema v2", "variant": "emphasis", "route": "straight" },
              { "from": "orders", "to": "validate", "label": "ordered orders", "classification": "consumer group", "variant": "emphasis", "route": "straight" },
              { "from": "payments", "to": "enrich", "label": "payment facts", "classification": "at-least-once", "variant": "emphasis", "route": "straight" },
              { "from": "validate", "to": "state", "label": "valid order", "classification": "idempotent", "variant": "emphasis", "route": "vertical-channel" },
              { "from": "enrich", "to": "state", "label": "enriched payment", "classification": "idempotent", "variant": "default", "route": "vertical-channel" },
              { "from": "state", "to": "fulfillment", "label": "ready orders", "classification": "read model", "variant": "emphasis", "route": "vertical-channel" },
              { "from": "state", "to": "analytics", "label": "order facts", "classification": "non-PII", "variant": "default", "route": "vertical-channel" },
              { "from": "validate", "to": "dlq", "label": "invalid event", "classification": "dead letter", "variant": "security", "fromSide": "top", "toSide": "top", "via": [[530, 80], [20, 80], [20, 550], [745, 550]], "labelAt": [300, 550] },
              { "from": "enrich", "to": "dlq", "label": "poison event", "classification": "dead letter", "variant": "security", "route": "bottom-channel", "labelDy": 30 },
              { "from": "dlq", "to": "ops", "label": "failure sample", "classification": "restricted", "variant": "security", "route": "vertical-channel" },
              { "from": "dlq", "to": "replay", "label": "approved replay", "classification": "audited batch", "variant": "dashed", "route": "straight", "labelDy": 30 }
            ],
            "cards": [
              { "dot": "amber", "title": "Transit Contract", "items": ["Every event and topic is named", "Partition keys preserve per-order ordering", "Consumer groups expose processing ownership"] },
              { "dot": "emerald", "title": "State + Delivery", "items": ["Processors write an idempotent materialized view", "Fulfillment and analytics consume distinct assets", "At-least-once delivery never implies duplicate business effects"] },
              { "dot": "rose", "title": "Failure Ownership", "items": ["Poison events land in a retained dead-letter topic", "On-call inspects samples before replay", "Replay is gated, batched, and auditable"] }
            ]
          }
          
        • product-analytics.dataflow.json 4.7 KB
          {
            "schema_version": 1,
            "diagram_type": "dataflow",
            "meta": {
              "title": "Product Analytics Data Flow",
              "subtitle": "Events, consent, PII isolation, warehouse sync, and downstream analytics",
              "output": "examples/dataflow-product-analytics.html",
              "viewBox": [1080, 760]
            },
            "stages": [
              { "label": "Sources" },
              { "label": "Ingest" },
              { "label": "Process" },
              { "label": "Store" },
              { "label": "Consume" }
            ],
            "nodes": [
              { "id": "web", "type": "frontend", "label": "Web App", "sublabel": "browser SDK", "stage": 0, "row": 0, "tag": "events" },
              { "id": "mobile", "type": "frontend", "label": "Mobile", "sublabel": "iOS / Android", "stage": 0, "row": 2, "tag": "events" },
              { "id": "edge", "type": "cloud", "label": "Edge API", "sublabel": "collector", "stage": 1, "row": 1, "tag": "TLS" },
              { "id": "consent", "type": "security", "label": "Consent Gate", "sublabel": "policy filter", "stage": 2, "row": 0, "tag": "PII guard" },
              { "id": "stream", "type": "messagebus", "label": "Event Stream", "sublabel": "Kafka topic", "stage": 2, "row": 2, "tag": "ordered" },
              { "id": "pii", "type": "security", "label": "PII Vault", "sublabel": "encrypted", "stage": 3, "row": 0, "tag": "restricted" },
              { "id": "warehouse", "type": "database", "label": "Warehouse", "sublabel": "analytics tables", "stage": 3, "row": 2, "tag": "curated" },
              { "id": "features", "type": "database", "label": "Feature Store", "sublabel": "daily batch", "stage": 3, "row": 4, "tag": "derived" },
              { "id": "dashboard", "type": "backend", "label": "Dashboards", "sublabel": "product metrics", "stage": 4, "row": 1, "tag": "SQL" },
              { "id": "model", "type": "backend", "label": "ML Model", "sublabel": "ranking job", "stage": 4, "row": 4, "tag": "features" }
            ],
            "flows": [
              { "from": "web", "to": "edge", "label": "clickstream", "classification": "user events", "variant": "emphasis", "fromSide": "right", "toSide": "left", "via": [[184, 157], [184, 271]], "labelAt": [204, 190] },
              { "from": "mobile", "to": "edge", "label": "app events", "classification": "device events", "variant": "default", "fromSide": "right", "toSide": "left", "via": [[222, 385], [222, 271]], "labelAt": [220, 342] },
              { "from": "edge", "to": "consent", "label": "identity + consent", "classification": "PII touch", "variant": "security", "fromSide": "top", "toSide": "left", "via": [[315, 112], [450, 112], [450, 157]], "labelAt": [382, 100] },
              { "from": "edge", "to": "stream", "label": "accepted events", "classification": "append-only", "variant": "emphasis", "fromSide": "right", "toSide": "left", "via": [[420, 271], [420, 385]], "labelAt": [438, 324] },
              { "from": "consent", "to": "pii", "label": "identity map", "classification": "encrypted PII", "variant": "security", "route": "straight", "labelAt": [638, 144] },
              { "from": "stream", "to": "warehouse", "label": "normalized facts", "classification": "non-PII", "variant": "emphasis", "route": "straight", "labelAt": [638, 372] },
              { "from": "warehouse", "to": "features", "label": "daily aggregates", "classification": "batch", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "route": "straight", "labelAt": [745, 496] },
              { "from": "warehouse", "to": "dashboard", "label": "metrics SQL", "classification": "read-only", "variant": "default", "fromSide": "right", "toSide": "left", "via": [[852, 385], [852, 271]], "labelAt": [830, 326] },
              { "from": "features", "to": "model", "label": "feature vectors", "classification": "derived", "variant": "dashed", "route": "straight", "labelAt": [852, 598] },
              { "from": "pii", "to": "dashboard", "label": "restricted join", "classification": "approved only", "variant": "security", "fromSide": "right", "toSide": "top", "via": [[878, 157], [878, 212], [960, 212]], "labelAt": [880, 198] }
            ],
            "cards": [
              {
                "dot": "emerald",
                "title": "Primary Data Path",
                "items": [
                  "Events move left to right through source, ingest, process, store, and consume stages",
                  "The hot path stays visually clear even with secondary batch flows",
                  "Labels name data assets instead of generic API verbs"
                ]
              },
              {
                "dot": "rose",
                "title": "Sensitive Boundary",
                "items": [
                  "Consent and PII paths are styled as security flows",
                  "PII lands in a restricted vault, separate from the analytics warehouse",
                  "Restricted joins are visible without implying default access"
                ]
              },
              {
                "dot": "orange",
                "title": "Derived Consumers",
                "items": [
                  "Dashboards read curated facts from the warehouse",
                  "Feature vectors are derived by batch from analytics tables",
                  "Consumption paths stay distinct from collection and consent handling"
                ]
              }
            ]
          }
          
        • production-deployment.architecture.json 4.6 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "Production Deployment Ownership",
              "output": "examples/production-deployment.html",
              "visual_preset": "blueprint",
              "animation": "trace",
              "quality_profile": "showcase",
              "engineering_profile": "deployment-ownership"
            },
            "components": [
              { "id": "clients", "type": "external", "label": "Customers", "sublabel": "web + mobile", "pos": [38, 300], "size": [122, 60] },
              { "id": "edge", "type": "cloud", "label": "Global Edge", "sublabel": "CDN + WAF", "pos": [230, 300], "size": [126, 60], "tag": "edge team" },
              { "id": "gateway", "type": "security", "label": "API Gateway", "sublabel": "public :443", "pos": [430, 300], "size": [128, 60], "tag": "platform" },
              { "id": "api_a", "type": "backend", "label": "API Pods / AZ-a", "sublabel": "private subnet", "pos": [630, 195], "size": [136, 62], "tag": "app team" },
              { "id": "api_b", "type": "backend", "label": "API Pods / AZ-b", "sublabel": "private subnet", "pos": [630, 405], "size": [136, 62], "tag": "app team" },
              { "id": "redis", "type": "database", "label": "Redis", "sublabel": "multi-AZ cache", "pos": [840, 195], "size": [126, 62], "tag": "platform" },
              { "id": "postgres", "type": "database", "label": "PostgreSQL", "sublabel": "primary / encrypted", "pos": [840, 405], "size": [126, 62], "tag": "data team" },
              { "id": "events", "type": "messagebus", "label": "Event Bus", "sublabel": "orders.v1", "pos": [1040, 300], "size": [126, 60], "tag": "platform" },
              { "id": "worker", "type": "backend", "label": "Workers", "sublabel": "private workload", "pos": [1240, 300], "size": [126, 60], "tag": "app team" },
              { "id": "replica", "type": "database", "label": "DR Replica", "sublabel": "eu-west-1", "pos": [1040, 610], "size": [126, 62], "tag": "data team" },
              { "id": "audit", "type": "cloud", "label": "Audit Archive", "sublabel": "immutable objects", "pos": [1240, 465], "size": [126, 62], "tag": "security" },
              { "id": "observability", "type": "external", "label": "Observability", "sublabel": "metrics + traces", "pos": [1240, 85], "size": [126, 62], "tag": "SRE" }
            ],
            "boundaries": [
              { "kind": "region", "label": "AWS us-east-1 / production", "wraps": ["edge", "gateway", "api_a", "api_b", "redis", "postgres", "events", "worker", "audit"] },
              { "kind": "security-group", "label": "private application network", "wraps": ["api_a", "api_b", "redis", "postgres", "events", "worker"] },
              { "kind": "region", "label": "AWS eu-west-1 / disaster recovery", "wraps": ["replica"] },
              { "kind": "security-group", "label": "DR private subnet", "wraps": ["replica"], "pad": 14 }
            ],
            "connections": [
              { "from": "clients", "to": "edge", "label": "HTTPS", "variant": "emphasis" },
              { "from": "edge", "to": "gateway", "label": "mTLS", "variant": "security" },
              { "from": "gateway", "to": "api_a", "label": "VPC route", "variant": "emphasis", "route": "orthogonal-h", "labelAt": [594, 275] },
              { "from": "gateway", "to": "api_b", "label": "VPC route", "variant": "emphasis", "route": "orthogonal-h", "labelAt": [594, 385] },
              { "from": "api_a", "to": "redis", "label": "cache", "route": "straight" },
              { "from": "api_b", "to": "postgres", "label": "SQL", "route": "straight" },
              { "from": "api_a", "to": "events", "label": "publish", "variant": "dashed", "fromSide": "top", "toSide": "top", "via": [[698, 170], [1103, 170]] },
              { "from": "api_b", "to": "events", "variant": "dashed", "fromSide": "top", "toSide": "bottom", "via": [[698, 380], [1103, 380]] },
              { "from": "events", "to": "worker", "variant": "emphasis" },
              { "from": "postgres", "to": "replica", "label": "cross-region WAL", "variant": "security", "route": "orthogonal-v", "labelAt": [1003, 529] },
              { "from": "worker", "to": "audit", "label": "evidence", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 58 },
              { "from": "worker", "to": "observability", "label": "OTLP", "variant": "dashed", "route": "orthogonal-v" }
            ],
            "cards": [
              { "dot": "cyan", "title": "Runtime Ownership", "items": ["Platform owns the edge, gateway, cache, and event bus", "Application teams own API pods and workers", "Data owns primary and disaster-recovery state"] },
              { "dot": "rose", "title": "Named Crossings", "items": ["Public HTTPS terminates at the managed edge", "mTLS crosses into the application network", "Cross-region WAL is explicit and encrypted"] },
              { "dot": "emerald", "title": "Operational Evidence", "items": ["Workers emit traces to SRE-owned observability", "Audit evidence lands in immutable storage", "Unknown placement should remain marked, never invented"] }
            ]
          }
          
        • web-app.architecture.json 3 KB
          {
            "schema_version": 1,
            "diagram_type": "architecture",
            "meta": {
              "title": "Sample Web App",
              "subtitle": "Classic 3-tier SaaS on AWS — rendered by Archify",
              "output": "web-app-rendered.html"
            },
            "components": [
              { "id": "users", "type": "external", "label": "Users", "sublabel": "Browser / Mobile", "pos": [40, 300], "size": [120, 60] },
              { "id": "auth", "type": "security", "label": "Auth Provider", "sublabel": "OAuth 2.0", "pos": [40, 110], "size": [120, 64], "tag": "JWT + PKCE" },
              { "id": "cdn", "type": "cloud", "label": "CloudFront", "sublabel": "CDN", "pos": [250, 300], "size": [130, 60] },
              { "id": "lb", "type": "cloud", "label": "Load Balancer", "sublabel": "HTTPS :443", "pos": [460, 300], "size": [130, 60] },
              { "id": "api", "type": "backend", "label": "API Server", "sublabel": "FastAPI :8000", "pos": [670, 300], "size": [130, 60] },
              { "id": "cache", "type": "database", "label": "Redis", "sublabel": "cache :6379", "pos": [670, 150], "size": [130, 60] },
              { "id": "db", "type": "database", "label": "PostgreSQL", "sublabel": "primary :5432", "pos": [880, 300], "size": [130, 60] },
              { "id": "s3", "type": "cloud", "label": "S3", "sublabel": "static assets", "pos": [250, 440], "size": [130, 60], "tag": "OAI protected" },
              { "id": "queue", "type": "messagebus", "label": "SQS", "sublabel": "job queue", "pos": [670, 440], "size": [130, 60] },
              { "id": "worker", "type": "backend", "label": "Worker", "sublabel": "async jobs", "pos": [880, 440], "size": [130, 60] }
            ],
            "boundaries": [
              { "kind": "region", "label": "AWS Region: us-west-2", "wraps": ["cdn", "lb", "api", "cache", "db", "s3", "queue", "worker"] },
              { "kind": "security-group", "label": "sg-api :443/:8000", "wraps": ["lb", "api"] }
            ],
            "connections": [
              { "from": "users", "to": "cdn", "label": "HTTPS", "variant": "emphasis" },
              { "from": "auth", "to": "api", "label": "verify JWT", "variant": "security", "fromSide": "right", "toSide": "left", "via": [[620, 142], [620, 330]] },
              { "from": "cdn", "to": "lb" },
              { "from": "cdn", "to": "s3", "label": "static", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 58 },
              { "from": "lb", "to": "api" },
              { "from": "api", "to": "cache", "label": "read-through", "fromSide": "top", "toSide": "bottom", "labelDy": -68 },
              { "from": "api", "to": "db", "label": "SQL" },
              { "from": "api", "to": "queue", "label": "enqueue", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "labelDy": 58 },
              { "from": "queue", "to": "worker" }
            ],
            "cards": [
              { "dot": "cyan", "title": "Edge", "items": ["CloudFront CDN fronts all traffic", "S3 serves static assets via OAI"] },
              { "dot": "emerald", "title": "Application", "items": ["FastAPI behind an HTTPS load balancer", "Redis read-through cache", "Async work drained from SQS by a worker"] },
              { "dot": "rose", "title": "Security", "items": ["OAuth 2.0 with JWT + PKCE", "API + LB isolated in a security group"] }
            ]
          }
          
      • workflow-first-draft
        • release-luna.workflow.json 8.1 KB
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "一次生产发布审批工作流",
              "locale": "zh-CN",
              "quality_profile": "showcase",
              "output": "release-luna.html"
            },
            "lanes": [
              {
                "id": "developer",
                "label": "开发者"
              },
              {
                "id": "ci",
                "label": "CI 与发布平台"
              },
              {
                "id": "oncall",
                "label": "值班负责人"
              },
              {
                "id": "audit",
                "label": "审计旁路"
              }
            ],
            "phases": [
              {
                "id": "build_phase",
                "label": "提交与验证",
                "fromCol": 0,
                "toCol": 2
              },
              {
                "id": "approval_phase",
                "label": "预发布与审批",
                "fromCol": 2,
                "toCol": 4
              },
              {
                "id": "release_phase",
                "label": "灰度与全量",
                "fromCol": 4,
                "toCol": 5
              }
            ],
            "groups": [
              {
                "id": "parallel_checks",
                "label": "并行检查,全部通过才汇合",
                "lane": "ci",
                "fromCol": 1,
                "toCol": 2,
                "variant": "security"
              }
            ],
            "mainPath": [
              "submit_release",
              "test_join",
              "staging_deploy",
              "smoke_test",
              "duty_approval",
              "canary_5",
              "metric_gate",
              "full_release",
              "publish_success"
            ],
            "nodes": [
              {
                "id": "submit_release",
                "lane": "developer",
                "col": 0,
                "type": "frontend",
                "label": "提交版本",
                "sublabel": "开发者发起发布"
              },
              {
                "id": "unit_tests",
                "lane": "ci",
                "col": 1,
                "type": "backend",
                "label": "单元测试",
                "sublabel": "并行执行",
                "yOffset": -68
              },
              {
                "id": "security_scan",
                "lane": "ci",
                "col": 1,
                "type": "security",
                "label": "安全扫描",
                "sublabel": "并行执行",
                "yOffset": 68
              },
              {
                "id": "test_join",
                "lane": "ci",
                "col": 2,
                "type": "backend",
                "label": "检查汇合",
                "sublabel": "两项均通过"
              },
              {
                "id": "staging_deploy",
                "lane": "ci",
                "col": 2,
                "type": "cloud",
                "label": "预发布部署",
                "sublabel": "部署候选版本"
              },
              {
                "id": "smoke_test",
                "lane": "ci",
                "col": 3,
                "type": "backend",
                "label": "冒烟测试",
                "sublabel": "验证预发布环境"
              },
              {
                "id": "duty_approval",
                "lane": "oncall",
                "col": 4,
                "type": "security",
                "label": "值班负责人审批",
                "sublabel": "批准或拒绝"
              },
              {
                "id": "canary_5",
                "lane": "ci",
                "col": 4,
                "type": "cloud",
                "label": "5% 灰度",
                "sublabel": "观察生产指标"
              },
              {
                "id": "metric_gate",
                "lane": "ci",
                "col": 5,
                "type": "security",
                "label": "指标达标?",
                "sublabel": "灰度结果分支"
              },
              {
                "id": "rollback_stable",
                "lane": "ci",
                "col": 5,
                "type": "backend",
                "label": "回滚上一稳定版本",
                "sublabel": "指标不达标"
              },
              {
                "id": "rollback_end",
                "lane": "ci",
                "col": 5,
                "type": "external",
                "label": "终止本次发布",
                "sublabel": "通知负责人;不自动重试"
              },
              {
                "id": "full_release",
                "lane": "ci",
                "col": 5,
                "type": "cloud",
                "label": "全量发布",
                "sublabel": "指标达标"
              },
              {
                "id": "publish_success",
                "lane": "developer",
                "col": 5,
                "type": "external",
                "label": "通知开发者成功"
              },
              {
                "id": "revise_version",
                "lane": "developer",
                "col": 1,
                "type": "frontend",
                "label": "修改版本",
                "sublabel": "修复后重新提交",
                "yOffset": 175
              },
              {
                "id": "audit_log",
                "lane": "audit",
                "col": 3,
                "type": "database",
                "label": "审计日志",
                "sublabel": "旁路记录:测试、审批、灰度、回滚",
                "yOffset": 112
              }
            ],
            "edges": [
              {
                "id": "submit_to_unit",
                "from": "submit_release",
                "to": "unit_tests",
                "label": "提交后触发",
                "role": "main"
              },
              {
                "id": "submit_to_scan",
                "from": "submit_release",
                "to": "security_scan",
                "label": "提交后触发",
                "role": "branch",
                "variant": "security"
              },
              {
                "id": "unit_pass",
                "from": "unit_tests",
                "to": "test_join",
                "label": "通过"
              },
              {
                "id": "scan_pass",
                "from": "security_scan",
                "to": "test_join",
                "label": "通过",
                "variant": "security"
              },
              {
                "id": "join_to_staging",
                "from": "test_join",
                "to": "staging_deploy",
                "label": "两项均通过",
                "role": "main"
              },
              {
                "id": "staging_to_smoke",
                "from": "staging_deploy",
                "to": "smoke_test",
                "label": "部署完成",
                "role": "main"
              },
              {
                "id": "smoke_to_approval",
                "from": "smoke_test",
                "to": "duty_approval",
                "label": "冒烟通过",
                "role": "main"
              },
              {
                "id": "approval_to_canary",
                "from": "duty_approval",
                "to": "canary_5",
                "label": "批准",
                "role": "main"
              },
              {
                "id": "canary_to_gate",
                "from": "canary_5",
                "to": "metric_gate",
                "label": "观察完成",
                "role": "main"
              },
              {
                "id": "gate_to_full",
                "from": "metric_gate",
                "to": "full_release",
                "label": "达标",
                "role": "main"
              },
              {
                "id": "full_to_success",
                "from": "full_release",
                "to": "publish_success",
                "label": "发布完成",
                "role": "main"
              },
              {
                "id": "tests_fail_to_revise",
                "from": "unit_tests",
                "to": "revise_version",
                "label": "失败,修改",
                "role": "error",
                "variant": "dashed"
              },
              {
                "id": "scan_fail_to_revise",
                "from": "security_scan",
                "to": "revise_version",
                "label": "失败,修改",
                "role": "error",
                "variant": "dashed"
              },
              {
                "id": "smoke_fail_to_revise",
                "from": "smoke_test",
                "to": "revise_version",
                "label": "失败,修改",
                "role": "error",
                "variant": "dashed"
              },
              {
                "id": "approval_reject_to_revise",
                "from": "duty_approval",
                "to": "revise_version",
                "label": "拒绝,修改",
                "role": "error",
                "variant": "dashed"
              },
              {
                "id": "revise_to_submit",
                "from": "revise_version",
                "to": "submit_release",
                "label": "重新提交",
                "role": "return",
                "variant": "dashed"
              },
              {
                "id": "gate_to_rollback",
                "from": "metric_gate",
                "to": "rollback_stable",
                "label": "不达标,回滚",
                "role": "error",
                "variant": "security"
              },
              {
                "id": "rollback_to_end",
                "from": "rollback_stable",
                "to": "rollback_end",
                "label": "回滚完成",
                "role": "error",
                "variant": "dashed"
              },
              {
                "id": "test_audit",
                "from": "test_join",
                "to": "audit_log",
                "label": "记录测试结果",
                "role": "async",
                "variant": "dashed"
              },
              {
                "id": "approval_audit",
                "from": "duty_approval",
                "to": "audit_log",
                "label": "记录审批决定",
                "role": "async",
                "variant": "dashed"
              },
              {
                "id": "canary_audit",
                "from": "metric_gate",
                "to": "audit_log",
                "label": "记录灰度结果",
                "role": "async",
                "variant": "dashed"
              },
              {
                "id": "rollback_audit",
                "from": "rollback_end",
                "to": "audit_log",
                "label": "记录回滚结果",
                "role": "async",
                "variant": "dashed"
              }
            ],
            "cards": [
              {
                "dot": "cyan",
                "title": "控制条件",
                "items": [
                  "单元测试与安全扫描并行,只有全部通过才进入预发布。",
                  "审计日志是旁路记录,不决定成功或重试。"
                ]
              },
              {
                "dot": "amber",
                "title": "失败路径",
                "items": [
                  "测试、冒烟或审批拒绝都回到开发者修改并重新提交。",
                  "灰度指标不达标时回滚并终止本次发布,不自动重新灰度。"
                ]
              }
            ]
          }
      • workflow-viewport
        • order-overflow.workflow.json 5.4 KB
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "订单处理工作流",
              "output": "order-overflow.html",
              "locale": "zh-CN",
              "quality_profile": "showcase"
            },
            "lanes": [
              { "id": "order_flow", "label": "订单处理流程" }
            ],
            "phases": [
              { "id": "submit_phase", "label": "提交与校验", "fromCol": 0, "toCol": 1 },
              { "id": "payment_phase", "label": "支付等待", "fromCol": 2, "toCol": 4, "variant": "emphasis" },
              { "id": "fulfillment_phase", "label": "履约与收尾", "fromCol": 5, "toCol": 5 }
            ],
            "mainPath": ["submit_order", "check_inventory", "reserve_inventory", "create_pending", "wait_payment", "payment_success", "deduct_inventory", "ship_order"],
            "semanticChecks": {
              "allowedRoots": ["submit_order"],
              "allowedTerminals": ["notify_insufficient", "release_inventory", "ship_order", "manual_fulfillment"],
              "requiredEdges": [
                { "from": "submit_order", "to": "check_inventory" },
                { "from": "check_inventory", "to": "reserve_inventory" },
                { "from": "reserve_inventory", "to": "create_pending" },
                { "from": "create_pending", "to": "wait_payment" },
                { "from": "wait_payment", "to": "payment_success" },
                { "from": "payment_success", "to": "deduct_inventory" },
                { "from": "deduct_inventory", "to": "ship_order" },
                { "from": "check_inventory", "to": "notify_insufficient" },
                { "from": "wait_payment", "to": "cancel_order" },
                { "from": "cancel_order", "to": "release_inventory" },
                { "from": "ship_order", "to": "manual_fulfillment" }
              ],
              "requiredPaths": [
                { "from": "check_inventory", "to": "notify_insufficient" },
                { "from": "wait_payment", "to": "cancel_order" },
                { "from": "cancel_order", "to": "release_inventory" },
                { "from": "ship_order", "to": "manual_fulfillment" }
              ]
            },
            "nodes": [
              { "id": "submit_order", "lane": "order_flow", "col": 0, "type": "external", "label": "提交订单", "sublabel": "用户确认商品" },
              { "id": "check_inventory", "lane": "order_flow", "col": 1, "type": "backend", "label": "校验库存", "sublabel": "检查可售数量" },
              { "id": "reserve_inventory", "lane": "order_flow", "col": 2, "type": "database", "label": "预占库存", "sublabel": "锁定可售数量" },
              { "id": "create_pending", "lane": "order_flow", "col": 3, "type": "backend", "label": "创建待支付订单", "sublabel": "订单状态:待支付", "width": 92 },
              { "id": "wait_payment", "lane": "order_flow", "col": 4, "type": "external", "label": "等待支付", "sublabel": "等待支付结果" },
              { "id": "payment_success", "lane": "order_flow", "col": 5, "type": "backend", "label": "支付成功", "sublabel": "确认到账", "yOffset": -110 },
              { "id": "deduct_inventory", "lane": "order_flow", "col": 5, "type": "database", "label": "扣减库存", "sublabel": "结算预占数量" },
              { "id": "ship_order", "lane": "order_flow", "col": 5, "type": "backend", "label": "发货", "sublabel": "创建配送任务", "yOffset": 80 },
              { "id": "notify_insufficient", "lane": "order_flow", "col": 2, "type": "external", "label": "提示库存不足", "sublabel": "订单失败", "yOffset": 100 },
              { "id": "cancel_order", "lane": "order_flow", "col": 5, "type": "backend", "label": "取消订单", "sublabel": "支付超时", "yOffset": 140 },
              { "id": "release_inventory", "lane": "order_flow", "col": 4, "type": "database", "label": "释放预占库存", "sublabel": "恢复可售数量", "yOffset": 160 },
              { "id": "manual_fulfillment", "lane": "order_flow", "col": 5, "type": "external", "label": "人工处理", "sublabel": "发货失败", "yOffset": 260 }
            ],
            "edges": [
              { "id": "submit_to_check", "from": "submit_order", "to": "check_inventory", "role": "main" },
              { "id": "check_to_reserve", "from": "check_inventory", "to": "reserve_inventory", "label": "库存充足", "role": "main", "variant": "emphasis" },
              { "id": "reserve_to_pending", "from": "reserve_inventory", "to": "create_pending", "label": "预占成功", "role": "main" },
              { "id": "pending_to_wait", "from": "create_pending", "to": "wait_payment", "role": "main" },
              { "id": "wait_to_paid", "from": "wait_payment", "to": "payment_success", "label": "支付成功", "role": "main", "variant": "emphasis" },
              { "id": "paid_to_deduct", "from": "payment_success", "to": "deduct_inventory", "label": "结算预占", "role": "main" },
              { "id": "deduct_to_ship", "from": "deduct_inventory", "to": "ship_order", "role": "main", "variant": "emphasis" },
              { "id": "check_to_insufficient", "from": "check_inventory", "to": "notify_insufficient", "label": "库存不足", "role": "error", "variant": "security" },
              { "id": "wait_to_timeout", "from": "wait_payment", "to": "cancel_order", "label": "支付超时", "role": "error", "variant": "security" },
              { "id": "cancel_to_release", "from": "cancel_order", "to": "release_inventory", "label": "释放预占", "role": "error", "variant": "dashed" },
              { "id": "ship_to_manual", "from": "ship_order", "to": "manual_fulfillment", "label": "发货失败", "role": "error", "variant": "security" }
            ],
            "cards": [
              { "dot": "emerald", "title": "库存语义", "items": ["库存充足后先预占", "支付成功再扣减", "支付超时释放预占"] },
              { "dot": "amber", "title": "异常出口", "items": ["库存不足提示订单失败", "支付超时取消订单", "发货失败转人工处理"] }
            ]
          }
          
        • order-reflow.workflow.json 6.8 KB
          {
            "schema_version": 2,
            "diagram_type": "workflow",
            "meta": {
              "title": "订单处理工作流",
              "output": "order-reflow.html",
              "locale": "zh-CN",
              "quality_profile": "showcase"
            },
            "lanes": [
              {
                "id": "order",
                "label": "订单与支付"
              },
              {
                "id": "result",
                "label": "库存与订单结果"
              },
              {
                "id": "fulfil",
                "label": "履约与异常处理"
              }
            ],
            "phases": [
              {
                "id": "submit_phase",
                "label": "提交与校验",
                "fromCol": 0,
                "toCol": 1
              },
              {
                "id": "payment_phase",
                "label": "支付等待",
                "fromCol": 2,
                "toCol": 4,
                "variant": "emphasis"
              },
              {
                "id": "fulfillment_phase",
                "label": "履约与收尾",
                "fromCol": 5,
                "toCol": 5
              }
            ],
            "mainPath": [
              "submit_order",
              "check_inventory",
              "reserve_inventory",
              "create_pending",
              "wait_payment",
              "payment_success",
              "deduct_inventory",
              "ship_order"
            ],
            "semanticChecks": {
              "allowedRoots": [
                "submit_order"
              ],
              "allowedTerminals": [
                "notify_insufficient",
                "release_inventory",
                "ship_order",
                "manual_fulfillment"
              ],
              "requiredEdges": [
                {
                  "from": "submit_order",
                  "to": "check_inventory"
                },
                {
                  "from": "check_inventory",
                  "to": "reserve_inventory"
                },
                {
                  "from": "reserve_inventory",
                  "to": "create_pending"
                },
                {
                  "from": "create_pending",
                  "to": "wait_payment"
                },
                {
                  "from": "wait_payment",
                  "to": "payment_success"
                },
                {
                  "from": "payment_success",
                  "to": "deduct_inventory"
                },
                {
                  "from": "deduct_inventory",
                  "to": "ship_order"
                },
                {
                  "from": "check_inventory",
                  "to": "notify_insufficient"
                },
                {
                  "from": "wait_payment",
                  "to": "cancel_order"
                },
                {
                  "from": "cancel_order",
                  "to": "release_inventory"
                },
                {
                  "from": "ship_order",
                  "to": "manual_fulfillment"
                }
              ],
              "requiredPaths": [
                {
                  "from": "check_inventory",
                  "to": "notify_insufficient"
                },
                {
                  "from": "wait_payment",
                  "to": "cancel_order"
                },
                {
                  "from": "cancel_order",
                  "to": "release_inventory"
                },
                {
                  "from": "ship_order",
                  "to": "manual_fulfillment"
                }
              ]
            },
            "nodes": [
              {
                "id": "submit_order",
                "lane": "order",
                "col": 0,
                "type": "external",
                "label": "提交订单",
                "sublabel": "用户确认商品"
              },
              {
                "id": "check_inventory",
                "lane": "order",
                "col": 1,
                "type": "backend",
                "label": "校验库存",
                "sublabel": "检查可售数量"
              },
              {
                "id": "reserve_inventory",
                "lane": "order",
                "col": 2,
                "type": "database",
                "label": "预占库存",
                "sublabel": "锁定可售数量"
              },
              {
                "id": "create_pending",
                "lane": "order",
                "col": 3,
                "type": "backend",
                "label": "创建待支付订单",
                "sublabel": "订单状态:待支付",
                "width": 92
              },
              {
                "id": "wait_payment",
                "lane": "order",
                "col": 4,
                "type": "external",
                "label": "等待支付",
                "sublabel": "等待支付结果"
              },
              {
                "id": "payment_success",
                "lane": "order",
                "col": 5,
                "type": "backend",
                "label": "支付成功",
                "sublabel": "确认到账"
              },
              {
                "id": "deduct_inventory",
                "lane": "result",
                "col": 5,
                "type": "database",
                "label": "扣减库存",
                "sublabel": "结算预占数量"
              },
              {
                "id": "ship_order",
                "lane": "fulfil",
                "col": 5,
                "type": "backend",
                "label": "发货",
                "sublabel": "创建配送任务"
              },
              {
                "id": "notify_insufficient",
                "lane": "result",
                "col": 1,
                "type": "external",
                "label": "提示库存不足",
                "sublabel": "订单失败"
              },
              {
                "id": "cancel_order",
                "lane": "result",
                "col": 4,
                "type": "backend",
                "label": "取消订单",
                "sublabel": "支付超时"
              },
              {
                "id": "release_inventory",
                "lane": "fulfil",
                "col": 4,
                "type": "database",
                "label": "释放预占库存",
                "sublabel": "恢复可售数量"
              },
              {
                "id": "manual_fulfillment",
                "lane": "fulfil",
                "col": 3,
                "type": "external",
                "label": "人工处理",
                "sublabel": "发货失败"
              }
            ],
            "edges": [
              {
                "id": "submit_to_check",
                "from": "submit_order",
                "to": "check_inventory",
                "role": "main"
              },
              {
                "id": "check_to_reserve",
                "from": "check_inventory",
                "to": "reserve_inventory",
                "label": "库存充足",
                "role": "main",
                "variant": "emphasis"
              },
              {
                "id": "reserve_to_pending",
                "from": "reserve_inventory",
                "to": "create_pending",
                "label": "预占成功",
                "role": "main"
              },
              {
                "id": "pending_to_wait",
                "from": "create_pending",
                "to": "wait_payment",
                "role": "main"
              },
              {
                "id": "wait_to_paid",
                "from": "wait_payment",
                "to": "payment_success",
                "label": "支付成功",
                "role": "main",
                "variant": "emphasis"
              },
              {
                "id": "paid_to_deduct",
                "from": "payment_success",
                "to": "deduct_inventory",
                "label": "结算预占",
                "role": "main"
              },
              {
                "id": "deduct_to_ship",
                "from": "deduct_inventory",
                "to": "ship_order",
                "role": "main",
                "variant": "emphasis"
              },
              {
                "id": "check_to_insufficient",
                "from": "check_inventory",
                "to": "notify_insufficient",
                "label": "库存不足",
                "role": "error",
                "variant": "security"
              },
              {
                "id": "wait_to_timeout",
                "from": "wait_payment",
                "to": "cancel_order",
                "label": "支付超时",
                "role": "error",
                "variant": "security"
              },
              {
                "id": "cancel_to_release",
                "from": "cancel_order",
                "to": "release_inventory",
                "label": "释放预占",
                "role": "error",
                "variant": "dashed"
              },
              {
                "id": "ship_to_manual",
                "from": "ship_order",
                "to": "manual_fulfillment",
                "label": "发货失败",
                "role": "error",
                "variant": "security"
              }
            ],
            "cards": [
              {
                "dot": "emerald",
                "title": "库存语义",
                "items": [
                  "库存充足后先预占",
                  "支付成功再扣减",
                  "支付超时释放预占"
                ]
              },
              {
                "dot": "amber",
                "title": "异常出口",
                "items": [
                  "库存不足提示订单失败",
                  "支付超时取消订单",
                  "发货失败转人工处理"
                ]
              }
            ]
          }
          
        • README.md 1.6 KB
          # Order workflow viewport regression
          
          Original task (Chinese): 用户提交订单,校验并预占库存,创建待支付订单并等待支付;支付成功扣减库存并发货;库存不足提示失败;支付超时取消订单并释放预占库存;发货失败进入人工处理。
          
          `order-overflow.workflow.json` is the final failed candidate from a Luna trial on
          PR #325 (`d634028`), after three layout repairs. Static showcase validation
          passed, but 1440×900 browser scrollHeight was 1499. Height-aware fitting now contains this implicit stacked workflow without changing
          its SVG geometry. The original layout remains a historical regression fixture,
          not a recommended authoring example.
          
          `order-reflow.workflow.json` preserves its node business fields, edges, mainPath,
          semanticChecks, cards, phases and metadata. Only lane grouping, columns and
          vertical offsets differ. Both compile and deliver successfully. The browser
          regression verifies that both implicit layouts fit. A copy pinned to the historical
          `860×786` viewBox still yields measured lane-overflow evidence: authored canvases
          retain their geometry, and the diagnostic gate remains exercised. It blocks remote HTTP(S) resources
          for repeatable font conditions; it does not establish online font reliability.
          
          Rendered frame IDs are indices, not source ownership IDs. The diagnostic's
          contained node boxes and blank-space measurements are observations, not proof
          that headers, routing space, ownership boundaries or absolute pins can be moved.
          The repaired layout is one valid answer to this task, not a universal repair.
          
      • automatic-routing-node-border-clearance.workflow.json 917 B
        {
          "schema_version": 1,
          "diagram_type": "workflow",
          "meta": {
            "title": "自动连线节点边框避让回归",
            "output": "automatic-routing-node-border-clearance.html",
            "quality_profile": "showcase",
            "viewBox": [720, 360]
          },
          "lanes": [
            { "id": "orchestrator", "label": "Orchestrator PTY" },
            { "id": "runtime", "label": "Hive Runtime" }
          ],
          "nodes": [
            {
              "id": "team_send",
              "lane": "orchestrator",
              "col": 2,
              "type": "backend",
              "label": "team send 派单",
              "sublabel": "选择目标 Worker"
            },
            {
              "id": "inject",
              "lane": "runtime",
              "col": 1,
              "type": "security",
              "label": "校验并注入输入",
              "sublabel": "UI token → PTY stdin"
            }
          ],
          "edges": [
            {
              "id": "stdin",
              "from": "inject",
              "to": "team_send",
              "label": "PTY stdin",
              "variant": "emphasis"
            }
          ]
        }
        
      • fail-migration-cleanup.mjs 595 B · in bundle
      • japanese-locale.architecture.json 37.3 KB
        {
          "schema_version": 1,
          "diagram_type": "architecture",
          "meta": {
            "title": "日本語ウェブアプリ",
            "subtitle": "ロケール検証用の固定入力",
            "locale": "ja",
            "translations": {
              "page.title": "{title} ダイアグラム",
              "diagram.description.architecture": "Archifyで生成されたアーキテクチャ図です。",
              "diagram.description.workflow": "Archifyで生成されたワークフロー図です。",
              "diagram.description.sequence": "Archifyで生成されたシーケンス図です。",
              "diagram.description.dataflow": "Archifyで生成されたデータフロー図です。",
              "diagram.description.lifecycle": "Archifyで生成されたライフサイクル図です。",
              "node.focus": "{label} にフォーカス",
              "node.focus.detail": "{label} にフォーカス、{detail}",
              "node.context.architecture": "アーキテクチャコンポーネント",
              "node.context.workflow": "ワークフローノード",
              "node.context.sequence": "シーケンス参加者",
              "node.context.dataflow": "データフローノード",
              "node.context.lifecycle": "ライフサイクル状態",
              "legend.title": "凡例",
              "legend.architecture.frontend": "フロントエンド",
              "legend.architecture.backend": "バックエンド",
              "legend.architecture.database": "データベース",
              "legend.architecture.cloud": "クラウド",
              "legend.architecture.security": "セキュリティ",
              "legend.architecture.messagebus": "メッセージバス",
              "legend.architecture.external": "外部",
              "legend.workflow.frontend": "ユーザーUI",
              "legend.workflow.backend": "エージェントロジック",
              "legend.workflow.security": "ポリシー",
              "legend.workflow.messagebus": "ツール実行",
              "legend.workflow.database": "コンテキスト / トレース",
              "legend.workflow.cloud": "クラウドサービス",
              "legend.workflow.external": "外部システム",
              "legend.sequence.emphasis": "リクエスト",
              "legend.sequence.return": "戻り値",
              "legend.sequence.security": "セキュリティ",
              "legend.sequence.dashed": "非同期トレース",
              "legend.sequence.default": "デフォルトメッセージ",
              "legend.dataflow.emphasis": "主要データ",
              "legend.dataflow.security": "ポリシー / PII",
              "legend.dataflow.dashed": "非同期バッチ",
              "legend.dataflow.database": "データストア",
              "legend.dataflow.default": "データフロー",
              "legend.lifecycle.start": "開始",
              "legend.lifecycle.active": "アクティブ状態",
              "legend.lifecycle.waiting": "待機",
              "legend.lifecycle.decision": "判断",
              "legend.lifecycle.success": "正常終了",
              "legend.lifecycle.failure": "失敗 / 終了",
              "legend.lifecycle.neutral": "中立",
              "legend.lifecycle.external": "外部",
              "viewer.kind.frontend": "フロントエンド",
              "viewer.kind.backend": "バックエンド",
              "viewer.kind.database": "データベース",
              "viewer.kind.cloud": "クラウド",
              "viewer.kind.security": "セキュリティ",
              "viewer.kind.messagebus": "メッセージバス",
              "viewer.kind.external": "外部",
              "viewer.kind.neutral": "中立",
              "viewer.kind.node": "ノード",
              "viewer.kind.start": "開始",
              "viewer.kind.active": "アクティブ",
              "viewer.kind.waiting": "待機",
              "viewer.kind.decision": "判断",
              "viewer.kind.success": "成功",
              "viewer.kind.failure": "失敗",
              "viewer.toolbar.actions": "ダイアグラム操作",
              "viewer.theme.toggle.title": "テーマ切替 (T)",
              "viewer.theme.toggle": "カラーテーマを切替",
              "viewer.theme.dark": "ダーク",
              "viewer.theme.light": "ライト",
              "viewer.preset.choose.title": "ビジュアルスタイルを選択 (Sで循環)",
              "viewer.preset.choose": "ビジュアルスタイルを選択",
              "viewer.preset.style": "スタイル",
              "viewer.preset.menu": "ビジュアルスタイル",
              "viewer.preset.identity": "ビジュアルアイデンティティ",
              "viewer.preset.cycles": "Sで循環",
              "viewer.preset.classic": "クラシック",
              "viewer.preset.classic.short": "クラシック",
              "viewer.preset.classic.hint": "安定した技術標準",
              "viewer.preset.flow": "シグナルフロー",
              "viewer.preset.flow.short": "フロー",
              "viewer.preset.flow.hint": "動きを強調した表現",
              "viewer.preset.blueprint": "ブループリント",
              "viewer.preset.blueprint.hint": "エンジニアリングレビュー向け",
              "viewer.preset.editorial": "エディトリアル",
              "viewer.preset.editorial.hint": "発行・公開ノート向け",
              "viewer.preset.badge.signalFlow": "シグナルフロー",
              "viewer.preset.badge.blueprint": "ブループリント / 改訂01",
              "viewer.preset.badge.editorial": "エディトリアル / フィールドノート",
              "viewer.preset.badge.editorialPlate": "ARCHIFY / プレート04",
              "viewer.preset.current": "ビジュアルスタイル: {style}。ビジュアルスタイルを選択",
              "viewer.motion.live": "ライブ",
              "viewer.motion.still": "静止",
              "viewer.motion.pause": "動きを一時停止",
              "viewer.motion.resume": "動きを再開",
              "viewer.motion.reduced": "「視差効果を減らす」設定により動きを一時停止しました",
              "viewer.motion.hidden": "このページが非表示のため動きを一時停止しました",
              "viewer.motion.yielding": "動きを一時停止、現在 {owner} に譲っています",
              "viewer.motion.yielding.title": "ライブプレビュー有効 · {owner} に譲っています",
              "viewer.owner.route": "ルートプローブ",
              "viewer.owner.lens": "セマンティックレンズ",
              "viewer.owner.relationship": "関係性プレビュー",
              "viewer.owner.intent": "インテントトレース",
              "viewer.owner.focus": "セマンティックフォーカス",
              "viewer.owner.legend": "凡例プレビュー",
              "viewer.owner.reader": "読者の操作",
              "viewer.present.enter": "プレゼンテーションステージに入る",
              "viewer.present.enter.title": "プレゼンテーションステージ (F)",
              "viewer.present.exit": "プレゼンテーションステージを終了",
              "viewer.present.exit.title": "プレゼンテーションステージを終了 (F または Escape)",
              "viewer.present.present": "プレゼンテーション",
              "viewer.present.exit.label": "終了",
              "viewer.export.button": "エクスポート",
              "viewer.export.button.title": "ダイアグラムをエクスポート (E)",
              "viewer.export.diagram": "ダイアグラムをエクスポート",
              "viewer.export.menu": "エクスポート",
              "viewer.export.subtitle": "持ち運びやすくクリーンな出力",
              "viewer.export.share": "共有",
              "viewer.export.shareCard": "シェアカード",
              "viewer.export.routeShareCard": "ルートシェアカード",
              "viewer.export.reachShareCard": "到達範囲シェアカード",
              "viewer.export.copyDiagram": "ダイアグラムをコピー",
              "viewer.export.clipboardPng": "PNGをクリップボードへ",
              "viewer.export.raster": "ラスター画像",
              "viewer.export.image": "画像",
              "viewer.export.lossless": "無劣化画像",
              "viewer.export.compact": "コンパクト画像",
              "viewer.export.modern": "モダン画像",
              "viewer.export.vectorMotion": "ベクターとモーション",
              "viewer.export.vectorMotion.heading": "ベクター & モーション",
              "viewer.export.editable": "編集可能なベクター",
              "viewer.export.motion6s": "6秒のモーション",
              "viewer.export.unsupported": "このブラウザではサポートされていません",
              "viewer.export.clipboardUnsupported": "このブラウザはクリップボードへの画像書き込みに対応していません",
              "viewer.export.clipboardUnsupported.short": "このブラウザはクリップボードへの画像書き込みに対応していません。",
              "viewer.export.motionUnavailable": "このブラウザではモーションキャプチャを利用できません",
              "viewer.export.webmUnavailable": "このブラウザではWebMを利用できません",
              "viewer.export.failed": "エクスポートに失敗しました: {message}",
              "viewer.export.unknownVariant": "不明なシェアカードの種類です: {variant}",
              "viewer.export.routeRequired": "ルートシェアカードをエクスポートする前にルートをトレースしてください",
              "viewer.export.reachRequired": "到達範囲シェアカードをエクスポートする前に編集済みの到達範囲をトレースしてください",
              "viewer.export.unknown": "不明",
              "viewer.export.routeFailed": "ルートシェアカードのエクスポートに失敗しました: {message}",
              "viewer.export.reachFailed": "到達範囲シェアカードのエクスポートに失敗しました: {message}",
              "viewer.export.copyFailed": "コピーに失敗しました: {message}",
              "viewer.export.copiedPng": "PNGをクリップボードにコピーしました",
              "viewer.export.downloadedRoute": "ルートシェアカードをダウンロードしました",
              "viewer.export.downloadedReach": "到達範囲シェアカードをダウンロードしました",
              "viewer.export.downloadedWebm": "WebMをダウンロードしました",
              "viewer.export.recording": "6秒間のモーションを録画中…",
              "viewer.export.card.routeSummary.one": "ルート: {source} → {target} · {count} 個の有向ホップ",
              "viewer.export.card.routeSummary.other": "ルート: {source} → {target} · {count} 個の有向ホップ",
              "viewer.export.card.reachSummary": "{origin} からの編集済み{direction} · {nodes} · {links} · 最大{hops}",
              "viewer.export.card.node.one": "{count} 個のノード",
              "viewer.export.card.node.other": "{count} 個のノード",
              "viewer.export.card.link.one": "{count} 個の接続",
              "viewer.export.card.link.other": "{count} 個の接続",
              "viewer.export.card.hop.one": "{count} ホップ",
              "viewer.export.card.hop.other": "{count} ホップ",
              "viewer.export.card.routeBadge": "ARCHIFY · ROUTE · {hops}",
              "viewer.export.card.reachBadge": "ARCHIFY · {direction} REACH",
              "viewer.export.direction.upstream": "アップストリーム",
              "viewer.export.direction.downstream": "ダウンストリーム",
              "viewer.export.error.canvasUnavailable": "{label} のキャンバスを利用できません",
              "viewer.export.error.contextUnavailable": "{label} の2Dキャンバスコンテキストを利用できません",
              "viewer.export.error.toBlobUnavailable": "{label} でcanvas.toBlobを利用できません",
              "viewer.export.error.toBlobNull": "{label} のcanvas.toBlobがデータを返しませんでした",
              "viewer.export.error.variantsCombined": "シェアカードの種類は組み合わせられません",
              "viewer.export.error.viewerState": "シェアカードのエクスポートで一時的なビューアー状態を削除できませんでした",
              "viewer.export.error.routeState": "ルートカードのエクスポートで解決済みルートを安全に保持できませんでした",
              "viewer.export.error.reachState": "到達範囲カードのエクスポートで編集済み到達範囲を安全に保持できませんでした",
              "viewer.export.error.webmRequirements": "WebMモーションのエクスポートにはトレースアニメーションとブラウザのMediaRecorder対応が必要です",
              "viewer.export.error.mediaRecorder": "MediaRecorderが失敗しました",
              "viewer.export.error.emptyWebm": "MediaRecorderが空のWebMを生成しました",
              "viewer.export.error.webmBackground": "WebMエクスポート用のSVG背景を読み込めませんでした",
              "viewer.guide.eyebrow": "ダイアグラムガイド",
              "viewer.guide.close": "ダイアグラムガイドを閉じる",
              "viewer.guide.inspecting": "コンパイル済みセマンティクスを検査中",
              "viewer.guide.actions": "ダイアグラム探索アクション",
              "viewer.guide.find": "任意のノードを検索",
              "viewer.guide.find.hint": "ラベル、役割、種類、固定IDで検索します。",
              "viewer.guide.route": "ルートをトレース",
              "viewer.guide.route.aria": "有向ルートをトレース",
              "viewer.guide.route.hint": "2つのセマンティックノードが編集済みの方向でどう接続されているかを確認します。",
              "viewer.guide.map": "システム全体を表示",
              "viewer.guide.map.hint": "ライブビューポートと固定ノードを持つセマンティックレーダーを開きます。",
              "viewer.guide.lens": "セマンティックな種類を比較",
              "viewer.guide.lens.hint": "役割を数え、そのトラフィックを表示し、直接編集されたリンクを比較します。",
              "viewer.guide.present": "プレゼンテーションステージに入る",
              "viewer.guide.present.hint": "エクスポートを変更せずに、ライブダイアグラムにビューポート全体を割り当てます。",
              "viewer.guide.shortcuts": "その他のキーボードショートカット",
              "viewer.guide.shortcut.export": "エクスポート",
              "viewer.guide.shortcut.theme": "テーマ",
              "viewer.guide.shortcut.style": "スタイル",
              "viewer.guide.shortcut.reset": "リセット",
              "viewer.guide.shortcut.zoomIn": "拡大",
              "viewer.guide.shortcut.zoomOut": "縮小",
              "viewer.guide.shortcut.close": "閉じる",
              "viewer.guide.facts": "{nodes} · {relationships}",
              "viewer.guide.fact.node.one": "{count} 個のセマンティックノード",
              "viewer.guide.fact.node.other": "{count} 個のセマンティックノード",
              "viewer.guide.fact.relationship.one": "{count} 件の関係",
              "viewer.guide.fact.relationship.other": "{count} 件の関係",
              "viewer.guide.open": "ダイアグラムガイドを開く",
              "viewer.finder.title": "ノードを検索",
              "viewer.finder.close": "ノード検索を閉じる",
              "viewer.finder.placeholder": "ラベルまたはIDで検索",
              "viewer.finder.search": "ダイアグラムノードを検索",
              "viewer.finder.results": "ダイアグラムノード",
              "viewer.finder.empty": "一致するノードがありません",
              "viewer.finder.result.focus": "{label} にフォーカス",
              "viewer.finder.result.routeStart": "{label} をルートの起点として選択",
              "viewer.finder.result.routeTarget": "{label} をルートの終点として選択、{links}",
              "viewer.finder.status.empty": "一致するノードがありません",
              "viewer.finder.status.count.one": "一致するノード {count} 個",
              "viewer.finder.status.count.other": "一致するノード {count} 個",
              "viewer.finder.noun.nodes": "ノード",
              "viewer.finder.link.one": "{count} 件の接続",
              "viewer.finder.link.other": "{count} 件の接続",
              "viewer.finder.result.focus.one": "{label} にフォーカス、関連する接続 {count} 件",
              "viewer.finder.result.focus.other": "{label} にフォーカス、関連する接続 {count} 件",
              "viewer.finder.status.filtered": "{available} 件の{noun}中 {visible} 件",
              "viewer.finder.status.all": "{available} 件の{noun}",
              "viewer.passport.eyebrow": "セマンティックパスポート",
              "viewer.passport.metadata": "ノードメタデータ",
              "viewer.passport.evidence": "検証済みソースの根拠",
              "viewer.passport.verified": "検証済みソース",
              "viewer.passport.verificationScope": "固定されたリビジョン時点のローカルGitに対して検証済みです。リモートアクセスは確認していません。",
              "viewer.passport.reach": "編集済みの到達範囲",
              "viewer.passport.reach.trace": "編集済みの到達可能性をトレース",
              "viewer.passport.upstream": "アップストリーム",
              "viewer.passport.downstream": "ダウンストリーム",
              "viewer.passport.upstream.trace": "アップストリームの編集済み到達可能性をトレース",
              "viewer.passport.downstream.trace": "ダウンストリームの編集済み到達可能性をトレース",
              "viewer.passport.close": "セマンティックパスポートを閉じる",
              "viewer.passport.copy": "リンクをコピー",
              "viewer.passport.copy.focus": "フォーカス中のノードへのリンクをコピー",
              "viewer.passport.relations": "関係",
              "viewer.passport.relations.show": "関連する関係を表示",
              "viewer.passport.relations.hide": "関連する関係を非表示",
              "viewer.passport.relations.list": "関連する関係",
              "viewer.passport.copyRelation": "関係をコピー",
              "viewer.passport.copyNode": "ノードをコピー",
              "viewer.passport.copyPinned": "固定された関係へのリンクをコピー",
              "viewer.passport.copySource": "ソースノードへのリンクをコピー",
              "viewer.passport.copy.focused.success": "フォーカス中のノードのリンクをコピーしました",
              "viewer.passport.copy.pinned.success": "固定された関係のリンクをコピーしました",
              "viewer.passport.copy.focused.failed": "フォーカス中のノードのリンクをコピーできませんでした",
              "viewer.passport.copy.pinned.failed": "固定された関係のリンクをコピーできませんでした",
              "viewer.passport.relationship.none": "関連する関係がありません",
              "viewer.passport.relationship.count.one": "{count} 件の関係",
              "viewer.passport.relationship.count.other": "{count} 件の関係",
              "viewer.passport.relationship.show.one": "関連する関係 {count} 件を表示",
              "viewer.passport.relationship.show.other": "関連する関係 {count} 件を表示",
              "viewer.passport.relationship.summary": "出向 {out} · 入向 {in}{loops}",
              "viewer.passport.relationship.loops": " · 自己ループ {count} 件",
              "viewer.passport.relationship.explorer": "直接関係エクスプローラー",
              "viewer.passport.relationship.help": "矢印キーで関係を探索します。EnterまたはSpaceで詳細を固定し、Escapeで解除します。",
              "viewer.passport.relationship.loopsBack": "ループして戻る",
              "viewer.passport.relationship.connectsTo": "接続先",
              "viewer.passport.relationship.connectsFrom": "接続元",
              "viewer.passport.relationship.pinned": "固定された関係 · {from} → {to} · {label}",
              "viewer.passport.relationship.inspect": "第 {index}/{total} 件の関係を検査: {from} から {to} へ、{label}。詳細はEnterを押してください。",
              "viewer.passport.relationship.group.out": "出向",
              "viewer.passport.relationship.group.in": "入向",
              "viewer.passport.relationship.group.loop": "自己ループ",
              "viewer.passport.relationship.row": "{group}: {relationship}、{neighbor}",
              "viewer.passport.relationship.direction.out": "出 →",
              "viewer.passport.relationship.direction.in": "← 入",
              "viewer.passport.relationship.direction.loop": "ループ",
              "viewer.passport.sourceCount.one": "検証済みソース参照 {count} 件",
              "viewer.passport.sourceCount.other": "検証済みソース参照 {count} 件",
              "viewer.passport.sourceMarker": "出典",
              "viewer.passport.beacon.one": "検証済みソース {count} 件。このノードにフォーカスして確認",
              "viewer.passport.beacon.other": "検証済みソース {count} 件。このノードにフォーカスして確認",
              "viewer.passport.repository.open": "検証済みリポジトリのリビジョン {revision} を開く",
              "viewer.passport.source.open": "リビジョン {revision} の検証済みソース {path} を開く",
              "viewer.passport.source.openLink": "開く ↗",
              "viewer.passport.reach.upstream.one": "アップストリームの編集済みノード {count} 件をトレース",
              "viewer.passport.reach.upstream.other": "アップストリームの編集済みノード {count} 件をトレース",
              "viewer.passport.reach.downstream.one": "ダウンストリームの編集済みノード {count} 件をトレース",
              "viewer.passport.reach.downstream.other": "ダウンストリームの編集済みノード {count} 件をトレース",
              "viewer.passport.reach.noUpstream": "アップストリームの編集済みノードがありません",
              "viewer.passport.reach.noDownstream": "ダウンストリームの編集済みノードがありません",
              "viewer.passport.reach.status": "{direction} · ノード {nodes} 件 · 接続 {links} 件 · 最大 {hops} ホップ",
              "viewer.route.eyebrow": "ルートプローブ",
              "viewer.route.start": "開始ノードを選択",
              "viewer.route.start.find": "開始点を検索",
              "viewer.route.start.find.aria": "ルートの開始点を検索",
              "viewer.route.copy": "リンクをコピー",
              "viewer.route.copy.aria": "トレース済みルートへのリンクをコピー",
              "viewer.route.clear": "クリア",
              "viewer.route.clear.aria": "ルートプローブをクリア",
              "viewer.route.traced": "トレース済みルート",
              "viewer.route.pickTwo": "ダイアグラム上で2つのセマンティックノードを選択してください",
              "viewer.route.pickOne": "ダイアグラム上でセマンティックノードを1つ選択してください",
              "viewer.route.controls": "ルートジャーニーのコントロール",
              "viewer.route.previous": "前のルート位置",
              "viewer.route.play": "ルートジャーニーを再生",
              "viewer.route.pause": "ルートジャーニーを一時停止",
              "viewer.route.replay": "ルートジャーニーをリプレイ",
              "viewer.route.next": "次のルート位置",
              "viewer.route.journey": "ジャーニー",
              "viewer.route.pause.label": "一時停止",
              "viewer.route.replay.label": "リプレイ",
              "viewer.route.overview": "概要",
              "viewer.route.overview.aria": "ルート全体の概要を表示",
              "viewer.route.instructions": "起点を選択してから終点を選択してください。方向が重要です。",
              "viewer.route.destination": "{label} からの終点を選択",
              "viewer.route.destination.find": "終点を検索",
              "viewer.route.destination.find.aria": "到達可能なルートの終点を検索",
              "viewer.route.differentDestination": "別の終点を選択",
              "viewer.route.distinct": "ルートには2つの異なるセマンティックノードが必要です。",
              "viewer.route.unreachable": "{label} への有向ルートがありません",
              "viewer.route.unreachable.detail": "{source} から {target} には到達できません。ハイライトされた終点を選択してください。",
              "viewer.route.start.instructions": "起点を選択してください。次のステップでは有向の終点のみが表示されます。",
              "viewer.route.copy.success": "トレース済みルートのリンクをコピーしました",
              "viewer.route.copy.failed": "ルートのリンクをコピーできませんでした",
              "viewer.route.position": "ルート位置 {index}/{total}: {label}",
              "viewer.route.step": "ステップ {index}/{total} · {phase} · {label}",
              "viewer.route.motionRequired": "自動ジャーニーにはライブモーションが必要です",
              "viewer.route.trigger.clear": "トレース済みルートをクリア",
              "viewer.route.overview.status": "{nodes} · {hops} · 最短の編集済みルート",
              "viewer.route.overview.node.one": "{count} 個のノード",
              "viewer.route.overview.node.other": "{count} 個のノード",
              "viewer.route.overview.hop.one": "{count} 有向ホップ",
              "viewer.route.overview.hop.other": "{count} 有向ホップ",
              "viewer.route.phase.playing": "再生中",
              "viewer.route.phase.complete": "完了",
              "viewer.route.phase.inspecting": "検査中",
              "viewer.route.destination.count.one": "利用可能な有向終点 {count} 件。ハイライトされたノードを選択してください。",
              "viewer.route.destination.count.other": "利用可能な有向終点 {count} 件。ハイライトされたノードを選択してください。",
              "viewer.route.noOutgoing": "ここから始まる出向ルートはありません。クリアして別の起点を選択してください。",
              "viewer.route.result.title": "{source} から {target}",
              "viewer.route.finder.source.title": "ルートの開始点を選択",
              "viewer.route.finder.source.placeholder": "ルートの起点を検索",
              "viewer.route.finder.source.empty": "一致するルートの起点がありません",
              "viewer.route.finder.source.results": "ルートを開始できるノード",
              "viewer.route.finder.source.noun": "ルートの起点",
              "viewer.route.finder.source.badge": "起点",
              "viewer.route.finder.target.title": "{label} からの終点",
              "viewer.route.finder.target.placeholder": "到達可能な終点を検索",
              "viewer.route.finder.target.empty": "一致する到達可能な終点がありません",
              "viewer.route.finder.target.results": "到達可能なルートの終点",
              "viewer.route.finder.target.noun": "到達可能な終点",
              "viewer.route.hop.one": "{count} ホップ",
              "viewer.route.hop.other": "{count} ホップ",
              "viewer.lens.eyebrow": "セマンティックレンズ",
              "viewer.lens.title": "システムの役割を比較",
              "viewer.lens.close": "セマンティックレンズを閉じる",
              "viewer.lens.instruction": "セマンティックな種類を最大2つ選択してください。1つ選ぶと実際のトラフィックが表示され、2つ選ぶと直接の編集済み関係のみを比較します。",
              "viewer.lens.kinds": "セマンティックな種類",
              "viewer.lens.choose": "種類を選択すると、そのノードと接する関係を検査できます。",
              "viewer.lens.copy": "セマンティックレンズへのリンクをコピー",
              "viewer.lens.clear": "セマンティックレンズをクリア",
              "viewer.lens.open": "セマンティックレンズを開く",
              "viewer.lens.openActive": "アクティブなセマンティックレンズを開く",
              "viewer.lens.legend": "セマンティック凡例",
              "viewer.lens.legend.inspect.one": "{label} を検査、{count} 個のノード",
              "viewer.lens.legend.inspect.other": "{label} を検査、{count} 個のノード",
              "viewer.lens.kind.count.one": "{label}、{count} 個のノード",
              "viewer.lens.kind.count.other": "{label}、{count} 個のノード",
              "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 直接関係 {count} 件",
              "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 直接関係 {count} 件",
              "viewer.lens.single": "{nodes} · {relationships} · 接続された周辺ノードは表示されたままです",
              "viewer.lens.node.one": "{label} ノード {count} 個",
              "viewer.lens.node.other": "{label} ノード {count} 個",
              "viewer.lens.relationship.one": "接する関係 {count} 件",
              "viewer.lens.relationship.other": "接する関係 {count} 件",
              "viewer.radar.title": "セマンティックレーダー",
              "viewer.radar.building": "概要を構築中",
              "viewer.radar.openFull": "完全なセマンティックレーダーを開く",
              "viewer.radar.open": "レーダーを開く",
              "viewer.radar.close": "セマンティックレーダーを閉じる",
              "viewer.radar.surface": "ダイアグラムの概要です。ノードをクリックしてフォーカスするか、矢印キーでパンできます。",
              "viewer.radar.click": "ノードをクリック",
              "viewer.radar.drag": "ドラッグしてパン",
              "viewer.radar.space": "セマンティックレーダーにはさらにMAPスペースが必要です。",
              "viewer.radar.nodes": "セマンティックダイアグラムのレーダーノード",
              "viewer.radar.focus": "セマンティックレーダーから {label} にフォーカス",
              "viewer.radar.status": "{count} 個のノード · {viewport}",
              "viewer.radar.fullMap": "{count} 個のノード · 全体マップ",
              "viewer.radar.compacted": "セマンティックパスポートやMAPコントロールを覆わないよう、レーダーを縮小しました。",
              "viewer.radar.cancelWaiting": "MAPスペースの確保待ちのセマンティックレーダーをキャンセル",
              "viewer.radar.needsSpace": "セマンティックレーダーには表示可能なMAPスペースがさらに必要です",
              "viewer.radar.viewport.full": "全体マップ",
              "viewer.radar.viewport.width": "幅 {percent}%",
              "viewer.radar.viewport.scale": "ビューポート {percent}%",
              "viewer.nav.controls": "ダイアグラム表示コントロール",
              "viewer.nav.route": "有向ルートをトレース",
              "viewer.nav.route.title": "ルートをトレース (R)",
              "viewer.nav.route.short": "パス",
              "viewer.nav.radar": "セマンティックレーダーを開く",
              "viewer.nav.radar.title": "セマンティックレーダー (M)",
              "viewer.nav.radar.short": "マップ",
              "viewer.nav.lens": "セマンティックレンズを開く",
              "viewer.nav.lens.title": "セマンティックレンズ (L)",
              "viewer.nav.lens.short": "レンズ",
              "viewer.nav.find": "ノードを検索",
              "viewer.nav.find.title": "ノードを検索 (/)",
              "viewer.nav.guide": "ダイアグラムガイドを開く",
              "viewer.nav.guide.title": "ダイアグラムガイド (?)",
              "viewer.nav.zoomOut": "縮小",
              "viewer.nav.zoomOut.title": "縮小 (-)",
              "viewer.nav.reset": "ダイアグラム表示をリセット",
              "viewer.nav.reset.title": "表示をリセット (0)",
              "viewer.nav.read": "閲覧",
              "viewer.nav.zoomIn": "拡大",
              "viewer.nav.zoomIn.title": "拡大 (+)",
              "viewer.nav.camera": "{hint}。ダイアグラム表示をリセット",
              "viewer.nav.camera.title": "{semantic}{hint} · 表示をリセット (0)",
              "viewer.nav.camera.semantic": "セマンティックカメラ有効 · ",
              "viewer.nav.level.map": "マップ",
              "viewer.nav.level.read": "閲覧",
              "viewer.nav.level.full": "全体",
              "viewer.nav.level.auto": "自動",
              "viewer.nav.detail.map": "拡大すると関係ラベルとノードのコンテキストが表示されます",
              "viewer.nav.detail.read": "さらに拡大するとタグと注釈が表示されます",
              "viewer.nav.detail.full": "ダイアグラムの完全な詳細",
              "viewer.intent.summary": "{label}。出向 {out} 件、入向 {in} 件{loops}。合計 {total} 件の接続。詳細はEnterを押してください。",
              "viewer.intent.loops": "、自己ループ {count} 件",
              "viewer.common.copied": "コピーしました",
              "viewer.common.copyFailed": "コピーに失敗しました",
              "viewer.common.copyLink": "リンクをコピー",
              "viewer.common.clear": "クリア",
              "viewer.common.close": "閉じる"
            },
            "output": "japanese-locale.html",
            "quality_profile": "showcase",
            "views": [
              {
                "id": "request-path",
                "label": "基本リクエスト経路",
                "focus": [
                  "users",
                  "cdn",
                  "lb",
                  "api",
                  "db"
                ],
                "note": "エッジからストレージまで顧客リクエストをたどります。"
              },
              {
                "id": "identity-and-cache",
                "label": "認証とキャッシュ",
                "focus": [
                  "auth",
                  "api",
                  "cache"
                ],
                "note": "認証と読み取りキャッシュをリクエスト経路の隣に分離します。"
              },
              {
                "id": "async-work",
                "label": "静的・非同期処理",
                "focus": [
                  "cdn",
                  "s3",
                  "api",
                  "queue",
                  "worker"
                ],
                "note": "付随する2つの経路を本経路と重ならないように示します。"
              }
            ]
          },
          "components": [
            {
              "id": "users",
              "type": "external",
              "label": "ユーザー",
              "sublabel": "ブラウザ / モバイル",
              "pos": [
                40,
                300
              ],
              "size": [
                120,
                60
              ]
            },
            {
              "id": "auth",
              "type": "security",
              "label": "認証プロバイダー",
              "sublabel": "OAuth 2.0",
              "pos": [
                40,
                110
              ],
              "size": [
                120,
                64
              ],
              "tag": "JWT + PKCE"
            },
            {
              "id": "cdn",
              "type": "cloud",
              "label": "CloudFront",
              "sublabel": "CDN",
              "pos": [
                250,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "lb",
              "type": "cloud",
              "label": "ロードバランサー",
              "sublabel": "HTTPS :443",
              "pos": [
                460,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "api",
              "type": "backend",
              "label": "APIサーバー",
              "sublabel": "FastAPI :8000",
              "pos": [
                670,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "cache",
              "type": "database",
              "label": "Redis",
              "sublabel": "cache :6379",
              "pos": [
                670,
                150
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "db",
              "type": "database",
              "label": "PostgreSQL",
              "sublabel": "primary :5432",
              "pos": [
                880,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "s3",
              "type": "cloud",
              "label": "S3",
              "sublabel": "静的アセット",
              "pos": [
                250,
                440
              ],
              "size": [
                130,
                60
              ],
              "tag": "OAI protected"
            },
            {
              "id": "queue",
              "type": "messagebus",
              "label": "SQS",
              "sublabel": "ジョブキュー",
              "pos": [
                670,
                440
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "worker",
              "type": "backend",
              "label": "ワーカー",
              "sublabel": "非同期処理",
              "pos": [
                880,
                440
              ],
              "size": [
                130,
                60
              ]
            }
          ],
          "boundaries": [
            {
              "kind": "region",
              "label": "AWSリージョン: us-west-2",
              "wraps": [
                "cdn",
                "lb",
                "api",
                "cache",
                "db",
                "s3",
                "queue",
                "worker"
              ]
            },
            {
              "kind": "security-group",
              "label": "sg-api :443/:8000",
              "wraps": [
                "lb",
                "api"
              ]
            }
          ],
          "connections": [
            {
              "id": "users-to-cdn",
              "from": "users",
              "to": "cdn",
              "label": "HTTPS",
              "variant": "emphasis"
            },
            {
              "id": "jwt-verification",
              "from": "auth",
              "to": "api",
              "label": "JWT検証",
              "variant": "security",
              "fromSide": "right",
              "toSide": "top",
              "via": [
                [
                  620,
                  142
                ],
                [
                  620,
                  246
                ],
                [
                  735,
                  246
                ]
              ]
            },
            {
              "id": "cdn-to-lb",
              "from": "cdn",
              "to": "lb"
            },
            {
              "id": "static-assets",
              "from": "cdn",
              "to": "s3",
              "label": "静的",
              "variant": "dashed",
              "fromSide": "bottom",
              "toSide": "top",
              "labelDy": 58
            },
            {
              "id": "lb-to-api",
              "from": "lb",
              "to": "api"
            },
            {
              "id": "cache-read-through",
              "from": "api",
              "to": "cache",
              "label": "read-through",
              "fromSide": "top",
              "toSide": "bottom",
              "labelDy": -68
            },
            {
              "id": "api-sql",
              "from": "api",
              "to": "db",
              "label": "SQL"
            },
            {
              "id": "enqueue-job",
              "from": "api",
              "to": "queue",
              "label": "enqueue",
              "variant": "dashed",
              "fromSide": "bottom",
              "toSide": "top",
              "labelDy": 58
            },
            {
              "id": "queue-to-worker",
              "from": "queue",
              "to": "worker"
            }
          ],
          "cards": [
            {
              "dot": "cyan",
              "title": "エッジ",
              "items": [
                "CloudFront CDNがトラフィックを受信",
                "S3がOAIで静的アセットを提供"
              ]
            },
            {
              "dot": "emerald",
              "title": "アプリケーション",
              "items": [
                "HTTPSロードバランサー配下のFastAPI",
                "Redis読み取りキャッシュ",
                "SQSでワーカーが非同期処理を実行"
              ]
            },
            {
              "dot": "rose",
              "title": "セキュリティ",
              "items": [
                "JWT + PKCEを用いたOAuth 2.0",
                "APIとLBをセキュリティグループで隔離"
              ]
            }
          ]
        }
        
      • korean-locale.architecture.json 35.3 KB
        {
          "schema_version": 1,
          "diagram_type": "architecture",
          "meta": {
            "title": "한국어 웹앱",
            "subtitle": "로케일 검증용 고정 입력",
            "locale": "ko",
            "translations": {
              "page.title": "{title} 다이어그램",
              "diagram.description.architecture": "Archify로 생성한 아키텍처 다이어그램입니다.",
              "diagram.description.workflow": "Archify로 생성한 워크플로우 다이어그램입니다.",
              "diagram.description.sequence": "Archify로 생성한 시퀀스 다이어그램입니다.",
              "diagram.description.dataflow": "Archify로 생성한 데이터플로우 다이어그램입니다.",
              "diagram.description.lifecycle": "Archify로 생성한 라이프사이클 다이어그램입니다.",
              "node.focus": "{label} 포커스",
              "node.focus.detail": "{label} 포커스, {detail}",
              "node.context.architecture": "아키텍처 구성요소",
              "node.context.workflow": "워크플로우 노드",
              "node.context.sequence": "시퀀스 참가자",
              "node.context.dataflow": "데이터플로우 노드",
              "node.context.lifecycle": "라이프사이클 상태",
              "legend.title": "범례",
              "legend.architecture.frontend": "프런트엔드",
              "legend.architecture.backend": "백엔드",
              "legend.architecture.database": "데이터베이스",
              "legend.architecture.cloud": "클라우드",
              "legend.architecture.security": "보안",
              "legend.architecture.messagebus": "메시지 버스",
              "legend.architecture.external": "외부",
              "legend.workflow.frontend": "사용자 UI",
              "legend.workflow.backend": "Agent 로직",
              "legend.workflow.security": "정책",
              "legend.workflow.messagebus": "도구 실행",
              "legend.workflow.database": "컨텍스트 / 추적",
              "legend.workflow.cloud": "클라우드 서비스",
              "legend.workflow.external": "외부 시스템",
              "legend.sequence.emphasis": "요청",
              "legend.sequence.return": "반환",
              "legend.sequence.security": "보안",
              "legend.sequence.dashed": "비동기 추적",
              "legend.sequence.default": "기본 메시지",
              "legend.dataflow.emphasis": "주요 데이터",
              "legend.dataflow.security": "정책 / PII",
              "legend.dataflow.dashed": "비동기 배치",
              "legend.dataflow.database": "데이터 저장소",
              "legend.dataflow.default": "데이터 흐름",
              "legend.lifecycle.start": "시작",
              "legend.lifecycle.active": "활성 상태",
              "legend.lifecycle.waiting": "대기",
              "legend.lifecycle.decision": "판단",
              "legend.lifecycle.success": "성공 종료",
              "legend.lifecycle.failure": "실패 / 종료",
              "legend.lifecycle.neutral": "중립 상태",
              "legend.lifecycle.external": "외부 상태",
              "viewer.kind.frontend": "프런트엔드",
              "viewer.kind.backend": "백엔드",
              "viewer.kind.database": "데이터베이스",
              "viewer.kind.cloud": "클라우드",
              "viewer.kind.security": "보안",
              "viewer.kind.messagebus": "메시지 버스",
              "viewer.kind.external": "외부",
              "viewer.kind.neutral": "중립",
              "viewer.kind.node": "노드",
              "viewer.kind.start": "시작",
              "viewer.kind.active": "활성",
              "viewer.kind.waiting": "대기",
              "viewer.kind.decision": "판단",
              "viewer.kind.success": "성공",
              "viewer.kind.failure": "실패",
              "viewer.toolbar.actions": "다이어그램 동작",
              "viewer.theme.toggle.title": "테마 전환 (T)",
              "viewer.theme.toggle": "색상 테마 전환",
              "viewer.theme.dark": "다크",
              "viewer.theme.light": "라이트",
              "viewer.preset.choose.title": "시각 스타일 선택 (S로 순환)",
              "viewer.preset.choose": "시각 스타일 선택",
              "viewer.preset.style": "스타일",
              "viewer.preset.menu": "시각 스타일",
              "viewer.preset.identity": "시각적 정체성",
              "viewer.preset.cycles": "S로 순환",
              "viewer.preset.classic": "클래식",
              "viewer.preset.classic.short": "클래식",
              "viewer.preset.classic.hint": "안정적인 기술 기본 스타일",
              "viewer.preset.flow": "시그널 플로우",
              "viewer.preset.flow.short": "플로우",
              "viewer.preset.flow.hint": "동적 흐름을 강조하는 프레젠테이션",
              "viewer.preset.blueprint": "블루프린트",
              "viewer.preset.blueprint.hint": "엔지니어링 리뷰용",
              "viewer.preset.editorial": "에디토리얼",
              "viewer.preset.editorial.hint": "발행 및 출시 노트에 적합",
              "viewer.preset.badge.signalFlow": "시그널 플로우",
              "viewer.preset.badge.blueprint": "블루프린트 / 개정 01",
              "viewer.preset.badge.editorial": "에디토리얼 / 현장 노트",
              "viewer.preset.badge.editorialPlate": "ARCHIFY / 도판 04",
              "viewer.preset.current": "현재 시각 스타일: {style}. 시각 스타일 선택",
              "viewer.motion.live": "동적",
              "viewer.motion.still": "정적",
              "viewer.motion.pause": "동작 일시정지",
              "viewer.motion.resume": "동작 재개",
              "viewer.motion.reduced": "동작 최소화 설정으로 인해 동작이 일시정지되었습니다",
              "viewer.motion.hidden": "페이지가 보이지 않는 동안 동작이 일시정지되었습니다",
              "viewer.motion.yielding": "동작 일시정지; 현재 {owner}에 양보 중",
              "viewer.motion.yielding.title": "실시간 미리보기 활성화 · {owner}에 양보 중",
              "viewer.owner.route": "경로 탐색",
              "viewer.owner.lens": "시맨틱 렌즈",
              "viewer.owner.relationship": "관계 미리보기",
              "viewer.owner.intent": "의도 추적",
              "viewer.owner.focus": "시맨틱 포커스",
              "viewer.owner.legend": "범례 미리보기",
              "viewer.owner.reader": "읽는 이의 상호작용",
              "viewer.present.enter": "프레젠테이션 모드 진입",
              "viewer.present.enter.title": "프레젠테이션 모드 (F)",
              "viewer.present.exit": "프레젠테이션 모드 종료",
              "viewer.present.exit.title": "프레젠테이션 모드 종료 (F 또는 Escape)",
              "viewer.present.present": "프레젠테이션",
              "viewer.present.exit.label": "종료",
              "viewer.export.button": "내보내기",
              "viewer.export.button.title": "다이어그램 내보내기 (E)",
              "viewer.export.diagram": "다이어그램 내보내기",
              "viewer.export.menu": "내보내기",
              "viewer.export.subtitle": "가볍고 깔끔한 출력물",
              "viewer.export.share": "공유",
              "viewer.export.shareCard": "공유 카드",
              "viewer.export.routeShareCard": "경로 공유 카드",
              "viewer.export.reachShareCard": "도달범위 공유 카드",
              "viewer.export.copyDiagram": "다이어그램 복사",
              "viewer.export.clipboardPng": "PNG를 클립보드로",
              "viewer.export.raster": "래스터 이미지",
              "viewer.export.image": "이미지",
              "viewer.export.lossless": "무손실 이미지",
              "viewer.export.compact": "압축 이미지",
              "viewer.export.modern": "최신 이미지 포맷",
              "viewer.export.vectorMotion": "벡터 및 동작",
              "viewer.export.vectorMotion.heading": "벡터 및 동작",
              "viewer.export.editable": "편집 가능한 벡터",
              "viewer.export.motion6s": "6초 동작",
              "viewer.export.unsupported": "이 브라우저에서 지원하지 않습니다",
              "viewer.export.clipboardUnsupported": "이 브라우저는 이미지 클립보드 쓰기를 지원하지 않습니다",
              "viewer.export.clipboardUnsupported.short": "이 브라우저는 이미지 클립보드 쓰기를 지원하지 않습니다.",
              "viewer.export.motionUnavailable": "이 브라우저에서는 동작을 캡처할 수 없습니다",
              "viewer.export.webmUnavailable": "이 브라우저에서는 WebM을 사용할 수 없습니다",
              "viewer.export.failed": "내보내기 실패: {message}",
              "viewer.export.unknownVariant": "알 수 없는 공유 카드 유형: {variant}",
              "viewer.export.routeRequired": "경로 공유 카드를 내보내려면 먼저 경로를 추적하세요",
              "viewer.export.reachRequired": "도달범위 공유 카드를 내보내려면 먼저 편집된 도달범위를 추적하세요",
              "viewer.export.unknown": "알 수 없음",
              "viewer.export.routeFailed": "경로 공유 카드 내보내기 실패: {message}",
              "viewer.export.reachFailed": "도달범위 공유 카드 내보내기 실패: {message}",
              "viewer.export.copyFailed": "복사 실패: {message}",
              "viewer.export.copiedPng": "PNG를 클립보드에 복사했습니다",
              "viewer.export.downloadedRoute": "경로 공유 카드를 다운로드했습니다",
              "viewer.export.downloadedReach": "도달범위 공유 카드를 다운로드했습니다",
              "viewer.export.downloadedWebm": "WebM을 다운로드했습니다",
              "viewer.export.recording": "6초 분량 동작을 녹화 중…",
              "viewer.export.card.routeSummary.one": "경로: {source} → {target} · 방향성 홉 {count}개",
              "viewer.export.card.routeSummary.other": "경로: {source} → {target} · 방향성 홉 {count}개",
              "viewer.export.card.reachSummary": "{origin}에서 시작한 편집된 {direction} · {nodes} · {links} · 최대 {hops}",
              "viewer.export.card.node.one": "노드 {count}개",
              "viewer.export.card.node.other": "노드 {count}개",
              "viewer.export.card.link.one": "연결 {count}개",
              "viewer.export.card.link.other": "연결 {count}개",
              "viewer.export.card.hop.one": "홉 {count}개",
              "viewer.export.card.hop.other": "홉 {count}개",
              "viewer.export.card.routeBadge": "ARCHIFY · 경로 · {hops}",
              "viewer.export.card.reachBadge": "ARCHIFY · {direction} 도달범위",
              "viewer.export.direction.upstream": "업스트림",
              "viewer.export.direction.downstream": "다운스트림",
              "viewer.export.error.canvasUnavailable": "{label}에 캔버스를 사용할 수 없습니다",
              "viewer.export.error.contextUnavailable": "{label}에 2D 캔버스 컨텍스트를 만들 수 없습니다",
              "viewer.export.error.toBlobUnavailable": "{label}에서 canvas.toBlob을 사용할 수 없습니다",
              "viewer.export.error.toBlobNull": "{label}의 canvas.toBlob이 데이터를 반환하지 않았습니다",
              "viewer.export.error.variantsCombined": "공유 카드 유형을 함께 조합할 수 없습니다",
              "viewer.export.error.viewerState": "공유 카드 내보내기가 임시 뷰어 상태를 제거하지 못했습니다",
              "viewer.export.error.routeState": "경로 카드 내보내기가 해석된 경로를 안전하게 보존하지 못했습니다",
              "viewer.export.error.reachState": "도달범위 카드 내보내기가 편집된 도달범위를 안전하게 보존하지 못했습니다",
              "viewer.export.error.webmRequirements": "WebM 동작 내보내기는 추적 애니메이션과 브라우저의 MediaRecorder 지원이 필요합니다",
              "viewer.export.error.mediaRecorder": "MediaRecorder 실패",
              "viewer.export.error.emptyWebm": "MediaRecorder가 빈 WebM을 생성했습니다",
              "viewer.export.error.webmBackground": "WebM 내보내기용 SVG 배경을 불러오지 못했습니다",
              "viewer.guide.eyebrow": "다이어그램 가이드",
              "viewer.guide.close": "다이어그램 가이드 닫기",
              "viewer.guide.inspecting": "컴파일된 시맨틱 구조 검사 중",
              "viewer.guide.actions": "다이어그램 탐색 동작",
              "viewer.guide.find": "아무 노드나 찾기",
              "viewer.guide.find.hint": "라벨, 역할, 유형, 고정 ID로 검색합니다.",
              "viewer.guide.route": "경로 추적",
              "viewer.guide.route.aria": "방향성 경로 추적",
              "viewer.guide.route.hint": "두 시맨틱 노드가 편집된 방향으로 어떻게 연결되는지 확인합니다.",
              "viewer.guide.map": "전체 시스템 보기",
              "viewer.guide.map.hint": "실시간 뷰포트와 고정 노드가 있는 시맨틱 레이더를 엽니다.",
              "viewer.guide.lens": "시맨틱 유형 비교",
              "viewer.guide.lens.hint": "역할 수를 세고, 트래픽을 표시하고, 직접 편집된 연결을 비교합니다.",
              "viewer.guide.present": "프레젠테이션 모드 진입",
              "viewer.guide.present.hint": "내보내기는 그대로 두고 실시간 다이어그램에 뷰포트 전체를 할애합니다.",
              "viewer.guide.shortcuts": "추가 키보드 단축키",
              "viewer.guide.shortcut.export": "내보내기",
              "viewer.guide.shortcut.theme": "테마",
              "viewer.guide.shortcut.style": "스타일",
              "viewer.guide.shortcut.reset": "초기화",
              "viewer.guide.shortcut.zoomIn": "확대",
              "viewer.guide.shortcut.zoomOut": "축소",
              "viewer.guide.shortcut.close": "닫기",
              "viewer.guide.facts": "{nodes} · {relationships}",
              "viewer.guide.fact.node.one": "시맨틱 노드 {count}개",
              "viewer.guide.fact.node.other": "시맨틱 노드 {count}개",
              "viewer.guide.fact.relationship.one": "관계 {count}개",
              "viewer.guide.fact.relationship.other": "관계 {count}개",
              "viewer.guide.open": "다이어그램 가이드 열기",
              "viewer.finder.title": "노드 찾기",
              "viewer.finder.close": "노드 찾기 닫기",
              "viewer.finder.placeholder": "라벨 또는 ID로 검색",
              "viewer.finder.search": "다이어그램 노드 검색",
              "viewer.finder.results": "다이어그램 노드",
              "viewer.finder.empty": "일치하는 노드가 없습니다",
              "viewer.finder.result.focus": "{label} 포커스",
              "viewer.finder.result.routeStart": "{label}을(를) 경로 시작점으로 선택",
              "viewer.finder.result.routeTarget": "{label}을(를) 경로 도착점으로 선택, {links}",
              "viewer.finder.status.empty": "일치하는 노드가 없습니다",
              "viewer.finder.status.count.one": "일치하는 노드 {count}개",
              "viewer.finder.status.count.other": "일치하는 노드 {count}개",
              "viewer.finder.noun.nodes": "노드",
              "viewer.finder.link.one": "연결 {count}개",
              "viewer.finder.link.other": "연결 {count}개",
              "viewer.finder.result.focus.one": "{label} 포커스, 관련 연결 {count}개",
              "viewer.finder.result.focus.other": "{label} 포커스, 관련 연결 {count}개",
              "viewer.finder.status.filtered": "{noun} {available}개 중 {visible}개",
              "viewer.finder.status.all": "{noun} {available}개",
              "viewer.passport.eyebrow": "시맨틱 패스포트",
              "viewer.passport.metadata": "노드 메타데이터",
              "viewer.passport.evidence": "검증된 소스 근거",
              "viewer.passport.verified": "검증된 소스",
              "viewer.passport.verificationScope": "고정된 리비전 기준 로컬 Git으로 검증했습니다. 원격 접근 권한은 확인하지 않았습니다.",
              "viewer.passport.reach": "편집된 도달범위",
              "viewer.passport.reach.trace": "편집된 도달가능성 추적",
              "viewer.passport.upstream": "업스트림",
              "viewer.passport.downstream": "다운스트림",
              "viewer.passport.upstream.trace": "업스트림 편집 도달가능성 추적",
              "viewer.passport.downstream.trace": "다운스트림 편집 도달가능성 추적",
              "viewer.passport.close": "시맨틱 패스포트 닫기",
              "viewer.passport.copy": "링크 복사",
              "viewer.passport.copy.focus": "포커스된 노드의 링크 복사",
              "viewer.passport.relations": "관계",
              "viewer.passport.relations.show": "연결된 관계 표시",
              "viewer.passport.relations.hide": "연결된 관계 숨기기",
              "viewer.passport.relations.list": "연결된 관계",
              "viewer.passport.copyRelation": "관계 복사",
              "viewer.passport.copyNode": "노드 복사",
              "viewer.passport.copyPinned": "고정된 관계의 링크 복사",
              "viewer.passport.copySource": "소스 노드의 링크 복사",
              "viewer.passport.copy.focused.success": "포커스된 노드 링크를 복사했습니다",
              "viewer.passport.copy.pinned.success": "고정된 관계 링크를 복사했습니다",
              "viewer.passport.copy.focused.failed": "포커스된 노드 링크를 복사할 수 없습니다",
              "viewer.passport.copy.pinned.failed": "고정된 관계 링크를 복사할 수 없습니다",
              "viewer.passport.relationship.none": "연결된 관계가 없습니다",
              "viewer.passport.relationship.count.one": "관계 {count}개",
              "viewer.passport.relationship.count.other": "관계 {count}개",
              "viewer.passport.relationship.show.one": "연결된 관계 {count}개 표시",
              "viewer.passport.relationship.show.other": "연결된 관계 {count}개 표시",
              "viewer.passport.relationship.summary": "출향 {out}개 · 입향 {in}개{loops}",
              "viewer.passport.relationship.loops": " · 자기순환 {count}개",
              "viewer.passport.relationship.explorer": "직접 관계 탐색기",
              "viewer.passport.relationship.help": "방향키로 관계를 탐색하세요. Enter 또는 Space로 상세정보를 고정하고, Escape로 지웁니다.",
              "viewer.passport.relationship.loopsBack": "되돌아옴",
              "viewer.passport.relationship.connectsTo": "연결 대상",
              "viewer.passport.relationship.connectsFrom": "연결 출처",
              "viewer.passport.relationship.pinned": "고정된 관계 · {from} → {to} · {label}",
              "viewer.passport.relationship.inspect": "{total}개 중 {index}번 관계 검사: {from}에서 {to}로, {label}. Enter로 상세정보 확인.",
              "viewer.passport.relationship.group.out": "출향",
              "viewer.passport.relationship.group.in": "입향",
              "viewer.passport.relationship.group.loop": "자기순환",
              "viewer.passport.relationship.row": "{group}: {relationship}, {neighbor}",
              "viewer.passport.relationship.direction.out": "출 →",
              "viewer.passport.relationship.direction.in": "← 입",
              "viewer.passport.relationship.direction.loop": "순환",
              "viewer.passport.sourceCount.one": "검증된 소스 참조 {count}개",
              "viewer.passport.sourceCount.other": "검증된 소스 참조 {count}개",
              "viewer.passport.sourceMarker": "출처",
              "viewer.passport.beacon.one": "검증된 소스 {count}개; 이 노드를 포커스하여 확인",
              "viewer.passport.beacon.other": "검증된 소스 {count}개; 이 노드를 포커스하여 확인",
              "viewer.passport.repository.open": "검증된 저장소 리비전 {revision} 열기",
              "viewer.passport.source.open": "리비전 {revision}의 검증된 소스 {path} 열기",
              "viewer.passport.source.openLink": "열기 ↗",
              "viewer.passport.reach.upstream.one": "업스트림 편집 노드 {count}개 추적",
              "viewer.passport.reach.upstream.other": "업스트림 편집 노드 {count}개 추적",
              "viewer.passport.reach.downstream.one": "다운스트림 편집 노드 {count}개 추적",
              "viewer.passport.reach.downstream.other": "다운스트림 편집 노드 {count}개 추적",
              "viewer.passport.reach.noUpstream": "업스트림 편집 노드가 없습니다",
              "viewer.passport.reach.noDownstream": "다운스트림 편집 노드가 없습니다",
              "viewer.passport.reach.status": "{direction} · 노드 {nodes}개 · 연결 {links}개 · 최대 {hops}홉",
              "viewer.route.eyebrow": "경로 탐색",
              "viewer.route.start": "시작 노드 선택",
              "viewer.route.start.find": "시작점 찾기",
              "viewer.route.start.find.aria": "경로 시작점 찾기",
              "viewer.route.copy": "링크 복사",
              "viewer.route.copy.aria": "추적된 경로의 링크 복사",
              "viewer.route.clear": "지우기",
              "viewer.route.clear.aria": "경로 탐색 지우기",
              "viewer.route.traced": "추적된 경로",
              "viewer.route.pickTwo": "다이어그램에서 시맨틱 노드 두 개를 선택하세요",
              "viewer.route.pickOne": "다이어그램에서 시맨틱 노드 하나를 선택하세요",
              "viewer.route.controls": "경로 이동 제어",
              "viewer.route.previous": "이전 경로 위치",
              "viewer.route.play": "경로 이동 재생",
              "viewer.route.pause": "경로 이동 일시정지",
              "viewer.route.replay": "경로 이동 다시 재생",
              "viewer.route.next": "다음 경로 위치",
              "viewer.route.journey": "이동 경로",
              "viewer.route.pause.label": "일시정지",
              "viewer.route.replay.label": "다시 재생",
              "viewer.route.overview": "개요",
              "viewer.route.overview.aria": "전체 경로 개요 표시",
              "viewer.route.instructions": "출발지를 먼저 선택한 뒤 도착지를 선택하세요. 방향이 중요합니다.",
              "viewer.route.destination": "{label}에서 출발할 도착지 선택",
              "viewer.route.destination.find": "도착지 찾기",
              "viewer.route.destination.find.aria": "도달 가능한 경로 도착지 찾기",
              "viewer.route.differentDestination": "다른 도착지 선택",
              "viewer.route.distinct": "경로에는 서로 다른 시맨틱 노드 두 개가 필요합니다.",
              "viewer.route.unreachable": "{label}(으)로 가는 방향성 경로가 없습니다",
              "viewer.route.unreachable.detail": "{source}에서 {target}에 도달할 수 없습니다. 강조 표시된 도착지를 선택하세요.",
              "viewer.route.start.instructions": "출발지를 선택하세요. 다음 단계에서는 방향성으로 도달 가능한 도착지만 표시됩니다.",
              "viewer.route.copy.success": "추적된 경로 링크를 복사했습니다",
              "viewer.route.copy.failed": "경로 링크를 복사할 수 없습니다",
              "viewer.route.position": "경로 위치 {total}개 중 {index}번: {label}",
              "viewer.route.step": "{total}단계 중 {index}단계 · {phase} · {label}",
              "viewer.route.motionRequired": "자동 이동에는 동적 모드가 필요합니다",
              "viewer.route.trigger.clear": "추적된 경로 지우기",
              "viewer.route.overview.status": "{nodes} · {hops} · 최단 편집 경로",
              "viewer.route.overview.node.one": "노드 {count}개",
              "viewer.route.overview.node.other": "노드 {count}개",
              "viewer.route.overview.hop.one": "방향성 홉 {count}개",
              "viewer.route.overview.hop.other": "방향성 홉 {count}개",
              "viewer.route.phase.playing": "재생 중",
              "viewer.route.phase.complete": "완료됨",
              "viewer.route.phase.inspecting": "검사 중",
              "viewer.route.destination.count.one": "방향성 도착지 {count}개 사용 가능. 강조 표시된 노드를 선택하세요.",
              "viewer.route.destination.count.other": "방향성 도착지 {count}개 사용 가능. 강조 표시된 노드를 선택하세요.",
              "viewer.route.noOutgoing": "여기서 시작하는 출향 경로가 없습니다. 지우고 다른 출발지를 선택하세요.",
              "viewer.route.result.title": "{source}에서 {target}까지",
              "viewer.route.finder.source.title": "경로 시작점 선택",
              "viewer.route.finder.source.placeholder": "경로 출발지 검색",
              "viewer.route.finder.source.empty": "일치하는 경로 출발지가 없습니다",
              "viewer.route.finder.source.results": "경로를 시작할 수 있는 노드",
              "viewer.route.finder.source.noun": "경로 출발지",
              "viewer.route.finder.source.badge": "시작",
              "viewer.route.finder.target.title": "{label}에서 출발할 도착지",
              "viewer.route.finder.target.placeholder": "도달 가능한 도착지 검색",
              "viewer.route.finder.target.empty": "일치하는 도달 가능한 도착지가 없습니다",
              "viewer.route.finder.target.results": "도달 가능한 경로 도착지",
              "viewer.route.finder.target.noun": "도달 가능한 도착지",
              "viewer.route.hop.one": "홉 {count}개",
              "viewer.route.hop.other": "홉 {count}개",
              "viewer.lens.eyebrow": "시맨틱 렌즈",
              "viewer.lens.title": "시스템 역할 비교",
              "viewer.lens.close": "시맨틱 렌즈 닫기",
              "viewer.lens.instruction": "시맨틱 유형을 최대 두 개까지 선택하세요. 하나를 선택하면 실제 트래픽을 표시하고, 두 개를 선택하면 직접 편집된 관계만 비교합니다.",
              "viewer.lens.kinds": "시맨틱 유형",
              "viewer.lens.choose": "유형을 선택해 해당 노드와 연결된 관계를 확인하세요.",
              "viewer.lens.copy": "시맨틱 렌즈 링크 복사",
              "viewer.lens.clear": "시맨틱 렌즈 지우기",
              "viewer.lens.open": "시맨틱 렌즈 열기",
              "viewer.lens.openActive": "활성 시맨틱 렌즈 열기",
              "viewer.lens.legend": "시맨틱 범례",
              "viewer.lens.legend.inspect.one": "{label} 검사, 노드 {count}개",
              "viewer.lens.legend.inspect.other": "{label} 검사, 노드 {count}개",
              "viewer.lens.kind.count.one": "{label}, 노드 {count}개",
              "viewer.lens.kind.count.other": "{label}, 노드 {count}개",
              "viewer.lens.compare.one": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 직접 관계 {count}개",
              "viewer.lens.compare.other": "{first} → {second}: {forward} · {second} → {first}: {reverse} · 직접 관계 {count}개",
              "viewer.lens.single": "{nodes} · {relationships} · 연결된 주변 노드는 계속 표시됩니다",
              "viewer.lens.node.one": "{label} 노드 {count}개",
              "viewer.lens.node.other": "{label} 노드 {count}개",
              "viewer.lens.relationship.one": "연결된 관계 {count}개",
              "viewer.lens.relationship.other": "연결된 관계 {count}개",
              "viewer.radar.title": "시맨틱 레이더",
              "viewer.radar.building": "개요 구성 중",
              "viewer.radar.openFull": "전체 시맨틱 레이더 열기",
              "viewer.radar.open": "레이더 열기",
              "viewer.radar.close": "시맨틱 레이더 닫기",
              "viewer.radar.surface": "다이어그램 개요입니다. 노드를 클릭해 포커스하거나 방향키로 이동하세요.",
              "viewer.radar.click": "노드 클릭",
              "viewer.radar.drag": "드래그로 이동",
              "viewer.radar.space": "시맨틱 레이더를 표시하려면 지도 공간이 더 필요합니다.",
              "viewer.radar.nodes": "시맨틱 다이어그램 레이더 노드",
              "viewer.radar.focus": "시맨틱 레이더에서 {label} 포커스",
              "viewer.radar.status": "노드 {count}개 · {viewport}",
              "viewer.radar.fullMap": "노드 {count}개 · 전체 지도",
              "viewer.radar.compacted": "시맨틱 패스포트나 지도 컨트롤을 가리지 않도록 레이더를 축소했습니다.",
              "viewer.radar.cancelWaiting": "지도 공간 확보를 기다리는 시맨틱 레이더 취소",
              "viewer.radar.needsSpace": "시맨틱 레이더를 표시하려면 지도 공간이 더 필요합니다",
              "viewer.radar.viewport.full": "전체 지도",
              "viewer.radar.viewport.width": "너비 {percent}%",
              "viewer.radar.viewport.scale": "뷰포트 {percent}%",
              "viewer.nav.controls": "다이어그램 보기 제어",
              "viewer.nav.route": "방향성 경로 추적",
              "viewer.nav.route.title": "경로 추적 (R)",
              "viewer.nav.route.short": "경로",
              "viewer.nav.radar": "시맨틱 레이더 열기",
              "viewer.nav.radar.title": "시맨틱 레이더 (M)",
              "viewer.nav.radar.short": "지도",
              "viewer.nav.lens": "시맨틱 렌즈 열기",
              "viewer.nav.lens.title": "시맨틱 렌즈 (L)",
              "viewer.nav.lens.short": "렌즈",
              "viewer.nav.find": "노드 찾기",
              "viewer.nav.find.title": "노드 찾기 (/)",
              "viewer.nav.guide": "다이어그램 가이드 열기",
              "viewer.nav.guide.title": "다이어그램 가이드 (?)",
              "viewer.nav.zoomOut": "축소",
              "viewer.nav.zoomOut.title": "축소 (-)",
              "viewer.nav.reset": "다이어그램 보기 초기화",
              "viewer.nav.reset.title": "보기 초기화 (0)",
              "viewer.nav.read": "읽기",
              "viewer.nav.zoomIn": "확대",
              "viewer.nav.zoomIn.title": "확대 (+)",
              "viewer.nav.camera": "{hint}. 다이어그램 보기 초기화",
              "viewer.nav.camera.title": "{semantic}{hint} · 보기 초기화 (0)",
              "viewer.nav.camera.semantic": "시맨틱 카메라 활성 · ",
              "viewer.nav.level.map": "개요",
              "viewer.nav.level.read": "읽기",
              "viewer.nav.level.full": "전체",
              "viewer.nav.level.auto": "자동",
              "viewer.nav.detail.map": "확대하면 관계 라벨과 노드 컨텍스트가 표시됩니다",
              "viewer.nav.detail.read": "다시 확대하면 태그와 주석이 표시됩니다",
              "viewer.nav.detail.full": "다이어그램 전체 상세정보",
              "viewer.intent.summary": "{label}. 출향 {out}개, 입향 {in}개{loops}. 연결 총 {total}개. Enter로 상세정보 확인.",
              "viewer.intent.loops": ", 자기순환 {count}개",
              "viewer.common.copied": "복사됨",
              "viewer.common.copyFailed": "복사 실패",
              "viewer.common.copyLink": "링크 복사",
              "viewer.common.clear": "지우기",
              "viewer.common.close": "닫기",
              "viewer.export.svg.auto": "SVG · 자동",
              "viewer.export.svg.auto.hint": "호스트 테마에 맞춤",
              "viewer.export.svg.light": "SVG · 라이트",
              "viewer.export.svg.light.hint": "항상 라이트 테마",
              "viewer.export.svg.dark": "SVG · 다크",
              "viewer.export.svg.dark.hint": "항상 다크 테마",
              "viewer.guide.title": "이 시스템 살펴보기",
              "viewer.focus.selectedNodes": "선택한 노드 {count}개",
              "viewer.passport.move": "의미 정보 패널 이동. 드래그하거나 화살표 키를 사용하고, Home 키로 초기화하세요.",
              "viewer.outline.title": "노드 목록",
              "viewer.rail.show": "설명 및 목록",
              "viewer.rail.controls": "측면 패널",
              "viewer.rail.collapse": "측면 패널 접기",
              "viewer.rail.bottom": "패널을 다이어그램 아래로 이동",
              "viewer.rail.right": "패널을 다이어그램 옆으로 이동"
            },
            "output": "korean-locale.html",
            "quality_profile": "showcase",
            "views": [
              {
                "id": "request-path",
                "label": "기본 요청 경로",
                "focus": [
                  "users",
                  "cdn",
                  "lb",
                  "api",
                  "db"
                ],
                "note": "가장자리에서 저장소까지 고객 요청을 따라갑니다."
              },
              {
                "id": "identity-and-cache",
                "label": "인증과 캐시",
                "focus": [
                  "auth",
                  "api",
                  "cache"
                ],
                "note": "인증과 읽기 캐시를 요청 경로 옆에 분리합니다."
              },
              {
                "id": "async-work",
                "label": "정적·비동기 작업",
                "focus": [
                  "cdn",
                  "s3",
                  "api",
                  "queue",
                  "worker"
                ],
                "note": "부가 경로 두 개를 본 요청과 겹치지 않게 보여 줍니다."
              }
            ]
          },
          "components": [
            {
              "id": "users",
              "type": "external",
              "label": "사용자",
              "sublabel": "브라우저 / 모바일",
              "pos": [
                40,
                300
              ],
              "size": [
                120,
                60
              ]
            },
            {
              "id": "auth",
              "type": "security",
              "label": "인증 공급자",
              "sublabel": "OAuth 2.0",
              "pos": [
                40,
                110
              ],
              "size": [
                120,
                64
              ],
              "tag": "JWT + PKCE"
            },
            {
              "id": "cdn",
              "type": "cloud",
              "label": "CloudFront",
              "sublabel": "CDN",
              "pos": [
                250,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "lb",
              "type": "cloud",
              "label": "로드 밸런서",
              "sublabel": "HTTPS :443",
              "pos": [
                460,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "api",
              "type": "backend",
              "label": "API 서버",
              "sublabel": "FastAPI :8000",
              "pos": [
                670,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "cache",
              "type": "database",
              "label": "Redis",
              "sublabel": "cache :6379",
              "pos": [
                670,
                150
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "db",
              "type": "database",
              "label": "PostgreSQL",
              "sublabel": "primary :5432",
              "pos": [
                880,
                300
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "s3",
              "type": "cloud",
              "label": "S3",
              "sublabel": "정적 자산",
              "pos": [
                250,
                440
              ],
              "size": [
                130,
                60
              ],
              "tag": "OAI protected"
            },
            {
              "id": "queue",
              "type": "messagebus",
              "label": "SQS",
              "sublabel": "작업 큐",
              "pos": [
                670,
                440
              ],
              "size": [
                130,
                60
              ]
            },
            {
              "id": "worker",
              "type": "backend",
              "label": "워커",
              "sublabel": "비동기 작업",
              "pos": [
                880,
                440
              ],
              "size": [
                130,
                60
              ]
            }
          ],
          "boundaries": [
            {
              "kind": "region",
              "label": "AWS 리전: us-west-2",
              "wraps": [
                "cdn",
                "lb",
                "api",
                "cache",
                "db",
                "s3",
                "queue",
                "worker"
              ]
            },
            {
              "kind": "security-group",
              "label": "sg-api :443/:8000",
              "wraps": [
                "lb",
                "api"
              ]
            }
          ],
          "connections": [
            {
              "id": "users-to-cdn",
              "from": "users",
              "to": "cdn",
              "label": "HTTPS",
              "variant": "emphasis"
            },
            {
              "id": "jwt-verification",
              "from": "auth",
              "to": "api",
              "label": "JWT 검증",
              "variant": "security",
              "fromSide": "right",
              "toSide": "top",
              "via": [
                [
                  620,
                  142
                ],
                [
                  620,
                  246
                ],
                [
                  735,
                  246
                ]
              ]
            },
            {
              "id": "cdn-to-lb",
              "from": "cdn",
              "to": "lb"
            },
            {
              "id": "static-assets",
              "from": "cdn",
              "to": "s3",
              "label": "정적",
              "variant": "dashed",
              "fromSide": "bottom",
              "toSide": "top",
              "labelDy": 58
            },
            {
              "id": "lb-to-api",
              "from": "lb",
              "to": "api"
            },
            {
              "id": "cache-read-through",
              "from": "api",
              "to": "cache",
              "label": "read-through",
              "fromSide": "top",
              "toSide": "bottom",
              "labelDy": -68
            },
            {
              "id": "api-sql",
              "from": "api",
              "to": "db",
              "label": "SQL"
            },
            {
              "id": "enqueue-job",
              "from": "api",
              "to": "queue",
              "label": "enqueue",
              "variant": "dashed",
              "fromSide": "bottom",
              "toSide": "top",
              "labelDy": 58
            },
            {
              "id": "queue-to-worker",
              "from": "queue",
              "to": "worker"
            }
          ],
          "cards": [
            {
              "dot": "cyan",
              "title": "가장자리",
              "items": [
                "CloudFront CDN이 트래픽을 받습니다",
                "S3가 OAI로 정적 자산을 제공합니다"
              ]
            },
            {
              "dot": "emerald",
              "title": "애플리케이션",
              "items": [
                "HTTPS 로드 밸런서 뒤의 FastAPI",
                "Redis 읽기 캐시",
                "SQS에서 워커가 비동기 작업을 처리"
              ]
            },
            {
              "dot": "rose",
              "title": "보안",
              "items": [
                "OAuth 2.0 with JWT + PKCE",
                "API와 LB를 보안 그룹으로 격리"
              ]
            }
          ]
        }
        
      • v1-workflow-700x400.workflow.json 957 B
        {
          "schema_version": 1,
          "diagram_type": "workflow",
          "meta": {
            "title": "Legacy narrow workflow",
            "output": "v1-workflow-700x400.html",
            "viewBox": [700, 400]
          },
          "lanes": [
            { "id": "first", "label": "First" },
            { "id": "second", "label": "Second" }
          ],
          "nodes": [
            { "id": "node_0", "lane": "first", "col": 0, "type": "frontend", "label": "frontend" },
            { "id": "node_1", "lane": "first", "col": 2, "type": "backend", "label": "backend" },
            { "id": "node_2", "lane": "first", "col": 4, "type": "database", "label": "database" },
            { "id": "node_3", "lane": "second", "col": 0, "type": "cloud", "label": "cloud" },
            { "id": "node_4", "lane": "second", "col": 2, "type": "security", "label": "security" },
            { "id": "node_5", "lane": "second", "col": 4, "type": "messagebus", "label": "messagebus" },
            { "id": "node_6", "lane": "second", "col": 5, "type": "external", "label": "external" }
          ],
          "edges": []
        }
        
      • v1-workflow-explicit-coordinates.workflow.json 1.4 KB
        {
          "schema_version": 1,
          "diagram_type": "workflow",
          "meta": {
            "title": "Pinned coordinate migration",
            "output": "pinned-coordinate-migration.html",
            "viewBox": [720, 700],
            "legend": { "mode": "hidden" }
          },
          "lanes": [
            { "id": "route", "label": "Explicit route" },
            { "id": "label", "label": "Explicit label" },
            { "id": "channel-source", "label": "Channel source" },
            { "id": "channel-target", "label": "Channel target" }
          ],
          "nodes": [
            { "id": "route-a", "lane": "route", "col": 0, "type": "backend", "label": "A" },
            { "id": "route-b", "lane": "route", "col": 2, "type": "backend", "label": "B" },
            { "id": "label-a", "lane": "label", "col": 2, "type": "backend", "label": "C" },
            { "id": "label-b", "lane": "label", "col": 3, "type": "backend", "label": "D" },
            { "id": "channel-a", "lane": "channel-source", "col": 1, "type": "backend", "label": "E" },
            { "id": "channel-b", "lane": "channel-target", "col": 1, "type": "backend", "label": "F" }
          ],
          "edges": [
            {
              "id": "pinned-via",
              "from": "route-a",
              "to": "route-b",
              "via": [[220, 119]]
            },
            {
              "id": "pinned-label",
              "from": "label-a",
              "to": "label-b",
              "label": "ok",
              "labelAt": [365, 203]
            },
            {
              "id": "pinned-channel",
              "from": "channel-a",
              "to": "channel-b",
              "fromSide": "right",
              "toSide": "right",
              "route": "outside-right",
              "channelX": 500
            }
          ]
        }
        
      • workflow-routing-clarity.workflow.json 3 KB
        {
          "schema_version": 2,
          "diagram_type": "workflow",
          "meta": {
            "title": "Agent Turn Workflow",
            "locale": "zh-CN",
            "output": "workflow-routing-clarity.html",
            "quality_profile": "showcase"
          },
          "lanes": [
            { "id": "host", "label": "Runtime Host" },
            { "id": "runtime", "label": "Session + AgentRun" },
            { "id": "evidence", "label": "Events + Projections" }
          ],
          "phases": [
            { "id": "admit", "label": "准入与路由", "fromCol": 0, "toCol": 1 },
            { "id": "execute", "label": "Turn 执行", "fromCol": 2, "toCol": 4, "variant": "emphasis" },
            { "id": "project", "label": "持久化与投影", "fromCol": 5, "toCol": 5, "variant": "dashed" }
          ],
          "mainPath": ["request", "admit", "start", "turn", "commit", "project"],
          "nodes": [
            { "id": "request", "lane": "host", "col": 0, "type": "frontend", "label": "Submit Task", "sublabel": "Desktop / TUI / CLI" },
            { "id": "admit", "lane": "host", "col": 1, "type": "security", "label": "Host Admission", "sublabel": "client + capability" },
            { "id": "start", "lane": "runtime", "col": 2, "type": "backend", "label": "Start Session", "sublabel": "SessionManager" },
            { "id": "turn", "lane": "runtime", "col": 3, "type": "backend", "label": "Run Turn", "sublabel": "model + tool loop" },
            { "id": "tool", "lane": "runtime", "col": 4, "type": "security", "label": "Tool Boundary", "sublabel": "permission / sandbox" },
            { "id": "commit", "lane": "evidence", "col": 4, "type": "database", "label": "Append Event", "sublabel": "RuntimeEvent" },
            { "id": "project", "lane": "evidence", "col": 5, "type": "frontend", "label": "Project State", "sublabel": "UI + recovery" },
            { "id": "graph", "lane": "host", "col": 3, "type": "messagebus", "label": "Agent Graph", "sublabel": "dependent child work" },
            { "id": "resume", "lane": "runtime", "col": 5, "type": "security", "label": "Resume Check", "sublabel": "safe replay or blocked" }
          ],
          "edges": [
            { "from": "request", "to": "admit", "label": "client request", "role": "main" },
            { "from": "admit", "to": "start", "label": "authorized session", "role": "main" },
            { "from": "start", "to": "turn", "label": "startTurn", "role": "main" },
            { "from": "turn", "to": "tool", "label": "dispatch tool", "variant": "security", "role": "main" },
            { "from": "tool", "to": "turn", "label": "tool result", "variant": "dashed", "role": "return" },
            { "from": "turn", "to": "commit", "label": "append event", "variant": "dashed", "role": "main" },
            { "from": "commit", "to": "project", "label": "projection", "variant": "dashed", "role": "main" },
            { "from": "start", "to": "graph", "label": "schedule graph", "variant": "emphasis", "role": "async" },
            { "from": "graph", "to": "turn", "label": "activation", "variant": "dashed", "role": "return" },
            { "from": "turn", "to": "resume", "label": "crash / handoff", "variant": "security", "role": "branch" },
            { "from": "resume", "to": "commit", "label": "replay evidence", "variant": "dashed", "role": "return" }
          ]
        }
        
      • workflow-shared-trunks.workflow.json 3.1 KB
        {
          "schema_version": 2,
          "diagram_type": "workflow",
          "meta": { "title": "分支与回流", "locale": "zh-CN", "output": "workflow.html" },
          "lanes": [
            { "id": "parent", "label": "会话入口与用户反馈" },
            { "id": "ordinary", "label": "普通工具路径" },
            { "id": "execution", "label": "主会话调度与独立委派" },
            { "id": "orchestration", "label": "多阶段编排路径" },
            { "id": "process", "label": "后台进程路径" }
          ],
          "nodes": [
            { "id": "submit", "lane": "parent", "col": 0, "type": "frontend", "label": "提交任务", "width": 156 },
            { "id": "capabilities", "lane": "parent", "col": 1, "type": "security", "label": "加载能力", "width": 172 },
            { "id": "decide", "lane": "execution", "col": 2, "type": "backend", "label": "执行决策", "width": 156 },
            { "id": "native", "lane": "ordinary", "col": 3, "type": "backend", "label": "普通工具", "width": 172 },
            { "id": "child", "lane": "execution", "col": 3, "type": "backend", "label": "独立执行", "width": 172 },
            { "id": "workflow", "lane": "orchestration", "col": 3, "type": "messagebus", "label": "任务编排", "width": 172 },
            { "id": "background", "lane": "process", "col": 3, "type": "external", "label": "后台进程", "width": 172 },
            { "id": "collect", "lane": "execution", "col": 4, "type": "messagebus", "label": "接收结果", "width": 156 },
            { "id": "reply", "lane": "parent", "col": 5, "type": "frontend", "label": "回复结果", "width": 172 }
          ],
          "edges": [
            { "id": "prepare", "from": "submit", "to": "capabilities", "label": "回合启动前", "role": "main", "variant": "emphasis" },
            { "id": "model-turn", "from": "capabilities", "to": "decide", "label": "可用工具面", "role": "main", "variant": "emphasis" },
            { "id": "ordinary-work", "from": "decide", "to": "native", "label": "普通工作", "role": "main", "variant": "emphasis" },
            { "id": "delegate-work", "from": "decide", "to": "child", "label": "独立执行", "role": "branch" },
            { "id": "orchestrate-work", "from": "decide", "to": "workflow", "label": "编排执行", "role": "branch" },
            { "id": "launch-process", "from": "decide", "to": "background", "label": "后台执行", "role": "branch" },
            { "id": "native-result", "from": "native", "to": "collect", "label": "工具结果", "role": "main", "variant": "emphasis" },
            { "id": "child-result", "from": "child", "to": "collect", "label": "完成后跟进", "role": "async", "variant": "dashed" },
            { "id": "workflow-result", "from": "workflow", "to": "collect", "label": "等待返回/稍后投递", "role": "async", "variant": "dashed" },
            { "id": "process-result", "from": "background", "to": "collect", "label": "状态/完成通知", "role": "async", "variant": "dashed" },
            { "id": "continue-work", "from": "collect", "to": "decide", "label": "仍需后续工作", "role": "return", "variant": "dashed", "channelY": 180 },
            { "id": "finish", "from": "collect", "to": "reply", "label": "综合结果", "role": "main", "variant": "emphasis" },
            { "id": "direct-answer", "from": "decide", "to": "reply", "label": "无需工具时直接回答", "role": "branch" }
          ]
        }
        
    • helpers
      • desktop-browser.mjs 2.2 KB · in bundle
      • offline-fonts.mjs 5.1 KB · in bundle
      • viewer-click.mjs 3.4 KB · in bundle
      • xml.mjs 1.2 KB · in bundle
    • adaptive-reader-layout.test.mjs 8.8 KB · in bundle
    • animation.test.mjs 8.5 KB · in bundle
    • architecture-automatic-labels.test.mjs 7.7 KB · in bundle
    • architecture-compare-recovery.test.mjs 14.6 KB · in bundle
    • architecture-delta-literals.test.mjs 4.7 KB · in bundle
    • architecture-delta-markers.test.mjs 6.7 KB · in bundle
    • architecture-delta.test.mjs 52.2 KB · in bundle
    • architecture-first-draft.test.mjs 8 KB · in bundle
    • architecture-leading-space.test.mjs 5.7 KB · in bundle
    • architecture-readable-routing-labels.test.mjs 5.6 KB · in bundle
    • architecture-readable-routing.test.mjs 5 KB · in bundle
    • architecture-reading-size-browser.test.mjs 11.7 KB · in bundle
    • architecture-repair-evidence.test.mjs 10.7 KB · in bundle
    • artifact-receipt-flush.test.mjs 5.2 KB · in bundle
    • atomic-output-recovery.test.mjs 18.3 KB · in bundle
    • authored-reachability.test.mjs 4.4 KB · in bundle
    • authored-straight-routes.test.mjs 7.3 KB · in bundle
    • authoring-safety-contract.test.mjs 3.8 KB · in bundle
    • automatic-port-spread.test.mjs 21.2 KB · in bundle
    • base-input-compatibility.test.mjs 1.3 KB · in bundle
    • brand-content-encoding.test.mjs 9.2 KB · in bundle
    • brand-href-entities.test.mjs 8 KB · in bundle
    • brand-marks.test.mjs 36.1 KB · in bundle
    • browser-gate.test.mjs 4.3 KB · in bundle
    • checkout-line-endings.test.mjs 3.7 KB · in bundle
    • chrome-pipe-transport.test.mjs 3.1 KB · in bundle
    • ci-scope.test.mjs 3.2 KB · in bundle
    • clean-skill-staging.test.mjs 30 KB · in bundle
    • cli-output-types.test.mjs 13.8 KB · in bundle
    • cli.test.mjs 196.6 KB · in bundle
    • community-proof-intake.test.mjs 4.6 KB · in bundle
    • compact-header-clearance.test.mjs 3.7 KB · in bundle
    • copy-site-assets.test.mjs 17.4 KB · in bundle
    • crossover-state-browser.test.mjs 10.4 KB · in bundle
    • cursor-onboarding.test.mjs 3.7 KB · in bundle
    • degraded.test.mjs 7.1 KB · in bundle
    • delivery-contract.test.mjs 11.9 KB · in bundle
    • delivery-sidecar-path.test.mjs 57.6 KB · in bundle
    • delivery-update.test.mjs 10.4 KB · in bundle
    • desktop-reader-browser.test.mjs 27.1 KB · in bundle
    • diagram-guide.test.mjs 4.2 KB · in bundle
    • edge-label-color.test.mjs 11.5 KB · in bundle
    • engineering-profile.test.mjs 10 KB · in bundle
    • export-browser.test.mjs 28.9 KB · in bundle
    • export-cleanup-browser.test.mjs 19.6 KB · in bundle
    • finalize-browser-lifecycle.test.mjs 10.8 KB · in bundle
    • finalize-browser.test.mjs 2.3 KB · in bundle
    • finalize-paths.test.mjs 5.1 KB · in bundle
    • finalize.test.mjs 44.6 KB · in bundle
    • finder-browser.test.mjs 19 KB · in bundle
    • finder.test.mjs 5.2 KB · in bundle
    • focus-browser.test.mjs 28.9 KB · in bundle
    • gallery.test.mjs 6.7 KB · in bundle
    • generate-validators.test.mjs 5.6 KB · in bundle
    • generate-viewer.test.mjs 9.4 KB · in bundle
    • generated-artifact-xml.test.mjs 3.7 KB · in bundle
    • geometry.test.mjs 56.1 KB · in bundle
    • golden.mjs 9.9 KB · in bundle
    • grid.test.mjs 1.7 KB · in bundle
    • guide-page.test.mjs 4 KB · in bundle
    • guide.test.mjs 5.1 KB · in bundle
    • i18n.test.mjs 45.2 KB · in bundle
    • intent-trace-browser.test.mjs 23 KB · in bundle
    • intent-trace.test.mjs 6.2 KB · in bundle
    • joint-layout-browser.test.mjs 31.2 KB · in bundle
    • joint-layout-contract.test.mjs 17.5 KB · in bundle
    • label-clearance.test.mjs 6.2 KB · in bundle
    • landing.test.mjs 5.4 KB · in bundle
    • layout-rules.test.mjs 96 KB · in bundle
    • legend-contract.test.mjs 17.2 KB · in bundle
    • lifecycle-band-title.test.mjs 5.2 KB · in bundle
    • lifecycle-note-only.test.mjs 9.9 KB · in bundle
    • lifecycle-planner.test.mjs 5.3 KB · in bundle
    • lifecycle-rail-browser.test.mjs 5.9 KB · in bundle
    • lifecycle-v2-layout.test.mjs 15.4 KB · in bundle
    • meta-output-contract.test.mjs 12.9 KB · in bundle
    • motion-governor-browser.test.mjs 21 KB · in bundle
    • motion-governor.test.mjs 5.7 KB · in bundle
    • native-output-path.test.mjs 10 KB · in bundle
    • node-icons.test.mjs 3.1 KB · in bundle
    • offline-font-browser.test.mjs 12.6 KB · in bundle
    • offline-self-containment.test.mjs 5.4 KB · in bundle
    • open-artifact.test.mjs 6.7 KB · in bundle
    • ordinary-model-floor.test.mjs 44.8 KB · in bundle
    • output-path.test.mjs 49.8 KB · in bundle
    • path-boundary-contract.test.mjs 7.3 KB · in bundle
    • path-semantics.test.mjs 34.6 KB · in bundle
    • portable-path.test.mjs 14.3 KB · in bundle
    • presentation.test.mjs 3.2 KB · in bundle
    • preset-tryon.test.mjs 5.3 KB · in bundle
    • preview-contract.test.mjs 2.1 KB · in bundle
    • preview-force-stop.test.mjs 10.9 KB · in bundle
    • preview.test.mjs 69.2 KB · in bundle
    • proof-aperture.test.mjs 4.4 KB · in bundle
    • reach-share-card.test.mjs 8.5 KB · in bundle
    • reader-layout-browser.test.mjs 18.7 KB · in bundle
    • reader-layout-settle-browser.test.mjs 3.7 KB · in bundle
    • reader-readability-maintained-browser.test.mjs 10.6 KB · in bundle
    • readme-showcase.test.mjs 18 KB · in bundle
    • real-repository-proof.test.mjs 8.9 KB · in bundle
    • relationship-direct-explorer.test.mjs 6.9 KB · in bundle
    • relationship-lens.test.mjs 7.1 KB · in bundle
    • relationship-permalink.test.mjs 6.4 KB · in bundle
    • relationship-pulse.test.mjs 6.6 KB · in bundle
    • release-identity.test.mjs 18.8 KB · in bundle
    • release-package-gates.test.mjs 80.7 KB · in bundle
    • render-failure-diagnostics.test.mjs 9.8 KB · in bundle
    • render-output-checks.test.mjs 62.5 KB · in bundle
    • renderer-atomic-write.test.mjs 61.6 KB · in bundle
    • renderer-diagnostic-boundary.test.mjs 4.4 KB · in bundle
    • renderer-import-isolation.test.mjs 4.3 KB · in bundle
    • repair-receipt.test.mjs 11.1 KB · in bundle
    • repository-evidence-replacement.test.mjs 6.8 KB · in bundle
    • repository-evidence-types-browser.test.mjs 7.6 KB · in bundle
    • repository-evidence-types.test.mjs 18 KB · in bundle
    • repository-evidence.test.mjs 38.7 KB · in bundle
    • repository-language-metadata.test.mjs 2.1 KB · in bundle
    • route-detour.test.mjs 6.4 KB · in bundle
    • route-journey.test.mjs 8.1 KB · in bundle
    • route-probe-browser.test.mjs 36.4 KB · in bundle
    • route-probe.test.mjs 6.2 KB · in bundle
    • route-share-card.test.mjs 9.6 KB · in bundle
    • semantic-camera.test.mjs 4.5 KB · in bundle
    • semantic-flow.test.mjs 4.7 KB · in bundle
    • semantic-legend-gateway.test.mjs 7.5 KB · in bundle
    • semantic-lens-browser.test.mjs 33.3 KB · in bundle
    • semantic-lens.test.mjs 5.3 KB · in bundle
    • semantic-passport-move-browser.test.mjs 30.9 KB · in bundle
    • semantic-passport.test.mjs 12.7 KB · in bundle
    • semantic-radar.test.mjs 36.5 KB · in bundle
    • semantic-zoom.test.mjs 4.3 KB · in bundle
    • sequence-column-fit.test.mjs 7.6 KB · in bundle
    • sequence-header-clearance.test.mjs 5.2 KB · in bundle
    • sequence-width-review.test.mjs 7.8 KB · in bundle
    • settled-flow.test.mjs 5.2 KB · in bundle
    • share-card-export.test.mjs 4.4 KB · in bundle
    • sidecar-path-length.test.mjs 15.9 KB · in bundle
    • site-language-continuity.test.mjs 25.5 KB · in bundle
    • site-language-integration.mjs 377 B · in bundle
    • skill-metadata.test.mjs 5.2 KB · in bundle
    • spatial-grid.test.mjs 2.1 KB · in bundle
    • spread-regression.test.mjs 2.6 KB · in bundle
    • stable-update-manifest.test.mjs 6.5 KB · in bundle
    • start-page.test.mjs 13.7 KB · in bundle
    • toolbar-polish.test.mjs 4.5 KB · in bundle
    • update-contract.test.mjs 4.7 KB · in bundle
    • update-notifier.test.mjs 114.5 KB · in bundle
    • v1-compatibility.test.mjs 13.4 KB · in bundle
    • validate-next-action.test.mjs 2.6 KB · in bundle
    • vertical-edge.test.mjs 2.8 KB · in bundle
    • viewer-camera-browser.test.mjs 19.8 KB · in bundle
    • viewer-chrome-layout.test.mjs 55.2 KB · in bundle
    • viewer-identifiers-browser.test.mjs 7.1 KB · in bundle
    • visual-check.test.mjs 130.7 KB · in bundle
    • webm-artifact.smoke.mjs 91.4 KB · in bundle
    • workflow-action-pinning.test.mjs 3.3 KB · in bundle
    • workflow-compiler-call-contract.test.mjs 3.7 KB · in bundle
    • workflow-compiler-hard-contract.test.mjs 87.7 KB · in bundle
    • workflow-compiler.test.mjs 52 KB · in bundle
    • workflow-migration.test.mjs 36.7 KB · in bundle
    • workflow-routing-clarity.test.mjs 11.4 KB · in bundle
    • workflow-semantic-contract.test.mjs 4.5 KB · in bundle
    • workflow-shared-trunks.test.mjs 15.4 KB · in bundle
    • workflow-vertical-label.test.mjs 6.5 KB · in bundle
  • LICENSE 1.1 KB · in bundle
  • package-lock.json 4.8 KB
    {
      "name": "archify",
      "version": "3.0.1",
      "lockfileVersion": 3,
      "requires": true,
      "packages": {
        "": {
          "name": "archify",
          "version": "3.0.1",
          "license": "MIT",
          "bin": {
            "archify": "bin/archify.mjs"
          },
          "devDependencies": {
            "ajv": "^8.17.1",
            "parse5": "7.3.0",
            "saxes": "6.0.0",
            "simple-icons": "16.28.0"
          },
          "engines": {
            "node": ">=18"
          }
        },
        "node_modules/ajv": {
          "version": "8.20.0",
          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
          "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
          "dev": true,
          "license": "MIT",
          "dependencies": {
            "fast-deep-equal": "^3.1.3",
            "fast-uri": "^3.0.1",
            "json-schema-traverse": "^1.0.0",
            "require-from-string": "^2.0.2"
          },
          "funding": {
            "type": "github",
            "url": "https://github.com/sponsors/epoberezkin"
          }
        },
        "node_modules/entities": {
          "version": "6.0.1",
          "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
          "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
          "dev": true,
          "license": "BSD-2-Clause",
          "engines": {
            "node": ">=0.12"
          },
          "funding": {
            "url": "https://github.com/fb55/entities?sponsor=1"
          }
        },
        "node_modules/fast-deep-equal": {
          "version": "3.1.3",
          "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
          "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
          "dev": true,
          "license": "MIT"
        },
        "node_modules/fast-uri": {
          "version": "3.1.7",
          "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz",
          "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
          "dev": true,
          "funding": [
            {
              "type": "github",
              "url": "https://github.com/sponsors/fastify"
            },
            {
              "type": "opencollective",
              "url": "https://opencollective.com/fastify"
            }
          ],
          "license": "BSD-3-Clause"
        },
        "node_modules/json-schema-traverse": {
          "version": "1.0.0",
          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
          "dev": true,
          "license": "MIT"
        },
        "node_modules/parse5": {
          "version": "7.3.0",
          "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
          "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
          "dev": true,
          "license": "MIT",
          "dependencies": {
            "entities": "^6.0.0"
          },
          "funding": {
            "url": "https://github.com/inikulin/parse5?sponsor=1"
          }
        },
        "node_modules/require-from-string": {
          "version": "2.0.2",
          "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
          "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
          "dev": true,
          "license": "MIT",
          "engines": {
            "node": ">=0.10.0"
          }
        },
        "node_modules/saxes": {
          "version": "6.0.0",
          "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
          "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
          "dev": true,
          "license": "ISC",
          "dependencies": {
            "xmlchars": "^2.2.0"
          },
          "engines": {
            "node": ">=v12.22.7"
          }
        },
        "node_modules/simple-icons": {
          "version": "16.28.0",
          "resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-16.28.0.tgz",
          "integrity": "sha512-sQPR5AtK/ijRjou7zw7mlLp08oB6FH7i0lOy5XJ2zp9mJs/yejgiOn7KvQoe2q4YJIx6VmgUSW5AOefebPt5kg==",
          "dev": true,
          "funding": [
            {
              "type": "opencollective",
              "url": "https://opencollective.com/simple-icons"
            },
            {
              "type": "github",
              "url": "https://github.com/sponsors/simple-icons"
            }
          ],
          "license": "CC0-1.0",
          "engines": {
            "node": ">=0.12.18"
          }
        },
        "node_modules/xmlchars": {
          "version": "2.2.0",
          "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
          "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
          "dev": true,
          "license": "MIT"
        }
      }
    }
    
  • package.json 1.6 KB
    {
      "name": "archify",
      "version": "3.0.1",
      "private": true,
      "type": "module",
      "description": "JSON-IR diagram renderers (architecture / workflow / sequence / dataflow / lifecycle).",
      "license": "MIT",
      "bin": {
        "archify": "./bin/archify.mjs"
      },
      "engines": {
        "node": ">=18"
      },
      "scripts": {
        "generate:viewer": "node ../scripts/generate-viewer.mjs",
        "check:viewer": "node ../scripts/generate-viewer.mjs --check",
        "generate:brand-marks": "node scripts/generate-brand-marks.mjs",
        "check:brand-marks": "node scripts/generate-brand-marks.mjs --check",
        "generate:validators": "node scripts/generate-validators.mjs",
        "check:validators": "node scripts/generate-validators.mjs --check",
        "check:release-identity": "node ../scripts/check-release-identity.mjs",
        "build:gallery": "node ../scripts/build-gallery.mjs ../docs",
        "build:guide": "node ../scripts/build-guide.mjs ../docs/guide.html",
        "build:start": "node ../scripts/build-start.mjs ../docs/start.html",
        "build:readme-showcase": "node ../scripts/build-readme-showcase.mjs",
        "test:webm": "node test/webm-artifact.smoke.mjs && node --test test/site-language-integration.mjs",
        "test:browser": "node ../scripts/run-browser-tests.mjs",
        "test": "npm run check:viewer && npm run check:brand-marks && npm run check:validators && npm run check:release-identity && node test/golden.mjs && node ../scripts/run-tests.mjs",
        "render:examples": "node scripts/render-examples.mjs ../examples"
      },
      "devDependencies": {
        "ajv": "^8.17.1",
        "parse5": "7.3.0",
        "saxes": "6.0.0",
        "simple-icons": "16.28.0"
      },
      "overrides": {
        "fast-uri": "^3.1.7"
      }
    }
    
  • skill-release.json 260 B
    {
      "schemaVersion": 1,
      "skillId": "archify",
      "channel": "stable",
      "version": "3.0.1",
      "source": {
        "repository": "https://github.com/tt-a1i/archify"
      },
      "updateManifestUrl": "https://tt-a1i.github.io/archify/skill-updates/archify/stable.json"
    }
    
  • SKILL.md 10.6 KB
    ---
    name: archify
    description: Create polished, validated architecture, workflow, sequence, data-flow, and lifecycle/state diagrams as explorable standalone HTML with inline SVG, dark/light themes, optional trace motion, and PNG/JPEG/WebP/SVG/WebM export. Accept plain-language requirements or pasted Mermaid flowchart, sequenceDiagram, and stateDiagram input; inspect repository evidence when the diagram must reflect real code. Use when the user asks to visualize system architecture, infrastructure, cloud/security/network topology, technical workflows, API call sequences, request lifecycles, data pipelines, ETL/ELT, data lineage, state machines, or to convert/beautify Mermaid.
    license: MIT
    metadata:
      version: "3.0"
      author: tt-a1i
      based_on: Cocoon-AI/architecture-diagram-generator (MIT, v1.0)
    ---
    
    # Archify
    
    Create an interactive HTML diagram from typed JSON. Static output is the default; enable motion only when requested.
    
    Run commands from your working directory. Unless the user names another location, give each new diagram request its own folder `.archify/<type>-<slug>-<YYYYMMDD-HHMMSS>/` there (local time, chosen once when the request starts): keep `candidate.json` and `<slug>.html` in it, set `meta.output` to that relative HTML path, and reuse the folder for every repair rerun. A later request gets a new folder, so earlier versions stay intact. Replace `bin/archify.mjs` in the commands below with the installed package's absolute path, or its path relative to your working directory; input and output paths resolve from that working directory.
    
    For a real codebase, read [Repository authoring](references/repository-authoring.md) while tracing the requested behavior. A system description uses the steps below; an existing JSON uses the handoff path.
    
    ## Existing candidate handoff
    
    When the user supplies a frozen candidate, run `finalize` first as one CLI invocation. Its passing receipt completes the automated gates; follow any visual review recommendation under Delivery before claiming visual quality. For repair, follow step 5.
    
    `finalize` includes a bounded update check in its delivery receipt; see Update awareness.
    
    ## Fast authoring path
    
    Use this path for ordinary generation. Read branch references only when their stated trigger applies.
    
    1. Choose `architecture`, `workflow`, `sequence`, `dataflow`, or `lifecycle` from the question.
    2. Use the exact schema and example paths in the Type router without listing their directories. Read [Authoring defaults](references/authoring-defaults.md) and the mode's example in a bounded batch separate from project documents and complete schemas so neither is truncated; recover any missing section before writing. For Architecture, use the matching showcase example. For Sequence, Dataflow, and Lifecycle, also read the mode and common schemas. Read the relevant schema definition before choosing any new field, enum, or constrained text, especially boundary kinds. Examples teach shape, not facts. Use fresh IDs, wording, and layout. Go directly to the candidate without preliminary help, doctor, starter validation, temporary diagrams, or output-path listing. Query brands only for an explicitly requested mark; read [Brand marks](references/brand-marks.md) for an unknown mark with a user-provided URL.
    3. Once the requested scope and, for a real codebase, [source evidence](references/repository-authoring.md) are covered, write the complete candidate directly without planning coordinates in prose. Choose Architecture abstraction and connected placement using Authoring defaults before coordinates: show the main user journey and necessary branches, preserve control roles and behavior-changing conditions, and leave enough room for actual relationship labels. No node, relationship, source, view, card, or boundary count is a target or ceiling. Use automatic routes first; add explicit routing only for necessary branch, return, supplied geometry, or measured repair. Set `meta.quality_profile` to `"showcase"` unless the user requests dense `standard`.
    4. Once the complete first candidate is written, run `finalize` directly. Its first gate is showcase validation; successful first drafts need no separate pre-validation. Keep the candidate unchanged while the command runs:
    
       ```bash
       node bin/archify.mjs finalize <type> <candidate.json> <output.html> --quality showcase --json
       ```
    
       For a repository-backed candidate, include evidence on the first draft and use the complete first command: `node bin/archify.mjs finalize <type> <candidate.json> <output.html> --repo-root <repo-root> --quality showcase --json`.
    
       A passing receipt proves the included `validate`, `deliver`, strict `check`, and real-browser `browser-check` gates passed. Use its compact summary; run standalone commands only for a separate request or focused failure diagnosis.
    
    5. A non-zero exit is never success. Read compact stdout or `evidence.summaryReceipt`, then [repair the failed gate](references/delivery-contract.md#failed-finalize-and-candidate-repair), including its repair limit. Preserve requested meaning and source evidence. For several tangled Architecture routes, read [Architecture layout repair](references/architecture-layout-repair.md); for measured field or geometry failures, read [Authoring contract](references/authoring-contract.md). Edit the connected neighborhood and rerun the complete `finalize` command from step 4.
    
    ## Update awareness
    
    `finalize` and standalone `deliver` include `update` in their receipts. Do not run a separate check for the same delivery. If `update.noticeRequired` is true, read `references/update-awareness.md` and keep one update line in your final response to the user, even after a quality gate fails. For a task with several diagrams, mention the update once in the final response. Snooze or ignore a reminder only when the user explicitly asks; never install or update on your own initiative.
    
    Before the first candidate, use the authoring references and relevant repository source, not Archify implementation or tests. Inspect Archify implementation if diagnostics remain unactionable after focused repairs.
    
    ## Type router
    
    | Type | Use for | Schema | Example |
    |---|---|---|---|
    | `architecture` | Components, services, cloud/security boundaries, infrastructure | `schemas/architecture.schema.json` | System descriptions, services, libraries, and CLI repos: `examples/web-app.architecture.json`; deployment repos: `examples/production-deployment.architecture.json` |
    | `workflow` | Processes, approval gates, tool calls, runbooks, CI/CD | `schemas/workflow.schema.json` | `examples/agent-tool-call.workflow.json` |
    | `sequence` | API call chains, request lifecycles, async traces, returns | `schemas/sequence.schema.json` | `examples/cache-miss-request.sequence.json` |
    | `dataflow` | Pipelines, ETL/ELT, lineage, governance, consumers | `schemas/dataflow.schema.json` | `examples/product-analytics.dataflow.json` |
    | `lifecycle` | State/status transitions, retries, waiting and terminal states | `schemas/lifecycle.schema.json` | `examples/deployment-release.lifecycle.json` |
    
    When ambiguous, run `node bin/archify.mjs guide "<scenario>" --json`. Scenario proof examples are structural references, not facts to copy.
    
    ## Mermaid input
    
    Read Mermaid for topology and meaning, then author fresh Archify JSON; do not mechanically render Mermaid styling.
    
    - `flowchart` / `graph` → `workflow`, or `architecture` for a component map.
    - `sequenceDiagram` → `sequence`; participants become semantic participants and arrows become messages.
    - `stateDiagram` → `lifecycle`; states and transitions retain meaning, not Mermaid style.
    
    ## Delivery
    
    Use the `finalize` command above for the first candidate and after a repair.
    
    `finalize` stops at the first non-passing gate. Its compact stdout and `<output-stem>.finalize-summary.json` are ordinary evidence. A passing run creates no screenshots and reports `visualReview: "not-requested"`.
    
    When a passing Architecture receipt reports `visualReviewRecommendation.signals.resolvedCrossovers`, copy the candidate aside and apply the hints in one edit that changes only node positions and sizes: every node, relationship (including its `from` and `to`), label, and source stays as it was. Rerun the complete `finalize` once with `--out-dir <folder>/review-2`, because the previous HTML already owns its browser evidence. If that run fails or reports more crossings, restore the copy and finalize it with `--out-dir <folder>/review-3`. Do not start a second placement round. Hints about extra bends alone are optional.
    
    When `layoutReviewRecommendation.action` is `inspect-sequence-width`, follow [Sequence width review](references/delivery-contract.md#sequence-width-review) before handing off a newly authored Sequence.
    
    Perceptual review is optional for ordinary generation, including a newly positioned Architecture. Use [Optional capture evidence](references/delivery-contract.md#optional-capture-evidence), with `--out-dir <folder>/visual-check`, when the user requests visual review, during development audits, or for a concrete route/browser concern. `visualReviewRecommendation` is advisory. Inspect captures before claiming visual quality; otherwise report automated checks only.
    
    Read [Delivery contract](references/delivery-contract.md) for failed gates, standalone commands, provenance/recovery, repeated delivery, exports, or opening. Recovery follows `deliver` → strict provenance `check` → `browser-check`; captures require strict provenance.
    
    For workflow viewport overflow, read [Workflow viewport repair](references/authoring-contract.md#workflow-viewport-repair) before the next layout edit.
    
    Report artifact checks, browser evidence, captures, and actual perceptual review as distinct results. For an explicitly requested immediate preview or active desktop loop, see [Optional opening](references/delivery-contract.md#optional-opening).
    
    ## Optional viewer capabilities
    
    `meta.animation: "trace"` is opt-in.
    
    Read `references/viewer-runtime.md` only when the user explicitly asks for Share Cards, Route/Reach cards, motion, deep links, presentation, search/focus, or another Viewer Runtime feature.
    
    ## Setup and fallback
    
    No install is required inside the skill package. For setup diagnosis, verify with:
    
    ```bash
    node bin/archify.mjs doctor
    node bin/archify.mjs demo <output-directory>
    ```
    
    When shell access is unavailable, hand-place architecture SVG into `assets/template.html`, use CSS semantic classes rather than inline colors, and follow the visual review contract in `references/delivery-contract.md`.
    
    ## Output
    
    Return the checked HTML as an absolute path, diagram type, validation summary, specification/artifact receipt, browser-evidence status, and truthful visual-review status. Do not claim success for a non-zero command or claim visual inspection you did not perform.
    
  • THIRD_PARTY_NOTICES.md 5.1 KB
    # Third-party notices
    
    Archify includes optional vector data for third-party brand marks. These marks
    are provided only to identify technologies and services in user-authored
    diagrams. Their inclusion does not imply sponsorship, endorsement, partnership,
    or affiliation with Archify.
    
    The Archify MIT license applies to Archify's own code and content. It does not
    replace the copyright licenses, trademark policies, or brand guidelines that
    apply to third-party marks. Users are responsible for confirming that their
    particular use is permitted.
    
    ## Simple Icons
    
    Most of the built-in vector paths and their metadata were generated from
    [Simple Icons 16.28.0](https://github.com/simple-icons/simple-icons/tree/16.28.0).
    Simple Icons makes its collection work available under
    [CC0 1.0 Universal](https://github.com/simple-icons/simple-icons/blob/16.28.0/LICENSE.md).
    
    As Simple Icons explains in its
    [disclaimer](https://github.com/simple-icons/simple-icons/blob/16.28.0/DISCLAIMER.md),
    CC0 for the collection does not mean that every underlying icon is CC0. License
    and brand-guideline metadata may be incomplete or change over time. The absence
    of an individual license entry is not a grant of permission.
    
    Archify embeds the selected icons as vector-path data and may render them in a
    user-selected color. The following individual licenses were recorded in the
    pinned Simple Icons 16.28.0 metadata:
    
    | Mark | Recorded source | Recorded license | Archify treatment |
    |---|---|---|---|
    | Angular | [Angular press kit](https://angular.dev/press-kit) | [`CC-BY-4.0`](https://creativecommons.org/licenses/by/4.0/) | Embedded as vector-path data; color may be changed by the authored diagram. |
    | Apache Airflow | [Apache logos](https://apache.org/logos) | [`Apache-2.0`](https://www.apache.org/licenses/LICENSE-2.0) | Embedded as vector-path data; Apache trademarks remain subject to the [ASF trademark policy](https://www.apache.org/foundation/marks/). |
    | Apache Kafka | [Apache logos](https://apache.org/logos) | [`Apache-2.0`](https://www.apache.org/licenses/LICENSE-2.0) | Embedded as vector-path data; Apache trademarks remain subject to the [ASF trademark policy](https://www.apache.org/foundation/marks/). |
    | .NET | [.NET brand repository](https://github.com/dotnet/brand/blob/c7d0f51b8ec59531332d05fb27a5b758a7a3d689/logo/dotnet-logo.svg) | [`CC0-1.0`](https://creativecommons.org/publicdomain/zero/1.0/) | Embedded as vector-path data; color may be changed by the authored diagram. |
    | JavaScript | [JS community logo](https://github.com/voodootikigod/logo.js/blob/1544bdeed6d618a6cfe4f0650d04ab8d9cfa76d9/js.svg) | [`MIT`](https://github.com/voodootikigod/logo.js/blob/1544bdeed6d618a6cfe4f0650d04ab8d9cfa76d9/LICENSE) | Embedded as vector-path data; color may be changed by the authored diagram. |
    | Jenkins | [Jenkins artwork source](https://get.jenkins.io/art/) | [`CC-BY-SA-3.0`](https://creativecommons.org/licenses/by-sa/3.0/) | Embedded as vector-path data; color may be changed by the authored diagram. Jenkins retains its trademark rights. |
    | Rust | [Rust project](https://www.rust-lang.org) | [`CC-BY-SA-4.0`](https://creativecommons.org/licenses/by-sa/4.0/) | Embedded as vector-path data; color may be changed by the authored diagram. See the [Rust media guide](https://www.rust-lang.org/policies/media-guide). |
    | Vue.js | [Vue logo source](https://github.com/vuejs/art/blob/a1c78b74569b70a25300925b4eacfefcc143b8f6/logo.svg) | [`CC-BY-NC-SA-4.0`](https://creativecommons.org/licenses/by-nc-sa/4.0/) | Embedded as vector-path data; color may be changed by the authored diagram. The non-commercial and share-alike conditions remain applicable; see the [Vue artwork terms](https://github.com/vuejs/art/blob/a1c78b74569b70a25300925b4eacfefcc143b8f6/README.md). |
    
    The source, guideline, and known license fields for every packaged mark are
    preserved in `renderers/shared/generated-brand-marks.mjs`.
    
    ## OpenAI mark
    
    The OpenAI vector path is recorded from the
    [OpenAI brand guidelines](https://openai.com/brand/), not from Simple Icons.
    Use remains subject to those current guidelines and any applicable trademark
    rights. Its inclusion does not state or imply endorsement by OpenAI.
    
    ## JetBrains Mono
    
    Delivered Archify viewer artifacts embed the JetBrains Mono variable font
    subsets served by Google Fonts. For characters covered by these subsets, font
    selection does not depend on a network request or a locally installed copy.
    Uncovered characters (including CJK) still use the system fallback stack;
    browser and operating-system rasterization can differ.
    JetBrains Mono is maintained at
    [github.com/JetBrains/JetBrainsMono](https://github.com/JetBrains/JetBrainsMono)
    and is distributed under the SIL Open Font License 1.1. The complete license
    text is preserved in `assets/JetBrainsMono-OFL.txt` in the packaged Skill and
    in the font CSS carried by standalone HTML and SVG exports.
    
    ## No additional rights granted
    
    Brand names, logos, and trademarks remain the property of their respective
    owners. This notice records provenance and known terms; it does not grant rights
    that Archify does not hold, and it does not state that every packaged mark has
    been cleared for every commercial, promotional, or redistributive use.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related