This document is a reading guide for reviewing Cosimo without trying to read the whole project from top to bottom. It explains the main logic flows, the modules that own them, and the invariants worth checking first.
For a broader design summary, read architecture.md. For schema history and
user-visible release history, read docs/rating-storage.md and
CHANGELOG.md.
All paths in this document are shown relative to the repository root.
How To Read The Project
Start with the pure library code, then move into the GUI. The core deck, scheduling, and database logic is much easier to review than the wx event code, and it explains most of the application's invariants.
Suggested reading order:
src/model.rssrc/deck_format.rssrc/scheduler.rssrc/review_store.rssrc/study_item.rssrc/review_session.rssrc/app_state.rssrc/ready_screen.rssrc/study_actions.rssrc/ready_card_actions.rssrc/deck_properties_actions.rssrc/deck_bundle.rssrc/deck_import.rssrc/sync.rssrc/sync_http.rssrc/sync_runtime.rssrc/sync_workflow.rssrc/sync_actions.rssrc/main.rs
Do not start by reading all of src/main.rs. It is the wx event wiring layer
and is easiest to understand after the state and model modules are familiar.
Recent rationalisation work moved ordinary study actions, ready-card mutation
actions, deck properties, sync workflows, and many ready-screen render
decisions into focused modules. main.rs is still best treated as the last
stop: it owns wx application startup, event binding, deferred menu dispatch,
some file/maintenance actions, and the remaining exam/quiz modal loops.
Core Runtime Objects
Cosimo works with three main data identities:
- A deck card is user-authored content in a
.cosimo-deckfile. - A study item is a study direction derived from a deck card. A standard item uses prompt to response; a generated reverse item uses response to prompt.
- A datum key is the stable storage key used by review history and scheduling.
src/model.rs defines Datum, DatumKey, confidence ratings, recall ratings,
and completed reviews. This is the first place to check when reviewing whether
stored numeric values are converted into typed values safely.
src/study_item.rs expands deck cards into standard and generated reverse
study items. Reverse items deliberately have separate datum keys so reviewing a
card in one direction does not change review history in the other direction.
File And Database Shape
The editable deck is plain text. The review history and schedules are SQLite. Optional audio lives beside the deck in a same-stem sidecar directory.
Important modules:
src/deck_format.rs: parse and format.cosimo-deckfiles.src/deck_import.rs: read supported Anki.apkgmaterial into new Cosimo deck text and imported MP3 sidecars.src/deck_data.rs: derive deck and review database paths.src/review_store.rs: schema, migrations, review history, schedules, card states, reverse-card records, scrub, and consistency checks.src/deck_bundle.rs: full deck bundle export, backup, preview, and restore.src/file_ops.rs: durable file writes, backup paths, pruning, application data paths, bundled resource lookup, and local file helpers.
The main data-safety rule is that user-authored deck content and review-store identity must stay aligned. Stable numeric card IDs in the deck are the bridge between those two worlds. New cards should receive monotonic IDs rather than reusing gaps left by removed cards.
When reviewing this area, check:
- no deck rewrite happens before a needed backup or migration guard
- review database migrations are idempotent or fail before data is partly moved
- inactive reverse-card history remains dormant until scrub, not accidentally reused by a new card
- duplicate prompts are blocked in normal editing paths
- duplicate responses remain valid except where active reverse cards would create ambiguous reverse prompts
Startup Flow
Startup begins in src/main.rs, but the logic is split across smaller modules.
High-level flow:
- Load compiled XRC resources and create the main UI.
- Migrate old portable settings files if present.
- Load
cosimo.iniand effective app settings fromsrc/app_config.rs. - Resolve the startup deck path through
src/startup_state.rsandsrc/deck_data.rs. - Open the deck and neighbouring review database through
AppState. - Run review database integrity and deck consistency checks.
- Migrate legacy deck IDs or legacy review keys if needed.
- Render the ready screen.
If startup cannot create or open the needed deck or database, the recovery path
offers the user a choice to open another deck or quit. That behaviour is owned
by src/startup_state.rs and thin startup handling in src/main.rs.
Portable Windows builds keep configuration, decks, backups, reports, and sync
temporary files beside the executable. The macOS port branch experiments with
separating bundled resources from user data through src/file_ops.rs; if that
work is revived, review every caller that currently expects portable paths.
AppState And Rendering
src/app_state.rs is the central mutable model for the GUI. It owns:
- deck path and review database path
- loaded deck data
- open
SqliteReviewStore - current ready-list filter, sort, and selected study item
- current study, exam, or quiz session state
- effective settings
Most user actions should follow this shape:
- Read or mutate
AppState. - Persist any data that must be durable immediately.
- Call ready-screen rendering/synchronisation.
src/ready_screen.rs turns state into native controls. Targeted render models
now make the main phase-dependent status text, card-panel content, ready
summary, phase chrome, action controls, and ready controls pure and directly
testable. The module still applies those models to wx controls and deliberately
keeps list replacement, focus movement, and audio-player sync close to the
concrete widgets. It also updates ready-list labels, filter counts, dynamic
menu state, status bar, timer refresh, and due-notification state. Ready-list
filtering and selection logic lives in src/ready_list.rs so it can be tested
without wx.
The ready-list accessible name comes from Localizer::ready_cards_heading.
The XRC also keeps a static text label immediately before the list because
native Windows accessibility may use that neighbouring label even when the
runtime name is set explicitly. It should describe the whole ready-list view,
not the currently running study session.
When reviewing UI changes, check that state changes and rendering are not mixed in ways that make focus, selection, or dynamic menus hard to reason about. If a handler starts to own persistence, modal flow, error reporting, and rendering all at once, it is a likely extraction target rather than a good place to add more code.
Ready List Flow
The ready list displays study items, not raw deck rows. That matters because a single deck card can produce both a standard and a generated reverse study item.
Important modules:
src/ready_list.rs: filter, sort, labels, counts, selection normalisation, and minimal native list update decisions.src/ready_screen.rs: applies those calculations to wx controls.src/menu_model.rs,src/menu_ui.rs,src/menu_dispatch.rs: menu labels, dynamic menu state, and deferred menu commands.
Selection should be preserved by study-item identity when filtering, sorting, editing, or changing card state. Adding a card selects the new card. Removing a card selects the next or previous visible card when possible.
Ordinary Study Flow
Ordinary scheduled and unscheduled study uses src/review_session.rs.
High-level flow:
- User starts a scheduled, unscheduled, or flagged study session.
AppStateaskssrc/scheduler.rsfor the queue or builds an unscheduled random queue.- The UI enters prompt phase.
- User may give a confidence rating or reveal without confidence.
- The UI enters response phase.
- User gives a recall rating.
- A review event is written to SQLite.
- The scheduler updates the card schedule.
- The session advances or shows the summary.
The current scheduler does not repeat Again cards later in the same session.
Instead, the scheduler writes learning or relearning steps and the card becomes
available again when due.
Important modules:
src/review_session.rs: phase, queue, progress, summary statistics.src/study_actions.rs: GUI-facing ordinary study commands: scheduled, forced, and flagged study entry, reveal, rating activation, feedback, current-card deferral, pass ending, and summary continuation.src/ready_card_actions.rs: ready-card mutations, selected-card details, add/batch-add, selected-card edit/remove, revealed-card edit, current-card flagging, duplicate prompt resolution, and bulk shown-card actions.src/review_input.rs: keyboard command handling for prompt and response phases.src/scheduler.rs: due queue construction and schedule updates.src/review_store.rs: event and schedule persistence.src/review_dialogs.rs: statistics, card details, learning dashboard, card editor, and related modal dialogues.
When reviewing study changes, check that exactly one review event is recorded per answered card, deferrals do not count as answered cards, and ending early does not write phantom answers.
Scheduler Flow
src/scheduler.rs owns both queue construction and card memory updates. The
current scheduler is FSRS-6 based. Review database migration replays stored
review events so old derived schedule rows are normalised to the current
scheduler rather than remaining mixed with newer rows.
Core responsibilities:
- decide which cards are due
- order due learning/relearning/review cards
- randomise near-tie due cards to reduce thematic clumping
- fill scheduled sessions up to the configured minimum when needed
- update schedule state after recall feedback
- estimate recall for ready-list sorting, card details, and the learning dashboard
Review this module when changing recall labels, lapse semantics, learning steps, estimated recall, or workload forecasts. The GUI should not duplicate scheduler formulae.
Exam Flow
Exam mode is report-only. It does not write review history or update schedules.
Important modules:
src/exam_mode.rs: exam setup, sampling size, typed answers, exact matching, grading model, timed progress, summary text.src/exam_dialog.rs: setup, question, timeout, finished notice, grading, exact-review, and summary dialogues.src/main.rs: the modal exam loop around those pieces.
High-level flow:
- User chooses count or percentage, optional exact mode, optional time limit, and study direction.
AppStatebuilds an exam pass from active cards.- Each modal question collects a typed answer.
- Exact answers are accepted automatically.
- In non-exact mode, exact answers are auto-accepted, nonblank inexact answers are manually graded after the question phase, and blank submitted answers are shown in review for the correct response but counted incorrect without a Yes/No grading choice.
- In exact mode, inexact answers are shown in review and counted incorrect.
- Summary/report is shown without scheduler writes.
Timed exams share one timer context across question dialogues. If timeout occurs, the current answer text is submitted if non-empty, then a guarded timeout transition is shown.
Exam and quiz review dialogues have had wx modal lifecycle bugs. Be careful
when changing button default IDs, explicit EndModal calls, Alt-N, timers,
or menu-triggered modal flows.
Quiz Flow
Quiz mode is also report-only.
Important modules:
src/quiz_mode.rs: quiz sizing, direction selection, question sampling, distractor generation, answers, summary.src/quiz_dialog.rs: setup, question, review, and summary dialogues.
Quiz questions are sampled from active cards, excluding suspended and currently deferred cards. When reverse cards exist, the setup can restrict the quiz to standard, reverse, or both directions. Distractors must come from the answer side for the current direction; reverse questions should not offer prompts from cards marked non-reversible.
Audio Flow
Audio playback and audio generation are separate.
Playback:
src/review_audio.rsresolves sidecar Opus/MP3/WAV files and owns play/stop state.- Ordinary study, ready-list preview, exam review/grading, and quiz review use the same sidecar layout.
- On Windows, Opus playback is decoded through Symphonia/libopus and played
through Rodio, while legacy WAV playback uses MCI status polling.
Ctrl+Pstops current playback, and prompt-to-response sequencing waits for real playback completion instead of guessing from file duration.
Generation:
src/audio_generation.rslaunches the siblingvoicehelper and drives the GUI progress dialogue from machine-readable helper output.src/bin/voice.rsreads the deck, uses OneCore or SAPI voices, writes the selected Opus/WAV format, preserves untracked side audio, and maintainsaudio-manifest.tsvas the boundary for Cosimo-managed generated files.src/bin/voice/sapi.rsisolates the COM/SAPI unsafe boundary.
Audio sidecar files are not part of ordinary deck backups. They are included
only in full deck bundle export/backup and sync bundles. src/audio_cleanup.rs
owns removal of Cosimo-recognised inoperative audio, currently removed-card
generated audio, lower-preference generated files hidden by a preferred format,
and generated files displaced by manual audio. MP3 sidecars imported from Anki
are playback-only manual audio and are preserved by generated audio cleanup.
Deck Import Flow
src/deck_import.rs owns the pure import surface for Anki .apkg packages.
It reads the archive and collection database, maps supported note fields into
Cosimo prompt/response cards, assigns fresh Cosimo card IDs, reports skipped or
unsupported records, and extracts supported MP3 prompt/response audio into the
same-stem sidecar layout. It deliberately does not import Anki scheduling,
review history, cloze semantics, arbitrary templates, tags, or deck hierarchy.
The GUI import action in src/main.rs should stay a thin file-dialog and
open-deck workflow around that model. Import writes a new deck and optional
sidecar files, then opens the imported deck through the normal startup/open
path so ordinary deck canonicalisation and duplicate-prompt checks still apply.
Backup, Restore, And Maintenance
There are several backup concepts:
- ordinary deck backups before deck text replacement
- retained review database backup at session start when enabled
- automatic full deck plus database bundle backup once per day when enabled
- manual full deck bundle export or backup
- manual full deck with study history export
- full deck sync upload and download, which use the bundle layer but apply sync-specific ownership and history rules
Review these modules together:
src/file_ops.rssrc/deck_bundle.rssrc/review_store.rs- relevant UI wrappers in
src/main.rs
Restore is staged: inspect the zip, extract to a temporary directory, validate contents, back up an existing target when needed, then replace files. If the currently open review database must be overwritten, the UI releases the active SQLite store first so Windows can release the file handle.
Sync Flow
Deck sync is snapshot-based. The client uploads or downloads full deck bundles; the server stores remote revisions and derives content-only bundles for public or unlisted shared downloads. There is no merge or reconciliation layer.
Important modules:
src/sync.rs: core sync domain model, UUIDs, visibility, quota limits, in-memory and SQLite server backends, OAuth session persistence, and storage invariants.src/sync_http.rs: HTTP routing for upload, download, listing, deletion, quota, login, logout, token invalidation, and the browser root page.src/sync_http_client.rs: blocking client for the GUI.src/sync_oauth.rs: Mastodon-compatible OAuth instance validation, application registration, account verification, and token revocation.src/sync_runtime.rs: derive sync settings, preflight state, local/remote ownership decisions, and remote status from deck metadata pluscosimo.ini.src/sync_menu.rs: dynamic menu/auth-state helpers and small sync-specific dialogue decisions.src/sync_actions.rs: GUI-facing sync workflows such as status, remote deck listing, login/logout, token invalidation, upload, download, and remote deletion actions.src/sync_workflow.rs: lower-level upload/download jobs, progress events, temporary bundle handling, local target selection, and local sync-state persistence.src/sync_status_model.rsandsrc/sync_remote_decks_model.rs: user-facing status/list/details text.src/bin/cosimo-sync-server.rsandsrc/bin/cosimo-sync-cgi.rs: standalone and CGI entry points.
The intended sync layering is:
main.rsbinds a menu or button event.sync_actions.rsowns the user-visible workflow.sync_runtime.rsderives policy decisions from config and deck metadata.sync_workflow.rsruns the actual transfer or restore/upload job.sync_http_client.rsandsync_http.rsspeak the protocol.sync.rsowns durable server-side storage and typed sync invariants.
Core sync invariants:
- owner uploads include study history; public and unlisted downloads are content-only and never include another user's review database
- the authenticated owner comes from the server bearer token, not editable deck metadata
- upload conflict checks compare the local expected remote revision with the server revision before replacing remote state
- downloading a different remote deck must never overwrite the currently open deck just because the deck file name matches
- unknown remote deck UUIDs restore only to a non-overwriting local path
- server storage must reject traversal, unsafe symlinks, unsupported bundle entries, over-limit uploads, and mismatched bundle hashes
CGI and reverse-proxy deployment details are documented in
docs/sync-deployment.md; protocol design notes are in docs/sync-design.md.
For client-side review, prefer reading sync_actions.rs before main.rs; it
now contains the full GUI sync workflows that used to be buried directly in wx
event handlers.
Localisation And UI Resources
User-facing strings should go through src/localization.rs and the .po files
in po/. XRC files in ui/ define the native controls; Rust code localises
their labels after loading.
Important rule: do not add hard-coded user-facing text in model or dialogue
code if it should be translated. Use the Localizer API.
When adding controls, check:
- accessible names for checkboxes and fields
- menu mnemonic uniqueness in each language
- tab order
- default button behaviour
- whether a source-level test is needed for fragile XRC or wx lifecycle wiring
System Tray And Timers
src/resident_tray.rs owns minimise-to-tray behaviour. This area is fragile
because wx taskbar icons behave like window objects and can assert if destroyed
while handlers are still active.
Current rules:
- restoring hides the visible tray icon but keeps the retained tray object
- tray context-menu commands are posted back to the frame for later handling
- frame close removes the visible icon and avoids explicit tray destruction
- tray polling and ready-screen refresh use different wx event owners
Do not simplify this lifecycle without retesting on Windows.
Where Bugs Usually Hide
Prioritise review effort around:
- deck ID migration and review history migration
- dormant reverse-card data and scrub
- duplicate prompt/response invariants
- scheduler state transitions and lapse semantics
- modal dialogue close paths, especially timers and shortcuts
- focus and selection preservation after ready-screen render
- dynamic menu enablement after metadata or card-state changes
- boundaries between
main.rs,sync_actions.rs,sync_runtime.rs, andsync_workflow.rs; wx event wiring, policy decisions, and transfer mechanics should not collapse back into one handler RefCellborrow lifetimes in UI handlers. Do not match directly onstate.borrow_mut()results; finish the borrow before rendering, opening a dialogue, or setting focus. This pattern caused the review deferral bug where the card was marked deferred but the prompt did not advance.- backup/restore overwrite boundaries
- audio generation overwrite policy
- localisation strings outside
Localizer
Tests Worth Running While Reviewing
Normal floor:
cargo test --lib --no-default-features
cargo test --bin cosimo
cargo check --bin cosimo
Scheduler reference check when reviewing scheduler logic:
cargo test --lib --no-default-features --features fsrs-reference fsrs_reference_tests
Release-level checks are described in CONTRIBUTING.md and
docs/qa-checklist.md. Manual Windows/NVDA testing remains necessary for focus
order, speech output, tray behaviour, and wx modal lifecycle issues.