Claude Skill

archify

Default Navin skill for architecture and technical diagrams. Create polished, validated architecture, workflow, sequence, data-flow, and lifecycle diagrams as explorable HTML with inline SVG (PNG/SVG/WebM export). Use for system architecture, infrastructure topology, PPT/deck dia

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

Full trust report

Download navinspire-ia-navin-navin_skills_archify-e9c73a3.zip · 1131 KB
Part of navinspire-ia/navin — 182 skills

Install

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

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

Skill manifest

Archify (Navin default for architecture)

Bundled from tt-a1i/archify (MIT, v2.16). This is the default skill whenever Navin must draw or explain a system: architecture, sequence, workflow, data-flow, state/lifecycle, a diagram in a PPT, a tender / RFP technical answer, a Markdown plan, or a code explanation.

Navin defaults

  • Preloaded on /studio, /tenders, /blueprint, and the Documents desk. Follow this file; do not invent Mermaid-only dumps as the deliverable.
  • CLI from a Navin checkout: node navin/skills/archify/bin/archify.mjs. In a bound workspace, skills/archify/bin/archify.mjs maps to this folder.
  • Skip scripts/check-update.mjs (vendored snapshot; do not phone home).
  • No unicode em dashes or en dashes in authored labels. Use a hyphen or rephrase.
  • PPT: deliver HTML, export PNG/SVG, place the export on the slide. Surrounding titles and bullets stay editable text.
  • Tenders: architecture, methodology and sequence diagrams go in the technical answer.
  • Plans and explanations: when the Markdown describes a system, include an Archify HTML path plus a one-line caption.

Create a self-contained, interactive HTML diagram from a small typed JSON specification. Static output is the default; enable motion only when the user asks for a demo or presentation.

Fast authoring path

Use this bounded path for ordinary generation. Do not read the optional Viewer Runtime reference unless the user asks about those features.

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

  2. Read one matching schema in schemas/, schemas/common.schema.json, and one matching JSON example in examples/. Read only those files. Fresh authorship means new stable IDs, domain wording, and layout; use the example for field shape, not facts. New workflow sources use schema_version: 2 and its readable layout contract; keep schema_version: 1 only when preserving an existing workflow's fixed geometry. When real product identity matters, query node bin/archify.mjs brands "<name>" --json; read references/brand-marks.md only for an unknown brand with a user-provided URL.

  3. Artifact first: the next tool action must write the candidate. Write the candidate before inspecting renderer internals. Do not plan exact coordinates in prose. Start with one clear main path, short side branches, sparse labels, and at most 12 primary nodes. Set meta.quality_profile to "showcase" unless the user explicitly requests a dense standard map. Start with automatic routes and labels. Do not add via, channelX, channelY, or labelAt before a diagnostic calls for one; apply at most one diagnosed geometry control per repair.

  4. Validate after every candidate edit and immediately before handoff:

    node bin/archify.mjs validate <type> <candidate.json> --quality showcase --json
    

    A receipt with only 4 artifact checks is basic validation, never showcase acceptance. A showcase pass must report all 9 artifact checks with 0 composition errors and 0 warnings. If the candidate omits or misspells the exact meta.quality_profile field, fix it before geometry. For a workflow v2 geometry diagnosis, run node bin/archify.mjs validate workflow <candidate.json> --layout-json and use the stable compiler receipt; solver internals are not authoring controls. A passing final validation freezes the candidate: never edit it afterward.

  5. For a delivered HTML, deliver is the final acceptance command:

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

    A non-zero exit can never be described as success. A failed delivery preserves any previous output, so do not run visual-check on that path: it would inspect the stale last-good artifact, not the failed candidate. If validation fails, change only the diagnosed subject, verify evidence, choose from supportedFixes, and rerun. Continue focused correction while the objective error count reaches a new minimum. If two consecutive rounds do not improve that best count, stop and report the unresolved diagnostics truthfully.

Update awareness

After the first candidate exists, run the packaged checker scripts/check-update.mjs once with Node and continue the requested workflow. If the command cannot run, continue without mentioning the check.

  • For silent, continue without mentioning the update check.
  • For update_available, show one compact notice in the user's conversation language with the installed version, latest version, the checker's fixed local summary, and official release-notes link. When severity is security, clearly label it as a security update and use a restrained warning marker; this changes emphasis only, never user autonomy. Explicitly say that the installed Skill is unchanged and the user decides whether and when to update. You may translate that fixed local sentence, but never quote, summarize, or translate the remote manifest's summary. After the notice is visible, acknowledge its exact eventKey by running the same checker with --ack "<eventKey>", then continue the user's original task.

The notice is information, not permission. Keep the installed version unchanged; this v0.1 workflow never downloads, installs, or executes an update, and silence is never consent.

Do not read renderers/shared/geometry.mjs, renderer source, validator source, tests, or benchmarks before the first candidate. Inspect implementation only for an unsupported internal diagnostic or after two focused repairs fail.

Workflow note: use schema v2 for new workflows; preserve schema v1 when an existing source needs fixed legacy geometry. Keep semantic edge labels and act on the compiler diagnostic. The canonical layout, pin, migration, and receipt contract is in renderers/workflow/README.md.

Lifecycle note: phase columns 0..4 occupy the main rail; event/terminal column N in 0..2 aligns exactly beneath main column N + 2. A recoverable state uses type: "failure" plus a real transition back to the active state.

Type router

Type Use for
architecture Components, services, cloud/security boundaries, infrastructure
workflow Processes, approval gates, tool calls, runbooks, CI/CD
sequence API call chains, request lifecycles, async traces, returns
dataflow Pipelines, ETL/ELT, lineage, governance, consumers
lifecycle State/status transitions, retries, waiting and terminal states

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.

Authoring invariants

  • One obvious main path; side branches leave the nearest main-path node. Remove low-value edges before adding routing controls.
  • Omit meta.visual_preset by default so every diagram opens in classic, regardless of whether its resolved color mode is light or dark. Color mode and visual preset are independent: switching Light / Dark must preserve the current preset. Set signal-flow, blueprint, or editorial only when the user explicitly requests that visual style.
  • Omit meta.subtitle by default. Never invent a subtitle that restates the title, nodes, or cards; include one short supporting line only when the user explicitly asks for it.
  • Treat the standalone desktop viewer as a first-screen artifact by default, not a shallow strip. Generate one responsive artifact for laptops and external displays-never device-specific HTML or alternate topology. The viewer may adapt only the outer reading width from the live viewport height; it must preserve the authored SVG/viewBox, proportions, semantic geometry, and normal document flow. On a wide or tall desktop, use enough authored vertical rhythm that the diagram panel and its necessary conclusion cards occupy the screen as a balanced whole; runtime scaling cannot repair an over-compressed Y layout or an undersized explicit meta.viewBox. Before handoff, open the real HTML at 1440×900, 1600×1000, and 1920×1080; additionally check 2048×1320 whenever the composition is intended for a large desktop display. Require document.documentElement.scrollWidth <= window.innerWidth and scrollHeight <= window.innerHeight at every checked size, while visually checking that the diagram remains comfortably readable and vertically balanced at the largest checked viewport. Repair overflow by removing only genuinely redundant content or compacting spacing before shrinking nodes, labels, or the main panel. If the largest viewport still has a conspicuous empty lower band at the viewer's width cap, redistribute authored Y positions and increase the viewBox height proportionally; do not add filler copy or decorative cards. Never counterfeit a pass with overflow: hidden, clipped content, an internal diagram scroller, stretched SVG height, or smaller typography. Narrow/mobile layouts may scroll vertically when containment requires it.
  • Omit meta.legend for the truthful auto default. When needed, use only mode: auto|all|hidden and renderer-supported entries.<kind>.label|visible; labels never change semantics.
  • Choose one primary authored language from an explicit user choice; otherwise follow the request or conversation's dominant language. meta.locale controls only renderer-owned Viewer UI: use "en" or "zh-CN" for the corresponding supported primary language. For every other language, omit meta.locale and explicitly disclose that the fixed Viewer UI and <html lang> fall back to English. The renderer never translates authored content. See references/authoring-contract.md for details.
  • Preserve exact product names, code identifiers, commands, protocols, API paths, and environment names. They may remain English inside localized copy, but never justify leaving the surrounding explanatory prose in another language.
  • Brand identity is optional and explicit. Put a canonical built-in ID in brand when the node names that real product. If no preset matches and the user supplied the official HTTP(S) URL, first run node bin/archify.mjs brands capture "<url>" --json, then author the returned digest-pinned brand object. Render and validate never perform an unpinned capture. Otherwise omit brand. Never infer a brand from a vague role such as "database", and never let a badge replace the semantic type, label, or relationship facts.
  • For sequence diagrams, omit meta.column_fit for the stable fixed layout. Set it to "spread" when a wide viewBox would otherwise leave unused horizontal space or when meaningful participant labels do not fit the fixed boxes; do not shorten semantic labels before trying spread.
  • Component types are frontend, backend, database, cloud, security, messagebus, and external; variants are default, emphasis, security, and dashed.
  • Relationship labels are semantic data. When one collides, move the label, adjust the route or spacing, then shorten the wording while preserving meaning. Omit only wording that is already fully implied by both endpoints and contains no protocol, action, direction, synchronous/asynchronous behavior, or cross-boundary mechanism. Preserve every meaningful label; deleting it is not a geometry 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 geometry repair.
  • Omit meta.engineering_profile by default. Region, cluster, and security boundary wording do not by themselves enable it. 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, must not remove the engineering profile merely to pass validation; repair the facts or report the diagnostics truthfully.
  • Spacing means clear gap, not center distance. For a relationship label, clear gap must exceed its measured mask width; follow the label-preserving repair order.
  • Automatic routes own their endpoint sides. A side is a direction contract: the first and final segment must leave/enter perpendicular to that side.
  • Automatic Port Spread is a default renderer behavior for architecture, workflow, data-flow, and lifecycle. It skips single relationships and explicit via, channelX, channelY, labelAt, or non-auto routes. Near parallel ports use an outside bridge so automatic routing cannot create a sub-8px segment or sub-16px interior turn. Architecture separately keeps unobstructed facing automatic ports (left/right or top/bottom) on one shared axis when their offset is under 16px and both ports retain corner clearance. If exactly one endpoint was spread, only the unshared endpoint may move onto that axis; if both endpoints were spread, keep the outside bridge so competing ports remain distinct.
  • Never accept an edge crossing an unrelated opaque node, an ambiguous shared corridor, or a relationship label masking another route.

Read references/authoring-contract.md only when you need field enums, spacing math, geometry repair rules, repository evidence, or mode-specific placement.

Delivery

Use validate during repair and deliver once for final acceptance. Delivery freezes the exact specification bytes into a private same-directory snapshot, renders and checks that snapshot, atomically commits the HTML, and reports SHA-256 plus byte counts for both specification and artifact. This is deterministic artifact evidence; it does not exercise the Viewer in a browser.

After delivery, collect bounded desktop evidence without modifying or rerendering the trusted HTML:

node bin/archify.mjs visual-check <output.html> --json

visual-check collects automated browser evidence from the exact delivered HTML without modifying or rerendering it. Its machine-readable measurements and screenshots do not approve perceptual polish. Follow references/delivery-contract.md for the canonical receipt fields, coverage, sidecars, exit behavior, and supplementary manual-record requirements.

Keep the three claims separate: deliver proves deterministic artifact checks, visual-check proves bounded behavior in a real browser, and perceptual visual review requires an actual human or image-capable reviewer. Report browser evidence and perceptual review independently. An unconstrained glance can support only perceptual review; use the canonical delivery contract when recording supplementary manual browser work or handling an environmental failure.

Add --open only when the user wants an immediate local preview. For an active desktop authoring loop, the optional command is:

node bin/archify.mjs preview <type> <input>.json <output>.html --quality showcase

Never start preview by default. Read references/delivery-contract.md when using preview, repository evidence, export receipts, visual review, or post-commit opening.

Optional viewer capabilities

Generated HTML already contains theme switching, pan/zoom, search, focus, relationship tracing, semantic views, presentation, and truthful exports. These are reader capabilities, not extra authoring work. meta.animation: "trace" is opt-in; meta.views is optional and should contain at most five curated chapters.

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

Setup and fallback

