Skip to content

feat(web): F11 — body preview + decision impact drill-down (PRD-006/RFC-005)#36

Merged
explosivebit merged 2 commits into
developfrom
feature/web-utilities-f11
May 6, 2026
Merged

feat(web): F11 — body preview + decision impact drill-down (PRD-006/RFC-005)#36
explosivebit merged 2 commits into
developfrom
feature/web-utilities-f11

Conversation

@explosivebit
Copy link
Copy Markdown
Contributor

Summary

Implements PRD-006 + RFC-005. Two coupled UX improvements that turn @forgeplan/web from a "table of contents" into a "decision viewer":

Body preview

  • ArtifactPanel adds + Show body / − Hide body toggle revealing the full markdown body inline.
  • New widgets/artifact-panel/lib/markdown-renderer.ts uses marked (GFM) + DOMPurify (allow-listed tags). XSS-safe by construction.
  • 6 unit tests (basic markdown, <script> strip, javascript: href strip, GFM table preserved, task checkbox <input type="checkbox">, empty fallback).
  • bodyExpanded persisted per session in localStorage.

Decision impact drill-down

  • Show downstream / Show upstream / Clear buttons in ArtifactPanel.
  • New widgets/dependency-graph/lib/impact-graph.ts — pure BFS bounded by MAX_IMPACT_DEPTH=8, direction normalised via type-tier.ts#normaliseHierarchyEdge so informs / refines / belongs-to / contains / supersedes all flow abstract → concrete consistently.
  • 7 unit tests (chain, diamond, cycle, depth cap, non-hierarchy filter, upstream chain, symmetry).
  • highlight.svelte.ts extended with impactRoot / impactDirection $state + setImpactRoot / impactedClass exports. Dual-exposed via entities/graph and widgets/dependency-graph/lib.
  • 5 views (Force / Tree / Radial / Lanes / Matrix) wire impact map via $derived.by; outer SVG gets class:impact-mode; nodes get node-impact-root / node-impacted-near / node-impacted-far.
  • Sankey + Sunburst do NOT participate — their hierarchy semantics already cover this view.
  • Matrix applies impact class to row + col headers; cells (edges) skipped.

Visual treatment

  • node-impact-root: accent stroke 2px + drop-shadow.
  • node-impacted-near: opacity 1.
  • node-impacted-far: opacity 0.7.
  • impact-mode unaffected nodes: opacity 0.18.

Dependencies

  • runtime: marked@^18, dompurify@^3.
  • dev: @types/dompurify, happy-dom (vitest DOM env).

Verify

  • svelte-check 0/0/432 files.
  • npm test 53/53 (40 baseline + 13 new).
  • npm run smoke PASS.

Test plan

  • CI smoke matrix (3-OS × Node 22) green.
  • svelte-check clean.
  • vitest 53/53.
  • Manual: open ArtifactPanel for a PRD, click "+ Show body" — markdown renders. Click "Show downstream" — affected RFCs/EVIDs glow accent in graph.

Refs: PRD-006 RFC-005

🤖 Generated with Claude Code

Implements PRD-006 / RFC-005. Two coupled UX improvements that turn
@forgeplan/web from a "table of contents" into a "decision viewer".

Body preview:
- ArtifactPanel adds "+ Show body / − Hide body" toggle revealing the
  full markdown body of the selected artifact inline.
- New `widgets/artifact-panel/lib/markdown-renderer.ts` uses marked
  (GFM tables / code / checkboxes) + DOMPurify (allow-listed tags,
  no scripts, no javascript: URLs).
- 6 unit tests cover basic markdown, XSS strip, GFM tables, task
  checkboxes, empty-string fallback.
- bodyExpanded state persisted per session in localStorage.

Decision impact drill-down:
- "Show downstream" / "Show upstream" buttons in ArtifactPanel.
- New `widgets/dependency-graph/lib/impact-graph.ts` exports
  computeDownstream / computeUpstream pure functions, BFS bounded
  by MAX_IMPACT_DEPTH=8, direction normalised via
  type-tier.ts#normaliseHierarchyEdge so all hierarchy relations
  (informs / refines / belongs-to / contains / supersedes) flow
  abstract → concrete consistently.
- 7 unit tests cover linear chain, diamond, cycle, depth cap,
  non-hierarchy filter, upstream chain, downstream/upstream
  symmetry.
- highlight.svelte.ts extended with impactRoot / impactDirection
  $state fields; setImpactRoot() and impactedClass() exported.
  Dual-exposed via entities/graph and widgets/dependency-graph/lib
  for FSD layering.
- 5 views (Force / Tree / Radial / Lanes / Matrix) wire impact map
  via $derived.by; outer SVG gets `impact-mode` class; nodes get
  `node-impact-root` / `node-impacted-near` / `node-impacted-far`
  applied alongside existing `nodeClass(...)`. Sankey + Sunburst
  do NOT participate — their hierarchy semantics already cover
  the impact view.
- Matrix applies impact class to row + col headers (artifacts);
  cells (which represent edges) are skipped.

Visual treatment in app.css:
- node-impact-root: stroke var(--accent), stroke-width 2,
  drop-shadow(0 0 8px var(--accent)).
- node-impacted-near: opacity 1.
- node-impacted-far: opacity 0.7.
- impact-mode unaffected nodes: opacity 0.18.

Dependencies:
- runtime: marked@^18, dompurify@^3.
- dev: @types/dompurify, happy-dom (vitest DOM env for renderer test).

Verify:
- svelte-check 0 errors / 0 warnings / 432 files.
- npm test 53/53 (40 baseline + 13 new — 6 renderer, 7 impact-graph).
- npm run smoke PASS.

Refs: PRD-006 RFC-005
PRD-006 (Standard) — Web body preview + decision impact drill-down.
9 SC, 8 FR, 5 NFR, 5 risks. Targets code reviewer / stakeholder /
new team member personas. Bundle ≤ 80 KB tracked via NFR-001.
DOMPurify + CSP layered for XSS (NFR-003).

RFC-005 (Standard) — Markdown rendering + decision impact algorithm.
Pins marked + DOMPurify config, BFS depth cap (MAX_IMPACT_DEPTH=8),
direction normalisation via type-tier.ts#normaliseHierarchyEdge.
Sankey + Sunburst explicitly excluded from impact mode.

PRD-007 (Standard) — Web stale + blind-spot push notifications.
9 SC, 9 FR, 5 NFR, 5 risks. Browser Notification API only (no SW).
Privacy: only id + title in payload (NFR-002). Throttle 1 per 60s
per category. F12 implementation.

RFC-006 (Standard) — Notification permission UX + breach detection.
State machine for default / requested / granted / denied. Breach
categories: new blind_spot / stale_count delta / orphan_count delta.
notifyBus pattern for cross-scope click-handler routing.

All 4 validated: PRD-006/007 PASS (with non-blocking warnings),
RFC-005/006 PASS clean.

Refs: PRD-006 RFC-005 PRD-007 RFC-006
@explosivebit explosivebit merged commit b32d893 into develop May 6, 2026
3 checks passed
@explosivebit explosivebit deleted the feature/web-utilities-f11 branch May 6, 2026 03:04
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