perf: Phase 3 — prompt caching, reduced-motion canvas, stub audit - #5
Conversation
Restructure the wizard chat system prompt into cache-controlled content
blocks so repeat turns on the same step read the large stable prefix from
cache instead of reprocessing it (~0.1x input cost on hits).
- buildSystemPrompt now returns Anthropic.TextBlockParam[]: a stable block
(persona + per-step knowledge base + rules + security) carrying
cache_control: ephemeral, followed by a volatile block (per-user profile
context) after the breakpoint.
- The volatile profile data previously sat in the MIDDLE of the prompt
("Current Context"), which would have invalidated everything after it on
every request; it's now moved to a trailing uncached block so the cached
prefix is byte-identical across a user's turns on a step.
- No model IDs, max_tokens, streaming, or data-tag handling changed; the
system field already accepts a block array, so the chat route call site is
unchanged beyond a clarifying comment.
Onboarding and bid-review routes are intentionally left uncached: their
static system prompts (~680 and ~1300 tokens) fall below the per-model
minimum cacheable prefix (2048 tokens on Sonnet 4.6, 4096 on Opus 4.8), so a
cache_control marker there would be a silent no-op.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a shared useReducedMotion hook (SSR-safe, subscribes to changes) and wire it into the two backdrop effects: - MatrixRain: skip the rAF loop entirely under prefers-reduced-motion (paint one static frame instead); when motion is allowed, cap the loop to ~30fps via a time accumulator in rAF and pause/resume on tab visibility changes. Tag the canvas with .matrix-rain-container so the existing reduced-motion/print CSS selectors actually match it. - TronGrid: drop the perspective floor layer under reduced motion so the backdrop stays flat and calm. Halves the per-frame work on low-power devices and stops animating unfocused tabs, with no visual change when motion is allowed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The render guard `(previewMode || !hydrated) && hydrated` was provably equivalent to `previewMode && hydrated` (previewMode is never true before hydration), so collapse it to the simpler, clearer form. No behavior change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the useEffect+useState matchMedia subscription with React's external-store primitive — SSR-safe and free of the setState-in-effect cascade warning. Behavior unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR introduces a ChangesReduced-motion accessibility for UI animations
AI prompt caching refactor and minor fixes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 144191612f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| function getSnapshot(): boolean { | ||
| return window.matchMedia(QUERY).matches; |
There was a problem hiding this comment.
Fall back when matchMedia is unavailable
In environments where window.matchMedia is absent (jsdom by default, and some embedded or legacy browsers), any component using this hook will throw during render because useSyncExternalStore calls getSnapshot even though subscribe handles the same case with a no-op. Rendering MatrixRain or TronGrid should fall back to false instead of crashing when matchMedia is unavailable.
Useful? React with 👍 / 👎.
Phase 3 (Depth & Polish) of the IronForge maximization roadmap (
docs/plans/2026-06-17-001). Orchestrated as three parallel agents on disjoint file sets, reviewed, then integrated.Units
buildSystemPrompt(chat route) now returnsAnthropic.TextBlockParam[]withcache_control: ephemeralon the stable prefix (persona + step knowledge base + rules), and the volatile per-user profile moved to a trailing uncached block so the cached prefix is byte-identical across a user's turns on a step. onboarding and bid-review intentionally skipped — their prompts (~680 and ~1300 tokens) fall below the Sonnet (2048) and Opus (4096) cacheable minimums, so a breakpoint there would be a no-op. The chat route is both the qualifying prompt and the highest-frequency path (multiple turns per step).useReducedMotionhook (viauseSyncExternalStore). Matrix rain now caps at ~30fps (time-accumulator in the rAF loop), pauses on tab-hidden (visibilitychange), and renders a single static frame underprefers-reduced-motion; tron-grid drops its perspective-depth layer under reduced motion. Cuts background-canvas CPU/GPU on mid-tier mobile.Verification
tsc --noEmitclean · lint 0 errors (22 pre-existing warnings) · production build succeeds.claude-apireference (Opus 4.8 = 4096, Sonnet 4.6 = 2048).Deferred (not in this PR)
usage.cache_read_input_tokens > 0on a 2nd WA chat turn (requires a live API call).useReducedMotionunit test (matchMedia mock) — low value vs the build/type coverage; flagged.🤖 Generated with Claude Code
Summary by CodeRabbit
Accessibility
Performance
Bug Fixes