Releases: ForgePlan/forgeplan-web
v0.2.4 — graph layout normalization
What changed
Graph layout no longer drifts. ForceView is now deterministic — the same dataset always renders to the same starting configuration, so panning/zooming back to a familiar cluster works between sessions.
Connection-aware ordering in all 5 views. High-degree artifacts surface earlier within their semantic group (kind / status / ring) — what was previously alphabetical clutter now visually conveys "what's important".
Implementation
- New
seeded-rand.tslib: FNV-1a 32-bit hash + mulberry32 PRNG +seededJitter(nodeId, half)— replacesMath.random()initialization inForceView.svelte. - New
degree.tslib: sharedbuildDegreeMap(skip self-edges, undirected count) +byDegreeDesc<T>(map, tieBreak?)comparator, threaded through:ForceView.svelte— pre-sort nodes before d3-forceRadialView.svelte— pre-sort ring members before angular layoutTreeView.svelte,MatrixView.svelte,LanesView.svelte— secondary sort key after kind / status, before id
SankeyViewandSunburstViewuntouched — already deterministic.
Tests
- 87/87 vitest (9 new tests in
seeded-rand.test.ts+degree-order.test.ts) svelte-check0 errors, 0 warnings (1076 files)- CI matrix green: ubuntu / macos / windows × Node 22
Compatibility
Patch release. No API changes, no breaking changes. forgeplan-web init / start / update semantics unchanged.
Refs: PRD-033, RFC-027, EVID-039
Commits
- 356b396 chore(release): bump version to 0.2.4
- b035111 chore(forgeplan): activate PRD-033, RFC-027, EVID-039
- 8a0c123 feat(dependency-graph): normalize node layout — seeded init + degree-first sort
Full Changelog: v0.2.3...v0.2.4
v0.2.3
What's changed
Bug fixes — multi-instance switcher
- Self-filter fix: current instance no longer appears in the switcher list.
window.location.hostreturnslocalhost:portin some browsers while the registry always stores127.0.0.1:port; addednormalizeHost()to map them before comparison. - Request flood fix: opening the dialog was triggering 2 000+ requests per second. Root cause:
refreshStatuses()was called inside theswitcherOpeneffect without atoFetchargument, causing Svelte 5 to trackotherInstancesas a dependency. EveryinstancePollertick changedotherInstances→ re-ran theswitcherOpeneffect → fired anotherinstancePoller.refresh()→ infinite loop. Fixed by splitting into a stablesetIntervaleffect and a separate reactive effect that passes the snapshot explicitly. - CORS fix:
/api/instance-statusnow responds withAccess-Control-Allow-Origin: *so cross-port status fetches (instance A checking instance B's health) are not blocked by the browser. - Instance discovery: reduced server-side registry cache TTL from 2 000 ms to 500 ms so newly-started instances appear in the switcher within one poll cycle.
Full changelog: v0.2.2...v0.2.3
v0.2.2
What's changed
Features
- health-bar: instance switcher rebuilt — Popover → Dialog, skeleton loading on open, live status checks + validation, refresh on re-open
Fixes
- button: center SVG icons in flex layout
Installation
npx @forgeplan/web@0.2.2 init -yFull changelog: v0.2.1...v0.2.2
v0.2.1
Fixed
- Instance switcher rewritten with Popover+Command (
health-bar) — replaced the bits-ui Combobox (anchor / open-in-empty-state issues) with a Popover + Command combination that opens reliably, anchors correctly to its trigger, and renders in both populated and empty states. - Combobox ghost variant — semi-transparent background, no border, consistent hover across themes; switcher is always visible even with ≤ 1 live instance.
- Registry heartbeat race (
registry) — heartbeat now re-registers an entry evicted by a concurrentinit, preventing silent loss of a running instance. - Timeline toggle (
template) — restored Retry button and Lucide arrow icons that regressed in 0.2.0.
Full changelog: https://github.com/ForgePlan/forgeplan-web/blob/main/CHANGELOG.md#021---2026-05-09
v0.2.0
First minor release on top of 0.1.13.
Highlights
- Multi-instance registry —
~/.forgeplan-web/instances.json+/api/instancesendpoint + HealthBar instance switcher (PRD-027 / RFC-023 / SPEC-003 / ADR-004). init --scope user|project— workspace-agnostic user scope at~/.forgeplan-web/;startfalls back from project to user scope (PRD-025 / RFC-021 / ADR-004).bin/adopts citty (^0.2.2, the only allow-listed runtime dep) and splits intocli/,commands/,lib/(ADR-003).- Feature-flag + image system —
init --image stable|nightly, build-time lifecycle validator, per-image smoke. Bundle approach is now the universal artifact form for everydist*/.--experimentalis a deprecated alias for--image nightly(removed in 0.3.0) (PRD-030 / RFC-026 / ADR-005). - UI / template polish — multi-tab artifact viewing (Shift+click),
Comboboxprimitive inshared/ui/,adapter-nodeprecompress disabled (smaller tarball).
Breaking changes
Only relevant if you depend on internals:
dist-experimental/directory in the published tarball is replaced bydist-nightly/. Users runningnpx @forgeplan/web initsee no change; consumers that pinned the directory name in scripts must switch todist-nightly/.
See CHANGELOG.md for the full set of entries.
v0.1.13
Added (PRD-018 / RFC-016 — shared/ui catalogue)
shared/ui/primitives based onbits-ui— single source of truth
for visual atoms. Visual atoms (Badge / Separator / Skeleton / Spinner /
Card / Alert / Progress), form basics (Label / Input / Field / InputGroup),
toggles (Toggle / ToggleGroup / ButtonGroup / Switch / Checkbox), radio
(Radio / RadioGroup), disclosure (Tabs / Collapsible / Accordion),
overlays (Tooltip / Popover, Toaster viasvelte-sonner), and command
palette (Command + Item family)./playgroundshowcase route — every primitive × every variant ×
every size, in both light and dark themes. The catalogue is the
contract for what an atom looks like.- Rule 24 —
shared/uiownership and customisation discipline
(.claude/rules/24-shared-ui-ownership.md). Forbids:global()
re-skins of primitive internals fromentities//widgets//
pages//routes/. Includes a verification grep snippet. - New primitive variants added by the rule-24 audit:
Button.variant= "ghost-mono",Button.size="icon",Badge.variant="mono",
Toggle.variant="outline-mono",ToggleGroup.variant="outline-mono",
Alert.tone="banner",TabsList.wrap. Replaces hand-rolled markup
(Tabs,Collapsible) across widgets.
Added (UI)
orchtheme — third palette (Orchestra-inspired), exposed as a
hidden 5-click easter egg on the theme toggle, with a 2 s freeze
after unlock to prevent immediate accidental switch.- Dense-graph render-resilience — Sankey and Tree views handle
100+ artifacts without layout thrash.
Changed
- Widget visuals migrated to primitives —
UpdateButton, mosaic
pane-icon buttons,HomePageerror-bar, filter chips,HealthBar
theme-switcher and notify,InsightsRailtab badges and R_eff
bars,ArtifactPanelkind chip and ghost buttons.
Reverted
- Force 3D experimental Threlte view mode (
#103) — reverted in
#105. Thedist-experimental/cap stays at 6M for now.
v0.1.12
Bundles five feature streams from develop into v0.1.12.
Added
- F18 Time-travel slider — SINGLE mode —
/api/snapshot?at=ISO,/api/timeline-events, collapsible Timeline panel with SVG scrubber. Canvas hydrates from snapshot when scrubbed. PRD-008 / RFC-007 / EVID-020. init --experimentalflag — opt-in to esbuild single-file bundle, ~9× smallerdist-experimental/. PRD-014 / RFC-013 / EVID-018.- Multi-graph mosaic dashboard — split-pane layout with persistent layout (#64).
- Version display footer — shows forgeplan CLI + @forgeplan/web versions (#57). PRD-012 / RFC-011 / EVID-016.
- Shared UI primitives + npm update notification — modal manager + update checker (#58). PRD-013 / RFC-012 / EVID-017.
- Light theme — dual-token CSS + `data-theme` attribute (#62). PRD-015 / RFC-014 / EVID-019.
Deferred
- COMPARE mode for time-travel (Alt-drag two scrubbers, diff overlay) — endpoint returns 501 with TODO. SC-4/SC-5 from PRD-008.
Verified
- 14 vitest files / 127 tests pass
- svelte-check: 0 errors / 0 warnings across 486 files
- 3-OS CI matrix green on PR #63 + PR #65
🤖 Generated with Claude Code
v0.1.11
F17 — minimap support extended to Matrix / Sankey / Sunburst (all 7 views now have minimap).
Changes
- Sankey — centroid
((x0+x1)/2, (y0+y1)/2)of d3-sankey nodes. - Sunburst — polar → xy:
cx + r·cos(θ−π/2), cy + r·sin(θ−π/2). - Matrix — diagonal centroid
MARGIN + HEADER + i·CELL + CELL/2. - Each view exports
panTo(canvasX, canvasY, k=1). - DependencyGraph drops the
enabled={false}gate; Minimap self-gates onnodes.length > 0.
Verify
Full changelog: v0.1.10...v0.1.11
v0.1.10
F16 — infinite-feel zoom + minimap with click-teleport.
Highlights
- scaleExtent [0.3, 3] → [0.05, 50] on Force / Tree / Radial / Lanes / Matrix / Sunburst (~167× dynamic range). Sankey unchanged.
- Minimap in bottom-right of
.canvas-body: 180×120 SVG miniature with viewport rect overlay; click or drag teleports canvas to that point atk=1. User never gets lost at extreme zoom. - Active for Force / Tree / Radial / Lanes (free 2D placement); Matrix / Sankey / Sunburst show muted "MINIMAP N/A" stub.
- New
lib/minimap-math.ts— pure functions + 7 unit tests. - View teleport API:
onViewStatecallback prop +panTo()method on supported views.
Verify
- svelte-check 0/0/440.
- vitest 81/81 (74 baseline + 7 minimap-math).
- 3-OS smoke matrix green on PRs #47, #48.
Full changelog: v0.1.9...v0.1.10
v0.1.9
F15 — bug-fix release responding to user-reported issues on a real 289-artifact workspace.
CRITICAL
each_key_duplicateruntime crash fixed.lib/filter.ts#filterEdgesnow dedupes by${from}>${to}:${relation}composite key. Workspaces with legitimately duplicate edges no longer crash Force/Tree/Radial/Lanes/Matrix views. 4 unit tests added.
UX
- HealthBar chips restructured — monospace tabular-nums values + uppercase 0.12em labels. Reads as "30 TOTAL · 27 ACTIVE · 3 DRAFT" instead of mashed text.
- ArtifactPanel default width 380 → 658 px (+73%). MAX_RATIO 0.6 → 0.7. Drag-resize handle on left edge with localStorage persist (key
forgeplan-web.panelWidth). Min 320, max 70vw. - "📋 Copy as markdown" moved into body-actions row next to Hide/Show body.
- Body section opens by default (
bodyExpanded = $state(true)).bodyHydratedguard race-safe against the new default overwriting stored'0'before reader-effect. .ghostbutton rule added inside ArtifactPanel (Svelte scoped CSS in HomePage didn't reach the panel; buttons rendered as browser-default before).- Sticky-stack panel sections + meta-trail — As user scrolls inside ArtifactPanel, each section pins below header. Single-active model via
activeStickyKeystate: only one block sticky at a time; earlier blocks getposition: staticso a shorter active block doesn't leave a taller previous one visible underneath. When body-actions becomes the active sticky,depthandupdated_atfrom the meta block fade-slide into the right side of the row. - Outgoing / Incoming collapse — Each links subsection has its own toggle (
+ N · Outgoing / − Hide). Auto-collapsed on artifact change when count > 8 to prevent panel exploding on hub artifacts. - No nested scroll containers —
.artifact-bodyand.links ullostmax-height: Xvh; overflow-y: auto. Outer panel scrolls. Page shell.root { overflow: hidden }— no horizontal/vertical scroll on page level.
Polish
- Chrome 132+ devtools probe 404 suppressed via
template/static/.well-known/appspecific/com.chrome.devtools.json = {}.
Verify
- svelte-check 0/0/437.
- vitest 74/74 (70 baseline + 4 filter dedup tests).
- 3-OS smoke matrix green on PRs #44, #45.
Refs: ad-hoc bug-fix.
Full changelog: v0.1.8...v0.1.9