feat: write equations through the page model; give new identities n 1

Math::paragraph builds the linear text and per-run object data from a Math
tree (Latin letters as mathematical italics, one run per object control,
the equation editor's Cambria Math italic style with the math flags and
language), and a new equation pass in the page writer rewrites a changed
equation paragraph the way OneNote stores one: the text, one style object
per distinct span format, run boundaries, the text-run data array naming
each run's inline object, and the language marker and flags every native
equation text object carries. tools/native_math.py types expressions
through the equation editor with AutoHotkey during a capture;
corpus/math-edit/native-editor adds subscripts, a sub-superscript,
parentheses, an integral and a sum to the MathML oracle, and the mapping
now covers them (n-ary operators take limits as scripts for integrals and
above/below otherwise; object arguments render in rows). The oracle tools
treat equation runs like hidden ones, since native XML exports them as
MathML rather than text.

Gating the ten-equation candidate found OneNote 2010 silently dropping an
outline element in roughly one build of five: deterministic per file,
structurally indistinguishable from the ones that rendered, and never seen
before because earlier rows added few paragraphs. OneNote never stores an
object as {guid},0, and with page::text::new_id giving n 1 every one of
eighteen builds and the written candidate rendered; corpus/math-edit/
native-drop keeps the dropped build, the cold read and a relocation
experiment. The transaction writer also keeps native files' 1 KiB
reservation after a transaction-log fragment that ends the file.

corpus/math-edit/written is the cold read of all ten expressions with a
screenshot; tools/test_math_edit.py checks it against the expected MathML.

Assisted-by: claude-fable-5.1
6478bd1e6eclover caruso committed on 9/26/2026, 3:26:20 AMparentdb49720
64 files changedLine totals unavailable