--- phase: 08-pagination-quality-cache-performance plan: 01 type: execute wave: 1 depends_on: [] files_modified: - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererCache.swift autonomous: true requirements: - QUAL-01 must_haves: truths: - "Cache key struct exists that captures viewport + typography configuration" - "Cache lookup and store methods exist on the cache type" - "Build succeeds with new cache file in project" artifacts: - path: "Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererCache.swift" provides: "Cache key struct and cache manager stub" exports: ["RDEPUBTextRendererCache", "RDEPUBPaginationCacheKey"] key_links: - from: "Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererCache.swift" to: "RDEPUBDTCoreTextRenderer" via: "import (future wiring)" pattern: "RDEPUBTextRendererCache" --- Create the pagination cache infrastructure: a cache key struct that captures viewport dimensions and typography configuration, plus a cache manager stub with lookup/store/invalidate methods. This is the structural foundation that plan 08-02 and future work will wire into the actual rendering pipeline. Purpose: Prevents the same chapter from being fully re-typeset when viewport and typography config haven't changed (QUAL-01). Output: `RDEPUBTextRendererCache.swift` with cache key struct and manager stub. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/08-pagination-quality-cache-performance/08-CONTEXT.md @.planning/phases/08-pagination-quality-cache-performance/08-RESEARCH.md From Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift: - `RDEPUBTextChapterRenderRequest` — contains `style: RDEPUBTextRenderStyle`, `context` with baseURL - `RDEPUBTextRenderStyle` — has `font: UIFont`, `lineSpacing: CGFloat`, `textColor: UIColor?`, `backgroundColor: UIColor?` From Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift: - `RDEPUBTextRenderStyle` properties used in rendering: `font.pointSize`, `font.familyName`, `font.fontName`, `lineSpacing` Task 1: Create cache key struct and cache manager stub Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererCache.swift - Sources/RDReaderView/EPUBTextRendering/RDEPUBDTCoreTextRenderer.swift (understand render request and style types) - Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererSupport.swift (understand what configuration affects pagination output) Create `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererCache.swift` with: 1. `RDEPUBPaginationCacheKey` struct — captures the inputs that determine pagination output: - `chapterID: String` (unique chapter identifier, e.g. href or file path) - `viewportSize: CGSize` (the available page dimensions) - `fontDescriptor: String` (font family + name + pointSize, concatenated) - `lineSpacing: CGFloat` - `textColorHash: Int?` (hash of textColor, if present) - Implement `Equatable` conformance (auto-synthesize is fine) 2. `RDEPUBTextRendererCache` class: - `static let shared = RDEPUBTextRendererCache()` - `private var cache: [RDEPUBPaginationCacheKey: [NSAttributedString]]` — maps key to array of page attributed strings - `func cachedPages(for key: RDEPUBPaginationCacheKey) -> [NSAttributedString]?` — returns cached pages or nil - `func store(pages: [NSAttributedString], for key: RDEPUBPaginationCacheKey)` — stores pages - `func invalidate(for key: RDEPUBPaginationCacheKey)` — removes a specific entry - `func invalidateAll()` — clears entire cache - `var entryCount: Int` — read-only count of cached entries (for diagnostics) Make the class `final` and `Sendable`-safe (use a lock or `@MainActor` annotation since rendering is main-thread). Use `NSLock` for thread safety. Do NOT wire this cache into the rendering pipeline yet — that is future work. This plan only creates the infrastructure. xcodebuild build -project ReadViewDemo/ReadViewDemo.xcodeproj -scheme ReadViewDemo -destination 'platform=iOS Simulator,name=iPhone 16' 2>&1 | tail -5 - `Sources/RDReaderView/EPUBTextRendering/RDEPUBTextRendererCache.swift` exists - File contains `struct RDEPUBPaginationCacheKey: Equatable` with properties: chapterID, viewportSize, fontDescriptor, lineSpacing, textColorHash - File contains `final class RDEPUBTextRendererCache` with static `shared` instance - Class has methods: `cachedPages(for:)`, `store(pages:for:)`, `invalidate(for:)`, `invalidateAll()` - Class has computed property `entryCount: Int` - Build succeeds (xcodebuild exits 0) Cache key struct and cache manager stub exist, build compiles successfully - Build succeeds with new file - Cache types are properly defined and accessible from other modules in the same target - RDEPUBPaginationCacheKey captures all inputs that affect pagination output - RDEPUBTextRendererCache provides a thread-safe, singleton cache surface ready for wiring - No existing code is modified — this is purely additive Create `.planning/phases/08-pagination-quality-cache-performance/08-01-SUMMARY.md` when done