@avodado/mcp 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -19,7 +19,7 @@ import { openapiToMarkdown } from "@avodado/sync";
19
19
  var SKILL_MD = '---\nname: avodado-docs\ndescription: >-\n Use whenever you author, edit, validate, or review Avodado documentation \u2014\n Markdown files that mix prose with typed YAML blocks (sequence \xB7 erd \xB7 table \xB7\n callout \xB7 userstory \xB7 timeline \xB7 kanban \xB7 tracker \xB7 meta \xB7 prose \xB7 glossary \xB7\n proscons \xB7 cvt \xB7 stats \xB7 code \xB7 agenda \xB7 tree \xB7 pyramid \xB7 funnel \xB7 flow \xB7 state \xB7\n dfd \xB7 journey \xB7 gantt \xB7 graph \xB7 quadrant \xB7 swimlane \xB7 c4 \xB7 uml \xB7 mece \xB7 frontend \xB7\n cluster \xB7 block \xB7 infra \xB7 event \xB7 ddd \xB7 network \xB7 felogic \xB7 belogic \xB7 dag \xB7\n wireframe).\n Trigger on any of: docs/**/*.md in an Avodado repo, the `avo` CLI, any block\n type above, `doc#id` cross-references, presence of `avodado.config.*` or\n `.avodado/skill/SKILL.md` in the workspace, or user mentions "avodado". Covers\n block grammar, every block\'s fields, the reference scheme, YAML pitfalls, and\n the validate workflow.\n---\n\n# Authoring Avodado documents\n\n> Repo location: commit this file at `.avodado/skill/SKILL.md`. `avo init`\n> copies it into new projects and writes editor adapters (`CLAUDE.md`,\n> `.cursor/rules/avodado.mdc`) that point here so Claude Code, Cursor, and\n> other agents pick it up automatically.\n\nAvodado documents are **plain Markdown with typed, fenced YAML blocks**. Prose\nis ordinary Markdown; anything structured (a diagram, a table, a user story,\na chart) is a fenced code block whose info-string is the block *type*, with a\nYAML body.\n\n**The one rule:** the `.md` file is the source of truth. You edit files\ndirectly. A document must read fine as plain text with no tooling, so never\npaste raw HTML or inline SVG \u2014 express structure through blocks instead.\n\n## Authoring recipe \u2014 follow this every time\n\nAny time you write or edit an Avodado doc, work through these steps in order.\nSkipping steps is the source of every authoring failure I\'ve seen.\n\n1. **Identify the doc\'s job.** Is this an API spec, an architecture overview, a\n roadmap, a runbook, a meeting agenda? The job picks the blocks (see *Choose\n your block* below).\n2. **Start with `meta`** \u2014 title + subtitle + tag. First block, always.\n3. **Add a short prose intro** under `## Overview`. 2-4 sentences. Plain Markdown.\n4. **Pick 2-5 blocks that carry the structure.** Don\'t try to use all 41 in one doc.\n If the content *describes* an architecture, a layering, a pipeline, a component\n tree, or a set of gates, **adapt it to the matching diagram \u2014 don\'t leave it as\n prose and don\'t flatten it into a table.** A table is for genuinely tabular data\n (rows \xD7 columns of values), never for boxes-and-arrows. See *Adapt the content*\n and the *Block glossary* below.\n5. **Give each referenceable block an `id:`** (a short slug). Other blocks reach\n it as `doc#id` from elsewhere; bare `#id` works inside the same doc.\n6. **Use `title` + optional `lede` on diagram blocks** so the section header reads\n like an editorial document, not a dump of YAML.\n7. **Quote any string containing `,` `:` `[` `]` `{` `}` `#` `&` `*` `!` `|` `>`\n `\'` `"`.** See *YAML pitfalls* below for the table of things that bite you.\n8. **Run `avo check`.** If anything\'s red, fix it before you call the change\n done. A passing check is the definition of done.\n\n## Choose your block \u2014 decision tables\n\nMost authoring failures come from picking the wrong block. Use these tables.\n\n### Block glossary \u2014 one line on what each is *for*\n\nThe whole vocabulary at a glance. Read this first; it\'s the map from *a concept in\nyour head* to *a block*. The detailed family tables below disambiguate the close calls.\n\n| Block | What it represents |\n|---|---|\n| `meta` | Document header \u2014 title, subtitle, tag pill. Always the first block. |\n| `callout` | A single aside: note / tip / warn / danger. |\n| `prose` | Structured prose (headings, paragraphs, lists, quotes) carried as data. |\n| `glossary` | Term \u2192 definition rows. |\n| `proscons` | Two columns weighed against each other: pros vs cons. |\n| `cvt` | Current \u2192 target (before / after) as two side-by-side panels. |\n| `agenda` | Meeting agenda \u2014 time, duration, owner, topic per row. |\n| `table` | Genuinely tabular data (rows \xD7 columns of values); cells can carry tone. |\n| `stats` | KPI cards \u2014 a value with a delta and an up/down/flat trend. |\n| `code` | One or more syntax-highlighted snippets under a titled header bar. |\n| `tracker` | A task list with status / priority / owner / due. |\n| `kanban` | Flexible named columns (e.g. Now / Next / Later) of cards. |\n| `timeline` | Phases in order with status dots (done / current / next / future). |\n| `gantt` | A schedule \u2014 tasks as bars across date columns. |\n| `userstory` | An agile story: role / want / soThat + acceptance criteria + links. |\n| `sequence` | Messages between actors **over time** (lifelines, returns); optional step list + endpoint pill. |\n| `state` | A state machine \u2014 states + event transitions (+ a transition table). |\n| `flow` | A decision flowchart \u2014 start / process / decision / end nodes, with `error` exits. |\n| `dag` | A pipeline / DAG \u2014 same shapes as `flow`, framed for CI/CD. |\n| `dfd` | Data-flow \u2014 processes, external entities, and datastores. |\n| `swimlane` | A cross-functional process with one horizontal lane per role. |\n| `journey` | A user journey across stages, with an optional emotion curve. |\n| `erd` | Entity-relationship diagram \u2014 tables, columns, PK/FK, crow\'s-foot cardinality. |\n| `uml` | A class diagram \u2014 attributes, methods, UML relationships. |\n| `c4` | C4 model (context / container / component) \u2014 people, systems, containers, stores. |\n| `block` | Generic boxes-and-arrows architecture \u2014 grid **or** horizontal `layers`, dashed `groups` zones. |\n| `infra` | Cloud topology (same engine as `block`) \u2014 CDN / gateway / compute / DB, nested account & network zones. |\n| `event` | Pub/sub topology (same engine) \u2014 producers \u2192 topics \u2192 consumers. |\n| `ddd` | DDD bounded-context map (same engine). |\n| `network` | Security zones with trust boundaries (same engine); supports `forbidden` (red) edges. |\n| `cluster` | Kubernetes-style namespaces holding services, with replica counts. |\n| `frontend` | A top-down component tree \u2014 root / layout / page / component / provider / hook / store. |\n| `felogic` | Frontend module/logic graph \u2014 components, hooks, interfaces, strategies; group zones + egress edges. |\n| `belogic` | Backend module/logic graph (same engine) \u2014 controller / service / repository / adapter / gateway + egress. |\n| `graph` | A generic node-link graph with colour-cycled groups. |\n| `mece` | A MECE issue tree \u2014 one problem broken into mutually-exclusive branches. |\n| `tree` | An indented file/folder hierarchy (HTML, not SVG). |\n| `pyramid` | A layered pyramid (strategy / hierarchy), widening top \u2192 bottom. |\n| `funnel` | A conversion funnel with auto-computed percentages. |\n| `quadrant` | A 2\xD72 matrix (e.g. effort vs impact) with plotted items. |\n| `wireframe` | Low-fi UI mockups inside device frames \u2014 desktop / browser / phone screens. |\n\n### Adapt the content \u2014 signals that should trigger a diagram\n\nWhen you\'re handed prose, a spec, or a generic table, these cues in the *source*\ntell you which diagram it really wants. This is the step people skip \u2014 and then\neverything degrades into tables and sequences.\n\n| If the source describes\u2026 | Adapt it to | Not |\n|---|---|---|\n| "layers / tiers / sits on top of / front-to-back / N-tier" | `block` (with `layers`) or `infra` | a table |\n| "the platform: these services + a shared backbone, who calls what" | `block` / `infra` / `cluster` | a table |\n| "a person uses the system, which depends on external systems" | `c4` (level: context) | prose |\n| "N checks/gates **in order**, any one can reject the request" | `flow` (decision nodes + `kind: error` exits) | a `sequence` \u2014 gates aren\'t temporal |\n| "A happens, then B, then C, then a reply comes back" (over time) | `sequence` | a `flow` |\n| "who does what across teams, step by step" | `swimlane` | a `flow` |\n| "components / providers / hooks / context / store" | `frontend` (tree) or `felogic` (with patterns + egress) | a table |\n| "controller / service / repository / adapter / gateway / middleware / Depends()" | `belogic` | a `sequence` |\n| "producers emit events \u2192 topics \u2192 consumers" | `event` | a `flow` |\n| "namespaces / pods / replicas / deployments" | `cluster` | a `block` |\n| "trust boundary / DMZ / zones / must-not-call" | `network` (with `forbidden` edges) | a `block` |\n| "tables, schema, primary/foreign keys, relationships" | `erd` | a `table` |\n| "options compared with verdicts/criteria" | `table` (this one really is tabular) | \u2014 |\n| "current state vs target state" / "before vs after" | `cvt` | a 2-column `table` |\n| "pros vs cons / trade-offs for one option" | `proscons` | a `table` |\n| "why is X happening \u2014 break the causes down" | `mece` | a bulleted list |\n| "phases / rollout in order" | `timeline` (status) or `gantt` (real dates) | a `table` |\n| "what the user sees / the screen / the app / the bell + feed" | `wireframe` (desktop / browser / phone) | prose |\n\n> **The rule:** if the source *describes* a structure \u2014 an architecture, a layering,\n> a pipeline, a component tree, a set of gates \u2014 render it as the matching **diagram**.\n> Prose and tables are the fallback for things that are genuinely paragraphs and\n> genuinely rows-of-values, not the default for everything.\n\n### Architecture and topology (which one when?)\n\n| If you want to show\u2026 | Use | Notes |\n|---|---|---|\n| Who uses the system + which external systems it depends on | `c4` (level: context) | One node per actor / system |\n| Containers inside a system, with optional boundary box | `c4` (level: container) | Use `family` to colour-code (client / service / data / store) |\n| Components inside one container | `c4` (level: component) | Same shape, finer granularity |\n| Generic boxes-and-arrows architecture | `block` | Grid layout; add `groups` for dashed zones; add `layers` to switch to horizontal-band layout |\n| Cloud deployment (CDN, gateway, compute, DB, \u2026) | `infra` | Same engine as `block`; conventionally for cloud topology |\n| Pub/sub event topology (producers \u2192 topics \u2192 consumers) | `event` | Same engine; conventionally for choreography |\n| Bounded-context map for DDD | `ddd` | Same engine; conventionally for context maps |\n| Security zones with trust boundaries | `network` | Same engine; supports `kind: forbidden` edges (red) |\n| Kubernetes-style namespaces with services inside | `cluster` | Has its own nested-box engine; supports `replicas` count |\n\n> `block` / `infra` / `event` / `ddd` / `network` share **one renderer**.\n> They differ only by the colored tag pill above the diagram (ARCH / INFRA / EVENT\n> / DDD / ZONES). Pick the slug that best signals intent to a reader; the YAML\n> grammar is identical.\n\n### Charts and overviews\n\n| If you want to show\u2026 | Use |\n|---|---|\n| KPI values with deltas + up/down arrows | `stats` |\n| Tabular data with optional cell tones | `table` |\n| Task list with status / owner / priority / due | `tracker` |\n| Now / Next / Later flexible columns | `kanban` |\n| Phases with status dots (done / current / next / future) | `timeline` |\n| Schedule with date columns and bars | `gantt` |\n| Conversion funnel with auto-percentages | `funnel` |\n| Hierarchical / strategic pyramid (top\u2192bottom widening) | `pyramid` |\n| 2\xD72 matrix (effort vs impact, etc.) | `quadrant` |\n| User journey across stages with optional emotion curve | `journey` |\n\n### Process and flow\n\n| If you want to show\u2026 | Use |\n|---|---|\n| Sequence of messages over time (with optional step-by-step list + endpoint tag) | `sequence` |\n| State machine with transitions + transition table | `state` |\n| Generic decision flow with diamonds + stadium nodes | `flow` |\n| Data-flow with processes, externals, datastores | `dfd` |\n| Cross-functional flow with horizontal lanes per role | `swimlane` |\n| CI/CD pipeline (same shapes as `flow`, navy DAG tag) | `dag` |\n\n### Code-flavoured\n\n| If you want to show\u2026 | Use |\n|---|---|\n| Class diagram with attrs/methods + UML markers | `uml` |\n| Top-down React/Vue component tree | `frontend` |\n| Frontend module graph with design patterns + interface stereotypes | `felogic` |\n| Backend module graph \u2014 same engine as felogic | `belogic` |\n| One or more syntax-highlighted code snippets | `code` |\n| MECE issue tree (left \u2192 right with depth-coloured branches) | `mece` |\n| Indented file/folder hierarchy (HTML, not SVG) | `tree` |\n| Generic node-link graph with `group:` colour cycling | `graph` |\n\n### Narrative and structure\n\n| If you want to show\u2026 | Use |\n|---|---|\n| Note / tip / warning / danger box | `callout` |\n| Structured prose (h3 + p + ul + quote sub-blocks) | `prose` |\n| Term / definition rows | `glossary` |\n| Two-column pros vs cons | `proscons` |\n| Before / after, "current" \u2192 "target" | `cvt` |\n| Meeting agenda (time + duration + title + owner) | `agenda` |\n| User story + acceptance criteria + cross-doc links | `userstory` |\n\n## Mixing blocks \u2014 document recipes\n\nA good Avodado doc is **2-5 blocks, each a different lens** on the subject \u2014\n*orient \u2192 big picture \u2192 detail \u2192 plan*. Don\'t show the same thing in two block\ntypes, and don\'t reach for all 41. Start from the doc\'s job and pick a stack:\n\n| Doc job | Core blocks (always) | Add when relevant | Skip / fold into prose when\u2026 |\n|---|---|---|---|\n| **API / endpoint spec** | `meta` + `sequence` (request flow) | `erd` (data touched) \xB7 `table` (status codes) \xB7 `code` (payloads) \xB7 `userstory` (the story it serves) | the call is a single hop \u2014 describe it in prose |\n| **Architecture overview** | `meta` + `c4` (context) **or** `block`/`infra` (the landscape) | `belogic`/`felogic` (one module\'s internals) \xB7 `flow` (a key decision path) \xB7 `tracker` (open decisions) | there are <3 components \u2014 a `callout` is enough |\n| **Design doc / RFC** | `meta` + `proscons` **or** `cvt` (the choice) | `mece` (problem breakdown) \xB7 `c4`/`block` (proposed arch) \xB7 `sequence`/`flow` (behavior) \xB7 `tracker` | only one option exists \u2014 just prose |\n| **Roadmap / plan** | `meta` + `timeline` (phases) **or** `gantt` (real dates) | `kanban` (now/next/later) \xB7 `tracker` (tasks) \xB7 `stats` (targets) | \u2014 |\n| **Runbook / procedure** | `meta` + `flow` **or** `swimlane` | `sequence` (one interaction) \xB7 `code` (commands) \xB7 `table` (symptom \u2192 action) \xB7 `callout: warn` | the steps are linear with no branches \u2014 an `ol` in `prose` |\n| **Data model** | `meta` + `erd` | `table` (field semantics) \xB7 `state` (record lifecycle) | it\'s a single table \u2014 use `table` alone |\n| **Frontend feature** | `meta` + `frontend` (tree) | `felogic` (logic + patterns) \xB7 `wireframe` (what the user sees) \xB7 `sequence` (data fetch) \xB7 `userstory` | \u2014 |\n| **Status / metrics** | `meta` + `stats` | `funnel` \xB7 `quadrant` \xB7 `timeline` | \u2014 |\n| **Meeting** | `meta` + `agenda` | `tracker` \xB7 `kanban` \xB7 `callout` | \u2014 |\n\n**Rules for combining:**\n\n- **One `meta`, first, always.** Everything after it is optional.\n- **Each block earns its place as a distinct lens.** `c4`/`block` shows the\n *structure*; `sequence`/`flow` shows *behavior*; `timeline`/`tracker` shows\n *plan*. If two blocks would draw the same boxes (`c4` **and** `block` for the\n same components, or `flow` **and** `sequence` for the same steps), keep one.\n- **Connect, don\'t repeat.** Give the referenced block an `id:` and point at it\n with `userstory.links[].ref: doc#id` instead of redrawing it elsewhere.\n- **Omit a block whose data is thin.** Fewer than ~3 nodes/rows? Fold it into a\n `callout` or a prose list \u2014 an almost-empty diagram reads worse than a sentence.\n- **Order top-to-bottom as the reader needs it:** orient (`meta` + intro) \u2192 the\n big picture (context / landscape) \u2192 the detail (one module / one flow) \u2192 what\'s\n next (plan / tracker).\n\n## YAML pitfalls \u2014 quote when in doubt\n\nThe YAML parser is doing exactly what you asked. Most "schema errors" are\nactually YAML mis-parses. **Quote the value** whenever it contains:\n\n| Character | What goes wrong unquoted | Fix |\n|---|---|---|\n| `,` (comma) | Inside `{ a, b }` flow style, treated as a separator. Your sentence becomes 3 keys. | `desc: "40 blocks, themes, agent skill"` |\n| `:` (colon) | Treated as `key: value`. `1:N` becomes a number sequence. | `card: "1:N"` |\n| `#` (hash) | Treated as a comment from there on. | `label: "POST /orders #idempotent"` |\n| Leading `*` `&` `!` `|` `>` `%` `@` `\\`` | YAML anchor / tag / literal / fold / reserved characters. | Quote the whole value. |\n| Leading `-` followed by space | Looks like a list item. | Quote. |\n| Numeric-looking (`0`, `02`, `1e3`) | Parsed as a number, fails `string` schemas. | Quote: `delta: "0"`, `version: "1.0"` |\n| `yes` / `no` / `true` / `false` / `null` | YAML 1.1 booleans (still around in some parsers). | Quote. |\n| Empty | Parsed as null. | Quote: `name: ""` |\n\nInline-mapping `{ k: v }` is fine for short records (under ~5 fields). For\nanything longer, use block-style \u2014 easier diffs, fewer comma traps:\n\n```yaml\n# \u2713 Good \u2014 block style for longer records\nitems:\n - title: Phase 1\n when: now\n status: active\n detail: A longer description with, commas, in, it.\n# \u2717 Bad \u2014 flow-style with unquoted commas\nitems:\n - { title: Phase 1, when: now, status: active, detail: A longer description with, commas }\n```\n\nWhen you write a `desc` / `note` / `summary` / `description` that contains\nprose, **always quote it** \u2014 those fields are the #1 source of validation\nerrors.\n\n## How a block looks\n\n````\n## Request flow\n\n```sequence\nid: seq-place-order\ntitle: Place order\nendpoint: { method: POST, path: /orders }\nactors:\n - { id: Client, name: Client }\n - { id: API, name: Orders API }\nmessages:\n - { from: Client, to: API, label: POST /orders, kind: sync }\n - { from: API, to: Client, label: 201 Created, kind: response }\n```\n````\n\nRules:\n\n- The info-string is exactly one of the **41 block types** listed below \u2014 never\n invent new ones.\n- The body is **YAML** (JSON is also accepted; YAML is preferred \u2014 prefer\n block-style over deep inline maps for readability and clean diffs).\n- Use only the fields documented for that block. Keep prose outside blocks.\n- A block MAY carry a top-level `id:` (a slug) so other blocks can reference it.\n- Most diagram blocks accept optional `title`, `description`, and `lede` \u2014\n these surface in the section header + diagram frame around the SVG.\n\n## Block data shapes \u2014 required vs optional (the contract)\n\nEvery block also carries optional `title`, `description`, `lede` (editorial text\nrendered around the diagram) and an optional top-level `id:` \u2014 **none are ever\nrequired**, so they\'re left out of the table below, which shows only the\n*structural* payload. `*` marks a **required** field; everything else is optional.\n**Omit optional fields you have no value for** \u2014 don\'t pad them with empty strings.\n`(n)` marks a **number** (don\'t quote it); every other value is a string.\n\n| Block | Structural shape (`*` = required, `(n)` = number) | Closed enums |\n|---|---|---|\n| `meta` | `title` `subtitle` `tag` | \u2014 |\n| `callout` | `tone` `title` `body` | tone: note \xB7 tip \xB7 warn \xB7 danger |\n| `prose` | `blocks[]`: `type` `text` `items[]` | type: h \xB7 p \xB7 ul \xB7 ol \xB7 quote |\n| `glossary` | `terms[]`: `term*` `def*` | \u2014 |\n| `proscons` | `prosLabel` `consLabel` `pros[]` `cons[]` | \u2014 |\n| `cvt` | `current{label, items[]}` `target{label, items[]}` `note` | \u2014 |\n| `agenda` | `items[]`: `title*` `time` `duration` `owner` `desc` | \u2014 |\n| `table` | `columns[]`: string \\| `{label*, align, highlight}` \xB7 `rows[][]`: string \\| number \\| `{v*, tone, lead, highlight}` \xB7 `note` | align: l \xB7 c \xB7 r \u2014 tone: pos \xB7 neg \xB7 warn \xB7 muted |\n| `stats` | `stats[]`: `value*` `label*` `delta` `trend` `accent` | trend: up \xB7 down \xB7 flat |\n| `code` | `blocks[]`: `code*` `title` `lang` | \u2014 |\n| `tracker` | `items[]`: `task*` `status` `priority` `owner` `due` | status: todo \xB7 doing \xB7 done \xB7 blocked \u2014 priority: high \xB7 med \xB7 low |\n| `kanban` | `columns[]`: `label*` `cards[]`: `title*` `tag` | \u2014 |\n| `timeline` | `items[]`: `label*` `date` `desc` `status` | status: done \xB7 current \xB7 next \xB7 future |\n| `gantt` | `periods[]` \xB7 `tasks[]`: `label*` `start`(n) `span`(n) `kind` | kind: done \xB7 active \xB7 current \xB7 milestone |\n| `userstory` | `role` `want` `soThat` `priority` `points`(n) \xB7 `criteria[]`: `given` `when` `then` \xB7 `links[]`: `ref` `mode` `label` | \u2014 |\n| `sequence` | `actors[]`: `id*` `name*` `sub` `external` \xB7 `messages[]`: `from*` `to*` `label` `kind` `summary` `code` `note` \xB7 `endpoint{method*, path*, status}` \xB7 `foot[]`: `label*` `value*` | msg kind: sync \xB7 response \xB7 async \xB7 error \xB7 note \u2014 method: GET \xB7 POST \xB7 PUT \xB7 PATCH \xB7 DELETE |\n| `state` | `states[]`: `id*` `col*`(n) `row*`(n) `name` `kind` \xB7 `transitions[]`: `from*` `to*` `event*` `guard` | kind: start \xB7 terminal \xB7 active \xB7 wait |\n| `flow` / `dag` | `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `label*` `kind` \xB7 `edges[]`: `from*` `to*` `label` `kind` | node kind: start \xB7 end \xB7 decision \xB7 process \u2014 edge kind: error |\n| `dfd` | `nodes[]`: `id*` `col*`(n) `row*`(n) `name*` `kind` `num` \xB7 `edges[]`: `from*` `to*` `label` | kind: process \xB7 external \xB7 store \xB7 datastore |\n| `swimlane` | `lanes[]`: `label*` \xB7 `steps[]`: `id*` `col*`(n) `lane*`(n) `label*` `kind` \xB7 `links[]`: `from*` `to*` `label` | kind: action \xB7 decision \xB7 start \xB7 end \xB7 wait |\n| `journey` | `stages[]`: `label*` \xB7 `rows[]`: `label*` `cells[]` \xB7 `emotion[]`(n, 0..1) | \u2014 |\n| `erd` | `entities[]`: `name*` `columns[]`: `name*` `type` `pk`(bool) `fk`(bool) \xB7 `relations[]`: `from*` `to*` `label` `card` | card: "1:1" \xB7 "1:N" \xB7 "N:M" (quote!) |\n| `uml` | `classes[]`: `id*` `col*`(n) `row*`(n) `name*` `stereotype` `attrs[]` `methods[]` \xB7 `rels[]`: `from*` `to*` `label` `kind` | rel kind: inheritance \xB7 extends \xB7 implementation \xB7 implements \xB7 composition \xB7 aggregation \xB7 dependency \xB7 association |\n| `c4` | `level` `boundary{label*}` \xB7 `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `kind*` `family` `name*` `tech` `desc` \xB7 `edges[]`: `from*` `to*` `label` `kind` | level: context \xB7 container \xB7 component \u2014 node kind: person \xB7 system \xB7 external \xB7 store \xB7 container \xB7 component \u2014 edge kind: solid \xB7 dashed \xB7 forbidden \xB7 error |\n| `block` `infra` `event` `ddd` `network` | `systemLabel` \xB7 `layers[]`: `label*` \xB7 `groups[]`: `id` `col*`(n) `row*`(n) `cols`(n) `rows`(n) `label*` `color` \xB7 `nodes[]`: `id*` `name*` (`col`(n)+`row`(n) **or** `layer`(n)) `w`(n) `kind` `tech` \xB7 `edges[]`: `from*` `to*` `label` `kind` | node kind: free string (client \xB7 service \xB7 microservice \xB7 db \xB7 cache \xB7 queue \xB7 gateway \xB7 cdn \xB7 external \xB7 \u2026) \u2014 edge kind: solid \xB7 dashed \xB7 forbidden \xB7 error |\n| `cluster` | `clusters[]`: `id*` `label*` `kind` \xB7 `services[]`: `id*` `cluster*` `label*` `kind` `tech` `replicas`(n) \xB7 `edges[]`: `from*` `to*` `label` `kind` | edge kind: solid \xB7 dashed \xB7 forbidden \xB7 error |\n| `frontend` | `nodes[]`: `id*` `name*` `parent` `kind` `note` | kind: root \xB7 layout \xB7 page \xB7 component \xB7 leaf \xB7 provider \xB7 context \xB7 hook \xB7 store \xB7 state |\n| `felogic` / `belogic` | `groups[]` (as `block`) \xB7 `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `kind` `name*` `note` \xB7 `edges[]`: `from*` `to*` `label` `kind` | node kind: free string (controller \xB7 service \xB7 repository \xB7 adapter \xB7 interface \xB7 strategy \xB7 hook \xB7 \u2026) \u2014 edge kind: uses \xB7 implements \xB7 reads \xB7 egress \xB7 https \xB7 api \xB7 dashed \xB7 async |\n| `graph` | `nodes[]`: `id*` `col*`(n) `row*`(n) `label*` `group`(n) \xB7 `edges[]`: `from*` `to*` `label` `dir` | dir: directed \xB7 undirected |\n| `mece` | `nodes[]`: `id*` `parent` `label*` `note` | \u2014 |\n| `tree` | `nodes[]`: `id*` `parent` `label*` `note` | \u2014 |\n| `pyramid` | `levels[]`: `label*` `desc` | \u2014 |\n| `funnel` | `stages[]`: `label*` `value*` | \u2014 |\n| `quadrant` | `xAxis{label, low, high}` `yAxis{label, low, high}` \xB7 `items[]`: `x*`(n, 0..1) `y*`(n, 0..1) `label*` | \u2014 |\n| `wireframe` | `screens[]`: `device` `title` `url` `label` `elements[]`: `type` `label` `rows`(n) `align` `tone` | device: desktop \xB7 browser \xB7 phone \u2014 element type: header \xB7 subheader \xB7 text \xB7 button \xB7 input \xB7 search \xB7 image \xB7 avatar \xB7 card \xB7 list \xB7 nav \xB7 tabs \xB7 divider \xB7 badge \xB7 toggle \xB7 spacer \u2014 align: l \xB7 c \xB7 r \u2014 tone: accent \xB7 muted \xB7 danger |\n\n**Reading the contract:**\n\n- A block with **no items at all** is a `W_EMPTY_BLOCK` warning \u2014 give it content\n or delete it. The `*` fields are the minimum to make each item valid.\n- **Grid blocks** (`flow` \xB7 `state` \xB7 `dfd` \xB7 `c4` \xB7 `uml` \xB7 `graph` \xB7 `swimlane`\n \xB7 `felogic`/`belogic` \xB7 grid-mode `block`) require `col`/`row` (1-indexed) on\n every node. Adding `layers:` to `block`/`infra`/`event`/`ddd`/`network` switches\n them to band layout, where nodes use `layer:` (an index) instead of `col`/`row`.\n- **Numbers stay unquoted:** coordinates (`col` `row` `lane` `w`), `points`,\n `replicas`, `group`, `start`/`span`, quadrant `x`/`y`, and `emotion[]`. Quote\n anything string-like that *looks* numeric (`version`, `delta: "0"`) \u2014 see *YAML\n pitfalls*.\n- **`kind` is optional on most nodes/edges** \u2014 omit it for the neutral default;\n set it only to get the right glyph, colour, or marker.\n\n## The 41 block types \u2014 by family\n\n### Document & meta\n\n#### `meta` \u2014 document cover (first block only)\n```meta\ntitle: Orders API\nsubtitle: How the orders service accepts and persists a purchase.\ntag: API \xB7 v1\n```\n\n### Prose & structure\n\n#### `prose` \u2014 structured prose (heading / paragraph / list / quote)\n```prose\ntitle: Background\nblocks:\n - { type: h, text: Why this exists }\n - { type: p, text: A short paragraph explaining context. }\n - { type: ul, items: [Idea one, Idea two] }\n - { type: quote, text: A pull-quote. }\n```\n\n#### `callout` \u2014 note / tip / warning / danger\n```callout\ntone: warn\ntitle: Idempotency required\nbody: Clients must send an Idempotency-Key header so retries are safe.\n```\n`tone` is `note | tip | warn | danger`.\n\n#### `glossary` \u2014 term / definition rows\n```glossary\nterms:\n - { term: Idempotent, def: A replay produces the same outcome. }\n - { term: SLO, def: Service-level objective the team commits to. }\n```\n\n### Tables & metrics\n\n#### `table` \u2014 comparison table\n```table\ncolumns: [Code, Meaning, When]\nrows:\n - [201, Created, Order persisted]\n - [409, Conflict, Idempotency key reused]\n```\nColumns may be objects: `{ label, align: l|c|r, highlight: boolean }`. Cells\nmay be objects: `{ v: value, tone: pos|neg|warn|muted, lead: boolean,\nhighlight: boolean }`. Optional top-level `note`.\n\n#### `stats` \u2014 KPI / metric cards\n```stats\ntitle: This quarter\nstats:\n - { value: 12.4k, label: Active users, delta: "+18%", trend: up }\n - { value: 99.95%, label: Uptime, delta: "0", trend: flat }\n```\n`trend` is `up | down | flat`. `delta` is a string.\n\n#### `code` \u2014 one or more code blocks\n```code\nblocks:\n - title: schema.sql\n lang: PostgreSQL\n code: |\n CREATE TABLE orders (id uuid PRIMARY KEY, total numeric);\n```\nRenders with syntax highlighting (kw, str, num, fn, ty, com tokens).\n\n### Sequence & state\n\n#### `sequence` \u2014 interaction over time (rich SVG + step list + footer)\n```sequence\nid: seq-place-order\ntitle: One transaction wraps authorize + persist.\nlede: Time runs downward. Solid arrows are sync; dashed are responses.\ndescription: Happy path shown.\nendpoint: { method: POST, path: /orders }\nactors:\n - { id: Client, name: Client, sub: web / mobile }\n - { id: API, name: Orders API, sub: orders handler }\n - { id: PG, name: Postgres, sub: orders }\n - { id: Payment, name: Payment GW, sub: external, external: true }\nmessages:\n - { from: Client, to: API, label: POST /orders, kind: sync, summary: "Place the order with cart, token, idempotency key.", code: "POST /orders\\nIdempotency-Key: ..." }\n - { from: API, to: API, kind: note, label: validate token, summary: "Validate bearer, check idempotency key." }\n - { from: API, to: PG, label: INSERT order, kind: sync, summary: "Open the txn and insert in PENDING.", note: "Required index: orders(idempotency_key)." }\n - { from: PG, to: API, label: order_id, kind: response, summary: "Returns the new order_id." }\n - { from: API, to: Client, label: 201 Created, kind: response, summary: "201 with the order." }\nfoot:\n - { label: Target p95, value: 250ms }\n - { label: Idempotent, value: via Idempotency-Key (24h TTL) }\n```\nEach message: `from` + `to` (must match an actor `id`), `label`,\noptional `kind` (`sync | response | async | error | note`).\n- `note` kind is a numbered annotation on one lane \u2014 no arrow.\n- `summary` (long form for the step list under the SVG),\n- `code` (a code snippet inside the step item),\n- `note` field (italic-gray sub-note below the summary).\n`endpoint.method` colours the tag pill (POST \u2192 navy, GET \u2192 green, etc.).\n`foot` items render as key/value pills beneath the diagram.\n\n#### `state` \u2014 state machine (+ transition table)\n```state\ntitle: Order lifecycle\nstates:\n - { id: s0, col: 1, row: 1, kind: start }\n - { id: pending, col: 2, row: 1, kind: wait, name: PENDING }\n - { id: confirmed, col: 3, row: 1, kind: active, name: CONFIRMED }\n - { id: end, col: 4, row: 1, kind: terminal }\ntransitions:\n - { from: s0, to: pending, event: create }\n - { from: pending, to: confirmed, event: pay }\n - { from: confirmed, to: end, event: ship }\n```\n`kind` on a state is `start | terminal | active | wait`.\n\n### Data model\n\n#### `erd` \u2014 entities and relations\n```erd\nentities:\n - name: orders\n columns:\n - { name: id, type: uuid, pk: true }\n - { name: user_id, type: uuid, fk: true }\nrelations:\n - { from: orders, to: order_items, card: "1:N" }\n```\nColumn flags are booleans (`pk: true`, `fk: true`). Relation `card` is\n`"1:1" | "1:N" | "N:M"`. Quote cardinality values because YAML parses the\nunquoted form as a number sequence.\n\n### Architecture diagrams\n\n#### `c4` \u2014 context / container / component\n```c4\ntitle: System context\nlevel: container\nboundary: { label: ShopCo platform }\nnodes:\n - { id: user, col: 1, row: 1, kind: person, name: Shopper, desc: A customer. }\n - { id: api, col: 2, row: 1, kind: container, family: service, name: Orders API, tech: Go }\n - { id: pay, col: 3, row: 1, kind: external, name: Payment GW }\nedges:\n - { from: user, to: api, label: places order }\n - { from: api, to: pay, label: authorises }\n```\n`kind` is `person | system | external | store | container | component`.\n`family` (for `container`/`component`): `client | service | data | store |\ncontroller | repo | external`. Edge `kind` is `solid | dashed | forbidden |\nerror`. Optional `boundary` draws a dashed box around the internal nodes.\n\n#### `block` \u2014 grid architecture with optional groups\n```block\ntitle: System architecture\ngroups:\n - { col: 1, row: 1, cols: 1, rows: 2, label: Edge, color: "#0e54a1" }\nnodes:\n - { id: api, col: 2, row: 1, kind: service, name: API, tech: Go }\n - { id: pg, col: 2, row: 2, kind: store, name: Postgres }\nedges:\n - { from: api, to: pg }\n```\nNode `kind` is one of: `client \xB7 service \xB7 microservice \xB7 compute \xB7 container \xB7\ndata \xB7 store \xB7 db \xB7 database \xB7 bucket \xB7 blob \xB7 object \xB7 queue \xB7 cache \xB7 gateway\n\xB7 lb \xB7 function \xB7 lambda \xB7 cdn \xB7 external \xB7 producer \xB7 topic \xB7 consumer \xB7\ncontext \xB7 firewall`. Known kinds get coloured + glyphed automatically.\n\n**Nested zones (AWS-style VPC / subnets).** `groups` can overlap to nest: draw\nthe outer zone (e.g. a VPC) as one big group, then inner zones (public / private\nsubnets) as smaller groups inside its cell range. The renderer paints larger\ngroups first, so smaller ones layer on top. Nodes still sit in grid `col`/`row`\ncells; the groups just frame them.\n```infra\ntitle: VPC topology\ngroups:\n - { col: 2, row: 1, cols: 3, rows: 3, label: "VPC 10.0.0.0/16", color: "#0e54a1" }\n - { col: 2, row: 1, cols: 3, rows: 1, label: Public subnet, color: "#1f9747" }\n - { col: 2, row: 2, cols: 3, rows: 1, label: "Private subnet \xB7 app", color: "#1a6dbe" }\nnodes:\n - { id: cf, col: 1, row: 1, kind: cdn, name: CloudFront }\n - { id: alb, col: 2, row: 1, kind: gateway, name: ALB }\n - { id: svc, col: 2, row: 2, kind: microservice, name: orders, tech: ECS }\nedges:\n - { from: cf, to: alb }\n - { from: alb, to: svc }\n```\n\n#### `infra` \u2014 same engine, layered layout\n```infra\ntitle: AWS topology\nsystemLabel: ShopCo \xB7 us-east-1\nlayers:\n - { label: Edge }\n - { label: Compute }\n - { label: Data }\nnodes:\n - { id: cf, layer: 0, kind: cdn, name: CloudFront }\n - { id: api, layer: 1, kind: service, name: API }\n - { id: pg, layer: 2, kind: store, name: orders-db }\n```\nPresence of `layers` switches `block`/`infra` to horizontal-band layout.\nNodes use `layer: <index>` instead of `col`/`row`.\n\n#### `event` \u2014 pub / sub choreography (same shape as block)\n```event\ntitle: Order events\nnodes:\n - { id: orders, col: 1, row: 1, kind: producer, name: orders }\n - { id: bus, col: 2, row: 1, kind: topic, name: order.events }\n - { id: ship, col: 3, row: 1, kind: consumer, name: shipping }\nedges:\n - { from: orders, to: bus }\n - { from: bus, to: ship }\n```\n\n#### `ddd` \u2014 bounded-context map (same shape as block)\n```ddd\ntitle: Bounded contexts\nnodes:\n - { id: cat, col: 1, row: 1, kind: context, name: Catalog }\n - { id: order, col: 2, row: 1, kind: context, name: Orders }\nedges:\n - { from: order, to: cat, label: reads, kind: dashed }\n```\n\n#### `network` \u2014 security zones (same shape as block)\nUses the `firewall` glyph and red zone tag.\n\n#### `cluster` \u2014 k8s-style nested boxes with services\n```cluster\ntitle: Production cluster\nclusters:\n - { id: api, label: api namespace, kind: namespace }\nservices:\n - { id: web, cluster: api, label: web, kind: service, tech: Next.js, replicas: 3 }\n - { id: orders, cluster: api, label: orders, kind: service, tech: Go, replicas: 4 }\nedges:\n - { from: web, to: orders }\n```\n`replicas` renders as small bars (capped at 5 + `\xD7N` label).\n\n### Code-flavoured architecture\n\n#### `felogic` / `belogic` \u2014 frontend / backend module graph\n```felogic\ntitle: Frontend logic\ngroups:\n - { id: app, label: App (browser), col: 1, row: 1, cols: 3, rows: 3, color: "#0e54a1" }\nnodes:\n - { id: ui, col: 1, row: 1, kind: component, name: Checkout UI }\n - { id: iface, col: 2, row: 2, kind: interface, name: DiscountStrategy }\n - { id: impl, col: 1, row: 3, kind: strategy, name: PercentOff }\nedges:\n - { from: ui, to: iface, kind: uses }\n - { from: impl, to: iface, kind: implements }\n```\nNode `kind` is one of: `engine | core \xB7 interface \xB7 strategy | adapter | impl \xB7\ncontroller | handler | route \xB7 service | usecase | apiclient | client \xB7\nrepository | repo | dao \xB7 worker | consumer \xB7 middleware \xB7 model | entity \xB7\ndb | store | database \xB7 cache \xB7 queue | bus | broker \xB7 state | store_state \xB7\nhook \xB7 external | backend | api | thirdparty`. Edge `kind` is\n`uses | implements | egress | https | api | reads | dashed | async`.\n`interface` nodes render with an \xABinterface\xBB stereotype banner.\n\n#### `frontend` \u2014 top-down component tree\n```frontend\ntitle: React component tree\nnodes:\n - { id: app, kind: root, name: App }\n - { id: layout, parent: app, kind: layout, name: Layout }\n - { id: page, parent: layout, kind: page, name: HomePage }\n - { id: hook, parent: page, kind: hook, name: useData }\n```\n`kind` is `root | layout | page | component | leaf | provider | context |\nhook | store | state`. Parents render above children with link paths.\n\n#### `uml` \u2014 class diagram\n```uml\nclasses:\n - { id: order, col: 1, row: 1, name: Order, attrs: ["id: UUID", "status: Status"], methods: ["place()", "cancel()"] }\n - { id: status, col: 1, row: 2, name: Status, stereotype: enumeration, attrs: ["PENDING", "CONFIRMED"] }\nrels:\n - { from: order, to: status, kind: association, label: has }\n```\nRelation `kind` is `inheritance | extends | implementation | implements |\ncomposition | aggregation | dependency | association` (drives the marker\nshape).\n\n#### `dag` \u2014 pipeline / DAG (reuses flow\'s renderer)\n```dag\ntitle: CI pipeline\nnodes:\n - { id: src, col: 1, row: 1, kind: start, label: Source }\n - { id: build, col: 2, row: 1, kind: process, label: Build }\n - { id: deploy, col: 3, row: 1, kind: end, label: Deploy }\nedges:\n - { from: src, to: build }\n - { from: build, to: deploy }\n```\n\n### Flow & process\n\n#### `flow` \u2014 flowchart with decisions\n```flow\ntitle: Decision flow\nnodes:\n - { id: start, col: 1, row: 1, kind: start, label: Start }\n - { id: check, col: 2, row: 1, kind: decision, label: Token valid? }\n - { id: ok, col: 3, row: 1, kind: end, label: Done }\n - { id: bad, col: 2, row: 2, kind: end, label: Reject }\nedges:\n - { from: start, to: check }\n - { from: check, to: ok, label: "yes" }\n - { from: check, to: bad, label: "no", kind: error }\n```\n`kind` is `start | end | decision | process`. Edge `kind: error` (or labels\nstarting with `no/fail/error/reject`) render in red.\n\n#### `dfd` \u2014 data-flow diagram\n```dfd\nnodes:\n - { id: client, col: 1, row: 1, kind: external, name: Client }\n - { id: proc, col: 2, row: 1, kind: process, name: Place order, num: 1 }\n - { id: db, col: 3, row: 1, kind: store, name: orders }\nedges:\n - { from: client, to: proc }\n - { from: proc, to: db }\n```\n`kind` is `process | external | store | datastore`. Optional `num` on\nprocesses.\n\n#### `swimlane` \u2014 cross-functional process\n```swimlane\nlanes:\n - { label: Customer }\n - { label: Sales }\nsteps:\n - { id: req, col: 1, lane: 0, kind: start, label: Submit }\n - { id: fulfill, col: 2, lane: 1, label: Fulfill }\nlinks:\n - { from: req, to: fulfill }\n```\nStep `kind` is `action | decision | start | end | wait`.\n\n### Charts & overviews\n\n#### `graph` \u2014 node-link graph\n```graph\nnodes:\n - { id: a, col: 1, row: 1, label: Module A, group: 0 }\n - { id: b, col: 2, row: 1, label: Module B, group: 1 }\nedges:\n - { from: a, to: b, dir: undirected }\n```\n`group: <n>` cycles through the chart palette. Edge `dir` is `directed`\n(default) or `undirected`.\n\n#### `mece` \u2014 issue tree (MECE breakdown)\n```mece\ntitle: Why are conversions down?\nnodes:\n - { id: root, label: Lower conversion }\n - { id: traffic, parent: root, label: Traffic quality }\n - { id: friction, parent: root, label: Funnel friction }\n - { id: f1, parent: friction, label: Slow checkout, note: p95 > 4s }\n```\nLeft-to-right tree, depth-coloured stripes, DFS layout.\n\n#### `tree` \u2014 indented hierarchy (HTML, not SVG)\n```tree\nnodes:\n - { id: src, label: src }\n - { id: components, parent: src, label: components }\n - { id: index, parent: src, label: index.ts, note: entry }\n```\n\n#### `gantt` \u2014 schedule bars\n```gantt\nperiods: [Q1, Q2, Q3, Q4]\ntasks:\n - { label: Discovery, start: 0, span: 1, kind: done }\n - { label: Build, start: 1, span: 2, kind: active }\n - { label: GA, start: 3, span: 1, kind: milestone }\n```\nTask `kind` is `done | active | current | milestone` (drives bar colour).\n\n#### `funnel` \u2014 conversion funnel\n```funnel\nstages:\n - { label: Visited, value: 10000 }\n - { label: Signed up, value: 2400 }\n - { label: Paying, value: 320 }\n```\nAuto-computes conversion percentages.\n\n#### `pyramid` \u2014 stacked hierarchy (top \u2192 bottom widening)\n```pyramid\nlevels:\n - { label: Vision, desc: Long-term direction }\n - { label: Tactics, desc: This quarter }\n```\n\n#### `quadrant` \u2014 2\xD72 matrix\n```quadrant\nxAxis: { label: Effort, low: Low, high: High }\nyAxis: { label: Impact, low: Low, high: High }\nitems:\n - { x: 0.2, y: 0.8, label: Quick win }\n - { x: 0.8, y: 0.8, label: Big bet }\n```\n`x` / `y` are 0..1.\n\n#### `journey` \u2014 user journey map with optional emotion curve\n```journey\nstages: [{ label: Discover }, { label: Sign up }, { label: Pay }]\nrows:\n - { label: Touchpoint, cells: [Landing, Form, Checkout] }\n - { label: Friction, cells: [Low, High, Medium] }\nemotion: [0.7, 0.3, 0.8]\n```\n\n### Planning & meta\n\n#### `userstory` \u2014 agile story + acceptance criteria + links\n```userstory\nid: US-142\nrole: shopper\nwant: pay for my cart in one step\nsoThat: I can complete my purchase quickly\npriority: High\npoints: 5\ncriteria:\n - { given: I have items, when: I submit valid payment, then: an order is created }\nlinks:\n - { ref: orders-api#seq-place-order, mode: sequence, label: Request flow }\n```\n`links` may use `ref: doc#id` (a real cross-reference) or a plain label.\n\n#### `timeline` \u2014 phases / roadmap\n```timeline\nitems:\n - { label: P0 \u2014 Core, date: now, status: current, desc: parser + resolver }\n - { label: P1 \u2014 CLI, date: next, status: next, desc: init / check / render }\n```\n`status` is `done | current | next | future` (colours the dot).\n\n#### `kanban` \u2014 flexible columns\n```kanban\ncolumns:\n - label: Now\n cards:\n - { title: Core parser }\n - { title: Validation, tag: priority }\n - label: Next\n cards:\n - { title: Hot reload }\n```\n\n#### `tracker` \u2014 task list with status / priority / owner / due\n```tracker\nitems:\n - { task: First task, status: doing, priority: high, owner: alice, due: 2026-01-15 }\n - { task: Second task, status: todo, priority: med }\n```\n`status` is `todo | doing | done | blocked`; `priority` is `high | med | low`.\n\n#### `cvt` \u2014 current vs target (before / after)\n```cvt\ntitle: Migration plan\ncurrent:\n label: Today\n items: [Single monolith, Shared DB, Manual deploys]\ntarget:\n label: Target\n items: [Modular services, Per-service stores, Continuous releases]\nnote: Migrate one service per quarter.\n```\n\n#### `proscons` \u2014 pros vs cons (two columns)\n```proscons\nprosLabel: Synchronous\nconsLabel: Asynchronous\npros: [Easy to reason about, One transaction]\ncons: [Latency-bound, Single point of failure]\n```\n\n#### `agenda` \u2014 meeting agenda\n```agenda\nitems:\n - { time: "09:00", duration: 30m, title: Round-robin, owner: Host }\n - { time: "09:30", duration: 60m, title: Deep dive, desc: API team }\n```\n\n### UI mockups\n\n#### `wireframe` \u2014 low-fi screen mockups (desktop / browser / phone)\n```wireframe\ntitle: What the user sees\nscreens:\n - device: browser\n title: Notification center\n url: app.example.com/inbox\n label: Desktop \u2014 notification center\n elements:\n - { type: nav, label: "Home, Inbox, Settings" }\n - { type: header, label: Notifications }\n - { type: badge, label: "3 new", tone: danger, align: r }\n - { type: list, rows: 4 }\n - { type: button, label: Mark all as read }\n - device: phone\n title: "9:41"\n label: iPhone \u2014 live bell + feed\n elements:\n - { type: header, label: Alerts }\n - { type: card, rows: 3 }\n - { type: tabs, label: "Home, Search, Bell, You" }\n```\n`screens` lay out left-to-right; each picks a `device` frame (`desktop` /\n`browser` / `phone`) and stacks `elements` top-to-bottom. `device: browser`\nshows an address bar (`url`); `phone` adds a notch + home indicator. `title`\nis the window/status-bar text, `label` is the caption under the frame.\n\nElement `type` is one of: `header \xB7 subheader \xB7 text \xB7 button \xB7 input \xB7 search\n\xB7 image \xB7 avatar \xB7 card \xB7 list \xB7 nav \xB7 tabs \xB7 divider \xB7 badge \xB7 toggle \xB7\nspacer`. `rows` repeats stack-like elements (`list` / `card`) or sizes `text` /\n`spacer`. `nav` / `tabs` read their items from a **comma-separated** `label`\n(quote it). `align` is `l | c | r`; `tone` is `accent | muted | danger` (colours\nbuttons, badges, toggles). Keep it low-fidelity \u2014 it\'s a wireframe, not a comp.\n\n## Cross-references (`doc#id`)\n\nBlocks become a connected model through references:\n\n- Give a block a unique `id:` (unique across the **whole repo**).\n- Reference it as `doc#id`, where `doc` is the target file\'s path **under the\n docs root** without `.md` (e.g. `orders-api`, or `architecture/overview`).\n A bare `#id` means the current document \u2014 **always prefer `#id` when\n referencing inside the same doc**, since it survives renames.\n- A reference whose target id does not exist is a **dangling reference** and\n fails validation. Only add a `ref` to an id you know exists (or are creating\n in the same change).\n- **Don\'t repeat the current document\'s slug in a ref.** If you\'re editing\n `docs/orders.md` and want to point at `id: seq-place-order` in the same file,\n write `ref: "#seq-place-order"`, NOT `ref: "orders#seq-place-order"`.\n\nThe only reference-bearing field in v1 is `userstory.links[].ref`.\n\n## Workflow \u2014 always validate\n\nAfter creating or editing any doc, run the CLI and fix everything it reports:\n\n```\navo check # validate all docs: schema + dangling refs + dup ids\navo check docs/orders-api.md # validate one file\navo check --json # machine-readable, useful in CI\navo render docs/orders-api.md -o out.html\navo preview docs/orders-api.md # render and open it\navo export docs/**/*.md --format pdf --out dist/\navo new # scaffold a new doc or block from a template\navo sync openapi spec.yaml --out docs/api.md # generate a doc from an OpenAPI spec\n```\n\n`avo check` exits non-zero on any error and names the file, line, and\noffending value. **A change is not done until `avo check` passes.**\n\n## When `avo check` fails \u2014 error code recipes\n\nEvery diagnostic carries a stable code so you can mechanically apply a fix.\n\n| Code | What it means | First thing to check |\n|---|---|---|\n| `E_PARSE_YAML` | YAML body failed to parse. Almost always a quoting issue. | Re-read *YAML pitfalls* above. Unquoted `,`/`:`/`#` in a `desc` is the usual culprit. |\n| `E_SCHEMA` | A field is missing, the wrong type, or an unknown name. Message contains the path (e.g. `sequence: messages.2.kind: ...`). | Compare your YAML against the block reference. Reject the urge to add fields not listed in this skill \u2014 the schema is strict. |\n| `E_DANGLING_REF` | A `userstory.links[].ref` points at an id that doesn\'t exist anywhere in the repo. `value` is the bad ref. | Either fix the ref string, or add the missing `id:` to the target block. Bare `#id` is current-doc; `doc#id` is path-under-docs-root + `#id`. |\n| `E_DUP_ID` | The same `id:` was used in two blocks. Message names both files + lines. | Ids are repo-global. Rename one. |\n| `E_BAD_REF_FORMAT` | A `ref:` string isn\'t `doc#id` or `#id` shape. | Match the format exactly. The id slug is `[\\w-]+`. |\n| `W_EMPTY_BLOCK` | A typed block had an empty body. | Add fields or remove the block. |\n\n### Common schema errors I see often\n\n| Symptom | Cause | Fix |\n|---|---|---|\n| `Expected string, received number` on `tech: 16` | YAML parsed `16` as a number. | Quote: `tech: "16"`. |\n| `Invalid enum value` on `tone: xyz` / `kind: xyz` / `status: xyz` | Used a value not in the enum. | Stick to the documented enum (`tone: note\\|tip\\|warn\\|danger`, etc.). |\n| `Unrecognized key(s) in object: \'foo\'` | You added a field that isn\'t in the schema. | Schemas are strict. Either remove the field, or use a documented one. |\n| Schemas on the `meta` block fail | You put a `meta` block somewhere other than first. | Move it to the top of the file. |\n| `Unrecognized key(s) in object: \'persists\'` and similar | Unquoted comma in a flow-style mapping turned a phrase into multiple keys. | Quote the value containing the comma. |\n\n## Field semantics \u2014 clarifications\n\nA few fields are easy to misuse. Lock these in.\n\n- `sequence.actors[].sub` is the **subtitle** under the actor\'s name on the\n lane head (e.g. `sub: web / mobile`, `sub: orders handler`). Keep it short \u2014\n 2-4 words.\n- `sequence.actors[].external: true` darkens the lane (slate instead of navy),\n signaling the actor lives outside your service boundary.\n- `sequence.messages[].kind: note` is **not a message** \u2014 it\'s a numbered\n annotation on the from-actor\'s lane, with no arrow. Use it for things like\n "validate token" that don\'t cross a boundary.\n- `sequence.messages[].summary` is the longer text shown in the step-by-step\n list **below** the SVG. Keep `label` short (the SVG arrow) and put detail in\n `summary`. `code:` adds a `<pre>` snippet inside the step item.\n- On most diagram blocks: `lede` renders as a `<p class="section-lede">` under\n the section title, sized for an editorial paragraph. `description` renders\n inside the diagram frame as the diagram\'s caption. Use both when you have\n both kinds of text to convey.\n- `userstory.links[].ref` is the only field in v1 that creates a real\n cross-document reference. Other `links` items render as plain chips.\n- `block` / `infra` / `event` / `ddd` / `network` use **identical YAML** \u2014 the\n block type slug only changes the colored tag pill. Pick the slug that best\n signals intent to a reader, not for any structural reason.\n- `userstory.id` is what other docs reference. Use a short stable id like\n `US-142`, not a sentence.\n- Diagram blocks with `layers:` set go into **horizontal-band layout**. Without\n `layers:` they use **grid layout** with `col`/`row`. Don\'t mix \u2014 the renderer\n uses the presence of `layers` to switch modes.\n\n## Do / Don\'t\n\n**Do**\n\n- Edit the specific block you need to change \u2014 surgically, a few lines \u2014 rather\n than regenerating a whole document.\n- Keep narrative in Markdown prose and structure in blocks.\n- Use `title` + `lede` on diagram blocks so the section header reads well.\n- Quote YAML values that contain commas, colons, or `1:N` cardinality strings\n (`desc: "40 blocks, themes, agent skill"`, `card: "1:N"`).\n- Give a block an `id:` whenever something else might reference it.\n- Run `avo check` and resolve all diagnostics before finishing.\n- When unsure which architecture block to use, pick `block` for boxes-and-arrows\n or `c4` for actor / system context \u2014 both are safe defaults.\n\n**Don\'t**\n\n- Paste raw HTML, `<svg>`, or `<style>` into a doc. Use blocks.\n- Invent block types or fields. The schemas are strict; unknown fields error.\n- Reference a `doc#id` that doesn\'t exist. Either fix the ref or add the id.\n- Stuff a whole spec into one giant block. Decompose into 3-5 focused blocks.\n- Write a `description` longer than 2 sentences. Use prose instead for long\n narrative.\n- Put commas inside flow-style mappings without quoting (see *YAML pitfalls*).\n- Reuse the same `id:` in two blocks. Ids are repo-global unique.\n- Add a `prose` block AND raw `##` headings for the same idea. Pick one.\n- Use `frontend` for backend modules, or `felogic` when you mean `frontend`.\n `frontend` is a top-down hierarchical tree; `felogic` / `belogic` are\n free-positioned module graphs with edges.\n\n## Quick block index (in case you forget)\n\n| Family | Blocks |\n|---|---|\n| Document & meta | `meta` |\n| Prose & structure | `prose` `callout` `glossary` |\n| Tables & metrics | `table` `stats` `code` |\n| Sequence & state | `sequence` `state` |\n| Data model | `erd` |\n| Architecture | `c4` `block` `infra` `event` `ddd` `network` `cluster` |\n| Code-flavoured | `felogic` `belogic` `frontend` `uml` `dag` |\n| Flow & process | `flow` `dfd` `swimlane` |\n| Charts & overviews | `graph` `mece` `tree` `gantt` `funnel` `pyramid` `quadrant` `journey` |\n| Planning & meta | `userstory` `timeline` `kanban` `tracker` `cvt` `proscons` `agenda` |\n| UI mockups | `wireframe` |\n';
