Releases: MarkovWangRR/iso-topology
Release list
v0.16.0
True depth ordering, an obstacle-avoiding router, and a repair loop that fixes what it scores
Two coordinated engineering waves — twelve parallel workstreams, each gated by adversarial contract review and pixel-level end-to-end verification. Every existing document renders byte-identically: all new capability is opt-in or purely additive.
Added
canvas: { depthSort: true }— true painter's-algorithm depth ordering. Parts are drawn back-to-front by world depth across group boundaries, so stacking no longer depends on authoring order; connectors are layered by endpoint depth instead of being pinned under every body. Off by default (author order preserved).routing: orthogonal2— an obstacle-avoiding, crossing-aware orthogonal router: Dijkstra over a sparse Hanan grid with a cost kernel aligned to the evaluator (tunnel ≫ crossing ≫ bend ≫ length), plus fan-out channel width that adapts to the source face span. The defaultorthogonalpath is untouched.- Self-repairing routing and overlaps — the repair loop now acts on the two defect classes it could previously only score: orthogonal edges that tunnel through nodes or cross each other are escalated to
orthogonal2(kept only on strict measured improvement, rolled back byte-identically otherwise), and overlapping siblings inside groups are pushed apart with the same conservative accept-or-rollback discipline. - Body-vs-body occlusion, detected and repaired — a node whose projected silhouette is substantially hidden behind a nearer body (paint-order aware, including
depthSortmode) now raises a locatedvalidatewarning, feeds a new readability component, and gets a repair actuator that walks it out from behind the occluder. Closes the last open Phase-1 item of the layout-engine master plan. layout: { mode: auto, engine: elk | dagre }— dense DAGs can route container auto-layout through the embedded d2 layout engines (pure offline, deterministic, automatic fallback to the built-in layering on failure). On 16–18-node benches this cuts weighted crossings+tunnels by ~86%.- Studio multi-select — marquee selection on empty canvas, shift-click add/remove, group move of the whole selection as ONE atomic server round-trip and ONE undo step, and batch delete. Panning moves to alt/middle-drag.
RenderWithRouteInfo— an in-memory route collector exposing every connector's real drawn world geometry.evaluatenow scores the routes actually rendered — including straight and bezier edges, which the old regex-based extraction never saw.- Richer shape styling —
cloudgains top-face icons and gradients;persongains body gradients,effects.outline,dropShadow, andbackglow; prisms gain per-wall gradients dispatched by wall normal and projected patterns pinned to each wall's true iso plane.
Fixed
- CJK screen labels measured 3× too wide — screen-space label boxes were sized by byte count; CJK text is now measured per rune through a single shared text-metrics module that also unifies five divergent width heuristics.
- Evaluator/pixel parity for upgraded routes —
orthogonal2routes are recorded by the route collector, so the evaluator can no longer report a crossing as cleared while it is still visible on screen. - SVG post-processing hardened — viewBox surgery survives attribute reordering and decoy attributes; per-part ID namespacing no longer rewrites text content that happens to contain
id="literals. - Studio selection survives a committed group move — the trailing click of a drag (or a marquee ending on a node) could clear or poison the selection; a fresh mousedown now invalidates any stale swallow-one-click guard.
Prebuilt binaries for isotopo and isotopo-mcp (linux/darwin/windows × amd64/arm64) with checksums are attached below.
v0.15.0
Self-repairing documents, cross-toolchain determinism, and smarter cyclic layout
Three engine improvements, each diagnosed empirically and gated by dedicated regression tests.
Added
isotopo repair <file> [--write]— the projection-repair loop (caption occlusions, node overlaps, label contrast) can now persist its fixes into your YAML, comment-preserved. Dry-run prints a JSON fix report;--writeapplies it. Exit codes: 0 = already clean, 2 = repairs found. Previouslyrenderfixed these defects in memory on every run whilevalidatewarned about them forever — the fix now lands in the source once and the warning is gone for good.validatemarks auto-fixable issues with"repairable": true, so an agent (or you) can tell “runisotopo repair --write” apart from “edit the source by hand”.
Changed
- Flows with feedback edges stay layered. Auto layout (
layout: { mode: auto }) no longer forfeits a graph to the force placer because of a single retry/writeback edge. Feedback arcs are identified with a deterministic GreedyFAS (Eades–Lin–Smyth) ordering and reversed for ranking only, keeping the left-to-right narrative; the arrangement is kept only if every edge has a clear route (trial + rollback), so dense meshes and bidirectional hub-and-spoke graphs still get the force placer's spread. - Bundled samples are warning-clean: the persisted repairs eliminate the 8 chronic group-caption occlusion warnings across langchain-app, data-fabric, vpc-boundary and clickhouse-hub.
Fixed
- Cross-toolchain golden stability. Projected coordinates are quantized to a 1e-6 grid, so sub-ULP differences in how Go releases compile the projection (FMA contraction) can no longer flip threshold decisions and drift rendered output between toolchains.
Prebuilt binaries for isotopo and isotopo-mcp (linux/darwin/windows × amd64/arm64) with checksums are attached below.
v0.14.2
Bigger logos and group captions
Readability follow-up to v0.14.1. Two layout-safe default changes (verified via rasterized renders):
Changed
- Icon-only logos are larger. A node with an icon and no label has no text sharing the face, so its brand logo now fills more of it (default scale 0.72 for icon-only; author-set larger scales are respected). Logo-only chips grow ~33 → 43px.
- Group captions read at 1:1. Category headers (e.g. "Databases & data warehouses") default to size 13 (was 11), matching the edge-label tier. An explicit group
text.sizestill wins.
Notes
- A
--readableautomatic node-enlargement was prototyped and reverted: resizing nodes breaks scenes placed with absoluteoffsetcoordinates. Node enlargement on hand-placed scenes must be done per-scene, not automatically.
Prebuilt binaries for isotopo and isotopo-mcp (linux/darwin/windows × amd64/arm64) with checksums are attached below.
v0.14.1
Bigger, more readable default label sizes
A focused readability follow-up to v0.14.0.
Changed
- Default label text is larger so diagrams read comfortably at 1:1. Only the unset defaults changed — explicit
text.size/labelFontSizeare untouched:- Node top-face labels: 16 → 18 (adaptive fit still shrinks to avoid overflow on small faces)
- Connector / edge labels: 11 → 13
- Screen labels (
--readable/text.orient: screen): 11 → 13
Notes
- Dense scenes with small nodes remain face-size constrained (their node labels are shrunk to fit the face regardless of the default); this change primarily benefits normal-density diagrams and edge labels.
v0.14.0
Readability + pkg.go.dev fixes
This release is focused on legibility and unblocking the API docs, from community feedback.
Fixed
- pkg.go.dev now shows documentation again. The
LICENSEwas a hand-edited Apache-2.0 whose reworded clauses dropped the license classifier below pkg.go.dev's confidence threshold (reported as UNKNOWN, hiding all docs). Restored verbatim canonical Apache-2.0. - Contrast-clean samples. Three bundled samples (incl. the flagship ClickHouse hub at ratio 2.08) shipped label text below the 3.0 contrast threshold; fills darkened, with a new repo-wide contrast gate in CI.
Added
isotopo render --readable— one opt-in flag for a legibility-first "documentation" render: upright screen labels with a canvas-aware contrast chip (dark text on light canvas, light on dark) + a padding floor. Non-destructive: only fills gaps the author left blank.- Contrast auto-repair in the render pass — any label below the 3.0 threshold is retinted to the most legible extreme (never the author's fill); gated by
--no-repair. - 2D top-down view promoted — the existing
projection: topdocumentation view is now documented in the README with aplan-view-2dsample. - Bad-case intake — a
bad-caseissue form +scripts/add-sample.shthat freezes a reported scene into a golden regression sample.
Changed
- Default top-face icon scale 0.4 → 0.55 so brand logos are identifiable at 1:1 (adaptive fit still caps overflow).
- Added a CI test workflow (
go build+go test ./...) running seven new regression gates on every PR.
Prebuilt binaries for isotopo and isotopo-mcp (linux/darwin/windows × amd64/arm64) with checksums are attached below.
v0.13.0
Full agent loop over MCP + prebuilt binaries
MCP server (isotopo-mcp 0.4.0)
iso_evaluate— layout scorecard (edge crossings, node overlaps, edge-through-node tunnelling, readability score) so an agent can self-correct before rendering.iso_preview— crop and return the SVG for one node / group /edge:N;projection: topfor the flat plan view.- The server now mirrors the full CLI loop: capabilities → validate → evaluate → render → preview.
Distribution
- Releases now ship prebuilt binaries for
isotopoandisotopo-mcp(linux/darwin/windows × amd64/arm64) with checksums — no Go toolchain required.
Docs
- README gains a dedicated MCP section (tool list + Claude Code / Claude Desktop / Cursor configs);
docs/agent/MCP.mdupdated.
v0.12.0 — readability-driven layout engine: projection-repair loop + adaptive placement
A readability-driven layout engine: one objective — measured in the iso projection the user actually sees — now drives placement and routing, with a self-repair loop that auto-fixes the defects that only exist in 2.5D. Validated end-to-end on every real demo.
Layout engine (new)
- Single readability objective
R, computed in iso screen space (occlusion, crossings, tunnelling, overlap, bends).evaluatereports the breakdown and the renderer optimizes toward the same number — they no longer disagree. (readability.go,docs/design/layout-engine-master-plan.md) - Projection-repair loop —
isotopo render --repair: detects iso-screen defects and locally repairs them — widens a group's front padding when its caption is ridden by a child; pushes genuinely-colliding nodes apart (Z-aware, so deliberately stacked boards stay intact) — iterating to a clean fixpoint. Strict no-op on already-clean scenes (byte-identical). - Graph-class adaptive placement — cyclic / mesh graphs (where longest-path layering crams nodes so edges tunnel) are routed to a deterministic force-directed placer with adaptive spread; DAGs keep longest-path. Clears mesh edge-tunnelling while keeping sparse graphs compact.
- Straight-edge crossing/tunnel detection — straight connectors are now scored as the line they actually render as, so their crossings and node-tunnelling are detected.
Validation & robustness
- Contrast lint reads
faces/pattern top fills; invisible text escalates to error. - Plan-view footprint-collision + depth-aware overlap (stacked parts aren't collisions).
- Warn when a child bursts a fixed container, a node covers a group label/title, or styles are inconsistent across a cluster.
Shapes & routing
- Cloud shape redesigned — classic 2-bump silhouette, corrected geometry, label on the iso top face.
- Elevated connectors route ground-hugging with vertical risers; tier-model guidance.
Housekeeping
- Removed the playbook subsystem —
samples/style_referis the sole style reference. iso_textis a first-class interactive node.
End-to-end acceptance over all 13 real samples/topology demos: 9 clean no-ops, 3 defective scenes auto-repaired (incl. README heroes), 0 regressions — and the validation itself caught & fixed a Z-stack repair regression.
v0.11.0 — sharper palette, ground-routed connectors, Studio editor overhaul
Highlights
Shape palette — aggressive subtraction
Retired 11 ambiguous / broken / redundant shapes (sphere, capsule, dome, torus, diamond, screen, browser-panel, prism, cone, pyramid, frustum) — they now hard-error as unknown shapes. Kept 18 sharp, distinct shapes.
Connectors — 2.5D ground routing
- Connectors run along the ground plane and dock at side-face geometry, occluded by the bodies they pass behind (real depth).
- Coincident same-style lines are de-duplicated so overlapping routes no longer read as one fat line.
- Per-face and per-connector linear gradients ("base color + optional gradient-to").
Studio editor — full UX overhaul
- Node & edge detail forms rebuilt: focused tabs with second-level cards, progressive disclosure (showWhen), sliders with units, segmented controls.
- Custom styled dropdowns replace native (edge from/to with distinct-endpoint locking; "copy style from another node"). Edge form: source → target direction arrow; unified gradient model; routing-conditional elbow. Toolbar: Overwrite separated from downloads; labeled "</> Code" toggle off the zoom controls. Full zh/en localization of the detail editor. Docs / API Per-node rendering API documented (RenderParts, NodeHTML, NodesIndexHTML, per-element nodes/ output, /nodes/ serve routes). Regression gate (build + vet + full suite + golden + wasm + fuzz) green.
v0.10.0 — position-resolution refactor + edit-engine hardening
Highlights
A single source of truth for node positions, and a stateless edit engine that no longer silently corrupts the document under cumulative editing.
Position-resolution refactor
- One world-coordinate resolver shared with the renderer (
resolveLoweredreuses the renderer's own lowering pass) — the editor and renderer can no longer diverge. Replaces the old per-op re-derivation + ad-hoc slab compensation. reparentis position-preserving in every container — manual, authored-offset, nested, cross-group, autosize, andlayout:row/col/grid (the layout is frozen on the way in/out). Round-trips and repeated cycles are drift-free.- Unified YAML reading — a tight flow map
{wx:30,wy:30}now parses the same for renderer and editor (previously the renderer dropped it to zero). - Backed by an acceptance suite (
acceptance_position_test.go) and byte-identical goldens (the refactor changed edit math, never rendering).
Edit-engine hardening (from multi-round structured + fuzz + cumulative-edit audits)
- Universal safety net: any edit op that would make the document unparseable returns an error on the original source instead of corrupt text.
set-field: id renames cascade to all connector/place/annotation references (incl..anchorand~Nstack-instance suffixes); reserved-word and invalid ids are quoted/rejected; container→leaf shape demotion and not-found targets are refused.add-edge: endpoints are validated; ids are quoted; same-column / inlineparts:blocks are handled.move: idempotent and precision-preserving across autosize/boundary/freeze paths.- Inline flow groups (
- { … parts: [ {…} ] }) are normalized so edits target the right nested child, not the outer group.
Validation & rendering robustness
- Parse-time nil-pointer normalization (kills a class of
Validatepanics). - Finite + bounded
geom/offset, boundedgeom.sides(render-DoS) andcanvas.padding. - Whole-class SVG escaping across every shape renderer + connectors + control characters, guarded by a standing injection test over all shapes.
- Typo'd
arrow/routing/anchor/canvas.grid/canvas.projectionare warnings with graceful fallback, instead of blanking the diagram. - Deterministic cross-CPU output (
data-scene-tx/ty).
All changes ship with regression tests; the full suite, goldens, go vet, and the WASM build are green.
v0.9.3
v0.9.3
Bug Fixes
- Fix drag displacement:
containerUndernow uses world-space coordinates for correct group detection during node moves - Fix
FreezeGroupLayoutTextto only striplayout:at direct property indent level, preserving nested group layouts - Fix multi-line YAML flow-map corruption in
collapseFlowMap(affectsUpsertInlineList,UpsertInlineKey,SetField)
Connector UX
- Hover stroke width increased to 6px with layered glow effect for better visibility
- Directional cursor on connector hover:
nesw-resize/nwse-resizebased on segment axis - Segment midpoint handle circles appear on hover, fade in/out smoothly
grabbingcursor during drag; handles hidden while dragging