authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-09-08 21:17:46-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-09-08 21:17:46-07:00
log44df465c5e6e99c1a98916fa6cbcbde01a666164
treee55e5901c921828f860e25c5fbfea16dcdc9d528
parentcffb05d4803d38e6fbc9acef1aff140f067a5ede
signature Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU

feat: create pages in existing sections atomically

Retain page identities and publish the new space with section navigation in one transaction. Cover empty and duplicate Unicode titles, native edits and Rust follow-ups, 521-page checkpoint/counter stress, historical asset preservation, and interrupted publication. Validation: 137 core, 99 offline and 150 Python tests; 29,328 ASan executions; workspace Clippy/formatting; both iOS targets compile. Five native clones removed. Acceptance: evidence/m10/PAGE-CREATION.md. Assisted-by: gpt-6-astra

76 files changed, 1417 insertions(+), 73 deletions(-)

corpus/page-lifecycle/creation/README.md created+37
......@@ -0,0 +1,37 @@
1# Page creation
2
3`candidate` adds four pages to `../03-renamed/notebook/Lifecycle.one`: an appended
4page without a title node, a prepended page with an empty title field, and two
5appended pages titled `New 🦋 é`. All thirteen ordered page identities survive
6each fresh OneNote 2010 reopen. Identical artifacts are relative symlinks.
7
8`cold` captures the first reopen. `native` adds a distinct body paragraph to each
9duplicate-title page through `tools/native/created-pages.ps1`; `native/cold`
10reopens that result in another cache. `followup` prefixes those bodies with
11`Rust + ` and the titles with `Reviewed `; `followup/cold` reopens that result.
12The retained `provenance.json` records the native capture inputs and clone removal.
13
14After building workspace examples, run `python -m unittest discover -s tools
15-p test_page_creation.py -v`. It compares native XML content and character formats,
16ordered identities, and complete active object graphs across each cold reopen.
17These thirteen-page comparisons need no graph normalization.
18
19Export fresh Rust candidates by setting each variable to a new output directory:
20
21| Core integration test (`cargo test -p onestore --test page TEST -- --exact`) | Variable |
22| --- | --- |
23| `native_section_accepts_empty_and_titled_pages_with_preserved_history` | `ONESTORE_PAGE_CREATION_OUTPUT` |
24| `native_changes_on_created_pages_accept_rust_followups` | `ONESTORE_PAGE_FOLLOWUP_OUTPUT` |
25| `repeated_page_creation_crosses_root_fragments_counters_and_section_checkpoints` | `ONESTORE_PAGE_STRESS_OUTPUT` |
26
27The last test produces 521 pages, crosses a section revision checkpoint and
28transaction-counter rollover, and checks that every unpublished candidate still
29exposes the complete preceding page order. Its large native capture is local
30evidence. Reproduce with `tools/native_runner.py INPUT OUTPUT --expected-pages 521
31--collect-notebook`, then `PYTHONPATH=tools python tools/verify_page_creation.py
32INPUT OUTPUT`. That comparison permits only exact native materialization of a
33previously absent section metadata copy; all other graph fields compare exactly.
34
35This core operation deliberately creates one optional title outline without
36generated date/time text or template content. MS-ONE 2.2.50 permits a title with
37one or two outlines. The fixture establishes this explicit empty-page contract.
corpus/page-lifecycle/creation/candidate/Lifecycle.one created
Binary files /dev/null and b/corpus/page-lifecycle/creation/candidate/Lifecycle.one differ
corpus/page-lifecycle/creation/cold/notebook/Lifecycle.one created
Binary files /dev/null and b/corpus/page-lifecycle/creation/cold/notebook/Lifecycle.one differ
corpus/page-lifecycle/creation/cold/read/hierarchy.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Notebook xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" name="notebook" nickname="notebook" ID="{3BFEF56D-B4F8-4F2E-A1BC-468DDA94A2D5}{1}{B0}" path="C:\one-tests\runs\capture\notebook" lastModifiedTime="2026-09-09T04:23:59.000Z" color="#B49EDE"><one:Section name="Lifecycle" ID="{C65593FF-0E35-0BF7-1FC3-16CBBB799594}{1}{B0}" path="C:\one-tests\runs\capture\notebook\Lifecycle.one" lastModifiedTime="2026-09-09T04:23:59.000Z" color="#91BAAE"><one:Page ID="{39C1FCAE-45F8-0FA4-3FC6-46AF3A75DC8A}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{266FCA0A-41B5-03F0-0ADE-86136233B704}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{6C02B3F9-D11E-0A62-1E9D-86328FA37C2A}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{4C0D72CA-D8C6-0D40-0E00-40C67411544F}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{58C13BB3-DE03-4816-B303-087ACC456B97}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{054D1020-5845-4210-8DEE-30AE886FFF66}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{5891D2E3-C28F-4C4F-91C8-E802A2DDA3B0}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{8B5220CE-1103-4F42-AD6F-443875AA4EFC}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"/><one:Page ID="{E0B7DA6E-27FF-4573-92CF-4663E293DAE6}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"/><one:Page ID="{9BFEBE8D-72F6-4211-B975-2E62E65AF7D7}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"/><one:Page ID="{3894C714-5BE5-03FC-208C-EFB4E9A37951}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"/><one:Page ID="{067A6101-C793-0F15-0101-74668CB91D5E}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"/><one:Page ID="{C6BB9F1B-5105-064D-086F-0B103A30C43B}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"/></one:Section></one:Notebook>
corpus/page-lifecycle/creation/cold/read/page-000.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{054D1020-5845-4210-8DEE-30AE886FFF66}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{8F196553-BA68-46B8-A5A9-2FFC33D426C2}{28}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[child]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{8F196553-BA68-46B8-A5A9-2FFC33D426C2}{35}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="149.6102294921875" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{8F196553-BA68-46B8-A5A9-2FFC33D426C2}{36}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body child &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/cold/read/page-001.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{067A6101-C793-0F15-0101-74668CB91D5E}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{067A6101-C793-0F15-0101-74668CB91D5E}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[New &#129419; é]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/cold/read/page-002.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{266FCA0A-41B5-03F0-0ADE-86136233B704}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{E81ABB11-7D00-0B97-2159-DD23F8403BFB}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/cold/read/page-003.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{3894C714-5BE5-03FC-208C-EFB4E9A37951}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/cold/read/page-004.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{39C1FCAE-45F8-0FA4-3FC6-46AF3A75DC8A}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{39C1FCAE-45F8-0FA4-3FC6-46AF3A75DC8A}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/cold/read/page-005.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{4C0D72CA-D8C6-0D40-0E00-40C67411544F}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/cold/read/page-006.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{5891D2E3-C28F-4C4F-91C8-E802A2DDA3B0}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{C844F950-C3B5-4FE0-ADCD-588A8B55C0F1}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[grandchild]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{C844F950-C3B5-4FE0-ADCD-588A8B55C0F1}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="175.9715728759766" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{C844F950-C3B5-4FE0-ADCD-588A8B55C0F1}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body grandchild &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/cold/read/page-007.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{58C13BB3-DE03-4816-B303-087ACC456B97}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:27.000Z" objectID="{5ADAA2C9-8AA5-4283-813C-C275E2BE752A}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Same title]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{5ADAA2C9-8AA5-4283-813C-C275E2BE752A}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="158.2952728271484" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{5ADAA2C9-8AA5-4283-813C-C275E2BE752A}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body parent &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/cold/read/page-008.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{6C02B3F9-D11E-0A62-1E9D-86328FA37C2A}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{43E67622-7E4B-067B-35F7-FE8CA3C5A2A8}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/cold/read/page-009.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{8B5220CE-1103-4F42-AD6F-443875AA4EFC}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:23:58.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{A6AAC17A-F7B8-4832-BB11-A47AA3FCCB83}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Renamed &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{EDDDEAD0-9F85-44A8-BE51-3B1A009C7ABD}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="170.2942504882812" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{EDDDEAD0-9F85-44A8-BE51-3B1A009C7ABD}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body duplicate &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/cold/read/page-010.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{9BFEBE8D-72F6-4211-B975-2E62E65AF7D7}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{2C80C4C5-DA5C-4DF0-BBB7-F55CC50454C4}{14}{B0}"><one:Position x="36.0" y="14.40000057220459" z="0"/><one:Size width="174.3547973632812" height="13.42771625518799"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{2C80C4C5-DA5C-4DF0-BBB7-F55CC50454C4}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body automatic &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/cold/read/page-011.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{C6BB9F1B-5105-064D-086F-0B103A30C43B}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{C6BB9F1B-5105-064D-086F-0B103A30C43B}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[New &#129419; é]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/cold/read/page-012.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{E0B7DA6E-27FF-4573-92CF-4663E293DAE6}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:23:59.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{A539CBE3-2AB2-40C1-871E-FA63AE8FCA56}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{7186FA13-086F-4F43-A09A-2487C41430AA}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="160.1752014160156" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{7186FA13-086F-4F43-A09A-2487C41430AA}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body trailing &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/Lifecycle.one created
Binary files /dev/null and b/corpus/page-lifecycle/creation/followup/Lifecycle.one differ
corpus/page-lifecycle/creation/followup/cold/notebook/Lifecycle.one created
Binary files /dev/null and b/corpus/page-lifecycle/creation/followup/cold/notebook/Lifecycle.one differ
corpus/page-lifecycle/creation/followup/cold/read/hierarchy.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Notebook xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" name="notebook" nickname="notebook" ID="{6DFB689D-2E8E-4686-9997-32046753F9FD}{1}{B0}" path="C:\one-tests\runs\capture\notebook" lastModifiedTime="2026-09-09T04:44:45.000Z" color="#B49EDE"><one:Section name="Lifecycle" ID="{C3953BFE-3B75-0740-087B-6C4AD8A1EE03}{1}{B0}" path="C:\one-tests\runs\capture\notebook\Lifecycle.one" lastModifiedTime="2026-09-09T04:44:45.000Z" color="#91BAAE"><one:Page ID="{3C0154AF-70B8-0313-287E-3C2E59ADA71D}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{23AF620B-74F5-0F47-1D66-FC9201EBCC93}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{69C21BF8-E45E-06D5-0925-FCB3EC7B07BD}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{49CDDACB-ED86-01F7-19B8-3A4717C92FD8}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{5D0193B2-EB43-44A1-A4BB-72FBAF9D1000}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{008DB821-6D05-4EA7-9A56-4A2FEBB784F1}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{5D517AE2-F7CF-40F8-8670-9283C105D827}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{8E9288CF-2443-43F5-BAD7-3EB91672356B}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{E577726F-12BF-49C4-8577-3CE2814BA171}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{9E3E168C-47B6-4EA6-AECD-54E385828C40}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{3D546F15-6EA5-0F4B-3734-95358A7B02C6}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{03BAC900-F2D3-03A2-16B9-0EE7EF6166C9}{1}{B0}" name="Reviewed New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/><one:Page ID="{C37B371A-6445-0AFA-1FD7-719159E8BFAC}{1}{B0}" name="Reviewed New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"/></one:Section></one:Notebook>
corpus/page-lifecycle/creation/followup/cold/read/page-000.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{008DB821-6D05-4EA7-9A56-4A2FEBB784F1}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{8AD9CD52-8F28-4A0F-B211-557D500C5D55}{28}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[child]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{8AD9CD52-8F28-4A0F-B211-557D500C5D55}{35}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="149.6102294921875" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{8AD9CD52-8F28-4A0F-B211-557D500C5D55}{36}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body child &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-001.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{03BAC900-F2D3-03A2-16B9-0EE7EF6166C9}{1}{B0}" name="Reviewed New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:42:47.000Z" objectID="{03BAC900-F2D3-03A2-16B9-0EE7EF6166C9}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Reviewed New &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T04:42:47.000Z" objectID="{80CDD07A-F21F-468D-A2FA-A92C4EC6F53F}{10}{B0}"><one:Position x="72.0" y="144.0" z="0"/><one:Size width="244.6467742919922" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T04:33:45.000Z" lastModifiedTime="2026-09-09T04:42:47.000Z" objectID="{80CDD07A-F21F-468D-A2FA-A92C4EC6F53F}{11}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Rust + Native body 0 after Rust page creation.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-002.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{23AF620B-74F5-0F47-1D66-FC9201EBCC93}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{EDDA1310-4840-0720-36E1-A7A29B98406C}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-003.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{3C0154AF-70B8-0313-287E-3C2E59ADA71D}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{3C0154AF-70B8-0313-287E-3C2E59ADA71D}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-004.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{3D546F15-6EA5-0F4B-3734-95358A7B02C6}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-005.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{49CDDACB-ED86-01F7-19B8-3A4717C92FD8}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-006.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{5D0193B2-EB43-44A1-A4BB-72FBAF9D1000}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:27.000Z" objectID="{5F1A0AC8-BFE5-4E34-9684-B8F481660EBD}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Same title]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{5F1A0AC8-BFE5-4E34-9684-B8F481660EBD}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="158.2952728271484" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{5F1A0AC8-BFE5-4E34-9684-B8F481660EBD}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body parent &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-007.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{5D517AE2-F7CF-40F8-8670-9283C105D827}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{CD845151-F6F5-4357-BA75-220BE88DBB66}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[grandchild]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{CD845151-F6F5-4357-BA75-220BE88DBB66}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="175.9715728759766" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{CD845151-F6F5-4357-BA75-220BE88DBB66}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body grandchild &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-008.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{69C21BF8-E45E-06D5-0925-FCB3EC7B07BD}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{4626DE23-4B0B-0ACC-224F-840DC01DD93F}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-009.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{8E9288CF-2443-43F5-BAD7-3EB91672356B}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{A36A697B-C2F8-4485-ACA9-DEFBC024B014}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Renamed &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{E81D42D1-AAC5-481F-A9E9-419B6344012A}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="170.2942504882812" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{E81D42D1-AAC5-481F-A9E9-419B6344012A}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body duplicate &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-010.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{9E3E168C-47B6-4EA6-AECD-54E385828C40}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{29406CC4-EF1C-4147-AC0F-8FDDA6DC2F53}{14}{B0}"><one:Position x="36.0" y="14.40000057220459" z="0"/><one:Size width="174.3547973632812" height="13.42771625518799"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{29406CC4-EF1C-4147-AC0F-8FDDA6DC2F53}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body automatic &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-011.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{C37B371A-6445-0AFA-1FD7-719159E8BFAC}{1}{B0}" name="Reviewed New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:42:47.000Z" objectID="{C37B371A-6445-0AFA-1FD7-719159E8BFAC}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Reviewed New &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T04:42:47.000Z" objectID="{DA84E582-1E18-4AD2-984E-701D70B4CB24}{10}{B0}"><one:Position x="72.0" y="144.0" z="0"/><one:Size width="244.6467742919922" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T04:33:45.000Z" lastModifiedTime="2026-09-09T04:42:47.000Z" objectID="{DA84E582-1E18-4AD2-984E-701D70B4CB24}{11}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Rust + Native body 1 after Rust page creation.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/followup/cold/read/page-012.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{E577726F-12BF-49C4-8577-3CE2814BA171}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:44:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{A0F963E2-1FF2-4C76-90A6-80E2CD57B1C1}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{74465212-3D2F-43F4-B722-5E06A7CC4B3D}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="160.1752014160156" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{74465212-3D2F-43F4-B722-5E06A7CC4B3D}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body trailing &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/notebook/Lifecycle.one created+1
......@@ -0,0 +1 @@
1../../notebook/Lifecycle.one
\ No newline at end of file
corpus/page-lifecycle/creation/native/cold/read/hierarchy.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Notebook xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" name="notebook" nickname="notebook" ID="{89446429-1F4A-475B-A18F-A3C179D6E0AB}{1}{B0}" path="C:\one-tests\runs\capture\notebook" lastModifiedTime="2026-09-09T04:37:57.000Z" color="#B49EDE"><one:Section name="Lifecycle" ID="{82D2B6AE-B1AA-0F47-17A3-639D555107BE}{1}{B0}" path="C:\one-tests\runs\capture\notebook\Lifecycle.one" lastModifiedTime="2026-09-09T04:37:57.000Z" color="#91BAAE"><one:Page ID="{7D46D9FF-FA67-0B14-37A6-33F9D45D4EA0}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{62E8EF5B-FE2A-0740-02BE-F3458C1B252E}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{288596A8-6E81-0ED2-16FD-F364618BEE00}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{088A579B-6759-09F0-0660-35909A39C665}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{1C461EE2-619C-4CA6-BB63-7D2C226DF9BD}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{41CA3571-E7DA-46A0-858E-45F866476D4C}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{1C16F7B2-7D10-48FF-99A8-9D544CF5319A}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{CFD5059F-AE9C-4BF2-A50F-316E9B82DCD6}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{A430FF3F-9860-41C3-9AAF-33350CBB48CC}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{DF799BDC-CD69-46A1-B115-5B34087265FD}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{7C13E245-E47A-074C-28EC-9AE2078BEB7B}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{42FD4450-780C-0BA5-0961-013062918F74}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/><one:Page ID="{823CBA4A-EE9A-02FD-000F-7E46D4185611}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"/></one:Section></one:Notebook>
corpus/page-lifecycle/creation/native/cold/read/page-000.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{088A579B-6759-09F0-0660-35909A39C665}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-001.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{1C16F7B2-7D10-48FF-99A8-9D544CF5319A}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{8CC3DC01-7C2A-4B50-A5AD-2DDC657D52DB}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[grandchild]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{8CC3DC01-7C2A-4B50-A5AD-2DDC657D52DB}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="175.9715728759766" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{8CC3DC01-7C2A-4B50-A5AD-2DDC657D52DB}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body grandchild &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-002.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{1C461EE2-619C-4CA6-BB63-7D2C226DF9BD}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:27.000Z" objectID="{1E5D8798-353A-4633-895C-B7230C96E700}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Same title]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{1E5D8798-353A-4633-895C-B7230C96E700}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="158.2952728271484" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{1E5D8798-353A-4633-895C-B7230C96E700}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body parent &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-003.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{288596A8-6E81-0ED2-16FD-F364618BEE00}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{07615373-C1D4-02CB-3D97-8BDA4DED3082}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-004.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{41CA3571-E7DA-46A0-858E-45F866476D4C}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{CB9E4002-05F7-4208-ADC9-5AAADDFCB4E8}{28}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[child]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{CB9E4002-05F7-4208-ADC9-5AAADDFCB4E8}{35}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="149.6102294921875" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{CB9E4002-05F7-4208-ADC9-5AAADDFCB4E8}{36}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body child &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-005.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{42FD4450-780C-0BA5-0961-013062918F74}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{42FD4450-780C-0BA5-0961-013062918F74}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[New &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{C18A5D2A-78C0-4E8A-BD22-A6FBC3361C82}{10}{B0}"><one:Position x="72.0" y="144.0" z="0"/><one:Size width="214.4557342529297" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T04:33:45.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{C18A5D2A-78C0-4E8A-BD22-A6FBC3361C82}{11}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Native body 0 after Rust page creation.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-006.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{62E8EF5B-FE2A-0740-02BE-F3458C1B252E}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{AC9D9E40-C29F-0F27-2939-A8751668A9D1}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-007.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{7C13E245-E47A-074C-28EC-9AE2078BEB7B}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-008.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{7D46D9FF-FA67-0B14-37A6-33F9D45D4EA0}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{7D46D9FF-FA67-0B14-37A6-33F9D45D4EA0}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-009.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{823CBA4A-EE9A-02FD-000F-7E46D4185611}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{823CBA4A-EE9A-02FD-000F-7E46D4185611}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[New &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{9BC368D2-94C7-42D5-8796-7FCAFD442299}{10}{B0}"><one:Position x="72.0" y="144.0" z="0"/><one:Size width="214.4557342529297" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T04:33:45.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{9BC368D2-94C7-42D5-8796-7FCAFD442299}{11}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Native body 1 after Rust page creation.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-010.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{A430FF3F-9860-41C3-9AAF-33350CBB48CC}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{E1BEEEB2-952D-4471-8F7E-8F3540A7587C}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{3501DF42-B7F0-4BF3-A8FA-51D12A3CA280}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="160.1752014160156" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{3501DF42-B7F0-4BF3-A8FA-51D12A3CA280}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body trailing &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-011.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{CFD5059F-AE9C-4BF2-A50F-316E9B82DCD6}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{E22DE42B-4827-4C82-B371-D12C4DD459A9}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Renamed &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{A95ACF81-201A-4018-B631-4E4CEEB4E897}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="170.2942504882812" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{A95ACF81-201A-4018-B631-4E4CEEB4E897}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body duplicate &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/cold/read/page-012.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{DF799BDC-CD69-46A1-B115-5B34087265FD}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:37:57.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{6807E194-65C3-4940-B3D7-800A2B2CC6EE}{14}{B0}"><one:Position x="36.0" y="14.40000057220459" z="0"/><one:Size width="174.3547973632812" height="13.42771625518799"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{6807E194-65C3-4940-B3D7-800A2B2CC6EE}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body automatic &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/notebook/Lifecycle.one created
Binary files /dev/null and b/corpus/page-lifecycle/creation/native/notebook/Lifecycle.one differ
corpus/page-lifecycle/creation/native/read/hierarchy.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Notebook xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" name="notebook" nickname="notebook" ID="{477DD477-3150-478E-84D1-0D30A0CB781D}{1}{B0}" path="C:\one-tests\runs\capture\notebook" lastModifiedTime="2026-09-09T04:35:14.000Z" color="#B49EDE"><one:Section name="Lifecycle" ID="{2E7A04FF-1560-053C-194A-E3E92C86F3EF}{1}{B0}" path="C:\one-tests\runs\capture\notebook\Lifecycle.one" lastModifiedTime="2026-09-09T04:35:14.000Z" color="#91BAAE"><one:Page ID="{D1EE6BAE-5EAD-016F-394F-B38DAD8ABAF1}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{CE405D0A-5AE0-0D3B-0C57-7331F5CCD17F}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{842D24F9-CA4B-04A9-1814-7310185C1A51}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{A422E5CA-C393-038B-0889-B5E4E3EE3234}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{B0EEACB3-C556-46DD-B58A-FD585BBA0DEC}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{ED628720-4310-4CDB-8B67-C58C1F90991D}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{B0BE45E3-D9DA-4284-9741-1D203522C5CB}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"/><one:Page ID="{637DB7CE-0A56-4189-ABE6-B11AE2552887}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1"/><one:Page ID="{08984D6E-3CAA-4BB8-9446-B341756CBC9D}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1"/><one:Page ID="{73D1298D-69A3-4CDA-BFFC-DB4071A591AC}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1"/><one:Page ID="{D0BB5014-40B0-0D37-2605-1A967E5C1F2A}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1"/><one:Page ID="{EE55F601-DCC6-01DE-0788-81441B467B25}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" pageLevel="1"/><one:Page ID="{2E94081B-4A50-0886-0EE6-FE32ADCFA240}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" pageLevel="1"/></one:Section></one:Notebook>
corpus/page-lifecycle/creation/native/read/page-000.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{08984D6E-3CAA-4BB8-9446-B341756CBC9D}{1}{B0}" name="Body trailing 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{4D165CE3-31E7-4E0A-8197-0F413970AC2D}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{99A96D13-133A-4188-A613-D1A553EB56D1}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="160.1752014160156" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{99A96D13-133A-4188-A613-D1A553EB56D1}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body trailing &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-001.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{2E94081B-4A50-0886-0EE6-FE32ADCFA240}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{2E94081B-4A50-0886-0EE6-FE32ADCFA240}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[New &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{376BDA83-300D-48AE-897F-FFBE8493D6C8}{10}{B0}"><one:Position x="72.0" y="144.0" z="0"/><one:Size width="214.4557342529297" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T04:33:45.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{376BDA83-300D-48AE-897F-FFBE8493D6C8}{11}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Native body 1 after Rust page creation.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-002.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{637DB7CE-0A56-4189-ABE6-B11AE2552887}{1}{B0}" name="Renamed 🦋 é" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:34.000Z" lastModifiedTime="2026-09-09T03:09:34.000Z" objectID="{4E85567A-ECED-46F9-BD98-51583403ADF8}{16}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Renamed &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{05F27DD0-84D0-4A63-B8D8-CE3897631CC6}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="170.2942504882812" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{05F27DD0-84D0-4A63-B8D8-CE3897631CC6}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body duplicate &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-003.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{73D1298D-69A3-4CDA-BFFC-DB4071A591AC}{1}{B0}" name="Body automatic 🦀 é preserved" dateTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{C4AF53C5-C109-433B-BD3E-007E52FB32BF}{14}{B0}"><one:Position x="36.0" y="14.40000057220459" z="0"/><one:Size width="174.3547973632812" height="13.42771625518799"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{C4AF53C5-C109-433B-BD3E-007E52FB32BF}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body automatic &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-004.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{842D24F9-CA4B-04A9-1814-7310185C1A51}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{ABC9E122-651E-08B0-337E-0BAE343AC4D3}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/native/read/page-005.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{A422E5CA-C393-038B-0889-B5E4E3EE3234}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/native/read/page-006.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{B0BE45E3-D9DA-4284-9741-1D203522C5CB}{1}{B0}" name="grandchild" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{206B6E50-D8E0-412B-AB44-ADA81CAAA68A}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[grandchild]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{206B6E50-D8E0-412B-AB44-ADA81CAAA68A}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="175.9715728759766" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:30.000Z" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{206B6E50-D8E0-412B-AB44-ADA81CAAA68A}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body grandchild &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-007.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{B0EEACB3-C556-46DD-B58A-FD585BBA0DEC}{1}{B0}" name="Same title" dateTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:27.000Z" objectID="{B2F535C9-91F0-4C48-87B5-375775411351}{32}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[Same title]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{B2F535C9-91F0-4C48-87B5-375775411351}{39}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="158.2952728271484" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:27.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{B2F535C9-91F0-4C48-87B5-375775411351}{40}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body parent &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-008.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{CE405D0A-5AE0-0D3B-0C57-7331F5CCD17F}{1}{B0}" name="Untitled page" dateTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="17.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:19.000Z" lastModifiedTime="2026-09-09T03:09:19.000Z" objectID="{00352C11-6655-055C-27D0-28016FBF5D80}{15}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/native/read/page-009.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{D0BB5014-40B0-0D37-2605-1A967E5C1F2A}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:42.000Z" pageLevel="1"><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings></one:Page>
corpus/page-lifecycle/creation/native/read/page-010.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{D1EE6BAE-5EAD-016F-394F-B38DAD8ABAF1}{1}{B0}" name="Untitled page" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{D1EE6BAE-5EAD-016F-394F-B38DAD8ABAF1}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[]]></one:T></one:OE></one:Title></one:Page>
corpus/page-lifecycle/creation/native/read/page-011.xml created+4
......@@ -0,0 +1,4 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{ED628720-4310-4CDB-8B67-C58C1F90991D}{1}{B0}" name="child" dateTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T04:33:41.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title lang="en-US"><one:OE author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{6736F253-A13D-4873-A320-DADEA42B40B9}{28}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[child]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T03:09:30.000Z" objectID="{6736F253-A13D-4873-A320-DADEA42B40B9}{35}{B0}"><one:Position x="36.0" y="86.4000015258789" z="0"/><one:Size width="149.6102294921875" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T03:09:29.000Z" lastModifiedTime="2026-09-09T03:09:29.000Z" objectID="{6736F253-A13D-4873-A320-DADEA42B40B9}{36}{B0}" alignment="left" quickStyleIndex="0"><one:T><![CDATA[<span
3style='font-weight:bold' lang=en-US>Body child &#129408; é</span><span
4lang=en-US> </span><span style='font-style:italic' lang=x-none>preserved</span>]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/native/read/page-012.xml created+2
......@@ -0,0 +1,2 @@
1<?xml version="1.0"?>
2<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2010/onenote" ID="{EE55F601-DCC6-01DE-0788-81441B467B25}{1}{B0}" name="New 🦋 é" dateTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" pageLevel="1" lang="en-US"><one:QuickStyleDef index="0" name="PageTitle" font="Calibri" fontSize="17.0"/><one:QuickStyleDef index="1" name="p" fontColor="automatic" highlightColor="automatic" font="Calibri" fontSize="11.0" spaceBefore="0.0" spaceAfter="0.0"/><one:PageSettings RTL="false" color="automatic"><one:PageSize><one:Automatic/></one:PageSize><one:RuleLines visible="false"/></one:PageSettings><one:Title showDate="false" showTime="false" lang="en-US"><one:OE author="Rust author" lastModifiedBy="Rust author" creationTime="2026-09-09T04:22:39.000Z" lastModifiedTime="2026-09-09T04:22:39.000Z" objectID="{EE55F601-DCC6-01DE-0788-81441B467B25}{15}{B0}" alignment="left" quickStyleIndex="0" style="font-family:Calibri;font-size:17.0pt"><one:T><![CDATA[New &#129419; é]]></one:T></one:OE></one:Title><one:Outline author="virtual" authorInitials="V" lastModifiedBy="virtual" lastModifiedByInitials="V" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{6D22EF7B-DC0A-44F1-B3CB-268FBAE1E8D3}{10}{B0}"><one:Position x="72.0" y="144.0" z="0"/><one:Size width="214.4557342529297" height="13.42771339416504"/><one:OEChildren><one:OE creationTime="2026-09-09T04:33:45.000Z" lastModifiedTime="2026-09-09T04:33:45.000Z" objectID="{6D22EF7B-DC0A-44F1-B3CB-268FBAE1E8D3}{11}{B0}" alignment="left" quickStyleIndex="1"><one:T><![CDATA[Native body 0 after Rust page creation.]]></one:T></one:OE></one:OEChildren></one:Outline></one:Page>
corpus/page-lifecycle/creation/provenance.json created+115
......@@ -0,0 +1,115 @@
1{
2 "cold": {
3 "capture": "evidence/m10/page-create-cold",
4 "run": {
5 "notebook": "/Users/clo/dev/one/evidence/m10/page-create-candidate",
6 "expected_pages": 13,
7 "author": null,
8 "author_timeout_seconds": 600,
9 "inspect": false,
10 "collect_notebook": true,
11 "base": {
12 "file": "win7-office-base.qcow2",
13 "format": "qcow2",
14 "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
15 "virtual_size": 68719476736
16 },
17 "scripts": {
18 "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
19 "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
20 }
21 },
22 "machine": {
23 "name": "m6-4b25125e",
24 "hostname": "ONE-M6-4B25125E"
25 },
26 "teardown": {
27 "absent": true
28 }
29 },
30 "native": {
31 "capture": "evidence/m10/page-create-native-edit",
32 "run": {
33 "notebook": "/Users/clo/dev/one/evidence/m10/page-create-cold/notebook",
34 "expected_pages": 13,
35 "author": "tools/native/created-pages.ps1",
36 "author_timeout_seconds": 600,
37 "inspect": false,
38 "collect_notebook": true,
39 "base": {
40 "file": "win7-office-base.qcow2",
41 "format": "qcow2",
42 "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
43 "virtual_size": 68719476736
44 },
45 "scripts": {
46 "author.ps1": "f7d94cfa418a971c2911bb3f57b9a9991c9e0b91d0f7d9c7526ca7c8cd5adc42",
47 "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
48 "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
49 }
50 },
51 "machine": {
52 "name": "m6-71dafa89",
53 "hostname": "ONE-M6-71DAFA89"
54 },
55 "teardown": {
56 "absent": true
57 }
58 },
59 "native/cold": {
60 "capture": "evidence/m10/page-create-native-edit-cold",
61 "run": {
62 "notebook": "/Users/clo/dev/one/evidence/m10/page-create-native-edit/notebook",
63 "expected_pages": 13,
64 "author": null,
65 "author_timeout_seconds": 600,
66 "inspect": false,
67 "collect_notebook": true,
68 "base": {
69 "file": "win7-office-base.qcow2",
70 "format": "qcow2",
71 "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
72 "virtual_size": 68719476736
73 },
74 "scripts": {
75 "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
76 "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
77 }
78 },
79 "machine": {
80 "name": "m6-eabc83c1",
81 "hostname": "ONE-M6-EABC83C1"
82 },
83 "teardown": {
84 "absent": true
85 }
86 },
87 "followup/cold": {
88 "capture": "evidence/m10/page-create-rust-followup-cold",
89 "run": {
90 "notebook": "/Users/clo/dev/one/evidence/m10/page-create-rust-followup",
91 "expected_pages": 13,
92 "author": null,
93 "author_timeout_seconds": 600,
94 "inspect": false,
95 "collect_notebook": true,
96 "base": {
97 "file": "win7-office-base.qcow2",
98 "format": "qcow2",
99 "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
100 "virtual_size": 68719476736
101 },
102 "scripts": {
103 "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
104 "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
105 }
106 },
107 "machine": {
108 "name": "m6-5a91d9d1",
109 "hostname": "ONE-M6-5A91D9D1"
110 },
111 "teardown": {
112 "absent": true
113 }
114 }
115}
crates/onestore/README.md+8
......@@ -45,6 +45,7 @@ harness also accepts `--client-profile release`.
4545| `document::Document`, `Revision::text_runs` | Interpret document objects and inherited text formatting while retaining unknown properties and revision identities |
4646| `protected::UnlockedSection` (optional feature) | Own decoded buffers for explicit known-password inspection; clear those buffers on drop; derived document strings/exports remain caller-owned |
4747| `create_section` | Create one page containing one plain-text paragraph and an author, including Unicode |
48| `PageCreation`, `PreparedEdit::create_page` | Add an empty top-level page and its section entry atomically, retaining page identities across retries |
4849| `create_table_of_contents` | Create ordered section entries from filenames and file identities |
4950| `replace_property_bytes` | Append one scalar-property revision; preserve prior revisions and unrelated property values and references |
5051| `replace_text`, `commit_text`, `commit_file_text` | Replace a UTF-16 range across ordinary text runs; publish text, run boundaries and modification time together |
......@@ -73,6 +74,13 @@ sections retain their encrypted structure and payloads. With the optional
7374AES-128/CBC, SHA-1 password wrappers into a borrowed document view. Incorrect
7475passwords, unsupported protection profiles and work-limit failures remain distinct.
7576The source stays encrypted; protected writes are rejected.
77`PageCreation::new` appends, or inserts before the first page space of an existing
78series. `Some("")` creates an empty title field; `None` omits the title node.
79The page has no body outlines, generated date/time text or applied template.
80Retain the intent to preserve its page, title and space identities; existing
81identities require reconciliation before retry. Body insertion and title edits
82use those identities through the existing APIs. [Native page-creation fixtures](../../corpus/page-lifecycle/creation/README.md)
83cover duplicate Unicode titles, native edits and Rust follow-up edits.
7684Insertions update child references, reference counts, modification times and automatic
7785titles atomically. Paragraphs can be nested or inserted into table cells; outline
7886coordinates use points. `Insertion::with_formatting` includes nonoverlapping UTF-16
crates/onestore/src/commit.rs+8
......@@ -183,6 +183,14 @@ pub struct PreparedEdit<'a> {
183183}
184184
185185impl<'a> PreparedEdit<'a> {
186 /// Creates a page and its section entry in one transaction, retaining the intent's identities.
187 pub fn create_page(source: &'a [u8], page: &crate::PageCreation) -> Result<Self, crate::Error> {
188 Ok(Self {
189 source,
190 written: page.apply(source)?,
191 })
192 }
193
186194 /// Moves or removes a subtree and normalizes its containers in one revision.
187195 pub fn tree(
188196 source: &'a [u8],
crates/onestore/src/lib.rs+2
......@@ -12,6 +12,7 @@ mod formatting;
1212mod insertion;
1313mod objects;
1414mod outline;
15mod page;
1516mod paragraph;
1617mod properties;
1718#[cfg(feature = "protected")]
......@@ -35,6 +36,7 @@ pub use formatting::TextAttribute;
3536pub use insertion::Insertion;
3637pub use objects::{Object, ObjectData, ObjectReferences, ResolvedRevision};
3738pub use outline::OutlineEdit;
39pub use page::PageCreation;
3840pub use paragraph::{ParagraphJoin, ParagraphSplit};
3941pub use properties::{IdStream, Property, PropertySets, Value};
4042pub use revisions::{ExGuid, ObjectSpace, Revision, RevisionIndex};
crates/onestore/src/page.rs created+260
......@@ -0,0 +1,260 @@
1use crate::{
2 Error, ExGuid,
3 create::{current_timestamps, properties, string},
4 document::{Document, Kind},
5 write::{PropertyObject, RevisionEdit, fresh_guid, write_revisions},
6};
7use serde::{Deserialize, Serialize};
8use std::{collections::BTreeMap, sync::Arc};
9
10fn invalid(message: &'static str) -> Error {
11 Error { offset: 0, message }
12}
13
14/// An empty top-level page with stable identities and creation time.
15/// Retain the intent across retries; an existing page identity rejects duplicate creation.
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(deny_unknown_fields)]
18pub struct PageCreation {
19 guid: [u8; 16],
20 series_guid: [u8; 16],
21 before: Option<ExGuid>,
22 title: Option<String>,
23 author: String,
24 created: u32,
25}
26
27impl PageCreation {
28 /// Appends a page, or inserts before the first page space of an existing series.
29 /// `Some("")` creates an empty title field; `None` creates a page without a title node.
30 /// The page has no body outlines or generated date/time text and does not apply a template.
31 pub fn new(before: Option<ExGuid>, title: Option<&str>, author: &str) -> Result<Self, Error> {
32 let page = Self {
33 guid: fresh_guid()?,
34 series_guid: fresh_guid()?,
35 before,
36 title: title.map(str::to_owned),
37 author: author.to_owned(),
38 created: current_timestamps()?.0,
39 };
40 page.validate()?;
41 Ok(page)
42 }
43
44 pub fn space(&self) -> ExGuid {
45 ExGuid {
46 guid: self.guid,
47 n: 1,
48 }
49 }
50
51 pub fn object(&self) -> ExGuid {
52 ExGuid {
53 guid: self.guid,
54 n: 12,
55 }
56 }
57
58 pub fn title_object(&self) -> Option<ExGuid> {
59 self.title.as_ref().map(|_| ExGuid {
60 guid: self.guid,
61 n: 16,
62 })
63 }
64
65 fn validate(&self) -> Result<(), Error> {
66 if self.guid == [0; 16]
67 || self.series_guid == [0; 16]
68 || self.guid == self.series_guid
69 || self.author.contains('\0')
70 || self.before.is_some_and(|id| id.guid == [0; 16])
71 || self
72 .title
73 .as_ref()
74 .is_some_and(|title| title.contains(['\0', '\r', '\n', '\u{fffc}', '\u{fddf}']))
75 {
76 return Err(invalid(
77 "Use a new page identity, an existing page anchor, and ordinary single-line title text",
78 ));
79 }
80 Ok(())
81 }
82
83 pub(crate) fn apply(&self, source: &[u8]) -> Result<Vec<u8>, Error> {
84 self.validate()?;
85 write_revisions(source, |index| {
86 if index.spaces.contains_key(&self.space()) {
87 return Err(invalid(
88 "This page identity already exists; reconcile the original creation",
89 ));
90 }
91 let document = Document::parse(index)?;
92 document.pages()?;
93 let section = &document.spaces[&document.root];
94 let view = &section.revisions[&section.contexts[&ExGuid::default()]];
95 let section_id = view.roots[&1];
96 let section_node = &view.nodes[&section_id];
97 if !matches!(section_node.kind, Kind::Section { .. })
98 || section_node.extra[0]
99 .iter()
100 .any(|field| field.id == 0x88001cde)
101 {
102 return Err(invalid("Choose an editable section for the new page"));
103 }
104 let position = match self.before {
105 None => section_node.children.len(),
106 Some(before) => section_node
107 .children
108 .iter()
109 .position(|id| view.nodes[id].spaces.first() == Some(&before))
110 .ok_or_else(|| {
111 invalid("Insert before the first page of an existing series, or append")
112 })?,
113 };
114 let raw = index.resolve(document.root, section.contexts[&ExGuid::default()])?;
115 let id = |n| ExGuid { guid: self.guid, n };
116 let reference = |n: u32| n.to_le_bytes().to_vec();
117 let timestamp = ((u64::from(self.created) + 315532800 + 11644473600) * 10000000)
118 .to_le_bytes()
119 .to_vec();
120 let modified = || (0x14001d7a, self.created.to_le_bytes().to_vec());
121 let mut table = BTreeMap::from([(0, self.guid)]);
122 let mut metadata_id = id(1);
123 for (byte, salt) in metadata_id.guid.iter_mut().zip([
124 0x31, 0xc0, 0xa8, 0x22, 0, 0x36, 0xee, 0x42, 0xb7, 0x14, 0xd7, 0xac, 0xda, 0x24,
125 0x35, 0xe8,
126 ]) {
127 *byte ^= salt;
128 }
129 table.insert(1, metadata_id.guid);
130 let table = Arc::new(table);
131 let object = |jcid, values: Vec<_>| -> Result<_, Error> {
132 Ok(PropertyObject {
133 jcid,
134 bytes: properties(&values)?,
135 global_ids: Arc::clone(&table),
136 })
137 };
138 let title = self.title.as_deref().unwrap_or_default().trim_start();
139 let metadata = vec![
140 (0x1c001c30, self.guid.to_vec()),
141 (0x1c001cf3, string(title)),
142 (0x14001d82, reference(40)),
143 (0x1400348b, reference(40)),
144 (0x14001dff, reference(1)),
145 (0x18001c65, timestamp.clone()),
146 ];
147 let mut page = vec![
148 modified(),
149 (0x1c001d75, string(&self.author)),
150 (0x1c001d3c, string("")),
151 ];
152 if self.title.is_some() {
153 page.push((0x24001d5f, reference(13)));
154 }
155 let mut objects = BTreeMap::from([
156 (id(10), object(0x60037, vec![(0x24001c1f, reference(12))])?),
157 (id(11), object(0x20030, metadata.clone())?),
158 (id(12), object(0x6000b, page)?),
159 ]);
160 if let Some(title) = &self.title {
161 for (n, jcid, values) in [
162 (
163 13,
164 0x6002c,
165 vec![
166 modified(),
167 (0x24001c20, reference(14)),
168 (0x14001c14, 0_f32.to_le_bytes().to_vec()),
169 (0x14001c15, 0_f32.to_le_bytes().to_vec()),
170 ],
171 ),
172 (
173 14,
174 0x6000c,
175 vec![
176 modified(),
177 (0x24001c20, reference(15)),
178 (0x0c001c03, vec![1]),
179 ],
180 ),
181 (
182 15,
183 0x6000d,
184 vec![
185 modified(),
186 (0x24001c1f, reference(16)),
187 (0x0c001c03, vec![1]),
188 (0x20001d78, reference(17)),
189 (0x20001d79, reference(17)),
190 (0x14001d09, self.created.to_le_bytes().to_vec()),
191 (0x88001cb4, vec![]),
192 ],
193 ),
194 (
195 16,
196 0x6000e,
197 vec![
198 modified(),
199 (0x1c001c22, string(title)),
200 (0x24001e13, reference(19)),
201 (0x2000342c, reference(18)),
202 (0x10001cfe, 0x409_u16.to_le_bytes().to_vec()),
203 (0x88001cb4, vec![]),
204 ],
205 ),
206 (17, 0x120001, vec![(0x1c001d75, string(&self.author))]),
207 (
208 18,
209 0x12004d,
210 vec![
211 (0x1c00345a, string("PageTitle")),
212 (0x1c001c0a, string("Calibri")),
213 (0x10001c0b, 34_u16.to_le_bytes().to_vec()),
214 ],
215 ),
216 (19, 0x12004d, vec![(0x14001c3b, reference(0x409))]),
217 ] {
218 objects.insert(id(n), object(jcid, values)?);
219 }
220 }
221 let series = object(
222 0x60008,
223 vec![
224 (0x1c001c30, self.series_guid.to_vec()),
225 (0x18001c65, timestamp),
226 (0x2c001d63, reference(1)),
227 (0x24003442, reference(257)),
228 ],
229 )?;
230 if raw.objects.contains_key(&id(2)) || raw.objects.contains_key(&metadata_id) {
231 return Err(invalid("The new page's section identities already exist"));
232 }
233 let mut parent = PropertyObject::from_object(&raw.objects[&section_id])?;
234 let mut children = section_node.children.clone();
235 children.insert(position, id(2));
236 let mut references = Vec::new();
237 for child in children {
238 references.extend_from_slice(&parent.reference(child)?);
239 }
240 parent.set(&[(0x24001c20, &references)])?;
241 Ok(BTreeMap::from([
242 (
243 document.root,
244 RevisionEdit::Update(BTreeMap::from([
245 (section_id, parent),
246 (id(2), series),
247 (metadata_id, object(0x20030, metadata)?),
248 ])),
249 ),
250 (
251 self.space(),
252 RevisionEdit::Create {
253 roots: BTreeMap::from([(1, id(10)), (2, id(11))]),
254 objects,
255 },
256 ),
257 ]))
258 })
259 }
260}
crates/onestore/src/write.rs+159-69
......@@ -354,6 +354,14 @@ pub(crate) struct PropertyObject {
354354 pub global_ids: Arc<BTreeMap<u32, [u8; 16]>>,
355355}
356356
357pub(crate) enum RevisionEdit {
358 Update(BTreeMap<ExGuid, PropertyObject>),
359 Create {
360 roots: BTreeMap<u32, ExGuid>,
361 objects: BTreeMap<ExGuid, PropertyObject>,
362 },
363}
364
357365impl PropertyObject {
358366 pub fn from_object(object: &crate::Object<'_>) -> Result<Self> {
359367 let ObjectData::Properties(bytes) = object.data else {
......@@ -597,13 +605,49 @@ pub(crate) fn write_revision(
597605 message: "Object space has no active default revision",
598606 })?;
599607 let revision = index.resolve(space, rid)?;
600 Ok(BTreeMap::from([(space, edit(&revision)?)]))
608 Ok(BTreeMap::from([(
609 space,
610 RevisionEdit::Update(edit(&revision)?),
611 )]))
601612 })
602613}
603614
615fn append_fragment(
616 source: &[u8],
617 output: &mut Vec<u8>,
618 list: &crate::NodeList,
619 nodes: &[Vec<u8>],
620) -> Result<(u32, usize)> {
621 let last_fragment = *list.fragments.last().unwrap();
622 let list_start = usize::try_from(last_fragment.offset).unwrap();
623 let list_id = u32::from_le_bytes(source[list_start + 8..list_start + 12].try_into().unwrap());
624 let chunk = append_list(output, list_id, nodes)?;
625 let start = usize::try_from(chunk.offset).unwrap();
626 let sequence = u32::try_from(list.fragments.len()).map_err(|_| Error {
627 offset: list_start,
628 message: "File-node fragment sequences are exhausted",
629 })?;
630 output[start + 12..start + 16].copy_from_slice(&sequence.to_le_bytes());
631 let last_node = list.nodes.last().unwrap();
632 let node_header = u32::from_le_bytes(
633 source[last_node.offset..last_node.offset + 4]
634 .try_into()
635 .unwrap(),
636 );
637 let nodes_end = last_node.offset + usize::try_from((node_header >> 10) & 0x1fff).unwrap();
638 let tail = list_start + usize::try_from(last_fragment.length).unwrap() - 20;
639 if tail - nodes_end >= 4 {
640 output[nodes_end..nodes_end + 4].copy_from_slice(&node(0xff, None, &[])?);
641 }
642 output[tail..tail + 8].copy_from_slice(&chunk.offset.to_le_bytes());
643 output[tail + 8..tail + 12].copy_from_slice(&(chunk.length as u32).to_le_bytes());
644
645 Ok((list_id, list.nodes.len() + nodes.len()))
646}
647
604648pub(crate) fn write_revisions(
605649 source: &[u8],
606 edit: impl FnOnce(&RevisionIndex<'_>) -> Result<BTreeMap<ExGuid, BTreeMap<ExGuid, PropertyObject>>>,
650 edit: impl FnOnce(&RevisionIndex<'_>) -> Result<BTreeMap<ExGuid, RevisionEdit>>,
607651) -> Result<Vec<u8>> {
608652 let store = Store::parse(source)?;
609653 let is_section = store.header.file_type == FileType::Section;
......@@ -617,25 +661,63 @@ pub(crate) fn write_revisions(
617661 index.validate_current()?;
618662 let changes = edit(&index)?;
619663 let mut output = source.to_vec();
620 let maximum = store
664 let mut maximum = store
621665 .transaction_fragments
622666 .iter()
623667 .flat_map(|fragment| fragment.entries.chunks_exact(8))
624668 .map(|entry| u32::from_le_bytes(entry[..4].try_into().unwrap()))
625669 .max()
626670 .unwrap();
671 let mut allocate_list = || {
672 maximum = maximum.checked_add(1).ok_or(Error {
673 offset: 0,
674 message: "File-node list identities are exhausted",
675 })?;
676 Ok::<_, Error>(maximum)
677 };
627678 let mut counts = Vec::new();
628 for (space, mut replacements) in changes {
629 let rid = *index
630 .spaces
631 .get(&space)
632 .and_then(|space| space.labels.get(&(ExGuid::default(), 1)))
633 .ok_or(Error {
634 offset: 0,
635 message: "Object space has no active default revision",
636 })?;
637 let mut revision = index.resolve(space, rid)?;
638 let reachable = revision.reachable()?;
679 let mut root_nodes = Vec::new();
680 for (space, change) in changes {
681 let (rid, mut revision, mut replacements) = match change {
682 RevisionEdit::Update(objects) => {
683 let rid = *index
684 .spaces
685 .get(&space)
686 .and_then(|space| space.labels.get(&(ExGuid::default(), 1)))
687 .ok_or(Error {
688 offset: 0,
689 message: "Object space has no active default revision",
690 })?;
691 (Some(rid), index.resolve(space, rid)?, objects)
692 }
693 RevisionEdit::Create { roots, objects } => {
694 if !is_section || space.guid == [0; 16] || index.spaces.contains_key(&space) {
695 return Err(Error {
696 offset: 0,
697 message: "Choose a new object-space identity in a section file",
698 });
699 }
700 if roots.is_empty() || objects.is_empty() {
701 return Err(Error {
702 offset: 0,
703 message: "New object space needs roots and objects",
704 });
705 }
706 (
707 None,
708 crate::ResolvedRevision {
709 roots,
710 objects: BTreeMap::new(),
711 },
712 objects,
713 )
714 }
715 };
716 let reachable = if rid.is_some() {
717 revision.reachable()?
718 } else {
719 BTreeSet::new()
720 };
639721 for (id, replacement) in &replacements {
640722 if let Some(object) = revision.objects.get(id) {
641723 if !reachable.contains(id) {
......@@ -769,11 +851,10 @@ pub(crate) fn write_revisions(
769851 }
770852
771853 // Native cold-open fails on long dependency chains; cap their depth at 512.
772 let checkpoint = std::iter::successors(Some(rid), |id| {
773 index.spaces[&space].revisions[id].dependency
774 })
775 .nth(511)
776 .is_some();
854 let checkpoint = rid.is_none()
855 || std::iter::successors(rid, |id| index.spaces[&space].revisions[id].dependency)
856 .nth(511)
857 .is_some();
777858 let selected: Vec<_> = revision
778859 .objects
779860 .iter()
......@@ -821,13 +902,25 @@ pub(crate) fn write_revisions(
821902 };
822903 let mut start = Vec::new();
823904 new_rid.encode(&mut start);
824 if checkpoint { ExGuid::default() } else { rid }.encode(&mut start);
905 if checkpoint {
906 ExGuid::default()
907 } else {
908 rid.unwrap()
909 }
910 .encode(&mut start);
825911 if !is_section {
826912 start.extend_from_slice(&0_u64.to_le_bytes());
827913 }
828914 start.extend_from_slice(&1_u32.to_le_bytes());
829915 start.extend_from_slice(&0_u16.to_le_bytes());
830 let mut manifest = vec![node(if is_section { 0x1e } else { 0x1b }, None, &start)?];
916 let mut manifest = Vec::new();
917 if rid.is_none() {
918 let mut payload = Vec::new();
919 space.encode(&mut payload);
920 payload.extend_from_slice(&0_u32.to_le_bytes());
921 manifest.push(node(0x14, None, &payload)?);
922 }
923 manifest.push(node(if is_section { 0x1e } else { 0x1b }, None, &start)?);
831924 for (table, objects) in groups {
832925 let mut payload = Vec::new();
833926 let mut group = if is_section {
......@@ -941,14 +1034,7 @@ pub(crate) fn write_revisions(
9411034 }
9421035 if is_section {
9431036 group.push(node(0xb8, None, &[])?);
944 let group_id = u32::try_from(counts.len())
945 .ok()
946 .and_then(|n| n.checked_add(1))
947 .and_then(|n| maximum.checked_add(n))
948 .ok_or(Error {
949 offset: 0,
950 message: "File-node list identities are exhausted",
951 })?;
1037 let group_id = allocate_list()?;
9521038 let chunk = append_list(&mut output, group_id, &group)?;
9531039 counts.push((group_id, group.len()));
9541040 manifest.push(node(0xb0, Some(Reference::NodeList(chunk)), &payload)?);
......@@ -979,47 +1065,51 @@ pub(crate) fn write_revisions(
9791065 }
9801066 }
9811067 manifest.push(node(0x1c, None, &[])?);
982 let root = store.list(store.header.root)?;
983 let space_node = root
984 .nodes
985 .iter()
986 .find(|node| node.id == 8 && node.fields(&store).exguid() == Ok(space))
987 .ok_or(Error {
988 offset: 0,
989 message: "Object space is absent from the root list",
990 })?;
991 let space_list = space_node.referenced_list(&store)?;
992 let revision_node = space_list.iter().rfind(|node| node.id == 0x10).unwrap();
993 let Some(Reference::NodeList(manifest_reference)) = revision_node.reference else {
994 unreachable!()
995 };
996 let revision_list = store.list(manifest_reference)?;
997 let last_fragment = *revision_list.fragments.last().unwrap();
998 let list_start = usize::try_from(last_fragment.offset).unwrap();
999 let list_id =
1000 u32::from_le_bytes(source[list_start + 8..list_start + 12].try_into().unwrap());
1001 let manifest_chunk = append_list(&mut output, list_id, &manifest)?;
1002 let manifest_start = usize::try_from(manifest_chunk.offset).unwrap();
1003 let sequence = u32::try_from(revision_list.fragments.len()).map_err(|_| Error {
1004 offset: list_start,
1005 message: "File-node fragment sequences are exhausted",
1006 })?;
1007 output[manifest_start + 12..manifest_start + 16].copy_from_slice(&sequence.to_le_bytes());
1008 let last_node = revision_list.nodes.last().unwrap();
1009 let node_header = u32::from_le_bytes(
1010 source[last_node.offset..last_node.offset + 4]
1011 .try_into()
1012 .unwrap(),
1013 );
1014 let nodes_end = last_node.offset + usize::try_from((node_header >> 10) & 0x1fff).unwrap();
1015 let tail = list_start + usize::try_from(last_fragment.length).unwrap() - 20;
1016 if tail - nodes_end >= 4 {
1017 output[nodes_end..nodes_end + 4].copy_from_slice(&node(0xff, None, &[])?);
1068 if rid.is_none() {
1069 let list_id = allocate_list()?;
1070 let chunk = append_list(&mut output, list_id, &manifest)?;
1071 counts.push((list_id, manifest.len()));
1072 let mut payload = Vec::new();
1073 space.encode(&mut payload);
1074 let nodes = vec![
1075 node(0xc, None, &payload)?,
1076 node(0x10, Some(Reference::NodeList(chunk)), &[])?,
1077 ];
1078 let list_id = allocate_list()?;
1079 let chunk = append_list(&mut output, list_id, &nodes)?;
1080 counts.push((list_id, nodes.len()));
1081 root_nodes.push(node(8, Some(Reference::NodeList(chunk)), &payload)?);
1082 } else {
1083 let root = store.list(store.header.root)?;
1084 let space_node = root
1085 .nodes
1086 .iter()
1087 .find(|node| node.id == 8 && node.fields(&store).exguid() == Ok(space))
1088 .ok_or(Error {
1089 offset: 0,
1090 message: "Object space is absent from the root list",
1091 })?;
1092 let space_list = space_node.referenced_list(&store)?;
1093 let revision_node = space_list.iter().rfind(|node| node.id == 0x10).unwrap();
1094 let Some(Reference::NodeList(manifest_reference)) = revision_node.reference else {
1095 unreachable!()
1096 };
1097 let revision_list = store.list(manifest_reference)?;
1098 counts.push(append_fragment(
1099 source,
1100 &mut output,
1101 revision_list,
1102 &manifest,
1103 )?);
10181104 }
1019 output[tail..tail + 8].copy_from_slice(&manifest_chunk.offset.to_le_bytes());
1020 output[tail + 8..tail + 12].copy_from_slice(&(manifest_chunk.length as u32).to_le_bytes());
1021
1022 counts.push((list_id, revision_list.nodes.len() + manifest.len()));
1105 }
1106 if !root_nodes.is_empty() {
1107 counts.push(append_fragment(
1108 source,
1109 &mut output,
1110 store.list(store.header.root)?,
1111 &root_nodes,
1112 )?);
10231113 }
10241114 if counts.is_empty() {
10251115 return Ok(source.to_vec());
crates/onestore/src/write/tests/multi.rs+10-4
......@@ -1,7 +1,7 @@
11use crate::{
22 ExGuid, RevisionIndex, Store,
33 document::{Document, Kind},
4 write::{PropertyObject, write_revisions},
4 write::{PropertyObject, RevisionEdit, write_revisions},
55};
66use std::collections::BTreeMap;
77
......@@ -90,7 +90,10 @@ fn nest(source: &[u8]) -> Vec<u8> {
9090 object.set(&[(0x24001c20, &children)])?;
9191 replacements.insert(root, object);
9292 changes.insert(index.root, replacements);
93 Ok(changes)
93 Ok(changes
94 .into_iter()
95 .map(|(sid, objects)| (sid, RevisionEdit::Update(objects)))
96 .collect())
9497 })
9598 .unwrap()
9699}
......@@ -213,7 +216,7 @@ fn empty_batches_and_invalid_spaces_do_not_produce_an_edit() {
213216 assert!(
214217 write_revisions(SOURCE, |_| Ok(BTreeMap::from([(
215218 ExGuid::default(),
216 BTreeMap::new()
219 RevisionEdit::Update(BTreeMap::new())
217220 )])))
218221 .is_err()
219222 );
......@@ -247,7 +250,10 @@ fn repeated_multi_space_edits_cross_counter_carries_and_checkpoint_each_space()
247250 object.set(&[(property, &step.to_le_bytes())])?;
248251 changes.insert(*sid, BTreeMap::from([(id, object)]));
249252 }
250 Ok(changes)
253 Ok(changes
254 .into_iter()
255 .map(|(sid, objects)| (sid, RevisionEdit::Update(objects)))
256 .collect())
251257 })
252258 .unwrap();
253259 let store = Store::parse(&written).unwrap();
crates/onestore/tests/page.rs created+356
......@@ -0,0 +1,356 @@
1use onestore::{
2 ExGuid, Insertion, PageCreation, PreparedEdit, RevisionIndex, Store,
3 document::{Document, Kind},
4};
5
6#[path = "support/current.rs"]
7mod current;
8#[path = "support/disk.rs"]
9mod disk;
10
11const SOURCE: &[u8] =
12 include_bytes!("../../../corpus/page-lifecycle/03-renamed/notebook/Lifecycle.one");
13
14#[test]
15fn native_section_accepts_empty_and_titled_pages_with_preserved_history() {
16 let original = Store::parse(SOURCE).unwrap();
17 let old_index = RevisionIndex::parse(&original).unwrap();
18 let original_pages = Document::parse(&old_index).unwrap().pages().unwrap();
19 let mut expected = original_pages.clone();
20 let mut source = SOURCE.to_vec();
21 for (ordinal, title) in [None, Some(""), Some("New 🦋 é"), Some("New 🦋 é")]
22 .into_iter()
23 .enumerate()
24 {
25 let before = (ordinal == 1).then_some(original_pages[0].0);
26 let intent = PageCreation::new(before, title, "Rust author").unwrap();
27 let serialized = serde_json::to_vec(&intent).unwrap();
28 let retained = serde_json::from_slice(&serialized).unwrap();
29 assert_eq!(intent, retained);
30 let prepared = PreparedEdit::create_page(&source, &retained).unwrap();
31 let store = Store::parse(prepared.as_bytes()).unwrap();
32 assert_eq!(
33 store.header.transaction_count,
34 original.header.transaction_count + ordinal as u32 + 1
35 );
36 assert_eq!(store.header.file_id, original.header.file_id);
37 let index = RevisionIndex::parse(&store).unwrap();
38 index.validate_current().unwrap();
39 let document = Document::parse(&index).unwrap();
40 let at = if ordinal == 1 { 0 } else { expected.len() };
41 expected.insert(at, (intent.space(), intent.object()));
42 assert_eq!(document.pages().unwrap(), expected);
43 let view = &document.spaces[&intent.space()];
44 let view = &view.revisions[&view.contexts[&ExGuid::default()]];
45 assert!(view.nodes[&intent.object()].children.is_empty());
46 assert_eq!(
47 view.nodes[&intent.object()].structure.len(),
48 usize::from(title.is_some())
49 );
50 let Kind::Metadata {
51 title: actual,
52 level,
53 } = &view.nodes[&view.roots[&2]].kind
54 else {
55 panic!()
56 };
57 assert_eq!(actual.as_deref(), Some(title.unwrap_or_default()));
58 assert_eq!(*level, Some(1));
59 if let Some(text) = intent.title_object() {
60 let Kind::RichText {
61 text, boilerplate, ..
62 } = &view.nodes[&text].kind
63 else {
64 panic!()
65 };
66 assert_eq!(text, title.unwrap());
67 assert!(!boilerplate);
68 }
69 for (sid, space) in &old_index.spaces {
70 for rid in space.revisions.keys() {
71 assert_eq!(
72 format!("{:?}", old_index.resolve(*sid, *rid).unwrap()),
73 format!("{:?}", index.resolve(*sid, *rid).unwrap())
74 );
75 }
76 if *sid != old_index.root {
77 assert_eq!(space.labels, index.spaces[sid].labels);
78 }
79 }
80 assert!(PreparedEdit::create_page(prepared.as_bytes(), &intent).is_err());
81 source = prepared.as_bytes().to_vec();
82 }
83 if let Some(output) = std::env::var_os("ONESTORE_PAGE_CREATION_OUTPUT") {
84 std::fs::create_dir(&output).unwrap();
85 std::fs::write(std::path::Path::new(&output).join("Lifecycle.one"), &source).unwrap();
86 }
87}
88
89#[test]
90fn created_pages_support_title_edits_and_body_insertion() {
91 let mut source = onestore::create_section("pages.one", "Original", "Author").unwrap();
92 for title in [None, Some(""), Some("Explicit 🦋 é")] {
93 let intent = PageCreation::new(None, title, "Author").unwrap();
94 source = PreparedEdit::create_page(&source, &intent)
95 .unwrap()
96 .as_bytes()
97 .to_vec();
98 let insertion =
99 Insertion::outline(intent.object(), 36.0, 36.0, "Body 🦀 é", "Author").unwrap();
100 source = PreparedEdit::insert(&source, intent.space(), &insertion)
101 .unwrap()
102 .as_bytes()
103 .to_vec();
104 let store = Store::parse(&source).unwrap();
105 let index = RevisionIndex::parse(&store).unwrap();
106 let document = Document::parse(&index).unwrap();
107 let view = &document.spaces[&intent.space()];
108 let view = &view.revisions[&view.contexts[&ExGuid::default()]];
109 let Kind::Metadata { title: actual, .. } = &view.nodes[&view.roots[&2]].kind else {
110 panic!()
111 };
112 assert_eq!(
113 actual.as_deref(),
114 Some(title.filter(|s| !s.is_empty()).unwrap_or("Body 🦀 é"))
115 );
116 if let Some(text) = intent.title_object() {
117 source = PreparedEdit::text(
118 &source,
119 intent.space(),
120 text,
121 0..title.unwrap().encode_utf16().count() as u32,
122 "Renamed",
123 )
124 .unwrap()
125 .as_bytes()
126 .to_vec();
127 let store = Store::parse(&source).unwrap();
128 let index = RevisionIndex::parse(&store).unwrap();
129 let document = Document::parse(&index).unwrap();
130 let view = &document.spaces[&intent.space()];
131 let view = &view.revisions[&view.contexts[&ExGuid::default()]];
132 let Kind::Metadata { title, .. } = &view.nodes[&view.roots[&2]].kind else {
133 panic!()
134 };
135 assert_eq!(title.as_deref(), Some("Renamed"));
136 }
137 }
138}
139
140#[test]
141fn invalid_page_intents_and_nonleading_anchors_reject_before_publication() {
142 for title in ["a\nb", "\r", "\0", "\u{fffc}", "\u{fddf}"] {
143 assert!(PageCreation::new(None, Some(title), "Author").is_err());
144 }
145 assert!(PageCreation::new(None, None, "\0").is_err());
146 assert!(PageCreation::new(Some(ExGuid::default()), None, "Author").is_err());
147 let source = include_bytes!("../../../corpus/page-lifecycle/04-nested/notebook/Lifecycle.one");
148 let store = Store::parse(source).unwrap();
149 let index = RevisionIndex::parse(&store).unwrap();
150 let pages = Document::parse(&index).unwrap().pages().unwrap();
151 let intent = PageCreation::new(Some(pages[4].0), Some("Child"), "Author").unwrap();
152 assert!(PreparedEdit::create_page(source, &intent).is_err());
153 let mut value = serde_json::to_value(PageCreation::new(None, None, "Author").unwrap()).unwrap();
154 value["guid"] = serde_json::to_value([0_u8; 16]).unwrap();
155 let invalid: PageCreation = serde_json::from_value(value.clone()).unwrap();
156 assert!(PreparedEdit::create_page(source, &invalid).is_err());
157 value["unknown"] = true.into();
158 assert!(serde_json::from_value::<PageCreation>(value).is_err());
159}
160
161#[test]
162fn new_space_and_section_entry_publish_as_one_complete_action() {
163 let source = onestore::create_section("pages.one", "Original", "Author").unwrap();
164 let intent = PageCreation::new(None, Some("New 🦋 é"), "Author").unwrap();
165 let prepared = PreparedEdit::create_page(&source, &intent).unwrap();
166 let old = current::current(&source);
167 let new = current::current(prepared.as_bytes());
168 assert_eq!(new.len(), old.len() + 1);
169 for write_limit in [1, 17, 4096] {
170 let mut complete = disk::Disk {
171 visible: source.clone(),
172 durable: source.clone(),
173 operation: 0,
174 fail_at: None,
175 write_limit,
176 random: 1954,
177 };
178 prepared.commit(&mut complete).unwrap();
179 assert_eq!(complete.durable, prepared.as_bytes());
180 for fail_at in 1..=complete.operation {
181 let mut interrupted = disk::Disk {
182 visible: source.clone(),
183 durable: source.clone(),
184 operation: 0,
185 fail_at: Some(fail_at),
186 write_limit,
187 random: 1954 + fail_at as u64,
188 };
189 prepared.commit(&mut interrupted).unwrap_err();
190 let observed = current::current(&interrupted.durable);
191 assert!(
192 observed == old || observed == new,
193 "{write_limit}:{fail_at}"
194 );
195 }
196 }
197}
198
199#[test]
200fn repeated_page_creation_crosses_root_fragments_counters_and_section_checkpoints() {
201 let mut source = onestore::create_section("PageStress.one", "Original", "Author").unwrap();
202 let original = source.clone();
203 let original_store = Store::parse(&original).unwrap();
204 let original_index = RevisionIndex::parse(&original_store).unwrap();
205 let mut expected = Document::parse(&original_index).unwrap().pages().unwrap();
206 let mut checkpoints = 0;
207 for step in 1..=520 {
208 let title = format!("Page {} 🦋 é", step % 7);
209 let intent = PageCreation::new(
210 None,
211 (step % 2 != 0).then_some(title.as_str()),
212 "Stress author",
213 )
214 .unwrap();
215 let prepared = PreparedEdit::create_page(&source, &intent).unwrap();
216 let mut unpublished = prepared.as_bytes().to_vec();
217 unpublished[96..100].copy_from_slice(&source[96..100]);
218 let old_store = Store::parse(&unpublished).unwrap();
219 let old_index = RevisionIndex::parse(&old_store).unwrap();
220 assert_eq!(
221 Document::parse(&old_index).unwrap().pages().unwrap(),
222 expected
223 );
224 let store = Store::parse(prepared.as_bytes()).unwrap();
225 assert_eq!(store.header.root, original_store.header.root);
226 assert_eq!(
227 store.header.transaction_count,
228 original_store.header.transaction_count + step
229 );
230 let index = RevisionIndex::parse(&store).unwrap();
231 assert_eq!(
232 index.spaces.len(),
233 original_index.spaces.len() + step as usize
234 );
235 expected.push((intent.space(), intent.object()));
236 assert_eq!(Document::parse(&index).unwrap().pages().unwrap(), expected);
237 let section = &index.spaces[&index.root];
238 let rid = section.labels[&(ExGuid::default(), 1)];
239 checkpoints += usize::from(section.revisions[&rid].dependency.is_none());
240 for (sid, space) in &original_index.spaces {
241 for rid in space.revisions.keys() {
242 assert_eq!(
243 format!("{:?}", original_index.resolve(*sid, *rid).unwrap()),
244 format!("{:?}", index.resolve(*sid, *rid).unwrap())
245 );
246 }
247 }
248 source = prepared.as_bytes().to_vec();
249 }
250 assert_eq!(checkpoints, 1);
251 if let Some(output) = std::env::var_os("ONESTORE_PAGE_STRESS_OUTPUT") {
252 std::fs::create_dir(&output).unwrap();
253 std::fs::write(
254 std::path::Path::new(&output).join("PageStress.one"),
255 &source,
256 )
257 .unwrap();
258 }
259}
260
261#[test]
262fn native_changes_on_created_pages_accept_rust_followups() {
263 let initial = include_bytes!(
264 "../../../corpus/page-lifecycle/creation/native/cold/notebook/Lifecycle.one"
265 );
266 let store = Store::parse(initial).unwrap();
267 let index = RevisionIndex::parse(&store).unwrap();
268 let document = Document::parse(&index).unwrap();
269 let mut targets = Vec::new();
270 for (sid, _) in document.pages().unwrap() {
271 let space = &document.spaces[&sid];
272 let view = &space.revisions[&space.contexts[&ExGuid::default()]];
273 let mut title = None;
274 let mut body = None;
275 for (id, node) in &view.nodes {
276 if let Kind::RichText { text, .. } = &node.kind {
277 if text == "New 🦋 é" {
278 title = Some(*id);
279 }
280 if text.starts_with("Native body ") {
281 body = Some(*id);
282 }
283 }
284 }
285 if let (Some(title), Some(body)) = (title, body) {
286 targets.push((sid, title, body));
287 }
288 }
289 assert_eq!(targets.len(), 2);
290 let mut source = initial.to_vec();
291 for (sid, title, body) in targets {
292 for (object, prefix) in [(body, "Rust + "), (title, "Reviewed ")] {
293 source = PreparedEdit::text(&source, sid, object, 0..0, prefix)
294 .unwrap()
295 .as_bytes()
296 .to_vec();
297 }
298 let store = Store::parse(&source).unwrap();
299 let index = RevisionIndex::parse(&store).unwrap();
300 let document = Document::parse(&index).unwrap();
301 let view = &document.spaces[&sid];
302 let view = &view.revisions[&view.contexts[&ExGuid::default()]];
303 assert!(
304 matches!(&view.nodes[&title].kind, Kind::RichText { text, .. } if text == "Reviewed New 🦋 é")
305 );
306 assert!(
307 matches!(&view.nodes[&body].kind, Kind::RichText { text, .. } if text.starts_with("Rust + Native body "))
308 );
309 assert!(
310 matches!(&view.nodes[&view.roots[&2]].kind, Kind::Metadata { title: Some(title), .. } if title == "Reviewed New 🦋 é")
311 );
312 }
313 if let Some(output) = std::env::var_os("ONESTORE_PAGE_FOLLOWUP_OUTPUT") {
314 std::fs::create_dir(&output).unwrap();
315 std::fs::write(std::path::Path::new(&output).join("Lifecycle.one"), &source).unwrap();
316 }
317}
318
319#[test]
320fn page_creation_preserves_native_features_and_file_data() {
321 for source in [
322 include_bytes!("../../../corpus/native-ink/20260905-ui/notebook/synthetic.one").as_slice(),
323 include_bytes!("../../../corpus/native-external-assets/notebook/synthetic.one").as_slice(),
324 include_bytes!("../../../corpus/m6/native-features-01/notebook/Features.one").as_slice(),
325 ] {
326 let before = Store::parse(source).unwrap();
327 let old = RevisionIndex::parse(&before).unwrap();
328 let original = Document::parse(&old).unwrap();
329 let intent = PageCreation::new(None, Some("Preserved features"), "Author").unwrap();
330 let prepared = PreparedEdit::create_page(source, &intent).unwrap();
331 let after = Store::parse(prepared.as_bytes()).unwrap();
332 let new = RevisionIndex::parse(&after).unwrap();
333 let document = Document::parse(&new).unwrap();
334 assert_eq!(
335 document.pages().unwrap().len(),
336 original.pages().unwrap().len() + 1
337 );
338 for (sid, space) in &old.spaces {
339 for rid in space.revisions.keys() {
340 let original = old.resolve(*sid, *rid).unwrap();
341 let retained = new.resolve(*sid, *rid).unwrap();
342 assert_eq!(format!("{original:?}"), format!("{retained:?}"));
343 for object in original.objects.values() {
344 if let Some(onestore::FileDataReference::Internal(id)) =
345 object.file_reference().unwrap()
346 {
347 assert_eq!(before.file_data(id).unwrap(), after.file_data(id).unwrap());
348 }
349 }
350 }
351 if *sid != old.root {
352 assert_eq!(space.labels, new.spaces[sid].labels);
353 }
354 }
355 }
356}
fuzz/Cargo.toml+7
......@@ -114,3 +114,10 @@ path = "fuzz_targets/offline_tree.rs"
114114test = false
115115doc = false
116116bench = false
117
118[[bin]]
119name = "page"
120path = "fuzz_targets/page.rs"
121test = false
122doc = false
123bench = false
fuzz/fuzz_targets/page.rs created+138
......@@ -0,0 +1,138 @@
1#![no_main]
2use libfuzzer_sys::fuzz_target;
3use onestore::{
4 CommitState, ExGuid, Insertion, PageCreation, PreparedEdit, RevisionIndex, Store,
5 document::{Document, Kind},
6};
7use std::sync::LazyLock;
8
9#[path = "../../crates/onestore/tests/support/current.rs"]
10mod current;
11#[path = "../../crates/onestore/tests/support/disk.rs"]
12mod disk;
13
14static SOURCE: LazyLock<Vec<u8>> = LazyLock::new(|| {
15 onestore::create_section("pages.one", "Original 🦀 é 東京", "Author").unwrap()
16});
17
18fuzz_target!(|input: &[u8]| {
19 if let Ok(intent) = serde_json::from_slice::<PageCreation>(input)
20 && let Ok(prepared) = PreparedEdit::create_page(&SOURCE, &intent)
21 {
22 current::current(prepared.as_bytes());
23 }
24 let mut persisted = SOURCE.clone();
25 let mut caches = std::array::from_fn::<_, 12, _>(|_| SOURCE.clone());
26 for step in input.chunks_exact(8).take(24) {
27 let actor = usize::from(step[0]) % caches.len();
28 if step[1] % 3 == 0 {
29 caches[actor].clone_from(&persisted);
30 }
31 let source = &caches[actor];
32 let store = Store::parse(source).unwrap();
33 let index = RevisionIndex::parse(&store).unwrap();
34 let document = Document::parse(&index).unwrap();
35 let mut pages = document.pages().unwrap();
36 let (sid, page) = pages[usize::from(step[2]) % pages.len()];
37 let space = &document.spaces[&sid];
38 let view = &space.revisions[&space.contexts[&ExGuid::default()]];
39 let text = ["", "Same title", "é 🦋 東京", " spaces "][usize::from(step[3]) % 4];
40 let titles: Vec<_> = view
41 .nodes
42 .iter()
43 .filter_map(|(id, node)| {
44 (node.extra[0].iter().any(|field| field.id == 0x88001cb4)
45 && matches!(
46 node.kind,
47 Kind::RichText {
48 boilerplate: false,
49 ..
50 }
51 ))
52 .then_some(*id)
53 })
54 .collect();
55 let (edit, title_update) = if step[1] & 8 != 0 && !titles.is_empty() {
56 let object = titles[0];
57 let Kind::RichText { text: original, .. } = &view.nodes[&object].kind else {
58 unreachable!()
59 };
60 (
61 PreparedEdit::text(
62 source,
63 sid,
64 object,
65 0..original.encode_utf16().count() as u32,
66 text,
67 )
68 .unwrap(),
69 Some((sid, object, text)),
70 )
71 } else if step[1] & 16 != 0 {
72 let intent = Insertion::outline(page, 36.0, 36.0, text, "Page fuzz").unwrap();
73 (
74 PreparedEdit::insert(source, sid, &intent).unwrap(),
75 Some((sid, intent.text_object(), text)),
76 )
77 } else {
78 let before = (step[2] & 1 != 0).then_some(sid);
79 let title = (step[3] & 4 == 0).then_some(text);
80 let intent = PageCreation::new(before, title, "Page fuzz").unwrap();
81 let restored = serde_json::from_value(serde_json::to_value(&intent).unwrap()).unwrap();
82 assert_eq!(intent, restored);
83 let edit = PreparedEdit::create_page(source, &restored).unwrap();
84 let position = before.map_or(pages.len(), |sid| {
85 pages.iter().position(|p| p.0 == sid).unwrap()
86 });
87 pages.insert(position, (intent.space(), intent.object()));
88 (
89 edit,
90 intent
91 .title_object()
92 .map(|object| (intent.space(), object, text)),
93 )
94 };
95 let after_store = Store::parse(edit.as_bytes()).unwrap();
96 let after_index = RevisionIndex::parse(&after_store).unwrap();
97 let after_document = Document::parse(&after_index).unwrap();
98 assert_eq!(after_document.pages().unwrap(), pages);
99 if let Some((sid, object, text)) = title_update {
100 let space = &after_document.spaces[&sid];
101 let view = &space.revisions[&space.contexts[&ExGuid::default()]];
102 assert!(
103 matches!(&view.nodes[&object].kind, Kind::RichText { text: actual, .. } if actual == text)
104 );
105 }
106 for (sid, space) in &index.spaces {
107 let rid = space.labels[&(ExGuid::default(), 1)];
108 assert_eq!(
109 format!("{:?}", index.resolve(*sid, rid).unwrap()),
110 format!("{:?}", after_index.resolve(*sid, rid).unwrap())
111 );
112 }
113 let before = current::current(&persisted);
114 let after = current::current(edit.as_bytes());
115 let mut disk = disk::Disk {
116 visible: persisted.clone(),
117 durable: persisted.clone(),
118 operation: 0,
119 fail_at: (step[4] != 0).then_some(usize::from(u16::from_le_bytes([step[4], step[5]]))),
120 write_limit: if step[6] & 1 == 0 { 17 } else { 4096 },
121 random: u64::from(step[7]) + 1,
122 };
123 let result = edit.commit(&mut disk);
124 let observed = current::current(&disk.durable);
125 match result {
126 Ok(()) => assert_eq!(observed, after),
127 Err(error) => {
128 assert!(observed == before || observed == after);
129 match error.state {
130 CommitState::NotCommitted => assert_eq!(observed, before),
131 CommitState::Committed => assert_eq!(observed, after),
132 CommitState::Unknown => {}
133 }
134 }
135 }
136 persisted = disk.durable;
137 }
138});
tools/native/created-pages.ps1 created+35
......@@ -0,0 +1,35 @@
1param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost)
2Set-StrictMode -Version Latest
3$ErrorActionPreference = 'Stop'
4& "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost
5$app = New-Object -ComObject OneNote.Application
6$notebook = ''
7try {
8 $app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0)
9 $section = ''
10 $app.OpenHierarchy('Lifecycle.one', $notebook, [ref]$section, 0)
11 $deadline = [DateTime]::UtcNow.AddSeconds(30)
12 do {
13 $hierarchy = ''
14 $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
15 [xml]$tree = $hierarchy
16 $pages = @($tree.SelectNodes('//*[local-name()="Page"]'))
17 if ($pages.Count -eq 13) { break }
18 Start-Sleep -Milliseconds 200
19 } while ([DateTime]::UtcNow -lt $deadline)
20 $targets = @($pages | Where-Object { $_.GetAttribute('name').StartsWith('New ') })
21 if ($pages.Count -ne 13 -or $targets.Count -ne 2) { throw 'Expected thirteen pages and two created title controls.' }
22 $inputs = Join-Path $Root 'inputs'
23 [void](New-Item -ItemType Directory -Path $inputs)
24 for ($i = 0; $i -lt $targets.Count; $i++) {
25 $pageId = [Security.SecurityElement]::Escape($targets[$i].GetAttribute('ID'))
26 $xml = "<one:Page xmlns:one='http://schemas.microsoft.com/office/onenote/2010/onenote' ID='$pageId'><one:Outline><one:Position x='72' y='144'/><one:OEChildren><one:OE><one:T>Native body $i after Rust page creation.</one:T></one:OE></one:OEChildren></one:Outline></one:Page>"
27 [IO.File]::WriteAllText((Join-Path $inputs ("native-$i.xml")), $xml, [Text.Encoding]::UTF8)
28 $app.UpdatePageContent($xml, [DateTime]::MinValue, 1, $false)
29 }
30 $app.SyncHierarchy($notebook)
31} finally {
32 [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
33 [GC]::Collect()
34 [GC]::WaitForPendingFinalizers()
35}
tools/test_page_creation.py created+48
......@@ -0,0 +1,48 @@
1import json
2from pathlib import Path
3import subprocess
4from tempfile import TemporaryDirectory
5import unittest
6
7from document_model import EXPORTER, ordered_pages, walk
8from verify_page_creation import compare
9
10FIXTURE = Path(__file__).resolve().parent.parent / 'corpus/page-lifecycle/creation'
11
12
13class PageCreationTest(unittest.TestCase):
14 def test_created_pages_and_both_writers_survive_native_cold_reopens(self):
15 for source, capture in [('candidate', 'cold'), ('native/notebook', 'native/cold'), ('followup', 'followup/cold')]:
16 with self.subTest(source=source):
17 compare(FIXTURE / source, FIXTURE / capture)
18
19 def test_duplicate_titles_keep_distinct_pages_through_native_and_rust_edits(self):
20 with TemporaryDirectory() as temporary:
21 identities = None
22 for ordinal, path in enumerate(('candidate', 'native/cold/notebook', 'followup/cold/notebook')):
23 output = Path(temporary) / str(ordinal)
24 subprocess.run([EXPORTER, FIXTURE / path / 'Lifecycle.one', output], check=True)
25 document = json.loads((output / 'document.json').read_text())
26 pages = list(ordered_pages(document))
27 self.assertEqual(len(pages), 13)
28 current = [(sid, page) for sid, _, _, page in pages]
29 self.assertEqual(len(set(current)), 13)
30 if identities is None:
31 identities = current
32 self.assertEqual(identities, current)
33 for index, (_, _, view, page) in enumerate(pages[-2:]):
34 title = ('Reviewed ' if ordinal == 2 else '') + 'New 🦋 é'
35 self.assertEqual(view['nodes'][view['roots']['2']]['kind']['title'], title)
36 expected = [title]
37 if ordinal:
38 expected.append(('Rust + ' if ordinal == 2 else '') + f'Native body {index} after Rust page creation.')
39 self.assertEqual([node['kind']['text'] for _, node in walk(view, page)
40 if node['kind']['type'] == 'RichText'], expected)
41 for at, titled in [(0, True), (10, False)]:
42 _, _, view, page = pages[at]
43 self.assertEqual(bool(view['nodes'][page]['structure']), titled)
44 self.assertEqual(view['nodes'][page]['children'], [])
45
46
47if __name__ == '__main__':
48 unittest.main()
tools/verify_page_creation.py created+73
......@@ -0,0 +1,73 @@
1"""Compare created pages with native XML and cold-reopened object graphs."""
2import argparse
3from copy import deepcopy
4import json
5from pathlib import Path
6import runpy
7import shutil
8import subprocess
9from tempfile import TemporaryDirectory
10from uuid import UUID
11
12from document_model import EXPORTER, ordered_pages, view
13
14compare_document = runpy.run_path(str(Path(__file__).with_name('verify-document.py')))['compare']
15
16
17def compare(source, capture):
18 files = list(source.glob('*.one'))
19 assert len(files) == 1
20 with TemporaryDirectory() as temporary:
21 temporary = Path(temporary)
22 native = temporary / 'native/read'
23 shutil.copytree(capture / 'read', native)
24 notebook = temporary / 'notebook'
25 notebook.mkdir()
26 (notebook / files[0].name).symlink_to(files[0].resolve())
27 compare_document(notebook, native)
28 models = []
29 for ordinal, file in enumerate((files[0], capture / 'notebook' / files[0].name)):
30 output = temporary / str(ordinal)
31 subprocess.run([EXPORTER, file, output], check=True)
32 models.append(json.loads((output / 'document.json').read_text()))
33 before, after = models
34 pages = list(ordered_pages(before))
35 assert [(sid, page) for sid, _, _, page in pages] == [
36 (sid, page) for sid, _, _, page in ordered_pages(after)]
37 assert before['root'] == after['root']
38 assert before['spaces'].keys() == after['spaces'].keys()
39 filled = 0
40 for sid in before['spaces']:
41 _, original = view(before, sid)
42 _, observed = view(after, sid)
43 expected = deepcopy(original['nodes'])
44 if sid == before['root']:
45 for series_id in original['nodes'][original['roots']['1']]['children']:
46 series = expected[series_id]
47 existing = [p for p in series['extra'][0] if p['id'] == 0x24003442]
48 added = [p for p in observed['nodes'][series_id]['extra'][0] if p['id'] == 0x24003442]
49 if existing or not added:
50 continue
51 copies = []
52 for page_sid in series['spaces']:
53 (_, _, page_view, _), = [p for p in pages if p[0] == page_sid]
54 # Native uses the space GUID when it differs from the page-node GUID.
55 guid = UUID(page_sid.split('}')[0].strip('{')).bytes_le
56 salt = UUID('22a8c031-3600-42ee-b714-d7acda2435e8').bytes_le
57 metadata = '{' + str(UUID(bytes_le=bytes(a ^ b for a, b in zip(guid, salt, strict=True)))).upper() + '},1'
58 assert metadata not in expected
59 expected[metadata] = page_view['nodes'][page_view['roots']['2']]
60 copies.append(metadata)
61 filled += 1
62 series['extra'][0].append({'id': 0x24003442, 'value': {'Objects': copies}})
63 assert original['roots'] == observed['roots']
64 assert expected == observed['nodes'], sid
65 print(f'Passed: {len(pages)} ordered pages and preserved active graphs; {filled} missing section metadata copies filled natively')
66
67
68if __name__ == '__main__':
69 parser = argparse.ArgumentParser(description=__doc__)
70 parser.add_argument('source', type=Path)
71 parser.add_argument('capture', type=Path)
72 args = parser.parse_args()
73 compare(args.source, args.capture)