# Cosimo

Cosimo is a spaced-repetition system for learning prompt/response pairs with a
screen-reader-accessible desktop interface. Accessibility is a hard project
requirement, not a later polish step.

The current application uses `wxdragon` on top of wxWidgets for the GUI,
stores editable learning content in a plain-text deck file, and stores review
history in SQLite.

## Project Goals

- Make the full review flow usable with screen readers and keyboard input.
- Keep learning content human-editable without pushing users through a database
  editor.
- Keep review history, ratings, and scheduling state separate from the editable
  deck content.
- Favour native controls and platform accessibility APIs over custom-drawn UI.

## Current State

The repository currently contains:

- a deck format for prompt/response pairs
- a typed Rust data model for review ratings
- SQLite-backed review event storage
- scheduled review sessions with configurable minimum session size
- a wxdragon desktop review UI for a single deck file
- pre-cycle deck review with a prompt list on the start screen
- ready-list filtering, including duplicate prompt/response filters,
  problem-card and direction-asymmetry filters, multiple sort criteria, sort
  direction, and per-card details
- card management from the GUI: add, edit, remove
- reversible cards with independent reverse-direction review history and
  scheduling
- deck format v2 metadata, deck properties, editable deck properties, and
  deck-stored non-reversible markers
- a learning dashboard with a concise summary, recall distribution,
  diagnostics, workload forecasts, study activity, and standard/reverse
  comparison when a deck contains reverse cards
- report-only exam mode with random active-card sampling, optional time limits,
  exact or adjudicated grading, summaries, and saved exam reports
- report-only quiz mode with random active-card sampling, four-choice
  questions, delayed feedback, answer review, and summaries
- optional WAV review audio for ordinary review and exam question prompts
- a Windows `voice.exe` helper for generating review-audio WAV files from
  installed OneCore or SAPI voices
- recent-deck reopening from `File -> Recent Decks`
- automatic deck and review-database backup options
- language selection for English, Spanish, and Galician
- end-of-session statistics and saved text reports
- flagged-card review, deferral, suspension, and non-reversible card markers
- optional sound notifications and minimise-to-system-tray behaviour

## Licence

Cosimo is released under the GNU General Public Licence version 3. See
[LICENSE](LICENSE).

## Review Model

For a user-facing introduction to studying with Cosimo, see
[docs/user-guide.md](docs/user-guide.md).

Release notes are kept in [CHANGELOG.md](CHANGELOG.md).

Each datum contains:

- a prompt or question
- a response or answer

User-facing documentation uses these terms:

- `study session`: one run from Start, Force Start, or Study Flagged through to
  the summary
- `question`: one prompt presentation inside a study session, including repeats
- `attempt`: one stored answer with recall feedback and optional confidence
  rating
- `study item`: one schedulable direction of a card, either the standard
  direction or a generated reverse direction

Established phrases such as `review database`, `review history`, `scheduled
review`, and `review audio` still use review for the broader spaced-repetition
process and stored study history.

Before seeing the response, the user may record a guess:

- `1` Don't know
- `2` Probably don't know
- `3` Probably know
- `4` Certainly know
- Space / `Reveal Response` records no guess and stores `Not answered`

After seeing the response, the user records feedback:

- `1` Again
- `2` Hard
- `3` Good
- `4` Easy

The review UI also supports:

- `0` End this session now
- `e` Edit the current card after its response has been revealed
- `Ctrl-F` Flag or unflag the current card during review
- `Ctrl-D` Defer the current card until tomorrow before revealing the response
- `Ctrl-P` Play or stop prompt/response audio when review audio is available;
  on the ready list this previews the selected card's prompt and response

Before a study session starts, Cosimo shows:

- the number of cards that would be scheduled now
- the configured minimum cards per session
- a navigable list of cards labelled by prompt
- a text filter for narrowing the prompt list by prompt or response
- `Add Card`, `Edit Selected`, and `Remove Selected` controls
- `Alt-S` to start the scheduled study session
- `Alt-X` to start an exam session
- `Alt-Z` to start a quiz session
- `Alt-L` to move to the text filter
- `F5` to refresh the ready summary, ready-list filters, and status bar
- `Ctrl-F` to flag or unflag the selected card
- `Alt-T` to force-start a full-deck study session in random order
- `Alt-Q` to quit from the ready screen in English, or `Alt-S` in Spanish and
  Galician

The normal `Add Card` dialogue can mark a new card as non-reversible while it
is created. Batch add deliberately omits that checkbox so repeated entry stays
quick.

Cards can be marked reversible before a study session starts. A generated reverse card
asks for the original response and expects the original prompt, using separate
review history and scheduling state from its parent card. Cosimo blocks reverse
generation when another card with the same response already has an active
generated reverse card, because the reverse prompt would be ambiguous. Duplicate
responses are otherwise allowed. The ready-list duplicate-response filter helps
find those cards before using bulk reversal, and `Deck -> Undo Last Bulk
Reversal` can remove the reverse cards created by the latest bulk batch while
leaving manual reverse cards and review history in place.

The ready summary, ready-list filters, and status bar refresh about once per
minute while the ready screen is open, so newly due cards become available for
scheduled start without reopening the deck.

At the end of a study session, or when the session is ended early, Cosimo shows
a summary dialogue for that session. The dialogue reports counts, percentages,
and timing, then offers `Continue` to return to the ready screen and
`Save Report` to save the summary under `reports/`.

## Scheduling

Normal `Start` builds a scheduled review queue:

- due cards are reviewed first
- if fewer cards are due than the configured minimum cards per session, Cosimo
  randomly fills the queue from the remaining cards
- if the minimum is `0`, only due cards are scheduled

Cosimo uses an FSRS-style spaced-repetition scheduler. It stores per-card memory
state in the review database, including difficulty, stability, due date,
repetitions, and lapses. Missed or wrong answers move a card back toward
learning; correct answers increase stability and make later intervals longer.

`Force Start` ignores due status and builds a randomised queue containing all
cards that are not suspended or deferred. This gives the user a way to study
even when no cards are due, while still respecting cards the user has
explicitly set aside.
Suspended cards are marked in the ready list, can be toggled from the Card
menu, the ready-list context menu, or Ctrl+S while the ready list has focus,
and are ignored by the status bar when it reports the next due review.
Flagged cards are also marked in the ready list and can be shown with the
flagged-card filter, but flags do not affect scheduling. Flagging is available
from Ctrl-F, the Card menu, the ready-list context menu, and review buttons
after the confidence or recall ratings.
`Study Flagged` starts an unscheduled study session through flagged cards that are not
suspended or deferred. Deferral is also available from the ready list and
during the prompt phase of a session before the answer has been revealed.

The minimum cards per session, automatic deck-backup policy, review database
backup policy, sound notifications, review audio, learning-dashboard
calibration rule, and minimise-to-tray behaviour are set in `Tools -> Options`
and are persisted in `cosimo.ini`.

## Repository Layout

For a fuller map of the codebase, see [architecture.md](architecture.md).

- [src/model.rs](src/model.rs): datum, rating, and review types
- [src/deck_format.rs](src/deck_format.rs): human-editable deck parser and formatter
- [src/review_store.rs](src/review_store.rs): SQLite review storage
- [src/scheduler.rs](src/scheduler.rs): due-card scheduling and minimum-session fill
- [src/exam_mode.rs](src/exam_mode.rs): report-only exam setup, answer
  collection, grading, and summaries
- [src/review_audio.rs](src/review_audio.rs): WAV sidecar audio resolution and
  playback state
- [src/localization.rs](src/localization.rs): message catalogue and locale selection
- [src/main.rs](src/main.rs): wxdragon startup and event wiring
- [src/app_state.rs](src/app_state.rs): loaded-deck state and state mutations
- [src/ready_screen.rs](src/ready_screen.rs): main screen rendering,
  ready-list synchronisation, refresh, and menu state
- [src/resident_tray.rs](src/resident_tray.rs): minimise-to-system-tray lifecycle
- [decks/deck.cosimo-deck](decks/deck.cosimo-deck): default deck file used by the GUI
- [ui/main.xrc](ui/main.xrc): main review window
- [ui/card_editor_dialog.xrc](ui/card_editor_dialog.xrc): add/edit card dialogue
- [ui/options_dialog.xrc](ui/options_dialog.xrc): language and session options
- [ui/stats_dialog.xrc](ui/stats_dialog.xrc): study-session statistics dialogue

User-facing documentation lives in [docs/user-guide.md](docs/user-guide.md)
and [docs/troubleshooting.md](docs/troubleshooting.md).

## Deck Format

Cosimo uses a plain-text deck format designed to stay editable by hand.

Example:

```text
deck_version=2
title=Spanish capitals
author=Example author
:::

Capital of Spain
---
Madrid
=1=

Translate this sentence:
I opened the window.
---
Abri la ventana.
=2=
```

Rules:

- current decks begin with a v2 metadata header ending in `:::`
- `---` separates prompt from response
- `=number=` ends one card and stores its stable card identity
- `=numberi=` marks a card as non-reversible
- `Deck -> Deck Properties` shows deck metadata, and
  `Deck -> Edit Deck Metadata` can edit the standard metadata fields
- a same-stem directory beside the deck file can contain optional WAV review
  audio keyed by card ID, such as `1.prompt.wav` and `1.response.wav`; these
  sidecar files are not included in automatic Cosimo backups
- legacy `===` terminators are accepted and upgraded automatically when the app
  opens the deck
- prompts and responses may span multiple lines
- prompts should be unique; Cosimo refuses normal add and edit actions that
  would create duplicate prompts, and `Deck -> Resolve Duplicate Prompts` can
  repair duplicate prompts introduced by manual deck edits
- duplicate responses are allowed, but from each group of cards with the same
  response, at most one card may have an active generated reverse card
- editing prompt or response text preserves the numbered identity
- review history does not live in the deck file

Generated reverse cards reuse the parent card's audio with prompt and response
swapped. Ordinary review can use prompt and response audio, including optional
guiding tones for automatic playback and a ready-list preview command. Exam
mode can use prompt audio while the learner is answering questions, and can
optionally play prompt audio, response audio, or both during grading and answer
review.
`voice.exe` can use OneCore or SAPI voices. Deck metadata can store
`prompt_voice`, `response_voice`, `prompt_voice_engine`, and
`response_voice_engine` defaults for `voice.exe`; command-line voice and engine
options override those defaults. `Deck -> Edit Deck Metadata` lists voices from
`voice.exe` when available, but the fields remain editable for manual filters.
The helper maintains `audio-manifest.tsv` in the sidecar audio directory so it
can regenerate files when card text, selected voice, or selected engine changes
while leaving unchanged generated audio alone. If no manifest exists yet,
existing selected WAV files are regenerated once to seed a truthful manifest;
if a manifest exists, individual untracked audio files are left untouched on the
current run but added to the manifest for future change detection. The generate
audio command on the Tools menu starts the helper for the current deck when
prompt and response voice metadata are present and generation is allowed, shows
progress, and writes its command output to the `reports` directory. If the menu
item is disabled, choose prompt/response voices and engines in
`Deck -> Edit Deck Metadata`, and check whether the deck is marked as manual
audio. If you keep your own recordings, use the manual-audio checkbox in
`Deck -> Edit Deck Metadata` to write `audio_generation=disabled`, and back up
the sidecar directory yourself; tracked files can be overwritten after card
text or voice-selection changes when generation is allowed.

## Runtime Files

- `decks/`: default portable deck directory beside the application
- `decks/deck.cosimo-deck`: default editable learning content
- `decks/deck.reviews.sqlite3`: review history and scheduling database for the default deck
- `decks/deck/` or another same-stem directory: optional WAV review audio for
  that deck, when present; automatic Cosimo backups do not include these files
- `voice.exe`: optional Windows helper for generating sidecar WAV files from
  installed OneCore or SAPI voices
- `reports/`: saved review, exam, and learning-dashboard reports
- `cosimo.ini`: persisted application settings, the most recently opened deck
  path, and the recent-decks list

These default runtime paths are resolved relative to the application executable,
not the shell or shortcut working directory. If the default deck is missing,
Cosimo creates an empty one on startup.

Older beta builds used `cosimo-settings.txt` and `cosimo-last-open-deck.txt`.
When Cosimo finds either file, it migrates their contents into `cosimo.ini` and
then removes the old file.

SQLite review databases are runtime state and are ignored by Fossil.

## Backup and Recovery

Back up each `.cosimo-deck` file, its matching `.reviews.sqlite3` file, and its
same-stem audio directory if you use review audio. The deck file contains the
editable prompts and responses. The review database contains scheduling state,
ratings, and review history. The audio directory contains WAV recordings and
the generated-audio manifest.

Cosimo also keeps automatic deck-content backups. Before it overwrites an
existing deck file, it copies the current version into the app-level `backups`
directory beside the executable. Backup names use a global rising number and
the deck name, such as `backups/000001-deck.cosimo-deck`. The
`backups/index.txt` file records each backup filename and the original deck
path. These automatic backups protect card text from accidental edits or
migration mistakes, but they do not include review history or sidecar audio.
For a portable copy of a deck and its sidecar files, use `File -> Export Full
Deck`. This writes a zip archive containing the `.cosimo-deck` file and its
same-stem sidecar directory, including audio and the generated-audio manifest,
but not the review database. `File -> Export Full Deck with Study History`
adds a consistent review-database snapshot for personal migration or a complete
manual backup. That archive contains personal study data, so use the no-history
export for sharing deck content. `File -> Full Deck Backup` writes the
deck-and-sidecar bundle into `backups/` with a timestamped name and records it
in `backups/deck-bundle-index.txt`.

Compressed bundle support is preliminary and restore is currently manual. With
Cosimo closed, extract the zip contents into the `decks` directory and allow
overwrites only if you mean to replace the current deck, sidecar audio, manifest,
or review database. Restoring a bundle can lose newer data if it overwrites
newer files.

The deck backup option in `Tools -> Options` controls automatic deck-content
backups:

- `Full`: keep every automatic deck backup.
- `Last only`: keep only the newest automatic backup for each original deck
  path.
- `None`: do not create automatic deck backups.

The review database backup option controls whether Cosimo keeps one automatic
review-database backup per review database. When set to `On session start`,
Cosimo refreshes that retained backup in the app-level `backups` directory when
a study session starts. The database backup index is
`backups/review-db-index.txt`. When set to `Off`, Cosimo does not create or
refresh review-database backups. Bulk reversible-card creation is also treated
as a significant database change: when review-database backups are enabled,
Cosimo refreshes the retained backup before writing and warns that the retained
backup will be overwritten.

`Tools -> Reclaim Database Space` runs SQLite `VACUUM` on the review database
without deleting dormant review data and without overwriting the retained
review-database backup.

For the default deck, back up:

- `decks/deck.cosimo-deck`
- `decks/deck.reviews.sqlite3`, if it exists
- `decks/deck/`, if you use review audio

For another deck such as `spanish.cosimo-deck`, back up the neighbouring
`spanish.reviews.sqlite3` file and any same-stem sidecar audio directory as
well. Close Cosimo before copying or restoring these files so SQLite is not in
the middle of a write.

Restoring only the `.cosimo-deck` file restores the cards but loses scheduling
history. Restoring both files preserves the cards and their review history.
The optional `cosimo.ini` file can also be backed up to preserve language,
session settings, backup policy, the last opened deck, and the recent-decks
list.

When Cosimo opens a review database, it runs SQLite's quick integrity check
before applying schema setup or deck migrations. It also checks higher-level
consistency after opening, including stored rating and schedule values,
study-session links, and active reversible cards whose responses have become
ambiguous. Duplicate prompts introduced by manual deck edits are reported as a
deck warning rather than a database failure; use the duplicate prompt filter or
`Deck -> Resolve Duplicate Prompts` to repair them. If either database check
fails, close Cosimo and restore the matching `.reviews.sqlite3` file from an
external backup, or fix the active deck if the error is caused by multiple
active reversed cards in the same duplicated-response set.

To restore an automatic deck backup, close Cosimo and copy the chosen backup
over the active `.cosimo-deck` file. If you also need to recover scheduling
history, restore the matching `.reviews.sqlite3` file from an external backup
or from Cosimo's retained review-database backup.

Use `Tools -> Options -> Delete Old Backups` to keep only the newest automatic
backup for each original deck path. Cosimo asks for confirmation before deleting
or renumbering backup files.

## Localisation

The current message catalogue supports English, Spanish, and Galician. Runtime
messages and most control labels go through the localisation layer in
[src/localization.rs](src/localization.rs).

Language is chosen in this order:

- `COSIMO_LANGUAGE`, when set to a recognised code
- the persisted language in `cosimo.ini`
- the system locale
- English