No install is required inside the skill package. 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 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 (navin)
  • assets
    • template.html 662.4 KB · in bundle
  • bin
    • archify.mjs 69.9 KB · in bundle
    • open-artifact.mjs 2.2 KB · in bundle
    • preview.mjs 23 KB · in bundle
    • visual-check.mjs 32.6 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 70.6 KB · in bundle
  • examples
    • agent-run.lifecycle.json 4.3 KB
      {
        "schema_version": 1,
        "diagram_type": "lifecycle",
        "meta": {
          "title": "Agent Run Lifecycle",
          "output": "examples/lifecycle-agent-run.html",
          "viewBox": [980, 660],
          "animation": "trace",
          "quality_profile": "showcase",
          "views": [
            { "id": "main-lifecycle", "label": "Main lifecycle", "focus": ["queued", "planning", "executing", "reviewing", "completed"], "note": "Follow the ordered phases from accepted request to completed response." },
            { "id": "human-waits", "label": "Human and input waits", "focus": ["executing", "approval", "reviewing", "blocked"], "note": "See where the run pauses without becoming terminal." },
            { "id": "recovery-and-exits", "label": "Recovery and terminal exits", "focus": ["executing", "failed", "blocked", "cancelled", "expired"], "note": "Separate retryable failure from cancellation and expiry." }
          ]
        },
        "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",
            "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 remain non-terminal until cancellation or expiry"
            ]
          },
          {
            "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.6 KB
      {
        "schema_version": 2,
        "diagram_type": "workflow",
        "meta": {
          "title": "Agent Tool Call Workflow",
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase",
          "views": [
            {
              "id": "happy-path",
              "label": "Request to result",
              "focus": ["user", "chat", "planner", "router", "approval", "tool", "external", "final"],
              "note": "Follow the successful request from user intent to the final reply."
            },
            {
              "id": "safety-gate",
              "label": "Policy and recovery",
              "focus": ["router", "approval", "blocked", "retry"],
              "note": "See where risky work stops, waits for consent, or returns for revision."
            },
            {
              "id": "evidence-loop",
              "label": "Evidence and memory",
              "focus": ["external", "store", "trace"],
              "note": "Isolate the durable trace and context path behind the visible answer."
            }
          ],
          "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 4.3 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",
          "views": [
            { "id": "accept-and-enqueue", "label": "Accept without blocking", "focus": ["client", "api", "queue"], "note": "The API acknowledges quickly after durable enqueue." },
            { "id": "work-and-retry", "label": "Background work and retry", "focus": ["queue", "worker", "provider"], "note": "Timeouts re-enter the queue instead of holding the original request open." },
            { "id": "observe-final-state", "label": "Observe final consistency", "focus": ["worker", "store", "notify", "client", "api"], "note": "Webhook delivery is primary; polling remains a bounded fallback." }
          ]
        },
        "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 3.2 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Brand-aware AI delivery",
          "quality_profile": "showcase",
          "viewBox": [1120, 640],
          "views": [
            {
              "id": "delivery-path",
              "label": "Delivery path",
              "focus": ["request", "claude", "github", "container", "edge", "customer"],
              "note": "Follow one delivery from the request through the model, repository, container, and edge."
            },
            {
              "id": "business-data",
              "label": "Business and data",
              "focus": ["container", "database", "billing"],
              "note": "Inspect durable state and billing without losing the main delivery path."
            }
          ]
        },
        "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 4.2 KB
      {
        "schema_version": 1,
        "diagram_type": "sequence",
        "meta": {
          "title": "Cache Miss Request Sequence",
          "output": "examples/sequence-cache-miss-request.html",
          "viewBox": [820, 760],
          "animation": "trace",
          "quality_profile": "showcase",
          "views": [
            { "id": "request-and-auth", "label": "Request and identity", "focus": ["user", "web", "api", "auth"], "note": "Follow the user request through the authentication check." },
            { "id": "cache-fallback", "label": "Cache fallback", "focus": ["api", "redis", "db"], "note": "See the cache miss and the source-of-truth query it triggers." },
            { "id": "return-and-trace", "label": "Return and trace", "focus": ["db", "api", "redis", "trace", "web", "user"], "note": "Separate response latency from the non-blocking observability write." }
          ]
        },
        "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": [
          { "id": "open-page", "from": "user", "to": "web", "y": 185, "label": "open page", "variant": "default" },
          { "id": "dashboard-request", "from": "web", "to": "api", "y": 228, "label": "GET /dashboard", "variant": "emphasis" },
          { "id": "verify-jwt", "from": "api", "to": "auth", "y": 270, "label": "verify JWT", "variant": "security" },
          { "id": "auth-claims", "from": "auth", "to": "api", "y": 305, "label": "claims ok", "variant": "return" },
          { "id": "cache-read", "from": "api", "to": "redis", "y": 354, "label": "read cache", "variant": "default" },
          { "id": "cache-miss", "from": "redis", "to": "api", "y": 391, "label": "miss", "variant": "return" },
          { "id": "profile-query", "from": "api", "to": "db", "y": 443, "label": "query profile + metrics", "variant": "emphasis" },
          { "id": "profile-rows", "from": "db", "to": "api", "y": 489, "label": "rows", "variant": "return" },
          { "id": "cache-write", "from": "api", "to": "redis", "y": 536, "label": "set cache", "variant": "dashed" },
          { "id": "trace-emit", "from": "api", "to": "trace", "y": 580, "label": "emit trace", "variant": "dashed" },
          { "id": "dashboard-response", "from": "api", "to": "web", "y": 625, "label": "200 JSON", "variant": "return" },
          { "id": "page-render", "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"
            ]
          }
        ]
      }
      
    • checkout-platform.base.architecture.json 2.2 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Checkout Platform - Baseline",
          "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.3 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Checkout Platform - Fraud Gate",
          "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 703.5 KB · in bundle
    • deployment-release.lifecycle.json 4.2 KB
      {
        "schema_version": 1,
        "diagram_type": "lifecycle",
        "meta": {
          "title": "Deployment Release Lifecycle",
          "output": "examples/deployment-release.html",
          "viewBox": [980, 680],
          "animation": "trace",
          "visual_preset": "signal-flow",
          "quality_profile": "showcase",
          "views": [
            { "id": "promotion-rail", "label": "Promotion rail", "focus": ["queued", "building", "verifying", "ready", "live"], "note": "Follow the deployment object from accepted change to healthy production." },
            { "id": "approval-gate", "label": "Approval gate", "focus": ["verifying", "approval", "cancelled", "ready"], "note": "Approval pauses promotion and can terminate the release cleanly." },
            { "id": "rollback-outcomes", "label": "Rollback outcomes", "focus": ["ready", "rollback", "failed", "live", "paused", "rolled_back"], "note": "Separate pre-promotion failure from post-promotion health regression." }
          ]
        },
        "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": 0, "tag": "pause" },
          { "id": "rollback", "type": "active", "label": "Rolling Back", "sublabel": "last good image", "lane": "recovery", "col": 1, "tag": "automatic" },
          { "id": "paused", "type": "waiting", "label": "Health Paused", "sublabel": "SLO regression", "lane": "waiting", "col": 2, "tag": "observe" },
          { "id": "cancelled", "type": "failure", "label": "Cancelled", "sublabel": "approval denied", "lane": "terminal", "col": 0, "tag": "terminal" },
          { "id": "failed", "type": "failure", "label": "Failed", "sublabel": "rollback failed", "lane": "terminal", "col": 1, "tag": "terminal" },
          { "id": "rolled_back", "type": "success", "label": "Rolled Back", "sublabel": "service restored", "lane": "terminal", "col": 2, "tag": "terminal" }
        ],
        "transitions": [
          { "from": "verifying", "to": "approval", "variant": "security", "route": "straight", "fromSide": "bottom", "toSide": "top" },
          { "from": "approval", "to": "cancelled", "variant": "security", "route": "straight", "fromSide": "bottom", "toSide": "top" },
          { "from": "ready", "to": "rollback", "variant": "security", "route": "straight", "fromSide": "bottom", "toSide": "top" },
          { "from": "rollback", "to": "failed", "variant": "security", "route": "straight", "fromSide": "bottom", "toSide": "top" },
          { "from": "live", "to": "paused", "variant": "dashed", "route": "straight", "fromSide": "bottom", "toSide": "top" },
          { "from": "paused", "to": "rolled_back", "variant": "emphasis", "route": "straight", "fromSide": "bottom", "toSide": "top" }
        ],
        "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 5.3 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",
          "views": [
            { "id": "order-transit", "label": "Order event transit", "focus": ["checkout", "orders", "validate", "state", "fulfillment"], "note": "Follow an order from producer through ordered processing to fulfillment." },
            { "id": "payment-transit", "label": "Payment event transit", "focus": ["billing", "payments", "enrich", "state", "analytics"], "note": "Track payment facts into the shared materialized state and analytics." },
            { "id": "failure-and-replay", "label": "Failure and replay", "focus": ["validate", "enrich", "dlq", "replay", "ops"], "note": "Isolate dead letters, operator review, and controlled replay ownership." }
          ]
        },
        "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"] }
        ]
      }
      
    • incident-response.workflow.json 5.2 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",
          "views": [
            { "id": "detect-and-triage", "label": "Detect and establish command", "focus": ["alert", "page", "triage", "declare"], "note": "Follow the first minutes from signal to an owned incident." },
            { "id": "mitigate-and-verify", "label": "Mitigate and prove recovery", "focus": ["triage", "contain", "recover", "verify", "close"], "note": "Keep mitigation separate from the evidence required to close." },
            { "id": "escalate-and-communicate", "label": "Escalation and communication", "focus": ["declare", "escalate", "update", "rollback"], "note": "See who is paged, what stakeholders hear, and when rollback begins." }
          ]
        },
        "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 697.3 KB · in bundle
    • product-analytics.dataflow.json 5.5 KB
      {
        "schema_version": 1,
        "diagram_type": "dataflow",
        "meta": {
          "title": "Product Analytics Data Flow",
          "output": "examples/dataflow-product-analytics.html",
          "viewBox": [1080, 760],
          "animation": "trace",
          "quality_profile": "showcase",
          "views": [
            { "id": "collection-path", "label": "Collection path", "focus": ["web", "mobile", "edge", "stream"], "note": "Follow product events from clients into the ordered event stream." },
            { "id": "consent-boundary", "label": "Consent and PII", "focus": ["edge", "consent", "pii"], "note": "Isolate the policy gate and restricted identity store." },
            { "id": "analytics-consumers", "label": "Curated consumers", "focus": ["stream", "warehouse", "dashboard", "features", "model"], "note": "See curated facts, dashboards, and the derived feature path." }
          ]
        },
        "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": [
          { "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", "route": "straight", "labelAt": [638, 372] },
          { "id": "daily-aggregates", "from": "warehouse", "to": "features", "label": "daily aggregates", "classification": "batch", "variant": "dashed", "fromSide": "bottom", "toSide": "top", "route": "straight", "labelAt": [745, 496] },
          { "id": "metrics-query", "from": "warehouse", "to": "dashboard", "label": "metrics SQL", "classification": "read-only", "variant": "default", "fromSide": "right", "toSide": "left", "via": [[852, 385], [852, 271]], "labelAt": [830, 326] },
          { "id": "feature-vectors", "from": "features", "to": "model", "label": "feature vectors", "classification": "derived", "variant": "dashed", "route": "straight", "labelAt": [852, 598] },
          { "id": "restricted-join", "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 5.3 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",
          "views": [
            {
              "id": "request-boundary",
              "label": "Request crosses the edge",
              "focus": ["clients", "edge", "gateway", "api_a", "api_b"],
              "note": "Follow public traffic into the private application network."
            },
            {
              "id": "state-ownership",
              "label": "State and ownership",
              "focus": ["api_a", "api_b", "redis", "postgres", "replica"],
              "note": "Separate stateless platform workloads from data-team-owned state."
            },
            {
              "id": "async-operations",
              "label": "Async and operations",
              "focus": ["api_b", "events", "worker", "audit", "observability"],
              "note": "See the asynchronous work and the evidence it emits."
            }
          ]
        },
        "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 5 KB
      {
        "schema_version": 1,
        "diagram_type": "workflow",
        "meta": {
          "title": "Release Delivery Workflow",
          "output": "examples/release-delivery.html",
          "animation": "trace",
          "quality_profile": "showcase",
          "views": [
            { "id": "commit-to-checks", "label": "Commit to green build", "focus": ["commit", "pull_request", "build", "checks"], "note": "Follow the change through reproducible build and blocking quality gates." },
            { "id": "approval-to-production", "label": "Approve and promote", "focus": ["checks", "approval", "deploy", "verify_prod", "announce"], "note": "See who authorizes production and how success is verified." },
            { "id": "rollback-path", "label": "Failure and rollback", "focus": ["checks", "failed", "verify_prod", "rollback", "deploy"], "note": "Isolate the two places where delivery stops or reverses safely." }
          ]
        },
        "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 700 KB · in bundle
    • web-app-rendered.html 698.4 KB · in bundle
    • web-app.architecture.json 3.7 KB
      {
        "schema_version": 1,
        "diagram_type": "architecture",
        "meta": {
          "title": "Sample Web App",
          "output": "web-app-rendered.html",
          "quality_profile": "showcase",
          "views": [
            { "id": "request-path", "label": "Primary request path", "focus": ["users", "cdn", "lb", "api", "db"], "note": "Follow the primary customer request from the edge to durable state." },
            { "id": "identity-and-cache", "label": "Identity and cache", "focus": ["auth", "api", "cache"], "note": "Isolate authentication and the read-through cache beside the request path." },
            { "id": "async-work", "label": "Static and async work", "focus": ["cdn", "s3", "api", "queue", "worker"], "note": "See the two secondary paths without adding noise to the main request." }
          ]
        },
        "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 706 KB · in bundle
  • migrations
    • workflow-v2.mjs 9 KB · in bundle
  • recipes
    • scenarios.mjs 31.3 KB · in bundle
  • references
    • authoring-contract.md 11 KB
      # Authoring contract
      
      Read this reference only after the Fast authoring path calls for more detail. The schemas and examples remain authoritative.
      
      ## 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. Use the nearest matching example for structure, then 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).
      
      ## 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.
      For supported languages, always write the matching `meta.locale`: `"en"` for
      English or `"zh-CN"` for Simplified Chinese. 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,
      guided views, 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.
      
      For a requested language outside `en` and `zh-CN`, do not write an unsupported
      locale. 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.
      
      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
      
      - 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.
      - A side is a direction contract. The first and final route segment must be perpendicular and outward/inward in the named direction.
      - 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.
      - 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.
      
      ### Spacing and labels
      
      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.
      
      ### 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, and route rhythm.
      5. Fix label-to-node, label-to-label, then label-to-route clearance.
      
      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
      
      Use one left-to-right spine with short vertical branches. Prefer 6-12 primary components and 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.
      
      ### 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
      
      Main phases use columns `0..4`; event and terminal bands use columns `0..2`.
      Event/terminal column `N` aligns to the same x coordinate as main column
      `N + 2`. A recoverable failure needs a real transition back to an active state.
      A card or guided view saying “retry” is not topology.
      
      ## Repository evidence
      
      When an architecture 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 architecture-only and is accepted by architecture
      `render`, `validate`, `deliver`, `preview`, and `compare`; workflow, sequence,
      dataflow, and lifecycle reject it. Never infer runtime causality from file
      proximity or naming alone.
      
      ## 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.
      
    • brand-marks.md 2.1 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.
      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.
      
      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 7.9 KB
      # Delivery contract
      
      ## Validate and deliver
      
      Use `validate` after every candidate edit. Use final atomic 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`. Renderer, checker, receipt, or commit failure exits non-zero, removes private state, preserves the previous trusted artifact, and never invokes an opener.
      
      Run `visual-check` only after `deliver` exits zero for the current candidate. If
      delivery fails and the output path already exists, that path still names the
      previous trusted artifact; running `visual-check` then would measure and capture
      stale output, not the rejected candidate. Report the delivery diagnostics and
      repair the source before collecting new visual evidence.
      
      The delivery interface exposes three separate claims:
      
      1. `deliver` proves deterministic artifact checks and byte identity.
      2. `visual-check` collects automated browser evidence from the exact artifact.
      3. Perceptual visual review records a human or image-capable reviewer's judgment.
      
      Passing one claim never implies either of the others. Never claim that the deterministic receipt includes visual review. It does not include browser evidence either.
      
      ## Automated browser evidence
      
      After delivery, inspect the exact trusted HTML without rerendering or modifying
      it:
      
      ```bash
      node bin/archify.mjs visual-check <output.html> --json
      ```
      
      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, then captures light/dark screenshots at 1440×900 and 2048×1320. It
      writes four PNG sidecars, one relative-path HTML contact sheet, and one JSON
      receipt beside the artifact. The receipt binds the source artifact SHA-256 and
      byte count, identifies `evidenceKind: "automated-browser"`, records READ plus
      Still runtime state, and always reports `visualReview: "pending"`; automated
      browser evidence cannot claim perceptual review.
      
      `browser_evidence` in the handoff records only the outcome of this automated command:
      
      - `passed` maps from exit 0 and receipt `status: "pass"` only after every required measurement and capture completes and passes.
      - `failed` maps from exit 1 and receipt `status: "fail"` when the inspection finds a defect, the command fails, or a runtime/capture 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 or capture failures leave incomplete evidence and must not be normalized to `skipped`. Failed or skipped capture runs remove stale
      image/contact-sheet sidecars rather than presenting prior evidence as current.
      They do not invalidate an already successful deterministic delivery, and they
      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.
      
      ## Optional opening
      
      Add `--open` only when the user wants an immediate local preview. It runs after that atomic commit, uses one argument-array OS opener with a five-second bound, and records `open.status`. 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. Server state, port, source path, diagnostics, error text, and reload tokens must never enter the generated artifact or any export.
      
      ## Perceptual delivery gate
      
      Automated validation and browser evidence cannot prove visual polish. After deterministic delivery, inspect the actual HTML in a capable browser or render the evidence screenshots with an image reader. Check both themes when changed, the default READ view, line crossings/corridors, label masks, node/card fit, focus/search/passport closure, and export cleanliness.
      
      For the default standalone desktop viewer, measure 1440×900, 1600×1000, and 1920×1080. When the artifact is intended for a large desktop display, also measure 2048×1320. A first-screen pass requires `document.documentElement.scrollWidth <= window.innerWidth` and `scrollHeight <= window.innerHeight` at every checked size. 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. If a desktop viewport overflows, 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.
      
      A manual browser record is supplementary to the automated status. Reproducing the same coverage requires all four exact viewport measurements, both endpoint themes, and an artifact-bound record of the inspected SHA-256 and byte count. It never changes `browser_evidence`: when Chrome/Chromium is unavailable, that status remains `skipped` even when the manual browser record is complete and `visual_review: passed`; an automated `failed` result likewise remains `failed`. An unconstrained browser glance can support perceptual review only.
      
      Report exactly one truthful status:
      
      - `visual_review: passed` - only after inspecting the rendered artifact.
      - `visual_review: skipped (image reader unavailable)` - when no capable visual surface exists.
      - `visual_review: failed` - with the concrete visible defect.
      
      Use `correction_rounds: 0`, `correction_rounds: 1`, or `correction_rounds: 2`; never exceed a maximum of two focused correction rounds. Never report `visual_review: passed` without inspecting the artifact.
      
      If visual review changes the candidate, validation and delivery must run again because the prior frozen specification receipt is 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: passed|skipped (image reader unavailable)|failed
      correction_rounds: 0|1|2
      ```
      
      Derive `browser_evidence` only from the latest artifact-bound `visual-check` receipt. Record any 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.
      
    • viewer-runtime.md 4.1 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, story, 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.
      
      ## Guided views and story
      
      `meta.views` may define at most five curated chapters using stable node IDs. The Named Chapter Rail, Chapter Delta Preview, Story Beat Navigator, Story Follow Camera, Story Director Strip, Story Horizon, and Shareable Story Moment links all derive from that one authored array; none owns parallel topology or layout.
      
      Story transitions classify only the exact relationship between adjacent authored stops: forward, reverse, multiple, or grouped/no direct link. Never infer a transitive edge, verb, causality, or runtime behavior from proximity, kinds, or story order. Playback is reader-started, bounded, stale-safe, and motion-governed.
      
      ## 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, story, camera, radar, presentation, motion ownership, and temporary overlays-must be removed from canonical export.
      
      ### Share Card
      
      The optional 1200×630 Share Card PNG is for README, release, social, or launch previews. It uses the current theme and visual preset, contains the complete canonical diagram without cropping, and never claims validation. Copy Share Card reuses the same canonical PNG when clipboard image writes are supported.
      
      ### 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
      • render-architecture.mjs 44.4 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 `meta.output` from the JSON file
        or falls back to `dataflow.html` in the current working directory.
        
        ## Input
        
        Data-flow JSON files must set:
        
        ```json
        {
          "schema_version": 1,
          "diagram_type": "dataflow",
          "meta": {
            "title": "Product Analytics Data Flow",
            "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 20.7 KB · in bundle
    • lifecycle
      • README.md 5.1 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 `meta.output` from the JSON file
        or falls back to `lifecycle.html` in the current working directory.
        
        ## Input
        
        Lifecycle JSON files must set:
        
        ```json
        {
          "schema_version": 1,
          "diagram_type": "lifecycle",
          "meta": {
            "title": "Agent Run Lifecycle",
            "viewBox": [980, 660]
          },
          "lanes": [],
          "states": [],
          "transitions": [],
          "cards": []
        }
        ```
        
        Lane ids are semantic and reserved: a lane with id `main` is required and maps
        to the top phase band; `terminal` maps to the bottom outcome band; every other
        lane id (up to 4 lanes total) shares the single middle event band. The three
        band headers render from your lane labels - the middle band joins the labels of
        all event lanes with ` + `. A complete worked example lives at
        `archify/examples/agent-run.lifecycle.json`.
        
        The schema lives at:
        
        ```text
        archify/schemas/lifecycle.schema.json
        ```
        
        ## Legend
        
        The default legend derives kinds from `states[].type`. 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.
        
        ## Layout budget
        
        | 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).
        
        ## Design Rules
        
        - Treat lifecycle diagrams as a phase map, not a dense state-transition graph.
        - Put the primary lifecycle on one horizontal rail using the `main` lane.
        - 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.
        - Avoid diagonal and crossing lines. Terminal exits should drop vertically from
          their source event whenever possible.
        - 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 23.7 KB · in bundle
    • sequence
      • README.md 4.7 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 `meta.output` from the JSON file
        or falls back to `sequence.html` in the current working directory.
        
        ## Input
        
        Sequence JSON files must set:
        
        ```json
        {
          "schema_version": 1,
          "diagram_type": "sequence",
          "meta": {
            "title": "Cache Miss Request Sequence",
            "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.
        
        ## Layout budget
        
        | Constant | Value |
        |----------|-------|
        | viewBox | default `[920, 760]`; 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; 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 row | y = height − 54 |
        
        `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.
        
        ## 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 20.6 KB · in bundle
    • shared
      • brand-marks.mjs 22.1 KB · in bundle
      • cli.mjs 9.9 KB · in bundle
      • desktop-readability.mjs 1.1 KB · in bundle
      • diagnostics.mjs 4.5 KB · in bundle
      • engineering-profiles.mjs 6.8 KB · in bundle
      • generated-brand-marks.mjs 159.8 KB · in bundle
      • generated-validators.mjs 420.7 KB · in bundle
      • geometry.mjs 55.8 KB · in bundle
      • i18n.mjs 47.1 KB · in bundle
      • layout-report.mjs 1015 B · in bundle
      • legend.mjs 8.4 KB · in bundle
      • output-path.mjs 10.4 KB · in bundle
      • repository-evidence.mjs 11.2 KB · in bundle
      • text-fit.mjs 2.1 KB · in bundle
      • utils.mjs 11.3 KB · in bundle
      • validator.mjs 3.4 KB · in bundle
    • workflow
      • README.md 10.1 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 `meta.output` from the JSON file
        or falls back to `workflow.html` in the current working directory.
        
        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"
          },
          "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.
        
        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 |
        
        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.
        
        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.
        - 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. 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 for fixed lane gaps.
        
      • render-workflow.mjs 1.1 KB · in bundle
      • workflow-compiler.mjs 167.4 KB · in bundle
      • workflow-migration-geometry.mjs 5.2 KB · in bundle
  • schemas
    • architecture.schema.json 6.5 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"],
            "properties": {
              "title": { "type": "string", "minLength": 1 },
              "locale": { "$ref": "common.schema.json#/$defs/locale" },
              "subtitle": { "type": "string" },
              "output": { "type": "string" },
              "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": {
                "type": "object",
                "additionalProperties": false,
                "required": ["url", "revision"],
                "properties": {
                  "url": {
                    "type": "string",
                    "pattern": "^https://github\\.com/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+(?:\\.git)?/?$"
                  },
                  "revision": { "type": "string", "pattern": "^[a-fA-F0-9]{40}$" }
                }
              },
              "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" },
                "brand": { "$ref": "common.schema.json#/$defs/brandMark" },
                "sources": {
                  "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 }
                    }
                  }
                },
                "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 3 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": {
            "enum": ["en", "zh-CN"]
          },
          "animation": {
            "enum": ["trace", "none"]
          },
          "visualPreset": {
            "enum": ["classic", "signal-flow", "blueprint", "editorial"]
          },
          "qualityProfile": {
            "enum": ["standard", "showcase"]
          },
          "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"]
          },
          "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 }
              }
            }
          },
          "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 5.8 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"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "type": "string"
              },
              "animation": {
                "$ref": "common.schema.json#/$defs/animation"
              },
              "visual_preset": {
                "$ref": "common.schema.json#/$defs/visualPreset"
              },
              "quality_profile": {
                "$ref": "common.schema.json#/$defs/qualityProfile"
              },
              "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"
                },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "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.4 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": {
            "const": 1
          },
          "diagram_type": {
            "const": "lifecycle"
          },
          "meta": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "title"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "type": "string"
              },
              "animation": {
                "$ref": "common.schema.json#/$defs/animation"
              },
              "visual_preset": {
                "$ref": "common.schema.json#/$defs/visualPreset"
              },
              "quality_profile": {
                "$ref": "common.schema.json#/$defs/qualityProfile"
              },
              "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": 566
                  }
                ],
                "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"
                },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "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 11.2 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 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: "en" | "zh-CN"`. 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.
      Omitting it preserves legacy behavior and resolves to English. Unsupported
      locale values fail schema validation instead of being guessed or silently
      rewritten.
      `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.
      
      It may also include up to five guided `views`. Each view has a unique `id`, a
      reader-facing `label`, a non-empty `focus` list of existing semantic node IDs,
      and an optional short `note`.
      
      ### 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`.
      The other four diagram schemas keep `schema_version` pinned to `1`.
      
      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. 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` - the bounded renderer locale, `en` or `zh-CN`
      - `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 bounded, read-only reader paths accepted by `meta.views`
      - `cards` - the summary-card blocks rendered below the SVG
      
      Lifecycle state `type` is mode-specific (`start`/`active`/`waiting`/...) and
      stays in `lifecycle.schema.json`.
      
      ## 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.
      
      Architecture additionally supports opt-in, revision-pinned repository evidence.
      `meta.repository` names a public GitHub URL and full commit SHA; a component may
      carry one to three `sources` with repo-relative POSIX paths, optional line
      ranges, and optional labels. 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.5 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"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "type": "string"
              },
              "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"]
              },
              "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"
                },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                }
              }
            }
          },
          "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.5 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"
            ],
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1
              },
              "locale": {
                "$ref": "common.schema.json#/$defs/locale"
              },
              "subtitle": {
                "type": "string"
              },
              "output": {
                "type": "string"
              },
              "animation": {
                "enum": [
                  "trace",
                  "none"
                ]
              },
              "visual_preset": {
                "enum": [
                  "classic",
                  "signal-flow",
                  "blueprint",
                  "editorial"
                ]
              },
              "quality_profile": {
                "enum": [
                  "standard",
                  "showcase"
                ]
              },
              "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"
                },
                "brand": {
                  "$ref": "common.schema.json#/$defs/brandMark"
                },
                "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 31.7 KB · in bundle
    • check-update.mjs 55 KB · in bundle
    • generate-brand-marks.mjs 5 KB · in bundle
    • generate-validators.mjs 2.3 KB · in bundle
    • render-examples.mjs 1.2 KB · in bundle
    • update-contract.mjs 6.6 KB · in bundle
  • LICENSE 1.1 KB · in bundle
  • package.json 1.4 KB
    {
      "name": "archify",
      "version": "2.16.0",
      "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: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": "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.5"
      }
    }
    
  • skill-release.json 261 B
    {
      "schemaVersion": 1,
      "skillId": "archify",
      "channel": "stable",
      "version": "2.16.0",
      "source": {
        "repository": "https://github.com/tt-a1i/archify"
      },
      "updateManifestUrl": "https://tt-a1i.github.io/archify/skill-updates/archify/stable.json"
    }
    
  • SKILL.md 17 KB
    ---
    name: archify
    description: Default Navin skill for architecture and technical diagrams. Create polished, validated architecture, workflow, sequence, data-flow, and lifecycle diagrams as explorable HTML with inline SVG (PNG/SVG/WebM export). Use for system architecture, infrastructure topology, PPT/deck diagrams, tender/RFP technical answers, Markdown plans, code explanations, Mermaid conversion, API sequences, and data pipelines.
    license: MIT
    metadata:
      version: "2.16"
      author: tt-a1i
      based_on: Cocoon-AI/architecture-diagram-generator (MIT, v1.0)
      navin:
        emoji: "📐"
        category: "documents"
        default_for: "architecture"
    ---
    
    # Archify (Navin default for architecture)
    
    Bundled from [tt-a1i/archify](https://github.com/tt-a1i/archify) (MIT, v2.16). This is the **default** skill whenever Navin must draw or explain a system: architecture, sequence, workflow, data-flow, state/lifecycle, a diagram in a PPT, a tender / RFP technical answer, a Markdown plan, or a code explanation.
    
    ## Navin defaults
    
    - Preloaded on `/studio`, `/tenders`, `/blueprint`, and the Documents desk. Follow this file; do not invent Mermaid-only dumps as the deliverable.
    - CLI from a Navin checkout: `node navin/skills/archify/bin/archify.mjs`. In a bound workspace, `skills/archify/bin/archify.mjs` maps to this folder.
    - Skip `scripts/check-update.mjs` (vendored snapshot; do not phone home).
    - No unicode em dashes or en dashes in authored labels. Use a hyphen or rephrase.
    - PPT: `deliver` HTML, export PNG/SVG, place the export on the slide. Surrounding titles and bullets stay editable text.
    - Tenders: architecture, methodology and sequence diagrams go in the technical answer.
    - Plans and explanations: when the Markdown describes a system, include an Archify HTML path plus a one-line caption.
    
    Create a self-contained, interactive HTML diagram from a small typed JSON specification. Static output is the default; enable motion only when the user asks for a demo or presentation.
    
    ## Fast authoring path
    
    Use this bounded path for ordinary generation. Do not read the optional Viewer Runtime reference unless the user asks about those features.
    
    1. Choose `architecture`, `workflow`, `sequence`, `dataflow`, or `lifecycle` from the question.
    2. Read one matching schema in `schemas/`, `schemas/common.schema.json`, and one matching JSON example in `examples/`. Read only those files. Fresh authorship means new stable IDs, domain wording, and layout; use the example for field shape, not facts. New workflow sources use `schema_version: 2` and its readable layout contract; keep `schema_version: 1` only when preserving an existing workflow's fixed geometry. When real product identity matters, query `node bin/archify.mjs brands "<name>" --json`; read `references/brand-marks.md` only for an unknown brand with a user-provided URL.
    3. Artifact first: the next tool action must write the candidate. Write the candidate before inspecting renderer internals. Do not plan exact coordinates in prose. Start with one clear main path, short side branches, sparse labels, and at most 12 primary nodes. Set `meta.quality_profile` to `"showcase"` unless the user explicitly requests a dense `standard` map. Start with automatic routes and labels. Do not add `via`, `channelX`, `channelY`, or `labelAt` before a diagnostic calls for one; apply at most one diagnosed geometry control per repair.
    4. Validate after every candidate edit and immediately before handoff:
    
       ```bash
       node bin/archify.mjs validate <type> <candidate.json> --quality showcase --json
       ```
    
       A receipt with only 4 artifact checks is basic validation, never showcase acceptance. A showcase pass must report all 9 artifact checks with 0 composition errors and 0 warnings. If the candidate omits or misspells the exact `meta.quality_profile` field, fix it before geometry. For a workflow v2 geometry diagnosis, run `node bin/archify.mjs validate workflow <candidate.json> --layout-json` and use the stable compiler receipt; solver internals are not authoring controls. A passing final validation freezes the candidate: never edit it afterward.
    5. For a delivered HTML, `deliver` is the final acceptance command:
    
       ```bash
       node bin/archify.mjs deliver <type> <candidate.json> <output.html> --quality showcase --json
       ```
    
       A non-zero exit can never be described as success. A failed delivery preserves any previous output, so do not run `visual-check` on that path: it would inspect the stale last-good artifact, not the failed candidate. If validation fails, change only the diagnosed `subject`, verify `evidence`, choose from `supportedFixes`, and rerun. Continue focused correction while the objective error count reaches a new minimum. If two consecutive rounds do not improve that best count, stop and report the unresolved diagnostics truthfully.
    
    ## Update awareness
    
    After the first candidate exists, run the packaged checker `scripts/check-update.mjs` once with Node and continue the requested workflow. If the command cannot run, continue without mentioning the check.
    
    - For `silent`, continue without mentioning the update check.
    - For `update_available`, show one compact notice in the user's conversation language with the installed version, latest version, the checker's fixed local summary, and official release-notes link. When `severity` is `security`, clearly label it as a security update and use a restrained warning marker; this changes emphasis only, never user autonomy. Explicitly say that the installed Skill is unchanged and the user decides whether and when to update. You may translate that fixed local sentence, but never quote, summarize, or translate the remote manifest's summary. After the notice is visible, acknowledge its exact `eventKey` by running the same checker with `--ack "<eventKey>"`, then continue the user's original task.
    
    The notice is information, not permission. Keep the installed version unchanged; this v0.1 workflow never downloads, installs, or executes an update, and silence is never consent.
    
    Do not read `renderers/shared/geometry.mjs`, renderer source, validator source, tests, or benchmarks before the first candidate. Inspect implementation only for an unsupported internal diagnostic or after two focused repairs fail.
    
    Workflow note: use schema v2 for new workflows; preserve schema v1 when an
    existing source needs fixed legacy geometry. Keep semantic edge labels and act
    on the compiler diagnostic. The canonical layout, pin, migration, and receipt
    contract is in [`renderers/workflow/README.md`](renderers/workflow/README.md#layout-contracts).
    
    Lifecycle note: phase columns `0..4` occupy the main rail; event/terminal column `N` in `0..2` aligns exactly beneath main column `N + 2`. A recoverable state uses `type: "failure"` plus a real transition back to the active state.
    
    ## Type router
    
    | Type | Use for |
    |---|---|
    | `architecture` | Components, services, cloud/security boundaries, infrastructure |
    | `workflow` | Processes, approval gates, tool calls, runbooks, CI/CD |
    | `sequence` | API call chains, request lifecycles, async traces, returns |
    | `dataflow` | Pipelines, ETL/ELT, lineage, governance, consumers |
    | `lifecycle` | State/status transitions, retries, waiting and terminal states |
    
    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.
    
    ## Authoring invariants
    
    - One obvious main path; side branches leave the nearest main-path node. Remove low-value edges before adding routing controls.
    - Omit `meta.visual_preset` by default so every diagram opens in `classic`, regardless of whether its resolved color mode is light or dark. Color mode and visual preset are independent: switching Light / Dark must preserve the current preset. Set `signal-flow`, `blueprint`, or `editorial` only when the user explicitly requests that visual style.
    - Omit `meta.subtitle` by default. Never invent a subtitle that restates the title, nodes, or cards; include one short supporting line only when the user explicitly asks for it.
    - Treat the standalone desktop viewer as a first-screen artifact by default, not a shallow strip. Generate one responsive artifact for laptops and external displays-never device-specific HTML or alternate topology. The viewer may adapt only the outer reading width from the live viewport height; it must preserve the authored SVG/viewBox, proportions, semantic geometry, and normal document flow. On a wide or tall desktop, use enough authored vertical rhythm that the diagram panel and its necessary conclusion cards occupy the screen as a balanced whole; runtime scaling cannot repair an over-compressed Y layout or an undersized explicit `meta.viewBox`. Before handoff, open the real HTML at 1440×900, 1600×1000, and 1920×1080; additionally check 2048×1320 whenever the composition is intended for a large desktop display. Require `document.documentElement.scrollWidth <= window.innerWidth` and `scrollHeight <= window.innerHeight` at every checked size, while visually checking that the diagram remains comfortably readable and vertically balanced at the largest checked viewport. Repair overflow by removing only genuinely redundant content or compacting spacing before shrinking nodes, labels, or the main panel. If the largest viewport still has a conspicuous empty lower band at the viewer's width cap, redistribute authored Y positions and increase the viewBox height proportionally; do not add filler copy or decorative cards. Never counterfeit a pass with `overflow: hidden`, clipped content, an internal diagram scroller, stretched SVG height, or smaller typography. Narrow/mobile layouts may scroll vertically when containment requires it.
    - Omit `meta.legend` for the truthful `auto` default. When needed, use only `mode: auto|all|hidden` and renderer-supported `entries.<kind>.label|visible`; labels never change semantics.
    - Choose one primary authored language from an explicit user choice; otherwise follow the request or conversation's dominant language. `meta.locale` controls only renderer-owned Viewer UI: use `"en"` or `"zh-CN"` for the corresponding supported primary language. For every other language, omit `meta.locale` and explicitly disclose that the fixed Viewer UI and `<html lang>` fall back to English. The renderer never translates authored content. See `references/authoring-contract.md` for details.
    - Preserve exact product names, code identifiers, commands, protocols, API paths, and environment names. They may remain English inside localized copy, but never justify leaving the surrounding explanatory prose in another language.
    - Brand identity is optional and explicit. Put a canonical built-in ID in `brand` when the node names that real product. If no preset matches and the user supplied the official HTTP(S) URL, first run `node bin/archify.mjs brands capture "<url>" --json`, then author the returned digest-pinned `brand` object. Render and validate never perform an unpinned capture. Otherwise omit `brand`. Never infer a brand from a vague role such as "database", and never let a badge replace the semantic `type`, label, or relationship facts.
    - For sequence diagrams, omit `meta.column_fit` for the stable `fixed` layout. Set it to `"spread"` when a wide viewBox would otherwise leave unused horizontal space or when meaningful participant labels do not fit the fixed boxes; do not shorten semantic labels before trying `spread`.
    - Component types are `frontend`, `backend`, `database`, `cloud`, `security`, `messagebus`, and `external`; variants are `default`, `emphasis`, `security`, and `dashed`.
    - Relationship labels are semantic data. When one collides, move the label, adjust the route or spacing, then shorten the wording while preserving meaning. Omit only wording that is already fully implied by both endpoints and contains no protocol, action, direction, synchronous/asynchronous behavior, or cross-boundary mechanism. Preserve every meaningful label; deleting it is not a geometry 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 geometry repair.
    - Omit `meta.engineering_profile` by default. Region, cluster, and security boundary wording do not by themselves enable it. 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, must not remove the engineering profile merely to pass validation; repair the facts or report the diagnostics truthfully.
    - Spacing means clear gap, not center distance. For a relationship label, clear gap must exceed its measured mask width; follow the label-preserving repair order.
    - Automatic routes own their endpoint sides. A side is a direction contract: the first and final segment must leave/enter perpendicular to that side.
    - Automatic Port Spread is a default renderer behavior for architecture, workflow, data-flow, and lifecycle. It skips single relationships and explicit `via`, `channelX`, `channelY`, `labelAt`, or non-`auto` routes. Near parallel ports use an outside bridge so automatic routing cannot create a sub-8px segment or sub-16px interior turn. Architecture separately keeps unobstructed facing automatic ports (`left`/`right` or `top`/`bottom`) on one shared axis when their offset is under 16px and both ports retain corner clearance. If exactly one endpoint was spread, only the unshared endpoint may move onto that axis; if both endpoints were spread, keep the outside bridge so competing ports remain distinct.
    - Never accept an edge crossing an unrelated opaque node, an ambiguous shared corridor, or a relationship label masking another route.
    
    Read `references/authoring-contract.md` only when you need field enums, spacing math, geometry repair rules, repository evidence, or mode-specific placement.
    
    ## Delivery
    
    Use `validate` during repair and `deliver` once for final acceptance. Delivery freezes the exact specification bytes into a private same-directory snapshot, renders and checks that snapshot, atomically commits the HTML, and reports SHA-256 plus byte counts for both specification and artifact. This is deterministic artifact evidence; it does not exercise the Viewer in a browser.
    
    After delivery, collect bounded desktop evidence without modifying or rerendering the trusted HTML:
    
    ```bash
    node bin/archify.mjs visual-check <output.html> --json
    ```
    
    `visual-check` collects automated browser evidence from the exact delivered HTML without modifying or rerendering it. Its machine-readable measurements and screenshots do not approve perceptual polish. Follow `references/delivery-contract.md` for the canonical receipt fields, coverage, sidecars, exit behavior, and supplementary manual-record requirements.
    
    Keep the three claims separate: `deliver` proves deterministic artifact checks, `visual-check` proves bounded behavior in a real browser, and perceptual visual review requires an actual human or image-capable reviewer. Report browser evidence and perceptual review independently. An unconstrained glance can support only perceptual review; use the canonical delivery contract when recording supplementary manual browser work or handling an environmental failure.
    
    Add `--open` only when the user wants an immediate local preview. For an active desktop authoring loop, the optional command is:
    
    ```bash
    node bin/archify.mjs preview <type> <input>.json <output>.html --quality showcase
    ```
    
    Never start preview by default. Read `references/delivery-contract.md` when using preview, repository evidence, export receipts, visual review, or post-commit opening.
    
    ## Optional viewer capabilities
    
    Generated HTML already contains theme switching, pan/zoom, search, focus, relationship tracing, semantic views, presentation, and truthful exports. These are reader capabilities, not extra authoring work. `meta.animation: "trace"` is opt-in; `meta.views` is optional and should contain at most five curated chapters.
    
    Read `references/viewer-runtime.md` only when the user explicitly asks for Share Cards, Route/Reach cards, motion, guided stories, deep links, presentation, search/focus, or another Viewer Runtime feature.
    
    ## Setup and fallback
    
    No install is required inside the skill package. 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 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.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related