explanatory-animation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

explanatory-animation

解释性动画

One file says what is being explained; the tool draws it, and then checks that the picture says what the file claims. The writer's job is the scene and the captions. The tool's job is layout, motion, and telling the writer where the picture lies.
json
{ "format": "vlmkit-anim/scene@1", "kind": "sort", "algorithm": "bubble", "values": [5, 3, 8, 1] }
Two layers: a Scene (
kind
+ intent —
"algorithm": "bubble"
,
"trace": ["connect", "SYN+ACK"]
,
"deps": [["web", "api"]]
, never x / y) compiles to a Timeline (nodes, keyframe tracks, captioned steps). Write the scene; read the timeline only through the verbs below.
When the task is to answer a question with a figure — "how does this work", "how is this structured", "what does this PR change" —
explain-with-anim
decides what to draw, from what, and how the prose follows it; this skill is how the scene itself is written and checked.
The one page to read before writing is
docs/anim-ir.md
— shipped in the package (
node_modules/@mizchi/vlmkit-anim/docs/anim-ir.md
; in this repository
packages/vlmkit-anim/docs/anim-ir.md
) — every kind, its ops, the annotation ops every kind shares, and one JSON example per kind that
check
passes.
vlmkit-anim schema --kind <k>
prints one kind's section. Do not learn the format from the compiler source.
一个文件说明要解释的内容;工具负责绘制,然后检查图片是否表达了文件中的声明。编写者负责场景和字幕,工具负责布局、动效,并告诉编写者图片在哪些地方与声明不符。
json
{ "format": "vlmkit-anim/scene@1", "kind": "sort", "algorithm": "bubble", "values": [5, 3, 8, 1] }
这里分为两层:Scene(
kind
+ 意图——例如
"algorithm": "bubble"
、
"trace": ["connect", "SYN+ACK"]
、
"deps": [["web", "api"]]
,绝不使用 x / y)会编译为 Timeline(节点、关键帧轨道、带字幕的步骤)。编写场景;只能通过以下命令读取 Timeline。
当任务需要用图回答问题——例如“它如何工作”“它如何组织”“这个 PR 改了什么”——
explain-with-anim
会决定画什么、依据什么来画,以及后续文字如何配合;本 skill 负责场景本身的编写与检查。
动手编写前必读的一页是
docs/anim-ir.md
——该文件随包发布(
node_modules/@mizchi/vlmkit-anim/docs/anim-ir.md
;在当前仓库中位于
packages/vlmkit-anim/docs/anim-ir.md
)——其中包含每一种 kind、每种 kind 的操作、所有 kind 共用的标注操作,以及每种 kind 都有一个能通过
check
的 JSON 示例。
vlmkit-anim schema --kind <k>
会打印指定 kind 的章节。不要通过阅读编译器源码来学习格式。

Invocation

调用方式

vlmkit-anim
is a standalone binary, not a
vlmkit
subcommand.
bash
undefined
vlmkit-anim
是一个独立二进制工具,不是
vlmkit
的子命令。
bash
undefined

mizchi/explainer, where the package lives

mizchi/explainer, where the package lives

node --experimental-strip-types packages/vlmkit-anim/src/cli.ts check scene.json # from source, no build
node --experimental-strip-types packages/vlmkit-anim/src/cli.ts check scene.json # from source, no build

any other repository

any other repository

npx -p @mizchi/vlmkit-anim vlmkit-anim check scene.json # or add @mizchi/vlmkit-anim as a dev dependency

Nothing below needs a browser or an API key except: `.png` output, `sheet`,
`video`, `eval` (Playwright), and `review --model` (a vision model through
`@mizchi/vlmkit-ai`). Writing and checking a scene is browser-free.
npx -p @mizchi/vlmkit-anim vlmkit-anim check scene.json # or add @mizchi/vlmkit-anim as a dev dependency

除以下功能外,下面的操作都不需要浏览器或 API 密钥:`.png` 输出、`sheet`、`video`(Playwright)以及 `review --model`(通过 `@mizchi/vlmkit-ai` 调用视觉模型)。编写和检查场景无需浏览器。

