@meltemi/diagrams-assist 1.11.34 → 1.11.36

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/guide.js CHANGED
@@ -6,6 +6,6 @@ export const GUIDE_PAGES = {
6
6
  gantt: "# Gantt charts\n\nUse `diagram <id>: gantt { }` for a plan or a roadmap: tasks scheduled on a time axis from dates,\ndependencies and durations, in sections. Dates and `after` place everything: never write `place`,\n`size`, `route`, `layout` or relations (`a -> b`) here, and never compute a date by hand.\n\n## Statements\n\n```text\nsection <id> [\"Label\"] { … }\ntask <id> [\"Label\"] [from <date>] [after <id>[, <id>…]] [for <duration> | to <date> | until <id>[, <id>…]] [done | active] [critical] [{ … }]\nmilestone <id> [\"Label\"] [at <date>] [after <id>[, <id>…]] [done | active] [critical] [{ … }]\nmarker <id> [\"Label\"] (at <date> | after <id>[, <id>…]) [{ … }]\n```\n\nA section holds tasks, milestones and markers, never another section; they may also stand at the top\nlevel. Every statement has an id, unique in the chart; the label defaults to the id. The clauses\ncome after the label, in any order; a block takes `description \"…\"`, `class a, b`, `link d.e` and\n`url \"…\"`. `from`, `after`, `for`, `to`, `until`, `at`, `done`, `active` and `critical` cannot be\nids. Statuses: planned (neither word), `active`, `done`; `critical` marks the critical path.\n\n## Dates, durations and the calendar\n\n```text\n2026-06-01 // a whole day, unquoted; 2026-06-01T09:30 is an instant (civil time, no zone)\nfor 10d // a number above 0 and s, min, h, d or w: for 1.5h, for 2w, for 30min\nexclude weekends // also weekdays and dates: exclude friday, 2026-12-25 (several statements add up)\ninclude 2026-06-06 // a working day despite the exclusions\nweekStart sunday // first day of weekly ticks (monday by default)\n```\n\nWith exclusions, `d` and `w` count working days (a week is `7 − excluded weekdays` days) and `h`, `min`\nand `s` count the hours of working days. Months and years are not durations: write the days.\n\n## The schedule\n\n- A task with `from` and no `after` starts there; with `after a, b` it starts when the later of them\n ends; with both, at the later of the two (`from` is \"not before\").\n- A task or milestone with neither follows the previous task or milestone of the file, across\n sections. The first one needs `from <date>` or `at <date>`.\n- A start on an excluded day moves to the next working day (a written date warns).\n- `for 5d` adds working time; `to 2026-06-05` is the last day, inclusive; `until a, b` ends when the\n first of them starts. Without an end clause a task lasts one day. A milestone is its start.\n- `after` and `until` name tasks and milestones, never sections or markers. Dependencies are `after`,\n never `a -> b`.\n\n```text\ntask design \"Design\" from 2026-06-01 for 5d\ntask build \"Build\" after design for 10d\ntask docs \"Docs\" after design from 2026-06-15 // not before 15 June, nor before design ends\nmilestone beta \"Beta\" after build\nmarker freeze \"Code freeze\" at 2026-07-01\n```\n\n## Chart settings\n\n```text\ntitle \"Roadmap\"\naxisFormat \"%d %b\" // strftime subset: %a %A %b %B %d %e %H %I %j %m %M %p %q %S %U %V %w %W %y %Y %%\nticks 1w // optional: a whole number and s, min, h, d, w, mo or y; the axis chooses otherwise\naxis bottom // top | bottom | both\nlabels bar // bar | column (task labels in the section column)\ndisplay normal // normal | compact (tasks packed into the fewest rows)\ndependencies shown // shown | hidden\ndayWidth 12 // units a day is wide, 1 to 100000; without it the chart fills its canvas\ntoday // a line at the day the picture is made; today 2026-06-17 pins it\n```\n\n`today` draws only when the day is inside the chart's span. For a picture that does not change with\nthe day (CI, a committed SVG), write `today <date>` or export with\n`pnpm mdg export plan.meltemi --today 2026-07-15`.\n\n## Styles, effects and stories\n\n```text\nrule task { radius 2 } // task, milestone, marker, section and relation (the arrows)\nstyle beta { fill warning } // fill, stroke, width, line, color; a task also radius\nanimate build { effect flow } // flow and trace need a task or milestone that follows others\nanimate beta { effect pulse } // pulse and dash take tasks, milestones, markers and sections\n```\n\n`shape`, `rotation`, `iconPosition`, `labelPosition`, `iconSize`, `routing`, `font`, `fontSize` and\n`fontWeight` are refused in charts.\nIn a story, `reveal`, `hide`, `highlight`, `focus` and `camera` take sections, tasks, milestones and\nmarkers; `draw a, b` grows task bars from their start; `trace live` lights the arrows of the chain\nthat drives a task or milestone that follows others.\n\n## Diagnostics\n\n| Code | Fix |\n| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `gantt.unscheduled` | the first task or milestone has no start: write `from <date>` (`at <date>`) |\n| `gantt.schedule` | a task ends before it starts: check `to` or `until`, or write `for <duration>` |\n| `gantt.cycle` | `after` and `until` loop: remove one reference of the loop |\n| `gantt.relation` | `a -> b` in a chart: write `after a` on `b` |\n| `gantt.excluded-day` | (warning) a written date falls on an excluded day: move it, or make it work with `include` |\n| `prop.invalid-value` | `2026-02-30`, a unit other than `s min h d w`, `0d`, an id that is a clause word, a section in `after`, an unknown `axisFormat` directive, `ticks 7` |\n| `prop.unknown` | a statement of another profile, a section in a section, a word that is no clause: the hint lists them |\n| `prop.duplicate` | two end clauses, a clause twice, `done` with `active`, a marker with `at` and `after`, a second `today` |\n| `ref.unknown-element` | `after` or `until` names no task or milestone: fix the id (the hint suggests close ones) |\n| `layout.ticks-crowded` | (warning) a written `ticks` is too fine: write a longer interval or widen with `dayWidth` |\n\nA loop or an unscheduled task has no dates and is not drawn: fix the error first.\n\n## Converting\n\n`pnpm mdg import plan.mmd` converts a Mermaid `gantt` and writes the dates Mermaid draws: exclusive\nend dates become inclusive `to`, `1w` under excluded weekdays becomes `7d`, months and years become\ndays, `crit`, `done` and `active` become `critical`, `done` and `active`, the `milestone` and `vert`\ntags become a `milestone` and a `marker`, `click … href` becomes `url`, and a chart with no\n`todayMarker` writes `today`. A task whose dates Meltemi resolves differently is reported once with\nboth dates. With `--merge`, a second import keeps the chart's `axisFormat`, `ticks`, `weekStart`,\n`axis`, `labels`, `display`, `dependencies`, `dayWidth` and styles, and takes the schedule from the\nsource. PlantUML `@startgantt` is not imported.\n",
7
7
  c4: "# Models and C4 views\n\nUse a `model` block for the architecture (who uses what, which containers a system has) and C4\nviews to draw it at one level each. Declare entities once in the model; views only list them.\n\n## Model\n\n```text\nmodel commerce {\n person customer \"Cliente\" { description \"Compra en línea\" }\n system shop \"Commerce\" {\n container web \"Web\" { technology \"React\" }\n container api \"API\" {\n technology \"Kotlin\"\n component orders \"Pedidos\"\n }\n datastore db \"Pedidos\" { technology \"PostgreSQL\" }\n api -> db: \"SQL\" as persist // inside shop: api is shop.api\n }\n system bank \"Banco\" { external }\n\n customer -> shop.web: \"Compra\" as visit\n shop.web -> shop.api: \"HTTPS\" as request { technology \"JSON/HTTPS\" }\n shop.api.orders -> bank: \"Autoriza\" as authorize\n}\n```\n\n- Persons and systems at the root; containers and datastores in systems; components in containers\n (`model.invalid-nesting` otherwise).\n- Entities are named by path: `shop.api.orders`. Relations use `->` only and name paths.\n- `external` marks persons and systems outside the organisation (drawn grey and dashed).\n\n## Views\n\n```text\ndiagram containers: c4 using commerce {\n level container // context | container | component\n scope shop // a system; a container for component views\n include customer, shop.web, shop.api, shop.db\n label shop.api \"API de pedidos\" // local text, the model keeps \"API\"\n direction LR\n layout assisted\n placement { place shop.api at (420, 120) }\n style shop.db { fill accent }\n}\n```\n\n- Without `include`, a view draws its default set: everything at the context level, otherwise\n the scope's children and the entities related to them. `exclude` removes entities.\n- A container view draws the scope's containers and datastores (inside a dashed boundary),\n persons and other systems; a component view the scope's components, the other containers of the\n system, persons and other systems. Anything else is `c4.out-of-level`.\n- Relations come from the model; ends inside hidden entities are lifted to the drawn ancestor\n (at the context level `customer -> shop.web` becomes `customer -> shop`). Two relations to the\n same pair stay two arrows; to draw one, write a combination in the view:\n `customer -> shop: \"Usa\" as uses`. A combination with no model relation behind it is\n `c4.unsupported-relation`.\n- Placement, styles and routes take paths: `route request from shop.web.east to shop.api.west`.\n\n## Notes in views\n\nA view accepts `note <id> \"Text\" [on <entity path>]` beside its lists: an annotation of the view,\nnever of the model and never an entity (`include`, `exclude`, `label` and relations cannot name it).\n`note cache \"Cached 5 min\" on shop.api` draws a note with a dotted leader to `shop.api`, which the\nview must draw (else `ref.unknown-element`). It takes `class` and `url`, the view's `style`, `class`,\n`rule` and `animate`, and a `place` in the view's `placement`.\n\n## Files\n\nKeep the model in `models/` and the views in `diagrams/` of a project, and import the model:\n\n```text\nimport commerce from \"../models/commerce.meltemi\"\ndiagram context: c4 using commerce { level context }\n```\n\nSequence and free objects link to entities with `link commerce.shop.api`; a participant without its\nown label shows the entity's.\n\n## Diagnostics\n\n| Code | Fix |\n| ------------------------- | ------------------------------------------------------------------------ |\n| `c4.invalid-level` | add `level context`, `level container` or `level component` |\n| `c4.scope-required` | add `scope <system>` (container view) or `scope <container>` (component) |\n| `c4.invalid-scope` | scope a system or a container; datastores have no components |\n| `c4.out-of-level` | remove the entity from `include`, or change the level |\n| `c4.unsupported-relation` | add the relation to the model, or remove the combination |\n| `ref.unknown-entity` | use the full path from the model's root (`shop.api`, not `api`) |\n| `ref.unknown-model` | declare or import the model named after `using` |\n| `model.invalid-nesting` | move the entity into the right parent |\n| `model.invalid-relation` | relate separate entities, not an entity and its parent |\n",
8
8
  free: "# Free compositions\n\nUse `diagram <id>: free { }` for a slide, an executive picture, a whiteboard, a kanban board or an\nexplanation that does not fit a flow notation. Objects are placed by hand (`layout manual` is the\ndefault); relations, `placement`, constraints, `style`, `class`, `rule`, `animate`, themes,\n`preset` and `canvas` work as in flow diagrams. A whiteboard writes `preset board`: the canvas\ngrows with its content and never reports `layout.too-large`.\n\n## Objects\n\n| Declaration | Object | Default size |\n| --------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------- |\n| `box <id> \"Label\"`, `id[\"L\"]` | a shape with a label and an optional `description` | its shape's size, widened to its text |\n| `id[(\"Label\")]` | a box with the `cylinder` shape | 160 × 64 |\n| `text <id> \"Text\\nmore\"` | measured text without a frame | its extent |\n| `icon <id> \"tabler:server\"` | an icon of the packs; find names with `pnpm mdg assets icons <w>` | 48 × 48 |\n| `image <id> \"img/logo.png\"` | a PNG, JPEG, GIF, WebP or SVG file of the project, relative to the file | its pixel size, at most 640 wide |\n| `note <id> \"Text\" [on <element>]` | an annotation: text with no frame until styled, and a dotted leader to the element it is attached to (below) | its text's extent |\n| `sticky <id> \"Text\"` | a sticky note: a square card whose text wraps and shrinks to fit (below) | 160 × 160, never grown |\n| `group <id> \"Label\" { ... }` | a band holding objects and relations; `group <id> \"\" { }` is plain; `layout column` makes it a list (below) | written, or fitted to children |\n| `line <id> from (x, y) to (x, y)` | a line that joins no element: a divider, a bracket, an underline (below) | the bounding box of its points |\n| `pen <id> [(x, y), (x, y), ...]` | a freehand stroke: handwriting, a drawn arrow, a highlighter mark (below) | its points' box plus half its width |\n\n`node`, `decision`, `data` and `tag` are flow kinds and are refused here; `note`, `sticky` and\n`pen` are free kinds. Relations take the lines without heads `a -- b` and `a --- b` too.\n\n## Notes\n\n`note remark \"Checked at the gateway\" on gateway { layer front }` is text at the theme's note size in\nthe muted colour, left-aligned and without a frame. `style remark { fill \"#fff7d6\"; stroke warning;\nline dashed }` gives it an outline (any of `fill`, `stroke` or `pattern` does); `font`, `fontSize`,\n`fontWeight`, `textAlign`, `radius`, `color`, `icon` and `rotation` apply, `shape` does not. The\nblock takes `description`, `class`, `layer`, `link` and `url`. `on <element>` attaches the note to\nany other element of the diagram: a dotted leader joins them, `layout auto` keeps them near each\nother, renaming the element rewrites the clause, and deleting the element leaves the note. An\nunknown target is `ref.unknown-element`; a note on itself, `prop.invalid-value`. A note with an\noutline can take `animate remark { effect dash }`; without one, only a pulse.\n\n## Stickies\n\n```text\nsticky cache \"Cache the catalogue at the edge before the sale\"\nsticky retry \"Retry payments\\nonce\"\nstyle retry { fill \"#f8bbd0\"; rotation 4 }\n```\n\n- A 160 × 160 card (scaled with the theme's `labelSize`, or its `size`) that never grows: the\n text wraps at spaces inside the theme's `padding`, at `fontSize` or 1.2 × the label size\n (15.6 px), and shrinks 1 px at a time down to 8 px until it fits. Text that still does not fit\n is `layout.text-overflow` (warning) and clipped: shorten it or use the `size` in the hint.\n- Colours: the theme's `sticky` card (`#fff59d` on light themes) and `stickyText` text; `fill`\n and `color` override them. Common fills: yellow `#fff59d`, pink `#f8bbd0`, green `#c8e6c9`,\n blue `#bbdefb`, orange `#ffe0b2`, purple `#e1bee7`. A soft shadow, `radius` 2, an outline only\n with `stroke`. Text is centred (`textAlign`, `verticalAlign`); an `icon` sits top left.\n- Takes `fill`, `stroke`, `color`, `line`, `width`, `fontSize`, `fontWeight`, `textAlign`,\n `verticalAlign`, `radius`, `rotation`, `opacity`, `icon`, `iconColor`, `iconSize`; `shape`,\n `pattern`, `iconPosition` and `labelPosition` are `prop.invalid-value`. `rule sticky { }` styles\n them all.\n- A sticky is a box for everything else: `place`, `size`, ports, constraints, relation endpoints\n (`cache -> retry`), stories and effects. `sticky s` without text is `prop.invalid-value`.\n\n## Shapes and corners\n\n`style a { shape hexagon }` draws a box (or a flow `node`) as one of twenty-four shapes. Each has a\ndefault size (technical themes; it scales with the label size), keeps its text inside its outline\nand grows until the text fits, and connectors end on its outline:\n\n| Size | Shapes |\n| --------- | ------------------------------------------------------------------------------------ |\n| 160 × 56 | `rounded` (default), `rectangle`, `pill`, `parallelogram`, `arrow`, `framed`, `flag` |\n| 160 × 64 | `cylinder`, `trapezoid`, `hexagon` |\n| 160 × 72 | `ellipse`, `octagon`, `document`, `callout` |\n| 160 × 80 | `diamond` |\n| 160 × 96 | `triangle`, `pentagon` |\n| 160 × 104 | `person` |\n| 160 × 120 | `agent` |\n| 120 × 120 | `square`, `circle`, `star` |\n| 180 × 100 | `cloud` |\n| 64 × 64 | `icon` (or its `iconSize`), the label outside (below) |\n\n- `square` and `circle` are a rectangle and an ellipse with a square default size; `arrow` points\n right; `framed` has two inner lines (a subroutine); `callout` has a tail at the bottom left.\n- `person` is a round head over a body; `agent` is an AI agent, a robot head (eyes, mouth and an\n antenna) over a body. Both keep the text in the body; an end on the north side meets the head.\n- `\\n` breaks a box's or a node's label into lines, as in a `text`.\n- A `size` too narrow for the text inside a shape is `layout.text-overflow`; use the hint's width.\n- A pinned end (`route r from a.east to d.north 30%`) is drawn where the side's normal meets the\n outline, so arrows touch diamonds, ellipses and stars.\n- `radius 0..64` sets the corner radius of boxes, nodes, notes and groups (`radius 0` squares\n them); `rectangle`, `square` and `framed` are always square, the other shapes ignore it. The\n theme's `radius` (8) and `groupRadius` (14) are the defaults.\n- Decisions, data stores, notes, tags, groups, texts, icons and images refuse `shape`, in `style`\n statements as in rules: their kind is their drawing. Only `rule box` and `rule node` may set it.\n\nText in every profile: `font \"<Family>\"`, `fontSize 6..160` and `fontWeight 400|500|600|700` on\nwhatever draws text (text defaults to 1.6 × the label size, stickies to 1.2 × at 400). Free-only\ntext properties (refused in flow diagrams):\n\n- `textAlign left|center|right` on boxes, stickies and text (text is left aligned by default);\n- `verticalAlign top|middle|bottom` on boxes (`middle` by default) moves the label, description\n and icon to the top or bottom of the shape's text band, the theme's padding from its edge:\n `style card { shape rectangle; textAlign left; verticalAlign top }` is draw.io's top-left text.\n Ellipses and other narrowing shapes move a wide block back towards the middle until it fits;\n cylinders keep it between the rims, documents above the wave, callouts above the tail. On\n `triangle`, `pentagon`, `star`, `person`, `agent` and `icon` shapes, with `iconPosition center`,\n and on texts, icons, images, groups and lines it moves nothing (`layout.vertical-align-ignored`);\n- `opacity 0..1` fades an element, a group, a line or a pen (`style draft { opacity 0.5 }`);\n relations refuse it;\n- a text, icon or image with `fill`, `stroke` or `pattern` gets a frame.\n\n## Lines\n\n```text\nline divider \"Phase 2\" from (40, 160) to (520, 160) // a labelled divider\nline bracket from (40, 220) to (520, 280) via [(280, 220)] // bends in a via list\ngroup notes \"Notes\" {\n text remark \"Read first\"\n line underline from (0, 22) to (120, 22) // in the group's interior\n}\nstyle divider { line dashed; stroke muted }\nstyle bracket { routing orthogonal; corners rounded; arrowhead triangle }\n```\n\n- A `line` joins nothing: use it for dividers, brackets, underlines and strokes; between two\n boxes write a relation (`a -- b`) so it follows them.\n- Its points are written in the statement, in the parent group's interior like `place`; it takes\n no `place`, `size` or `rotation` (`prop.invalid-value`).\n- It takes a relation's styles: `stroke`, `width`, `line`, `arrowhead` and `arrowtail` (none by\n default), `routing` (`polyline` by default, `orthogonal`, `bezier`), `corners`, and `color`,\n `fill`, `icon` for its label pill; a box's properties (`shape`, `radius`, the text properties)\n are `prop.invalid-value`. `rule line { }` styles every line.\n- The label is the optional second argument, on a pill at 50 %;\n `label divider at 20% offset (0, -14)` in `placement` moves it. `flow`, `dash`, `pulse` and\n `trace` run along a line.\n- A line whose points coincide is drawn as a dot: `layout.degenerate-line`. Flow, sequence and C4\n diagrams refuse `line` (`prop.unknown`).\n\n## Pen strokes\n\n```text\npen marker [(40, 70), (280, 70)] // declared first: under the text\ntext heading \"Why the cache helps\"\npen arrow [(216, 140), (250, 128.5), (290, 130), (336, 140)]\npen dot [(400, 60)] // one point is a dot\nstyle marker { stroke highlight; width 20; opacity 0.35 } // a highlighter mark\nstyle arrow { width 4; arrowhead triangle }\n```\n\n- A freehand stroke: one smooth path through the midpoints of its points (round caps and joins).\n Use it for handwriting, drawn arrows, circles and underlines; use a `line` for a straight\n divider and a relation between two boxes.\n- `pen <id> [(x, y), ...]`: at least one tuple of plain numbers, decimals kept, in the parent\n group's interior like `place`; no label, no `place`, `size` or `rotation`\n (`prop.invalid-value`). `pen p [10, 20]`, `pen p []` and `pen p` are `prop.invalid-value` with\n the form `pen <id> [(x, y), (x, y), ...]` in the hint.\n- Styles: `stroke` (the theme's `ink`), `width` 1..64 (3; `width 0` is refused), `line`,\n `opacity`, `arrowhead`, `arrowtail` (none). Anything else (`fill`, `shape`, `routing`, text\n properties) is `prop.invalid-value`. `rule pen { }` styles every pen.\n- The highlighter is `stroke highlight; width 20; opacity 0.35`; declare it before the text it\n marks so the text is painted over it.\n- Pens take no part in `layout.overlap` or the label checks, are never moved by the engine or a\n list, are not jittered by sketch themes, and run `flow`, `dash`, `pulse` and `trace` like a line.\n A story's `draw a, b over 2s` replays them ([stories.md](stories.md)).\n- `pnpm mdg format` prints a long point list filled to 100 columns, not one point per line.\n\n## Icons in boxes and as shapes\n\nFlow diagrams take these too. The `icon` of a node, decision, data store or box goes beside the\ntext (`iconPosition left`, the default, or `right`), above or below it (`top`, `bottom`), or at the\ncentre as the picture of the box (`center`), with the label in a band at the `labelPosition` edge\ninside (`bottom` by default). `shape icon` draws the element as its icon alone, with the label\noutside at `labelPosition`, as provider icons are drawn in architecture diagrams:\n\n```text\nbox gateway \"API Gateway\"\nbox fn \"Checkout\"\nbox orders \"Orders\"\nbox tile \"Orders DB\"\ngateway -> fn\nfn -> orders\n\nstyle gateway { icon \"aws:api-gateway\"; shape icon } // label below the icon\nstyle fn { icon \"aws:lambda\"; shape icon; labelPosition top } // label above\nstyle orders { icon \"aws:dynamodb\"; shape icon; fill surface; stroke line } // framed\nstyle tile { icon \"tabler:database\"; iconPosition center } // 120 × 120 tile\n```\n\n- `iconSize` is the icon's side: 8 to 128 (px or unitless) or `auto`. Beside the text the theme's\n 18 px is the default; a number grows a box without `size`, and is clamped (never cut) in a box\n with a written `size`, where `auto` fills the room. A centred icon is as large as fits; a\n written `size` without room for an 8 px icon beside the label band is `layout.text-overflow`.\n- An icon shape is a 64 × 64 square (or `iconSize`; a written `size` wins, the icon fitted\n inside), with nothing behind the icon unless `fill`, `stroke` or `pattern` frames it; a frame\n adds half the padding on each side (an 80 × 80 square around a 64 px icon). Arrows, ports and\n anchors end on the square (`to fn.south` is the icon's bottom edge); groups and the canvas\n count the label too, and a box over the label is `layout.overlap`, so leave room for it. A\n connector on the label's side is drawn from beyond the label; other routes go around it.\n- `labelPosition` does nothing unless the icon is the centre piece: `layout.label-position-ignored`.\n `shape icon` without an `icon` is `layout.icon-missing` and draws a dashed placeholder.\n- A free `icon <id> \"pack:name\"` object is an icon without text; for a labelled icon use a box\n with `shape icon`.\n\n## Coordinates\n\n- `place` is the centre, as in flow diagrams.\n- **Inside a group, `place` is relative to the group's interior**: its top-left corner plus\n `groupPadding` (16) across and the header down: `groupHeader` (40) in the technical themes, or\n `groupPadding` (16) for an untitled group (`\"\"`, no description, no icon). A child at\n `(w/2, h/2)` touches the interior's top-left corner. Moving the group moves its children.\n- Every group needs a `place`. Without `size` it fits its children: padding + rightmost child edge\n - padding wide, header + lowest child edge + padding tall.\n- Route waypoints are always diagram coordinates.\n\n## Containers, stacks and bands\n\nThese are the pictures of a visual editor's containers and backdrops; flow diagrams take them too.\n\n```text\ngroup outer \"\" { // nested plain rectangles: untitled groups\n group inner \"\" {\n box core \"Core\"\n }\n}\nbox plate \"\" // a stack: the outer box first, empty label\nbox card \"Card\"\ngroup band \"\" { layer back } // a band behind arranged boxes (layers back, main)\n\nstyle outer { fill \"#dae8fc\"; stroke \"#6c8ebf\"; radius 0 }\nstyle inner { fill \"#fff2cc\"; stroke \"#d6b656\"; radius 0 }\nstyle band { fill \"#f5f5f5\"; radius 0 }\n```\n\n- **Untitled groups** draw only their outline, have no title band and cut no gap in connectors;\n children keep half the padding (8 px) from every edge (`layout.container-margin`).\n- **Stacks**: a box lying strictly inside a box declared before it on the same layer is not\n `layout.overlap`; a partial overlap still is, so are two boxes that coincide, and so is a stack\n declared inner first (its hint says to declare the outer box first). A\n container's own label may lie over its children, but two labels at the same point are\n `layout.label-overlap`: leave the outer labels empty.\n- **Bands**: a group with `place` and `size` is neither arranged by the engine nor an obstacle, so\n on a back layer it stays behind the boxes `layout assisted` arranges (pin one box with `place`\n so the others arrange around it). Boxes and groups on different layers are not checked against\n each other, and connectors cross them straight. In `layout auto` a group's `place` is ignored:\n make the band a group holding its boxes.\n\n## Lists and kanban boards\n\n```text\ndiagram board: free {\n preset board\n group kanban \"\" {\n layout row // the columns side by side\n spacing 24\n align stretch // every column as tall as the tallest\n group todo \"To do\" {\n layout column // the cards top to bottom, in source order\n spacing 12\n sticky cache \"Cache the catalogue\"\n sticky retry \"Retry payments once\"\n }\n group done \"Done\" {\n layout column\n sticky login \"Sign in with passkeys\"\n }\n }\n placement {\n place kanban at (360, 300) // only the outer list needs a place\n }\n}\n```\n\n- `layout column|row` in a free group block makes the group a list: its elements and groups go one\n after the other in source order from the interior's corner, `spacing <n>` apart (0..400; half\n `groupPadding`, 8, by default). To reorder cards, reorder their declarations.\n- `align start|center|end|stretch` places children across the axis (`start` by default);\n `stretch` gives a child without a written `size` the interior's full width (column) or height\n (row).\n- Children keep their size; the list is derived from them, and a written `size` on the list is\n only its least size. A list inside a list needs no `place`.\n- A `place` on a child of a list is `layout.place-ignored` (warning): remove it. Lines and pens in a\n list keep their written points. A group that is not a list, inside a list, still places its own\n children with `place`.\n- The engine treats a list as one box in every mode; `pnpm mdg layout` writes a `place` for it and\n nothing for its children.\n- `spacing` or `align` without `layout` is `prop.invalid-value` (add `layout column`); `layout grid`\n lists `column, row`; `layout auto` belongs to the diagram, not to a group. Flow diagrams refuse\n the three.\n\n## Layers, order and links\n\n- `layers back, main, front` lists layers back to front; `main` is the default and comes last\n when unlisted. Put `layer front` in an object's or relation's block.\n- Within a layer, groups paint first, then objects (lines included) in source order, then\n relations: declare what must be on top later.\n- `link checkout.api` in a block records that the object stands for element `api` of `diagram\ncheckout` (same file), `link co.api` through `import checkout as co from \"...\"`, or `link\nviews.checkout.api` through `import \"...\" as views`. Identity only; nothing is kept in step.\n\n## From a flow diagram\n\n`pnpm mdg convert sheet.meltemi --to free [--diagram <id>] [--id <new>]` adds a free copy of the\nflow diagram as drawn: every box with `place` and `size`, children inside their copied groups,\nlayers, routes, labels, styles and animations, a `link` from each object to its source, and\nclasses `from_decision`, `from_data`, `from_tag` for the drawing of the flow kinds; notes stay notes,\nwith their `on` clause.\nEdit the copy freely; the flow diagram is unchanged.\n\n## Diagnostics\n\n| Code | Fix |\n| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `ref.unknown-layer` | add the layer to `layers` (the hint gives the statement) or fix its name |\n| `ref.unknown-link` | the diagram or element does not exist; fix the name or remove the `link` |\n| `asset.outside-project` | image paths are relative, use `/`, no URLs, and stay inside the project |\n| `asset.unknown-image` | the file does not exist next to the path written |\n| `asset.unsupported-image` | not a PNG, JPEG, GIF, WebP or SVG image, broken, or over 8 MB |\n| `layout.image-unavailable` | the host could not read the image; a placeholder is drawn |\n| `layout.missing-placement` | an object or a group has no `place` (children of a list need none; a group that is not a list, inside a list, places its own children) |\n| `layout.place-ignored` | a child of a list (`layout column\\|row`) has a `place`, which the list overrides: remove the `place`, or the group's `layout` |\n| `layout.text-overflow` | a `size` too narrow for a box's text, or a sticky whose text does not fit even at 8 px: shorten the text or use the size in the hint |\n| `layout.too-large` | the content exceeds `preset document` or `preset slide`: split it into views, or write `preset board` for a whiteboard |\n| `layout.overlap` | boxes overlap partly, or a stack is declared inner first: declare the outer box first |\n| `layout.icon-missing` | `shape icon` without an `icon` style: add `icon \"pack:name\"` or choose another shape |\n| `layout.label-position-ignored` | `labelPosition` only moves the label of `iconPosition center` and `shape icon` elements |\n| `layout.vertical-align-ignored` | `verticalAlign` moves nothing on this shape or kind: choose a shape with a text band (`rectangle`, `ellipse`, `cylinder`), set `labelPosition` with a centred icon, or remove it |\n| `layout.degenerate-line` | a line's points coincide: move an end or add a bend with `via` |\n| `prop.invalid-value` | `textAlign`, `verticalAlign` and `opacity` are free-only; `font`, `fontSize` and `fontWeight` are refused on icons, images and pens; `shape` is for `node` and `box` only; a line or a pen takes no `place`, `size` or `rotation`; a pen needs `[(x, y), ...]` and `width` 1..64; a sticky needs its text; `spacing` and `align` need `layout column\\|row`; `opacity` is refused on relations |\n",
9
- stories: "# Stories\n\nA `story` tells a diagram step by step for a walkthrough, a talk or a recorded demo. It never\nchanges the diagram: scenes reveal, hide, highlight, focus, frame, trace and draw parts of it on one\ndeterministic clock, and may switch to another view of the same system. Write the diagram first,\nthen the story below it (or in another file that imports the diagram).\n\n```text\nstory purchase for checkout {\n title \"A purchase\"\n\n scene overview {\n reveal client, api, orders, db over 800ms\n hold 1s\n }\n\n scene processing {\n trace request over 1200ms\n parallel {\n trace save over 1200ms\n highlight db over 1200ms\n }\n hold 2s\n }\n}\n```\n\n## Vocabulary\n\n| Statement | Default | Meaning |\n| ------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |\n| `scene <id> [\"Title\"] { ... }` | | a step; scenes run one after the other |\n| `view <diagram>` | | first in a scene: the diagram it shows from now on |\n| `transition cut\\|fade\\|morph [over <time>]` | 800 ms | needed when the view changes; `morph` moves boxes with the same id, `cut` takes 0 |\n| `reveal a, b [over <time>]` | 600 ms | fades in; targets first revealed start hidden |\n| `hide a, b [over <time>]` | 600 ms | fades out |\n| `highlight a [over <time>]` | 1 s | accent outline for the action's time |\n| `focus a, b` / `focus all` | 600 ms | dims the rest to 25 % until the end of the scene; `all` clears it |\n| `camera a, b` / `camera all` | 800 ms | frames the targets plus 40 px; `all` frames the whole view |\n| `trace r [over <time>]` | 1.2 s | draws one named relation from source to target in the accent colour |\n| `draw a, b [over <time>]` | 800 ms | replays pens, free lines and named relations as drawn, one after another, and keeps them; targets first drawn start hidden |\n| `hold <time>` | | waits |\n| `parallel { ... }` | | actions that start together; lasts as long as the longest |\n\nTargets are ids of the scene's view: elements, named relations (`as <id>`), named notes and\nfragments; entity paths (`shop.api`) in C4 views. Times are `800ms` or `1.5s`, up to `600s`.\n\n## Rules that save iterations\n\n- Name every relation you want to trace: `api -> db: \"SQL\" as save`.\n- A whiteboard's explanation is a `draw` of its pens in the order they were written\n (`draw title, arrow over 2s`): each takes a share of the time proportional to its length, in its\n own colour, and stays drawn ([free.md](free.md#pen-strokes)).\n- Reveal everything that should appear; anything never revealed is visible from the start. An\n arrow appears with its two ends, so reveal the boxes, not the relations.\n- In a gantt chart ([gantt.md](gantt.md)) the targets are sections, tasks, milestones and markers:\n `reveal` a section to show its band and rows, `draw a, b` to grow task bars from their start, and\n `trace x` to light the arrows of the chain that drives a task or milestone that follows others;\n `draw` of anything but a task, or `trace` of a task without arrows, is `story.invalid-target`.\n- Two actions on the same target and channel must not overlap (`story.conflict`): put a `reveal`\n and a `hide` of the same box in sequence, not in one `parallel`.\n- A change of `view` needs a `transition` (`story.missing-transition`); use `morph` between views\n that share ids (two C4 views of one model), `fade` otherwise.\n- Keep scenes short (a few seconds) and end the story with a `hold` so the last state stays.\n\n## Diagnostics\n\n| Code | Fix |\n| -------------------------- | ----------------------------------------------------------------------------- |\n| `story.unknown-diagram` | the diagram after `for` or `view` is not in the file or imported |\n| `ref.unknown-element` | the target is not an id of the scene's view; use the suggested id |\n| `story.invalid-target` | `trace` needs a named relation; `draw` a pen, a free line or a named relation |\n| `story.missing-transition` | add `transition cut`, `fade` or `morph` after `view` |\n| `story.conflict` | two overlapping actions on one target and channel; sequence them |\n| `story.empty-scene` | warning: give the scene an action or remove it |\n| `prop.invalid-value` | a time without `ms` or `s`, beyond 600 s, or a statement out of place |\n\n## Checking a story\n\n```bash\npnpm mdg validate path/to/sheet.meltemi\n```\n\n```bash\npnpm mdg export path/to/sheet.meltemi --story purchase --at 2.4s\n```\n\n`--story` writes `<stem>.<story>.svg`: the end of the story, or the frame at `--at`. Export a few\ninstants (the start of each scene, the middle of a trace) and look at them; the canvas in VS Code\nplays the story with a timeline.\n\nTo share the story, write its HTML player, an offline page with pause, progress, scenes, reduced\nmotion, a static view, a text summary, zoom, hover cards and a detail panel (`--embed` writes a\nfragment for an existing page):\n\n```bash\npnpm mdg export path/to/sheet.meltemi --story purchase --format html\n```\n",
9
+ stories: "# Stories\n\nA `story` tells a diagram step by step for a walkthrough, a talk or a recorded demo. It never\nchanges the diagram: scenes reveal, hide, highlight, focus, frame, trace and draw parts of it on one\ndeterministic clock, and may switch to another view of the same system. Write the diagram first,\nthen the story below it (or in another file that imports the diagram).\n\n```text\nstory purchase for checkout {\n title \"A purchase\"\n\n scene overview {\n reveal client, api, orders, db over 800ms\n hold 1s\n }\n\n scene processing {\n trace request over 1200ms\n parallel {\n trace save over 1200ms\n highlight db over 1200ms\n }\n hold 2s\n }\n}\n```\n\n## Vocabulary\n\n| Statement | Default | Meaning |\n| ------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |\n| `scene <id> [\"Title\"] { ... }` | | a step; scenes run one after the other |\n| `view <diagram>` | | first in a scene: the diagram it shows from now on |\n| `transition cut\\|fade\\|morph [over <time>]` | 800 ms | needed when the view changes; `morph` moves boxes with the same id, `cut` takes 0 |\n| `reveal a, b [over <time>]` | 600 ms | fades in; targets first revealed start hidden |\n| `hide a, b [over <time>]` | 600 ms | fades out |\n| `highlight a [over <time>]` | 1 s | accent outline for the action's time |\n| `focus a, b` / `focus all` | 600 ms | dims the rest to 25 % until the end of the scene; `all` clears it |\n| `camera a, b` / `camera all` | 800 ms | frames the targets plus 40 px; `all` frames the whole view |\n| `trace r [over <time>]` | 1.2 s | draws one named relation from source to target in the accent colour |\n| `draw a, b [over <time>]` | 800 ms | replays pens, free lines and named relations as drawn, one after another, and keeps them; targets first drawn start hidden |\n| `hold <time>` | | waits |\n| `parallel { ... }` | | actions that start together; lasts as long as the longest |\n\nTargets are ids of the scene's view: elements, named relations (`as <id>`), named notes and\nfragments; entity paths (`shop.api`) in C4 views. Times are `800ms` or `1.5s`, up to `600s`.\n\n## Rules that save iterations\n\n- Name every relation you want to trace: `api -> db: \"SQL\" as save`.\n- A whiteboard's explanation is a `draw` of its pens in the order they were written\n (`draw title, arrow over 2s`): each takes a share of the time proportional to its length, in its\n own colour, and stays drawn ([free.md](free.md#pen-strokes)).\n- Reveal everything that should appear; anything never revealed is visible from the start. An\n arrow appears with its two ends, so reveal the boxes, not the relations.\n- In a gantt chart ([gantt.md](gantt.md)) the targets are sections, tasks, milestones and markers:\n `reveal` a section to show its band and rows, `draw a, b` to grow task bars from their start, and\n `trace x` to light the arrows of the chain that drives a task or milestone that follows others;\n `draw` of anything but a task, or `trace` of a task without arrows, is `story.invalid-target`.\n- Two actions on the same target and channel must not overlap (`story.conflict`): put a `reveal`\n and a `hide` of the same box in sequence, not in one `parallel`.\n- A change of `view` needs a `transition` (`story.missing-transition`); use `morph` between views\n that share ids (two C4 views of one model), `fade` otherwise.\n- Keep scenes short (a few seconds) and end the story with a `hold` so the last state stays.\n\n## Diagnostics\n\n| Code | Fix |\n| -------------------------- | ----------------------------------------------------------------------------- |\n| `story.unknown-diagram` | the diagram after `for` or `view` is not in the file or imported |\n| `ref.unknown-element` | the target is not an id of the scene's view; use the suggested id |\n| `story.invalid-target` | `trace` needs a named relation; `draw` a pen, a free line or a named relation |\n| `story.missing-transition` | add `transition cut`, `fade` or `morph` after `view` |\n| `story.conflict` | two overlapping actions on one target and channel; sequence them |\n| `story.empty-scene` | warning: give the scene an action or remove it |\n| `prop.invalid-value` | a time without `ms` or `s`, beyond 600 s, or a statement out of place |\n\n## Authoring and revising with an agent\n\n1. Read the current file and its imported diagrams. Inventory diagram ids, existing story ids,\n scene ids, named relations and export profiles before choosing targets. A new story uses its\n own stable id; do not replace an existing story unless the person requested it.\n2. Write a small `story` block with named scenes, titles and explicit times. Add it alongside\n the diagram, preserving comments, formatting, other stories and exports. A story in a separate\n file imports the diagram: `import checkout from \"./checkout.meltemi\"`.\n3. Validate the whole project after each logical edit, including edits to shared diagrams or\n imported views. A valid story alone does not prove that an export in another file still works.\n Fix errors and relevant warnings before presenting the result.\n4. With MCP, call `inspect_story` with the project, file path and story id. It returns the\n compiled timeline: total `durationMs`, ordered scenes, resolved `view` identities,\n `startMs`/`endMs`/`durationMs`, transitions and nested actions. Action `path` starts with the\n scene index and then its nested action indexes. All times are absolute milliseconds on the\n story clock; omitted source times already have the language defaults applied.\n5. Preview the start and `stillAtMs` of every scene, plus the middle of important actions. The\n exact end of a scene is the start of the next, which may switch view or reset scene effects;\n `stillAtMs` gives its final state just before that boundary (or the exact end of the last).\n Inspect the pictures, not only the JSON. Each inspection and preview reads its own snapshot:\n compare their `revision` values and re-inspect if another edit arrived. These calls do not lock\n a revision or request a historical preview.\n6. To adjust a scene's length, edit its action durations or its trailing `hold`, then inspect\n again. Sequential actions add; `parallel` lasts as long as its longest child; a scene includes\n its transition. Do not scale every action just to add a pause. When reordering scenes, check\n each active view and its required transition again: a preceding view may have changed.\n7. To delete a story, remove only that story block. Find exports `for <story-id>` across the\n project first; report them and remove or retarget those dependencies only within the person's\n requested scope. Keep unrelated stories, scenes and diagrams intact. Validate the whole\n project again and inspect the surviving story when relevant.\n\nFor account projects, every write uses `read_files`' current `revision` as `ifRevision` and a\nfresh idempotency key per logical change. A `revision.mismatch` requires another read and a\nminimal reapplication on the person's latest text, preserving their comments and edits. Never\nretry an old whole-file replacement over newer source. See [mcp.md](mcp.md#story-timelines).\n\nWith `mdg mcp --folder <dir>`, the same `inspect_story` reads files from disk without an account.\nIts content-derived `revision` identifies a folder snapshot; it is not a cloud write revision.\nUse your file tools for small source edits and re-inspect after any disk change. Without MCP,\nvalidate through the CLI and export a few known scene/action instants as below; do not claim to\nhave inspected a compiled timeline through a tool that is unavailable.\n\n## Checking a story\n\n```bash\npnpm mdg validate path/to/sheet.meltemi\n```\n\n```bash\npnpm mdg export path/to/sheet.meltemi --story purchase --at 2.4s\n```\n\n`--story` writes `<stem>.<story>.svg`: the end of the story, or the frame at `--at`. Export a few\ninstants (the start of each scene, the middle of a trace) and look at them; the canvas in VS Code\nplays the story with a timeline.\n\nTo share the story, write its HTML player, an offline page with pause, progress, scenes, reduced\nmotion, a static view, a text summary, zoom, hover cards and a detail panel (`--embed` writes a\nfragment for an existing page):\n\n```bash\npnpm mdg export path/to/sheet.meltemi --story purchase --format html\n```\n",
10
10
  };
