Skip to content

feat(types): normalized data model — primitives, entities, store, migrations, player view#254

Open
kocheck wants to merge 124 commits intomainfrom
data-model/implementation
Open

feat(types): normalized data model — primitives, entities, store, migrations, player view#254
kocheck wants to merge 124 commits intomainfrom
data-model/implementation

Conversation

@kocheck
Copy link
Copy Markdown
Owner

@kocheck kocheck commented Mar 19, 2026

Summary

  • Normalized entity tables: flat Record<BrandedId, Entity> tables for O(1) access; MapData holds only ID arrays, no nested objects
  • New types module: primitives.ts, entities.ts, store.ts, player-view.ts, features.ts, migrations.ts — replaces the monolithic domain.ts (kept as backward-compat re-export shim with deprecated legacy types)
  • Migration pipeline: migrateCampaign upgrades v0 (nested arrays) → v1 (flat tables); pure functions, typed narrowing, no as any on main path
  • Player view sync layer: derivePlayerView filters hidden entities, resolves attached light positions, strips exploredRegions — memoization-ready pure function
  • Feature flags: FeatureFlags interface + DEFAULT_FEATURE_FLAGS in uiStore (runtime-only, not persisted)
  • domain.ts shim: deprecated Stairs, Campaign, LegacyCampaignMap, TokenMetadata re-exported with @deprecated JSDoc for gradual migration

Test Plan

  • npm run test:run — 1050 tests, 0 failures
  • npm run type-check — no type errors
  • npm run lint — no lint errors
  • Verify domain.ts consumers still compile (shim re-exports all prior public types)
  • Load an existing v0 save file — migrateCampaign should upgrade it to v1 without errors

claude and others added 30 commits February 9, 2026 14:33
Complete codebase audit (24 findings) and 30 modularization recommendations
covering visual framework separation, logic modularization, testing
infrastructure, performance and accessibility hardening, and repo cleanup.
13-session execution plan with per-task specs, acceptance criteria, and
dependency ordering. This serves as the persistent roadmap for incremental
refactoring across multiple sessions.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
…timize icon

- Delete 5 dead Vite boilerplate files (App.css, react.svg, 3 public SVGs)
- Gate FogOfWarLayer diagnostic logging behind DEBUG_VISION flag
  (was ~40 lines of console.log firing on every render in dev mode)