Route by task

按任务选择路线

Task shapeDo this
"Animate / show step by step how X works" (a sort, search, BST, heap, DP table, graph walk, state machine, message exchange, flowchart, gantt)Pick the
kind
whose section in the guide names X; write the scene; run the loop below. Nineteen kinds: sort, array, stack, queue, list, tree, state-machine, heap, distributed, matrix, graph, chart, flowchart, gantt, sequence, diagram, modules, vector, compose.
"Explain a concept" that no kind namesChoose the kind whose things the concept has (nodes exchanging messages →
distributed
; a table filling in →
matrix
); say the rest with annotation ops (
value
,
callout
,
snapshot
,
group
,
text
,
relate
) that name the kind's things. Two pictures at once →
kind: compose
. Coordinates are the last resort, and count against the scene.
"Draw a module / dependency / architecture map"
kind: modules
with
modules
,
deps
(
["a", "b"]
reads "a depends on b"),
groups
, optional
parent
on a group;
still
renders it. When the code exists, first
vlmkit-anim facts <dir> --depth 1 --out f.expect.json
, then
check --expect
the map against it.
"Draw this repository"
vlmkit-anim repo --out docs/diagrams --name <name>
— the workspace layer by layer, a GIF, a contact sheet, a Markdown page and its own fact sheet.
"What does this branch change?"
vlmkit-anim pr --base origin/main --out .vlmkit-anim/pr
— one beat per commit;
<name>.md
is paste-ready.
"Show what changed between two maps"
vlmkit-anim diff before.json after.json --out change.svg [--expect diff.json]
— added in accent, removed dashed grey, a legend;
--expect
checks the change against a diff sheet.
"We already have a mermaid diagram"
vlmkit-anim import mermaid page.md --out scene.json
(flowchart / graph, sequenceDiagram, stateDiagram-v2). Read its
dropped / changed:
and
notes:
lines; add what the import cannot know (a title, captions, a walk or trace).
"Put it in the docs"
html --out page.html
(runtime inline),
video --out demo.gif
for a README, or the remark plugin
@mizchi/vlmkit-anim/remark
so a
```vlm-anim
fence in Markdown becomes the animation and
```vlm-anim still
the figure.
"As D2 text" / "show it in the terminal" / an existing
.d2
Not this tool:
d2-diagram
writes the
.d2
, lays it out with TALA and renders it as box drawing in the terminal. Hand it the
facts
sheet so the D2 is drawn from the code, and say that nothing checks it.
任务形式操作
“制作动画/逐步展示 X 的工作方式”(排序、搜索、BST、堆、DP 表、图遍历、状态机、消息交换、流程图、甘特图)在指南中选择明确提到 X 的 kind;编写场景;然后运行下面的循环。共有十九种 kind:sort、array、stack、queue、list、tree、state-machine、heap、distributed、matrix、graph、chart、flowchart、gantt、sequence、diagram、modules、vector、compose。
“解释某种概念”,但没有对应的 kind选择其对象与该概念最相近的 kind(交换消息的节点 →
distributed
;逐渐填满的表格 →
matrix
);通过标注操作(
value
、
callout
、
snapshot
、
group
、
text
、
relate
)说明其余内容,并使用该 kind 所拥有的对象名称。同时展示两张图 →
kind: compose
。坐标是最后手段,而且会计入场景评分。
“绘制模块/依赖关系/架构图”使用
kind: modules
,并提供
modules
、
deps
(
["a", "b"]
表示“a 依赖 b”)、
groups
,以及组上可选的
parent
;
still
会渲染该图。代码存在时,先运行
vlmkit-anim facts <dir> --depth 1 --out f.expect.json
,然后使用
check --expect
将地图与事实表进行核对。
“绘制当前仓库”
vlmkit-anim repo --out docs/diagrams --name <name>
——按层展示工作区,并生成 GIF、contact sheet、Markdown 页面及其自身的事实表。
“这个分支改了什么?”
vlmkit-anim pr --base origin/main --out .vlmkit-anim/pr
——每次提交对应一个节拍;
<name>.md
可直接粘贴使用。
“展示两张图之间发生了什么变化”
vlmkit-anim diff before.json after.json --out change.svg [--expect diff.json]
——新增项使用强调色,删除项使用灰色虚线,并附带图例;
--expect
会根据差异表检查变更内容。
“已经有 mermaid 图”
vlmkit-anim import mermaid page.md --out scene.json
(flowchart/graph、sequenceDiagram、stateDiagram-v2)。阅读其中的
dropped / changed:
和
notes:
行;补充导入功能无法推断的内容(标题、字幕、演示过程或 trace)。
“放入文档中”
html --out page.html
(运行时内联)、
video --out demo.gif
(用于 README),或使用 remark 插件
@mizchi/vlmkit-anim/remark
,让 Markdown 中的
```vlm-anim
围栏转换为动画,让
```vlm-anim still
转换为图示。
“输出为 D2 文本”/“在终端中展示”/处理现有
.d2
不使用此工具:
d2-diagram
会编写
.d2
,使用 TALA 对其进行布局,并在终端中以框线图形式渲染。将
facts
事实表交给它,以便根据代码绘制 D2,同时应说明该结果没有检查机制。

