Repository navigation
Make every fix land on the text the app actually has - #2
Merged
Merged
Conversation
Keys typed right after a space reached the app before the fix began, so its backspaces ate them; a field read taken while keys were still queued counted them twice, and the doubled letter was then fixed by deleting the space before the word. The hook now numbers every key and click that reaches the app: fixes and completions start capture only if nothing got through after their key, and field text is read with no key in flight and kept only if it agrees. Arrows, Tab, Esc and edit keys re-read the field later; stale tokens stay out of ghosts. Verified with cargo test --workspace. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
A fix is typed only after reading that the text before the caret ends with the word at a word break, so a shadow that counted a key twice or a field the app changed can no longer make it delete a space. The check after typing is read again twice, 200 ms apart, before it counts as a miss; a miss logs a masked shape of both endings and re-reads the field instead of trusting it. Misses are stored per app: over one in fifty of its last 20+ fixes turns auto-fix off there for a week, and the dashboard says so. Verified with cargo test. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
The typing model fixed `htmlr` to `humor`, `htmml` to `hmm`, `xlsx` to `ls` and cut `healthyep` down to `healthy`. A word without a vowel, or a dictionary word with two or more letters added at the end, is now at most a suggestion. A doubled last letter (`thatt`) is still fixed. Verified with cargo test -p cc-correct. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
The typing model picks by key distance alone: `morth` became `north` where the sentence wanted `month`, `calory` became `color`. Before an S0 fix that is not a doubled letter goes in, the loaded model is asked for its likeliest next words after the text before the typo, with keys captured meanwhile. A dictionary word close to the typo that it rates four times higher stops the fix. No engine, or no answer within 150 ms, leaves the fix as it was. Verified with cargo test -p cc-app -p cc-engine. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
A fix pair that was undone (reverted, or backspaced over within 3 s) and never kept, or undone three times and at least as often as kept, is no longer typed. Tuning counts those quick overwrites as undos too. Demoted rules were only held in memory from the run that demoted them, so a restart applied them again; they now load from events.db at startup. Verified with cargo test -p cc-app -p cc-store. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
The model check turns capture on before asking; if replace_tail then found a key had got through and gave up, nothing ended that capture, and every key typed afterwards would have been held and never replayed. replace_tail now ends a capture it finds on when it gives up at that point. Verified with cargo test -p cc-app. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
A spelling fix is S0 only when the word it picks is doubled keys away from what was typed, or one edit away with the same first letter (or the first two letters swapped, as in htis). The e2e run typed calory, two edits from both color and calorie, and morth, which the keyboard reads as north and the sentence as month; both were auto-fixed to the wrong word. In the owner's history, non-doubled fixes that changed the first letter were kept 3 of 7 times and two-edit fixes 9 of 15. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
on_word_boundary never looked at the focused element, so fixes were typed into read-only pages, password fields and apps the privacy settings turn off, and typos were learned from those fields too. Before a fix, and before learning a typo, the app now reads the focus the way completions do. It skips the fix when the field is not one it may type in, or when the focus moved since the word was typed. The model check failed with os error 10053 when it reused a pooled connection that llama-server had closed. Its client now keeps no idle connections. A fix that needs the model's view and gets no answer within 300 ms is skipped instead of typed. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
tools/e2e/contenteditable.ps1 types seven sentences with typos into a role=textbox contenteditable at 45 ms per key, 12 ms after a space, and checks each word that landed: it must be what was typed or that word's allowed fix. Two lines hold typos that go through the model check. With -Bare the field has no role, UIA reports a group, and nothing may change. The script refuses to type unless the test field has the focus. Claude-Session: https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes could delete one character too many, joining two words, or eat keys typed right after a space: keys typed during the check reached the app first, and field reads taken while keys were still queued counted them twice. The hook now numbers every key and click; a fix starts only if nothing reached the app after its key, and only after reading that the field ends with the word. The read-back after typing is repeated before it counts as a miss, and an app with too many misses goes suggest-only.
Auto-fix also never checked the focused field, so it typed into read-only pages, password fields and apps turned off in privacy settings. It now uses the same check as completions. Spelling auto-fix needs doubled keys or one edit that keeps the first letter (
caloryandmorthwere fixed to the wrong word). A guessed fix waits up to 300 ms for the model and is skipped without an answer. Undone pairs are never typed again, and demotions survive restarts.Risk: fewer fixes when typing very fast, when UIA is slow, or when the model takes over 300 ms (it took 156–245 ms in the e2e run).
cargo test --release --workspace --exclude cc-benchpasses.tools/e2e/contenteditable.ps1ran 7 times in a Chrome textbox field and once in a bare field, with 0 failed lines.https://claude.ai/code/session_01DiRshLaPboWShtRAdGazjy