Skip to content

fix: the running ring in exports, the status check, render-svg's work directory - #106

Merged
endrix merged 4 commits into
mainfrom
fix/export-run-ring
Oct 24, 2026
Merged

endrix merged 4 commits into
mainfrom
fix/export-run-ring

Conversation

@endrix

@endrix endrix commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Three fixes found while reviewing #105, one commit each.

Export as SVG: the running ring (e0cbbbd)

A running node's ring came out as a rainbow square over the node's title. This happened in the editor's Export as SVG during a live run, and in every headless render of running states. A coverage render draws every TBD or open clause as running, so it hit those too.

In the editor the ring is HTML inside a foreignObject: a turning conic-gradient square, placed absolutely and masked down to a band. The export copies neither the placement nor the mask for HTML, and standalone SVG renderers draw no HTML at all.

The export now replaces each ring with a rect stroked in the ring's colours (--wf-ring-colors, as a linear sweep). The stroke runs down the middle of the band on the node's edge (--wf-ring-width, and the band's own radius). Checked in Chrome and in Inkscape. The coverage test's excuses for position, inset and the masks now name the ring.

Node states: the status check (307c98b)

The check status in EXECUTION_STATUS_CLASS also accepted names every object inherits. A status of toString passed, put a function where a CSS class goes, and the whole diagram failed to draw. Statuses are now checked against the map's own keys.

render-svg: the work directory (51e1ba0)

A failed layout or render exited before the clean-up, leaving a dialogram-render-* directory in /tmp each time. The directory is now removed in a finally; with --keep it is kept and its path printed.

Tests

  • svg-export-run-ring.test.ts covers the colour list, the stroke geometry and the hook's place in the export.
  • execution-states.test.ts covers inherited names.
  • Checked by hand: a failed render now leaves no directory.
  • Typecheck (5/5), neutrality (5/5) and the diagram-client suite (336) pass.

Review fixes (6f41ad3)

  • Ring geometry: width, bleed and radius now come from the band as laid out (computed padding, top and corner radius), not from the raw custom properties.
  • Colours: each one is resolved to rgb() by painting a pixel and reading it back, after dropping a stop's positions. oklch(), color-mix() and #0af 0 50% no longer come out black.
  • No ring: where the editor draws no ring (no band width, fewer than two colours) the export draws none. The glow is left out.
  • Gradient ids: numbered per export, so two exports of the same diagram are identical text.
  • Tests: runRingElement is now tested through a fake document.
  • render-svg interrupts: on SIGINT or SIGTERM it stops esbuild (which would otherwise keep writing into the directory), then removes the directory.

https://claude.ai/code/session_01E8WfqKknDNN6xpNVcJL5K8

…square

Export as SVG drew a running node's ring as a rainbow square over the
node's title (in the editor during a live run, and in every headless
render of `running` states, which a coverage render draws for every TBD or
open clause). The ring is HTML in a foreignObject: a turning
conic-gradient square, absolutely placed and masked down to a band. The
export copies neither the placement nor the mask for HTML, and standalone
SVG renderers draw no HTML at all.

The export now replaces each ring with what it reads as: a rect stroked
with the ring's colours (`--wf-ring-colors`, as a linear sweep) down the
middle of the band on the node's edge (`--wf-ring-width`, the band's
radius). Checked in Chrome and in Inkscape. The coverage test's excuses
for `position`, `inset` and the masks now name the ring.

Claude-Session: https://claude.ai/code/session_01E8WfqKknDNN6xpNVcJL5K8
`state.status in EXECUTION_STATUS_CLASS` also answered for what every
object inherits, so a status named `toString` or `constructor` passed, put
a function where a CSS class goes, and the diagram failed to draw. The
status is now checked against the map's own keys, in `showExecutionStates`
and in `applyExecutionStates`.

Claude-Session: https://claude.ai/code/session_01E8WfqKknDNN6xpNVcJL5K8
A failed layout or render called `process.exit(1)` before the clean-up, so
each failure left a `dialogram-render-*` directory in the temporary folder.
The failures now throw, and `main` removes the directory in a `finally`
(or keeps it and says where, with `--keep`).

Claude-Session: https://claude.ai/code/session_01E8WfqKknDNN6xpNVcJL5K8
…errupts clean up

Review of #106:

- The ring's width, bleed and radius are read from the band as laid out
  (its computed padding, `top` and corner), not from the raw custom
  properties, so a ring declared in `rem`, moved by `--wf-ring-bleed`, or
  of width 0 comes out as the editor draws it.
- Each colour is resolved by painting it on a pixel and reading it back,
  after dropping a stop's positions: `oklch()` and `color-mix()` (which
  Inkscape drew black) and `#0af 0 50%` (which Chrome drew black) now come
  out as `rgb()`. A colour that is none is dropped.
- Where the editor draws no ring (no band width, fewer than two colours,
  which is no conic gradient), the export draws none either, instead of a
  solid ring in `currentColor`.
- Ring gradients are numbered per export, so two exports of one diagram
  are the same text.
- The builder is `runRingElement`, tested through a fake document: the
  gradient stops, the rect, and the cases that draw nothing.
- render-svg: an interrupt (SIGINT, SIGTERM) stops esbuild, which would
  otherwise go on writing into the directory, then removes it.

Claude-Session: https://claude.ai/code/session_01E8WfqKknDNN6xpNVcJL5K8
@endrix
endrix merged commit a6caf84 into main Oct 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant