Skip to content

fix(lm): paragraph is a hard prediction boundary - #102

Merged
willwade merged 1 commit into
mainfrom
fix/paragraph-hard-boundary
Oct 16, 2026
Merged

willwade merged 1 commit into
mainfrom
fix/paragraph-hard-boundary

Conversation

@willwade

@willwade willwade commented Oct 15, 2026 •

Copy link
Copy Markdown

What this fixes

Dasher-Windows tester report (v0.1.33): "When you zoom an "enter", the canvas is supposed to reset right? But it doesn'"'"'t, it remembers the last punctuation you put. Then you have to zoom a capital letter."

Root cause

The PPM context chained through the paragraph symbol. The bundled English corpus breaks paragraphs as .\r\n (94% of lines start with a capital after CRLF), so the [.][para] context matched training and predicted sentence start — but any other predecessor of the newline produced a sequence the corpus never contains, and the escape mixture degraded the after-newline prediction to a mid-sentence blend:

context before newline uppercase-group mass (before → after)
. + newline 0.95 → 0.92
bare word + newline 0.67 → 0.92
zoomed space + newline 0.67 → 0.92
comma + newline 0.72 → 0.92
blank line (double newline) 0.67 → 0.92

(Measured with dasher_get_probabilities against the real engine + bundled corpus; "uppercase-group mass" = the share of the top-level Upper case Latin letters group in the crosshair distribution.)

Fix

A paragraph now starts the canonical paragraph-start context: the alphabet default context (trailing whitespace stripped — the corpus has no [space][para] sequences) followed by the paragraph symbol. Three sites, all in CAlphabetManager:

  • GetContextSymbols (seeded/rebuilt contexts): symbols before the last paragraph symbol are replaced by the canonical seed symbols
  • CreateSymbolNode (live zoom): the paragraph node'"'"'s context is the canonical seed context rather than the parent chain extended
  • CSymbolNode::SetFlag NF_COMMITTED (adaptive learn): the trie keeps the learned [x][para] chain, but the node'"'"'s prediction context becomes the canonical seed

Training is unchanged — PPM vine learning already records after-paragraph statistics at every order. Alphabets without a paragraph symbol are untouched (SymbolPrintsNewLineCharacter guards every site).

Verification

  • Full suite green: 46/46 incl. PPM goldens, LM correctness, direct-mode shadow, property invariants
  • New mapping-free regression test (test_paragraph_context.cpp): ten predecessor variants must yield exactly the canonical distribution, and it must differ from mid-word / bare-period contexts

Follow-up needed on the Dasher-Windows side after this releases: bump the submodule pin.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; the remaining feedback is a non-blocking test gap.

Findings

  1. P2 Live newline paths lack coverage ▶

Summary

The PR makes newline predictions start from a consistent paragraph context.

  • Paragraph breaks now reset Dasher’s next-character predictions.

No new actionable issues were found.

Reviews (5) · Last reviewed commit: "fix(lm): paragraph is a hard prediction ..." · Reviewed by Greptile

Comment thread src/DasherCore/AlphabetManager.cpp Outdated
Comment thread tests/test_paragraph_context.cpp
@willwade
willwade force-pushed the fix/paragraph-hard-boundary branch 3 times, most recently from 3b7c35a to de52c10 Compare October 15, 2026 22:12
Comment thread src/DasherCore/AlphabetManager.cpp Outdated
@willwade
willwade force-pushed the fix/paragraph-hard-boundary branch from de52c10 to 203351e Compare October 15, 2026 22:28
Comment thread src/DasherCore/AlphabetManager.cpp
Comment thread tests/test_paragraph_context.cpp Outdated
"When you zoom an enter, the canvas is supposed to reset... but it
doesn'"'"'t, it remembers the last punctuation you put. Then you have to
zoom a capital letter."

The PPM context chained THROUGH the paragraph symbol. The bundled
English corpus breaks paragraphs as ".\r\n" (94% of lines start with a
capital after CRLF), so the [.][para] context matched training and
predicted sentence start - but any other predecessor of the newline
(a zoomed space, a bare word, a comma, a blank line) produced a
sequence the corpus never contains, and the escape mixture degraded
the after-newline prediction to a mid-sentence blend (uppercase group
0.67 vs 0.92 after ". "; lowercase group 0.25).

A paragraph now starts the canonical paragraph-start context: the
alphabet default context (trailing whitespace stripped - the corpus
has no [space][para] sequences) followed by the paragraph symbol.
Measured: every predecessor variant now predicts identically to the
known-good period+newline case. Sites, all paragraph-symbol-guarded:

- CAlphabetManager::GetContextSymbols (seeded/rebuilt contexts):
  symbols before the last paragraph symbol are replaced by the
  canonical seed symbols;
- CAlphabetManager::CreateSymbolNode (live zoom): the paragraph
  node'"'"'s context is the canonical seed context rather than the
  parent chain extended; CRoutingAlphMgr::CreateSymbolNode (which
  overrides it) applies the same reset, entering the BASE symbol;
- CSymbolNode::SetFlag NF_COMMITTED (adaptive learn): the trie keeps
  the learned [x][para] chain, but the node'"'"'s prediction context
  becomes the canonical seed. Routing alphabets translate the route
  symbol down via the new CAlphabetManager::ContextSymbol virtual -
  EnterSymbol accepts base symbols only (greptile P1: passing the
  route number failed the range assertion in debug and lost the
  paragraph context in release).

Training is unchanged - PPM vine learning already records after-
paragraph statistics at every order. Alphabets without a paragraph
symbol are untouched.

Full suite green (47/47) incl. PPM goldens and LM correctness. Two
regression tests, mapping-free: ten seeded predecessor variants must
yield exactly the canonical distribution; and a LIVE zoom test steers
the mouse into the actual paragraph node from a word+space state and
requires the post-Enter distribution to equal the canonical one.

Signed-off-by: will wade <willwade@gmail.com>
@willwade
willwade force-pushed the fix/paragraph-hard-boundary branch from 203351e to 0ad4902 Compare October 15, 2026 22:54
@willwade
willwade merged commit 1c09bb4 into main Oct 16, 2026
15 checks passed
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