Skip to content

Apply the intended ordering to scheduled words that are due - #731

Draft
mircealungu wants to merge 1 commit into
masterfrom
wt/fix-schedule-ordering
Draft

mircealungu wants to merge 1 commit into
masterfrom
wt/fix-schedule-ordering

Conversation

@mircealungu

Copy link
Copy Markdown
Member

The bug

scheduled_words_due_today and scheduled_words_due_now in zeeguu/core/word_scheduling/basicSR/basicSR.py both did this:

query.order_by(
    -Phrase.rank.desc(), cls.cooling_interval.desc()
)  # By using the negative for rank, we ensure NULL is last.

if limit is not None:
    query = query.limit(limit)

return query.all()

SQLAlchemy query methods return a new query; they do not mutate in place. The order_by result was thrown away, so limit/all ran on the un-ordered query. The intended ordering — most frequent word first, then descending cooling_interval so words closest to being learned come first — has never been applied to due words.

Compare user_words_not_scheduled (basicSR.py:171-173), which builds the same ordering correctly by chaining it into the query expression.

The fix

Assign the result of order_by in both methods. Two lines. Nothing else changed.

Test

Added test_due_words_are_ordered_by_rank_then_cooling_interval to zeeguu/core/test/test_scheduling.py. It schedules four due words with known Phrase.rank / cooling_interval values, created in an order that is deliberately not the expected one, and asserts both scheduled_words_due_today and scheduled_words_due_now return them most-frequent-first, then by descending cooling interval, with the unranked word last.

Verified the test fails on master's version of basicSR.py and passes with the fix.

Test results: zeeguu/core/test + zeeguu/api/test — 449 passed, 12 subtests passed, 0 failures. No pre-existing failures to report.


⚠️ Caveat the maintainer must weigh before merging — this is why the PR is a draft

This fix is correct in itself, but it will make an existing composition problem in the practice queue more visible, not less.

A separate investigation found that the practice queue admits unscheduled words ordered by ascending frequency rank (basicSR.py:171-173). The effect is large:

  • A top-100 word is 5.2x more likely to be scheduled than a rank-20,000+ word — 33.6% of fit words vs 6.5%.
  • Nothing in fit_for_study looks at frequency at all. There is no gate that asks whether the learner already knows the word.
  • On one real account, 227 of 386 practised words are words a reading-derived model is confident the learner already knows. They consume roughly 70% of that user's exercises.

Restoring the intended ordering for due words means those very frequent words will now be pushed to the front of each session instead of appearing in arbitrary order. The underlying problem is unchanged — the queue admits the same words either way — but the user-visible symptom gets sharper: sessions will more consistently open with words the learner already knows.

So there is a real choice here:

  1. Merge now. The code then does what it was always written to intend, and the composition problem becomes more legible — arguably a good thing if it motivates the fix.
  2. Merge after an admission gate exists — something that skips words the learner demonstrably reads without help — so that the restored ordering surfaces a queue that is actually worth ordering.

I have no view on which is right; that is a product call. Flagging it so the decision is made deliberately rather than discovered in user feedback.

🤖 Generated with Claude Code

scheduled_words_due_today and scheduled_words_due_now both called
query.order_by(-Phrase.rank.desc(), cls.cooling_interval.desc()) and
discarded the result. SQLAlchemy query methods return a new query rather
than mutating in place, so the next line -- query.limit(...) / query.all()
-- ran on the un-ordered query and the intended ordering was never applied
to due words.

Assign the result in both methods, matching how user_words_not_scheduled
already chains the ordering into its query expression.

Adds a regression test that schedules four due words with known ranks and
cooling intervals and asserts they come back most-frequent-first, then by
descending cooling interval, with unranked words last. The test fails
without this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

ArchLens - No architecturally relevant changes to the existing views

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant