TrayLearn: Add mastery-first UK phonics app with local SRS, UI, and tests#3
TrayLearn: Add mastery-first UK phonics app with local SRS, UI, and tests#3xoxoskeleton wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 886cef6acd
ℹ️ 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".
| const selectedIds = new Set(start.map((c) => c.id)) | ||
|
|
||
| const reviewPool = due | ||
| .filter((c) => !selectedIds.has(c.id) && (c.tray === 'Frequent' || c.tray === 'Growing')) |
There was a problem hiding this comment.
Exclude locked-stage cards from due review selection
This reviewPool filter pulls every due Frequent/Growing card regardless of stage, so isNew cards above unlockedStage can enter sessions through the due path. In this commit, starter cards for higher stages are seeded as due, which means advanced cards will surface before readiness gating is met once earlier cards are rescheduled. That bypasses the stage-unlock rule that newCards already enforces.
Useful? React with 👍 / 👎.
| maxDailyDue: activeChild.settings.maxDailyDue, | ||
| unlockedStage: activeChild.unlockedStage | ||
| }) | ||
| }, [cards, activeChild]) |
There was a problem hiding this comment.
Snapshot session cards instead of recomputing on every DB update
sessionCards is memoized from live-query cards and re-derived whenever cards changes, but each rating writes to Dexie and changes due/tray state mid-session. That causes the session list to reorder/shrink while cardIndex continues incrementing, which can skip cards or produce duplicates during a single run. The session should be fixed at start rather than rebuilt from mutable live data after each answer.
Useful? React with 👍 / 👎.
| return current.percentile + ratio * (next.percentile - current.percentile); | ||
| const addCustomCard = async () => { | ||
| if (!activeChild || !customPrompt.trim()) return | ||
| if (!canUseWholeWordCard(customStage as 0 | 1 | 2 | 3 | 4, customTricky)) { |
There was a problem hiding this comment.
Check card type before enforcing whole-word stage guard
This guard runs for every custom card regardless of customType, so non-tricky Stage 1/2 cards like SoundCard and DigraphCard are rejected even though only whole-word cards should be blocked. As written, users must mark unrelated cards as tricky to save them, which breaks normal custom-card creation for early stages.
Useful? React with 👍 / 👎.
Motivation
pnpm i/pnpm dev) and covered by unit tests for core scheduling rules.Description
starterCardsinlib/content.tsand DB helpers inlib/db.ts.lib/srs.ts, session selection algorithm inlib/session.ts, and stage-gating/whole-word safeguards inlib/gating.ts.pages/index.tsx, a safe local API inpages/api/generate.ts, and UI styling/config intailwind.config.ts,postcss.config.js, andstyles/globals.css.lib/types.ts), a sync stub/feature-flag (lib/sync.ts), export/print & custom card hooks, and updateREADME.mdwith run instructions and where to find scheduling logic; updatepackage.jsonand lockfile to include dependencies and test scripts.tests/srs.test.tsandtests/session.test.tsplusvitest.config.ts, and wirepnpm testscript.Testing
pnpm test(Vitest) and all tests passed: 5 tests in 2 files (tray movement and session selection) — ✅ passed.pnpm lint(next lint) with no ESLint warnings or errors — ✅ passed.pnpm build(Next.js) to validate type/compile output and static generation; build completed successfully — ✅ passed.Codex Task