feat(cmd/crucible): machine visualizer — scoped, granular, forge-themed render (D2)#186
Merged
Conversation
…ed render Project the IR through a view-model at a chosen scope and detail granularity and render it as a themed SVG via the embedded D2 engine (pure Go, no Chromium, no external Graphviz). - Scope: -from/-to (path A→X), -from (reachable-from-A), or whole machine; -mode shortest|all|trace selects the path view. - Detail: -detail outline|guards|actions|lifecycle|full (default actions), a cumulative ladder refined by repeatable -show/-hide <dimension>. Lifecycle detail (entry/exit/invoke) renders as in-node compartments. - Distinct shapes per kind (initial dot, atomic 3D steel box, invoke hexagon, history circle, final double-ring, composite/parallel containers); the active path is highlighted in ember over cold-steel context. - Theme: -theme file.json overlays the embedded "forge" default palette. - New internal packages: viewmodel (projection), query (path/scope BFS over the IR), render (D2 emit + in-process SVG + post-process). Replaces the previous WebAssembly Graphviz svg/png backend with D2 and removes that dependency. `render -format png` now errors with guidance to render -format svg and convert with resvg/rsvg-convert; dot/mermaid output is unchanged.
…ed render)
An edge whose label starts with `[` (e.g. an eventless transition carrying only a
guard, rendered as `[hasStock]`) made D2 parse the value as an array and fail to
compile ("edges cannot be assigned arrays"), so RenderSVG errored. The emitter's
quote() used a too-narrow blacklist that left such labels bare.
Replace it with a whitelist — bare only for ^[A-Za-z_][A-Za-z0-9_]*$, everything
else double-quoted (escaping backslash then quote). quote() is the single helper
used at every label/name/title/compartment site, so this fixes the whole
special-char class. Adds emit + end-to-end RenderSVG regression tests; existing
goldens unchanged (a new guard_only_edge golden covers the quoted forms).
Found by the granularity showcase (eventless+guard transition).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Turns
crucible renderinto a machine visualizer: project the IR through a view-model at a chosen scope and detail granularity, and render it as a polished, themed SVG via the embedded D2 engine (pure Go, no Chromium, no external Graphviz).Why (pivot from go-graphviz)
The go-graphviz/DOT path (#185) hit a composition ceiling — sprawling layout, no clean containers, weak shape vocabulary. After research + spikes, D2 proved meaningfully better and embeds in-process in pure Go like go-graphviz did. This PR pivots the SVG backend to D2 and builds the visualizer on top.
What
Pipeline:
IR → query (path/scope) → view-model projection (detail) → D2 emit → in-process SVG.-from/-to(path A→X),-fromonly (reachable-from-A), or whole machine.-mode shortest|all|trace.-detail outline|guards|actions|lifecycle|full(defaultactions) — a cumulative ladder — refined by repeatable-show/-hide <dimension>. Lifecycle detail (entry/exit/invoke) renders as in-node compartments.-theme file.jsonoverlays the embedded forge default palette.viewmodel,query,render.Backend swap: removes the go-graphviz dependency (and its bundled Graphviz).
dot/mermaidtext output is unchanged.-format pngnow errors with guidance to render-format svgand convert withresvg/rsvg-convert(SVG is the scalable primary).Verification
go build/vet/test(4 packages) /golangci-lint— all green, includingGOWORK=off(standalone consumer build holds after the dep swap).dot/mermaidregression,png→usage error, unknown-endpoint→usage error.Notes / honesty
THIRD_PARTY_NOTICES.md).Design + research artifacts live under
~/llm/plans/crucible/(not committed, per repo convention).