11
11
  //# sourceMappingURL=guide.js.map
package/dist/guide.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"guide.js","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,QAAQ,EAAE,86yBAA86yB;IACx7yB,QAAQ,EAAE,wjOAAwjO;IAClkO,KAAK,EAAE,qhPAAqhP;IAC5hP,EAAE,EAAE,+gJAA+gJ;IACnhJ,IAAI,EAAE,kk2BAAkk2B;IACxk2B,OAAO,EAAE,m7MAAm7M;CAC77M,CAAC"}
1
+ {"version":3,"file":"guide.js","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAAA,wFAAwF;AAExF,2DAA2D;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAqC;IAC3D,QAAQ,EAAE,86yBAA86yB;IACx7yB,QAAQ,EAAE,wjOAAwjO;IAClkO,KAAK,EAAE,qhPAAqhP;IAC5hP,EAAE,EAAE,+gJAA+gJ;IACnhJ,IAAI,EAAE,kk2BAAkk2B;IACxk2B,OAAO,EAAE,uwTAAuwT;CACjxT,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meltemi/diagrams-assist",
3
- "version": "1.11.34",
3
+ "version": "1.11.36",
4
4
  "description": "Optional AI assistance for Meltemi sources: model adapters, reviewable proposals against a known revision, partial acceptance.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -26,17 +26,17 @@
26
26
  "dist"
27
27
  ],
28
28
  "dependencies": {
29
- "@meltemi/diagrams-i18n": "1.11.34",
30
- "@meltemi/diagrams-language": "1.11.34",
31
- "@meltemi/diagrams-model": "1.11.34"
29
+ "@meltemi/diagrams-model": "1.11.36",
30
+ "@meltemi/diagrams-language": "1.11.36",
31
+ "@meltemi/diagrams-i18n": "1.11.36"
32
32
  },
33
33
  "publishConfig": {
34
34
  "access": "public"
35
35
  },
36
36
  "meltemiRelease": {
37
37
  "repository": "askenaz-dev/meltemi-diagrams",
38
- "sha": "819e6698eb88ab09a5d3f3520df1d8d865ab0ccb",
39
- "tag": "v1.11.34"
38
+ "sha": "ccb070df86aee9bdf82359d08eeab0b391feff49",
39
+ "tag": "v1.11.36"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.build.json",