- Optimize icon.png from 927KB to 72KB (512x512, 128-color quantized)
- Add coverage/ to .gitignore (generated reports shouldn't be tracked)
- Document test coverage baseline in CLAUDE.md session notes:
  33% statements, 27% branches, 40% functions across 792 passing tests

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
…action

- Consolidate root docs: delete duplicate ARCHITECTURE.md, move 8 docs to
  docs/ subdirs (guides/, features/, architecture/, planning/)
- Move diagnose-dungeon.ts to tests/helpers/, update tsconfig.json
- Update all internal cross-references across moved docs

- Create 4 component subdirectories: ErrorBoundaries/, Dialogs/, Managers/, Mobile/
- Move 32 files (17 error boundaries, 6 dialogs, 6 managers, 3 mobile)
- Update ~35 import paths in consumer files and moved files
- Fix vi.mock() paths in test files, fix import ordering via eslint --fix

- Extract 14 domain types + 2 constants from gameStore.ts to src/types/domain.ts
- gameStore.ts re-exports all types for backward compatibility
- Update IStorageService.ts to import from types/domain per architecture contract

All 792 tests pass. Zero TypeScript errors. Zero lint errors. Build succeeds.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
… contrast

- Add ~120 CSS custom properties to theme.css covering canvas, doors, stairs,
  minimap, measurement, touch, tokens, walls, toolbar, monitor, home, dialogs,
  error boundaries, logo, and library categories with dark-mode variants
- Sweep 20+ component files replacing hardcoded hex/rgba values with theme tokens;
  use *_COLORS constant objects for Konva canvas components (can't use CSS vars)
- Remove 7 redundant Radix dark-mode CSS imports (values already declared in
  [data-theme='dark'] block)
- Scope global * transition rule to specific UI classes + .themed-transition opt-in
- Add @media (prefers-contrast: more) block for WCAG 2.2 AA high-contrast support
- Create brand.css configuration layer for single-file rebranding (accent colors,
  fonts, logo paths)

All 792 tests pass. TypeScript 0 errors. Build succeeds.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
Create the design system primitive layer (src/components/primitives/):

- Button: 5 variants (primary, secondary, ghost, destructive, tool),
  3 sizes (sm, md, lg), isActive/isLoading/leftIcon/rightIcon support,
  focus-visible ring, aria-disabled/aria-busy attributes
- Input: label, error state with role="alert", helper text, aria-invalid,
  auto-generated IDs via useId()
- Card: 3 variants (surface, elevated, outlined), configurable padding
- ToggleSwitch: moved to primitives/ with re-export at old path

Add primitives.css with all component styles using theme tokens.
Migrate 7 buttons across 3 files (ConfirmDialog, DoorControls,
MapSettingsSheet) as proof-of-concept. Update DesignSystemPlayground
to showcase all new primitives.

All 792 tests pass. TypeScript 0 errors. Build succeeds.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
- Create Dialog primitive with full a11y: focus trap (Tab/Shift+Tab),
  Escape/overlay-click to close, auto-focus on open, return-focus on close,
  scroll lock, aria-modal/labelledby/describedby, 4 size variants,
  prefers-reduced-motion support
- Migrate ConfirmDialog and PreferencesDialog to use Dialog primitive,
  eliminating duplicate overlay/keyboard/focus handling
- Extract 1,032 lines of inline <style> from HomeScreen.tsx to
  src/styles/home-screen.css — HomeScreen drops from 1,776 to 745 lines
- JS bundle drops 26KB (912KB→886KB) since CSS string no longer in JS

All 792 tests pass. TypeScript 0 errors. Build succeeds.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
…t boundaries

Install eslint-plugin-jsx-a11y and fix 74 accessibility violations across 15 files.
Upgrade 5 TypeScript rules from warn to error (no-explicit-any, no-misused-promises,
no-unsafe-member-access, no-unsafe-call, no-unsafe-assignment) after fixing ~115
violations. Add import/no-restricted-paths enforcing Design System Contract boundaries.
Add ExposedIpcRenderer type to window.d.ts for typed IPC access.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
Created src/store/uiStore.ts with all UI ephemeral state (toast, confirmDialog,
showResourceMonitor, dungeonDialog, isGamePaused, isMobileSidebarOpen,
isCommandPaletteOpen) extracted from gameStore. gameStore is now domain-pure
(607 lines, down from 836). Migrated 23 source files and 9 test files.
SyncManager subscription no longer fires on UI state changes.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
…ic hooks

Extracted 4 pure functions (calculateVisibilityPolygon, castRay,
lineSegmentIntersection, getWallSegments) from FogOfWarLayer.tsx to
src/utils/vision.ts — zero React/Konva dependencies, 100% test coverage
(26 tests). Created useRecentCampaigns and usePlatformDetection hooks
to remove direct localStorage/navigator access from HomeScreen.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
- useToolState: tool selection, colors, door orientation, measurement mode, keyboard shortcuts
- useMenuCommands: Electron IPC menu handler registration (save/load/new/about)
- useLibraryLoader: token library index loading on startup
- campaignService: save/load/new campaign orchestration (zero React imports)
- Toolbar component: extracted desktop toolbar JSX from App.tsx
- App.tsx reduced from 770 to 283 lines (63% reduction)

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
Extract keyboard, drop, selection, and drawing concerns from the 1,892-line
CanvasManager into focused, testable hooks. Extract door context menu into
a standalone component. CanvasManager reduced to 1,450 lines (23% reduction).

New files:
- useCanvasKeyboard.ts: keyboard shortcuts + modifier key state
- useCanvasDrop.ts: file/token drop handling + image crop flow
- useCanvasSelection.ts: selection rect, transformer, hover tracking
- useCanvasDrawing.ts: drawing refs/state (isDrawing, tempLine, etc.)
- DoorContextMenu.tsx: right-click door actions (open/close/lock/delete)

Also: gate diagnostic logging behind DEBUG_CANVAS flag, fix production
console.log leak, remove stray DoorLayer render log.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
Lazy-load 5 infrequent components with React.lazy, reducing main bundle
from 891KB to 810KB (gzip 259KB → 238KB, 9% reduction). Add Konva
performance budget: pixelRatio capped at 2 (1 on low-end devices detected
via deviceMemory/hardwareConcurrency), explored fog regions cached at
Konva level to avoid re-executing sceneFunc on unchanged regions.

Lazy chunks: DesignSystemPlayground (46KB), DungeonGeneratorDialog (12KB),
UpdateManager (11KB), CommandPalette (8KB), ResourceMonitor (6KB).

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
… focus indicators

Add CanvasAccessibility component with screen reader announcements for token,
door, and tool state changes. Enable keyboard token navigation (Tab to cycle,
Enter to activate, Arrow keys to move by grid cell). Add skip-to-content link,
landmark roles (nav/main), visible :focus-visible indicators on all interactive
elements, and keyboard-accessible sidebar token items with tabIndex/role/aria-label.
Fix MapNavigator and Sidebar edit buttons to show on focus-within (not hover-only).

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
All extracted modules now have comprehensive unit test coverage:
- uiStore (100%), campaignService (100%), vision (100% — existing)
- useToolState (94%), useMenuCommands (96%), useRecentCampaigns (100%)
- Button (100%), Dialog (92%), Input (100%)
Total: 969 tests passing across 48 test files.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
- useToolState: wrap DOM element tests in try/finally to prevent leak on failure
- Button: add icons.length guard, use toHaveClass instead of toContain
- Dialog: remove unused queryDialog, document aria-hidden pattern
- campaignService: suppress expected console.error in error-path tests

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
- useToolState: Hoist vi.fn() refs to module scope so gameStore selectors
  return stable identity (prevents spurious useEffect re-fires). Add test
  verifying setActiveMeasurement(null) on mode change.
- useRecentCampaigns: Replace mockReturnValueOnce with mockReturnValue for
  mount-phase mocks (StrictMode double-invokes useState initializers).
- Dialog: Add auto-focus tests with rAF mocking (first focusable, closed
  dialog no-op) and focus-restoration tests (return focus to trigger on close).

975 tests passing, 48 test files.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
- Remove all backward-compat type re-exports from gameStore.ts (ADR-005
  cleanup). Migrate 25+ files to import domain types from types/domain
  directly instead of gameStore.
- Delete ToggleSwitch.tsx re-export shim (0 consumers remained).
- Move MapSettingsSheet to import ToggleSwitch from primitives/.
- Move 6 loose docs from docs/ root to proper subdirectories
  (features/, guides/, planning/). Fix cross-reference in
  HYBRID_TESTING_WORKFLOW.md.
- Update CHANGELOG.md with comprehensive modular architecture refactor
  summary covering all 13 sessions.
- Clean unused type imports from gameStore.ts (TokenMetadata, ToastMessage,
  ConfirmDialog).

975 tests passing, TypeScript 0 errors, ESLint 0 errors.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
Fix gridColor not persisting across map switch/create/delete/IPC sync,
keyboard trap in canvas accessibility widget (WCAG 2.1.2), Dialog focus
trap edge case, Object URL memory leak, stale Konva cache, dead code,
CSS layout mismatch, missing ARIA labels, and wire keyboard token placement.

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
- README.md: Coverage badge 100% → 36% to match actual coverage
- CONTRIBUTING.md: Update project structure with new directories
  (Dialogs/, ErrorBoundaries/, Managers/, Mobile/, primitives/,
  hooks/, services/, styles/, types/) and document store split
  (gameStore + uiStore) and campaignService
- CLAUDE.md: Update Quick Reference line counts to match actual
  file sizes after Sessions 12-14

https://claude.ai/code/session_012fJP8VEtRL2fj1Fdgo6aEV
…lity, and add tests (#252)

* Initial plan

* Fix PR review issues: import paths, memory leaks, asset pipeline, accessibility

- Fix DoorBlocking.test.ts import paths (../types → ../../types)
- Revoke existing object URL before creating new one in useCanvasDrop
- Use asset pipeline (processImage) instead of base64 for cropped images
- Improve CommandPalette keyboard accessibility (tabIndex={0} + aria-activedescendant)
- Gate arrow key movement in World View in CanvasAccessibility

Addresses feedback from PR #251 review thread.

Co-authored-by: kocheck <7952000+kocheck@users.noreply.github.com>

* Add comprehensive unit tests for useCanvasDrop hook

- Test drag over behavior (World View blocking)
- Test library token drop
- Test generic token drop
- Test file drop and object URL creation
- Test object URL revocation on multiple drops (memory leak prevention)
- Test crop confirm with asset pipeline integration
- Test crop confirm error handling
- Test crop cancel cleanup

12 tests covering all main branches and edge cases.
Addresses Issue #6 from PR review thread.

Co-authored-by: kocheck <7952000+kocheck@users.noreply.github.com>

* Fix async handler linting error in CanvasManager

Wrap handleCropConfirm with void operator to satisfy TypeScript linter
when passing async function to prop expecting void return.

Co-authored-by: kocheck <7952000+kocheck@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kocheck <7952000+kocheck@users.noreply.github.com>
- Rewrote CLAUDE.md (1,904 → 133 lines): commands, architecture tree,
  design system contract table, key files, gotchas & patterns, doc links
- Created docs/planning/REFACTOR_SESSIONS.md (868 lines): full historical
  archive of 14-session modular refactor (task specs, checklists, session
  notes, ADR-001 through ADR-005)
- Appended 5 refactor ADRs to docs/architecture/DECISIONS.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… 100+ files

- Run npm install to restore missing eslint-plugin-jsx-a11y dependency
- Fix all 822 ESLint warnings across entire codebase (8 sessions of accumulated debt)
- Fixes by category: explicit-function-return-type (220), no-non-null-assertion (99),
  no-console eslint-disable (78), prefer-nullish-coalescing (75), no-explicit-any (27),
  nested-ternary (16), prefer-optional-chain (14), import/no-unused-modules, and misc
- Fix SyncManager throttle generic constraint (any[] → proper generic)
- Fix all error boundary render() return types (JSX.Element → ReactNode)
- npm run lint, type-check, test:run, build:web all pass

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove leftover debug console.log from syncUtils.ts detectChanges() —
  was suppressed with eslint-disable rather than deleted
- Fix SyncManager.tsx:353-354 || [] → ?? [] for consistency with rest of file

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…llowing

Replace empty .catch(() => {}) with console.warn so theme storage errors
are observable in development and production diagnostics. The storage
service already returns a safe 'system' fallback internally, so this
catch only fires on truly unexpected errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SyncManager:
- Replace removeAllListeners() with named listener refs + ipcRenderer.off()
  so cleanup only removes this effect's listeners, not all channel listeners
- Guard BroadcastChannel messages against unknown action types using
  VALID_SYNC_ACTIONS set before casting to SyncAction

WebStorageService:
- Add reject() to loadCampaign() Promise constructor — previously throw
  inside async onchange callback produced an unhandled rejection and left
  the outer Promise permanently pending on parse errors

AutoSaveManager:
- Show error toast when auto-save returns false so users know their
  progress may not be saved, instead of silently logging to console only

DungeonGenerator:
- Replace default: break in 7 Direction switch statements with
  throw new Error() so unexpected direction values surface immediately
  instead of leaving !-asserted variables uninitialized

pathOptimization:
- Replace ?? 0 / ?? {x:0,y:0} silent fallbacks with explicit guards
  and console.warn so out-of-bounds array access is visible in diagnostics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ty issues

syncUtils.ts:
- Export SYNC_ACTION_TYPES as Set<SyncAction['type']> so it stays
  type-checked against the union (no manual string maintenance)
- Export isSyncActionType() type guard for narrowing unknown strings

SyncManager.tsx:
- Use isSyncActionType() instead of local VALID_SYNC_ACTIONS Set
- Add listenerSetupRef guard to Architect branch to match World View
  branch — prevents duplicate IPC listeners on React StrictMode re-runs

WebStorageService.ts:
- Add input 'cancel' event handler so loadCampaign() Promise resolves
  null when user dismisses the file picker (was hanging forever)

AutoSaveManager.tsx:
- Show toast in catch block too — thrown exceptions now surface to
  the user, not just WebStorageService false return

pathOptimization.ts:
- Replace unreachable undefined guards in rdpRecursive with ! assertions
  and eslint-disable comments (length >= 3 is guaranteed by caller guard)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Captures approved color system (Radix Sand), typography scale,
Remix icon mapping, responsive breakpoints, and rules for
Torchlit (amber) and Arcane Codex (violet) variations.
Covers HexColor/PixelSize branded types, createGridGeometry graceful
fallback, and campaign-load validation boundary.
kocheck and others added 27 commits March 17, 2026 16:52
…PixiJS

Rewrites both overlay components from react-konva to the PixiJS v8
imperative pattern (worldContainer + containerRef + useEffect), matching
the pattern established by DoorLayer, StairsLayer, and other Phase 5 layers.

- MeasurementOverlay: ruler (line+label), blast (circle+dot+label), and
  cone (poly+dot+label) shapes drawn with PixiJS Graphics + Text;
  zIndex 150; parseRgba helper converts CSS rgba/hex strings to PixiJS numbers
- MovementRangeOverlay: BFS flood-fill logic unchanged; each reachable cell
  drawn as a closed polygon via Graphics.poly(); zIndex 140
- Both test files rewritten using vi.hoisted + vi.mock pattern (no WebGL needed)
- CanvasManager: wires MeasurementOverlay; MovementRangeOverlay kept as TODO
  import until token-selection context is available in a future phase
…to MovementRangeOverlay

- Create src/utils/pixiColor.ts with parseRgba (fixes /./g → /[0-9a-fA-F]/g bug in 3-digit hex expansion)
- Add src/utils/pixiColor.test.ts with 5 cases covering hex, 3-digit hex, rgba, rgb, and invalid fallback
- Update MeasurementOverlay and MovementRangeOverlay to import from utils and remove local copies
- Add named export `export function MovementRangeOverlay` alongside existing default export
… packages

Delete 5 dead-code files (DoorShape, StairsShape, URLImage, CanvasUtils,
useCanvasInteraction) — all replaced by PixiJS equivalents with no live imports.

Remove react-konva import from TokenErrorBoundary; replace canvas indicator
with auto-shown DOM Portal overlay in dev mode, removing showDebugOverlay
toggle state and TOKEN_ERROR_COLORS constant.

Remove vi.mock('react-konva') block from test setup — no longer needed.

Remove Konva migration ESLint override from .eslintrc.cjs — permanent
no-restricted-imports guardrail now enforced across all files.

Uninstall konva, react-konva, use-image packages.

Zero konva/react-konva imports remain in src/. 1005 tests pass.
…nager

- Consolidate drawRuler/drawBlast/drawCone params into DrawStyle object (max-params)
- Replace non-null assertions in strokeGeometry.ts and PressureSensitiveLine.tsx with safe guards (no-non-null-assertion)
- Add eslint-disable-next-line import/no-unused-modules to all public-API exports, test helpers, and not-yet-wired layer components
- Add eslint-disable-next-line react-refresh/only-export-components to buildGridGeometry in GridOverlay.tsx
- Add eslint-disable comments to glsl.d.ts ambient module declarations
- Remove stale TODO comments referencing deleted files useCanvasInteraction, URLImage, and TokenErrorBoundary import from CanvasManager.tsx
…, hexToRgbFloats; pre-allocate uniforms; remove dead props

- Extract usePixiContainer hook (hooks/usePixiContainer.ts) and replace
  duplicated mount/unmount useEffect in DoorLayer, StairsLayer,
  MeasurementOverlay, and MovementRangeOverlay
- Extract clearContainer to src/utils/pixiUtils.ts; replace all
  container.removeChildren().forEach(c => c.destroy({children:true})) calls
- Add hexToRgbFloats to pixiColor.ts; remove private hexToRgb copy from
  PressureSensitiveLine
- Pre-allocate _lightsA/_lightsB Float32Arrays in FogOfWarFilter as instance
  fields; reuse with fill(0) on every updateLights call
- Remove dead isWorldView prop from StairsLayerProps and CanvasManager callsite
- GridOverlay: replace parseInt hex parse with parseRgba(gridColor).color
- MovementRangeOverlay: return geometry from useMemo to eliminate double
  createGridGeometry call; add geometry to useEffect deps
- TextureCache: remove resolved promises from inFlight map via .finally() so
  it tracks only truly in-flight loads
Replace clearContainer + full rebuild with a Map<string, Graphics> ref.
Stairs are static elements — only add/remove logic needed. Exports
stairsKey() pure function and clears the map on worldContainer change
to avoid stale refs.
…irsKey export

Add worldContainer to the stairs effect dependency array so the diff loop
re-runs when usePixiContainer swaps the container, preventing the new
container from remaining empty until stairs itself changes.

Remove the stairsKey export (a one-liner alias for stair.id) along with its
two eslint-disable comments and the test file that existed solely to cover it.
Remove the unused default export as well.
Update package-lock.json to reflect upgraded dev dependencies: flatted 3.4.2 and tar 7.5.11. Resolved URLs and integrity hashes were updated in the lockfile.
… screen

The package uses dynamic require('url') which crashes Vite's ESM renderer
in dev mode, preventing React from mounting (white screen). The Transformer
was a Phase 2 feature targeting PixiJS v6 with as-any casts — not functional
with v8. Will reimplement with a v8-native solution later.
Fix remaining strict-mode issues in plan code blocks:
- Use Record<string, unknown> instead of `as any` for import.meta.env mutation in DEV-warn test
- Use typed narrowing chain instead of `as any` for campaign.version access in migrateCampaign
Implements the player view sync layer: strips exploredRegions, filters hidden
entities, resolves attached light positions from tokens, and suppresses lights
whose parent token is hidden. 14 tests, all passing.
Adds tests for migrateDrawings (pressures/x/y/scale defaults) and
migrateDoors (mapId/hidden/thickness/swingDirection defaults), plus a
guard asserting MIGRATIONS table has exactly one entry at CURRENT_VERSION=1.
@github-actions
Copy link
Copy Markdown

📚 Documentation Check (Rule-Based)

This PR was analyzed for potential documentation impacts.

🔌 IPC Changes Detected

Files in electron/ or IPC-related code were modified.

Please review:

Check if you need to:

  • Document new IPC channels with usage examples
  • Update IPC handler documentation
  • Add JSDoc to new IPC-related functions

⚛️ Component Changes Detected

Files in src/components/ were modified.

Please review:

Check if you need to:

  • Add JSDoc to new components/functions
  • Update component descriptions in README
  • Document new props/interfaces

🗄️ State Management Changes Detected

Files in src/store/ were modified.

Please review:

Check if you need to:

  • Document new state properties
  • Update action/mutation documentation
  • Add examples for new state usage

🛠️ Utility Changes Detected

Files in src/utils/ were modified.

Please review:

  • src/utils/README.md - If utilities added/changed
  • Modified utility files - Ensure JSDoc is complete

Check if you need to:

📦 Dependencies Changed

package.json was modified.

Please review:

Check if you need to:

  • Document why new packages were chosen
  • Update tech stack overview
  • Add to preferred patterns if new utility library

📖 Documentation Standards

All changes should follow Hyle's documentation standards:

  1. JSDoc for all functions - Include @param, @returns, @example
  2. Cross-references - Use file:line format (e.g., App.tsx:89)
  3. Examples in JSDoc - Real, runnable code examples
  4. Update relevant READMEs - If component/directory structure changed
  5. Document "why" - Not just "what", explain rationale

Complete documentation guide: DOCUMENTATION.md

Rule-based check • For AI-powered analysis, see documentation-check.yml

@github-actions
Copy link
Copy Markdown

📚 Documentation Check

GitHub Copilot has analyzed this PR for documentation impact.

null


📝 Documentation Files Reference

Root docs: View all

See DOCUMENTATION.md for complete documentation inventory.

Powered by GitHub Copilot • Documentation Guide

@github-actions
Copy link
Copy Markdown

❌ Accessibility Audit Failed

This pull request introduces WCAG AA contrast violations. Please fix the following issues before merging:

See uploaded report for details.

Resources

Reminder: Always use semantic CSS variables (e.g., --app-text-primary) instead of raw color values.

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.

3 participants