Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ same rule. Defaults are no-ops, nothing third-party is forced on the consumer.

This "stdlib-only" guarantee is about the library you import: the `state` engine
and its seams pull in nothing third-party. The standalone `crucible` CLI is a
leaf tool, not a library, and is the one exception — it embeds a pure-Go
(WebAssembly) Graphviz **only** for `render -format svg|png`, so you can render
images without installing Graphviz. That convenience lives entirely in the CLI
binary; it never enters the `state` engine or any module you import. See
leaf tool, not a library, and is the one exception — it embeds
[D2](https://d2lang.com) (MPL-2.0, pure Go, no Chromium) **only** for
`render -format svg`, so you can render diagrams without installing Graphviz.
That dependency lives entirely in the CLI binary; it never enters the `state`
engine or any module you import. See
[`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md) for attribution.

## Documentation
Expand Down
78 changes: 21 additions & 57 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Third-Party Notices

The `crucible` command-line tool (`cmd/crucible`) embeds third-party software so
that `crucible render -format svg|png` can produce images without requiring an
that `crucible render -format svg` can produce diagrams without requiring an
external Graphviz installation. The crucible `state` engine and its seams do
**not** depend on any of the software listed here; these notices apply only to
the CLI binary.
Expand All @@ -11,68 +11,32 @@ with each dependency, which remain authoritative.

---

## github.com/goccy/go-graphviz
## oss.terrastruct.com/d2

Pure-Go bindings that run Graphviz compiled to WebAssembly via
[wazero](https://github.com/tetratelabs/wazero). Used by the CLI to render DOT
to SVG/PNG in-process.
The D2 diagramming engine. Used by the CLI to lay out and render the machine
diagram to SVG in-process — pure Go, with no Chromium and no external Graphviz
install. The distributed `crucible` binary therefore contains D2.

- License: MIT
- Project: https://github.com/goccy/go-graphviz
- License: Mozilla Public License, Version 2.0 (MPL-2.0)
- Project: https://github.com/terrastruct/d2
- License text: https://www.mozilla.org/en-US/MPL/2.0/ (and the `LICENSE`
shipped within the `oss.terrastruct.com/d2` module)

```
MIT License

Copyright (c) 2020 Masaaki Goshima

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

---

## Graphviz (bundled as WebAssembly by go-graphviz)

`go-graphviz` embeds the [Graphviz](https://graphviz.org/) graph-layout and
rendering engine compiled to WebAssembly. The distributed `crucible` binary
therefore contains Graphviz.

- License: Eclipse Public License, Version 1.0 (EPL-1.0)
- Project: https://graphviz.org/
- License text: https://graphviz.org/license/ (and the `LICENSE` shipped within
the go-graphviz module under `vendor`/embedded WebAssembly assets)

Graphviz is distributed under the Eclipse Public License, Version 1.0. The full
license text is available at https://www.eclipse.org/legal/epl-v10.html. The
program source for the embedded Graphviz is available from the Graphviz project
at https://gitlab.com/graphviz/graphviz.
MPL-2.0 is a file-level copyleft license. The full license text is authoritative
and is shipped with the module in the Go module cache.

---

## Transitive image-encoding dependencies
## Transitive dependencies

`go-graphviz` pulls in pure-Go image-encoding libraries used during PNG/JPEG
rendering. Their licenses are reproduced in their respective module directories
in the Go module cache and in `cmd/crucible/go.sum`:
D2 pulls in supporting libraries during layout and SVG rendering. Their licenses
are reproduced in their respective module directories in the Go module cache and
recorded in `cmd/crucible/go.sum`. Notable entries:

- `github.com/tetratelabs/wazero` — Apache License 2.0 (WebAssembly runtime)
- `github.com/disintegration/imaging` — MIT
- `github.com/fogleman/gg` — MIT
- `github.com/dop251/goja` — MIT (JavaScript engine used by D2 layout)
- `oss.terrastruct.com/util-go` — MPL-2.0
- `github.com/alecthomas/chroma/v2` — MIT
- `github.com/PuerkitoBio/goquery` — BSD-3-Clause
- `github.com/lucasb-eyer/go-colorful` — MIT
- `github.com/golang/freetype` — FreeType License / GNU GPL (dual)
- `github.com/flopp/go-findfont` — MIT
- `golang.org/x/image`, `golang.org/x/text` — BSD-3-Clause
- `golang.org/x/image`, `golang.org/x/net`, `golang.org/x/text` — BSD-3-Clause
30 changes: 25 additions & 5 deletions cmd/crucible/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ versioned independently of the `state` module.

### Added

- `render -format svg|png` renders the machine directly to a themed image via an
embedded, pure-Go (WebAssembly) Graphviz — no external Graphviz install is
required. The image carries the Crucible brand palette. `-o file` writes the
output to a file instead of stdout (the norm for binary `png`); `mermaid` and
`dot` output is unchanged.
- Machine visualizer: `render -format svg` renders the machine directly to a
themed, scalable SVG via the embedded D2 engine (pure Go, no Chromium, no
external Graphviz install). The pipeline supports scope and detail projection:
`-from`/`-to` with `-mode shortest|all|trace` select a whole / reachable-from
/ path scope, and `-detail outline|guards|actions|lifecycle|full` (default
`actions`) sets a cumulative detail ladder, refined by repeatable
`-show`/`-hide <dimension>`. `-o file` writes the SVG to a file instead of
stdout.
- `render -theme file.json` overlays a JSON theme onto the embedded default
forge palette; omitted fields keep their defaults.
- `lint -format` selects the output format: `text` (default), `json`, or
`sarif` (SARIF 2.1.0) for machine-readable CI ingestion.
- `diff -format` selects `text` (default) or `json` output.
Expand All @@ -25,6 +30,21 @@ versioned independently of the `state` module.
guards default to false). `-initial` overrides the IR's declared start state.
`-format` selects `text` (default) or `json` output.

### Changed

- The `render` SVG backend now uses the embedded D2 engine
(`oss.terrastruct.com/d2`) instead of the previous WebAssembly Graphviz
backend. SVG output is themed with the Crucible forge palette and rendered
in-process.

### Removed

- The previous WebAssembly Graphviz rendering dependency (and its bundled
Graphviz engine) is removed in favor of D2.
- `render -format png` no longer renders directly; it now exits with a usage
error hinting to render `-format svg` and convert with `resvg` or
`rsvg-convert`.

## [0.1.0] - 2026-06-13

Initial release.
Expand Down
87 changes: 78 additions & 9 deletions cmd/crucible/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,87 @@ physical location unless the IR was read from stdin (`-`).
### render

```
crucible render <ir.json> [-format mermaid|dot|svg|png] [-o outfile]
crucible render <ir.json> [-format mermaid|dot|svg] [-o outfile] \
[-from state] [-to state] [-mode shortest|all|trace] \
[-detail outline|guards|actions|lifecycle|full] \
[-show dim]... [-hide dim]... [-theme file.json]
```

Renders the machine as a Mermaid `stateDiagram-v2` (the default), Graphviz DOT,
or a themed `svg`/`png` image. The `svg` and `png` formats are rendered directly
by an embedded, pure-Go (WebAssembly) Graphviz, so **no external Graphviz
install is required** and the image carries the Crucible brand palette.
Renders the machine as a diagram. `-format` selects the output:

`-o` writes the output to a file instead of stdout; it is the norm for `png`,
whose bytes are binary. `mermaid`/`dot` remain text and stream to stdout
unchanged (the historical `crucible render m.json -format dot | dot -Tsvg`
pipeline still works for callers who prefer their own Graphviz).
- `mermaid` (the default) — a Mermaid `stateDiagram-v2`, streamed to stdout.
- `dot` — Graphviz DOT, streamed to stdout (the historical
`crucible render m.json -format dot | dot -Tsvg` pipeline still works for
callers who prefer their own Graphviz).
- `svg` — a themed, scalable SVG rendered in-process by the embedded D2 engine
(pure Go, no Chromium and no external Graphviz install). The SVG carries the
Crucible forge palette.

There is no `png` format: `-format png` exits with a usage error pointing you
at the conversion path. SVG is the scalable raster-free output; for a PNG,
render `-format svg` and convert it, e.g.:

```
crucible render m.json -format svg -o m.svg
resvg m.svg m.png # recommended
# or: rsvg-convert m.svg -o m.png
```

`-o` writes the output to a file instead of stdout; it is the norm for `svg`.

#### Scope and detail

The SVG pipeline projects the machine along two independent axes: **scope**
(how much of the graph to keep) and **detail** (how much of each
state/transition to show).

**Scope** is chosen from `-from`/`-to`/`-mode`:

- No `-from`: the **whole** machine.
- `-from A` only: the subgraph **reachable from A**.
- `-from A -to X`: a **path** from A to X. `-mode` shapes it:
- `shortest` (default) keeps the whole reachable subgraph but highlights the
single shortest A→X path (off-path elements stay, dimmed).
- `all` keeps the union of all simple A→X paths, all highlighted.
- `trace` keeps **only** the shortest A→X path, dropping everything else.

`-to` requires `-from`; a non-default `-mode` requires `-from`. Endpoints are
bare state names (composite names resolve to their region).

**Detail** is a cumulative ladder set by `-detail` (default `actions`); each
level implies all the levels below it:

| Level | Adds |
|-------------|---------------------------------------------------|
| `outline` | states and transitions only |
| `guards` | + transition guards |
| `actions` | + effects and assigns (the default) |
| `lifecycle` | + entry/exit actions and invocations |
| `full` | + delays, descriptions, data-flow, context schema, source |

`-show <dimension>` and `-hide <dimension>` (both repeatable) override the
ladder per dimension; `-show` wins when both name the same one. Dimensions:
`guards`, `effects`, `assigns`, `entry-exit`, `invoke`, `delays`,
`descriptions`, `data-flow`, `context-schema`, `source`.

#### Theme

`-theme file.json` overlays a JSON theme onto the embedded default forge
palette; fields you omit keep their defaults. Without `-theme`, the embedded
default theme is used.

#### Examples

```
# Whole machine, default detail, as Mermaid (to stdout):
crucible render m.json

# Just the shortest path from cart to done, nothing else, as SVG:
crucible render m.json -format svg -mode trace -from cart -to done -o path.svg

# Reachable-from-A view with full detail but guards suppressed:
crucible render m.json -format svg -from active -detail full -hide guards -o active.svg
```

### diff

Expand Down
Loading