| 1 | # Native page-removal references |
| 2 | |
| 3 | Eleven synthetic OneNote 2010 cases exercise individual parent, child, grandchild, |
| 4 | trailing and leading-page removal; explicit multi-page removal; removal of every |
| 5 | page; permanent removal; and recycling pages containing tables, list controls, |
| 6 | tags, images, attachments and ink. The two leading cases also contain a nonempty |
| 7 | page-version graph. These are sequential COM `DeleteHierarchy` calls with frozen |
| 8 | original page identities. They do not represent keyboard deletion of a collapsed |
| 9 | selection or an atomic notebook-wide transaction. |
| 10 | |
| 11 | Every case retains synchronized before/after section files, full native page XML |
| 12 | and binary payloads, scripts, requested page indices, and an independent cold |
| 13 | capture. `provenance.json` records the captured hashes and all 22 clone teardown |
| 14 | records. Identical files within the capture have one stored copy and relative |
| 15 | links. All fixtures originate from the public synthetic corpus. |
| 16 | |
| 17 | The raw Rust oracle checks retained page/object identities and bodies, page order, |
| 18 | series reuse, indentation, source tombstones, retained revisions, labeled history, |
| 19 | and exact cold graphs. Recycled pages are associated by their notebook-management |
| 20 | GUID, including when titles are identical. Reachable properties, nested property |
| 21 | sets, ordered references, context relationships and internal file payloads compare |
| 22 | across identifier remapping. Only identical author records may merge. Current-page |
| 23 | metadata normalizes to level one; observed modification-time changes must equal |
| 24 | the copied page's timestamp. Version-page levels and timestamps remain exact. |
| 25 | Native discards nine old storage revisions in the ink case and eight in the |
| 26 | feature case; those counts are explicit regression expectations. Removal of |
| 27 | storage revisions is distinct from losing semantic page versions. |
| 28 | |
| 29 | The copy oracle includes negative controls for an ordinary text edit and a |
| 30 | changed attachment payload. Python independently compares native XML, character |
| 31 | formatting and media against before, after and cold stores. Empty native section |
| 32 | hierarchies can contain only an XML declaration after reopening. |
| 33 | |
| 34 | ```sh |
| 35 | cargo build -p onestore-notebook --all-features --example document |
| 36 | cargo test -p onestore --all-features --test page_removal |
| 37 | python -m unittest discover -s tools -p test_page_removal.py |
| 38 | ``` |
| 39 | |
| 40 | A fresh owned-clone capture uses `python tools/native_page_removal.py CASE OUTPUT`, |
| 41 | where `CASE` is a key from `provenance.json` and `OUTPUT` is a new directory. The |
| 42 | controller removes its clones after use. These fixtures establish reference |
| 43 | semantics for the page-removal writer; they do not implement that writer. |
| 44 | |
| 45 | `sanitizer.json` records 64 initial mutation inputs and the 32 supplemental store |
| 46 | paths/hashes for the existing `document` fuzz target. With ASan and seed 1993, |
| 47 | 20,000 executions completed in 40 seconds without an invariant or sanitizer |
| 48 | failure. Decode the input hex into a new writable corpus and set |
| 49 | `ONESTORE_DOCUMENT_SEEDS` to the recorded repository-relative paths joined with |
| 50 | the platform path separator, then use `cargo +nightly fuzz run document CORPUS -- |
| 51 | -seed=1993 -max_total_time=120 -timeout=30 -runs=20000`. The target also retains its |
| 52 | built-in synthetic sources. This is bounded reader testing of these inputs. |
| 53 | |
| 54 | `rust-followup` takes four Rust `delete_pages_permanently` outputs (`parent`, `all`, |
| 55 | `features`, `leading-parent`) and lets OneNote 2010 create a titled page with a bold |
| 56 | body in each section through COM (`tools/native/page-removal-followup.ps1`), then |
| 57 | reopens the natively saved section through a fresh cache. The Rust test |
| 58 | `native_pages_created_after_rust_removal_reopen_cold` requires every surviving page |
| 59 | to keep its exact active revision through both native phases, the new page to carry |
| 60 | the native title and body, and the cold reopen to change no object space. |
| 61 | `tools/test_page_removal.py` compares both captures' native XML with the Rust model |
| 62 | and finds the native title exactly once in each hierarchy. Regenerate the candidates |
| 63 | with `ONESTORE_PAGE_REMOVAL_OUTPUT` on the removal reference test, then run the |
| 64 | runner with `--author` into `followup` and cold into `followup-cold`. |