release: v0.1.9 — F15 bug-fix release#45
Merged
Merged
Conversation
## Summary Back-merge of `release/v0.1.8` (now merged into `main`, tagged `v0.1.8`, published to npm with provenance) into `develop` so the version bump and any release-only commits don't get lost. Per [`guides/GIT-FLOW-GUIDE.ru.md`](guides/GIT-FLOW-GUIDE.ru.md) §6.10. ## What's in this back-merge - `a3d94b6` — `chore(release): bump version to 0.1.8` - `6a8a073` — release PR #42 merge commit (already on main, tagged v0.1.8, npm published). No new code changes — release was already QA'd through PR #42 (3-OS smoke matrix green, npm publish workflow success). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Five bug-fixes + UX refinements landed in one PR.
CRITICAL (each_key_duplicate runtime crash on real workspaces):
- lib/filter.ts: filterEdges now dedupes by composite key
`${from}>${to}:${relation}`, keeping first occurrence. Workspaces
with legitimately duplicate edges (two evidences with same relation
on same target) no longer crash Force/Tree/Radial/Lanes/Matrix.
- 4 unit tests added (visibility filter, exact dedup, relation
preservation, dedup-after-filter ordering).
HealthBar readability:
- Chip wrapper: <strong class="chip-value">{n}</strong>
<span class="chip-label">{label}</span>. Tabular-nums on values,
uppercase 0.12em letter-spacing on labels. "30 TOTAL · 27 ACTIVE"
reads cleanly instead of mashed "30TOTAL27ACTIVE...".
ArtifactPanel:
- Default width 380 → 658px (+73%). MAX_RATIO 0.6 → 0.7.
- 4px drag handle on left edge. PointerEvent-based; ArrowLeft/Right
keyboard; persisted to localStorage.forgeplan-web.panelWidth.
- "📋 Copy as markdown" moved from .impact-actions to new
.body-actions row alongside "+ Show body / − Hide body".
- bodyExpanded default true. bodyHydrated guard race-safe against
the new default overwriting stored '0' before reader-effect.
- Removed inner overflow on .artifact-body and .links ul. The
panel itself scrolls; no nested scrollbars.
- .ghost rule added inside ArtifactPanel (was missing — buttons
rendered as browser-default). Mono uppercase, accent on hover /
aria-expanded=true.
Page-level:
- .root { overflow: hidden } — no horizontal/vertical scroll on
the page shell.
Static:
- template/static/.well-known/appspecific/com.chrome.devtools.json
= {}. Suppresses Chrome 132+ devtools probe 404.
Verify:
- svelte-check 0/0/437.
- npm test 74/74 (70 baseline + 4 filter dedup tests).
- Playwright on http://127.0.0.1:5174/ — 0 console errors after
fix lands in template (user's running .forgeplan-web bundle is
pre-built; the fix takes effect on next `init --force` or after
release).
Refs: ad-hoc bug-fix
As the user scrolls the panel, each major section pins below the
header with a solid background and an escalating z-index — later
sections paint over earlier ones, producing a "previous block leaves
when next arrives" effect.
Layout:
- header z-index 1 → 10 (always on top of the sticky stack).
- impact-actions / meta / links / body-actions get class .sticky-row,
position: sticky; top: var(--header-h); background: var(--bg-1).
- z-index escalates 1→2→3→4 so visually only one block is "the one
pinned" at any scroll depth.
Meta-trail:
- New <span class="meta-trail"> in body-actions row, right-aligned
via margin-left: auto.
- Holds depth + updated_at (compact form: "DEPTH standard · UPD 06.05.2026").
- Visible only when scrollTop has reached body-actions sticky line:
`metaScrolledPast = panel.scrollTop + headerH + 8 >= bodyActionsEl.offsetTop`.
- 220ms opacity + translateX fade-slide. aria-hidden (canonical meta
block remains visible above for SR users until scrolled past).
- pointer-events: none — doesn't block button clicks.
Header height measured via ResizeObserver on bind:this={headerEl},
exposed as CSS var --header-h on .panel for sticky top calculation.
prefers-reduced-motion drops the trail transition.
Verify:
- svelte-check 0/0/437.
- npm test 74/74.
Refs: ad-hoc UX polish
) ## Summary Five bug-fixes + UX refinements reported by user on a real 289-artifact workspace. ### CRITICAL — each_key_duplicate runtime crash `Error: https://svelte.dev/e/each_key_duplicate` cascaded across Force / Tree / Radial / Lanes / Matrix views when the workspace had legitimately duplicate edges (two evidence packs both inform the same PRD with same relation; supersede chains; etc.). Root cause: `${from}>${to}:${relation}` not unique by construction. **Fix:** `filterEdges` in `lib/filter.ts` dedupes by composite key, keeping first occurrence. UI sees stable unique-key dataset. 4 new unit tests. ### HealthBar readability Chips were `289total177active...` — values+labels mashed. Now: `<strong class="chip-value">` (mono tabular-nums, 13px, var(--fg)) + `<span class="chip-label">` (10px uppercase 0.12em). Reads as "30 TOTAL · 27 ACTIVE · 3 DRAFT". ### ArtifactPanel - **Default width 380 → 658px** (+73%). PRD bodies now breathe. - **Drag-resize** on left edge. PointerEvent + setPointerCapture; ArrowLeft/Right keyboard; persisted in localStorage. Range [320px, 0.7×innerWidth]. - **"📋 Copy as markdown" moved** from `.impact-actions` (top) to new `.body-actions` row alongside `+ Show body / − Hide body`. Tighter visual grouping by purpose. - **Body section opens by default** (`bodyExpanded = true`). `bodyHydrated` guard race-safe against the new default overwriting stored `'0'` before reader-effect runs. - **No nested scrollbars** — dropped `max-height: 60vh; overflow-y: auto` on `.artifact-body` and `.links ul`. The outer `.panel` scrolls; the body content flows naturally. - **`.ghost` button rule** added locally in ArtifactPanel (Svelte scoped CSS in HomePage didn't reach the panel; buttons rendered as browser-default before). Mono uppercase, accent on hover / `aria-expanded="true"`. ### Page shell `.root { overflow: hidden }` — no horizontal/vertical scrollbars at the page level. All scroll happens inside individual panes. ### Devtools probe `template/static/.well-known/appspecific/com.chrome.devtools.json = {}`. Chrome 132+ probes this endpoint; we now respond 200 instead of 404. ## Verify - `npx svelte-check` — 0/0/437. - `npm test` — 74/74 (70 baseline + 4 filter dedup tests). - Playwright — 0 console errors after fix lands. ## Note for user The currently running `http://127.0.0.1:5174/` instance is a previously-built `.forgeplan-web/` bundle. After this PR merges and they run `npx @forgeplan/web init --force` (or after we cut `v0.1.9`), the crash disappears. Source-side it's already verified. ## Test plan - [ ] CI smoke matrix (3-OS × Node 22) green. - [ ] svelte-check clean on PR. - [ ] vitest 74/74. - [ ] Manual: load real workspace with duplicate edges → no console errors across all 7 views. - [ ] Manual: drag panel left edge → widens up to 70vw; reload → width persists. - [ ] Manual: open ArtifactPanel for any PRD → body markdown rendered immediately. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
F15 — bug-fix release responding to user-reported issues on a real 289-artifact workspace: - CRITICAL each_key_duplicate runtime crash on Force/Tree/Radial/ Lanes/Matrix views when workspace contains duplicate edges. Fixed via dedupe in lib/filter.ts#filterEdges. - HealthBar chips restructured for readability. - ArtifactPanel default width 380 → 658px (+73%) with drag-resize. - "Copy as markdown" moved to body-actions row next to Hide/Show. - Body section opens by default; bodyHydrated guards localStorage race. - Sticky-stack panel sections + meta-trail fade-slide into body-actions. - Page-level overflow hidden; no nested scroll containers. - Chrome 132+ devtools probe 404 suppressed. Refs: ad-hoc bug-fix
User reported: with sticky-stack, when active block was shorter
(body-actions, 40px) but a previous block was taller (links with
many items, 200px+), the bottom of the taller previous one was
visible *below* the active sticky. Both were pinned at the same
top: var(--header-h), and lower z-index didn't fully hide a taller
sibling underneath.
Fix: instead of relying on z-index escalation, track the **active**
sticky block via a scroll listener (`activeStickyKey` state). Each
sticky-row gets `class:passed` when a later row has reached the
sticky line — `.sticky-row.passed { position: static }` lets it
scroll away with normal content flow.
Result: only one block occupies the sticky line at any moment.
Previous taller blocks visibly leave when the next one arrives.
Outgoing / Incoming collapse:
- Each links subsection has its own toggle
(`+ N · Outgoing / − Hide`).
- Auto-collapsed when list length > 8 — prevents the panel from
visually exploding on hub artifacts (e.g. 50+ incoming edges
on a popular PRD).
- $effect keys on `id`, not length — user toggles survive the
10s poll re-deriving identical edge arrays.
Verify:
- svelte-check 0/0/437.
- npm test 74/74.
Refs: ad-hoc UX polish
explosivebit
added a commit
that referenced
this pull request
May 6, 2026
Back-merge of `release/v0.1.9` (now merged into `main`, tagged `v0.1.9`, published to npm with provenance) into `develop`. Per `guides/GIT-FLOW-GUIDE.ru.md` §6.10. Includes: - `0e115f2` `chore(release): bump version to 0.1.9` - `011982e` `fix(web): single-active sticky + Outgoing/Incoming collapse` - `0884303` release PR #45 merge commit (already on main, tagged v0.1.9, npm published). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
v0.1.9 — bug-fix release responding to user-reported issues on a real 289-artifact workspace.
CRITICAL (runtime crash)
each_key_duplicateruntime error cascaded across Force / Tree / Radial / Lanes / Matrix views when workspace contained legitimately duplicate edges (two evidence packs both informing same PRD with same relation). Fixed by deduplicating inlib/filter.ts#filterEdgesat the single chokepoint.UX
bodyHydratedguard..ghostbutton rule added inside ArtifactPanel (was missing — buttons were browser-default)..artifact-bodyand.links ullost theirmax-height: Xvh; overflow-y: auto. The outer panel scrolls..root { overflow: hidden }— no horizontal/vertical scroll on page level.Polish
template/static/.well-known/appspecific/com.chrome.devtools.json = {}.Verify
Test plan
v0.1.9annotated onmain, Draft GitHub Release → publish firesrelease.yml→npm publish --provenance.release/v0.1.9→develop.npx @forgeplan/web init --forceagainst the real 289-artifact workspace — crash gone, panel comfortable to read PRD bodies.🤖 Generated with Claude Code