Skip to content

release: v0.1.9 — F15 bug-fix release#45

Merged
explosivebit merged 7 commits into
mainfrom
release/v0.1.9
May 6, 2026
Merged

release: v0.1.9 — F15 bug-fix release#45
explosivebit merged 7 commits into
mainfrom
release/v0.1.9

Conversation

@explosivebit
Copy link
Copy Markdown
Contributor

Summary

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

CRITICAL (runtime crash)

  • each_key_duplicate runtime 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 in lib/filter.ts#filterEdges at the single chokepoint.
  • 4 unit tests added (visibility filter, exact dedup, relation preservation, ordering).

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.
  • "📋 Copy as markdown" moved into body-actions row next to Hide/Show body.
  • Body section opens by default with race-safe bodyHydrated guard.
  • .ghost button rule added inside ArtifactPanel (was missing — buttons were browser-default).
  • Sticky-stack panel sections + meta-trail — as user scrolls, each section pins below header with escalating z-index; the depth + updated_at values fade-slide into right side of body-actions when its sticky line is reached.
  • No nested scroll containers.artifact-body and .links ul lost their max-height: Xvh; overflow-y: auto. The 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).

Test plan

  • CI smoke matrix (3-OS × Node 22) green.
  • After merge: tag v0.1.9 annotated on main, Draft GitHub Release → publish fires release.ymlnpm publish --provenance.
  • Back-merge release/v0.1.9develop.
  • User runs npx @forgeplan/web init --force against the real 289-artifact workspace — crash gone, panel comfortable to read PRD bodies.

🤖 Generated with Claude Code

## 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 explosivebit merged commit 0884303 into main May 6, 2026
3 checks passed
@explosivebit explosivebit deleted the release/v0.1.9 branch May 6, 2026 10:53
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)
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