Motion has one public contract:
generated semantic SVG -> validated animated GIF
PNG and JPEG are not accepted as animation inputs. Animated WebP, MP4, WebM, poster generation, and the old offline motion-review player are not part of this surface. Static SVG/PNG rendering and the single-file interactive HTML exporter remain unchanged.
Use the most recently generated SVG when the user says:
让这张图动起来生成 GIF制作 GIF把刚才的 SVG 转成 GIFGenerate a GIFAnimate this diagramAnimate this SVG as a GIFNo format, preset, duration, or frame-rate wording is needed. The default is a
960px-wide, 5.75-second, 20fps, 115-frame, infinitely looping GIF. auto reads the
style id and explicit data-motion-* edge metadata from the generated SVG.
The input must satisfy one of the twelve approved motion-scene contracts. Exact
source bytes are not pinned, so validated title and content variants of a
supported topology are accepted. The role/stage/order schedule, route direction,
required source colors, and geometry remain fail-closed; auto does not infer
missing metadata or apply reviewed motion to an arbitrary same-style topology.
The only motion media artifact is GIF. Unless --report supplies another path,
the CLI also writes <output>.motion.json with the validation evidence.
Six measured ByteByteGo newsletter GIFs use short 2.10–2.75 second loops at a uniform 20 or 33.33fps. Only 1.20–3.56% of their canvases change over a loop and every measured frame is unique. The default loop extends to 5.75 seconds so the accepted 1.8-second construction leaves frames 38–109 for a clearly readable, continuously moving operating state. This project applies those lessons as a reusable technical-diagram contract:
Styles 1–12 are enabled and their signature, speed, path, geometry, and
construction contracts are user-approved. The shared +2s-settled-flow
timing revision was approved on 2026-07-17, so new default 5.75-second packages
record review_status: user-approved. The explicit 3.75-second and 2.75-second
compatibility timelines remain available when requested.
Style 1 follows eight explicit route roles:
| Frames | Role | Edge meaning |
|---|---|---|
1–8 |
ingress |
user request |
5–12 |
reason |
application to model |
9–16 |
extract |
fact extraction |
13–20 |
transform |
extracted facts |
17–24 |
resolve |
conflict resolution |
21–28 |
memory-write |
durable write |
25–32 |
memory-read |
memory relation/read |
29–36 |
response-context |
context to response |
The connector-draw-on-with-persistent-data-flow primitive transiently hides all immutable
source edges and their route-owned label groups. Each route gets one marker-free
linear draw clone and one settled clone that restores the original marker at
arrival. Its label plate and text appear only with that settled route; label
geometry never moves. The topology is complete by frame 36. From frames 36–114,
every settled route gets an adjacent marker-free, filter-free pair that preserves
the source path direction. The persistent-data-flow-stream body uses memory-cyan
#06b6d4, rounded caps and joins, opacity .90, width
min(4.0px, max(3.0px, source stroke × 1.60)), and dash pattern 16 25. Style 1's
current 2.4px source routes therefore resolve to exactly 3.84px. Its immediately
following persistent-data-flow-head clone stays inside that body with color
#e0f2fe, width 2.20px, opacity .98, rounded caps and joins, and pattern
6 35. Both patterns have a 41-unit period; the head dash offset is always the
body offset minus 10 units, placing the bright six-unit segment over the leading
six units of the cyan body. Neither clone carries a marker, filter, glow, or blur.
Both layers advance together by -6.0 SVG user units per rendered frame toward
the target: 6px/frame or 120px/s at 960px, and 3px/frame or 60px/s at 50% review
scale. Their shared phase is (motionStage × 7 + motionOrder × 3) mod 41; the
request/reason/extract/facts/resolved/write/relate/context phase order is
[7, 14, 21, 28, 31, 35, 1, 8]. Period 41 and step 6 are coprime, so the 39
stream samples do not repeat a phase. Frames 36, 37, and 38 use pair-layer factors
.30, .65, and 1.00; frames 38–109 hold full body/head opacities .90/.98.
Frames 110–114 keep both layers advancing while multiplying settled topology,
labels, body, and head opacity by 1.00, .7575, .515, .2725, and .03.
Sampling uses time × fps − 0.5, so frames 0–35 match the accepted raw Chromium
baseline exactly.
This keeps the reset in motion and leaves frame 74 distinct from the connector-free
frame 0. Runtime geometry sentinels also fail closed unless ingress travels right,
resolve travels left, and memory-write follows down → left → down while the
dash offset remains negative; declaring source/target metadata alone is not enough.
Style 2 selects the tool-grounding scene by SVG style metadata. Its schedule is
keyed by the exact (data-motion-role, data-motion-order) pair, so two grounding
routes remain independently addressable and every expected key must appear exactly
once. The source edge stage and route color are validated before rendering.
| Frames | Stage | Role / order | Evidence transition | Body color |
|---|---|---|---|---|
1–8 |
1 |
ingress / 0 |
query enters the application | #a855f7 |
5–12 |
2 |
delegate / 0 |
application delegates to the model | #a855f7 |
9–16 |
3 |
tool-call / 0 |
model issues the terminal command | #38bdf8 |
13–20 |
4 |
inspect / 0 |
terminal output is inspected | #38bdf8 |
17–24 |
5 |
index / 0 |
inspected evidence enters the index | #22c55e |
21–28 |
6 |
grounding / 0 |
indexed evidence returns to grounding | #fb7185 |
25–32 |
6 |
grounding / 1 |
grounding reaches the answer context | #fb7185 |
29–36 |
7 |
answer / 0 |
grounded answer returns to the user | #f97316 |
After each route settles, it receives one adjacent, marker-free, filter-free pair.
The terminal-evidence-stream body inherits that source route's stroke, uses width
min(3.8px, max(3.0px, source stroke × 1.50)), opacity .94, and dash pattern
15 26. Style 2's 2.3px routes resolve to exactly 3.45px. The immediately following
terminal-command-head is white #f8fafc, 2.0px wide, opacity 1.00, and uses
pattern 5 36; its offset is the body offset minus 10 units. Both advance by
-6.0 SVG user units per rendered frame, equal to 6px/frame at 960px and 3px/frame
at 50% review size. The phase formula is
(motionStage × 6 + motionOrder × 3) mod 41, producing
[6, 12, 18, 24, 30, 36, 39, 1] in schedule order. Period 41 and step 6 are
coprime, so all 39 stream samples remain phase-unique.
All eight directions are runtime sentinels: ingress / 0 right;
delegate / 0 down → left → down; tool-call / 0 right; inspect / 0 down;
index / 0 right → up; grounding / 0 up → left → up; grounding / 1 right;
and answer / 0 right. The body/head pair fades in on frames 36–38, holds full
opacity on frames 38–109, then keeps moving while sharing the five-frame reset.
One scene signature appears over the terminal prompt: terminal-prompt-cursor.
The renderer requires exactly one data-node-id="terminal" node and exactly one
unchanged _ source text within it. A 2.2px-high #a7f3d0 rectangle is derived
from that underscore's runtime getBBox() and placed in a separate signature
layer. It changes opacity only: from frames 16–69, each 16-frame period has eight
bright frames at .95 followed by eight absent frames. Its cadence runs through
reset_start - 1; frames 110–114 multiply a
bright cursor by the shared reset opacity. The source underscore remains visible
and unmutated. Terminal text typing, scan lines, glows, camera motion, and animated
backgrounds are outside this scene contract.
Style 3 selects the service-blueprint scene. SHA-256
b8f55d9ea0c6111176d8ff50d2e844b2001ee5087a3940621e635e1b875d470d
remains the reviewed reference source, not an exact-byte input lock. Its schedule
is keyed by the exact (data-motion-role, data-motion-order) pair.
Every key resolves to one immutable source edge, and every source stage and route
color is validated before rendering.
| Frames | Stage | Role / order | Blueprint transition | Body color |
|---|---|---|---|---|
1–6 |
1 |
ingress / 0 |
client request enters the gateway | #38bdf8 |
4–9 |
2 |
policy / 0 |
gateway checks identity and policy | #67e8f9 |
8–13 |
3 |
fanout / 0 |
gateway opens the Order branch | #38bdf8 |
11–16 |
3 |
fanout / 1 |
gateway opens the Catalog branch | #38bdf8 |
14–19 |
3 |
fanout / 2 |
gateway opens the Billing branch | #38bdf8 |
18–23 |
4 |
data-write / 0 |
Order writes Postgres | #fde047 |
21–26 |
4 |
data-write / 1 |
Catalog writes Redis | #fde047 |
24–29 |
4 |
data-write / 2 |
Billing writes Warehouse | #fde047 |
28–33 |
5 |
event / 0 |
Billing publishes an event | #fb7185 |
31–36 |
6 |
telemetry / 0 |
Event Router emits metrics | #fb7185 |
From frame 36, each settled route receives one marker-free, filter-free
blueprint-distribution-wave body. It inherits the source stroke, uses width
min(3.4px, max(2.8px, source stroke × 1.40)), opacity .92, rounded caps and
joins, and dash pattern 12 31. The reviewed 2.1px routes resolve to exactly
2.94px, or 1.47px at 50% review scale. Dash offset advances by -6.0 SVG units
per rendered frame.
Each body is paired with one blueprint-registration-bead: a circle with radius
3.0px, fill #e0f2fe, source-colored 1.2px stroke, and opacity .98. Its initial
path distance is the route phase. Every rendered frame advances cx and cy by
+6.0 user units through getPointAtLength; the bead wraps from the target end
to the source start and never reverses. Only cx, cy, and opacity change.
The stage-only phase formula is
(motionStage × 7 + motionOrder × 0) mod 43, producing
[7, 14, 21, 21, 21, 28, 28, 28, 35, 42]. All three fan-out routes therefore
share phase 21, and all three equal-length data-write routes share phase 28 and
the same bead Y coordinate throughout the live interval. Period 43 and step 6
are coprime, so the 39 live samples do not repeat a body phase.
The ten runtime direction sentinels require: ingress right; policy right;
fan-out/0 down → left → down; fan-out/1 down; fan-out/2 down → right → down;
all three data writes down; event right; and telemetry down. Body dash offset
must stay negative while bead travel stays positive. Bodies and beads are absent
through frame 35, fade in with .30, .65, and 1.00 factors on frames
36–38, hold full opacity on frames 38–109, then keep advancing through the
five-frame reset. Glow, blur, shadow, scan lines, node/text/camera/background
motion, halo, ripple, and terminal cursors remain outside the Style 3 contract.
Style 4 selects the memory-lifecycle scene. SHA-256
04cf833659e82c3e1743db4042cacf839a6d784a99c32d076e36fd4776e70c1b
remains the reviewed reference source, not an exact-byte input lock. Its exact
(data-motion-role, data-motion-order) schedule allows only one active
connector build:
| Frames | Stage | Role / order | Memory transition | Rail/card color |
|---|---|---|---|---|
1–4 |
1 |
sample / 0 |
sensory input enters working memory | #3b82f6 |
5–8 |
2 |
attend / 0 |
active context reaches the agent | #3b82f6 |
9–12 |
3 |
invoke / 0 |
the agent invokes procedural memory | #7c3aed |
13–22 |
4 |
remember / 0 |
working context enters episodic memory | #059669 |
23–26 |
5 |
consolidate / 0 |
episodes become semantic knowledge | #ea580c |
27–36 |
6 |
recall / 0 |
semantic knowledge returns to the agent | #ea580c |
From frame 36, all six settled paths receive a marker-free, filter-free
notion-memory-rail. Each rail uses destination-memory color, width
min(3.0px, max(2.4px, source stroke × 1.50)), opacity .88, round caps and
joins, and dash pattern 12 35. The reviewed 1.8px paths resolve to exactly
2.70px, or 1.35px at 50% review size. The phase formula
(motionStage × 7 + motionOrder × 0) mod 47 produces
[7, 14, 21, 28, 35, 42]; dash offset advances by -6.0 user units per frame.
Period 47 and step 6 are coprime, so none of the 39 live rail samples repeats.
Each rail is paired with one notion-memory-card group. Its white outer rect is
x=-7, y=-5, 14×10, rx=2, with a 1.4px semantic-color stroke. Two 2px
butt-cap ink lines use shape-rendering="crispEdges" and run from (-4.5,-2)
to (4,-2) and from (-4.5,2) to (0.5,2). The exact normalized starting-progress vector is
[0.08, 0.22, 0.36, 0.50, 0.64, 0.78]; distance is
8 + progress × (pathLength − 16). Cards keep 8px clearance from both endpoints,
advance +6.0 path units per rendered frame, wrap from target clearance to
source clearance, and animate only group transform and opacity.
Direction sentinels require sample, attend, and invoke to point right at 0°;
remember to point down at 90°; consolidate to point right at 0°; and recall
to point up at -90°. Rails and cards are absent through frame 35, fade in with
.30, .65, and 1.00 factors on frames 36–38, hold full opacity on frames
38–109, and keep advancing during the shared five-frame reset. Cards and rails
remain below route labels and nodes. Generic packet heads, circular beads,
terminal cursors, glow, blur, shadow, scan lines, node/text/camera/background
motion, halo, and ripple remain outside the Style 4 contract.
All eight approved style contracts preserve immutable source paths, labels, nodes, containers,
text, and markers. They reuse the connector-free opening, exact semantic draw-on,
frames 36–38 live fade, frames 38–109 operating hold, and moving 110–114
reset. Live rails never exceed their source stroke width or their scene ceiling.
| Style | Preset | Rail | Signature / auxiliary | Travel | Style / timing status |
|---|---|---|---|---|---|
| 5 | agent-orchestration |
glass-handoff-rail |
14×9 glass-task-capsule; coordinator halo |
6px/frame | approved / +2s approved |
| 6 | governed-runtime |
governance-thread |
12×12 policy-seal |
6px/frame | approved / +2s approved |
| 7 | token-stream |
api-token-rail |
three-cell token-train |
6px/frame | approved / +2s approved |
| 8 | golden-circuit |
luxury-circuit-rail |
gem-tracer; only its gem halo is filtered |
6px/frame | approved / +2s approved |
| 9 | review-trace |
review-trace-rail |
review-cursor |
5px/frame | approved / +2s approved |
| 10 | cloud-flow |
cloud-flow-rail |
region chevrons, replication capsule, availability pulses | 6px/frame | approved / +2s approved |
| 11 | event-transit |
event-transit-rail |
event train, exception/projection cars, dwell rings | 5px/frame | approved / +2s approved |
| 12 | ops-pulse |
incident / telemetry rails | ECG/export heads, trace reveals, waterfall-scanner |
5px/frame | approved / +2s approved |
Styles 8, 11, and 12 use (data-motion-role, data-motion-stage,
data-motion-order) because repeated roles must stay independently addressable.
Styles 10–12 add only explicit motion metadata to their source fixtures; stripping
data-motion-role, data-motion-stage, and data-motion-order reproduces the
pre-animation static SVG geometry exactly.
SKILL_ROOT="${CLAUDE_SKILL_DIR:-/absolute/path/from-codex-skill-metadata}"
python3 "$SKILL_ROOT/scripts/fireworks.py" animate diagram.svg diagram.gif
Optional controls remain deliberately small:
python3 "$SKILL_ROOT/scripts/fireworks.py" animate diagram.svg diagram.gif \
--preset auto --duration 5.75 --fps 20 --width 960 \
--report diagram.motion.json
Use --dry-run to validate identity, semantics, geometry, timeline, output path,
and render budget without launching Chrome or writing artifacts. duration × fps
must be a whole number of at least 55 frames. Width × height × frame count may
not exceed 600 million rendered pixels.
SVG-to-GIF export needs Node.js 22.12+, FFmpeg/FFprobe, Chrome/Chromium, and either
puppeteer or puppeteer-core:
brew install ffmpeg
for SKILL_ROOT in \
"$HOME/.agents/skills/fireworks-tech-graph" \
"$HOME/.claude/skills/fireworks-tech-graph"
do
[ -d "$SKILL_ROOT" ] || continue
npm install --prefix "$SKILL_ROOT" --ignore-scripts --no-save --package-lock=false puppeteer-core@25.3.0
python3 "$SKILL_ROOT/scripts/fireworks.py" doctor
done
Set FIREWORKS_CHROME_PATH for a nonstandard Chrome install. Set
FIREWORKS_PUPPETEER_PATH to an explicit trusted module directory when keeping
the Node runtime elsewhere. Renderer resolution never searches the caller's
working directory, so installing puppeteer-core in the diagram project does
not make it available to a copied Skill. A skills --copy install creates two
independent roots, so each existing root needs its own runtime installation.
Chrome sandboxing is enabled by default; the no-sandbox override is reserved for
isolated CI runners.
viewBox, valid semantic metadata, and
explicit motion role, stage, and order on every reviewed edge.0–35 from 55-frame and 75-frame timelines;
their hashes must match before GIF palette quantization. Keep a separate 75-frame
raw baseline for the approved Style 1 worker and require every post-change frame
to remain byte-identical.0–70 through a three-tier compatibility gate: binary SHA-256 exact,
decoded RGBA exact, then guarded compositor-antialias equivalence. The guarded
tier requires AE ≤ 128, normalized RMSE ≤ 0.001, every connected difference
component to be at most 2px wide or high, and every component to remain on an
edge or node border. Report each tier separately. DOM and per-style signature
geometry remain strict-exact before GIF palette quantization.38–109.
Frame 110 is the sole permitted boundary repeat because its unchanged reset
opacity is exactly 1.00; classify it as intentional_reset_boundary_repeat.
Frames 111–114 remain globally distinct. Record all repeated frame indices
and embed infinite GIF looping.