| 1 | # Native paragraph reconciliation controls |
| 2 | |
| 3 | `before` contains sixteen OneNote-authored pages and one unchanged source page. |
| 4 | `tools/native/paragraph-reconciliation.ps1` creates these cases and applies the |
| 5 | separate COM replacement controls retained in `remote`. Whole-page COM updates |
| 6 | replace rich-text identities, including unchanged text. Every local split/join |
| 7 | and dependent edit therefore remains a conflict without remote publication. |
| 8 | |
| 9 | `keyboard` begins from the same notebook and records actual native keystrokes, |
| 10 | screenshots, XML, and saved bytes. Prefix/boundary edits, children, bullets, tags, |
| 11 | formatting, sibling replacement, and empty-paragraph typing exercise independent |
| 12 | changes. Bullets alter ancestry: the first paragraph gains an outline group, |
| 13 | and a later bullet becomes a child of its preceding paragraph. Replacing a whole |
| 14 | selected sibling creates a new paragraph; the split/join targets retain identity. |
| 15 | |
| 16 | `reconciled` retains Rust output and a fresh OneNote cold-open. Each local |
| 17 | split or join is a page-model save with a dependent text edit, with SQLite |
| 18 | reopen between local acknowledgements and publications. Six cases merge |
| 19 | automatically against the keyboard changes; ten publish after the conflicting |
| 20 | page is reviewed against the remote page. Public tests check all 32 receipts, |
| 21 | exact active graph/child levels, native characters/styles, and the saved |
| 22 | graph's identities. COM replacement controls retain all sixteen local branches |
| 23 | across reopen without publishing. |
| 24 | |
| 25 | Regenerate keyboard controls with `tools/native_runner.py` on `before/notebook`, |
| 26 | using `--expected-pages 17 --inspect --collect-notebook`. Once inspection is |
| 27 | ready, run `tools/native_paragraph_reconciliation.py OUTPUT`; it records actions |
| 28 | and requests final capture. The runner removes its owned clone. The ignored |
| 29 | Rust test `export_native_reconciliation` in `crates/notebook/tests/sync_paragraph.rs` |
| 30 | generates reconciled output |
| 31 | at a new absolute `ONESTORE_NATIVE_RECONCILIATION_OUTPUT` directory. Cold-open its |
| 32 | `candidate` with the same runner, without inspection. Verification lives in |
| 33 | `tools/test_paragraph_edit.py` and `crates/notebook/tests/sync_paragraph.rs`. |
| 34 | |
| 35 | The original COM pass stopped at its fifth case because its tag definition |
| 36 | followed page settings. The recorded continuation fixes the schema order and |
| 37 | applies only the remaining twelve cases. Scripts, commands, and both phase |
| 38 | hashes retain this provenance; the before-image was preserved throughout. |
| 39 | Identical captured files link to their canonical corpus copy. |