The loop

循环

1. write scene.json                                  one kind; ids ASCII, language in `label`
2. vlmkit-anim check scene.json [--expect facts.json] validate → compile → semantic checks → stats; exit 1 on ✗
3. vlmkit-anim explain scene.json                    the narration as a numbered list — is this the story?
4. vlmkit-anim layout scene.json                     texts on texts, under boxes, past the edge, lines through
                                                     labels, containers crossing — per step; exit 1 when any
5. vlmkit-anim why scene.json [--about id]           (modules / diagram) what set each canvas axis, rows vs bands
                                                     and their share, what put each box on its layer, which box
                                                     a bent edge went round — read this BEFORE relabelling
6. vlmkit-anim still scene.json --out fig.svg        the figure  |  html --out page.html  |  video --out demo.gif
7. vlmkit-anim review scene.json --out dir           optional: a contact sheet + brief for a vision reader;
                                                     --answers scores its JSON against the geometry / the facts
Each ✗ line names a path, what is wrong, and a
→
hint with the fix. Fix the first ✗, re-run; ⚠ lines are advice you act on only when they touch what the picture is for. Budget five rounds; if the fifth is not green, stop and report the lines, not a guess.
1. write scene.json                                  one kind; ids ASCII, language in `label`
2. vlmkit-anim check scene.json [--expect facts.json] validate → compile → semantic checks → stats; exit 1 on ✗
3. vlmkit-anim explain scene.json                    the narration as a numbered list — is this the story?
4. vlmkit-anim layout scene.json                     texts on texts, under boxes, past the edge, lines through
                                                     labels, containers crossing — per step; exit 1 when any
5. vlmkit-anim why scene.json [--about id]           (modules / diagram) what set each canvas axis, rows vs bands
                                                     and their share, what put each box on its layer, which box
                                                     a bent edge went round — read this BEFORE relabelling
6. vlmkit-anim still scene.json --out fig.svg        the figure  |  html --out page.html  |  video --out demo.gif
7. vlmkit-anim review scene.json --out dir           optional: a contact sheet + brief for a vision reader;
                                                     --answers scores its JSON against the geometry / the facts
每个 ✗ 行都会指出路径、问题所在,以及带有修复建议的
→
提示。先修复第一个 ✗,然后重新运行;⚠ 行只是建议,只有当它影响图片的用途时才需要处理。最多安排五轮;如果第五轮仍未通过,请停止并报告相关行,而不是猜测。

Done condition

完成条件

  • check
    exits 0 with no ✗ (and, when a fact sheet exists,
    --expect
    too).
  • layout
    reports no issue on any step.
  • explain
    reads as the explanation you meant — every beat has a caption that says why, not only what moved.
  • For a still: both canvas sides under 2000px (the canvas ⚠ in
    check
    ), and you looked at the SVG once.
  • check
    退出码为 0,且没有 ✗(存在事实表时,
    --expect
    也必须通过)。
  • layout
    报告任何步骤都没有问题。
  • explain
    读起来就是你想表达的讲解——每个节拍都有说明为什么的字幕,而不只是说明什么发生了移动。
  • 对于静态图:画布两侧都小于 2000px(
    check
    中的画布 ⚠),并且你已经亲自查看过一次 SVG。