`en`, `en-US`, and similar English codes resolve to English. `es`, `es-ES`,
`es-MX`, and similar Spanish codes resolve to Spanish. `gl`, `gl-ES`, and
similar Galician codes resolve to Galician. Unknown codes fall back to English.
On Windows, Cosimo reads the user's default locale through the platform locale
API. On other platforms, it checks `LC_ALL`, `LC_MESSAGES`, `LANG`, and
`LANGUAGE`.

## Build

The default build artifact is the GUI application.

```bash
cargo build
```

wxdragon and native wxWidgets pieces can take time to compile the first time.
Avoid `cargo clean` unless you actually need to throw away cached build output.

## Test

Fast library-only tests:

```bash
cargo test --lib --no-default-features
```

Check the GUI binary:

```bash
cargo check --bin cosimo
```

Release preparation should also exercise the Windows audio helper and release
package metadata:

```bash
cargo test --bin voice
cargo check --no-default-features --features release-tool --bin cosimo-release
cargo package --locked --offline --allow-dirty
```

Fossil also runs pre-commit verification through
[tools/pre-commit-check.sh](tools/pre-commit-check.sh),
which executes both test commands before a normal commit.

## Run

```bash
cargo run
```

The application defaults to `decks/deck.cosimo-deck` beside the executable.
Review history is stored beside each deck, using the deck stem plus
`.reviews.sqlite3`; for example, `decks/spanish.cosimo-deck` uses
`decks/spanish.reviews.sqlite3`.

## Review Flow

1. On startup, review the ready-screen summary and the list of card prompts.
2. Add, edit, or remove cards before starting the session.
3. Start the scheduled session with `Alt-S`, or force-start the whole deck with
   `Alt-T`.
4. For each prompt, enter `1` through `4` for the pre-response guess, or press
   Space to reveal the response without recording a guess.
5. After the response is shown, enter `1` through `4` for recall feedback. If
   the card text needs correction, press `e` to edit it before rating recall.
6. Enter `0` during either rating phase to end the session early.
7. Review the statistics and continue back to the ready screen.

Exam mode is started separately with `Alt-X` or `Start Exam`. It samples active
cards randomly, excludes suspended and deferred cards, collects typed answers,
and produces a report-only summary. It can also run with a simple minute-based
time limit; the current answer is submitted when time expires, then Cosimo
pauses on a time-out notice before moving to grading, answer review, or the
summary. Exam mode does not record review events or update schedules.

## Accessibility Notes

The current review flow is built around native text and button controls:

- the ready screen exposes the card set through a native list box
- the ready screen supports keyboard access to start, force-start, and quit via
  mnemonics
- the prompt content is focusable and read by screen readers before rating
- Space can reveal the response without a pre-response rating
- the response content becomes focusable after the pre-response rating or
  direct reveal
- numeric keys activate ratings directly
- `e` opens the current card for editing after reveal and returns focus to the
  previous post-response control
- the statistics dialogue focuses the summary text first
- the card editor uses normal text controls for prompt and response editing
- informative messages are intentionally concise and avoid repeating focus
  information that the screen reader already announces

Accessibility regressions should be treated as blocking defects.

The beta accessibility acceptance check is recorded in
[docs/accessibility-acceptance.md](docs/accessibility-acceptance.md).

Known defect: on the target Windows screen-reader stack, tabbing or
shift-tabbing into the ready-screen prompt list can announce the selected item
twice. Arrow-key navigation inside the list, selection, edit, remove, and
review startup remain functional. This is currently treated as a known native
list accessibility defect rather than a release blocker.

## Version Control

This repository uses Fossil, not Git.

Useful commands in this checkout:

```bash
FOSSIL_HOME="$PWD" fossil status
FOSSIL_HOME="$PWD" fossil diff
FOSSIL_HOME="$PWD" fossil add path/to/file
FOSSIL_HOME="$PWD" fossil commit --nosync path/to/file -m "Describe the change"
```

`--nosync` is currently relevant because this checkout may try to autosync
against a readonly peer checkout and fail before the local commit completes.

This checkout also carries a Fossil `before-commit` hook in
[.fossil-settings/hooks](.fossil-settings/hooks).
If you absolutely have to bypass that hook, Fossil supports `--no-verify`.

If you add a new file such as an XRC resource, remember to `fossil add` it
before committing.