20
20
 
21
21
  // src/server.ts
22
- var THEMES = ["navy", "soft", "dark", "teal", "plum", "slate"];
22
+ var THEMES = ["textbook", "minimal", "soft", "dark", "teal", "plum", "slate"];
23
23
  function formatDiagnostics(diags) {
24
24
  if (diags.length === 0) return "OK \u2014 no diagnostics. The document is valid.";
25
25
  return diags.map((d) => {
@@ -53,7 +53,7 @@ server.registerTool(
53
53
  inputSchema: {
54
54
  markdown: z.string(),
55
55
  slug: z.string().optional(),
56
- theme: z.enum(THEMES).optional().describe("Visual theme (default navy).")
56
+ theme: z.enum(THEMES).optional().describe("Visual theme (default textbook).")
57
57
  }
58
58
  },
59
59
  ({ markdown, slug, theme }) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/skill.generated.ts"],"sourcesContent":["/**\n * Avodado MCP server.\n *\n * Exposes Avodado's pure document tooling (parse, validate, render, schemas,\n * cross-references, OpenAPI sync) and the authoring grammar as MCP tools +\n * resources, so any MCP client (Claude Code/Desktop, Cursor, …) can author,\n * validate, and render Avodado documents natively.\n *\n * Transport: stdio. Run via `npx @avodado/mcp` (or the `avodado-mcp` bin).\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport {\n parseDocument,\n validateDocument,\n resolveRefs,\n blockSchemas,\n BLOCK_TYPES,\n type Diagnostic,\n type InputDocument,\n} from '@avodado/core';\nimport { renderDocument, type ThemeName } from '@avodado/render';\nimport { openapiToMarkdown } from '@avodado/sync';\nimport { SKILL_MD } from './skill.generated.js';\n\nconst THEMES = ['navy', 'soft', 'dark', 'teal', 'plum', 'slate'] as const;\n\nfunction formatDiagnostics(diags: readonly Diagnostic[]): string {\n if (diags.length === 0) return 'OK — no diagnostics. The document is valid.';\n return diags\n .map((d) => {\n const loc =\n d.line !== undefined ? `:${d.line}${d.column !== undefined ? `:${d.column}` : ''}` : '';\n const hint = d.hint !== undefined ? ` (hint: ${d.hint})` : '';\n return `${d.level.toUpperCase()} ${d.file}${loc} [${d.code}] ${d.message}${hint}`;\n })\n .join('\\n');\n}\n\nconst server = new McpServer({ name: 'avodado', version: '0.0.1' });\n\nserver.registerTool(\n 'check_document',\n {\n title: 'Check an Avodado document',\n description:\n 'Parse and validate Avodado Markdown (prose + typed YAML blocks). Returns diagnostics; \"OK\" means valid. Use this after writing or editing a document.',\n inputSchema: {\n markdown: z.string().describe('The Avodado document Markdown.'),\n slug: z.string().optional().describe('Document slug (defaults to \"doc\").'),\n },\n },\n ({ markdown, slug }) => {\n const s = slug ?? 'doc';\n const diags = validateDocument(parseDocument(markdown, s), s);\n return { content: [{ type: 'text', text: formatDiagnostics(diags) }] };\n },\n);\n\nserver.registerTool(\n 'render_document',\n {\n title: 'Render an Avodado document to HTML',\n description: 'Render Avodado Markdown to a standalone, styled HTML document.',\n inputSchema: {\n markdown: z.string(),\n slug: z.string().optional(),\n theme: z.enum(THEMES).optional().describe('Visual theme (default navy).'),\n },\n },\n ({ markdown, slug, theme }) => {\n const html = renderDocument(\n parseDocument(markdown, slug ?? 'doc'),\n theme !== undefined ? { theme: theme as ThemeName } : {},\n );\n return { content: [{ type: 'text', text: html }] };\n },\n);\n\nserver.registerTool(\n 'list_block_types',\n {\n title: 'List Avodado block types',\n description: 'List every supported Avodado block type.',\n inputSchema: {},\n },\n () => ({ content: [{ type: 'text', text: BLOCK_TYPES.join('\\n') }] }),\n);\n\nserver.registerTool(\n 'get_block_schema',\n {\n title: 'Get a block JSON Schema',\n description: 'Return the JSON Schema (fields, enums) for a given Avodado block type.',\n inputSchema: { type: z.enum([...BLOCK_TYPES] as [string, ...string[]]) },\n },\n ({ type }) => {\n const schema = blockSchemas[type as keyof typeof blockSchemas];\n const json = zodToJsonSchema(schema, type);\n return { content: [{ type: 'text', text: JSON.stringify(json, null, 2) }] };\n },\n);\n\nserver.registerTool(\n 'resolve_refs',\n {\n title: 'Resolve cross-document references',\n description:\n 'Check `doc#id` references across multiple Avodado documents (dangling refs, duplicate ids).',\n inputSchema: {\n documents: z\n .array(z.object({ slug: z.string(), markdown: z.string() }))\n .describe('The documents to cross-check.'),\n },\n },\n ({ documents }) => {\n const inputs: InputDocument[] = documents.map((d) => ({\n doc: parseDocument(d.markdown, d.slug),\n file: d.slug,\n }));\n const { diagnostics } = resolveRefs(inputs);\n return { content: [{ type: 'text', text: formatDiagnostics(diagnostics) }] };\n },\n);\n\nserver.registerTool(\n 'sync_openapi',\n {\n title: 'Generate an Avodado doc from OpenAPI',\n description: 'Convert an OpenAPI spec (JSON) into an Avodado Markdown document.',\n inputSchema: {\n spec: z.string().describe('The OpenAPI spec as a JSON string.'),\n slug: z.string().optional(),\n },\n },\n ({ spec, slug }) => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(spec);\n } catch {\n return { isError: true, content: [{ type: 'text', text: 'Invalid JSON spec.' }] };\n }\n const md = openapiToMarkdown(\n parsed as Parameters<typeof openapiToMarkdown>[0],\n slug !== undefined ? { slug } : {},\n );\n return { content: [{ type: 'text', text: md }] };\n },\n);\n\nserver.registerTool(\n 'get_authoring_guide',\n {\n title: 'Get the Avodado authoring guide',\n description:\n 'Return the full Avodado authoring grammar (block types, every field, YAML pitfalls, recipes). Read this BEFORE authoring Avodado documents.',\n inputSchema: {},\n },\n () => ({ content: [{ type: 'text', text: SKILL_MD }] }),\n);\n\nserver.registerResource(\n 'authoring-skill',\n 'avodado://skill',\n {\n title: 'Avodado authoring guide',\n description: 'The block grammar, fields, and authoring rules for Avodado documents.',\n mimeType: 'text/markdown',\n },\n (uri) => ({\n contents: [{ uri: uri.href, mimeType: 'text/markdown', text: SKILL_MD }],\n }),\n);\n\nasync function main(): Promise<void> {\n await server.connect(new StdioServerTransport());\n // Protocol uses stdout; logs go to stderr.\n console.error('avodado-mcp server running on stdio');\n}\n\nmain().catch((err: unknown) => {\n console.error(err);\n process.exit(1);\n});\n","// AUTO-GENERATED from packages/cli/templates/.avodado/skill/SKILL.md — do not edit.\nexport const SKILL_MD = \"---\\nname: avodado-docs\\ndescription: >-\\n Use whenever you author, edit, validate, or review Avodado documentation —\\n Markdown files that mix prose with typed YAML blocks (sequence · erd · table ·\\n callout · userstory · timeline · kanban · tracker · meta · prose · glossary ·\\n proscons · cvt · stats · code · agenda · tree · pyramid · funnel · flow · state ·\\n dfd · journey · gantt · graph · quadrant · swimlane · c4 · uml · mece · frontend ·\\n cluster · block · infra · event · ddd · network · felogic · belogic · dag ·\\n wireframe).\\n Trigger on any of: docs/**/*.md in an Avodado repo, the `avo` CLI, any block\\n type above, `doc#id` cross-references, presence of `avodado.config.*` or\\n `.avodado/skill/SKILL.md` in the workspace, or user mentions \\\"avodado\\\". Covers\\n block grammar, every block's fields, the reference scheme, YAML pitfalls, and\\n the validate workflow.\\n---\\n\\n# Authoring Avodado documents\\n\\n> Repo location: commit this file at `.avodado/skill/SKILL.md`. `avo init`\\n> copies it into new projects and writes editor adapters (`CLAUDE.md`,\\n> `.cursor/rules/avodado.mdc`) that point here so Claude Code, Cursor, and\\n> other agents pick it up automatically.\\n\\nAvodado documents are **plain Markdown with typed, fenced YAML blocks**. Prose\\nis ordinary Markdown; anything structured (a diagram, a table, a user story,\\na chart) is a fenced code block whose info-string is the block *type*, with a\\nYAML body.\\n\\n**The one rule:** the `.md` file is the source of truth. You edit files\\ndirectly. A document must read fine as plain text with no tooling, so never\\npaste raw HTML or inline SVG — express structure through blocks instead.\\n\\n## Authoring recipe — follow this every time\\n\\nAny time you write or edit an Avodado doc, work through these steps in order.\\nSkipping steps is the source of every authoring failure I've seen.\\n\\n1. **Identify the doc's job.** Is this an API spec, an architecture overview, a\\n roadmap, a runbook, a meeting agenda? The job picks the blocks (see *Choose\\n your block* below).\\n2. **Start with `meta`** — title + subtitle + tag. First block, always.\\n3. **Add a short prose intro** under `## Overview`. 2-4 sentences. Plain Markdown.\\n4. **Pick 2-5 blocks that carry the structure.** Don't try to use all 41 in one doc.\\n If the content *describes* an architecture, a layering, a pipeline, a component\\n tree, or a set of gates, **adapt it to the matching diagram — don't leave it as\\n prose and don't flatten it into a table.** A table is for genuinely tabular data\\n (rows × columns of values), never for boxes-and-arrows. See *Adapt the content*\\n and the *Block glossary* below.\\n5. **Give each referenceable block an `id:`** (a short slug). Other blocks reach\\n it as `doc#id` from elsewhere; bare `#id` works inside the same doc.\\n6. **Use `title` + optional `lede` on diagram blocks** so the section header reads\\n like an editorial document, not a dump of YAML.\\n7. **Quote any string containing `,` `:` `[` `]` `{` `}` `#` `&` `*` `!` `|` `>`\\n `'` `\\\"`.** See *YAML pitfalls* below for the table of things that bite you.\\n8. **Run `avo check`.** If anything's red, fix it before you call the change\\n done. A passing check is the definition of done.\\n\\n## Choose your block — decision tables\\n\\nMost authoring failures come from picking the wrong block. Use these tables.\\n\\n### Block glossary — one line on what each is *for*\\n\\nThe whole vocabulary at a glance. Read this first; it's the map from *a concept in\\nyour head* to *a block*. The detailed family tables below disambiguate the close calls.\\n\\n| Block | What it represents |\\n|---|---|\\n| `meta` | Document header — title, subtitle, tag pill. Always the first block. |\\n| `callout` | A single aside: note / tip / warn / danger. |\\n| `prose` | Structured prose (headings, paragraphs, lists, quotes) carried as data. |\\n| `glossary` | Term → definition rows. |\\n| `proscons` | Two columns weighed against each other: pros vs cons. |\\n| `cvt` | Current → target (before / after) as two side-by-side panels. |\\n| `agenda` | Meeting agenda — time, duration, owner, topic per row. |\\n| `table` | Genuinely tabular data (rows × columns of values); cells can carry tone. |\\n| `stats` | KPI cards — a value with a delta and an up/down/flat trend. |\\n| `code` | One or more syntax-highlighted snippets under a titled header bar. |\\n| `tracker` | A task list with status / priority / owner / due. |\\n| `kanban` | Flexible named columns (e.g. Now / Next / Later) of cards. |\\n| `timeline` | Phases in order with status dots (done / current / next / future). |\\n| `gantt` | A schedule — tasks as bars across date columns. |\\n| `userstory` | An agile story: role / want / soThat + acceptance criteria + links. |\\n| `sequence` | Messages between actors **over time** (lifelines, returns); optional step list + endpoint pill. |\\n| `state` | A state machine — states + event transitions (+ a transition table). |\\n| `flow` | A decision flowchart — start / process / decision / end nodes, with `error` exits. |\\n| `dag` | A pipeline / DAG — same shapes as `flow`, framed for CI/CD. |\\n| `dfd` | Data-flow — processes, external entities, and datastores. |\\n| `swimlane` | A cross-functional process with one horizontal lane per role. |\\n| `journey` | A user journey across stages, with an optional emotion curve. |\\n| `erd` | Entity-relationship diagram — tables, columns, PK/FK, crow's-foot cardinality. |\\n| `uml` | A class diagram — attributes, methods, UML relationships. |\\n| `c4` | C4 model (context / container / component) — people, systems, containers, stores. |\\n| `block` | Generic boxes-and-arrows architecture — grid **or** horizontal `layers`, dashed `groups` zones. |\\n| `infra` | Cloud topology (same engine as `block`) — CDN / gateway / compute / DB, nested account & network zones. |\\n| `event` | Pub/sub topology (same engine) — producers → topics → consumers. |\\n| `ddd` | DDD bounded-context map (same engine). |\\n| `network` | Security zones with trust boundaries (same engine); supports `forbidden` (red) edges. |\\n| `cluster` | Kubernetes-style namespaces holding services, with replica counts. |\\n| `frontend` | A top-down component tree — root / layout / page / component / provider / hook / store. |\\n| `felogic` | Frontend module/logic graph — components, hooks, interfaces, strategies; group zones + egress edges. |\\n| `belogic` | Backend module/logic graph (same engine) — controller / service / repository / adapter / gateway + egress. |\\n| `graph` | A generic node-link graph with colour-cycled groups. |\\n| `mece` | A MECE issue tree — one problem broken into mutually-exclusive branches. |\\n| `tree` | An indented file/folder hierarchy (HTML, not SVG). |\\n| `pyramid` | A layered pyramid (strategy / hierarchy), widening top → bottom. |\\n| `funnel` | A conversion funnel with auto-computed percentages. |\\n| `quadrant` | A 2×2 matrix (e.g. effort vs impact) with plotted items. |\\n| `wireframe` | Low-fi UI mockups inside device frames — desktop / browser / phone screens. |\\n\\n### Adapt the content — signals that should trigger a diagram\\n\\nWhen you're handed prose, a spec, or a generic table, these cues in the *source*\\ntell you which diagram it really wants. This is the step people skip — and then\\neverything degrades into tables and sequences.\\n\\n| If the source describes… | Adapt it to | Not |\\n|---|---|---|\\n| \\\"layers / tiers / sits on top of / front-to-back / N-tier\\\" | `block` (with `layers`) or `infra` | a table |\\n| \\\"the platform: these services + a shared backbone, who calls what\\\" | `block` / `infra` / `cluster` | a table |\\n| \\\"a person uses the system, which depends on external systems\\\" | `c4` (level: context) | prose |\\n| \\\"N checks/gates **in order**, any one can reject the request\\\" | `flow` (decision nodes + `kind: error` exits) | a `sequence` — gates aren't temporal |\\n| \\\"A happens, then B, then C, then a reply comes back\\\" (over time) | `sequence` | a `flow` |\\n| \\\"who does what across teams, step by step\\\" | `swimlane` | a `flow` |\\n| \\\"components / providers / hooks / context / store\\\" | `frontend` (tree) or `felogic` (with patterns + egress) | a table |\\n| \\\"controller / service / repository / adapter / gateway / middleware / Depends()\\\" | `belogic` | a `sequence` |\\n| \\\"producers emit events → topics → consumers\\\" | `event` | a `flow` |\\n| \\\"namespaces / pods / replicas / deployments\\\" | `cluster` | a `block` |\\n| \\\"trust boundary / DMZ / zones / must-not-call\\\" | `network` (with `forbidden` edges) | a `block` |\\n| \\\"tables, schema, primary/foreign keys, relationships\\\" | `erd` | a `table` |\\n| \\\"options compared with verdicts/criteria\\\" | `table` (this one really is tabular) | — |\\n| \\\"current state vs target state\\\" / \\\"before vs after\\\" | `cvt` | a 2-column `table` |\\n| \\\"pros vs cons / trade-offs for one option\\\" | `proscons` | a `table` |\\n| \\\"why is X happening — break the causes down\\\" | `mece` | a bulleted list |\\n| \\\"phases / rollout in order\\\" | `timeline` (status) or `gantt` (real dates) | a `table` |\\n| \\\"what the user sees / the screen / the app / the bell + feed\\\" | `wireframe` (desktop / browser / phone) | prose |\\n\\n> **The rule:** if the source *describes* a structure — an architecture, a layering,\\n> a pipeline, a component tree, a set of gates — render it as the matching **diagram**.\\n> Prose and tables are the fallback for things that are genuinely paragraphs and\\n> genuinely rows-of-values, not the default for everything.\\n\\n### Architecture and topology (which one when?)\\n\\n| If you want to show… | Use | Notes |\\n|---|---|---|\\n| Who uses the system + which external systems it depends on | `c4` (level: context) | One node per actor / system |\\n| Containers inside a system, with optional boundary box | `c4` (level: container) | Use `family` to colour-code (client / service / data / store) |\\n| Components inside one container | `c4` (level: component) | Same shape, finer granularity |\\n| Generic boxes-and-arrows architecture | `block` | Grid layout; add `groups` for dashed zones; add `layers` to switch to horizontal-band layout |\\n| Cloud deployment (CDN, gateway, compute, DB, …) | `infra` | Same engine as `block`; conventionally for cloud topology |\\n| Pub/sub event topology (producers → topics → consumers) | `event` | Same engine; conventionally for choreography |\\n| Bounded-context map for DDD | `ddd` | Same engine; conventionally for context maps |\\n| Security zones with trust boundaries | `network` | Same engine; supports `kind: forbidden` edges (red) |\\n| Kubernetes-style namespaces with services inside | `cluster` | Has its own nested-box engine; supports `replicas` count |\\n\\n> `block` / `infra` / `event` / `ddd` / `network` share **one renderer**.\\n> They differ only by the colored tag pill above the diagram (ARCH / INFRA / EVENT\\n> / DDD / ZONES). Pick the slug that best signals intent to a reader; the YAML\\n> grammar is identical.\\n\\n### Charts and overviews\\n\\n| If you want to show… | Use |\\n|---|---|\\n| KPI values with deltas + up/down arrows | `stats` |\\n| Tabular data with optional cell tones | `table` |\\n| Task list with status / owner / priority / due | `tracker` |\\n| Now / Next / Later flexible columns | `kanban` |\\n| Phases with status dots (done / current / next / future) | `timeline` |\\n| Schedule with date columns and bars | `gantt` |\\n| Conversion funnel with auto-percentages | `funnel` |\\n| Hierarchical / strategic pyramid (top→bottom widening) | `pyramid` |\\n| 2×2 matrix (effort vs impact, etc.) | `quadrant` |\\n| User journey across stages with optional emotion curve | `journey` |\\n\\n### Process and flow\\n\\n| If you want to show… | Use |\\n|---|---|\\n| Sequence of messages over time (with optional step-by-step list + endpoint tag) | `sequence` |\\n| State machine with transitions + transition table | `state` |\\n| Generic decision flow with diamonds + stadium nodes | `flow` |\\n| Data-flow with processes, externals, datastores | `dfd` |\\n| Cross-functional flow with horizontal lanes per role | `swimlane` |\\n| CI/CD pipeline (same shapes as `flow`, navy DAG tag) | `dag` |\\n\\n### Code-flavoured\\n\\n| If you want to show… | Use |\\n|---|---|\\n| Class diagram with attrs/methods + UML markers | `uml` |\\n| Top-down React/Vue component tree | `frontend` |\\n| Frontend module graph with design patterns + interface stereotypes | `felogic` |\\n| Backend module graph — same engine as felogic | `belogic` |\\n| One or more syntax-highlighted code snippets | `code` |\\n| MECE issue tree (left → right with depth-coloured branches) | `mece` |\\n| Indented file/folder hierarchy (HTML, not SVG) | `tree` |\\n| Generic node-link graph with `group:` colour cycling | `graph` |\\n\\n### Narrative and structure\\n\\n| If you want to show… | Use |\\n|---|---|\\n| Note / tip / warning / danger box | `callout` |\\n| Structured prose (h3 + p + ul + quote sub-blocks) | `prose` |\\n| Term / definition rows | `glossary` |\\n| Two-column pros vs cons | `proscons` |\\n| Before / after, \\\"current\\\" → \\\"target\\\" | `cvt` |\\n| Meeting agenda (time + duration + title + owner) | `agenda` |\\n| User story + acceptance criteria + cross-doc links | `userstory` |\\n\\n## Mixing blocks — document recipes\\n\\nA good Avodado doc is **2-5 blocks, each a different lens** on the subject —\\n*orient → big picture → detail → plan*. Don't show the same thing in two block\\ntypes, and don't reach for all 41. Start from the doc's job and pick a stack:\\n\\n| Doc job | Core blocks (always) | Add when relevant | Skip / fold into prose when… |\\n|---|---|---|---|\\n| **API / endpoint spec** | `meta` + `sequence` (request flow) | `erd` (data touched) · `table` (status codes) · `code` (payloads) · `userstory` (the story it serves) | the call is a single hop — describe it in prose |\\n| **Architecture overview** | `meta` + `c4` (context) **or** `block`/`infra` (the landscape) | `belogic`/`felogic` (one module's internals) · `flow` (a key decision path) · `tracker` (open decisions) | there are <3 components — a `callout` is enough |\\n| **Design doc / RFC** | `meta` + `proscons` **or** `cvt` (the choice) | `mece` (problem breakdown) · `c4`/`block` (proposed arch) · `sequence`/`flow` (behavior) · `tracker` | only one option exists — just prose |\\n| **Roadmap / plan** | `meta` + `timeline` (phases) **or** `gantt` (real dates) | `kanban` (now/next/later) · `tracker` (tasks) · `stats` (targets) | — |\\n| **Runbook / procedure** | `meta` + `flow` **or** `swimlane` | `sequence` (one interaction) · `code` (commands) · `table` (symptom → action) · `callout: warn` | the steps are linear with no branches — an `ol` in `prose` |\\n| **Data model** | `meta` + `erd` | `table` (field semantics) · `state` (record lifecycle) | it's a single table — use `table` alone |\\n| **Frontend feature** | `meta` + `frontend` (tree) | `felogic` (logic + patterns) · `wireframe` (what the user sees) · `sequence` (data fetch) · `userstory` | — |\\n| **Status / metrics** | `meta` + `stats` | `funnel` · `quadrant` · `timeline` | — |\\n| **Meeting** | `meta` + `agenda` | `tracker` · `kanban` · `callout` | — |\\n\\n**Rules for combining:**\\n\\n- **One `meta`, first, always.** Everything after it is optional.\\n- **Each block earns its place as a distinct lens.** `c4`/`block` shows the\\n *structure*; `sequence`/`flow` shows *behavior*; `timeline`/`tracker` shows\\n *plan*. If two blocks would draw the same boxes (`c4` **and** `block` for the\\n same components, or `flow` **and** `sequence` for the same steps), keep one.\\n- **Connect, don't repeat.** Give the referenced block an `id:` and point at it\\n with `userstory.links[].ref: doc#id` instead of redrawing it elsewhere.\\n- **Omit a block whose data is thin.** Fewer than ~3 nodes/rows? Fold it into a\\n `callout` or a prose list — an almost-empty diagram reads worse than a sentence.\\n- **Order top-to-bottom as the reader needs it:** orient (`meta` + intro) → the\\n big picture (context / landscape) → the detail (one module / one flow) → what's\\n next (plan / tracker).\\n\\n## YAML pitfalls — quote when in doubt\\n\\nThe YAML parser is doing exactly what you asked. Most \\\"schema errors\\\" are\\nactually YAML mis-parses. **Quote the value** whenever it contains:\\n\\n| Character | What goes wrong unquoted | Fix |\\n|---|---|---|\\n| `,` (comma) | Inside `{ a, b }` flow style, treated as a separator. Your sentence becomes 3 keys. | `desc: \\\"40 blocks, themes, agent skill\\\"` |\\n| `:` (colon) | Treated as `key: value`. `1:N` becomes a number sequence. | `card: \\\"1:N\\\"` |\\n| `#` (hash) | Treated as a comment from there on. | `label: \\\"POST /orders #idempotent\\\"` |\\n| Leading `*` `&` `!` `|` `>` `%` `@` `\\\\`` | YAML anchor / tag / literal / fold / reserved characters. | Quote the whole value. |\\n| Leading `-` followed by space | Looks like a list item. | Quote. |\\n| Numeric-looking (`0`, `02`, `1e3`) | Parsed as a number, fails `string` schemas. | Quote: `delta: \\\"0\\\"`, `version: \\\"1.0\\\"` |\\n| `yes` / `no` / `true` / `false` / `null` | YAML 1.1 booleans (still around in some parsers). | Quote. |\\n| Empty | Parsed as null. | Quote: `name: \\\"\\\"` |\\n\\nInline-mapping `{ k: v }` is fine for short records (under ~5 fields). For\\nanything longer, use block-style — easier diffs, fewer comma traps:\\n\\n```yaml\\n# ✓ Good — block style for longer records\\nitems:\\n - title: Phase 1\\n when: now\\n status: active\\n detail: A longer description with, commas, in, it.\\n# ✗ Bad — flow-style with unquoted commas\\nitems:\\n - { title: Phase 1, when: now, status: active, detail: A longer description with, commas }\\n```\\n\\nWhen you write a `desc` / `note` / `summary` / `description` that contains\\nprose, **always quote it** — those fields are the #1 source of validation\\nerrors.\\n\\n## How a block looks\\n\\n````\\n## Request flow\\n\\n```sequence\\nid: seq-place-order\\ntitle: Place order\\nendpoint: { method: POST, path: /orders }\\nactors:\\n - { id: Client, name: Client }\\n - { id: API, name: Orders API }\\nmessages:\\n - { from: Client, to: API, label: POST /orders, kind: sync }\\n - { from: API, to: Client, label: 201 Created, kind: response }\\n```\\n````\\n\\nRules:\\n\\n- The info-string is exactly one of the **41 block types** listed below — never\\n invent new ones.\\n- The body is **YAML** (JSON is also accepted; YAML is preferred — prefer\\n block-style over deep inline maps for readability and clean diffs).\\n- Use only the fields documented for that block. Keep prose outside blocks.\\n- A block MAY carry a top-level `id:` (a slug) so other blocks can reference it.\\n- Most diagram blocks accept optional `title`, `description`, and `lede` —\\n these surface in the section header + diagram frame around the SVG.\\n\\n## Block data shapes — required vs optional (the contract)\\n\\nEvery block also carries optional `title`, `description`, `lede` (editorial text\\nrendered around the diagram) and an optional top-level `id:` — **none are ever\\nrequired**, so they're left out of the table below, which shows only the\\n*structural* payload. `*` marks a **required** field; everything else is optional.\\n**Omit optional fields you have no value for** — don't pad them with empty strings.\\n`(n)` marks a **number** (don't quote it); every other value is a string.\\n\\n| Block | Structural shape (`*` = required, `(n)` = number) | Closed enums |\\n|---|---|---|\\n| `meta` | `title` `subtitle` `tag` | — |\\n| `callout` | `tone` `title` `body` | tone: note · tip · warn · danger |\\n| `prose` | `blocks[]`: `type` `text` `items[]` | type: h · p · ul · ol · quote |\\n| `glossary` | `terms[]`: `term*` `def*` | — |\\n| `proscons` | `prosLabel` `consLabel` `pros[]` `cons[]` | — |\\n| `cvt` | `current{label, items[]}` `target{label, items[]}` `note` | — |\\n| `agenda` | `items[]`: `title*` `time` `duration` `owner` `desc` | — |\\n| `table` | `columns[]`: string \\\\| `{label*, align, highlight}` · `rows[][]`: string \\\\| number \\\\| `{v*, tone, lead, highlight}` · `note` | align: l · c · r — tone: pos · neg · warn · muted |\\n| `stats` | `stats[]`: `value*` `label*` `delta` `trend` `accent` | trend: up · down · flat |\\n| `code` | `blocks[]`: `code*` `title` `lang` | — |\\n| `tracker` | `items[]`: `task*` `status` `priority` `owner` `due` | status: todo · doing · done · blocked — priority: high · med · low |\\n| `kanban` | `columns[]`: `label*` `cards[]`: `title*` `tag` | — |\\n| `timeline` | `items[]`: `label*` `date` `desc` `status` | status: done · current · next · future |\\n| `gantt` | `periods[]` · `tasks[]`: `label*` `start`(n) `span`(n) `kind` | kind: done · active · current · milestone |\\n| `userstory` | `role` `want` `soThat` `priority` `points`(n) · `criteria[]`: `given` `when` `then` · `links[]`: `ref` `mode` `label` | — |\\n| `sequence` | `actors[]`: `id*` `name*` `sub` `external` · `messages[]`: `from*` `to*` `label` `kind` `summary` `code` `note` · `endpoint{method*, path*, status}` · `foot[]`: `label*` `value*` | msg kind: sync · response · async · error · note — method: GET · POST · PUT · PATCH · DELETE |\\n| `state` | `states[]`: `id*` `col*`(n) `row*`(n) `name` `kind` · `transitions[]`: `from*` `to*` `event*` `guard` | kind: start · terminal · active · wait |\\n| `flow` / `dag` | `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `label*` `kind` · `edges[]`: `from*` `to*` `label` `kind` | node kind: start · end · decision · process — edge kind: error |\\n| `dfd` | `nodes[]`: `id*` `col*`(n) `row*`(n) `name*` `kind` `num` · `edges[]`: `from*` `to*` `label` | kind: process · external · store · datastore |\\n| `swimlane` | `lanes[]`: `label*` · `steps[]`: `id*` `col*`(n) `lane*`(n) `label*` `kind` · `links[]`: `from*` `to*` `label` | kind: action · decision · start · end · wait |\\n| `journey` | `stages[]`: `label*` · `rows[]`: `label*` `cells[]` · `emotion[]`(n, 0..1) | — |\\n| `erd` | `entities[]`: `name*` `columns[]`: `name*` `type` `pk`(bool) `fk`(bool) · `relations[]`: `from*` `to*` `label` `card` | card: \\\"1:1\\\" · \\\"1:N\\\" · \\\"N:M\\\" (quote!) |\\n| `uml` | `classes[]`: `id*` `col*`(n) `row*`(n) `name*` `stereotype` `attrs[]` `methods[]` · `rels[]`: `from*` `to*` `label` `kind` | rel kind: inheritance · extends · implementation · implements · composition · aggregation · dependency · association |\\n| `c4` | `level` `boundary{label*}` · `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `kind*` `family` `name*` `tech` `desc` · `edges[]`: `from*` `to*` `label` `kind` | level: context · container · component — node kind: person · system · external · store · container · component — edge kind: solid · dashed · forbidden · error |\\n| `block` `infra` `event` `ddd` `network` | `systemLabel` · `layers[]`: `label*` · `groups[]`: `id` `col*`(n) `row*`(n) `cols`(n) `rows`(n) `label*` `color` · `nodes[]`: `id*` `name*` (`col`(n)+`row`(n) **or** `layer`(n)) `w`(n) `kind` `tech` · `edges[]`: `from*` `to*` `label` `kind` | node kind: free string (client · service · microservice · db · cache · queue · gateway · cdn · external · …) — edge kind: solid · dashed · forbidden · error |\\n| `cluster` | `clusters[]`: `id*` `label*` `kind` · `services[]`: `id*` `cluster*` `label*` `kind` `tech` `replicas`(n) · `edges[]`: `from*` `to*` `label` `kind` | edge kind: solid · dashed · forbidden · error |\\n| `frontend` | `nodes[]`: `id*` `name*` `parent` `kind` `note` | kind: root · layout · page · component · leaf · provider · context · hook · store · state |\\n| `felogic` / `belogic` | `groups[]` (as `block`) · `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `kind` `name*` `note` · `edges[]`: `from*` `to*` `label` `kind` | node kind: free string (controller · service · repository · adapter · interface · strategy · hook · …) — edge kind: uses · implements · reads · egress · https · api · dashed · async |\\n| `graph` | `nodes[]`: `id*` `col*`(n) `row*`(n) `label*` `group`(n) · `edges[]`: `from*` `to*` `label` `dir` | dir: directed · undirected |\\n| `mece` | `nodes[]`: `id*` `parent` `label*` `note` | — |\\n| `tree` | `nodes[]`: `id*` `parent` `label*` `note` | — |\\n| `pyramid` | `levels[]`: `label*` `desc` | — |\\n| `funnel` | `stages[]`: `label*` `value*` | — |\\n| `quadrant` | `xAxis{label, low, high}` `yAxis{label, low, high}` · `items[]`: `x*`(n, 0..1) `y*`(n, 0..1) `label*` | — |\\n| `wireframe` | `screens[]`: `device` `title` `url` `label` `elements[]`: `type` `label` `rows`(n) `align` `tone` | device: desktop · browser · phone — element type: header · subheader · text · button · input · search · image · avatar · card · list · nav · tabs · divider · badge · toggle · spacer — align: l · c · r — tone: accent · muted · danger |\\n\\n**Reading the contract:**\\n\\n- A block with **no items at all** is a `W_EMPTY_BLOCK` warning — give it content\\n or delete it. The `*` fields are the minimum to make each item valid.\\n- **Grid blocks** (`flow` · `state` · `dfd` · `c4` · `uml` · `graph` · `swimlane`\\n · `felogic`/`belogic` · grid-mode `block`) require `col`/`row` (1-indexed) on\\n every node. Adding `layers:` to `block`/`infra`/`event`/`ddd`/`network` switches\\n them to band layout, where nodes use `layer:` (an index) instead of `col`/`row`.\\n- **Numbers stay unquoted:** coordinates (`col` `row` `lane` `w`), `points`,\\n `replicas`, `group`, `start`/`span`, quadrant `x`/`y`, and `emotion[]`. Quote\\n anything string-like that *looks* numeric (`version`, `delta: \\\"0\\\"`) — see *YAML\\n pitfalls*.\\n- **`kind` is optional on most nodes/edges** — omit it for the neutral default;\\n set it only to get the right glyph, colour, or marker.\\n\\n## The 41 block types — by family\\n\\n### Document & meta\\n\\n#### `meta` — document cover (first block only)\\n```meta\\ntitle: Orders API\\nsubtitle: How the orders service accepts and persists a purchase.\\ntag: API · v1\\n```\\n\\n### Prose & structure\\n\\n#### `prose` — structured prose (heading / paragraph / list / quote)\\n```prose\\ntitle: Background\\nblocks:\\n - { type: h, text: Why this exists }\\n - { type: p, text: A short paragraph explaining context. }\\n - { type: ul, items: [Idea one, Idea two] }\\n - { type: quote, text: A pull-quote. }\\n```\\n\\n#### `callout` — note / tip / warning / danger\\n```callout\\ntone: warn\\ntitle: Idempotency required\\nbody: Clients must send an Idempotency-Key header so retries are safe.\\n```\\n`tone` is `note | tip | warn | danger`.\\n\\n#### `glossary` — term / definition rows\\n```glossary\\nterms:\\n - { term: Idempotent, def: A replay produces the same outcome. }\\n - { term: SLO, def: Service-level objective the team commits to. }\\n```\\n\\n### Tables & metrics\\n\\n#### `table` — comparison table\\n```table\\ncolumns: [Code, Meaning, When]\\nrows:\\n - [201, Created, Order persisted]\\n - [409, Conflict, Idempotency key reused]\\n```\\nColumns may be objects: `{ label, align: l|c|r, highlight: boolean }`. Cells\\nmay be objects: `{ v: value, tone: pos|neg|warn|muted, lead: boolean,\\nhighlight: boolean }`. Optional top-level `note`.\\n\\n#### `stats` — KPI / metric cards\\n```stats\\ntitle: This quarter\\nstats:\\n - { value: 12.4k, label: Active users, delta: \\\"+18%\\\", trend: up }\\n - { value: 99.95%, label: Uptime, delta: \\\"0\\\", trend: flat }\\n```\\n`trend` is `up | down | flat`. `delta` is a string.\\n\\n#### `code` — one or more code blocks\\n```code\\nblocks:\\n - title: schema.sql\\n lang: PostgreSQL\\n code: |\\n CREATE TABLE orders (id uuid PRIMARY KEY, total numeric);\\n```\\nRenders with syntax highlighting (kw, str, num, fn, ty, com tokens).\\n\\n### Sequence & state\\n\\n#### `sequence` — interaction over time (rich SVG + step list + footer)\\n```sequence\\nid: seq-place-order\\ntitle: One transaction wraps authorize + persist.\\nlede: Time runs downward. Solid arrows are sync; dashed are responses.\\ndescription: Happy path shown.\\nendpoint: { method: POST, path: /orders }\\nactors:\\n - { id: Client, name: Client, sub: web / mobile }\\n - { id: API, name: Orders API, sub: orders handler }\\n - { id: PG, name: Postgres, sub: orders }\\n - { id: Payment, name: Payment GW, sub: external, external: true }\\nmessages:\\n - { from: Client, to: API, label: POST /orders, kind: sync, summary: \\\"Place the order with cart, token, idempotency key.\\\", code: \\\"POST /orders\\\\nIdempotency-Key: ...\\\" }\\n - { from: API, to: API, kind: note, label: validate token, summary: \\\"Validate bearer, check idempotency key.\\\" }\\n - { from: API, to: PG, label: INSERT order, kind: sync, summary: \\\"Open the txn and insert in PENDING.\\\", note: \\\"Required index: orders(idempotency_key).\\\" }\\n - { from: PG, to: API, label: order_id, kind: response, summary: \\\"Returns the new order_id.\\\" }\\n - { from: API, to: Client, label: 201 Created, kind: response, summary: \\\"201 with the order.\\\" }\\nfoot:\\n - { label: Target p95, value: 250ms }\\n - { label: Idempotent, value: via Idempotency-Key (24h TTL) }\\n```\\nEach message: `from` + `to` (must match an actor `id`), `label`,\\noptional `kind` (`sync | response | async | error | note`).\\n- `note` kind is a numbered annotation on one lane — no arrow.\\n- `summary` (long form for the step list under the SVG),\\n- `code` (a code snippet inside the step item),\\n- `note` field (italic-gray sub-note below the summary).\\n`endpoint.method` colours the tag pill (POST → navy, GET → green, etc.).\\n`foot` items render as key/value pills beneath the diagram.\\n\\n#### `state` — state machine (+ transition table)\\n```state\\ntitle: Order lifecycle\\nstates:\\n - { id: s0, col: 1, row: 1, kind: start }\\n - { id: pending, col: 2, row: 1, kind: wait, name: PENDING }\\n - { id: confirmed, col: 3, row: 1, kind: active, name: CONFIRMED }\\n - { id: end, col: 4, row: 1, kind: terminal }\\ntransitions:\\n - { from: s0, to: pending, event: create }\\n - { from: pending, to: confirmed, event: pay }\\n - { from: confirmed, to: end, event: ship }\\n```\\n`kind` on a state is `start | terminal | active | wait`.\\n\\n### Data model\\n\\n#### `erd` — entities and relations\\n```erd\\nentities:\\n - name: orders\\n columns:\\n - { name: id, type: uuid, pk: true }\\n - { name: user_id, type: uuid, fk: true }\\nrelations:\\n - { from: orders, to: order_items, card: \\\"1:N\\\" }\\n```\\nColumn flags are booleans (`pk: true`, `fk: true`). Relation `card` is\\n`\\\"1:1\\\" | \\\"1:N\\\" | \\\"N:M\\\"`. Quote cardinality values because YAML parses the\\nunquoted form as a number sequence.\\n\\n### Architecture diagrams\\n\\n#### `c4` — context / container / component\\n```c4\\ntitle: System context\\nlevel: container\\nboundary: { label: ShopCo platform }\\nnodes:\\n - { id: user, col: 1, row: 1, kind: person, name: Shopper, desc: A customer. }\\n - { id: api, col: 2, row: 1, kind: container, family: service, name: Orders API, tech: Go }\\n - { id: pay, col: 3, row: 1, kind: external, name: Payment GW }\\nedges:\\n - { from: user, to: api, label: places order }\\n - { from: api, to: pay, label: authorises }\\n```\\n`kind` is `person | system | external | store | container | component`.\\n`family` (for `container`/`component`): `client | service | data | store |\\ncontroller | repo | external`. Edge `kind` is `solid | dashed | forbidden |\\nerror`. Optional `boundary` draws a dashed box around the internal nodes.\\n\\n#### `block` — grid architecture with optional groups\\n```block\\ntitle: System architecture\\ngroups:\\n - { col: 1, row: 1, cols: 1, rows: 2, label: Edge, color: \\\"#0e54a1\\\" }\\nnodes:\\n - { id: api, col: 2, row: 1, kind: service, name: API, tech: Go }\\n - { id: pg, col: 2, row: 2, kind: store, name: Postgres }\\nedges:\\n - { from: api, to: pg }\\n```\\nNode `kind` is one of: `client · service · microservice · compute · container ·\\ndata · store · db · database · bucket · blob · object · queue · cache · gateway\\n· lb · function · lambda · cdn · external · producer · topic · consumer ·\\ncontext · firewall`. Known kinds get coloured + glyphed automatically.\\n\\n**Nested zones (AWS-style VPC / subnets).** `groups` can overlap to nest: draw\\nthe outer zone (e.g. a VPC) as one big group, then inner zones (public / private\\nsubnets) as smaller groups inside its cell range. The renderer paints larger\\ngroups first, so smaller ones layer on top. Nodes still sit in grid `col`/`row`\\ncells; the groups just frame them.\\n```infra\\ntitle: VPC topology\\ngroups:\\n - { col: 2, row: 1, cols: 3, rows: 3, label: \\\"VPC 10.0.0.0/16\\\", color: \\\"#0e54a1\\\" }\\n - { col: 2, row: 1, cols: 3, rows: 1, label: Public subnet, color: \\\"#1f9747\\\" }\\n - { col: 2, row: 2, cols: 3, rows: 1, label: \\\"Private subnet · app\\\", color: \\\"#1a6dbe\\\" }\\nnodes:\\n - { id: cf, col: 1, row: 1, kind: cdn, name: CloudFront }\\n - { id: alb, col: 2, row: 1, kind: gateway, name: ALB }\\n - { id: svc, col: 2, row: 2, kind: microservice, name: orders, tech: ECS }\\nedges:\\n - { from: cf, to: alb }\\n - { from: alb, to: svc }\\n```\\n\\n#### `infra` — same engine, layered layout\\n```infra\\ntitle: AWS topology\\nsystemLabel: ShopCo · us-east-1\\nlayers:\\n - { label: Edge }\\n - { label: Compute }\\n - { label: Data }\\nnodes:\\n - { id: cf, layer: 0, kind: cdn, name: CloudFront }\\n - { id: api, layer: 1, kind: service, name: API }\\n - { id: pg, layer: 2, kind: store, name: orders-db }\\n```\\nPresence of `layers` switches `block`/`infra` to horizontal-band layout.\\nNodes use `layer: <index>` instead of `col`/`row`.\\n\\n#### `event` — pub / sub choreography (same shape as block)\\n```event\\ntitle: Order events\\nnodes:\\n - { id: orders, col: 1, row: 1, kind: producer, name: orders }\\n - { id: bus, col: 2, row: 1, kind: topic, name: order.events }\\n - { id: ship, col: 3, row: 1, kind: consumer, name: shipping }\\nedges:\\n - { from: orders, to: bus }\\n - { from: bus, to: ship }\\n```\\n\\n#### `ddd` — bounded-context map (same shape as block)\\n```ddd\\ntitle: Bounded contexts\\nnodes:\\n - { id: cat, col: 1, row: 1, kind: context, name: Catalog }\\n - { id: order, col: 2, row: 1, kind: context, name: Orders }\\nedges:\\n - { from: order, to: cat, label: reads, kind: dashed }\\n```\\n\\n#### `network` — security zones (same shape as block)\\nUses the `firewall` glyph and red zone tag.\\n\\n#### `cluster` — k8s-style nested boxes with services\\n```cluster\\ntitle: Production cluster\\nclusters:\\n - { id: api, label: api namespace, kind: namespace }\\nservices:\\n - { id: web, cluster: api, label: web, kind: service, tech: Next.js, replicas: 3 }\\n - { id: orders, cluster: api, label: orders, kind: service, tech: Go, replicas: 4 }\\nedges:\\n - { from: web, to: orders }\\n```\\n`replicas` renders as small bars (capped at 5 + `×N` label).\\n\\n### Code-flavoured architecture\\n\\n#### `felogic` / `belogic` — frontend / backend module graph\\n```felogic\\ntitle: Frontend logic\\ngroups:\\n - { id: app, label: App (browser), col: 1, row: 1, cols: 3, rows: 3, color: \\\"#0e54a1\\\" }\\nnodes:\\n - { id: ui, col: 1, row: 1, kind: component, name: Checkout UI }\\n - { id: iface, col: 2, row: 2, kind: interface, name: DiscountStrategy }\\n - { id: impl, col: 1, row: 3, kind: strategy, name: PercentOff }\\nedges:\\n - { from: ui, to: iface, kind: uses }\\n - { from: impl, to: iface, kind: implements }\\n```\\nNode `kind` is one of: `engine | core · interface · strategy | adapter | impl ·\\ncontroller | handler | route · service | usecase | apiclient | client ·\\nrepository | repo | dao · worker | consumer · middleware · model | entity ·\\ndb | store | database · cache · queue | bus | broker · state | store_state ·\\nhook · external | backend | api | thirdparty`. Edge `kind` is\\n`uses | implements | egress | https | api | reads | dashed | async`.\\n`interface` nodes render with an «interface» stereotype banner.\\n\\n#### `frontend` — top-down component tree\\n```frontend\\ntitle: React component tree\\nnodes:\\n - { id: app, kind: root, name: App }\\n - { id: layout, parent: app, kind: layout, name: Layout }\\n - { id: page, parent: layout, kind: page, name: HomePage }\\n - { id: hook, parent: page, kind: hook, name: useData }\\n```\\n`kind` is `root | layout | page | component | leaf | provider | context |\\nhook | store | state`. Parents render above children with link paths.\\n\\n#### `uml` — class diagram\\n```uml\\nclasses:\\n - { id: order, col: 1, row: 1, name: Order, attrs: [\\\"id: UUID\\\", \\\"status: Status\\\"], methods: [\\\"place()\\\", \\\"cancel()\\\"] }\\n - { id: status, col: 1, row: 2, name: Status, stereotype: enumeration, attrs: [\\\"PENDING\\\", \\\"CONFIRMED\\\"] }\\nrels:\\n - { from: order, to: status, kind: association, label: has }\\n```\\nRelation `kind` is `inheritance | extends | implementation | implements |\\ncomposition | aggregation | dependency | association` (drives the marker\\nshape).\\n\\n#### `dag` — pipeline / DAG (reuses flow's renderer)\\n```dag\\ntitle: CI pipeline\\nnodes:\\n - { id: src, col: 1, row: 1, kind: start, label: Source }\\n - { id: build, col: 2, row: 1, kind: process, label: Build }\\n - { id: deploy, col: 3, row: 1, kind: end, label: Deploy }\\nedges:\\n - { from: src, to: build }\\n - { from: build, to: deploy }\\n```\\n\\n### Flow & process\\n\\n#### `flow` — flowchart with decisions\\n```flow\\ntitle: Decision flow\\nnodes:\\n - { id: start, col: 1, row: 1, kind: start, label: Start }\\n - { id: check, col: 2, row: 1, kind: decision, label: Token valid? }\\n - { id: ok, col: 3, row: 1, kind: end, label: Done }\\n - { id: bad, col: 2, row: 2, kind: end, label: Reject }\\nedges:\\n - { from: start, to: check }\\n - { from: check, to: ok, label: \\\"yes\\\" }\\n - { from: check, to: bad, label: \\\"no\\\", kind: error }\\n```\\n`kind` is `start | end | decision | process`. Edge `kind: error` (or labels\\nstarting with `no/fail/error/reject`) render in red.\\n\\n#### `dfd` — data-flow diagram\\n```dfd\\nnodes:\\n - { id: client, col: 1, row: 1, kind: external, name: Client }\\n - { id: proc, col: 2, row: 1, kind: process, name: Place order, num: 1 }\\n - { id: db, col: 3, row: 1, kind: store, name: orders }\\nedges:\\n - { from: client, to: proc }\\n - { from: proc, to: db }\\n```\\n`kind` is `process | external | store | datastore`. Optional `num` on\\nprocesses.\\n\\n#### `swimlane` — cross-functional process\\n```swimlane\\nlanes:\\n - { label: Customer }\\n - { label: Sales }\\nsteps:\\n - { id: req, col: 1, lane: 0, kind: start, label: Submit }\\n - { id: fulfill, col: 2, lane: 1, label: Fulfill }\\nlinks:\\n - { from: req, to: fulfill }\\n```\\nStep `kind` is `action | decision | start | end | wait`.\\n\\n### Charts & overviews\\n\\n#### `graph` — node-link graph\\n```graph\\nnodes:\\n - { id: a, col: 1, row: 1, label: Module A, group: 0 }\\n - { id: b, col: 2, row: 1, label: Module B, group: 1 }\\nedges:\\n - { from: a, to: b, dir: undirected }\\n```\\n`group: <n>` cycles through the chart palette. Edge `dir` is `directed`\\n(default) or `undirected`.\\n\\n#### `mece` — issue tree (MECE breakdown)\\n```mece\\ntitle: Why are conversions down?\\nnodes:\\n - { id: root, label: Lower conversion }\\n - { id: traffic, parent: root, label: Traffic quality }\\n - { id: friction, parent: root, label: Funnel friction }\\n - { id: f1, parent: friction, label: Slow checkout, note: p95 > 4s }\\n```\\nLeft-to-right tree, depth-coloured stripes, DFS layout.\\n\\n#### `tree` — indented hierarchy (HTML, not SVG)\\n```tree\\nnodes:\\n - { id: src, label: src }\\n - { id: components, parent: src, label: components }\\n - { id: index, parent: src, label: index.ts, note: entry }\\n```\\n\\n#### `gantt` — schedule bars\\n```gantt\\nperiods: [Q1, Q2, Q3, Q4]\\ntasks:\\n - { label: Discovery, start: 0, span: 1, kind: done }\\n - { label: Build, start: 1, span: 2, kind: active }\\n - { label: GA, start: 3, span: 1, kind: milestone }\\n```\\nTask `kind` is `done | active | current | milestone` (drives bar colour).\\n\\n#### `funnel` — conversion funnel\\n```funnel\\nstages:\\n - { label: Visited, value: 10000 }\\n - { label: Signed up, value: 2400 }\\n - { label: Paying, value: 320 }\\n```\\nAuto-computes conversion percentages.\\n\\n#### `pyramid` — stacked hierarchy (top → bottom widening)\\n```pyramid\\nlevels:\\n - { label: Vision, desc: Long-term direction }\\n - { label: Tactics, desc: This quarter }\\n```\\n\\n#### `quadrant` — 2×2 matrix\\n```quadrant\\nxAxis: { label: Effort, low: Low, high: High }\\nyAxis: { label: Impact, low: Low, high: High }\\nitems:\\n - { x: 0.2, y: 0.8, label: Quick win }\\n - { x: 0.8, y: 0.8, label: Big bet }\\n```\\n`x` / `y` are 0..1.\\n\\n#### `journey` — user journey map with optional emotion curve\\n```journey\\nstages: [{ label: Discover }, { label: Sign up }, { label: Pay }]\\nrows:\\n - { label: Touchpoint, cells: [Landing, Form, Checkout] }\\n - { label: Friction, cells: [Low, High, Medium] }\\nemotion: [0.7, 0.3, 0.8]\\n```\\n\\n### Planning & meta\\n\\n#### `userstory` — agile story + acceptance criteria + links\\n```userstory\\nid: US-142\\nrole: shopper\\nwant: pay for my cart in one step\\nsoThat: I can complete my purchase quickly\\npriority: High\\npoints: 5\\ncriteria:\\n - { given: I have items, when: I submit valid payment, then: an order is created }\\nlinks:\\n - { ref: orders-api#seq-place-order, mode: sequence, label: Request flow }\\n```\\n`links` may use `ref: doc#id` (a real cross-reference) or a plain label.\\n\\n#### `timeline` — phases / roadmap\\n```timeline\\nitems:\\n - { label: P0 — Core, date: now, status: current, desc: parser + resolver }\\n - { label: P1 — CLI, date: next, status: next, desc: init / check / render }\\n```\\n`status` is `done | current | next | future` (colours the dot).\\n\\n#### `kanban` — flexible columns\\n```kanban\\ncolumns:\\n - label: Now\\n cards:\\n - { title: Core parser }\\n - { title: Validation, tag: priority }\\n - label: Next\\n cards:\\n - { title: Hot reload }\\n```\\n\\n#### `tracker` — task list with status / priority / owner / due\\n```tracker\\nitems:\\n - { task: First task, status: doing, priority: high, owner: alice, due: 2026-01-15 }\\n - { task: Second task, status: todo, priority: med }\\n```\\n`status` is `todo | doing | done | blocked`; `priority` is `high | med | low`.\\n\\n#### `cvt` — current vs target (before / after)\\n```cvt\\ntitle: Migration plan\\ncurrent:\\n label: Today\\n items: [Single monolith, Shared DB, Manual deploys]\\ntarget:\\n label: Target\\n items: [Modular services, Per-service stores, Continuous releases]\\nnote: Migrate one service per quarter.\\n```\\n\\n#### `proscons` — pros vs cons (two columns)\\n```proscons\\nprosLabel: Synchronous\\nconsLabel: Asynchronous\\npros: [Easy to reason about, One transaction]\\ncons: [Latency-bound, Single point of failure]\\n```\\n\\n#### `agenda` — meeting agenda\\n```agenda\\nitems:\\n - { time: \\\"09:00\\\", duration: 30m, title: Round-robin, owner: Host }\\n - { time: \\\"09:30\\\", duration: 60m, title: Deep dive, desc: API team }\\n```\\n\\n### UI mockups\\n\\n#### `wireframe` — low-fi screen mockups (desktop / browser / phone)\\n```wireframe\\ntitle: What the user sees\\nscreens:\\n - device: browser\\n title: Notification center\\n url: app.example.com/inbox\\n label: Desktop — notification center\\n elements:\\n - { type: nav, label: \\\"Home, Inbox, Settings\\\" }\\n - { type: header, label: Notifications }\\n - { type: badge, label: \\\"3 new\\\", tone: danger, align: r }\\n - { type: list, rows: 4 }\\n - { type: button, label: Mark all as read }\\n - device: phone\\n title: \\\"9:41\\\"\\n label: iPhone — live bell + feed\\n elements:\\n - { type: header, label: Alerts }\\n - { type: card, rows: 3 }\\n - { type: tabs, label: \\\"Home, Search, Bell, You\\\" }\\n```\\n`screens` lay out left-to-right; each picks a `device` frame (`desktop` /\\n`browser` / `phone`) and stacks `elements` top-to-bottom. `device: browser`\\nshows an address bar (`url`); `phone` adds a notch + home indicator. `title`\\nis the window/status-bar text, `label` is the caption under the frame.\\n\\nElement `type` is one of: `header · subheader · text · button · input · search\\n· image · avatar · card · list · nav · tabs · divider · badge · toggle ·\\nspacer`. `rows` repeats stack-like elements (`list` / `card`) or sizes `text` /\\n`spacer`. `nav` / `tabs` read their items from a **comma-separated** `label`\\n(quote it). `align` is `l | c | r`; `tone` is `accent | muted | danger` (colours\\nbuttons, badges, toggles). Keep it low-fidelity — it's a wireframe, not a comp.\\n\\n## Cross-references (`doc#id`)\\n\\nBlocks become a connected model through references:\\n\\n- Give a block a unique `id:` (unique across the **whole repo**).\\n- Reference it as `doc#id`, where `doc` is the target file's path **under the\\n docs root** without `.md` (e.g. `orders-api`, or `architecture/overview`).\\n A bare `#id` means the current document — **always prefer `#id` when\\n referencing inside the same doc**, since it survives renames.\\n- A reference whose target id does not exist is a **dangling reference** and\\n fails validation. Only add a `ref` to an id you know exists (or are creating\\n in the same change).\\n- **Don't repeat the current document's slug in a ref.** If you're editing\\n `docs/orders.md` and want to point at `id: seq-place-order` in the same file,\\n write `ref: \\\"#seq-place-order\\\"`, NOT `ref: \\\"orders#seq-place-order\\\"`.\\n\\nThe only reference-bearing field in v1 is `userstory.links[].ref`.\\n\\n## Workflow — always validate\\n\\nAfter creating or editing any doc, run the CLI and fix everything it reports:\\n\\n```\\navo check # validate all docs: schema + dangling refs + dup ids\\navo check docs/orders-api.md # validate one file\\navo check --json # machine-readable, useful in CI\\navo render docs/orders-api.md -o out.html\\navo preview docs/orders-api.md # render and open it\\navo export docs/**/*.md --format pdf --out dist/\\navo new # scaffold a new doc or block from a template\\navo sync openapi spec.yaml --out docs/api.md # generate a doc from an OpenAPI spec\\n```\\n\\n`avo check` exits non-zero on any error and names the file, line, and\\noffending value. **A change is not done until `avo check` passes.**\\n\\n## When `avo check` fails — error code recipes\\n\\nEvery diagnostic carries a stable code so you can mechanically apply a fix.\\n\\n| Code | What it means | First thing to check |\\n|---|---|---|\\n| `E_PARSE_YAML` | YAML body failed to parse. Almost always a quoting issue. | Re-read *YAML pitfalls* above. Unquoted `,`/`:`/`#` in a `desc` is the usual culprit. |\\n| `E_SCHEMA` | A field is missing, the wrong type, or an unknown name. Message contains the path (e.g. `sequence: messages.2.kind: ...`). | Compare your YAML against the block reference. Reject the urge to add fields not listed in this skill — the schema is strict. |\\n| `E_DANGLING_REF` | A `userstory.links[].ref` points at an id that doesn't exist anywhere in the repo. `value` is the bad ref. | Either fix the ref string, or add the missing `id:` to the target block. Bare `#id` is current-doc; `doc#id` is path-under-docs-root + `#id`. |\\n| `E_DUP_ID` | The same `id:` was used in two blocks. Message names both files + lines. | Ids are repo-global. Rename one. |\\n| `E_BAD_REF_FORMAT` | A `ref:` string isn't `doc#id` or `#id` shape. | Match the format exactly. The id slug is `[\\\\w-]+`. |\\n| `W_EMPTY_BLOCK` | A typed block had an empty body. | Add fields or remove the block. |\\n\\n### Common schema errors I see often\\n\\n| Symptom | Cause | Fix |\\n|---|---|---|\\n| `Expected string, received number` on `tech: 16` | YAML parsed `16` as a number. | Quote: `tech: \\\"16\\\"`. |\\n| `Invalid enum value` on `tone: xyz` / `kind: xyz` / `status: xyz` | Used a value not in the enum. | Stick to the documented enum (`tone: note\\\\|tip\\\\|warn\\\\|danger`, etc.). |\\n| `Unrecognized key(s) in object: 'foo'` | You added a field that isn't in the schema. | Schemas are strict. Either remove the field, or use a documented one. |\\n| Schemas on the `meta` block fail | You put a `meta` block somewhere other than first. | Move it to the top of the file. |\\n| `Unrecognized key(s) in object: 'persists'` and similar | Unquoted comma in a flow-style mapping turned a phrase into multiple keys. | Quote the value containing the comma. |\\n\\n## Field semantics — clarifications\\n\\nA few fields are easy to misuse. Lock these in.\\n\\n- `sequence.actors[].sub` is the **subtitle** under the actor's name on the\\n lane head (e.g. `sub: web / mobile`, `sub: orders handler`). Keep it short —\\n 2-4 words.\\n- `sequence.actors[].external: true` darkens the lane (slate instead of navy),\\n signaling the actor lives outside your service boundary.\\n- `sequence.messages[].kind: note` is **not a message** — it's a numbered\\n annotation on the from-actor's lane, with no arrow. Use it for things like\\n \\\"validate token\\\" that don't cross a boundary.\\n- `sequence.messages[].summary` is the longer text shown in the step-by-step\\n list **below** the SVG. Keep `label` short (the SVG arrow) and put detail in\\n `summary`. `code:` adds a `<pre>` snippet inside the step item.\\n- On most diagram blocks: `lede` renders as a `<p class=\\\"section-lede\\\">` under\\n the section title, sized for an editorial paragraph. `description` renders\\n inside the diagram frame as the diagram's caption. Use both when you have\\n both kinds of text to convey.\\n- `userstory.links[].ref` is the only field in v1 that creates a real\\n cross-document reference. Other `links` items render as plain chips.\\n- `block` / `infra` / `event` / `ddd` / `network` use **identical YAML** — the\\n block type slug only changes the colored tag pill. Pick the slug that best\\n signals intent to a reader, not for any structural reason.\\n- `userstory.id` is what other docs reference. Use a short stable id like\\n `US-142`, not a sentence.\\n- Diagram blocks with `layers:` set go into **horizontal-band layout**. Without\\n `layers:` they use **grid layout** with `col`/`row`. Don't mix — the renderer\\n uses the presence of `layers` to switch modes.\\n\\n## Do / Don't\\n\\n**Do**\\n\\n- Edit the specific block you need to change — surgically, a few lines — rather\\n than regenerating a whole document.\\n- Keep narrative in Markdown prose and structure in blocks.\\n- Use `title` + `lede` on diagram blocks so the section header reads well.\\n- Quote YAML values that contain commas, colons, or `1:N` cardinality strings\\n (`desc: \\\"40 blocks, themes, agent skill\\\"`, `card: \\\"1:N\\\"`).\\n- Give a block an `id:` whenever something else might reference it.\\n- Run `avo check` and resolve all diagnostics before finishing.\\n- When unsure which architecture block to use, pick `block` for boxes-and-arrows\\n or `c4` for actor / system context — both are safe defaults.\\n\\n**Don't**\\n\\n- Paste raw HTML, `<svg>`, or `<style>` into a doc. Use blocks.\\n- Invent block types or fields. The schemas are strict; unknown fields error.\\n- Reference a `doc#id` that doesn't exist. Either fix the ref or add the id.\\n- Stuff a whole spec into one giant block. Decompose into 3-5 focused blocks.\\n- Write a `description` longer than 2 sentences. Use prose instead for long\\n narrative.\\n- Put commas inside flow-style mappings without quoting (see *YAML pitfalls*).\\n- Reuse the same `id:` in two blocks. Ids are repo-global unique.\\n- Add a `prose` block AND raw `##` headings for the same idea. Pick one.\\n- Use `frontend` for backend modules, or `felogic` when you mean `frontend`.\\n `frontend` is a top-down hierarchical tree; `felogic` / `belogic` are\\n free-positioned module graphs with edges.\\n\\n## Quick block index (in case you forget)\\n\\n| Family | Blocks |\\n|---|---|\\n| Document & meta | `meta` |\\n| Prose & structure | `prose` `callout` `glossary` |\\n| Tables & metrics | `table` `stats` `code` |\\n| Sequence & state | `sequence` `state` |\\n| Data model | `erd` |\\n| Architecture | `c4` `block` `infra` `event` `ddd` `network` `cluster` |\\n| Code-flavoured | `felogic` `belogic` `frontend` `uml` `dag` |\\n| Flow & process | `flow` `dfd` `swimlane` |\\n| Charts & overviews | `graph` `mece` `tree` `gantt` `funnel` `pyramid` `quadrant` `journey` |\\n| Planning & meta | `userstory` `timeline` `kanban` `tracker` `cvt` `proscons` `agenda` |\\n| UI mockups | `wireframe` |\\n\";\n"],"mappings":";;;AAWA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,sBAAsC;AAC/C,SAAS,yBAAyB;;;ACxB3B,IAAM,WAAW;;;AD2BxB,IAAM,SAAS,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAE/D,SAAS,kBAAkB,OAAsC;AAC/D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MACJ,IAAI,CAAC,MAAM;AACV,UAAM,MACJ,EAAE,SAAS,SAAY,IAAI,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,IAAI,EAAE,MAAM,KAAK,EAAE,KAAK;AACvF,UAAM,OAAO,EAAE,SAAS,SAAY,WAAW,EAAE,IAAI,MAAM;AAC3D,WAAO,GAAG,EAAE,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,GAAG,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,GAAG,IAAI;AAAA,EACjF,CAAC,EACA,KAAK,IAAI;AACd;AAEA,IAAM,SAAS,IAAI,UAAU,EAAE,MAAM,WAAW,SAAS,QAAQ,CAAC;AAElE,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,UAAU,EAAE,OAAO,EAAE,SAAS,gCAAgC;AAAA,MAC9D,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oCAAoC;AAAA,IAC3E;AAAA,EACF;AAAA,EACA,CAAC,EAAE,UAAU,KAAK,MAAM;AACtB,UAAM,IAAI,QAAQ;AAClB,UAAM,QAAQ,iBAAiB,cAAc,UAAU,CAAC,GAAG,CAAC;AAC5D,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,kBAAkB,KAAK,EAAE,CAAC,EAAE;AAAA,EACvE;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,MACX,UAAU,EAAE,OAAO;AAAA,MACnB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,OAAO,EAAE,KAAK,MAAM,EAAE,SAAS,EAAE,SAAS,8BAA8B;AAAA,IAC1E;AAAA,EACF;AAAA,EACA,CAAC,EAAE,UAAU,MAAM,MAAM,MAAM;AAC7B,UAAM,OAAO;AAAA,MACX,cAAc,UAAU,QAAQ,KAAK;AAAA,MACrC,UAAU,SAAY,EAAE,MAA0B,IAAI,CAAC;AAAA,IACzD;AACA,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,CAAC,EAAE;AAAA,EACnD;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,CAAC;AAAA,EAChB;AAAA,EACA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,YAAY,KAAK,IAAI,EAAE,CAAC,EAAE;AACrE;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,WAAW,CAA0B,EAAE;AAAA,EACzE;AAAA,EACA,CAAC,EAAE,KAAK,MAAM;AACZ,UAAM,SAAS,aAAa,IAAiC;AAC7D,UAAM,OAAO,gBAAgB,QAAQ,IAAI;AACzC,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,CAAC,EAAE;AAAA,EAC5E;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,WAAW,EACR,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,EAC1D,SAAS,+BAA+B;AAAA,IAC7C;AAAA,EACF;AAAA,EACA,CAAC,EAAE,UAAU,MAAM;AACjB,UAAM,SAA0B,UAAU,IAAI,CAAC,OAAO;AAAA,MACpD,KAAK,cAAc,EAAE,UAAU,EAAE,IAAI;AAAA,MACrC,MAAM,EAAE;AAAA,IACV,EAAE;AACF,UAAM,EAAE,YAAY,IAAI,YAAY,MAAM;AAC1C,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,kBAAkB,WAAW,EAAE,CAAC,EAAE;AAAA,EAC7E;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM,EAAE,OAAO,EAAE,SAAS,oCAAoC;AAAA,MAC9D,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,CAAC,EAAE,MAAM,KAAK,MAAM;AAClB,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO,EAAE,SAAS,MAAM,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,qBAAqB,CAAC,EAAE;AAAA,IAClF;AACA,UAAM,KAAK;AAAA,MACT;AAAA,MACA,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACnC;AACA,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,GAAG,CAAC,EAAE;AAAA,EACjD;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa,CAAC;AAAA,EAChB;AAAA,EACA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,SAAS,CAAC,EAAE;AACvD;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,SAAS;AAAA,IACR,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,iBAAiB,MAAM,SAAS,CAAC;AAAA,EACzE;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AAE/C,UAAQ,MAAM,qCAAqC;AACrD;AAEA,KAAK,EAAE,MAAM,CAAC,QAAiB;AAC7B,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
1
+ {"version":3,"sources":["../src/server.ts","../src/skill.generated.ts"],"sourcesContent":["/**\n * Avodado MCP server.\n *\n * Exposes Avodado's pure document tooling (parse, validate, render, schemas,\n * cross-references, OpenAPI sync) and the authoring grammar as MCP tools +\n * resources, so any MCP client (Claude Code/Desktop, Cursor, …) can author,\n * validate, and render Avodado documents natively.\n *\n * Transport: stdio. Run via `npx @avodado/mcp` (or the `avodado-mcp` bin).\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport {\n parseDocument,\n validateDocument,\n resolveRefs,\n blockSchemas,\n BLOCK_TYPES,\n type Diagnostic,\n type InputDocument,\n} from '@avodado/core';\nimport { renderDocument, type ThemeName } from '@avodado/render';\nimport { openapiToMarkdown } from '@avodado/sync';\nimport { SKILL_MD } from './skill.generated.js';\n\nconst THEMES = ['textbook', 'minimal', 'soft', 'dark', 'teal', 'plum', 'slate'] as const;\n\nfunction formatDiagnostics(diags: readonly Diagnostic[]): string {\n if (diags.length === 0) return 'OK — no diagnostics. The document is valid.';\n return diags\n .map((d) => {\n const loc =\n d.line !== undefined ? `:${d.line}${d.column !== undefined ? `:${d.column}` : ''}` : '';\n const hint = d.hint !== undefined ? ` (hint: ${d.hint})` : '';\n return `${d.level.toUpperCase()} ${d.file}${loc} [${d.code}] ${d.message}${hint}`;\n })\n .join('\\n');\n}\n\nconst server = new McpServer({ name: 'avodado', version: '0.0.1' });\n\nserver.registerTool(\n 'check_document',\n {\n title: 'Check an Avodado document',\n description:\n 'Parse and validate Avodado Markdown (prose + typed YAML blocks). Returns diagnostics; \"OK\" means valid. Use this after writing or editing a document.',\n inputSchema: {\n markdown: z.string().describe('The Avodado document Markdown.'),\n slug: z.string().optional().describe('Document slug (defaults to \"doc\").'),\n },\n },\n ({ markdown, slug }) => {\n const s = slug ?? 'doc';\n const diags = validateDocument(parseDocument(markdown, s), s);\n return { content: [{ type: 'text', text: formatDiagnostics(diags) }] };\n },\n);\n\nserver.registerTool(\n 'render_document',\n {\n title: 'Render an Avodado document to HTML',\n description: 'Render Avodado Markdown to a standalone, styled HTML document.',\n inputSchema: {\n markdown: z.string(),\n slug: z.string().optional(),\n theme: z.enum(THEMES).optional().describe('Visual theme (default textbook).'),\n },\n },\n ({ markdown, slug, theme }) => {\n const html = renderDocument(\n parseDocument(markdown, slug ?? 'doc'),\n theme !== undefined ? { theme: theme as ThemeName } : {},\n );\n return { content: [{ type: 'text', text: html }] };\n },\n);\n\nserver.registerTool(\n 'list_block_types',\n {\n title: 'List Avodado block types',\n description: 'List every supported Avodado block type.',\n inputSchema: {},\n },\n () => ({ content: [{ type: 'text', text: BLOCK_TYPES.join('\\n') }] }),\n);\n\nserver.registerTool(\n 'get_block_schema',\n {\n title: 'Get a block JSON Schema',\n description: 'Return the JSON Schema (fields, enums) for a given Avodado block type.',\n inputSchema: { type: z.enum([...BLOCK_TYPES] as [string, ...string[]]) },\n },\n ({ type }) => {\n const schema = blockSchemas[type as keyof typeof blockSchemas];\n const json = zodToJsonSchema(schema, type);\n return { content: [{ type: 'text', text: JSON.stringify(json, null, 2) }] };\n },\n);\n\nserver.registerTool(\n 'resolve_refs',\n {\n title: 'Resolve cross-document references',\n description:\n 'Check `doc#id` references across multiple Avodado documents (dangling refs, duplicate ids).',\n inputSchema: {\n documents: z\n .array(z.object({ slug: z.string(), markdown: z.string() }))\n .describe('The documents to cross-check.'),\n },\n },\n ({ documents }) => {\n const inputs: InputDocument[] = documents.map((d) => ({\n doc: parseDocument(d.markdown, d.slug),\n file: d.slug,\n }));\n const { diagnostics } = resolveRefs(inputs);\n return { content: [{ type: 'text', text: formatDiagnostics(diagnostics) }] };\n },\n);\n\nserver.registerTool(\n 'sync_openapi',\n {\n title: 'Generate an Avodado doc from OpenAPI',\n description: 'Convert an OpenAPI spec (JSON) into an Avodado Markdown document.',\n inputSchema: {\n spec: z.string().describe('The OpenAPI spec as a JSON string.'),\n slug: z.string().optional(),\n },\n },\n ({ spec, slug }) => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(spec);\n } catch {\n return { isError: true, content: [{ type: 'text', text: 'Invalid JSON spec.' }] };\n }\n const md = openapiToMarkdown(\n parsed as Parameters<typeof openapiToMarkdown>[0],\n slug !== undefined ? { slug } : {},\n );\n return { content: [{ type: 'text', text: md }] };\n },\n);\n\nserver.registerTool(\n 'get_authoring_guide',\n {\n title: 'Get the Avodado authoring guide',\n description:\n 'Return the full Avodado authoring grammar (block types, every field, YAML pitfalls, recipes). Read this BEFORE authoring Avodado documents.',\n inputSchema: {},\n },\n () => ({ content: [{ type: 'text', text: SKILL_MD }] }),\n);\n\nserver.registerResource(\n 'authoring-skill',\n 'avodado://skill',\n {\n title: 'Avodado authoring guide',\n description: 'The block grammar, fields, and authoring rules for Avodado documents.',\n mimeType: 'text/markdown',\n },\n (uri) => ({\n contents: [{ uri: uri.href, mimeType: 'text/markdown', text: SKILL_MD }],\n }),\n);\n\nasync function main(): Promise<void> {\n await server.connect(new StdioServerTransport());\n // Protocol uses stdout; logs go to stderr.\n console.error('avodado-mcp server running on stdio');\n}\n\nmain().catch((err: unknown) => {\n console.error(err);\n process.exit(1);\n});\n","// AUTO-GENERATED from packages/cli/templates/.avodado/skill/SKILL.md — do not edit.\nexport const SKILL_MD = \"---\\nname: avodado-docs\\ndescription: >-\\n Use whenever you author, edit, validate, or review Avodado documentation —\\n Markdown files that mix prose with typed YAML blocks (sequence · erd · table ·\\n callout · userstory · timeline · kanban · tracker · meta · prose · glossary ·\\n proscons · cvt · stats · code · agenda · tree · pyramid · funnel · flow · state ·\\n dfd · journey · gantt · graph · quadrant · swimlane · c4 · uml · mece · frontend ·\\n cluster · block · infra · event · ddd · network · felogic · belogic · dag ·\\n wireframe).\\n Trigger on any of: docs/**/*.md in an Avodado repo, the `avo` CLI, any block\\n type above, `doc#id` cross-references, presence of `avodado.config.*` or\\n `.avodado/skill/SKILL.md` in the workspace, or user mentions \\\"avodado\\\". Covers\\n block grammar, every block's fields, the reference scheme, YAML pitfalls, and\\n the validate workflow.\\n---\\n\\n# Authoring Avodado documents\\n\\n> Repo location: commit this file at `.avodado/skill/SKILL.md`. `avo init`\\n> copies it into new projects and writes editor adapters (`CLAUDE.md`,\\n> `.cursor/rules/avodado.mdc`) that point here so Claude Code, Cursor, and\\n> other agents pick it up automatically.\\n\\nAvodado documents are **plain Markdown with typed, fenced YAML blocks**. Prose\\nis ordinary Markdown; anything structured (a diagram, a table, a user story,\\na chart) is a fenced code block whose info-string is the block *type*, with a\\nYAML body.\\n\\n**The one rule:** the `.md` file is the source of truth. You edit files\\ndirectly. A document must read fine as plain text with no tooling, so never\\npaste raw HTML or inline SVG — express structure through blocks instead.\\n\\n## Authoring recipe — follow this every time\\n\\nAny time you write or edit an Avodado doc, work through these steps in order.\\nSkipping steps is the source of every authoring failure I've seen.\\n\\n1. **Identify the doc's job.** Is this an API spec, an architecture overview, a\\n roadmap, a runbook, a meeting agenda? The job picks the blocks (see *Choose\\n your block* below).\\n2. **Start with `meta`** — title + subtitle + tag. First block, always.\\n3. **Add a short prose intro** under `## Overview`. 2-4 sentences. Plain Markdown.\\n4. **Pick 2-5 blocks that carry the structure.** Don't try to use all 41 in one doc.\\n If the content *describes* an architecture, a layering, a pipeline, a component\\n tree, or a set of gates, **adapt it to the matching diagram — don't leave it as\\n prose and don't flatten it into a table.** A table is for genuinely tabular data\\n (rows × columns of values), never for boxes-and-arrows. See *Adapt the content*\\n and the *Block glossary* below.\\n5. **Give each referenceable block an `id:`** (a short slug). Other blocks reach\\n it as `doc#id` from elsewhere; bare `#id` works inside the same doc.\\n6. **Use `title` + optional `lede` on diagram blocks** so the section header reads\\n like an editorial document, not a dump of YAML.\\n7. **Quote any string containing `,` `:` `[` `]` `{` `}` `#` `&` `*` `!` `|` `>`\\n `'` `\\\"`.** See *YAML pitfalls* below for the table of things that bite you.\\n8. **Run `avo check`.** If anything's red, fix it before you call the change\\n done. A passing check is the definition of done.\\n\\n## Choose your block — decision tables\\n\\nMost authoring failures come from picking the wrong block. Use these tables.\\n\\n### Block glossary — one line on what each is *for*\\n\\nThe whole vocabulary at a glance. Read this first; it's the map from *a concept in\\nyour head* to *a block*. The detailed family tables below disambiguate the close calls.\\n\\n| Block | What it represents |\\n|---|---|\\n| `meta` | Document header — title, subtitle, tag pill. Always the first block. |\\n| `callout` | A single aside: note / tip / warn / danger. |\\n| `prose` | Structured prose (headings, paragraphs, lists, quotes) carried as data. |\\n| `glossary` | Term → definition rows. |\\n| `proscons` | Two columns weighed against each other: pros vs cons. |\\n| `cvt` | Current → target (before / after) as two side-by-side panels. |\\n| `agenda` | Meeting agenda — time, duration, owner, topic per row. |\\n| `table` | Genuinely tabular data (rows × columns of values); cells can carry tone. |\\n| `stats` | KPI cards — a value with a delta and an up/down/flat trend. |\\n| `code` | One or more syntax-highlighted snippets under a titled header bar. |\\n| `tracker` | A task list with status / priority / owner / due. |\\n| `kanban` | Flexible named columns (e.g. Now / Next / Later) of cards. |\\n| `timeline` | Phases in order with status dots (done / current / next / future). |\\n| `gantt` | A schedule — tasks as bars across date columns. |\\n| `userstory` | An agile story: role / want / soThat + acceptance criteria + links. |\\n| `sequence` | Messages between actors **over time** (lifelines, returns); optional step list + endpoint pill. |\\n| `state` | A state machine — states + event transitions (+ a transition table). |\\n| `flow` | A decision flowchart — start / process / decision / end nodes, with `error` exits. |\\n| `dag` | A pipeline / DAG — same shapes as `flow`, framed for CI/CD. |\\n| `dfd` | Data-flow — processes, external entities, and datastores. |\\n| `swimlane` | A cross-functional process with one horizontal lane per role. |\\n| `journey` | A user journey across stages, with an optional emotion curve. |\\n| `erd` | Entity-relationship diagram — tables, columns, PK/FK, crow's-foot cardinality. |\\n| `uml` | A class diagram — attributes, methods, UML relationships. |\\n| `c4` | C4 model (context / container / component) — people, systems, containers, stores. |\\n| `block` | Generic boxes-and-arrows architecture — grid **or** horizontal `layers`, dashed `groups` zones. |\\n| `infra` | Cloud topology (same engine as `block`) — CDN / gateway / compute / DB, nested account & network zones. |\\n| `event` | Pub/sub topology (same engine) — producers → topics → consumers. |\\n| `ddd` | DDD bounded-context map (same engine). |\\n| `network` | Security zones with trust boundaries (same engine); supports `forbidden` (red) edges. |\\n| `cluster` | Kubernetes-style namespaces holding services, with replica counts. |\\n| `frontend` | A top-down component tree — root / layout / page / component / provider / hook / store. |\\n| `felogic` | Frontend module/logic graph — components, hooks, interfaces, strategies; group zones + egress edges. |\\n| `belogic` | Backend module/logic graph (same engine) — controller / service / repository / adapter / gateway + egress. |\\n| `graph` | A generic node-link graph with colour-cycled groups. |\\n| `mece` | A MECE issue tree — one problem broken into mutually-exclusive branches. |\\n| `tree` | An indented file/folder hierarchy (HTML, not SVG). |\\n| `pyramid` | A layered pyramid (strategy / hierarchy), widening top → bottom. |\\n| `funnel` | A conversion funnel with auto-computed percentages. |\\n| `quadrant` | A 2×2 matrix (e.g. effort vs impact) with plotted items. |\\n| `wireframe` | Low-fi UI mockups inside device frames — desktop / browser / phone screens. |\\n\\n### Adapt the content — signals that should trigger a diagram\\n\\nWhen you're handed prose, a spec, or a generic table, these cues in the *source*\\ntell you which diagram it really wants. This is the step people skip — and then\\neverything degrades into tables and sequences.\\n\\n| If the source describes… | Adapt it to | Not |\\n|---|---|---|\\n| \\\"layers / tiers / sits on top of / front-to-back / N-tier\\\" | `block` (with `layers`) or `infra` | a table |\\n| \\\"the platform: these services + a shared backbone, who calls what\\\" | `block` / `infra` / `cluster` | a table |\\n| \\\"a person uses the system, which depends on external systems\\\" | `c4` (level: context) | prose |\\n| \\\"N checks/gates **in order**, any one can reject the request\\\" | `flow` (decision nodes + `kind: error` exits) | a `sequence` — gates aren't temporal |\\n| \\\"A happens, then B, then C, then a reply comes back\\\" (over time) | `sequence` | a `flow` |\\n| \\\"who does what across teams, step by step\\\" | `swimlane` | a `flow` |\\n| \\\"components / providers / hooks / context / store\\\" | `frontend` (tree) or `felogic` (with patterns + egress) | a table |\\n| \\\"controller / service / repository / adapter / gateway / middleware / Depends()\\\" | `belogic` | a `sequence` |\\n| \\\"producers emit events → topics → consumers\\\" | `event` | a `flow` |\\n| \\\"namespaces / pods / replicas / deployments\\\" | `cluster` | a `block` |\\n| \\\"trust boundary / DMZ / zones / must-not-call\\\" | `network` (with `forbidden` edges) | a `block` |\\n| \\\"tables, schema, primary/foreign keys, relationships\\\" | `erd` | a `table` |\\n| \\\"options compared with verdicts/criteria\\\" | `table` (this one really is tabular) | — |\\n| \\\"current state vs target state\\\" / \\\"before vs after\\\" | `cvt` | a 2-column `table` |\\n| \\\"pros vs cons / trade-offs for one option\\\" | `proscons` | a `table` |\\n| \\\"why is X happening — break the causes down\\\" | `mece` | a bulleted list |\\n| \\\"phases / rollout in order\\\" | `timeline` (status) or `gantt` (real dates) | a `table` |\\n| \\\"what the user sees / the screen / the app / the bell + feed\\\" | `wireframe` (desktop / browser / phone) | prose |\\n\\n> **The rule:** if the source *describes* a structure — an architecture, a layering,\\n> a pipeline, a component tree, a set of gates — render it as the matching **diagram**.\\n> Prose and tables are the fallback for things that are genuinely paragraphs and\\n> genuinely rows-of-values, not the default for everything.\\n\\n### Architecture and topology (which one when?)\\n\\n| If you want to show… | Use | Notes |\\n|---|---|---|\\n| Who uses the system + which external systems it depends on | `c4` (level: context) | One node per actor / system |\\n| Containers inside a system, with optional boundary box | `c4` (level: container) | Use `family` to colour-code (client / service / data / store) |\\n| Components inside one container | `c4` (level: component) | Same shape, finer granularity |\\n| Generic boxes-and-arrows architecture | `block` | Grid layout; add `groups` for dashed zones; add `layers` to switch to horizontal-band layout |\\n| Cloud deployment (CDN, gateway, compute, DB, …) | `infra` | Same engine as `block`; conventionally for cloud topology |\\n| Pub/sub event topology (producers → topics → consumers) | `event` | Same engine; conventionally for choreography |\\n| Bounded-context map for DDD | `ddd` | Same engine; conventionally for context maps |\\n| Security zones with trust boundaries | `network` | Same engine; supports `kind: forbidden` edges (red) |\\n| Kubernetes-style namespaces with services inside | `cluster` | Has its own nested-box engine; supports `replicas` count |\\n\\n> `block` / `infra` / `event` / `ddd` / `network` share **one renderer**.\\n> They differ only by the colored tag pill above the diagram (ARCH / INFRA / EVENT\\n> / DDD / ZONES). Pick the slug that best signals intent to a reader; the YAML\\n> grammar is identical.\\n\\n### Charts and overviews\\n\\n| If you want to show… | Use |\\n|---|---|\\n| KPI values with deltas + up/down arrows | `stats` |\\n| Tabular data with optional cell tones | `table` |\\n| Task list with status / owner / priority / due | `tracker` |\\n| Now / Next / Later flexible columns | `kanban` |\\n| Phases with status dots (done / current / next / future) | `timeline` |\\n| Schedule with date columns and bars | `gantt` |\\n| Conversion funnel with auto-percentages | `funnel` |\\n| Hierarchical / strategic pyramid (top→bottom widening) | `pyramid` |\\n| 2×2 matrix (effort vs impact, etc.) | `quadrant` |\\n| User journey across stages with optional emotion curve | `journey` |\\n\\n### Process and flow\\n\\n| If you want to show… | Use |\\n|---|---|\\n| Sequence of messages over time (with optional step-by-step list + endpoint tag) | `sequence` |\\n| State machine with transitions + transition table | `state` |\\n| Generic decision flow with diamonds + stadium nodes | `flow` |\\n| Data-flow with processes, externals, datastores | `dfd` |\\n| Cross-functional flow with horizontal lanes per role | `swimlane` |\\n| CI/CD pipeline (same shapes as `flow`, navy DAG tag) | `dag` |\\n\\n### Code-flavoured\\n\\n| If you want to show… | Use |\\n|---|---|\\n| Class diagram with attrs/methods + UML markers | `uml` |\\n| Top-down React/Vue component tree | `frontend` |\\n| Frontend module graph with design patterns + interface stereotypes | `felogic` |\\n| Backend module graph — same engine as felogic | `belogic` |\\n| One or more syntax-highlighted code snippets | `code` |\\n| MECE issue tree (left → right with depth-coloured branches) | `mece` |\\n| Indented file/folder hierarchy (HTML, not SVG) | `tree` |\\n| Generic node-link graph with `group:` colour cycling | `graph` |\\n\\n### Narrative and structure\\n\\n| If you want to show… | Use |\\n|---|---|\\n| Note / tip / warning / danger box | `callout` |\\n| Structured prose (h3 + p + ul + quote sub-blocks) | `prose` |\\n| Term / definition rows | `glossary` |\\n| Two-column pros vs cons | `proscons` |\\n| Before / after, \\\"current\\\" → \\\"target\\\" | `cvt` |\\n| Meeting agenda (time + duration + title + owner) | `agenda` |\\n| User story + acceptance criteria + cross-doc links | `userstory` |\\n\\n## Mixing blocks — document recipes\\n\\nA good Avodado doc is **2-5 blocks, each a different lens** on the subject —\\n*orient → big picture → detail → plan*. Don't show the same thing in two block\\ntypes, and don't reach for all 41. Start from the doc's job and pick a stack:\\n\\n| Doc job | Core blocks (always) | Add when relevant | Skip / fold into prose when… |\\n|---|---|---|---|\\n| **API / endpoint spec** | `meta` + `sequence` (request flow) | `erd` (data touched) · `table` (status codes) · `code` (payloads) · `userstory` (the story it serves) | the call is a single hop — describe it in prose |\\n| **Architecture overview** | `meta` + `c4` (context) **or** `block`/`infra` (the landscape) | `belogic`/`felogic` (one module's internals) · `flow` (a key decision path) · `tracker` (open decisions) | there are <3 components — a `callout` is enough |\\n| **Design doc / RFC** | `meta` + `proscons` **or** `cvt` (the choice) | `mece` (problem breakdown) · `c4`/`block` (proposed arch) · `sequence`/`flow` (behavior) · `tracker` | only one option exists — just prose |\\n| **Roadmap / plan** | `meta` + `timeline` (phases) **or** `gantt` (real dates) | `kanban` (now/next/later) · `tracker` (tasks) · `stats` (targets) | — |\\n| **Runbook / procedure** | `meta` + `flow` **or** `swimlane` | `sequence` (one interaction) · `code` (commands) · `table` (symptom → action) · `callout: warn` | the steps are linear with no branches — an `ol` in `prose` |\\n| **Data model** | `meta` + `erd` | `table` (field semantics) · `state` (record lifecycle) | it's a single table — use `table` alone |\\n| **Frontend feature** | `meta` + `frontend` (tree) | `felogic` (logic + patterns) · `wireframe` (what the user sees) · `sequence` (data fetch) · `userstory` | — |\\n| **Status / metrics** | `meta` + `stats` | `funnel` · `quadrant` · `timeline` | — |\\n| **Meeting** | `meta` + `agenda` | `tracker` · `kanban` · `callout` | — |\\n\\n**Rules for combining:**\\n\\n- **One `meta`, first, always.** Everything after it is optional.\\n- **Each block earns its place as a distinct lens.** `c4`/`block` shows the\\n *structure*; `sequence`/`flow` shows *behavior*; `timeline`/`tracker` shows\\n *plan*. If two blocks would draw the same boxes (`c4` **and** `block` for the\\n same components, or `flow` **and** `sequence` for the same steps), keep one.\\n- **Connect, don't repeat.** Give the referenced block an `id:` and point at it\\n with `userstory.links[].ref: doc#id` instead of redrawing it elsewhere.\\n- **Omit a block whose data is thin.** Fewer than ~3 nodes/rows? Fold it into a\\n `callout` or a prose list — an almost-empty diagram reads worse than a sentence.\\n- **Order top-to-bottom as the reader needs it:** orient (`meta` + intro) → the\\n big picture (context / landscape) → the detail (one module / one flow) → what's\\n next (plan / tracker).\\n\\n## YAML pitfalls — quote when in doubt\\n\\nThe YAML parser is doing exactly what you asked. Most \\\"schema errors\\\" are\\nactually YAML mis-parses. **Quote the value** whenever it contains:\\n\\n| Character | What goes wrong unquoted | Fix |\\n|---|---|---|\\n| `,` (comma) | Inside `{ a, b }` flow style, treated as a separator. Your sentence becomes 3 keys. | `desc: \\\"40 blocks, themes, agent skill\\\"` |\\n| `:` (colon) | Treated as `key: value`. `1:N` becomes a number sequence. | `card: \\\"1:N\\\"` |\\n| `#` (hash) | Treated as a comment from there on. | `label: \\\"POST /orders #idempotent\\\"` |\\n| Leading `*` `&` `!` `|` `>` `%` `@` `\\\\`` | YAML anchor / tag / literal / fold / reserved characters. | Quote the whole value. |\\n| Leading `-` followed by space | Looks like a list item. | Quote. |\\n| Numeric-looking (`0`, `02`, `1e3`) | Parsed as a number, fails `string` schemas. | Quote: `delta: \\\"0\\\"`, `version: \\\"1.0\\\"` |\\n| `yes` / `no` / `true` / `false` / `null` | YAML 1.1 booleans (still around in some parsers). | Quote. |\\n| Empty | Parsed as null. | Quote: `name: \\\"\\\"` |\\n\\nInline-mapping `{ k: v }` is fine for short records (under ~5 fields). For\\nanything longer, use block-style — easier diffs, fewer comma traps:\\n\\n```yaml\\n# ✓ Good — block style for longer records\\nitems:\\n - title: Phase 1\\n when: now\\n status: active\\n detail: A longer description with, commas, in, it.\\n# ✗ Bad — flow-style with unquoted commas\\nitems:\\n - { title: Phase 1, when: now, status: active, detail: A longer description with, commas }\\n```\\n\\nWhen you write a `desc` / `note` / `summary` / `description` that contains\\nprose, **always quote it** — those fields are the #1 source of validation\\nerrors.\\n\\n## How a block looks\\n\\n````\\n## Request flow\\n\\n```sequence\\nid: seq-place-order\\ntitle: Place order\\nendpoint: { method: POST, path: /orders }\\nactors:\\n - { id: Client, name: Client }\\n - { id: API, name: Orders API }\\nmessages:\\n - { from: Client, to: API, label: POST /orders, kind: sync }\\n - { from: API, to: Client, label: 201 Created, kind: response }\\n```\\n````\\n\\nRules:\\n\\n- The info-string is exactly one of the **41 block types** listed below — never\\n invent new ones.\\n- The body is **YAML** (JSON is also accepted; YAML is preferred — prefer\\n block-style over deep inline maps for readability and clean diffs).\\n- Use only the fields documented for that block. Keep prose outside blocks.\\n- A block MAY carry a top-level `id:` (a slug) so other blocks can reference it.\\n- Most diagram blocks accept optional `title`, `description`, and `lede` —\\n these surface in the section header + diagram frame around the SVG.\\n\\n## Block data shapes — required vs optional (the contract)\\n\\nEvery block also carries optional `title`, `description`, `lede` (editorial text\\nrendered around the diagram) and an optional top-level `id:` — **none are ever\\nrequired**, so they're left out of the table below, which shows only the\\n*structural* payload. `*` marks a **required** field; everything else is optional.\\n**Omit optional fields you have no value for** — don't pad them with empty strings.\\n`(n)` marks a **number** (don't quote it); every other value is a string.\\n\\n| Block | Structural shape (`*` = required, `(n)` = number) | Closed enums |\\n|---|---|---|\\n| `meta` | `title` `subtitle` `tag` | — |\\n| `callout` | `tone` `title` `body` | tone: note · tip · warn · danger |\\n| `prose` | `blocks[]`: `type` `text` `items[]` | type: h · p · ul · ol · quote |\\n| `glossary` | `terms[]`: `term*` `def*` | — |\\n| `proscons` | `prosLabel` `consLabel` `pros[]` `cons[]` | — |\\n| `cvt` | `current{label, items[]}` `target{label, items[]}` `note` | — |\\n| `agenda` | `items[]`: `title*` `time` `duration` `owner` `desc` | — |\\n| `table` | `columns[]`: string \\\\| `{label*, align, highlight}` · `rows[][]`: string \\\\| number \\\\| `{v*, tone, lead, highlight}` · `note` | align: l · c · r — tone: pos · neg · warn · muted |\\n| `stats` | `stats[]`: `value*` `label*` `delta` `trend` `accent` | trend: up · down · flat |\\n| `code` | `blocks[]`: `code*` `title` `lang` | — |\\n| `tracker` | `items[]`: `task*` `status` `priority` `owner` `due` | status: todo · doing · done · blocked — priority: high · med · low |\\n| `kanban` | `columns[]`: `label*` `cards[]`: `title*` `tag` | — |\\n| `timeline` | `items[]`: `label*` `date` `desc` `status` | status: done · current · next · future |\\n| `gantt` | `periods[]` · `tasks[]`: `label*` `start`(n) `span`(n) `kind` | kind: done · active · current · milestone |\\n| `userstory` | `role` `want` `soThat` `priority` `points`(n) · `criteria[]`: `given` `when` `then` · `links[]`: `ref` `mode` `label` | — |\\n| `sequence` | `actors[]`: `id*` `name*` `sub` `external` · `messages[]`: `from*` `to*` `label` `kind` `summary` `code` `note` · `endpoint{method*, path*, status}` · `foot[]`: `label*` `value*` | msg kind: sync · response · async · error · note — method: GET · POST · PUT · PATCH · DELETE |\\n| `state` | `states[]`: `id*` `col*`(n) `row*`(n) `name` `kind` · `transitions[]`: `from*` `to*` `event*` `guard` | kind: start · terminal · active · wait |\\n| `flow` / `dag` | `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `label*` `kind` · `edges[]`: `from*` `to*` `label` `kind` | node kind: start · end · decision · process — edge kind: error |\\n| `dfd` | `nodes[]`: `id*` `col*`(n) `row*`(n) `name*` `kind` `num` · `edges[]`: `from*` `to*` `label` | kind: process · external · store · datastore |\\n| `swimlane` | `lanes[]`: `label*` · `steps[]`: `id*` `col*`(n) `lane*`(n) `label*` `kind` · `links[]`: `from*` `to*` `label` | kind: action · decision · start · end · wait |\\n| `journey` | `stages[]`: `label*` · `rows[]`: `label*` `cells[]` · `emotion[]`(n, 0..1) | — |\\n| `erd` | `entities[]`: `name*` `columns[]`: `name*` `type` `pk`(bool) `fk`(bool) · `relations[]`: `from*` `to*` `label` `card` | card: \\\"1:1\\\" · \\\"1:N\\\" · \\\"N:M\\\" (quote!) |\\n| `uml` | `classes[]`: `id*` `col*`(n) `row*`(n) `name*` `stereotype` `attrs[]` `methods[]` · `rels[]`: `from*` `to*` `label` `kind` | rel kind: inheritance · extends · implementation · implements · composition · aggregation · dependency · association |\\n| `c4` | `level` `boundary{label*}` · `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `kind*` `family` `name*` `tech` `desc` · `edges[]`: `from*` `to*` `label` `kind` | level: context · container · component — node kind: person · system · external · store · container · component — edge kind: solid · dashed · forbidden · error |\\n| `block` `infra` `event` `ddd` `network` | `systemLabel` · `layers[]`: `label*` · `groups[]`: `id` `col*`(n) `row*`(n) `cols`(n) `rows`(n) `label*` `color` · `nodes[]`: `id*` `name*` (`col`(n)+`row`(n) **or** `layer`(n)) `w`(n) `kind` `tech` · `edges[]`: `from*` `to*` `label` `kind` | node kind: free string (client · service · microservice · db · cache · queue · gateway · cdn · external · …) — edge kind: solid · dashed · forbidden · error |\\n| `cluster` | `clusters[]`: `id*` `label*` `kind` · `services[]`: `id*` `cluster*` `label*` `kind` `tech` `replicas`(n) · `edges[]`: `from*` `to*` `label` `kind` | edge kind: solid · dashed · forbidden · error |\\n| `frontend` | `nodes[]`: `id*` `name*` `parent` `kind` `note` | kind: root · layout · page · component · leaf · provider · context · hook · store · state |\\n| `felogic` / `belogic` | `groups[]` (as `block`) · `nodes[]`: `id*` `col*`(n) `row*`(n) `w`(n) `kind` `name*` `note` · `edges[]`: `from*` `to*` `label` `kind` | node kind: free string (controller · service · repository · adapter · interface · strategy · hook · …) — edge kind: uses · implements · reads · egress · https · api · dashed · async |\\n| `graph` | `nodes[]`: `id*` `col*`(n) `row*`(n) `label*` `group`(n) · `edges[]`: `from*` `to*` `label` `dir` | dir: directed · undirected |\\n| `mece` | `nodes[]`: `id*` `parent` `label*` `note` | — |\\n| `tree` | `nodes[]`: `id*` `parent` `label*` `note` | — |\\n| `pyramid` | `levels[]`: `label*` `desc` | — |\\n| `funnel` | `stages[]`: `label*` `value*` | — |\\n| `quadrant` | `xAxis{label, low, high}` `yAxis{label, low, high}` · `items[]`: `x*`(n, 0..1) `y*`(n, 0..1) `label*` | — |\\n| `wireframe` | `screens[]`: `device` `title` `url` `label` `elements[]`: `type` `label` `rows`(n) `align` `tone` | device: desktop · browser · phone — element type: header · subheader · text · button · input · search · image · avatar · card · list · nav · tabs · divider · badge · toggle · spacer — align: l · c · r — tone: accent · muted · danger |\\n\\n**Reading the contract:**\\n\\n- A block with **no items at all** is a `W_EMPTY_BLOCK` warning — give it content\\n or delete it. The `*` fields are the minimum to make each item valid.\\n- **Grid blocks** (`flow` · `state` · `dfd` · `c4` · `uml` · `graph` · `swimlane`\\n · `felogic`/`belogic` · grid-mode `block`) require `col`/`row` (1-indexed) on\\n every node. Adding `layers:` to `block`/`infra`/`event`/`ddd`/`network` switches\\n them to band layout, where nodes use `layer:` (an index) instead of `col`/`row`.\\n- **Numbers stay unquoted:** coordinates (`col` `row` `lane` `w`), `points`,\\n `replicas`, `group`, `start`/`span`, quadrant `x`/`y`, and `emotion[]`. Quote\\n anything string-like that *looks* numeric (`version`, `delta: \\\"0\\\"`) — see *YAML\\n pitfalls*.\\n- **`kind` is optional on most nodes/edges** — omit it for the neutral default;\\n set it only to get the right glyph, colour, or marker.\\n\\n## The 41 block types — by family\\n\\n### Document & meta\\n\\n#### `meta` — document cover (first block only)\\n```meta\\ntitle: Orders API\\nsubtitle: How the orders service accepts and persists a purchase.\\ntag: API · v1\\n```\\n\\n### Prose & structure\\n\\n#### `prose` — structured prose (heading / paragraph / list / quote)\\n```prose\\ntitle: Background\\nblocks:\\n - { type: h, text: Why this exists }\\n - { type: p, text: A short paragraph explaining context. }\\n - { type: ul, items: [Idea one, Idea two] }\\n - { type: quote, text: A pull-quote. }\\n```\\n\\n#### `callout` — note / tip / warning / danger\\n```callout\\ntone: warn\\ntitle: Idempotency required\\nbody: Clients must send an Idempotency-Key header so retries are safe.\\n```\\n`tone` is `note | tip | warn | danger`.\\n\\n#### `glossary` — term / definition rows\\n```glossary\\nterms:\\n - { term: Idempotent, def: A replay produces the same outcome. }\\n - { term: SLO, def: Service-level objective the team commits to. }\\n```\\n\\n### Tables & metrics\\n\\n#### `table` — comparison table\\n```table\\ncolumns: [Code, Meaning, When]\\nrows:\\n - [201, Created, Order persisted]\\n - [409, Conflict, Idempotency key reused]\\n```\\nColumns may be objects: `{ label, align: l|c|r, highlight: boolean }`. Cells\\nmay be objects: `{ v: value, tone: pos|neg|warn|muted, lead: boolean,\\nhighlight: boolean }`. Optional top-level `note`.\\n\\n#### `stats` — KPI / metric cards\\n```stats\\ntitle: This quarter\\nstats:\\n - { value: 12.4k, label: Active users, delta: \\\"+18%\\\", trend: up }\\n - { value: 99.95%, label: Uptime, delta: \\\"0\\\", trend: flat }\\n```\\n`trend` is `up | down | flat`. `delta` is a string.\\n\\n#### `code` — one or more code blocks\\n```code\\nblocks:\\n - title: schema.sql\\n lang: PostgreSQL\\n code: |\\n CREATE TABLE orders (id uuid PRIMARY KEY, total numeric);\\n```\\nRenders with syntax highlighting (kw, str, num, fn, ty, com tokens).\\n\\n### Sequence & state\\n\\n#### `sequence` — interaction over time (rich SVG + step list + footer)\\n```sequence\\nid: seq-place-order\\ntitle: One transaction wraps authorize + persist.\\nlede: Time runs downward. Solid arrows are sync; dashed are responses.\\ndescription: Happy path shown.\\nendpoint: { method: POST, path: /orders }\\nactors:\\n - { id: Client, name: Client, sub: web / mobile }\\n - { id: API, name: Orders API, sub: orders handler }\\n - { id: PG, name: Postgres, sub: orders }\\n - { id: Payment, name: Payment GW, sub: external, external: true }\\nmessages:\\n - { from: Client, to: API, label: POST /orders, kind: sync, summary: \\\"Place the order with cart, token, idempotency key.\\\", code: \\\"POST /orders\\\\nIdempotency-Key: ...\\\" }\\n - { from: API, to: API, kind: note, label: validate token, summary: \\\"Validate bearer, check idempotency key.\\\" }\\n - { from: API, to: PG, label: INSERT order, kind: sync, summary: \\\"Open the txn and insert in PENDING.\\\", note: \\\"Required index: orders(idempotency_key).\\\" }\\n - { from: PG, to: API, label: order_id, kind: response, summary: \\\"Returns the new order_id.\\\" }\\n - { from: API, to: Client, label: 201 Created, kind: response, summary: \\\"201 with the order.\\\" }\\nfoot:\\n - { label: Target p95, value: 250ms }\\n - { label: Idempotent, value: via Idempotency-Key (24h TTL) }\\n```\\nEach message: `from` + `to` (must match an actor `id`), `label`,\\noptional `kind` (`sync | response | async | error | note`).\\n- `note` kind is a numbered annotation on one lane — no arrow.\\n- `summary` (long form for the step list under the SVG),\\n- `code` (a code snippet inside the step item),\\n- `note` field (italic-gray sub-note below the summary).\\n`endpoint.method` colours the tag pill (POST → navy, GET → green, etc.).\\n`foot` items render as key/value pills beneath the diagram.\\n\\n#### `state` — state machine (+ transition table)\\n```state\\ntitle: Order lifecycle\\nstates:\\n - { id: s0, col: 1, row: 1, kind: start }\\n - { id: pending, col: 2, row: 1, kind: wait, name: PENDING }\\n - { id: confirmed, col: 3, row: 1, kind: active, name: CONFIRMED }\\n - { id: end, col: 4, row: 1, kind: terminal }\\ntransitions:\\n - { from: s0, to: pending, event: create }\\n - { from: pending, to: confirmed, event: pay }\\n - { from: confirmed, to: end, event: ship }\\n```\\n`kind` on a state is `start | terminal | active | wait`.\\n\\n### Data model\\n\\n#### `erd` — entities and relations\\n```erd\\nentities:\\n - name: orders\\n columns:\\n - { name: id, type: uuid, pk: true }\\n - { name: user_id, type: uuid, fk: true }\\nrelations:\\n - { from: orders, to: order_items, card: \\\"1:N\\\" }\\n```\\nColumn flags are booleans (`pk: true`, `fk: true`). Relation `card` is\\n`\\\"1:1\\\" | \\\"1:N\\\" | \\\"N:M\\\"`. Quote cardinality values because YAML parses the\\nunquoted form as a number sequence.\\n\\n### Architecture diagrams\\n\\n#### `c4` — context / container / component\\n```c4\\ntitle: System context\\nlevel: container\\nboundary: { label: ShopCo platform }\\nnodes:\\n - { id: user, col: 1, row: 1, kind: person, name: Shopper, desc: A customer. }\\n - { id: api, col: 2, row: 1, kind: container, family: service, name: Orders API, tech: Go }\\n - { id: pay, col: 3, row: 1, kind: external, name: Payment GW }\\nedges:\\n - { from: user, to: api, label: places order }\\n - { from: api, to: pay, label: authorises }\\n```\\n`kind` is `person | system | external | store | container | component`.\\n`family` (for `container`/`component`): `client | service | data | store |\\ncontroller | repo | external`. Edge `kind` is `solid | dashed | forbidden |\\nerror`. Optional `boundary` draws a dashed box around the internal nodes.\\n\\n#### `block` — grid architecture with optional groups\\n```block\\ntitle: System architecture\\ngroups:\\n - { col: 1, row: 1, cols: 1, rows: 2, label: Edge, color: \\\"#0e54a1\\\" }\\nnodes:\\n - { id: api, col: 2, row: 1, kind: service, name: API, tech: Go }\\n - { id: pg, col: 2, row: 2, kind: store, name: Postgres }\\nedges:\\n - { from: api, to: pg }\\n```\\nNode `kind` is one of: `client · service · microservice · compute · container ·\\ndata · store · db · database · bucket · blob · object · queue · cache · gateway\\n· lb · function · lambda · cdn · external · producer · topic · consumer ·\\ncontext · firewall`. Known kinds get coloured + glyphed automatically.\\n\\n**Nested zones (AWS-style VPC / subnets).** `groups` can overlap to nest: draw\\nthe outer zone (e.g. a VPC) as one big group, then inner zones (public / private\\nsubnets) as smaller groups inside its cell range. The renderer paints larger\\ngroups first, so smaller ones layer on top. Nodes still sit in grid `col`/`row`\\ncells; the groups just frame them.\\n```infra\\ntitle: VPC topology\\ngroups:\\n - { col: 2, row: 1, cols: 3, rows: 3, label: \\\"VPC 10.0.0.0/16\\\", color: \\\"#0e54a1\\\" }\\n - { col: 2, row: 1, cols: 3, rows: 1, label: Public subnet, color: \\\"#1f9747\\\" }\\n - { col: 2, row: 2, cols: 3, rows: 1, label: \\\"Private subnet · app\\\", color: \\\"#1a6dbe\\\" }\\nnodes:\\n - { id: cf, col: 1, row: 1, kind: cdn, name: CloudFront }\\n - { id: alb, col: 2, row: 1, kind: gateway, name: ALB }\\n - { id: svc, col: 2, row: 2, kind: microservice, name: orders, tech: ECS }\\nedges:\\n - { from: cf, to: alb }\\n - { from: alb, to: svc }\\n```\\n\\n#### `infra` — same engine, layered layout\\n```infra\\ntitle: AWS topology\\nsystemLabel: ShopCo · us-east-1\\nlayers:\\n - { label: Edge }\\n - { label: Compute }\\n - { label: Data }\\nnodes:\\n - { id: cf, layer: 0, kind: cdn, name: CloudFront }\\n - { id: api, layer: 1, kind: service, name: API }\\n - { id: pg, layer: 2, kind: store, name: orders-db }\\n```\\nPresence of `layers` switches `block`/`infra` to horizontal-band layout.\\nNodes use `layer: <index>` instead of `col`/`row`.\\n\\n#### `event` — pub / sub choreography (same shape as block)\\n```event\\ntitle: Order events\\nnodes:\\n - { id: orders, col: 1, row: 1, kind: producer, name: orders }\\n - { id: bus, col: 2, row: 1, kind: topic, name: order.events }\\n - { id: ship, col: 3, row: 1, kind: consumer, name: shipping }\\nedges:\\n - { from: orders, to: bus }\\n - { from: bus, to: ship }\\n```\\n\\n#### `ddd` — bounded-context map (same shape as block)\\n```ddd\\ntitle: Bounded contexts\\nnodes:\\n - { id: cat, col: 1, row: 1, kind: context, name: Catalog }\\n - { id: order, col: 2, row: 1, kind: context, name: Orders }\\nedges:\\n - { from: order, to: cat, label: reads, kind: dashed }\\n```\\n\\n#### `network` — security zones (same shape as block)\\nUses the `firewall` glyph and red zone tag.\\n\\n#### `cluster` — k8s-style nested boxes with services\\n```cluster\\ntitle: Production cluster\\nclusters:\\n - { id: api, label: api namespace, kind: namespace }\\nservices:\\n - { id: web, cluster: api, label: web, kind: service, tech: Next.js, replicas: 3 }\\n - { id: orders, cluster: api, label: orders, kind: service, tech: Go, replicas: 4 }\\nedges:\\n - { from: web, to: orders }\\n```\\n`replicas` renders as small bars (capped at 5 + `×N` label).\\n\\n### Code-flavoured architecture\\n\\n#### `felogic` / `belogic` — frontend / backend module graph\\n```felogic\\ntitle: Frontend logic\\ngroups:\\n - { id: app, label: App (browser), col: 1, row: 1, cols: 3, rows: 3, color: \\\"#0e54a1\\\" }\\nnodes:\\n - { id: ui, col: 1, row: 1, kind: component, name: Checkout UI }\\n - { id: iface, col: 2, row: 2, kind: interface, name: DiscountStrategy }\\n - { id: impl, col: 1, row: 3, kind: strategy, name: PercentOff }\\nedges:\\n - { from: ui, to: iface, kind: uses }\\n - { from: impl, to: iface, kind: implements }\\n```\\nNode `kind` is one of: `engine | core · interface · strategy | adapter | impl ·\\ncontroller | handler | route · service | usecase | apiclient | client ·\\nrepository | repo | dao · worker | consumer · middleware · model | entity ·\\ndb | store | database · cache · queue | bus | broker · state | store_state ·\\nhook · external | backend | api | thirdparty`. Edge `kind` is\\n`uses | implements | egress | https | api | reads | dashed | async`.\\n`interface` nodes render with an «interface» stereotype banner.\\n\\n#### `frontend` — top-down component tree\\n```frontend\\ntitle: React component tree\\nnodes:\\n - { id: app, kind: root, name: App }\\n - { id: layout, parent: app, kind: layout, name: Layout }\\n - { id: page, parent: layout, kind: page, name: HomePage }\\n - { id: hook, parent: page, kind: hook, name: useData }\\n```\\n`kind` is `root | layout | page | component | leaf | provider | context |\\nhook | store | state`. Parents render above children with link paths.\\n\\n#### `uml` — class diagram\\n```uml\\nclasses:\\n - { id: order, col: 1, row: 1, name: Order, attrs: [\\\"id: UUID\\\", \\\"status: Status\\\"], methods: [\\\"place()\\\", \\\"cancel()\\\"] }\\n - { id: status, col: 1, row: 2, name: Status, stereotype: enumeration, attrs: [\\\"PENDING\\\", \\\"CONFIRMED\\\"] }\\nrels:\\n - { from: order, to: status, kind: association, label: has }\\n```\\nRelation `kind` is `inheritance | extends | implementation | implements |\\ncomposition | aggregation | dependency | association` (drives the marker\\nshape).\\n\\n#### `dag` — pipeline / DAG (reuses flow's renderer)\\n```dag\\ntitle: CI pipeline\\nnodes:\\n - { id: src, col: 1, row: 1, kind: start, label: Source }\\n - { id: build, col: 2, row: 1, kind: process, label: Build }\\n - { id: deploy, col: 3, row: 1, kind: end, label: Deploy }\\nedges:\\n - { from: src, to: build }\\n - { from: build, to: deploy }\\n```\\n\\n### Flow & process\\n\\n#### `flow` — flowchart with decisions\\n```flow\\ntitle: Decision flow\\nnodes:\\n - { id: start, col: 1, row: 1, kind: start, label: Start }\\n - { id: check, col: 2, row: 1, kind: decision, label: Token valid? }\\n - { id: ok, col: 3, row: 1, kind: end, label: Done }\\n - { id: bad, col: 2, row: 2, kind: end, label: Reject }\\nedges:\\n - { from: start, to: check }\\n - { from: check, to: ok, label: \\\"yes\\\" }\\n - { from: check, to: bad, label: \\\"no\\\", kind: error }\\n```\\n`kind` is `start | end | decision | process`. Edge `kind: error` (or labels\\nstarting with `no/fail/error/reject`) render in red.\\n\\n#### `dfd` — data-flow diagram\\n```dfd\\nnodes:\\n - { id: client, col: 1, row: 1, kind: external, name: Client }\\n - { id: proc, col: 2, row: 1, kind: process, name: Place order, num: 1 }\\n - { id: db, col: 3, row: 1, kind: store, name: orders }\\nedges:\\n - { from: client, to: proc }\\n - { from: proc, to: db }\\n```\\n`kind` is `process | external | store | datastore`. Optional `num` on\\nprocesses.\\n\\n#### `swimlane` — cross-functional process\\n```swimlane\\nlanes:\\n - { label: Customer }\\n - { label: Sales }\\nsteps:\\n - { id: req, col: 1, lane: 0, kind: start, label: Submit }\\n - { id: fulfill, col: 2, lane: 1, label: Fulfill }\\nlinks:\\n - { from: req, to: fulfill }\\n```\\nStep `kind` is `action | decision | start | end | wait`.\\n\\n### Charts & overviews\\n\\n#### `graph` — node-link graph\\n```graph\\nnodes:\\n - { id: a, col: 1, row: 1, label: Module A, group: 0 }\\n - { id: b, col: 2, row: 1, label: Module B, group: 1 }\\nedges:\\n - { from: a, to: b, dir: undirected }\\n```\\n`group: <n>` cycles through the chart palette. Edge `dir` is `directed`\\n(default) or `undirected`.\\n\\n#### `mece` — issue tree (MECE breakdown)\\n```mece\\ntitle: Why are conversions down?\\nnodes:\\n - { id: root, label: Lower conversion }\\n - { id: traffic, parent: root, label: Traffic quality }\\n - { id: friction, parent: root, label: Funnel friction }\\n - { id: f1, parent: friction, label: Slow checkout, note: p95 > 4s }\\n```\\nLeft-to-right tree, depth-coloured stripes, DFS layout.\\n\\n#### `tree` — indented hierarchy (HTML, not SVG)\\n```tree\\nnodes:\\n - { id: src, label: src }\\n - { id: components, parent: src, label: components }\\n - { id: index, parent: src, label: index.ts, note: entry }\\n```\\n\\n#### `gantt` — schedule bars\\n```gantt\\nperiods: [Q1, Q2, Q3, Q4]\\ntasks:\\n - { label: Discovery, start: 0, span: 1, kind: done }\\n - { label: Build, start: 1, span: 2, kind: active }\\n - { label: GA, start: 3, span: 1, kind: milestone }\\n```\\nTask `kind` is `done | active | current | milestone` (drives bar colour).\\n\\n#### `funnel` — conversion funnel\\n```funnel\\nstages:\\n - { label: Visited, value: 10000 }\\n - { label: Signed up, value: 2400 }\\n - { label: Paying, value: 320 }\\n```\\nAuto-computes conversion percentages.\\n\\n#### `pyramid` — stacked hierarchy (top → bottom widening)\\n```pyramid\\nlevels:\\n - { label: Vision, desc: Long-term direction }\\n - { label: Tactics, desc: This quarter }\\n```\\n\\n#### `quadrant` — 2×2 matrix\\n```quadrant\\nxAxis: { label: Effort, low: Low, high: High }\\nyAxis: { label: Impact, low: Low, high: High }\\nitems:\\n - { x: 0.2, y: 0.8, label: Quick win }\\n - { x: 0.8, y: 0.8, label: Big bet }\\n```\\n`x` / `y` are 0..1.\\n\\n#### `journey` — user journey map with optional emotion curve\\n```journey\\nstages: [{ label: Discover }, { label: Sign up }, { label: Pay }]\\nrows:\\n - { label: Touchpoint, cells: [Landing, Form, Checkout] }\\n - { label: Friction, cells: [Low, High, Medium] }\\nemotion: [0.7, 0.3, 0.8]\\n```\\n\\n### Planning & meta\\n\\n#### `userstory` — agile story + acceptance criteria + links\\n```userstory\\nid: US-142\\nrole: shopper\\nwant: pay for my cart in one step\\nsoThat: I can complete my purchase quickly\\npriority: High\\npoints: 5\\ncriteria:\\n - { given: I have items, when: I submit valid payment, then: an order is created }\\nlinks:\\n - { ref: orders-api#seq-place-order, mode: sequence, label: Request flow }\\n```\\n`links` may use `ref: doc#id` (a real cross-reference) or a plain label.\\n\\n#### `timeline` — phases / roadmap\\n```timeline\\nitems:\\n - { label: P0 — Core, date: now, status: current, desc: parser + resolver }\\n - { label: P1 — CLI, date: next, status: next, desc: init / check / render }\\n```\\n`status` is `done | current | next | future` (colours the dot).\\n\\n#### `kanban` — flexible columns\\n```kanban\\ncolumns:\\n - label: Now\\n cards:\\n - { title: Core parser }\\n - { title: Validation, tag: priority }\\n - label: Next\\n cards:\\n - { title: Hot reload }\\n```\\n\\n#### `tracker` — task list with status / priority / owner / due\\n```tracker\\nitems:\\n - { task: First task, status: doing, priority: high, owner: alice, due: 2026-01-15 }\\n - { task: Second task, status: todo, priority: med }\\n```\\n`status` is `todo | doing | done | blocked`; `priority` is `high | med | low`.\\n\\n#### `cvt` — current vs target (before / after)\\n```cvt\\ntitle: Migration plan\\ncurrent:\\n label: Today\\n items: [Single monolith, Shared DB, Manual deploys]\\ntarget:\\n label: Target\\n items: [Modular services, Per-service stores, Continuous releases]\\nnote: Migrate one service per quarter.\\n```\\n\\n#### `proscons` — pros vs cons (two columns)\\n```proscons\\nprosLabel: Synchronous\\nconsLabel: Asynchronous\\npros: [Easy to reason about, One transaction]\\ncons: [Latency-bound, Single point of failure]\\n```\\n\\n#### `agenda` — meeting agenda\\n```agenda\\nitems:\\n - { time: \\\"09:00\\\", duration: 30m, title: Round-robin, owner: Host }\\n - { time: \\\"09:30\\\", duration: 60m, title: Deep dive, desc: API team }\\n```\\n\\n### UI mockups\\n\\n#### `wireframe` — low-fi screen mockups (desktop / browser / phone)\\n```wireframe\\ntitle: What the user sees\\nscreens:\\n - device: browser\\n title: Notification center\\n url: app.example.com/inbox\\n label: Desktop — notification center\\n elements:\\n - { type: nav, label: \\\"Home, Inbox, Settings\\\" }\\n - { type: header, label: Notifications }\\n - { type: badge, label: \\\"3 new\\\", tone: danger, align: r }\\n - { type: list, rows: 4 }\\n - { type: button, label: Mark all as read }\\n - device: phone\\n title: \\\"9:41\\\"\\n label: iPhone — live bell + feed\\n elements:\\n - { type: header, label: Alerts }\\n - { type: card, rows: 3 }\\n - { type: tabs, label: \\\"Home, Search, Bell, You\\\" }\\n```\\n`screens` lay out left-to-right; each picks a `device` frame (`desktop` /\\n`browser` / `phone`) and stacks `elements` top-to-bottom. `device: browser`\\nshows an address bar (`url`); `phone` adds a notch + home indicator. `title`\\nis the window/status-bar text, `label` is the caption under the frame.\\n\\nElement `type` is one of: `header · subheader · text · button · input · search\\n· image · avatar · card · list · nav · tabs · divider · badge · toggle ·\\nspacer`. `rows` repeats stack-like elements (`list` / `card`) or sizes `text` /\\n`spacer`. `nav` / `tabs` read their items from a **comma-separated** `label`\\n(quote it). `align` is `l | c | r`; `tone` is `accent | muted | danger` (colours\\nbuttons, badges, toggles). Keep it low-fidelity — it's a wireframe, not a comp.\\n\\n## Cross-references (`doc#id`)\\n\\nBlocks become a connected model through references:\\n\\n- Give a block a unique `id:` (unique across the **whole repo**).\\n- Reference it as `doc#id`, where `doc` is the target file's path **under the\\n docs root** without `.md` (e.g. `orders-api`, or `architecture/overview`).\\n A bare `#id` means the current document — **always prefer `#id` when\\n referencing inside the same doc**, since it survives renames.\\n- A reference whose target id does not exist is a **dangling reference** and\\n fails validation. Only add a `ref` to an id you know exists (or are creating\\n in the same change).\\n- **Don't repeat the current document's slug in a ref.** If you're editing\\n `docs/orders.md` and want to point at `id: seq-place-order` in the same file,\\n write `ref: \\\"#seq-place-order\\\"`, NOT `ref: \\\"orders#seq-place-order\\\"`.\\n\\nThe only reference-bearing field in v1 is `userstory.links[].ref`.\\n\\n## Workflow — always validate\\n\\nAfter creating or editing any doc, run the CLI and fix everything it reports:\\n\\n```\\navo check # validate all docs: schema + dangling refs + dup ids\\navo check docs/orders-api.md # validate one file\\navo check --json # machine-readable, useful in CI\\navo render docs/orders-api.md -o out.html\\navo preview docs/orders-api.md # render and open it\\navo export docs/**/*.md --format pdf --out dist/\\navo new # scaffold a new doc or block from a template\\navo sync openapi spec.yaml --out docs/api.md # generate a doc from an OpenAPI spec\\n```\\n\\n`avo check` exits non-zero on any error and names the file, line, and\\noffending value. **A change is not done until `avo check` passes.**\\n\\n## When `avo check` fails — error code recipes\\n\\nEvery diagnostic carries a stable code so you can mechanically apply a fix.\\n\\n| Code | What it means | First thing to check |\\n|---|---|---|\\n| `E_PARSE_YAML` | YAML body failed to parse. Almost always a quoting issue. | Re-read *YAML pitfalls* above. Unquoted `,`/`:`/`#` in a `desc` is the usual culprit. |\\n| `E_SCHEMA` | A field is missing, the wrong type, or an unknown name. Message contains the path (e.g. `sequence: messages.2.kind: ...`). | Compare your YAML against the block reference. Reject the urge to add fields not listed in this skill — the schema is strict. |\\n| `E_DANGLING_REF` | A `userstory.links[].ref` points at an id that doesn't exist anywhere in the repo. `value` is the bad ref. | Either fix the ref string, or add the missing `id:` to the target block. Bare `#id` is current-doc; `doc#id` is path-under-docs-root + `#id`. |\\n| `E_DUP_ID` | The same `id:` was used in two blocks. Message names both files + lines. | Ids are repo-global. Rename one. |\\n| `E_BAD_REF_FORMAT` | A `ref:` string isn't `doc#id` or `#id` shape. | Match the format exactly. The id slug is `[\\\\w-]+`. |\\n| `W_EMPTY_BLOCK` | A typed block had an empty body. | Add fields or remove the block. |\\n\\n### Common schema errors I see often\\n\\n| Symptom | Cause | Fix |\\n|---|---|---|\\n| `Expected string, received number` on `tech: 16` | YAML parsed `16` as a number. | Quote: `tech: \\\"16\\\"`. |\\n| `Invalid enum value` on `tone: xyz` / `kind: xyz` / `status: xyz` | Used a value not in the enum. | Stick to the documented enum (`tone: note\\\\|tip\\\\|warn\\\\|danger`, etc.). |\\n| `Unrecognized key(s) in object: 'foo'` | You added a field that isn't in the schema. | Schemas are strict. Either remove the field, or use a documented one. |\\n| Schemas on the `meta` block fail | You put a `meta` block somewhere other than first. | Move it to the top of the file. |\\n| `Unrecognized key(s) in object: 'persists'` and similar | Unquoted comma in a flow-style mapping turned a phrase into multiple keys. | Quote the value containing the comma. |\\n\\n## Field semantics — clarifications\\n\\nA few fields are easy to misuse. Lock these in.\\n\\n- `sequence.actors[].sub` is the **subtitle** under the actor's name on the\\n lane head (e.g. `sub: web / mobile`, `sub: orders handler`). Keep it short —\\n 2-4 words.\\n- `sequence.actors[].external: true` darkens the lane (slate instead of navy),\\n signaling the actor lives outside your service boundary.\\n- `sequence.messages[].kind: note` is **not a message** — it's a numbered\\n annotation on the from-actor's lane, with no arrow. Use it for things like\\n \\\"validate token\\\" that don't cross a boundary.\\n- `sequence.messages[].summary` is the longer text shown in the step-by-step\\n list **below** the SVG. Keep `label` short (the SVG arrow) and put detail in\\n `summary`. `code:` adds a `<pre>` snippet inside the step item.\\n- On most diagram blocks: `lede` renders as a `<p class=\\\"section-lede\\\">` under\\n the section title, sized for an editorial paragraph. `description` renders\\n inside the diagram frame as the diagram's caption. Use both when you have\\n both kinds of text to convey.\\n- `userstory.links[].ref` is the only field in v1 that creates a real\\n cross-document reference. Other `links` items render as plain chips.\\n- `block` / `infra` / `event` / `ddd` / `network` use **identical YAML** — the\\n block type slug only changes the colored tag pill. Pick the slug that best\\n signals intent to a reader, not for any structural reason.\\n- `userstory.id` is what other docs reference. Use a short stable id like\\n `US-142`, not a sentence.\\n- Diagram blocks with `layers:` set go into **horizontal-band layout**. Without\\n `layers:` they use **grid layout** with `col`/`row`. Don't mix — the renderer\\n uses the presence of `layers` to switch modes.\\n\\n## Do / Don't\\n\\n**Do**\\n\\n- Edit the specific block you need to change — surgically, a few lines — rather\\n than regenerating a whole document.\\n- Keep narrative in Markdown prose and structure in blocks.\\n- Use `title` + `lede` on diagram blocks so the section header reads well.\\n- Quote YAML values that contain commas, colons, or `1:N` cardinality strings\\n (`desc: \\\"40 blocks, themes, agent skill\\\"`, `card: \\\"1:N\\\"`).\\n- Give a block an `id:` whenever something else might reference it.\\n- Run `avo check` and resolve all diagnostics before finishing.\\n- When unsure which architecture block to use, pick `block` for boxes-and-arrows\\n or `c4` for actor / system context — both are safe defaults.\\n\\n**Don't**\\n\\n- Paste raw HTML, `<svg>`, or `<style>` into a doc. Use blocks.\\n- Invent block types or fields. The schemas are strict; unknown fields error.\\n- Reference a `doc#id` that doesn't exist. Either fix the ref or add the id.\\n- Stuff a whole spec into one giant block. Decompose into 3-5 focused blocks.\\n- Write a `description` longer than 2 sentences. Use prose instead for long\\n narrative.\\n- Put commas inside flow-style mappings without quoting (see *YAML pitfalls*).\\n- Reuse the same `id:` in two blocks. Ids are repo-global unique.\\n- Add a `prose` block AND raw `##` headings for the same idea. Pick one.\\n- Use `frontend` for backend modules, or `felogic` when you mean `frontend`.\\n `frontend` is a top-down hierarchical tree; `felogic` / `belogic` are\\n free-positioned module graphs with edges.\\n\\n## Quick block index (in case you forget)\\n\\n| Family | Blocks |\\n|---|---|\\n| Document & meta | `meta` |\\n| Prose & structure | `prose` `callout` `glossary` |\\n| Tables & metrics | `table` `stats` `code` |\\n| Sequence & state | `sequence` `state` |\\n| Data model | `erd` |\\n| Architecture | `c4` `block` `infra` `event` `ddd` `network` `cluster` |\\n| Code-flavoured | `felogic` `belogic` `frontend` `uml` `dag` |\\n| Flow & process | `flow` `dfd` `swimlane` |\\n| Charts & overviews | `graph` `mece` `tree` `gantt` `funnel` `pyramid` `quadrant` `journey` |\\n| Planning & meta | `userstory` `timeline` `kanban` `tracker` `cvt` `proscons` `agenda` |\\n| UI mockups | `wireframe` |\\n\";\n"],"mappings":";;;AAWA,SAAS,iBAAiB;AAC1B,SAAS,4BAA4B;AACrC,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,sBAAsC;AAC/C,SAAS,yBAAyB;;;ACxB3B,IAAM,WAAW;;;AD2BxB,IAAM,SAAS,CAAC,YAAY,WAAW,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAE9E,SAAS,kBAAkB,OAAsC;AAC/D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MACJ,IAAI,CAAC,MAAM;AACV,UAAM,MACJ,EAAE,SAAS,SAAY,IAAI,EAAE,IAAI,GAAG,EAAE,WAAW,SAAY,IAAI,EAAE,MAAM,KAAK,EAAE,KAAK;AACvF,UAAM,OAAO,EAAE,SAAS,SAAY,WAAW,EAAE,IAAI,MAAM;AAC3D,WAAO,GAAG,EAAE,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,GAAG,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,GAAG,IAAI;AAAA,EACjF,CAAC,EACA,KAAK,IAAI;AACd;AAEA,IAAM,SAAS,IAAI,UAAU,EAAE,MAAM,WAAW,SAAS,QAAQ,CAAC;AAElE,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,UAAU,EAAE,OAAO,EAAE,SAAS,gCAAgC;AAAA,MAC9D,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oCAAoC;AAAA,IAC3E;AAAA,EACF;AAAA,EACA,CAAC,EAAE,UAAU,KAAK,MAAM;AACtB,UAAM,IAAI,QAAQ;AAClB,UAAM,QAAQ,iBAAiB,cAAc,UAAU,CAAC,GAAG,CAAC;AAC5D,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,kBAAkB,KAAK,EAAE,CAAC,EAAE;AAAA,EACvE;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,MACX,UAAU,EAAE,OAAO;AAAA,MACnB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,OAAO,EAAE,KAAK,MAAM,EAAE,SAAS,EAAE,SAAS,kCAAkC;AAAA,IAC9E;AAAA,EACF;AAAA,EACA,CAAC,EAAE,UAAU,MAAM,MAAM,MAAM;AAC7B,UAAM,OAAO;AAAA,MACX,cAAc,UAAU,QAAQ,KAAK;AAAA,MACrC,UAAU,SAAY,EAAE,MAA0B,IAAI,CAAC;AAAA,IACzD;AACA,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,CAAC,EAAE;AAAA,EACnD;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,CAAC;AAAA,EAChB;AAAA,EACA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,YAAY,KAAK,IAAI,EAAE,CAAC,EAAE;AACrE;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,WAAW,CAA0B,EAAE;AAAA,EACzE;AAAA,EACA,CAAC,EAAE,KAAK,MAAM;AACZ,UAAM,SAAS,aAAa,IAAiC;AAC7D,UAAM,OAAO,gBAAgB,QAAQ,IAAI;AACzC,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,CAAC,EAAE;AAAA,EAC5E;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa;AAAA,MACX,WAAW,EACR,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC,EAC1D,SAAS,+BAA+B;AAAA,IAC7C;AAAA,EACF;AAAA,EACA,CAAC,EAAE,UAAU,MAAM;AACjB,UAAM,SAA0B,UAAU,IAAI,CAAC,OAAO;AAAA,MACpD,KAAK,cAAc,EAAE,UAAU,EAAE,IAAI;AAAA,MACrC,MAAM,EAAE;AAAA,IACV,EAAE;AACF,UAAM,EAAE,YAAY,IAAI,YAAY,MAAM;AAC1C,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,kBAAkB,WAAW,EAAE,CAAC,EAAE;AAAA,EAC7E;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,aAAa;AAAA,MACX,MAAM,EAAE,OAAO,EAAE,SAAS,oCAAoC;AAAA,MAC9D,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,CAAC,EAAE,MAAM,KAAK,MAAM;AAClB,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO,EAAE,SAAS,MAAM,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,qBAAqB,CAAC,EAAE;AAAA,IAClF;AACA,UAAM,KAAK;AAAA,MACT;AAAA,MACA,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACnC;AACA,WAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,GAAG,CAAC,EAAE;AAAA,EACjD;AACF;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aACE;AAAA,IACF,aAAa,CAAC;AAAA,EAChB;AAAA,EACA,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,SAAS,CAAC,EAAE;AACvD;AAEA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,UAAU;AAAA,EACZ;AAAA,EACA,CAAC,SAAS;AAAA,IACR,UAAU,CAAC,EAAE,KAAK,IAAI,MAAM,UAAU,iBAAiB,MAAM,SAAS,CAAC;AAAA,EACzE;AACF;AAEA,eAAe,OAAsB;AACnC,QAAM,OAAO,QAAQ,IAAI,qBAAqB,CAAC;AAE/C,UAAQ,MAAM,qCAAqC;AACrD;AAEA,KAAK,EAAE,MAAM,CAAC,QAAiB;AAC7B,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avodado/mcp",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Model Context Protocol server for Avodado — author, validate, and render Avodado documents from any MCP client.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -15,9 +15,9 @@
15
15
  "@modelcontextprotocol/sdk": "^1.29.0",
16
16
  "zod": "^3.24.1",
17
17
  "zod-to-json-schema": "^3.25.2",
18
- "@avodado/core": "0.0.1",
19
- "@avodado/render": "0.0.1",
20
- "@avodado/sync": "0.0.1"
18
+ "@avodado/core": "0.0.2",
19
+ "@avodado/render": "0.1.0",
20
+ "@avodado/sync": "0.0.2"
21
21
  },
22
22
  "publishConfig": {
23
23
  "access": "public",