Skip to content

Release 1.2.3: confidence engine, stats and practice UX - #32

Merged
egno merged 13 commits into
mainfrom
dev
Jul 29, 2026
Merged

Release 1.2.3: confidence engine, stats and practice UX#32
egno merged 13 commits into
mainfrom
dev

Conversation

@egno

@egno egno commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • Confidence: min(speed, accuracy) instead of product; recency-weighted windowed aggregates (0.7 decay) for speed, accuracy, and attempts; docs/wiki updates.
  • Stats: single #stats-trends block via format_metric_trend_block; layout + focus grids; removed WPM trend row and session history; heatmap hint and layout order (title → trends → caption → heatmap).
  • Practice UX: word-wrap at · boundaries; lesson colors (white/grey42/red/yellow); bold-underline cursor; Last row WPM/acc/time with deltas vs window baseline; focus note shows speed ratio and accuracy %.
  • HUD: Learn segment activity vs goal independent; 5s idle pauses learn timer toward daily goal.
  • Version bump to 1.2.3 (pyproject.toml, domain/version.py, uv.lock, CHANGELOG).

Test plan

  • uv run pytest -q — 351 passed, 4 deselected
  • Manual: practice session — idle pause/resume, Last deltas, typing colors and wrap
  • Manual: stats — overview/focus grids, key drill-down, Esc back to overview
  • Manual: HUD Learn dim/green states when goal reached vs idle

Made with Cursor

Egno and others added 13 commits July 29, 2026 11:05
Expose session window and attempt floors in settings so unlocks, focus,
and heatmap respond to tunable confidence inputs; round scores to two
decimals so weak/mastered decisions match what practice displays.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove session window and attempt floors from Settings so routine saves
do not overwrite advanced adaptive-engine values; document settings.toml.

Co-authored-by: Cursor <cursoragent@cursor.com>
…in comments.

Also fixes a pyright error in _snapshot_unlock_state (list invariance on
Iterator vs list) that CI never reached because ruff failed first.
FOCUS_CHAR_BOOST weighting (added in b0f130e) changed the generated
lesson text but the checked-in snapshot was never refreshed to match.
Confidence uses min(speed, accuracy) with recency-weighted session
aggregates; stats trends unified on one widget; practice gets word-wrap,
typing colors, underline cursor, idle learn timer, and HUD Last deltas.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep dev 1.2.3 release changes when resolving conflicts with main (1.2.2).

Co-authored-by: Cursor <cursoragent@cursor.com>
Ruff import order, line length, unused imports, and aggregate int casts.

Co-authored-by: Cursor <cursoragent@cursor.com>
Run `uv run pre-commit install` once per clone to enable lint on commit.

Co-authored-by: Cursor <cursoragent@cursor.com>
Matches CI: uv run pyright with pass_filenames false so pyproject.toml scope applies.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use explicit grid/spark_width kwargs in format_metric_trend_block and
TypedDict session fixtures in tests instead of untyped dict unpacking.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Baselines were stale after 1.2.3 presentation changes; README now lists
what pre-commit covers vs the macOS snapshot job.

Co-authored-by: Cursor <cursoragent@cursor.com>
@egno
egno merged commit bef1117 into main Jul 29, 2026
8 checks passed
@egno egno mentioned this pull request Jul 29, 2026
1 task
@egno
egno deleted the dev branch July 29, 2026 15:19
egno added a commit that referenced this pull request Jul 31, 2026
* Add confidence tuning settings and align rounded scores across UI.

Expose session window and attempt floors in settings so unlocks, focus,
and heatmap respond to tunable confidence inputs; round scores to two
decimals so weak/mastered decisions match what practice displays.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bump version to 1.2.2 on dev.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Make confidence tuning config-file only.

Remove session window and attempt floors from Settings so routine saves
do not overwrite advanced adaptive-engine values; document settings.toml.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix lint errors: unused imports, unsorted imports, ambiguous unicode in comments.

Also fixes a pyright error in _snapshot_unlock_state (list invariance on
Iterator vs list) that CI never reached because ruff failed first.

* Regenerate stale practice-screen snapshot.

FOCUS_CHAR_BOOST weighting (added in b0f130e) changed the generated
lesson text but the checked-in snapshot was never refreshed to match.

* Release 1.2.3: windowed confidence, stats and practice UX.

Confidence uses min(speed, accuracy) with recency-weighted session
aggregates; stats trends unified on one widget; practice gets word-wrap,
typing colors, underline cursor, idle learn timer, and HUD Last deltas.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix lint errors after merge for PR #32.

Ruff import order, line length, unused imports, and aggregate int casts.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add ruff pre-commit hook.

Run `uv run pre-commit install` once per clone to enable lint on commit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add pyright pre-commit hook.

Matches CI: uv run pyright with pass_filenames false so pyproject.toml scope applies.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix pyright errors so pre-commit pyright hook passes.

Use explicit grid/spark_width kwargs in format_metric_trend_block and
TypedDict session fixtures in tests instead of untyped dict unpacking.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update README for 1.2.3 stats layout and pre-commit hooks.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Refresh practice/stats UI snapshots and document CI checks.

Baselines were stale after 1.2.3 presentation changes; README now lists
what pre-commit covers vs the macOS snapshot job.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ignore lead spaces

* Document custom layouts and fix platform paths; refresh Settings layout dropdown when TOML layouts change without restart. Bump to 1.2.3 and expand layout TOML/repo tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bias word-list drills toward weak bigrams like Markov mode.

Word-list sampling now scores dictionary words with transition weights so
adaptive lessons practice measured weak pairs, not just weak keys.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Gate unlocks on measured transition confidence and tune focus bias via settings.toml.

New keys stay locked until unlocked bigrams with data meet the confidence threshold; lesson generation boosts weak focus keys and transitions using configurable multipliers (not exposed in the Settings UI).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Prioritize weak keys over transition focus and drop same-key bigrams.

Same-letter pairs no longer enter transition stats or unlock gates; lesson
building favors letter drill while any unlocked key is below mastery.
Leading skip keys also apply at word boundaries for accidental spaces.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor

* refactoring

* refactor

* refactor

* refactor

* refactor

* refactor

* Release 1.3.0: weak-focus word quota and lesson variety.

Weak-focus lessons now guarantee a configurable share of focus-matching
words, sample the wordlist without replacement, and fall back to Markov
when the pool is exhausted. Adds lesson_word_count, focus_word_min_fraction,
and max_word_repeats to settings.toml, fixes empty-transition rebuild loops,
and hardens edge cases around invalid settings and tiny alphabets.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add configurable generated word length for lessons and WPM math.

Users can set min/max generated word length in settings; the generator,
Markov fallback padding, and WPM↔CPM conversion use those bounds so
target speed matches the text they actually type.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Align wordlist sampling with generated word bounds and default 2-4.

Dictionary words in lessons now honor generated_word_min/max (same as
Markov), defaults tighten to 2-4 for shorter practice text, with
integration tests for settings.toml and WPM conversion paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Egno <egno@duck.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
egno added a commit that referenced this pull request Jul 31, 2026
* Add confidence tuning settings and align rounded scores across UI.

Expose session window and attempt floors in settings so unlocks, focus,
and heatmap respond to tunable confidence inputs; round scores to two
decimals so weak/mastered decisions match what practice displays.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bump version to 1.2.2 on dev.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Make confidence tuning config-file only.

Remove session window and attempt floors from Settings so routine saves
do not overwrite advanced adaptive-engine values; document settings.toml.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix lint errors: unused imports, unsorted imports, ambiguous unicode in comments.

Also fixes a pyright error in _snapshot_unlock_state (list invariance on
Iterator vs list) that CI never reached because ruff failed first.

* Regenerate stale practice-screen snapshot.

FOCUS_CHAR_BOOST weighting (added in b0f130e) changed the generated
lesson text but the checked-in snapshot was never refreshed to match.

* Release 1.2.3: windowed confidence, stats and practice UX.

Confidence uses min(speed, accuracy) with recency-weighted session
aggregates; stats trends unified on one widget; practice gets word-wrap,
typing colors, underline cursor, idle learn timer, and HUD Last deltas.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix lint errors after merge for PR #32.

Ruff import order, line length, unused imports, and aggregate int casts.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add ruff pre-commit hook.

Run `uv run pre-commit install` once per clone to enable lint on commit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add pyright pre-commit hook.

Matches CI: uv run pyright with pass_filenames false so pyproject.toml scope applies.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix pyright errors so pre-commit pyright hook passes.

Use explicit grid/spark_width kwargs in format_metric_trend_block and
TypedDict session fixtures in tests instead of untyped dict unpacking.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update README for 1.2.3 stats layout and pre-commit hooks.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Refresh practice/stats UI snapshots and document CI checks.

Baselines were stale after 1.2.3 presentation changes; README now lists
what pre-commit covers vs the macOS snapshot job.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ignore lead spaces

* Document custom layouts and fix platform paths; refresh Settings layout dropdown when TOML layouts change without restart. Bump to 1.2.3 and expand layout TOML/repo tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bias word-list drills toward weak bigrams like Markov mode.

Word-list sampling now scores dictionary words with transition weights so
adaptive lessons practice measured weak pairs, not just weak keys.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Gate unlocks on measured transition confidence and tune focus bias via settings.toml.

New keys stay locked until unlocked bigrams with data meet the confidence threshold; lesson generation boosts weak focus keys and transitions using configurable multipliers (not exposed in the Settings UI).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Prioritize weak keys over transition focus and drop same-key bigrams.

Same-letter pairs no longer enter transition stats or unlock gates; lesson
building favors letter drill while any unlocked key is below mastery.
Leading skip keys also apply at word boundaries for accidental spaces.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor

* refactoring

* refactor

* refactor

* refactor

* refactor

* refactor

* Release 1.3.0: weak-focus word quota and lesson variety.

Weak-focus lessons now guarantee a configurable share of focus-matching
words, sample the wordlist without replacement, and fall back to Markov
when the pool is exhausted. Adds lesson_word_count, focus_word_min_fraction,
and max_word_repeats to settings.toml, fixes empty-transition rebuild loops,
and hardens edge cases around invalid settings and tiny alphabets.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add configurable generated word length for lessons and WPM math.

Users can set min/max generated word length in settings; the generator,
Markov fallback padding, and WPM↔CPM conversion use those bounds so
target speed matches the text they actually type.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Align wordlist sampling with generated word bounds and default 2-4.

Dictionary words in lessons now honor generated_word_min/max (same as
Markov), defaults tighten to 2-4 for shorter practice text, with
integration tests for settings.toml and WPM conversion paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: restore CI after v1.3.0 merge artifacts

Remove duplicated session timer helpers, refresh practice/settings
snapshots, and skip Unix permission tests on Windows where chmod
semantics differ.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Egno <egno@duck.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
egno added a commit that referenced this pull request Aug 5, 2026
* Add confidence tuning settings and align rounded scores across UI.

Expose session window and attempt floors in settings so unlocks, focus,
and heatmap respond to tunable confidence inputs; round scores to two
decimals so weak/mastered decisions match what practice displays.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bump version to 1.2.2 on dev.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Make confidence tuning config-file only.

Remove session window and attempt floors from Settings so routine saves
do not overwrite advanced adaptive-engine values; document settings.toml.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix lint errors: unused imports, unsorted imports, ambiguous unicode in comments.

Also fixes a pyright error in _snapshot_unlock_state (list invariance on
Iterator vs list) that CI never reached because ruff failed first.

* Regenerate stale practice-screen snapshot.

FOCUS_CHAR_BOOST weighting (added in b0f130e) changed the generated
lesson text but the checked-in snapshot was never refreshed to match.

* Release 1.2.3: windowed confidence, stats and practice UX.

Confidence uses min(speed, accuracy) with recency-weighted session
aggregates; stats trends unified on one widget; practice gets word-wrap,
typing colors, underline cursor, idle learn timer, and HUD Last deltas.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix lint errors after merge for PR #32.

Ruff import order, line length, unused imports, and aggregate int casts.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add ruff pre-commit hook.

Run `uv run pre-commit install` once per clone to enable lint on commit.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add pyright pre-commit hook.

Matches CI: uv run pyright with pass_filenames false so pyproject.toml scope applies.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix pyright errors so pre-commit pyright hook passes.

Use explicit grid/spark_width kwargs in format_metric_trend_block and
TypedDict session fixtures in tests instead of untyped dict unpacking.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Update README for 1.2.3 stats layout and pre-commit hooks.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Refresh practice/stats UI snapshots and document CI checks.

Baselines were stale after 1.2.3 presentation changes; README now lists
what pre-commit covers vs the macOS snapshot job.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ignore lead spaces

