-
Notifications
You must be signed in to change notification settings - Fork 1
Roadmap
RubricMaker is an offline-first rubric creation and grading tool for educators. This roadmap lists completed phases first (newest at the top of that section is the most recently shipped), then planned work.
- ✅ Rubric builder with multiple scoring modes (Total Points, Weighted, Single-Point)
- ✅ Interactive grading interface with score modifiers
- ✅ CEFR framework integration (Can-Do statements)
- ✅ Student self-assessment & peer review
- ✅ Essay assignments with rich text editor
- ✅ Analytics dashboard with class statistics
- ✅ Multi-format export (PDF, DOCX, CSV)
- ✅ Student portal with shareable links
- ✅ Offline-first architecture with localStorage
- ✅ Basic theme customization
Phase 1: Cloud Sync & Collaboration (PR #128)
- ✅ Sync conflict resolution —
src/utils/syncMerge.ts, remote-as-baseline merge with LWW on rubrics, wired into all three hydration sites (startup, reconnect, OTP sign-in) - ✅ Cambridge English framework — CEFR ↔ exam mapping (
src/data/cambridgeExams.ts), opt-in "B2 · FCE" badges, optional Cambridge Dictionary API vocabulary lookups - ✅ Theme bundles — 5 one-click presets (
src/data/themes.ts), tonal accent scale viacolor-mix(), 5 decorative export fonts for PDF/DOCX
Phase 2: Infrastructure Stabilization (PR #131 + wiki updates)
- ✅ 2.1 Multi-device e2e — second-browser-context Supabase fixture, propagation/LWW-race/network-partition specs (
e2e/specs/18-multi-device-sync.spec.ts) - ✅ 2.2 LWW extended to every editable collection (rubrics, grades, peer reviews, classes, students, grade scales, comment snippets/bank, self-assessments, speaking sessions, analysis results); add/delete-only collections (
attachments,exportTemplates,favoriteStandards) intentionally left on pending-queue protection only - ✅ 2.3 Wiki documentation pass — Cambridge + theming guides added to Features.md, conflict-resolution strategy documented in Supabase-Sync.md
- ✅ 3.1 Speaking session recordings — IndexedDB blob store, local-only audio, DB-gated video, optional cloud sync with cascade delete
- ✅ 3.2 Vocabulary profiling dashboard (
/vocabulary) — per-student/class CEFR distribution charts, open CEFR word lists, CSV export - ✅ 3.3 Peer review analytics (
/peer-analytics/:rubricId) — consistency scoring, leniency bias, inter-rater spread, comment heatmap - ✅ 3.4 Full testing environment (
/tests,/test/:code) — MC/short-answer/open questions, auto-scoring, class-average adjustment, live proctoring monitor
Phase 3.5: Hot Text Questions & Standalone Essays Workspace (PR #140)
- ✅ Hot-text question type —
src/utils/clozeParse.tsparses{{cloze}}and[[hot-text]]syntax; scoring intestCalc.ts - ✅ Standalone
/essaysworkspace (parallel to/tests) — prompt editor, rubric connector, per-student share links, submission-code import, reusable assignment templates (PR #143)
- ✅ 4.1 Expanded statistics — multi-class Compare view, trend overlay, rule-based insights, track/year filters
- ✅ 4.2 Activity dashboard (
/activity-dashboard) — rubric/test/essay × class grid, assign-from-view, submission count badges - ✅ 4.3 Admin hardening —
teacher/admin/observer roles + RLS, pg_cron data retention, student soft-delete archive (restore/anonymize), audit log with CSV export - ✅ 4.4 SIS roster sync (partial) — CSV upsert + optional roster-removal sync; native Magister API integration still reserved for community contribution
- ✅ 4.5 Self-hosting ops —
docs/SELF_HOSTING_OPS.md, HestiaCP/Virtualmin guides
- ✅ 5.1 Mobile grading — touch stepper alongside sliders, single-column ComparativeGrading reflow <768px, iPad CSS, mobile e2e
- ✅ 5.2 WCAG 2.1 AAA —
src/utils/contrastCheck.ts+ enforcement test, accessible modals with focus trap/restoration, keyboard drag-and-drop, i18n'd skip link - ✅ 5.3 Help & documentation — page tours (Joyride) on 12 pages total, contextual tooltips (
src/components/ui/HelpPopover.tsx) for score modifiers/LWW sync/proctoring flags - ✅ a11y test coverage — RubricBuilder/GradeStudent/ComparativeGrading added to the jest-axe page suite (PR #152, closing the Phase 5.2 follow-up)
- ✅ Route-shaped skeleton loading for lazy routes and async actions (PR #153)
Phase 6: Strategic Features (PR #157)
Scoped down from the original proposal before implementation — see "Deferred from Phase 6" below for what was cut and why.
- ✅ 6.1 Student Learning Paths — rule-based (no AI/LLM) rubric recommendations from CEFR-skill cohort gaps, consecutive-low-score intervention flagging,
/students/:id/learning-path(src/utils/learningPathAggregator.ts) - ✅ 6.2 Rubric Marketplace (school-scoped) — publish/browse/clone/upvote within a school via the existing
schools/school_memberstables,/marketplace(supabase/migrations/040_rubric_marketplace.sql,src/pages/MarketplacePage.tsx) - ✅ 6.3 Integration Ecosystem (CSV import only) — Clever CSV and OneRoster CSV roster-import auto-detection added to the existing CSV import modal; LTI 1.3 LMS integration deferred (see below)
- ✅ 6.4 Test Summary Export — per-question and per-skill/standard strong/weak breakdown, PDF/DOCX export (single + batch) from the test results page, feature parity with the rubric summary export (
src/utils/testSummaryAggregator.ts) - ✅ 6.5 Report Card Improvement — consolidated PDF/DOCX report card per student combining rubric grades, standards coverage, learning goals, CEFR overview, and test summary, with section toggles and single/batch export from the Export page (
src/utils/reportCardAggregator.ts)
Verification baseline (carried through every phase above): typecheck/lint clean, full unit suite green (1755+ tests), i18n parity across en/nl/fr/de/es, e2e suite green on chromium/firefox/webkit/mobile-chrome (pre-existing/environmental flakes tracked separately, not regressions).
Phase 7: Longitudinal & Historical Insight (PR #159)
- ✅ 7.1 Multi-year student history —
Student.pastClassMembershipsrecorded on every class change (manual move via Edit Student, and CSV sync-mode re-import transfers), with a confirmation summary before sync-mode CSV mutates anything; trail rendered on the student profile - ✅ 7.2 Rubric version diffing — "Compare" button per saved version opens a diff against the current rubric (criteria added/removed/changed, title/weight, level points/labels) (
src/utils/rubricVersionDiff.ts,RubricVersionDiffModal.tsx); version history/snapshot/restore already existed - ✅ 7.3 Standards coverage gap analysis — class-level aggregator cross-references every linked standard against what's been graded, split into Assessed/Not yet assessed, surfaced on the Activity Dashboard (
src/utils/standardsCoverageAggregator.ts,ClassCoverageGapPanel.tsx)
Phase 8: Collaboration & Department Workflow (PR #160)
- ✅ 8.1 Co-grading & moderation — second-marker grade reuses the peer-review data model (
StudentRubricwithisPeerReview: true);src/utils/coGradingModerationQueue.tsflags disputes above a configurable point threshold;/moderationlists disputes with a per-criterion delta and keep/accept resolution - ✅ 8.2 Department rubric/comment-bank libraries —
sharedWithSchoolflag on rubrics and comment-bank items, read-only to every teacher in the same school (041_school_sharing.sql, mirrors the Phase 6 marketplace's school_members join pattern) - ✅ 8.3 Grading task assignment — batch-assign a class's ungraded submissions for a rubric to a colleague from the Activity Dashboard (
GradingTasktype,042_grading_tasks.sql); completion is derived, not a stored flag - ✅ 8.4 Manual reordering — drag-and-drop reordering (
src/utils/displayOrder.ts,@hello-pangea/dnd) on RubricList, TestListPage, EssayListPage, the Activity Dashboard, and the class list on the Students page, per teacher. List containers use flexbox-wrap rather than CSS grid, since@hello-pangea/dndcomputes drag displacement from sibling bounding rects and doesn't support CSS grid track layout — grid caused incorrect cross-row drag animation and made it impossible to drop a card between two others in a different row. - ✅ 8.5 Cohort-based filtering — year/track cohort filter on the Rubrics, Tests, and Essays lists (
src/utils/cohortAggregator.ts,src/components/CohortFilter.tsx); a student counts as in-cohort via their current class or any past class frompastClassMemberships, so an item stays visible to a cohort across a class transfer. Manual reordering is disabled while a cohort filter is active. Not added to the Activity Dashboard, since its existing class-level year/track filter already serves the same need for that per-class matrix view.
- ✅ 9.1 RTL readiness — CSS logical-properties audit (
src/index.css): physicalleft/right/margin-left/padding-left/border-right/text-align: leftrules converted toinset-inline-*/margin-inline-*/padding-inline-*/border-inline-*/text-align: start, a no-op in the 5 existing LTR locales. Newsrc/utils/rtlLanguages.ts+ anAppContexteffect setsdir="rtl"on<html>when an RTL language is active — inert today (no RTL locale shipped yet) but ready for one. The mobile sidebar drawer'stransform: translateX()slide animation has no logical-property equivalent and was deliberately left sliding from the left edge only — tracked below as a known gap, not fixed in this pass. - ✅ 9.2 Installable offline PWA —
vite-plugin-pwa(Workbox) generates the manifest + service worker at build time;registerType: 'prompt'(notautoUpdate) so a new build never silently swaps JS under a mid-session sync — the user gets a native confirm prompt (src/pwa.ts) before reloading. Supabase requests (/rest/,/auth/,/realtime/,/storage/,/functions/+ version segment, matched by path so it covers both hosted and self-hosted Supabase) are explicitlyNetworkOnlyin the Workbox runtime-caching config — the service worker must never make a failed sync request look like it succeeded. Works under the existing relativebase: './'sub-path hosting config. Manifest icons:rubric-icon.svg(sizes: any) plus 192×192/512×512 PNG fallbacks (pwa-192.png/pwa-512.png, rasterized from the same SVG via a one-off Playwright screenshot script — no new dependency) for broader Chrome/Android installability. A dedicatedmaskablepurpose variant is still a follow-up, see Known Issues. - ✅ 9.3 Dyslexia-friendly reading mode — new Settings toggle (
dyslexiaFriendlyMode) sets--line-height: 1.8/--letter-spacing: 0.04emapp-wide via the same CSS-custom-property pattern as the existing theme bundles; no new component, just two new:rootvars insrc/index.csswith theirvar(--x, default)fallback as the single source of truth for the off state. - ✅ 9.4 Expanded essay exports — new "Essay Export" section on the Export page (
src/pages/ExportPage.tsx) andsrc/utils/essayExport.ts. Exports a TipTap essay submission (EssaySubmission.contentHtml) to Markdown, DOCX, or PDF, either as a single essay, separate files for several selected students, or combined into one document (Markdown---join, DOCXPageBreak, PDFpage-break-after). No new data model was needed: the essay/rubric/analysis combined export (exportEssayWithRubric) joinsEssaySubmission↔StudentRubric↔DocumentAnalysisResultat export time by(rubricId, studentId), rather than adding a stored attachment FK — avoiding the schema change the original proposal assumed was required. The HTML→Markdown/DOCX conversion is a small custom DOM walker scoped to exactly the tags TipTap'sEssayEditoremits (no new dependency); tables/task-lists degrade to plain text in Markdown/DOCX (PDF keeps full fidelity since it prints the HTML directly via the existingprintHtml/browser-print pattern). Batch "separate files" mode loops single-file downloads rather than zipping — no JSZip added.
- ✅ Two-tier navigation —
Sidebar.tsxrebuilt as an icon rail + sub-panel, grouped into 6 domains; fixed the rail mis-highlighting "Overview" on dynamic grading/session routes - ✅ "Warm Scholar" re-skin — new color tokens and fonts (Bricolage Grotesque/Hanken Grotesk), CEFR badge palette retuned to keep 4.5:1 contrast; fixed a bug where
AppContext.tsxhardcoded--accent/--fontas JS inline-style overrides that silently beat whatever the CSS theme said - ✅ Per-student CEFR profile depth — per-cell evidence (rubric/date/score) in
cefrStudentAggregator.ts, surfaced as a "Skill Evidence" section on the CEFR detail page - ✅ Live-session nudge — teacher can nudge a student mid essay/test live-monitor session (
useLiveSessionTelemetry.ts) - ✅ Marketplace CEFR tags — chip picker on the publish form, new migration
- ✅ Moderation Reconcile — third resolution action in
ModerationQueuePage.tsx(per-criterion average, viacoGradingModerationQueue.ts) - ✅ Dev seed-data tool — "Load sample data" button (Settings → Administration, dev-only) for realistic demo data during design review
- ✅ Full desktop/tablet UX audit (
docs/UX_AUDIT.md, tracking issue #201) — 23 findings filed, all resolved: grade-pill clutter on Students, CEFR Overview sticky columns, rubric editor/Comparative Grading/Grade Student tablet clipping, Statistics heatmap-vs-table/histogram redundancy, rubrics card-grid wrap, test/essay action-button stacking, moderation baseline-zero bug, CEFR↔Learning Path↔Vocabulary cross-links, notification panel clipping, Activity Dashboard date grouping/legend, Marketplace filter/sort, Student Portal nav + teacher-preview banner, dev-only direct-access share-code links, spotlight-search open animation - ✅ Co-grading reviewer identity — colleague picker replaces free-text reviewer name entry (PR #173)
- ✅ DocsPage i18n migration — remaining hardcoded body content moved to translation keys (PR #174)
- ✅ Offline-first storage fix — stopped writing a full duplicate copy to
localStoragewhile connected to Supabase; persistence now gated throughisOffline()/the pending-sync queue per the rule inCLAUDE.md(PR #175)
- ✅ 10.1 Global search — spotlight modal (
Ctrl/Cmd+Kor the Topbar search icon) over rubrics, tests, students, classes, and essay assignments;type:/class:filter tokens plus diacritic-insensitive substring matching (searchAll()) - ✅ 10.2 Global active-class selector — Topbar
<select>two-way bound tosettings.activeClassId; Statistics' own class filter initializes from and syncs back to it live - ✅ 10.3 Statistics Custom Views — gallery of 3 recommended charts, independently recolorable/toggleable, exportable as PNG (
statsChartPresets.ts); fixed a bug where the Criterion Heat Map ignored the page's class filter and exclude-not-handed-in toggle - ✅ 10.4 Export page student selector — split out of the Rubric Export card into its own collapsible section, so it no longer gets in the way of Essay/Period/Report-card export
Phase 11: Data Portability & School-System Interop (11.1–11.2, complete) (PR #238)
- ✅ 11.1 Gradebook export presets —
src/utils/gradebookExportPresets.ts, a "Gradebook format" dropdown next to the Export page's CSV button switches between the existing generic export and ready-made column presets for Magister and SOMtoday (student name/number + grade converted to the Dutch 1-10 scale via1 + pct/100*9). Reuses the existingPapa.unparse/handleCsvExportpipeline — generic export behavior unchanged. - ✅ 11.2 Calendar/due-date export —
src/utils/icsExport.ts, a minimal VCALENDAR/VEVENT builder (no new dependency, no recurrence/timezone-DB). "Export due dates (.ics)" button on the Essay Export section downloads every essay assignment's deadline (EssayAssignment.expiresAt) as one file. Scoped to essay assignments only —Testhas no due-date field in the current data model, so test deadlines were dropped from this item rather than adding a new field speculatively; see below.
Scoped against the codebase first (see prior revision of this page for the full per-item analysis), then implemented the well-bounded slices from each item; the open-ended/large halves were deferred rather than rushed — see "Deferred from Phase 12" below.
- ✅ 12.1 (partial) TipTap mark coverage —
src/utils/essayExport.ts's HTML→DOCX/Markdown walker now handlescolor/highlight/font-family/font-size/line-height/text-alignmarks, real GFM tables (was: flattened to pipe-separated text), and GFM task-list checkbox syntax — previously silently dropped per the walker's ownponytail:scope-limiting comment. DOCX tables render as realTable/TableRow/TableCellnodes (header-row shading, borders) instead of flattened paragraphs. Essay template download/import deferred — see below. - ✅ 12.2 (partial) Period Report — three independently-shipped slices: (1) the ambiguous combined locale heading
"Period Report / Report Card"renamed to just"Period Report"across all 5 locales — "Report Card" stays a separate, more detailed export with its own name, since they're genuinely two different functions (exportPeriodReportvsexportReportCard), not the same feature under two names; (2) comment/feedback text run through the existing<...>-stripping pattern (already used indocxExport.ts/essayUtils.ts) before being written intoperiodReportExport.ts'sTextRuns; (3) a real grade-trend bar chart, rasterized via a plain<canvas>(no Recharts/headless-render infra pulled into this non-React export utility) and embedded as a DOCXImageRun, replacing the old colored-cell trend table — falls back to the original table whencanvas.getContext('2d')is unavailable (e.g. under jsdom in tests). Essay-style template download/import for period reports deferred — see below. - ✅ 12.3 phase 1: group-graded rubric (duplicate-scores) — new
StudentRubric.groupIdfield;createGroupStudentRubrics(rubricId, studentIds)inAppContext.tsxcreates oneStudentRubricper student sharing a freshgroupId; the existingSAVE_STUDENT_RUBRICreducer case fans outentries/overallComment/globalModifierto every sibling sharing thatgroupIdon every save (not just at creation — the group stays in sync on later edits too). New "Group grade" entry point on the Rubrics list opens a student-picker modal, then drops the teacher into the normal single-studentGradeStudentscreen — no new grading UI was built. A banner onGradeStudentshows which other students will receive the same scores. Per-criterion individual/collaborative scope split (phase 2) deferred — see below. - Verification: typecheck/lint clean (0 errors, same 152 pre-existing warnings), 1846/1846 unit tests (8 new, incl. a reducer test asserting the group fan-out and a chart-embedding test stubbing
HTMLCanvasElement), i18n parity 0 missing/extra across en/nl/fr/de/es, coverage 58.67%/50.42%/48.17%/59.96% (stmts/branches/fns/lines, above the 50/37 thresholds). Docs/i18n updated per CLAUDE.md:DocsPage.tsx(Essays tab styling-fidelity note, Analytics tab report-card chart note, new Grading tab "Group grading" section),README.md(Export options + new Group grading bullet),LandingPage.tsx(extended the existing Smart Grading card — no new card, per the established "extension not new feature" convention).
Each phase below groups proposals under one theme so they can be scoped and shipped independently. None of these involve AI/LLM content generation — that remains explicitly out of scope for this project.
Phase 9 (Accessibility & Reach Expansion), Phase 10 (Improved Searching & Querying), Phase 11 (Data Portability & School-System Interop), and Phase 12 (Improving the application — scoped slices) are now complete — see the "✅ Completed Phases" section above. The larger, open-ended halves of Phase 12 were deferred rather than rushed — see "Deferred from Phase 12" below.
- Extend coverage on all fronts to at least 70% coverage on all categories and pages
- Up the coverage gating to 65% after achieving the above
- Extend testing suite to cover all routes in the teacher and student views
- Extend the Supabase testing suite to cover all the supabase methods
- Run a lighthouse audit
- Fix any issues that make the application less usable or responsive
- Fix all the unexpected 'any' warnings
- Triage all the issues, and order them from simple to complex fixes
- Add pre-commit hooks that help the commits work more cleanly. Think
prettier --writeandeslint --fix
- Audit the CI/CD pipeline
- See if any of the ordering should be changed
- Add extra reporting for critical CI/CD tests
- Research any additions that could fill CI/CD gaps (free tools are a requirement)
- Show students some of the statistics teachers can already see (think about progress which is already partially implemented with the grade history)
- Also show the radar views for all of the rubrics (combined and separated)
- Show a list view of everything planned or overdue
- Allow a student to ask for additional feedback and explanation on a test, rubric, or essay
- Send this to the teacher's notifications, allowing extra feedback or explanation to be given in a reply or the assessment
- Allow for students to use teacher made flashcard decks for vocabulary
- .csv, .xls(x), and .doc(x) imports
- Students currently have no single view of outstanding tests and essays assigned to them — they only find work via a direct share-code link.
- Add a to-do list (could build on 14.2's planned/overdue list view) that surfaces open
TestandEssayAssignmentitems per student, with status (not started / in progress / submitted) and due/expiry date where set. - Note:
Testhas no due-date field today (onlyEssayAssignment.expiresAtdoes — see "Deferred from Phase 11" below); adding one would make this list more useful but isn't a hard prerequisite for a first version.
Scoped out of an earlier phase's implementation, not dropped. All remain candidates for a future phase if there's demand.
- LTI 1.3 LMS integration (Canvas, Blackboard, Moodle) — needs a live LMS sandbox to verify OAuth/launch flows; CSV-based roster import (Clever, OneRoster) shipped instead as a same-outcome, locally-testable substitute for the common "get students into the app" need.
-
Public/cross-tenant rubric marketplace — shipped as school-scoped only (reuses
schools/school_members); a public marketplace would need a moderation queue, abuse controls, and report/flag tooling that don't exist yet.
-
11.3 Read-only public API for institutional reporting — not started. The biggest item of the original three and the only one introducing a new attack surface. Needs: a Supabase Edge Function reading already-aggregated stats (reuse
gradeCalc.ts-style logic, not raw tables), an opt-in toggle inAdminPage.tsx→IntegrationsTab(off by default, per-school), and a scoped inbound API key/token distinct from the existing outbound Standards/Cambridge keys. Response must be pre-anonymized server-side (no student names/IDs) in the SQL/function layer, not left to the caller to discard fields. Recommend scoping this against a concrete consuming dashboard once one exists, rather than guessing the response shape — a small follow-up PR, not a large one. -
Test due-date export —
Testhas no due-date field in the current data model (onlyEssayAssignment.expiresAtdoes), so 11.2 shipped essay-deadline export only. Adding adueDate/expiresAtfield toTestand wiring it intoicsExport.ts's event list is a small follow-up if test deadlines turn out to matter in practice — not added speculatively.
-
12.1 Essay export styling template (download/import) — not started. The rubric's
ExportTemplateflow (table-header extraction from an uploaded blank DOCX) doesn't transfer to essays, which aren't tabular; needs its own template shape (paragraph/heading styles) and parsing logic designed from scratch. The TipTap mark-coverage half of 12.1 shipped; this half needs its own design pass before implementation. - 12.2 Period Report styling template (download/import) — same as above, not started; deferred for the same reason (no tabular pattern to reuse, needs a fresh design).
-
12.2 Unifying "Period Report" and "Report Card" into one export — only the naming was de-duplicated (one heading instead of two ambiguous ones); the two underlying functions (
exportPeriodReport/exportReportCard) still have different input shapes and weren't merged. A real merge is a product decision, not just a refactor — revisit only if having two adjacent export panels turns out to actually confuse teachers in practice. -
12.3 Phase 2: per-criterion group grading scope — not started. Phase 1 (duplicate-scores group, all criteria shared) shipped; splitting which criteria are collaborative vs. individual per rubric, with per-student override storage and offline-sync fan-out for partial edits, is real new data-model and UI work — recommend scoping a UI flow first, per the original Phase 12 scoping note's recommendation, before touching
RubricCriterion/gradeCalc.ts.
| Issue | Impact | Owner | Priority |
|---|---|---|---|
| Native Magister SIS API integration (bulk import + live sync) not built — CSV path covers production use today | School IT can't fully automate roster sync | Reserved for community contribution | Low |
Multi-device e2e specs (18-multi-device-sync.spec.ts) require a local Supabase stack to verify outside CI; no Docker daemon in some dev sandboxes |
Slower local iteration on sync code | — | Low |
Mobile sidebar drawer (.sidebar overlay, transform: translateX()) always slides in from the left edge, even under dir="rtl" — translateX has no CSS logical-property equivalent |
Cosmetic-only RTL gap on mobile nav; inert until an RTL locale ships | — | Low |
PWA manifest icons (SVG + 192/512 PNG) have no dedicated maskable purpose variant |
Android adaptive-icon masking may crop/pad the icon awkwardly on some launchers | — | Low |
-
Unit tests: Vitest (coverage thresholds: 50% lines/statements, 37% functions/branches — see
npm run coverage) -
E2E tests: Playwright, including a dedicated
mobile-chromeandsupabaseproject - i18n: Parity tests across EN, NL, FR, DE, ES locales — new locales must pass the same parity check and be checked against existing UI layout for overflow
-
Accessibility: axe-core in CI (WCAG 2.1 AA minimum; AAA contrast enforced via
contrastCheck.ts) - Performance: Offline-first validation; sync latency benchmarks for > 100 rubrics
Last updated: 30 June 2026 — Phase 11 (11.1/11.2) confirmed merged via PR #238. Phase 12 implemented in scoped slices: 12.1 TipTap mark coverage in essay exports, 12.2 Period Report naming/HTML-stripping/grade-trend chart, 12.3 phase-1 group grading (duplicate-scores). Template download/import (12.1/12.2) and per-criterion group scope (12.3 phase 2) deferred. All deferred items (Phase 6, 11, 12) consolidated under one "Deferred Items" heading after Phase 13.