Skip to content

Releases: ForgePlan/forgeplan-web

v0.2.4 — graph layout normalization

25 May 18:40
03f6457

Choose a tag to compare

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.ts lib: FNV-1a 32-bit hash + mulberry32 PRNG + seededJitter(nodeId, half) — replaces Math.random() initialization in ForceView.svelte.
  • New degree.ts lib: shared buildDegreeMap (skip self-edges, undirected count) + byDegreeDesc<T>(map, tieBreak?) comparator, threaded through:
    • ForceView.svelte — pre-sort nodes before d3-force
    • RadialView.svelte — pre-sort ring members before angular layout
    • TreeView.svelte, MatrixView.svelte, LanesView.svelte — secondary sort key after kind / status, before id
  • SankeyView and SunburstView untouched — already deterministic.

Tests

  • 87/87 vitest (9 new tests in seeded-rand.test.ts + degree-order.test.ts)
  • svelte-check 0 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

09 May 17:52
c643ae6

Choose a tag to compare

What's changed

Bug fixes — multi-instance switcher

  • Self-filter fix: current instance no longer appears in the switcher list. window.location.host returns localhost:port in some browsers while the registry always stores 127.0.0.1:port; added normalizeHost() to map them before comparison.
  • Request flood fix: opening the dialog was triggering 2 000+ requests per second. Root cause: refreshStatuses() was called inside the switcherOpen effect without a toFetch argument, causing Svelte 5 to track otherInstances as a dependency. Every instancePoller tick changed otherInstances → re-ran the switcherOpen effect → fired another instancePoller.refresh() → infinite loop. Fixed by splitting into a stable setInterval effect and a separate reactive effect that passes the snapshot explicitly.
  • CORS fix: /api/instance-status now responds with Access-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

09 May 17:15
d29f8da

Choose a tag to compare

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 -y

Full changelog: v0.2.1...v0.2.2

v0.2.1

09 May 14:51
4feec4b

Choose a tag to compare

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 concurrent init, 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

09 May 13:07
ea21d01

Choose a tag to compare

First minor release on top of 0.1.13.

Highlights

  • Multi-instance registry~/.forgeplan-web/instances.json + /api/instances endpoint + HealthBar instance switcher (PRD-027 / RFC-023 / SPEC-003 / ADR-004).
  • init --scope user|project — workspace-agnostic user scope at ~/.forgeplan-web/; start falls 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 into cli/, commands/, lib/ (ADR-003).
  • Feature-flag + image systeminit --image stable|nightly, build-time lifecycle validator, per-image smoke. Bundle approach is now the universal artifact form for every dist*/. --experimental is 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), Combobox primitive in shared/ui/, adapter-node precompress disabled (smaller tarball).

Breaking changes

Only relevant if you depend on internals:

  • dist-experimental/ directory in the published tarball is replaced by dist-nightly/. Users running npx @forgeplan/web init see no change; consumers that pinned the directory name in scripts must switch to dist-nightly/.

See CHANGELOG.md for the full set of entries.

v0.1.13

08 May 13:06
61cbcb9

Choose a tag to compare

Added (PRD-018 / RFC-016 — shared/ui catalogue)

  • shared/ui/ primitives based on bits-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 via svelte-sonner), and command
    palette (Command + Item family).
  • /playground showcase 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/ui ownership and customisation discipline
    (.claude/rules/24-shared-ui-ownership.md). Forbids :global()
    re-skins of primitive internals from entities/ / 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)

  • orch theme — 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, HomePage error-bar, filter chips, HealthBar
    theme-switcher and notify, InsightsRail tab badges and R_eff
    bars, ArtifactPanel kind chip and ghost buttons.

Reverted

  • Force 3D experimental Threlte view mode (#103) — reverted in
    #105. The dist-experimental/ cap stays at 6M for now.

v0.1.12

06 May 21:57
93ce167

Choose a tag to compare

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 --experimental flag — opt-in to esbuild single-file bundle, ~9× smaller dist-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

06 May 11:37
fb468d1

Choose a tag to compare

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 on nodes.length > 0.

Verify

  • svelte-check 0/0/440.
  • vitest 81/81.
  • 3-OS smoke matrix green on PRs #50, #51.

Full changelog: v0.1.10...v0.1.11

v0.1.10

06 May 11:13
687a6d9

Choose a tag to compare

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 at k=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: onViewState callback 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

06 May 10:54
0884303

Choose a tag to compare

F15 — bug-fix release responding to user-reported issues on a real 289-artifact workspace.

CRITICAL

  • each_key_duplicate runtime crash fixed. lib/filter.ts#filterEdges now 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)). bodyHydrated guard race-safe against the new default overwriting stored '0' before reader-effect.
  • .ghost button 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 activeStickyKey state: only one block sticky at a time; earlier blocks get position: static so a shorter active block doesn't leave a taller previous one visible underneath. When body-actions becomes the active sticky, depth and updated_at from 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-body and .links ul lost max-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