* Document custom layouts and fix platform paths; refresh Settings layout dropdown when TOML layouts change without restart. Bump to 1.2.3 and expand layout TOML/repo tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Bias word-list drills toward weak bigrams like Markov mode.

Word-list sampling now scores dictionary words with transition weights so
adaptive lessons practice measured weak pairs, not just weak keys.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Gate unlocks on measured transition confidence and tune focus bias via settings.toml.

New keys stay locked until unlocked bigrams with data meet the confidence threshold; lesson generation boosts weak focus keys and transitions using configurable multipliers (not exposed in the Settings UI).

Co-authored-by: Cursor <cursoragent@cursor.com>

* Prioritize weak keys over transition focus and drop same-key bigrams.

Same-letter pairs no longer enter transition stats or unlock gates; lesson
building favors letter drill while any unlocked key is below mastery.
Leading skip keys also apply at word boundaries for accidental spaces.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor

* refactoring

* refactor

* refactor

* refactor

* refactor

* refactor

* Release 1.3.0: weak-focus word quota and lesson variety.

Weak-focus lessons now guarantee a configurable share of focus-matching
words, sample the wordlist without replacement, and fall back to Markov
when the pool is exhausted. Adds lesson_word_count, focus_word_min_fraction,
and max_word_repeats to settings.toml, fixes empty-transition rebuild loops,
and hardens edge cases around invalid settings and tiny alphabets.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Add configurable generated word length for lessons and WPM math.

Users can set min/max generated word length in settings; the generator,
Markov fallback padding, and WPM↔CPM conversion use those bounds so
target speed matches the text they actually type.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Align wordlist sampling with generated word bounds and default 2-4.

Dictionary words in lessons now honor generated_word_min/max (same as
Markov), defaults tighten to 2-4 for shorter practice text, with
integration tests for settings.toml and WPM conversion paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: restore CI after v1.3.0 merge artifacts

Remove duplicated session timer helpers, refresh practice/settings
snapshots, and skip Unix permission tests on Windows where chmod
semantics differ.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: calibrating focus display and skill heatmap without lesson bias

Heatmap and HUD used attempt-ramped confidence, so calibrating keys could
look mastered while lessons still treated them as uncertain. skill_of keeps
display honest without changing scheduling; calibrating is first-class in
the UI with shorter HUD copy and Focus-States wiki docs.

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: split skill from confidence for unlock and focus

Unlock the next key from per-key skill plus attempt floor, not ramped
confidence or bigram thresholds. Transition focus uses skill-only gating
so calibrating keys no longer block bigram focus; lesson sampling adds
coverage-deficit weight for under-sampled keys.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: keep dictionary word bounds separate from Markov bounds

Wordlist sampling was using generated_word_min/max, so valid imported words were dropped or capped incorrectly while Markov fill should stay on its own 2–4 range.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix transition focus when measured keys are ready but bigrams lag.

Unpracticed auto-unlocked keys no longer block transition focus; two-key drills get an unmeasured-pair fallback and sparse transition weighting.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Prioritize bigram practice for newly-mastered keys, gate progression on it

Give a just-mastered key's bigrams sampling weight and focus priority right
away instead of waiting for them to appear by chance (newest_key_unmeasured_pairs,
shared by focus selection and lesson weighting). Extend compute_unlocked with
an optional transition gate so the next letter also waits on the newest key's
single weakest measured bigram, bounded to one pair with a stall-attempts
safety valve so a stuck pair can't block progression forever.

Fix session_use_cases' unlock snapshot to pass transitions/gate settings into
compute_unlocked too, so alphabet_size can't ratchet past what the gate
actually cleared. Move the gate's shared "newest practiced key" primitives
into a neutral domain/newest_key module so focus.py and unlock.py depend on
it instead of each other.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* refactor: tighten skill/confidence split and lesson gating

Keep unlock and focus on measured skill while confidence drives remedial pacing; extract session_queries and refactor BuildLesson gating/focus resolution. Persist word-length bounds on SessionResult (schema v4) for remedial WPM gates and split domain tests with doc updates.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: keep wordlist words intact during focus drill

Resample dictionary words for focus bigrams instead of splicing chars into real words.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Release 1.3.1.

Skill/confidence split for unlocks and focus, bigram progression gating,
dictionary vs Markov word bounds, and word-list focus drill fixes.
Refresh README, wiki, CHANGELOG, and demo GIF.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Egno <egno@duck.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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