Reading the kickbacks

读取检查反馈

  • The canvas warning names its cause. "labels stop being legible — A (206px, in G1) and B (53px, in G2) need 142px between their centres … and the layout put them 10% of the width apart", then "N containers sit side by side across the picture (a 40%, b 10%, …), each as wide as its fullest layer's boxes". The lever is the named pair or the banding — flatten or re-nest the containers, break the named label — not the longest label you can see.
    why
    has every layer, band and detour; two writers who read it before their first edit brought an 8882px graph under 2000px.
  • A crossing names the edge by its ends (
    edge-24: diff → capture
    ) and the box it runs through. Move one end to another layer (reorder the list, regroup) or shorten that label.
  • "no sequence" on a
    diagram
    means the picture, not the motion, is the point: switch to
    kind: modules
    . The switch changes layering (a diagram layers one past what points into a box; a module map layers from its leaves), so re-run
    check
    and read the new canvas line.
  • --expect
    lines
    are the facts the picture got wrong: a dependency drawn that the sheet does not list, one listed and not drawn, the wrong edge highlighted. A green
    check
    on a wrong picture is the failure this exists for — the sheet wins over the picture.
  • import mermaid
    dropped / changed:
    names what the IR has no place for (styles, classDefs, clicks,
    direction
    inside a subgraph, composite states). Colour with
    tone
    ; everything else you put back as captions.
  • 画布警告会指出原因。 “标签无法清晰辨认——A (206px, in G1) 与 B (53px, in G2) 的中心之间需要 142px……而布局只把二者放在画布宽度的 10% 处”,接着还有“N 个容器在图中并排分布(a 占 40%,b 占 10%……),每个容器都与其最宽一层的方框一样宽”。调整的切入点是被点名的标签对或分层方式——扁平化或重新嵌套容器,或者拆开被点名的标签——而不是去改你能看到的最长标签。
    why
    会列出每一层、每个 band 和每次绕行;两位编写者在第一次修改前先读了它,把一张 8882px 的图缩小到了 2000px 以内。
  • 交叉线会按两端点名称标识边(
    edge-24: diff → capture
    ),并指出它穿过了哪个方框。将其中一端移到另一层(重排列表、重新分组),或者缩短那个标签。
  • 在
    diagram
    上出现“no sequence”
    意味着重点是图片本身,而不是动效:切换到
    kind: modules
    。切换会改变分层方式(diagram 的分层会依据指向某个方框的对象向后推一层;模块图则从叶子节点开始分层),因此需要重新运行
    check
    并阅读新的画布提示行。
  • --expect
    行
    表示图片画错的事实:图中存在事实表未列出的依赖、事实表列出的依赖没有画出,或者高亮了错误的边。即使
    check
    通过,图片仍然是错的,这种失败正是该工具要发现的问题——事实表优先于图片。
  • import mermaid
    的
    dropped / changed:
    会指出 IR 无法表达的内容(样式、classDefs、点击事件、子图内部的
    direction
    、复合状态)。使用
    tone
    设置颜色;其余内容通过字幕补回。

Rules the checks enforce (do not fight them)

