Code and technology abstract background
2026-07-14·Jordan

v2.8.11: Mastery Decay Correction, Session Topic Threading & PDF OCR Reliability

A patch fixing critical correctness bugs in the mastery scoring system, threading the session topic through the content generation pipeline, making PDF OCR reliable for scanned documents, and fixing diagram image extraction from provider responses.

Share:X (Twitter)

v2.8.11 is a patch fixing several critical correctness and reliability bugs identified during the v2.8.8 audit follow-up. Here is what changed:

Mastery Recency Decay Correction

The mastery scoring system had a subtle but significant bug: the recency decay was being applied to the new result instead of the stored prior score. This meant that when a student studied a topic for the first time and got a perfect score, the decay would immediately reduce that score - effectively penalising brand-new knowledge for being new.

Now the decay correctly ages the stored prior score before blending it with fresh evidence. New knowledge is scored at full strength. Only stale knowledge - topics not revisited in weeks - gets reduced weight. Read-time decay was also removed from the lookup functions, so the stored masteryScore is always the canonical value. On first attempt with no prior score, no decay is applied at all.

Session Topic Threading

Every roadmap session has always had a topic and subtopic, but the content generation pipeline never actually received them. The AI was generating study materials without knowing what specific topic the student was studying - it only knew the subject. We threaded the topic end-to-end: from the roadmap session model, through the server functions and cron job handlers, into the generation core where it now focuses the retrieval query and knowledge context. The context block sent to the AI now includes a "Focus topic" line, and the knowledge context query filters for content related to that topic. Study materials should now feel noticeably more targeted to what you're actually working on.

PDF OCR Reliability

The PDF OCR fallback path (used when a PDF has too little extractable text - typical for scanned documents) was sending the raw PDF as a data:application/pdf;base64,... URI in an image_url field. Vision models don't support the PDF format; they expect JPEG, PNG, or WebP. The OCR effectively always failed for scanned documents.

Now each PDF page is rendered to a PNG using the OffscreenCanvas API from pdfjs-dist, and each page is sent as a separate image_url part. The router and provider layers now accept string | string[] for the imageDataUri parameter to support multiple pages. Scanned documents that previously returned zero text will now be properly transcribed.

Diagram Generation Fix

OpenRouter's chat-completions endpoint returns AI-generated images in message.images, not in message.content (which contains a text caption). The diagram generation code was reading only message.content and treating the caption text as the image URL, so every diagram rendered as a text placeholder instead of an actual image.

The fix adds modalities: ["image", "text"] to the request body for the image model (so OpenRouter knows to return images), and adds an early-return path that extracts the image URL from message.images[0].image_url.url. The existing text-model path is unchanged.

Additional Fixes

Knowledge memory type safety: The new knowledge-memory engine was using a hand-rolled Supabase client type with plain-Promise return shapes that didn't match the real supabase-js PostgrestFilterBuilder, causing 8 typecheck errors across the engine and its callers. Switched to the codebase-wide SupabaseLike type.

Diagram model metadata: The diagram generation hardcoded model: "gemini-3.1-flash-image-preview" in stored metadata, which never matched the actual routed model. Now records the real model returned by the provider call.

Material context prioritisation: Study material context now sorts past papers first to ensure exam format profiling gets priority in the limited context window.

Divide-by-zero guard: The progress tracking components now handle a zero denominator gracefully instead of returning NaN.

This patch makes the mastery system mathematically correct, ensures every diagram renders as a real image, makes scanned PDFs work reliably, and keeps the codebase type-safe.

We use cookies to improve your experience and analyze usage. Learn more