feat: add extractBoardContext slug extraction utility #108
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/pal-e-app!108
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "107-feat-extractboardcontext-slug-extraction"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Implements pure function utility to extract architecture and user story slugs from board note content blocks. Foundational work for enriched board renderer (#104).
Changes
src/lib/board-context.ts-- new file with extractBoardContext function and BoardContextData interfaceTest Plan
npm run checkpasses with no errorsReview Checklist
Related Notes
PR #108 Review
DOMAIN REVIEW
Stack: SvelteKit 5 (runes), TypeScript, CSS custom properties, Mermaid.js
Correctness issues found:
BUG: Arch filter matches ANY arch label, not the selected one (
+page.svelteline 58)This checks whether the item has any
arch:label, not whether it has a label matching the specificactiveArchSlug. If a board has items witharch:fooandarch:bar, clicking thearch-foothumbnail shows both. The fix is:Anti-pattern:
$derived(() => ...)should be$derived.by(() => ...)(ArchThumbnail.sveltelines 16-29,BoardContext.sveltelines 28-33)$derived(() => expr)stores the arrow function as the derived value, then the template calls it withderivedFacet().$derived.by(() => expr)is the correct form for multi-statement derived values.$derived(expr)is correct for single expressions (as used correctly inStoryCard.svelteline 15).Semantic HTML:
<a>nested inside<button>(ArchThumbnail.sveltelines 77-81)<a>element inside a<button>violates HTML spec (interactive content cannot nest inside interactive content). Screen readers and keyboard navigation will behave unpredictably.<div role="button" tabindex="0">or moving the link outside the button.Things done well:
extractBoardContextcorrectly parses section boundaries using heading level comparison (lines 28-31).<code>arch-*</code>and<a href="/notes/arch-*">patterns with deduplication.loadBoardContextis correctly fire-and-forget (line 83) -- board loads fast, context loads asynchronously without blocking.loadBoardContextgracefully falls back to empty arrays (lines 123-126).MermaidBlock.svelte(dynamic import, initialize, render, innerHTML).BoardContextis collapsed by default (good UX for boards where context is secondary).BLOCKERS
No test coverage for
board-context.ts-- This is a pure utility module with three parsing functions (extractBoardContext,extractArchData,extractStoryData). Pure functions with complex regex parsing and section-boundary logic are the easiest code to unit test and the most important to cover. This is new functionality with zero tests. BLOCKER per review criteria.Arch filter bug --
itemMatchesContextFilterdoes not filter by the selected arch slug. It passes any item with anyarch:label. This defeats the purpose of clicking a specific architecture thumbnail to filter. Must fix.Nested interactive elements --
<a>inside<button>inArchThumbnail.svelteis invalid HTML. Accessibility tools will report this. Screen readers may skip the link entirely or double-announce the element.NITS
$derived(() => ...)vs$derived.by(() => ...)-- works but is wrong idiom. Fix in ArchThumbnail (lines 16, 23) and BoardContext (line 28).getBlockHtmlfor list blocks (board-context.ts line 64) usesJSON.stringify(block.content)-- this means the regex on line 37-40 would need to match against JSON-serialized content. If list items contain arch slugs in their HTML, the<code>andhrefregexes would still match inside the JSON string, but this is fragile. Consider extracting list item HTML directly fromblock.content.items.Hardcoded facet colors in
ArchThumbnail.sveltelines 25-28 (#3b82f6,#8b5cf6,#f59e0b). These should use CSS custom properties for theme consistency. The rest of the codebase usesvar(--color-*)tokens.The
facetprop is passed as empty string""from BoardContext (line 57) and never populated. IfderivedFacetslug-sniffing logic does not match, it falls through tofacet || 'Architecture'which always returns'Architecture'since facet is always empty. The prop exists but is dead. Either populate it from data or remove it.-webkit-line-clamp(StoryCard.svelte line 99) -- works in all modern browsers but the-webkit-prefix suggests legacy. The unprefixedline-clampis now a standard property in CSS Overflow Level 4.SOP COMPLIANCE
107-feat-extractboardcontext-slug-extractionfollows{issue-number}-{kebab-case}conventionboard-context.tsextraction utility, but the branch includes 4 additional component files and page integration. The description should be updated to reflect the full scope.PROCESS OBSERVATIONS
board-context.tsis highly testable pure logic. Adding vitest (or whatever test runner the project uses) with unit tests for the three extract functions would take minimal effort and catch regressions in the regex parsing.VERDICT: NOT APPROVED
Three blockers must be fixed:
extractBoardContext,extractArchData, andextractStoryDataarch:label<a>inside<button>in ArchThumbnail (invalid HTML, accessibility violation)Updated: Full Board-Context Renderer Implementation
This PR now contains the complete board-context renderer feature (10 commits):
Components Added
src/lib/board-context.ts—extractBoardContext,extractArchData,extractStoryData,extractComponentsutilitiessrc/lib/components/StoryCard.svelte— story summary card with AC progress barsrc/lib/components/ArchThumbnail.svelte— architecture diagram thumbnail with mermaid previewsrc/lib/components/BoardContext.svelte— collapsible context header containersrc/lib/board-context.test.ts— 11 assertions covering all extraction functionsIntegration
src/routes/boards/[slug]/+page.svelte— BoardContext wired above kanban, context filtering, dimmingCode Review Fixes
<button><a>replaced with<div role="button">for a11yStory
story:board-context-renderer— Superuser can open a board and see architecture diagrams + user stories above the kanban.Spec
docs/superpowers/specs/2026-04-12-board-centric-renderer-design.md