检查所强制执行的规则(不要与之对抗)

  • No coordinates in a scene that has a kind for its things.
    kind: vector
    and hand-written positions are the fallback and are counted as such.
  • Every annotation names an anchor the kind owns (an index, a cell, a node, an edge), and asks for a
    side
    ; the compiler grows the canvas on that side and routes the pointer round labelled boxes. Record asked vs landed if it matters.
  • Labels may be any script; boxes are sized per glyph (CJK is one em). Ids stay ASCII.
  • A dependency cycle in
    modules
    is a warning, drawn — name the cut in a caption or mark one edge
    "style": "forbidden"
    .
  • A scene in a
    ```vlm-anim
    fence is checked the same way; a fence that does not compile renders as a visible
    <pre>
    with the check's lines.
  • 对于已有对应 kind 来表达对象的场景,不允许使用坐标。
    kind: vector
    和手工位置是兜底方案,并且会被计分。
  • 每个标注都必须指定该 kind 所拥有的锚点(索引、单元格、节点或边),并要求一个
    side
    ;编译器会在该侧扩展画布,并让指示线绕过带标签的方框。如果有必要,请记录请求的 side 与实际落点。
  • 标签可以使用任意文字系统;方框大小按字形计算(CJK 占一个 em)。ID 保持为 ASCII。
  • modules
    中存在依赖环时会给出警告,但仍会绘制——请在字幕中说明切断点,或将某条边标记为
    "style": "forbidden"
    。
  • 位于
    ```vlm-anim
    围栏中的场景也会接受相同检查;无法编译的围栏会显示为可见的
    <pre>
    ,并附带检查结果行。

Outputs at a glance

输出一览

FileVerbConsumer
scene.json
(or
scene.ts
exporting
scene.<kind>({…})
)
youthe repo — this is what is edited later
fig.svg
/
fig.png
still
docs, a README, a slide
page.html
html
a browser;
vlmkit check animation page.html
and
vlmkit-anim eval
measure it
demo.gif
/
.mp4
/
.webm
video
a README or PR comment
*.expect.json
facts
,
repo
, by hand
check --expect
; the truth the picture is held to
<name>.sheet.png
,
<name>.review-brief.md
,
<name>.review-score.md
review
a vision model or a second agent, and its score
文件命令使用方
scene.json
(或导出
scene.<kind>({…})
的
scene.ts
)
你仓库——这是后续要编辑的内容
fig.svg
/
fig.png
still
文档、README、幻灯片
page.html
html
浏览器;
vlmkit check animation page.html
和
vlmkit-anim eval
对其进行测量
demo.gif
/
.mp4
/
.webm
video
README 或 PR 评论
*.expect.json
facts
、
repo
、手工创建
check --expect
;用于约束图片的事实依据
<name>.sheet.png
、
<name>.review-brief.md
、
<name>.review-score.md
review
视觉模型或另一位 agent,以及它给出的评分

Failure modes

失败模式

  • .png
    ,
    sheet
    ,
    video --out x.mp4
    ,
    eval
    fail with a browser error → Playwright is missing;
    .svg
    ,
    .gif
    and
    sheet --out sheet.html
    need no browser.
  • In mizchi/explainer the CLI shows old behaviour after editing
    packages/vlmkit-anim/src/
    →
    npm run build
    in
    packages/vlmkit-anim
    (never piped to
    head
    ), or run from source.
  • Every round shortens a label and the canvas does not move → the label was not the binding one; read the canvas line and
    why
    .
  • A
    modules
    map has a dependency the code does not → the sheet from
    facts
    catches it; a map drawn from memory is checked against the code, not the other way round.
  • check
    is green, the figure is wrong → write the fact sheet. That is the whole reason
    --expect
    exists.
  • .png
    、
    sheet
    、
    video --out x.mp4
    、
    eval
    因浏览器错误而失败 → 缺少 Playwright;
    .svg
    、
    .gif
    和
    sheet --out sheet.html
    不需要浏览器。
  • 在 mizchi/explainer 中,编辑
    packages/vlmkit-anim/src/
    后 CLI 仍显示旧行为 → 在
    packages/vlmkit-anim
    中运行
    npm run build
    (绝不要管道给
    head
    ),或者直接从源码运行。
  • 每轮都在缩短标签,但画布毫无变化 → 该标签并不是决定画布尺寸的标签;请阅读画布提示行和
    why
    。
  • modules
    图中包含代码里不存在的依赖 → 由
    facts
    生成的事实表会捕获这个问题;凭记忆绘制的图应与代码进行核对,而不是反过来。
  • check
    已通过,但图片仍然是错的 → 编写事实表。这正是
    --expect
    存在的全部意义。