diff --git a/corpus/conflict-page/README.md b/corpus/conflict-page/README.md
index ffe296770ee5a58ef7a9d29c5301215a1dbf9bfa..b540b343d993dd2cbdaaa87cdd456213cefbe955 100644
--- a/corpus/conflict-page/README.md
+++ b/corpus/conflict-page/README.md
@@ -58,6 +58,11 @@ holding A's edit, in a new series where A had it; B's version stays in the recyc
- `native-restore`: from One, Two, Target, Three, Four, A moved Four before One
(re-seriesing One, Two, Target, Three) and B deleted Target: Four, One, Two, Target, Three.
+`series-move` is `a_move_after_a_native_merge_drops_its_empty_series`
+(`crates/onestore/tests/page_movement.rs`, `ONESTORE_EMPTY_SERIES_EXPORT`): Rust moves a
+page of `native-pages/merged`, giving it a series of its own and dropping the empty
+series; OneNote's cold read (`cold`) keeps every byte after the header.
+
`page_moves_and_a_removed_page_merge_as_onenote_merges_them` in
`crates/notebook/tests/sync_pages.rs` replays both with Snowbound's queue, A's moves as
moves of the pages A re-seriesed, and reaches OneNote's order.
diff --git a/corpus/conflict-page/series-move/candidate/synthetic.one b/corpus/conflict-page/series-move/candidate/synthetic.one
new file mode 100644
index 0000000000000000000000000000000000000000..75084eb9bc4aa62589ed9ddc0c31d995a55099c2
Binary files /dev/null and b/corpus/conflict-page/series-move/candidate/synthetic.one differ
diff --git a/corpus/conflict-page/series-move/cold/commands.jsonl b/corpus/conflict-page/series-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..1561461d6e8c2b377b7a80a0691cd691c30f190f
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-BAB2A5E1 -ExpectedPages 6", "exit": 0, "stdout": "Read 1 sections and 6 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/conflict-page/series-move/cold/machine.json b/corpus/conflict-page/series-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..45e2ecbe277496ef6f63e165c9acb9a4ce2bdcbc
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-bab2a5e1", "hostname": "ONE-M6-BAB2A5E1"}
diff --git a/corpus/conflict-page/series-move/cold/notebook/Open Notebook.onetoc2 b/corpus/conflict-page/series-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..de4e9a08aee7794a4b7fac1aa4f3162c296f5df9
Binary files /dev/null and b/corpus/conflict-page/series-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/conflict-page/series-move/cold/notebook/synthetic.one b/corpus/conflict-page/series-move/cold/notebook/synthetic.one
new file mode 100644
index 0000000000000000000000000000000000000000..3f09b6bb6752e2e99baf53edb4dc3e2a39fd32d5
Binary files /dev/null and b/corpus/conflict-page/series-move/cold/notebook/synthetic.one differ
diff --git a/corpus/conflict-page/series-move/cold/read/af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7.attachment b/corpus/conflict-page/series-move/cold/read/af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7.attachment
new file mode 100644
index 0000000000000000000000000000000000000000..66b6151e91f90df6a61a19ef2f4447da278e07b2
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7.attachment
@@ -0,0 +1 @@
+Fictitious attachment for native corpus.
\ No newline at end of file
diff --git a/corpus/conflict-page/series-move/cold/read/environment.json b/corpus/conflict-page/series-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..558738690b859d204761f42546811b79ff46b25a
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-BAB2A5E1",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/conflict-page/series-move/cold/read/hierarchy.xml b/corpus/conflict-page/series-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8609425b71fd4757d515aaa6914ec0906881a10f
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/conflict-page/series-move/cold/read/page-000.xml b/corpus/conflict-page/series-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d71a7aa8e4c7c06da9f0db4de7495ba16ce0b28e
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/conflict-page/series-move/cold/read/page-001.xml b/corpus/conflict-page/series-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1a0aaa3c40859abf0fc98bf04a71cb9d2d9448ba
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/conflict-page/series-move/cold/read/page-002.xml b/corpus/conflict-page/series-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fee1f8cd287cf05959241a3982ec1da5d436d530
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/conflict-page/series-move/cold/read/page-003.xml b/corpus/conflict-page/series-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a7819ad6d77e22f21d49472f3cd29ad5bd21d739
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/conflict-page/series-move/cold/read/page-004.xml b/corpus/conflict-page/series-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aab83066edbd248a1ec4e09bcc10d66aa68eb0ad
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/conflict-page/series-move/cold/read/page-005.xml b/corpus/conflict-page/series-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..79cbccdfc5a48a04dd373268dada7092acd1f1a7
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/page-005.xml
@@ -0,0 +1,26 @@
+
+Fictitious: café, 東京, مرحبا]]>AK4FHQSiAaIBAWAqABofi0JwRYR1gL7QRdkE+oeVMvLsF0G4wBa/8yv0et67E4vlXrNInJuhJVq3
+URK/7HHMzCKxQYkOuxMs7nqhWM9UiuaXxU+PBvi60uGbIsRmbacNslhJmh1OQDQGbBADBkgQRSNG
+IwUIC2VPZmdoZGkZFDIIAIAeAiHi4kEzCADwEAKLxeJBZAMVRgBACpUE/QGH81d3mq7mkzgM0mcB
+mk1gEBgEBgEBgE1mUAgMzmUAmsygE1mUzmkBmc0gMzmk1mUAmsyTOaTWZQCazKZgALSmiazKATWZ
+QCAwCAwBAZpM4DAJlNYBMprAJlNZpM4DNJmmU1mkzgM0mcBmkzmU1gEyAAFpTSAzOaQGZzRAYBAY
+BAYBMprAIDNJnAZpM0yms0mcBmkzgM0mcymsAmU1gEyms0maZAACZTSawCZTWATKawCAoBAYBAZn
+NIDAJrMoBNZlAJrMpnMoBNZlAJrMpnNIDM5pAZnNJrMkzmk1AACH8C7XgWnmkzgM0msAmU1gEBgE
+BgEBTOaQGATWZQCazKATWZTOaTWZTNNJrMpmmUzTSaplM00mqZTOaTVMpmmk1TKATKazSawCAzSZ
+wGAQFAIDAJrMoBAZnNIDM5pAZnMpnNJrMpmmk1mUzTSaplM00mqZTNNJrMpmmk1TKZplhuAzKATW
+ZQCazKAIDAIDAIDNJnAYBMprAJlM4DNJnMprNJnMk1mkzmSazRM5kms0TOZJnMprNEzmSazQtKaQ
+GZzRNZlAIDAIDAIDAJlNYAmU1gEymsAmU1mkzmU1miZzKazRM5kmcyTWaJnMk1mkzmSazRM5kAUU
+RgBAAAAJBAUURgAAAAASABEgXhT+65lz/EiPi+8SFvjqCAk+gEcDAa/89Qd0AxVGAEAKABEg2R87
+QQrSFUA=AOECHQJSegFgKgAaH4tCcEWEdYC+0EXZBPqHlTLy7BdBuMAWv/Mr9HreuxOL5V6zSJyboSVat1ES
+v+xxzMwisUGJDrsTLO56oVjPVIrml8VPjwb4utLhmyLEZm2nDbJYSZodTkA0BmwQAwZIEEUjRiMF
+CAtlT2ZnaGRpGRQyCACAHgIh4uJBMwgA8BACi8XiQWQDFUYAQArKAUuH88s3nkzmkzgM0mcBmkzg
+KAQGAQGATWZQCAzOaQGZzKATWZTOaQGZzSAzOaTWZQCazJM5pNZlAJrMpmAAAACH8D9XgeBJlM0z
+mRNZpNZpM4DAJlNYBAUAgMAgMzmkBgE1mUAmsyTOaTWZTOaTVMpnNJqmUzTSaplM00mqZTOZTNNJ
+qmUzTSagBRRGAIAAAAkEBRRGAAAAABIAESDPTQ4xwIZyTqQ8FVDbHxeKCj9AI5rARvPPUDugAxVG
+AEAKABEgLMlfQdkfI0A=iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAusB9Y9J1uoA
+AAAASUVORK5CYII=
diff --git a/corpus/conflict-page/series-move/cold/read/payloads.json b/corpus/conflict-page/series-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..229effe100aa68119db3065f5255bd77f368ae3a
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/read/payloads.json
@@ -0,0 +1,10 @@
+[
+ {
+ "sha256": "af1af4b8987109ce1e335e538910fb3860b7c57eb3b6110a06aa2114e06d69a7",
+ "name": "fictitious-attachment.txt",
+ "object": "{15F5F520-9712-4630-BDC9-C9932963E8D2}{11}{B0}",
+ "kind": "InsertedFile",
+ "page": "{9CBAF166-4FD0-45B3-BB50-0BCAAA4F6E47}{1}{B0}",
+ "bytes": 43
+ }
+]
\ No newline at end of file
diff --git a/corpus/conflict-page/series-move/cold/run.json b/corpus/conflict-page/series-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..254fa4a9b489333970a43599550ca41987e27e79
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/Users/clo/dev/one/evidence/series/empty-series",
+ "expected_pages": 6,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/conflict-page/series-move/cold/scripts/cold.ps1 b/corpus/conflict-page/series-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/conflict-page/series-move/cold/scripts/read.ps1 b/corpus/conflict-page/series-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/conflict-page/series-move/cold/source.json b/corpus/conflict-page/series-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..200d0ed30d5bde12015795462984fa4e0b6d62e1
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "synthetic.one",
+ "bytes": 67768,
+ "sha256": "7c55e483f464d329e7bb394813d202bc1295f0a24ecc895a3c81fa3b582a02bd",
+ "mtime_ns": 1790524980196111805
+ }
+]
diff --git a/corpus/conflict-page/series-move/cold/teardown.json b/corpus/conflict-page/series-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/conflict-page/series-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/notebook-management/README.md b/corpus/notebook-management/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..740888260d744b036414238a591958a4aad90288
--- /dev/null
+++ b/corpus/notebook-management/README.md
@@ -0,0 +1,38 @@
+# Notebook management
+
+`candidate` is the notebook `a_notebook_is_managed_as_onenote_manages_one` in
+`crates/snowbound/src/manage.rs` makes through the calls the app makes: `Notebook::create`
+(a table of contents in the notebook colour OneNote gave new notebooks, and "New Section 1"
+holding a page with OneNote's title date and time fields); new sections in OneNote's
+new-section colour order and groups; pages created with `SectionOp::Create`, titled with
+`Text`, given our Ivy art as a background picture (`template_ops`) or the Teal page colour
+(`PageOp::Color`), and made a subpage; a page given Informal Meeting Notes (the art and
+the template's outlines, lowered to ops from the page model `meeting.rs` builds); a page deleted to the recycle bin
+(`Notebook::recycle_pages`, then `SectionOp::Delete`); a page moved to another section
+as a drop on its tab moves it (`notebook::session::moved`, then `SectionOp::Delete`); a section renamed and moved into a
+group, the group renamed, a group and a section deleted to the recycle bin, and the root
+reordered.
+
+`cold` is its fresh OneNote 2010 read: the hierarchy lists every section, group and page
+where the app put it, with its colour; the recycle bin holds "Deleted Pages"
+(`isDeletedPages`) with the deleted page, and the deleted group's and section's files; the
+Teal page reads back `color="#D4F9F2"`, the Ivy page one background image, the Meeting
+page OneNote's four outlines with their numbering, to-do tag and bullets, and the
+screenshots show the art, the colour and each title's date and time. OneNote left the
+files' identities as written. `tools/test_notebook_management.py` checks this without a VM.
+
+`native` is what OneNote 2010 did through its own interface on the VM. `new-notebook`:
+File, New made "New Section 1" with an "Untitled page" titled with the date and time
+(`created`); New Section named sections "New Section N"; a section dragged onto a group
+moved into its folder (`moved`); deleting a page copied it into
+`OneNote_RecycleBin/OneNote_DeletedPages.one` (grey) with its identity, title and
+creation time, and deleting a group moved its sections into the recycle bin and removed
+its folder (`final`). `section-colors`: sixteen sections made with New Section, whose
+colours are the order new sections take. `page-color`: View, Page Color stores
+`0x14001d2a` (COLORREF) on the page node and "No color" removes it; `colors.txt` is each
+of the sixteen colours as the page XML reports it, in the menu's order. `meeting-template`
+is the page XML of a page made from Business, Informal Meeting Notes.
+
+Regenerate with `SNOWBOUND_MANAGEMENT_EXPORT` set to a new directory while running the
+test, then `tools/native_runner.py OUTPUT COLD --expected-pages -1 --collect-notebook
+--screenshots`.
diff --git a/corpus/notebook-management/candidate/Archive/Inner.one b/corpus/notebook-management/candidate/Archive/Inner.one
new file mode 100644
index 0000000000000000000000000000000000000000..3c2ba163fbc30575f8b08d0b11d986535f61a681
Binary files /dev/null and b/corpus/notebook-management/candidate/Archive/Inner.one differ
diff --git a/corpus/notebook-management/candidate/Archive/Kitchen.one b/corpus/notebook-management/candidate/Archive/Kitchen.one
new file mode 100644
index 0000000000000000000000000000000000000000..5962d483ac23f9553469c62a67f46989809d1955
Binary files /dev/null and b/corpus/notebook-management/candidate/Archive/Kitchen.one differ
diff --git a/corpus/notebook-management/candidate/Archive/Open Notebook.onetoc2 b/corpus/notebook-management/candidate/Archive/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..dedfd5215945f6ad75e1fccb1a8177b8e10d922e
Binary files /dev/null and b/corpus/notebook-management/candidate/Archive/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/candidate/New Section 1.one b/corpus/notebook-management/candidate/New Section 1.one
new file mode 100644
index 0000000000000000000000000000000000000000..e0165ec08fc5def1d657b30a897322c8cec67ed3
Binary files /dev/null and b/corpus/notebook-management/candidate/New Section 1.one differ
diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/Binned.one b/corpus/notebook-management/candidate/OneNote_RecycleBin/Binned.one
new file mode 100644
index 0000000000000000000000000000000000000000..58c3ded0a9e206b0cfa74314573980d4a8b80d5a
Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/Binned.one differ
diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/Gone.one b/corpus/notebook-management/candidate/OneNote_RecycleBin/Gone.one
new file mode 100644
index 0000000000000000000000000000000000000000..323c0959345c375689929e184e118bba7c2bbdc9
Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/Gone.one differ
diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/candidate/OneNote_RecycleBin/OneNote_DeletedPages.one
new file mode 100644
index 0000000000000000000000000000000000000000..5d5029ff8df9d995ccae84c336437513a8d124d2
Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/OneNote_DeletedPages.one differ
diff --git a/corpus/notebook-management/candidate/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/candidate/OneNote_RecycleBin/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..77840fd4927a26d842ce933e6ad13199191d6e62
Binary files /dev/null and b/corpus/notebook-management/candidate/OneNote_RecycleBin/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/candidate/Open Notebook.onetoc2 b/corpus/notebook-management/candidate/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..78a587ca72eb2b4e4a34dd6e3da20a93b5a4399a
Binary files /dev/null and b/corpus/notebook-management/candidate/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/cold/commands.jsonl b/corpus/notebook-management/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..bdc582b97c968d6bba445f644c38bfe888998749
--- /dev/null
+++ b/corpus/notebook-management/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-C64C87EA -ExpectedPages -1 -KeepOpen", "exit": 0, "stdout": "Read 6 sections and 11 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/notebook-management/cold/machine.json b/corpus/notebook-management/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..aef822426d5ea4ba407e22b013a346495a932367
--- /dev/null
+++ b/corpus/notebook-management/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-c64c87ea", "hostname": "ONE-M6-C64C87EA"}
diff --git a/corpus/notebook-management/cold/notebook/Archive/Inner.one b/corpus/notebook-management/cold/notebook/Archive/Inner.one
new file mode 100644
index 0000000000000000000000000000000000000000..3c2ba163fbc30575f8b08d0b11d986535f61a681
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Archive/Inner.one differ
diff --git a/corpus/notebook-management/cold/notebook/Archive/Kitchen.one b/corpus/notebook-management/cold/notebook/Archive/Kitchen.one
new file mode 100644
index 0000000000000000000000000000000000000000..5962d483ac23f9553469c62a67f46989809d1955
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Archive/Kitchen.one differ
diff --git a/corpus/notebook-management/cold/notebook/Archive/Open Notebook.onetoc2 b/corpus/notebook-management/cold/notebook/Archive/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..dedfd5215945f6ad75e1fccb1a8177b8e10d922e
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Archive/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/cold/notebook/New Section 1.one b/corpus/notebook-management/cold/notebook/New Section 1.one
new file mode 100644
index 0000000000000000000000000000000000000000..0c4cdcb43cf46c6558336ae39699c6bfa2712a05
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/New Section 1.one differ
diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Binned.one b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Binned.one
new file mode 100644
index 0000000000000000000000000000000000000000..58c3ded0a9e206b0cfa74314573980d4a8b80d5a
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Binned.one differ
diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Gone.one b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Gone.one
new file mode 100644
index 0000000000000000000000000000000000000000..323c0959345c375689929e184e118bba7c2bbdc9
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Gone.one differ
diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/OneNote_DeletedPages.one
new file mode 100644
index 0000000000000000000000000000000000000000..5d5029ff8df9d995ccae84c336437513a8d124d2
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/OneNote_DeletedPages.one differ
diff --git a/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..77840fd4927a26d842ce933e6ad13199191d6e62
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/OneNote_RecycleBin/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/cold/notebook/Open Notebook.onetoc2 b/corpus/notebook-management/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..78a587ca72eb2b4e4a34dd6e3da20a93b5a4399a
Binary files /dev/null and b/corpus/notebook-management/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/cold/read/environment.json b/corpus/notebook-management/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..f7eb402d6aa1a310167f9d76ccc2b8ff049c8835
--- /dev/null
+++ b/corpus/notebook-management/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-C64C87EA",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/notebook-management/cold/read/hierarchy.xml b/corpus/notebook-management/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f695994113f6b0f0bf7dd261ee60615c00802ea9
--- /dev/null
+++ b/corpus/notebook-management/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-000.navigation.json b/corpus/notebook-management/cold/read/page-000.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..ac6854758e1c1c8293a873d4b0e7f108b6dd562c
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-000.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Ivy page - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-000.png b/corpus/notebook-management/cold/read/page-000.png
new file mode 100644
index 0000000000000000000000000000000000000000..f81b30607798ee8a9aa453077d6a7bdcf98f7ce2
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-000.png differ
diff --git a/corpus/notebook-management/cold/read/page-000.xml b/corpus/notebook-management/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a68f4ab1bcb13e59b26ff556fa55e650fc679fd0
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-000.xml
@@ -0,0 +1,353 @@
+
+/9j/4AAQSkZJRgABAgAAAQABAAD//gAYU25vd2JvdW5kIHRlbXBsYXRlIGl2ef/AABEIAxgA2AMB
+EQACEQEDEQH/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsL
+EBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQU
+FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQID
+BAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHB
+FVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2
+d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna
+4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1
+EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ0
+4SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeI
+iYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery
+8/T19vf4+fr/2gAMAwEAAhEDEQA/AP1ToAKAOS8f+KbvwbFYamkX2nThL5V3EB8wDfdcH2wRjoc1
+5GYYqpg+SqleN7NfkzGtV9jDnauup0el6nbazp8F7aSCW2nUOjjuK9KlVhXgqkHdM1TUldbHK/Cf
+/kW7r/sIXH/odeblf8F/4pfmcGB/hv1Z2leuegFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQBW1HTrbVrGazu4lntpl2PG3QisqtKFaDpzV0xNKSszmNP0uP4X+ENUZLh7y1t
+vMuIUkGCgxwme/PfjrXlU6X9l4ao+bmSu1/l95lCEcPTstlf/Mz/AIM3Dt4GM03+ta6mZsjHzFuf
+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
diff --git a/corpus/notebook-management/cold/read/page-001.navigation.json b/corpus/notebook-management/cold/read/page-001.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..20e0221bdcf96d641ed39c1832eccfa918ed7e69
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-001.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Untitled page (Read-Only - Recycle Bin) - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-001.png b/corpus/notebook-management/cold/read/page-001.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed8d73fac0ceab73e50d4a6f264d051e90fd7563
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-001.png differ
diff --git a/corpus/notebook-management/cold/read/page-001.xml b/corpus/notebook-management/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d4cb0a4dd2f3587fce7410f767e477baf2e6acec
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-002.navigation.json b/corpus/notebook-management/cold/read/page-002.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..a3ec3aa40d7375c559da1ef012a98cc97da4412c
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-002.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Untitled page - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-002.png b/corpus/notebook-management/cold/read/page-002.png
new file mode 100644
index 0000000000000000000000000000000000000000..5b95aede972f80028ddd390c5c0cb7107cc7fd25
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-002.png differ
diff --git a/corpus/notebook-management/cold/read/page-002.xml b/corpus/notebook-management/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d2c26e6002845b90cdf8fe649a3eb28ad87bb0da
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-003.navigation.json b/corpus/notebook-management/cold/read/page-003.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..a3ec3aa40d7375c559da1ef012a98cc97da4412c
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-003.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Untitled page - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-003.png b/corpus/notebook-management/cold/read/page-003.png
new file mode 100644
index 0000000000000000000000000000000000000000..414786112e263cf616c5da191808e6450a83ba67
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-003.png differ
diff --git a/corpus/notebook-management/cold/read/page-003.xml b/corpus/notebook-management/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..194401d5f5f29be6d2b415ffbf73cc80fa4ffaf6
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-004.navigation.json b/corpus/notebook-management/cold/read/page-004.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..757040e961a0fe5e54443e3ab577881b6b8568bc
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-004.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Deleted page (Read-Only - Recycle Bin) - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-004.png b/corpus/notebook-management/cold/read/page-004.png
new file mode 100644
index 0000000000000000000000000000000000000000..8ce36b51d4cd1c7c4305a7a7629fa2c3c8c9d02a
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-004.png differ
diff --git a/corpus/notebook-management/cold/read/page-004.xml b/corpus/notebook-management/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d576a32c4e28a1c822f1aa024db30149cdceb1b0
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-005.navigation.json b/corpus/notebook-management/cold/read/page-005.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..20e0221bdcf96d641ed39c1832eccfa918ed7e69
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-005.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Untitled page (Read-Only - Recycle Bin) - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-005.png b/corpus/notebook-management/cold/read/page-005.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ce88073d57856c4b9a2ccbd55b975b56f0d2015
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-005.png differ
diff --git a/corpus/notebook-management/cold/read/page-005.xml b/corpus/notebook-management/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..841e9fb04117ed54b846dd560f50b2cbdd25a611
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-006.navigation.json b/corpus/notebook-management/cold/read/page-006.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..2fa796696208f53a7e0ea8c6c71d646a15d6e2bd
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-006.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Moved page - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-006.png b/corpus/notebook-management/cold/read/page-006.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffeb407e94c8d18ea0f03c6ce91bf5e00571b426
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-006.png differ
diff --git a/corpus/notebook-management/cold/read/page-006.xml b/corpus/notebook-management/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c1d46ea159d32ee8cdcebc4cfe0f780a6c75208c
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-007.navigation.json b/corpus/notebook-management/cold/read/page-007.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..64dd2a7d5c176e5251e86cd9c7806550d101baaa
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-007.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Subpage - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-007.png b/corpus/notebook-management/cold/read/page-007.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ff4506a271959248a80170f8dee03ca707f0034
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-007.png differ
diff --git a/corpus/notebook-management/cold/read/page-007.xml b/corpus/notebook-management/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..57cfc811a3a9d564f17afc25ef1031028802dedc
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-007.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-008.navigation.json b/corpus/notebook-management/cold/read/page-008.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..f70a181359d1b0b864f1b599b34955e5b50a3929
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-008.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Teal page - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-008.png b/corpus/notebook-management/cold/read/page-008.png
new file mode 100644
index 0000000000000000000000000000000000000000..fff8b2d52036abe34fd4d510a2f320ea316966f4
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-008.png differ
diff --git a/corpus/notebook-management/cold/read/page-008.xml b/corpus/notebook-management/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bdcf9695fcdb9332b7c7d840bb9c59940c89bfc9
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-009.navigation.json b/corpus/notebook-management/cold/read/page-009.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..546ea1cbdf4f48c614748b7e3e8bf00339cd4541
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-009.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Garden plan - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-009.png b/corpus/notebook-management/cold/read/page-009.png
new file mode 100644
index 0000000000000000000000000000000000000000..3711d76195cba4e60fd064d8bb610fc8972343ff
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-009.png differ
diff --git a/corpus/notebook-management/cold/read/page-009.xml b/corpus/notebook-management/cold/read/page-009.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b2c0ff6de0d913c81c9acfba464843e0f228e123
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-009.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/notebook-management/cold/read/page-010.navigation.json b/corpus/notebook-management/cold/read/page-010.navigation.json
new file mode 100644
index 0000000000000000000000000000000000000000..74254503daba42e8020fe5a0fe571b3faf618fe0
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-010.navigation.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Meeting page - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/read/page-010.png b/corpus/notebook-management/cold/read/page-010.png
new file mode 100644
index 0000000000000000000000000000000000000000..01580be61f561c37ae680d012379751a38befbdb
Binary files /dev/null and b/corpus/notebook-management/cold/read/page-010.png differ
diff --git a/corpus/notebook-management/cold/read/page-010.xml b/corpus/notebook-management/cold/read/page-010.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d9851076f835702c16f7d40a5e43ffab099d102
--- /dev/null
+++ b/corpus/notebook-management/cold/read/page-010.xml
@@ -0,0 +1,345 @@
+
+/9j/4AAQSkZJRgABAgAAAQABAAD//gAkU25vd2JvdW5kIHRlbXBsYXRlIHNtYWxsLXB1c2gtcGlu
+c//AABEIAxgCZAMBEQACEQEDEQH/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsK
+CwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQU
+FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/xAAfAAABBQEBAQEB
+AQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEH
+InEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFla
+Y2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbH
+yMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQID
+BAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJ
+IzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1
+dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY
+2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhEDEQA/AP1ToAKACgAoAa7rGjO7BVUZLMcAD1oS
+vogOF1j4tWFjcGKztnvwpwZN+xPw4JP5V61PLpzV5uxyyxEU9NTsdK1KHWNOgvLc5imUMM9R6g+4
+PH4V5tSDpycJdDojJSV0W6zKCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDzb4u65c24ttNi3RwTJ5kjj+PnAX8OpHuK
+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
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBUvseS2cVpDclnl3igL55x6
+171DY4am5gRS7GrraMEWb253adKPp/MVEI+8im9DbBzXIzUWpAKACmBXklLybecCtErIlnR+HNea
+wIiny0B790/+tXFXo8+q3N4TtozauPGMEcmIoGlUfxE7a5o4Ztas1dRGvpuoR6naiaMMozghuxrn
+nB03ZmkXzK5arMoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKAM7VS3kHFbU9yJHm2s2EtxO3Br26c0kcUk2Zq6NKT901r7ZEcg3V9Me00meRgQBt/
+9CFOlUUppClG0bm6LN1HSuXmNrB9mfPSldBYcto57UcyCxZh0t5D0qHNIpRJP+ETnOWjYN32txS+
+sR6h7N9CrPayWMnlzIUbGcGtFJT1RDVtyNHVnVSyoGIG5jgDPFN6K4LU7yzuIbK2jhjxtQY+vvXk
+yTk7s607aE66gpPWp5CrkiXit3qXFoLkyyBqixQ6gBaACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKAIpohKuDTTsKxnyaNE+SVrb2rRPKUpdKRH+6Kr2jYuUwv
+iTarbeBNSlUYK+Vz/wBtUFduBlzYmK9fyZz4hWpNnUPoyHtXD7VnRykf9iJn7tP2rFykqaOg7UnU
+HylmPT0TtUObY7EV3KLdTinFcwPQ47xE7TyrMMkAbT7V6VBWVjmnqVtPt0eFzKiyK4xtcZGPpV1H
+0QookijmsOLWQtD/AM8JTkL/ALp6j6HI+lZ2T3K2LkOoM4/iVh1VuCKlwHcsR6gw71DgO5qWGoly
+BWE4GiZuRNuTNcr0NCSkMKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoASgAIzQBWmi3GmmI5P4rrt+Herf9sv8A0clell3+9Q+f5M5sT/Cf9dTtcV5h1BigAxQA
+UAUb61MoNawlYhowbjTWyeK64zMnEqtZMvatOYVhhtX9DT5hWFFmxP3aOYLEsensx6VDmOxqWGnF
+CDzWE5miRuRLsTFcrNCSkMKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgBpXNAHH/Fsf8W81X/tl/6OSvSy7/eofP8AJnLiv4T/AK6nZV5p1BQAUAJQAEZF
+AETW6t2p3FYiawU9qvnYrDP7NX0FPnCwo05R2FLnCxIlmq9qlybHYmWML2qbjHUALQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv/bL/
+ANHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uf8AJPNV/wC2X/o5K9LL
+v96h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/ABc/5J5qv/bL/wBHJXpZd/vUPn+T
+OXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uf8k81X/tl/6OSvSy7/AHqHz/JnLiv4T/rq
+dhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAcf8XP8Aknmq/wDbL/0clell3+9Q+f5M5cV/Cf8AXU7CvNOo
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoA4/wCLn/JPNV/7Zf8Ao5K9LLv96h8/yZy4r+E/66nYV5p1BQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFAHH/Fz/knmq/8AbL/0clell3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgDj/i5/yTzVf+2X/o5K9LLv96h8/wAmcuK/hP8ArqdhXmnUFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAc
+f8XP+Sear/2y/wDRyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/ACTz
+Vf8Atl/6OSvSy7/eofP8mcuK/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/wAXP+Sear/2y/8A
+RyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/JPNV/7Zf+jkr0su/wB6
+h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/Fz/AJJ5qv8A2y/9HJXpZd/vUPn+TOXF
+fwn/AF1OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP8Ai5/yTzVf+2X/AKOSvSy7/eofP8mcuK/hP+up
+2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv/AGy/9HJXpZd/vUPn+TOXFfwn/XU7CvNOoKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoA4/4uf8k81X/tl/6OSvSy7/eofP8AJnLiv4T/AK6nYV5p1BQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFAHH/Fz/knmq/9sv8A0clell3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgDj/i5/wAk81X/ALZf+jkr0su/3qHz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8A
+Fz/knmq/9sv/AEclell3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/i5/yTzVf+
+2X/o5K9LLv8AeofP8mcuK/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/wCSear/ANsv/RyV
+6WXf71D5/kzlxX8J/wBdTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/AIuf8k81X/tl/wCjkr0su/3q
+Hz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8XP+Sear/wBsv/RyV6WXf71D5/kzlxX8
+J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/JPNV/7Zf+jkr0su/3qHz/ACZy4r+E/wCup2Fe
+adQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv/bL/ANHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoA4/4uf8AJPNV/wC2X/o5K9LLv96h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFAHH/ABc/5J5qv/bL/wBHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oA4/4uf8k81X/tl/6OSvSy7/AHqHz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8XP8A
+knmq/wDbL/0clell3+9Q+f5M5cV/Cf8AXU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/wCLn/JPNV/7
+Zf8Ao5K9LLv96h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/Fz/knmq/8AbL/0clel
+l3+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/i5/yTzVf+2X/o5K9LLv96h8/wAm
+cuK/hP8ArqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8XP+Sear/2y/wDRyV6WXf71D5/kzlxX8J/1
+1OwrzTqCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKAOP+Ln/ACTzVf8Atl/6OSvSy7/eofP8mcuK/hP+up2FeadQ
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQBx/wAXP+Sear/2y/8ARyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKAOP+Ln/JPNV/7Zf+jkr0su/wB6h8/yZy4r+E/66nYV5p1BQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFAHH/Fz/AJJ5qv8A2y/9HJXpZd/vUPn+TOXFfwn/AF1OwrzTqCgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+OP8Ai5/yTzVf+2X/AKOSvSy7/eofP8mcuK/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J
+5qv/AGy/9HJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uf8k81X/tl/6O
+SvSy7/eofP8AJnLiv4T/AK6nYV5p1BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHH/Fz/knmq/9sv8A0clell3+
+9Q+f5M5cV/Cf9dTsK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDj/i5/wAk81X/ALZf+jkr0su/3qHz/JnL
+iv4T/rqdhXmnUFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcf8AFz/knmq/9sv/AEclell3+9Q+f5M5cV/Cf9dT
+sK806goAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgDj/i5/yTzVf+2X/o5K9LLv8AeofP8mcuK/hP+up2FeadQUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQBx/xc/wCSear/ANsv/RyV6WXf71D5/kzlxX8J/wBdTsK806goAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgDj/AIuf8k81X/tl/wCjkr0su/3qHz/JnLiv4T/rqdhXmnUFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAcf8XP+Sear/wBsv/RyV6WXf71D5/kzlxX8J/11OwrzTqCgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOP+
+Ln/JPNV/7Zf+jkr0su/3qHz/ACZy4r+E/wCup2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBx/xc/5J5qv
+/bL/ANHJXpZd/vUPn+TOXFfwn/XU7CvNOoKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA4/4uc/D3Vf+2X/o1K9L
+Lv8AeofP8mcuJ/hP+up2FeadQUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQByHxZ5+H+q/8AbL/0alejl3+9Q+f5
+M5sT/Cf9dTr6846QoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDkvitz4B1T/tl/6NSvRy//AHmPz/JnNif4T/rq
+dbXnHSFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAcn8VBnwFqn/AGy/9GpXoZf/ALzH5/kzmxH8J/11OsrzzpCg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKAOU+KXPgTU/+2X/o1K9DAf7zH5/kzmxH8J/11OrrzzpCgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKAOV+J4z4G1L/tl/6NSu/Af7xH5/kznxH8JnVVwHQFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAcv8A
+E0Z8Eal/2y/9GpXfgP8AeI/P8mc+I/hs6iuA6AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDmPiUM+CdR/7Z/8A
+oxa7sD/vEfn+TOfEfw2dPXCdAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBzPxIGfBeo/8AbP8A9GLXdgv94j8/
+yZhX/hs6auE3CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAOa+Ioz4N1D/tn/wCjFrtwX8ePz/JmFf8Ahs6WuI3C
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKAOc+IYz4P1D/tn/AOjFrtwX8ePz/JmFf+Gzo64jcKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoA534gDPhG/wD+2f8A6MWu3B/x4/P8jCv/AA2dFXEbhQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAHPePh
+nwlff9s//Ri12YP+PH5/kYVv4bOhrjNwoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDA8djPhS+/4B/6MWuvCfxo
+/P8AIxrfAzfrkNgoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDB8cjPha9/4B/6GtdeE/jR+f5GNb4Gb1chsFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAYXjcZ8MXv/AP/AENa68L/ABo/10Ma3wM3a5DYKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAw/Ggz4ZvP+Af+hrXVhf4y/roZVfgZuVymoUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQBi+MRnw5d/wDAP/Q1
+rpw38Vf10MqvwM2q5jUKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAxvF/8AyLt3/wAA/wDQ1rpw38Vf10MqvwM2
+a5jUKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAyPFgz4fuv+Af+hiunD/xV/XQyq/AzXrmNQoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgDJ8Vc6Ddf8B/9DFdGH/iIzqfCzWrnNAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgDK8TjOh3P/Af/QhX
+Rh/4iM6nws1a5zQKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAy/Eozolz/wH/0IVvQ/iIzqfCzUrA0CgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKAM3xEM6Pcf8B/8AQhW9H+IiJ/CaVYFhQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAGd4g50if8A
+4D/6EK2o/GiJ/CaNYlhQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQ
+AUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAB
+QAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAGfrozpU/wDwH/0IVtR+NET+E0KxLCgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKAKOtjOmTf8B/9CFa0vjRE/hL1ZFhQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAFLWBnTpfw/m
+K1pfGiJ7F2siwoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgCnqwzp8v4fzFaU/iRMti5WZQUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQBV1MZsZPw/mK0p/EiZbFqsygoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgCtqIzZyfh/MVcPiJlsWagoKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAr3wzav8Ah/Orh8RMtixUFBQAUAFABQAUAFABQAUAFABQAUAFABQAUAFA
+BQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAEF4M27/h/Oqj
+uJ7E9SMKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAiuRmBvw/nVR3EyWpGFABQAUAFABQAUAFABQAUAFABQAUAF
+ABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUA
+FABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUARz8xGm
+txMkpDCgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKAGScoaaEx9IYUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAU
+AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQA
+UAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAjcigBaACgAoAK
+ACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA
+KACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAo
+AKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgA
+oAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACg
+AoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAC
+gAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKA
+CgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgD//2Q==Agenda]]>Action Items]]>Important Dates]]>Meeting Details]]>Announcements]]>Discussion]]>Summary]]>Next Meeting]]>
diff --git a/corpus/notebook-management/cold/read/payloads.json b/corpus/notebook-management/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/notebook-management/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/notebook-management/cold/run.json b/corpus/notebook-management/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..a7cfb7953b3888a98f58d04ce3ffe59d6b344dba
--- /dev/null
+++ b/corpus/notebook-management/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/tmp/mgmt4/candidate",
+ "expected_pages": -1,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/notebook-management/cold/scripts/cold.ps1 b/corpus/notebook-management/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/notebook-management/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/notebook-management/cold/scripts/read.ps1 b/corpus/notebook-management/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/notebook-management/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/notebook-management/cold/source.json b/corpus/notebook-management/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..3f9864a1a8f8f931ed3c2a8fcdc2eff837b51972
--- /dev/null
+++ b/corpus/notebook-management/cold/source.json
@@ -0,0 +1,56 @@
+[
+ {
+ "path": "Archive/Inner.one",
+ "bytes": 6816,
+ "sha256": "4947149bfe3af5bdf0224e01a0ce95a9849ffad5cbe7d5af4771c6c644850cde",
+ "mtime_ns": 1790521518477003662
+ },
+ {
+ "path": "Archive/Kitchen.one",
+ "bytes": 9992,
+ "sha256": "ea8fea880e9f42ff4999c6d7fd1a90c0977ab2efd0501aa1e4bcee85c6279f55",
+ "mtime_ns": 1790521519374324319
+ },
+ {
+ "path": "Archive/Open Notebook.onetoc2",
+ "bytes": 4200,
+ "sha256": "5a0c4e1078e51e3fdea8660b1ecb73f76048e556d5ae21691428fd798801e5d8",
+ "mtime_ns": 1790521519426971739
+ },
+ {
+ "path": "New Section 1.one",
+ "bytes": 85232,
+ "sha256": "9e903193b2ae555d1aaeeef01b21e749204a0f6a5f9560b18e835f8bc1655097",
+ "mtime_ns": 1790521519332264376
+ },
+ {
+ "path": "OneNote_RecycleBin/Binned.one",
+ "bytes": 6816,
+ "sha256": "d2cb20d7cb2238b5525ce6c5b378323eacc265688b6d78cb32a6bdc7f8db9570",
+ "mtime_ns": 1790521519520939028
+ },
+ {
+ "path": "OneNote_RecycleBin/Gone.one",
+ "bytes": 6816,
+ "sha256": "976f0b7e524ac877d3ced0f803f50a812b5747a9edf8bccc387276f9ccbc16c0",
+ "mtime_ns": 1790521519461432928
+ },
+ {
+ "path": "OneNote_RecycleBin/OneNote_DeletedPages.one",
+ "bytes": 6888,
+ "sha256": "b005c3a26c475d717d87ec66d72eccdfa1d35c72000966fd132728bd086bb860",
+ "mtime_ns": 1790521519201361387
+ },
+ {
+ "path": "OneNote_RecycleBin/Open Notebook.onetoc2",
+ "bytes": 4592,
+ "sha256": "a4784bb35ecae53b6f6ad576c3c0687078e72ace4fba47d004d6498aadfae8b2",
+ "mtime_ns": 1790521519539400089
+ },
+ {
+ "path": "Open Notebook.onetoc2",
+ "bytes": 9392,
+ "sha256": "cbeebc6c391f65d834f819f9ed90077f36ddbcf7f7e41ff72614200a659b2fef",
+ "mtime_ns": 1790521519587646429
+ }
+]
diff --git a/corpus/notebook-management/cold/teardown.json b/corpus/notebook-management/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/notebook-management/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/notebook-management/native/meeting-template/meeting.xml b/corpus/notebook-management/native/meeting-template/meeting.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4932875680b34645c17451f81d8d99b96247276d
--- /dev/null
+++ b/corpus/notebook-management/native/meeting-template/meeting.xml
@@ -0,0 +1,12 @@
+
+Meeting Title]]>Agenda]]>Action Items]]>Important Dates]]>Meeting Details]]>Announcements]]>Discussion]]>Summary]]>Next Meeting]]>
+
diff --git a/corpus/notebook-management/native/new-notebook/created/New Section 1.one b/corpus/notebook-management/native/new-notebook/created/New Section 1.one
new file mode 100644
index 0000000000000000000000000000000000000000..869fe4f7b0c9fba22790f3fb20893cd18ad25d36
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section 1.one differ
diff --git a/corpus/notebook-management/native/new-notebook/created/New Section 2.one b/corpus/notebook-management/native/new-notebook/created/New Section 2.one
new file mode 100644
index 0000000000000000000000000000000000000000..8409d9ac2349c5239335854199604cb39b3f1b67
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section 2.one differ
diff --git a/corpus/notebook-management/native/new-notebook/created/New Section 3.one b/corpus/notebook-management/native/new-notebook/created/New Section 3.one
new file mode 100644
index 0000000000000000000000000000000000000000..a693ccabf3b07854958984699d903b377aff7096
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section 3.one differ
diff --git a/corpus/notebook-management/native/new-notebook/created/New Section Group/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/created/New Section Group/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..f240ab3a1f7a795f2827834d668ad74d5f0085e4
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/New Section Group/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/new-notebook/created/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/created/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..9e9e8ce40149c700f970e5a8f715658b906c4423
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/created/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/new-notebook/final/New Section 1.one b/corpus/notebook-management/native/new-notebook/final/New Section 1.one
new file mode 100644
index 0000000000000000000000000000000000000000..869fe4f7b0c9fba22790f3fb20893cd18ad25d36
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/New Section 1.one differ
diff --git a/corpus/notebook-management/native/new-notebook/final/New Section 2.one b/corpus/notebook-management/native/new-notebook/final/New Section 2.one
new file mode 100644
index 0000000000000000000000000000000000000000..3587519af681696c5d87f3f03f344fe822a3dd6c
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/New Section 2.one differ
diff --git a/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/New Section 3.one b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/New Section 3.one
new file mode 100644
index 0000000000000000000000000000000000000000..dab7f1460a27e217a45f02f7d09e82dc01e45b15
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/New Section 3.one differ
diff --git a/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/OneNote_DeletedPages.one
new file mode 100644
index 0000000000000000000000000000000000000000..eb2cb978197b94e1f5cbde8137c24bcdfe5668e3
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/OneNote_DeletedPages.one differ
diff --git a/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..88f4d60a185e0f22faf8c54e06f282e8a839e5a4
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/OneNote_RecycleBin/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/new-notebook/final/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/final/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..284899a7f0245d741916124775ccbb860657f992
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/final/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/Kept/New Section 3.one b/corpus/notebook-management/native/new-notebook/moved/Kept/New Section 3.one
new file mode 100644
index 0000000000000000000000000000000000000000..9e733c7f8eb1ed5361073be90bdf114f57ce095e
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/Kept/New Section 3.one differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/Kept/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/moved/Kept/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..0a81bd5f41952f8152100c0646efaea29f39aa25
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/Kept/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/New Section 1.one b/corpus/notebook-management/native/new-notebook/moved/New Section 1.one
new file mode 100644
index 0000000000000000000000000000000000000000..869fe4f7b0c9fba22790f3fb20893cd18ad25d36
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/New Section 1.one differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/New Section 2.one b/corpus/notebook-management/native/new-notebook/moved/New Section 2.one
new file mode 100644
index 0000000000000000000000000000000000000000..d1bc4afdcf9d6d7d11316d85739654eb77891df4
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/New Section 2.one differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/OneNote_DeletedPages.one b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/OneNote_DeletedPages.one
new file mode 100644
index 0000000000000000000000000000000000000000..eb2cb978197b94e1f5cbde8137c24bcdfe5668e3
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/OneNote_DeletedPages.one differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..1bd3b23b1bdf08c0c77eea881bb5f0c43c483c48
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/OneNote_RecycleBin/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/new-notebook/moved/Open Notebook.onetoc2 b/corpus/notebook-management/native/new-notebook/moved/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..284899a7f0245d741916124775ccbb860657f992
Binary files /dev/null and b/corpus/notebook-management/native/new-notebook/moved/Open Notebook.onetoc2 differ
diff --git a/corpus/notebook-management/native/page-color/Garden.one b/corpus/notebook-management/native/page-color/Garden.one
new file mode 100644
index 0000000000000000000000000000000000000000..afa9553362c03b4eb8422404aa3c831ebd3f5b70
Binary files /dev/null and b/corpus/notebook-management/native/page-color/Garden.one differ
diff --git a/corpus/notebook-management/native/page-color/colors.txt b/corpus/notebook-management/native/page-color/colors.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5bb9e648c50fd28ed757836ad70567c8796be51f
--- /dev/null
+++ b/corpus/notebook-management/native/page-color/colors.txt
@@ -0,0 +1,16 @@
+#EDF5FE
+#FFEEEF
+#FDFDDD
+#ECF9E5
+#E5EDF3
+#FBEDF6
+#FFFADF
+#ECF0E5
+#E9E9ED
+#F3E9FF
+#F9F4E7
+#E5EFEB
+#E8E3EB
+#EFDEDE
+#FBF2E1
+#D4F9F2
diff --git a/corpus/notebook-management/native/section-colors/New Section 1.one b/corpus/notebook-management/native/section-colors/New Section 1.one
new file mode 100644
index 0000000000000000000000000000000000000000..ea5d31cd300313a1a7eebf5c6c3ac21bc3798b19
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 1.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 10.one b/corpus/notebook-management/native/section-colors/New Section 10.one
new file mode 100644
index 0000000000000000000000000000000000000000..d61a0d002e5d4e107eb9d731609e9c152b371158
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 10.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 11.one b/corpus/notebook-management/native/section-colors/New Section 11.one
new file mode 100644
index 0000000000000000000000000000000000000000..b71b7513bb332dc57c04a255fb03f623234a78ed
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 11.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 12.one b/corpus/notebook-management/native/section-colors/New Section 12.one
new file mode 100644
index 0000000000000000000000000000000000000000..15df53c12a8ed7cbfafadb8849a6ac70a63af64b
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 12.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 13.one b/corpus/notebook-management/native/section-colors/New Section 13.one
new file mode 100644
index 0000000000000000000000000000000000000000..ba6fd26a09fe5c1dc9619e6a9de19ee0c51c71fe
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 13.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 14.one b/corpus/notebook-management/native/section-colors/New Section 14.one
new file mode 100644
index 0000000000000000000000000000000000000000..e421f0d23b0161f8c7d38364c7dc51899d421556
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 14.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 15.one b/corpus/notebook-management/native/section-colors/New Section 15.one
new file mode 100644
index 0000000000000000000000000000000000000000..23b9457bb1f6b32123e71eb39b363b29260e0439
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 15.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 16.one b/corpus/notebook-management/native/section-colors/New Section 16.one
new file mode 100644
index 0000000000000000000000000000000000000000..e34fc568fe8b6ae4ab0c6d3886dc2f273d4eb1d8
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 16.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 2.one b/corpus/notebook-management/native/section-colors/New Section 2.one
new file mode 100644
index 0000000000000000000000000000000000000000..606ed706060e7289435ba7174919f19c1850e73c
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 2.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 3.one b/corpus/notebook-management/native/section-colors/New Section 3.one
new file mode 100644
index 0000000000000000000000000000000000000000..ec71d360a990470ef670f1d3681322bed14e95e5
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 3.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 4.one b/corpus/notebook-management/native/section-colors/New Section 4.one
new file mode 100644
index 0000000000000000000000000000000000000000..a82da67e28b900ebe62d51814f0503eb7b78667e
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 4.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 5.one b/corpus/notebook-management/native/section-colors/New Section 5.one
new file mode 100644
index 0000000000000000000000000000000000000000..8ed83908d225f85734ec4fcafcada255f0b91333
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 5.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 6.one b/corpus/notebook-management/native/section-colors/New Section 6.one
new file mode 100644
index 0000000000000000000000000000000000000000..168e1a95f2e27efad1a0ffbbdd54c74337e10aa3
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 6.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 7.one b/corpus/notebook-management/native/section-colors/New Section 7.one
new file mode 100644
index 0000000000000000000000000000000000000000..51a48f512bb59e79193e68b078e071bce39045ec
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 7.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 8.one b/corpus/notebook-management/native/section-colors/New Section 8.one
new file mode 100644
index 0000000000000000000000000000000000000000..b6536430d73a94a9999fa7ece6187727b8b7fc10
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 8.one differ
diff --git a/corpus/notebook-management/native/section-colors/New Section 9.one b/corpus/notebook-management/native/section-colors/New Section 9.one
new file mode 100644
index 0000000000000000000000000000000000000000..58b87fb2f4314caf90a26e713ecdf887e4283979
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/New Section 9.one differ
diff --git a/corpus/notebook-management/native/section-colors/Open Notebook.onetoc2 b/corpus/notebook-management/native/section-colors/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..638cf0a165bdc1557fc5d43e0734b3ce9f01e3dc
Binary files /dev/null and b/corpus/notebook-management/native/section-colors/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/README.md b/corpus/page-lifecycle/offline-edits-series/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..223bb2c20f2efcb5fa948af996c05f5d9b9469d8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/README.md
@@ -0,0 +1,22 @@
+# Offline page batches merged as page series
+
+`../offline-edits` regenerated since page lists merge as OneNote merges page series
+(`../../conflict-page/native-pages`): a page the remote moved keeps the remote's place.
+In every native movement state OneNote gave the pages the offline batch places series of
+their own, so all eighteen keep OneNote's placement and publish the body edit alone.
+`twelve-clients` moves disjoint pages, each into a series of its own; each client's
+batch publishes whole, twelve publications, all merged.
+
+Every candidate reopened in a fresh OneNote 2010 clone without changes beyond the header,
+except two native repairs of inputs OneNote wrote: `indent-02-promoted-parent` refreshes the
+stale section metadata level that `../movement/02-promoted-parent` left (MS-ONE 2.2.81,
+note 9), and `twelve-clients` fills the seed page's absent optional metadata copy. The
+verifier accounts for both. `provenance.json` records the captures (`evidence/series`) and
+removed clones.
+
+```sh
+ONESTORE_OFFLINE_PAGE_EDIT_OUTPUT=/tmp/one-page-edits cargo test -p notebook --all-features --test sync_pages native_page_changes_reconcile_with_atomic_offline_batches -- --exact
+python tools/offline_page_edits.py /tmp/one-page-edits /tmp/one-page-edits-cold --workers 4
+ONESTORE_OFFLINE_PAGE_CLIENT_OUTPUT=/tmp/one-page-clients cargo test -p notebook --all-features --test sync_pages twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review -- --exact
+python tools/native_runner.py /tmp/one-page-clients /tmp/one-page-clients-cold --expected-pages 37 --collect-notebook
+```
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..72126bfae93f5df61d58ff5735c3288825b9786f
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..d45628bfbabca2d0ea68bcfc5da4d20c22c71bf8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 201,
+ 10,
+ 106,
+ 102,
+ 142,
+ 247,
+ 18,
+ 79,
+ 177,
+ 108,
+ 120,
+ 98,
+ 206,
+ 193,
+ 214,
+ 20
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 115,
+ 33,
+ 106,
+ 78,
+ 121,
+ 140,
+ 215,
+ 65,
+ 186,
+ 48,
+ 82,
+ 176,
+ 47,
+ 20,
+ 4,
+ 78
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 73,
+ 55,
+ 27,
+ 125,
+ 117,
+ 195,
+ 180,
+ 79,
+ 166,
+ 201,
+ 36,
+ 230,
+ 140,
+ 154,
+ 66,
+ 37
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [220, 211, 38, 107, 179, 97, 114, 74, 158, 104, 66, 109, 244, 125, 212, 30], n: 1 } })",
+ "phase": "01-demoted-parent",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [220, 211, 38, 107, 179, 97, 114, 74, 158, 104, 66, 109, 244, 125, 212, 30], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..f2cf56d820b2200bfb7658d3874ea15bff95a709
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-228507E9 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..c457190cbd8e0f9d62e1f5efb25f49ef151caf65
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-228507e9", "hostname": "ONE-M6-228507E9"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..97d3aff4ff3f838f88251df68089844e1a8747a7
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..53d7e88f6e6295e632e9c61853b87740cb0a41ee
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..c13d34785e20b80736284859f8152cf4606cc6c5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-228507E9",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1a29a6844ad637156aed12f8b4ba6171f26531f2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..858b57d24d8518ebb2120b54e9b78db065b93787
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c3a23280e16c1127d057fa54d3d650b8067b479f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..032d51926ae215ddaa9897f2abe0b1747de89f5e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec9cbb4839dc9cd9d8817db9b12211d69045c38e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a052490e8fe062827b2bea34a1113964796efb7c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..661378ce8c297500e2e812275c29d57b4e68f785
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea3f6b2e40f8fa832624da6a9796b1b4db96e588
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8f01c14273f7647c78dd08a18dbd761786c79931
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..922b0f3af9455f44b47fb7ba5ca70d82b4652131
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..cc7dd9496cc00b8cd86aac836717cf9c4af17420
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpxbgzk4zk",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..a8f3b6ee4359c4fb18b3256a3d88cea0f7a1460a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 58888,
+ "sha256": "9a3b4662022dc604139192a1ce6e89e0a86fb2f4f28d612d0b21fc39cbb0321b",
+ "mtime_ns": 1790522182582306261
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-01-demoted-parent/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..431142b312654c6e1d461efb98317156d5e56962
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..0372d7523bcc49b3ac641cff3a8cff18352ac546
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 1,
+ 158,
+ 214,
+ 127,
+ 88,
+ 144,
+ 125,
+ 70,
+ 142,
+ 160,
+ 108,
+ 163,
+ 26,
+ 254,
+ 139,
+ 224
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 246,
+ 145,
+ 67,
+ 226,
+ 173,
+ 106,
+ 84,
+ 66,
+ 166,
+ 80,
+ 187,
+ 112,
+ 214,
+ 75,
+ 197,
+ 145
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 208,
+ 245,
+ 172,
+ 222,
+ 94,
+ 188,
+ 190,
+ 76,
+ 137,
+ 17,
+ 74,
+ 122,
+ 80,
+ 23,
+ 13,
+ 147
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [73, 133, 222, 97, 87, 220, 209, 73, 167, 94, 12, 96, 167, 99, 69, 216], n: 1 } })",
+ "phase": "02-promoted-parent",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [73, 133, 222, 97, 87, 220, 209, 73, 167, 94, 12, 96, 167, 99, 69, 216], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..8d7be41c10e77e795253d0dc7ef37d87ccc10bac
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-59E6B833 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..e3329b44275f980cc4be994edf8ba1650a44140a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-59e6b833", "hostname": "ONE-M6-59E6B833"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..437694f7b53895ced50da43039ca1bbe13221932
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..535921a8f2262dd6c7f64a4cfdc7347d3785d16b
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..15e02e27889409e561dccc7134045d3b029be439
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-59E6B833",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b3b69165374f37ab320117f43adf55d6f2716f64
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..58f1d73cec228c77df1ba009dc2467a8ad04ed44
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a42f077dc6706dd0f0434422bd3ac405367f5d55
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f4b37154b12e28613809e81fdf97ddf0d21229ad
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..895a2a70ed73d1916f9efdc88f052fad64d6ee74
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6a0ae873830d6e54c81b002ea36ddebbaaebd037
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d818291f29f362527fc01b8d71f094ad336bbac5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2064b9282a977f12c810ead80dc126e12b0aeb9c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9b1a6a4973666a0b48a1e76eb427d6eee3c34026
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c4a42b9bfd207b87c4f67c50321227d8fd108f85
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..6c9319f0e654777b82a6b67ac3fd8f37192f5285
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp2tw32xod",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..f99bc48bf502212594222780fb91e0945a5b79bb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 60864,
+ "sha256": "dac0d3baff9cba15171a7a49ad5e3fe5ae4f1d9486a282f73eca7bf12a4302cf",
+ "mtime_ns": 1790522182571809194
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-02-promoted-parent/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..1587d4cc88a634e365cc77340853aabf9c33efa1
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..ee1b2e0da4c9171ba3fdcbbcf2c7091df9aa770f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 230,
+ 73,
+ 229,
+ 66,
+ 147,
+ 157,
+ 254,
+ 73,
+ 141,
+ 167,
+ 232,
+ 94,
+ 176,
+ 115,
+ 2,
+ 69
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 161,
+ 23,
+ 180,
+ 51,
+ 0,
+ 216,
+ 36,
+ 72,
+ 157,
+ 74,
+ 208,
+ 42,
+ 195,
+ 215,
+ 100,
+ 23
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 131,
+ 50,
+ 221,
+ 188,
+ 200,
+ 84,
+ 156,
+ 73,
+ 132,
+ 49,
+ 39,
+ 179,
+ 247,
+ 214,
+ 250,
+ 204
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [141, 148, 26, 99, 137, 196, 192, 74, 138, 245, 125, 174, 49, 216, 252, 21], n: 1 } })",
+ "phase": "03-selected-group-move",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [141, 148, 26, 99, 137, 196, 192, 74, 138, 245, 125, 174, 49, 216, 252, 21], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..80e422fc9196b61b1179c46d07d695167ad21cd5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-2F0CFD28 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..c9549d43bac69dfab31855178bd352ecbe775f31
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-2f0cfd28", "hostname": "ONE-M6-2F0CFD28"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..115c5eeeab32230bf7d6acd35282c20fbc8f7e6c
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..3f77ceaff7126fa4e1a1df9a79e7ef9f5652f00e
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..aec98400f3af82d1746045cfdee917871d54b62c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-2F0CFD28",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1dcee9ce61a6f025bc05980a80700f15d75bd65a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c624f125c2036f984f28614438febf6e9b370dd7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ff6487e8b772cfa44d0602163009c7a9dd67aac
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd656860b05a008df92b0a6643527617892b911b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d43f03b1eba66f2197870f98fc60f8a7bc3d8dcf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35086a6b786f970077c97fd17650662e1cf36ebb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2ff0182fc3ca1e510675080786cf707edae35387
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..407acf7d0ed2f396612a995136c9dc242426dafb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..29333ee95284b0b4384ff07b7dd10c1952ad82b8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f0060b4e811957e0bd10c4d974d8b0becaf20c4e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..b8621b526dd1682702024eb4c5658d8046059de8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqu8gvf97",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..133eb197277ea5d9bed9a5a4d119c647f369a633
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 62448,
+ "sha256": "e8227277e0b943d76ff7f1317a204bc1c90d83edb14d57c1e4fc4b6025572d5a",
+ "mtime_ns": 1790522182601367622
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-03-selected-group-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..69f04d26d12abaf31536f7de4fb00d9628af3ae2
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..11c96fa3739bceaffd24195e823e6e4b911bfff7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 78,
+ 38,
+ 62,
+ 248,
+ 116,
+ 109,
+ 88,
+ 72,
+ 144,
+ 98,
+ 203,
+ 126,
+ 141,
+ 180,
+ 205,
+ 201
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 11,
+ 136,
+ 4,
+ 10,
+ 224,
+ 67,
+ 69,
+ 67,
+ 170,
+ 135,
+ 131,
+ 23,
+ 217,
+ 9,
+ 214,
+ 1
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 42,
+ 95,
+ 98,
+ 74,
+ 100,
+ 10,
+ 90,
+ 66,
+ 190,
+ 78,
+ 156,
+ 145,
+ 230,
+ 147,
+ 236,
+ 168
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [124, 112, 85, 50, 117, 173, 10, 69, 136, 197, 175, 234, 251, 205, 20, 89], n: 1 } })",
+ "phase": "04-subpage-move",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [124, 112, 85, 50, 117, 173, 10, 69, 136, 197, 175, 234, 251, 205, 20, 89], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..426ea04c16448bade9f23017ac63fbed33e58e32
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-1F7DB150 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..8e7f3c818af58549ca65e3171afe3605bd8a2736
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-1f7db150", "hostname": "ONE-M6-1F7DB150"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..fe6ef49298fea0ae4a0e9e3764fcbe249c34cd6d
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..6cad571062f841ae6c2591834e0a84b2057dbd99
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..eeab5e3904cba8ce0b498dfef7312bf16996f814
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-1F7DB150",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b2e59a0ed49eade85c8df218ff44cbe44beb71e0
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44d60ce47a187806674b4093a138b8ef1db49b34
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f99f97578095dbb044f1a0af8468dfad6373073c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6c2fa4227fa6d1b487eb577dcc58b0d834de6b58
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bd19c898bf1050b2de7cdc579b6afee1b171f23e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3dbba2c05f8fade039b622de918c0b7d9100b64d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0e9611af66427a25f5d05480f0d6ea9b7e15c9d2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c4deb02accd80acb440a8a9af8a0101e14b8d15d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9f538388a6952f3c6b75a7c83964b05444762d62
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5310d3d905a30e533d1786fb52627608a3e039c0
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..8f75f8f639907082b39d5f10c4c98be68226a7a4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6no75z1i",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..3831a7e7b30492ebd4cbe77b57e8258502c0fc6b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 65000,
+ "sha256": "44eca1c10b54a10f3b8d08487d222d94aaac3b9a28f6b6f52ffd5d0d702aaf63",
+ "mtime_ns": 1790522182581472144
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-04-subpage-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..6c5becbe1d9eca0dc4d37947bb8ce1eedf9e7a49
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..6467cdfe02be9a206458ed70cd13b2de9a25b258
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 14,
+ 220,
+ 221,
+ 208,
+ 175,
+ 223,
+ 224,
+ 67,
+ 190,
+ 81,
+ 164,
+ 165,
+ 98,
+ 194,
+ 13,
+ 106
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 108,
+ 13,
+ 33,
+ 174,
+ 169,
+ 6,
+ 175,
+ 72,
+ 175,
+ 126,
+ 38,
+ 95,
+ 230,
+ 228,
+ 176,
+ 104
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 60,
+ 228,
+ 133,
+ 219,
+ 247,
+ 75,
+ 15,
+ 69,
+ 149,
+ 161,
+ 85,
+ 245,
+ 196,
+ 175,
+ 27,
+ 0
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [30, 166, 117, 224, 142, 251, 179, 74, 189, 198, 122, 150, 170, 50, 122, 155], n: 1 } })",
+ "phase": "05-insert-before-subpage",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [30, 166, 117, 224, 142, 251, 179, 74, 189, 198, 122, 150, 170, 50, 122, 155], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..067e27b3f30be03d273062961a4a280fe0d4209b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-4A72E5A4 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..d5bb7718c6d6c57e369b8696e24ed51b98ddefff
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-4a72e5a4", "hostname": "ONE-M6-4A72E5A4"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..7bf0ecf6fa12cf6320bd762ce301e01c19febecd
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..a18363df5cce0fcc4fa8ce380c53242e871d69ed
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..4328d79c9e31665cba40eb393b711ff3ef1e26ad
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-4A72E5A4",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..df24741812b7fadf3f8e95b2d8c27f090644d1e7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..faf3743c0934ddc4767e433e65592c6a9b081bee
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b4827900da71e06888a05e0ba1a25bcb833f09c6
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..01675b458dc319d694d8737b74bb08cd110b56c4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..69f24e0782b8b589619684491cf6da74f6d94039
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..65c0edbf10b00fac83abcbce139658380ab9415c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2fb638b608f7585f077b82fbf513857d088fbf4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d0a42e4a53a0e4224a715c560b921d684113bd80
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..20cc4b19cf5f77ea0f80e96c59d6a3d5ecefef4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a833ffcec4860293c2c429353cb976d618d552d4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..da74f669b403adca3647484ec2e3db1520278765
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpy26z3j6d",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..2b708373e12ac9e29f5a9be07748c65243226099
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 66944,
+ "sha256": "2f144e06946d6424cb548a4b51fdd58c2be2be35fb93ddb8f80808dce7ef8ed8",
+ "mtime_ns": 1790522182575647033
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-05-insert-before-subpage/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..689fec86d62375f695029bd2d6e4e86717432374
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..5741c0e4c35c5dc6c899ede5709a2d8ef7f72f25
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 191,
+ 13,
+ 164,
+ 227,
+ 82,
+ 236,
+ 26,
+ 68,
+ 190,
+ 184,
+ 125,
+ 92,
+ 176,
+ 151,
+ 92,
+ 109
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 56,
+ 89,
+ 41,
+ 215,
+ 48,
+ 19,
+ 73,
+ 75,
+ 153,
+ 165,
+ 39,
+ 124,
+ 235,
+ 93,
+ 47,
+ 90
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 175,
+ 208,
+ 247,
+ 122,
+ 131,
+ 58,
+ 148,
+ 64,
+ 189,
+ 66,
+ 158,
+ 33,
+ 255,
+ 61,
+ 102,
+ 224
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [13, 174, 2, 173, 50, 101, 29, 74, 170, 248, 125, 169, 18, 82, 231, 129], n: 1 } })",
+ "phase": "06-promoted-level-two",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [13, 174, 2, 173, 50, 101, 29, 74, 170, 248, 125, 169, 18, 82, 231, 129], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..a41f19f8dde5632abc91260a1d9413da602b79aa
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-2D9428EA -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..aa6b9bfa79fedcb3d28e3d1055ff2d4c05d1864b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-2d9428ea", "hostname": "ONE-M6-2D9428EA"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..4efbd49e287a84892027b8af86da0b55bd8252f2
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..e13f001048a6b65598288dfbe4c5dda176cc624b
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..5347a62104fa3d0d06ed9b5a3b3c5927103feb18
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-2D9428EA",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c8771f96700c7f5f22b5f86115ee2d1dfdf8a101
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..321bce3401e39a406739e159b8c3c39dec7da5b5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f84fb6bb541c28f4f1c8391695240c00f9f3a22e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..db868d00b5cb83450627bde6404eaae4c2b9532c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dd6875c098c938c4a89f7e54a8d29008ae9ec7cf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd0d6a902cfe5da28f893968263a5980b827dcab
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b19a47a0873abe679ba86d5dc2887c11f0aa4764
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9270a65e790c1e8638cfdfee82c931c87cb9c7ba
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bc1320729fdbb14b6aac1f86e5e99e06c8029679
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..195af6d10c4b8251e8645aecad80de3c36ebd3a3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..a012636809e78b528641b06f077b7926ea3edd24
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7i0tqm4j",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..7d0988aa41e18888d02fa1e4401f65c9fc50b767
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 70296,
+ "sha256": "30860c7715ac247a1f77d1d0c8c27edfcc248e719183cb7990381f5ad5230d89",
+ "mtime_ns": 1790522182588156289
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-06-promoted-level-two/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..1e513db665ef80e44ca910f46ae945196b516541
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..b4d80b5e2451e38b169636679e1ee8c1df2ff11a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 55,
+ 220,
+ 38,
+ 71,
+ 47,
+ 170,
+ 53,
+ 66,
+ 139,
+ 104,
+ 24,
+ 238,
+ 194,
+ 96,
+ 177,
+ 2
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 140,
+ 13,
+ 145,
+ 79,
+ 63,
+ 166,
+ 77,
+ 73,
+ 158,
+ 26,
+ 254,
+ 232,
+ 198,
+ 149,
+ 101,
+ 89
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 18,
+ 181,
+ 156,
+ 40,
+ 205,
+ 204,
+ 124,
+ 69,
+ 153,
+ 67,
+ 16,
+ 116,
+ 216,
+ 205,
+ 169,
+ 116
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [28, 191, 204, 103, 192, 238, 143, 72, 160, 21, 202, 184, 111, 209, 202, 133], n: 1 } })",
+ "phase": "07-promoted-root",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [28, 191, 204, 103, 192, 238, 143, 72, 160, 21, 202, 184, 111, 209, 202, 133], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..3d83743d7bf3eaaa763096b062c79aa7da098bc7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-A2C6CE60 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..f9e0355e2e8401c9ee10e51c81eb07e6db9b63c7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-a2c6ce60", "hostname": "ONE-M6-A2C6CE60"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..807c9aa65807aecf61a7b00e4db18a9bd0ecf255
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..bf722526d9d8a33e73e81e3f180d5e4fb1e9d8f1
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..5a85ccbf0449658639e1f86e48983510593fee35
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-A2C6CE60",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..880eb154cbc57ce0896cdbfb7c011e9698fc5243
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9b3db3eb84dd1feae69a8953a3e8b0e504652b5e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..073ef166cc94c0dedb7d65bf8abe3e7a422dfa9d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dabd964dc71754f2b21930d2cd5388a3c3b2cf2c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e9be811f3cfbedc4f2438bf5cc3996a0a06114e2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6326c4e89b431037a71496126f9f944c697d544d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..650940eb76e0d3c15c3f7b61afeb4c4d6e2eeff2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..61daa4e1f11077f6637519f0c8115aa15939315a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..41124192e79acb3269d17dd9b5122ebd2765d9b5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d72292dc950e2afd5d64fff840b3ac92a0ebfed5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..fd55e663833ab31b3804f71f8b32cfb5c550c6c7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfsvvpr33",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..1831786687fa6174c1e9cf6f78efece384070843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 72360,
+ "sha256": "550991e8db44ff19e287605df0548e26e03d5f4b02ea3c56b37206fd4a122974",
+ "mtime_ns": 1790522182583277710
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-07-promoted-root/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..5bf316916c183d18b4aa5107ec0a87f4fdf49b7f
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..c74c072fd5bbb81ebfb09112823296e5ad9c78ae
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 94,
+ 111,
+ 203,
+ 102,
+ 137,
+ 5,
+ 1,
+ 65,
+ 179,
+ 170,
+ 125,
+ 232,
+ 204,
+ 23,
+ 163,
+ 106
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 229,
+ 103,
+ 227,
+ 76,
+ 55,
+ 67,
+ 28,
+ 66,
+ 188,
+ 213,
+ 158,
+ 204,
+ 32,
+ 66,
+ 155,
+ 181
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 71,
+ 45,
+ 134,
+ 175,
+ 49,
+ 202,
+ 56,
+ 76,
+ 130,
+ 139,
+ 137,
+ 23,
+ 7,
+ 208,
+ 7,
+ 1
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [49, 49, 147, 226, 188, 223, 28, 78, 185, 7, 77, 190, 226, 242, 41, 152], n: 1 } })",
+ "phase": "08-collapsed-group-move",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [49, 49, 147, 226, 188, 223, 28, 78, 185, 7, 77, 190, 226, 242, 41, 152], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..57af14945e8fb227758860c660563fdbf97d5b86
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-150CFDA8 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fe8cc6e93463aa707cd26df67b3fee734765a52
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-150cfda8", "hostname": "ONE-M6-150CFDA8"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..d29d893b909f014d8060a109ba63bf0982d5763b
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..6bd7ccbb1de681b9a66a8e2a8eefe0b4425bb6f6
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..621383846820371b866e81612d88773fdfde47a9
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-150CFDA8",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6b86eb21979e2157e39eb8f36ab91f65df21ca14
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d7d23890a7623ef59aa23e852a5b04605e9cf83f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7a9f9a91079456831fae18ad06e6a9a4c07ff07f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d1e7bb650c1aac13b93736955b595152e826b59
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6b2a6384f919ee508f05065763dde63ff0561d1b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..48ae3e9224cd8a511bc32c49cdfee6c68e0fc825
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..491a4b519310b767edc73bdb7e12c967f0bb1e3b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a984c9fff8620cff291601a45d0ab01b1c2ba259
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..83972288bca3c5e30f0448fc75bf1c3d22613e21
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e622faf5845b57b7ca8b55283db8021dccc0730
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..344bfc8207eff473c53886b77733172a13d59338
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfwhuw46n",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..dca465583aeef623347b5f3b090aff8892dc545f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 73840,
+ "sha256": "b68abccdc4c7c98c65311b2924f3903540b22c7f6e0bb8153b31bbe34fdf2c05",
+ "mtime_ns": 1790522182560292804
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-08-collapsed-group-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..38bb2887e0a99b3648f71cad9663b170007c7a82
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..caf57b62e3cdea172688f7b4bcd733e7d21c2ac1
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/candidate/manifest.json
@@ -0,0 +1,87 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "group",
+ "original": [
+ {
+ "guid": [
+ 106,
+ 239,
+ 107,
+ 240,
+ 178,
+ 128,
+ 132,
+ 68,
+ 153,
+ 189,
+ 143,
+ 39,
+ 201,
+ 121,
+ 23,
+ 95
+ ],
+ "level": 1,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A3D5318-2F37-02D8-0DC9-CC0BC689209F},1"
+ },
+ {
+ "guid": [
+ 153,
+ 239,
+ 1,
+ 102,
+ 46,
+ 96,
+ 32,
+ 70,
+ 136,
+ 164,
+ 197,
+ 78,
+ 35,
+ 85,
+ 187,
+ 83
+ ],
+ "level": 2,
+ "position": {
+ "Before": null
+ },
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ },
+ {
+ "guid": [
+ 235,
+ 105,
+ 29,
+ 79,
+ 205,
+ 140,
+ 16,
+ 65,
+ 169,
+ 123,
+ 14,
+ 62,
+ 80,
+ 183,
+ 253,
+ 48
+ ],
+ "level": 3,
+ "position": {
+ "Before": null
+ },
+ "space": "{8A6DBA48-33BB-0681-2F02-2C73A811E8B8},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [110, 9, 150, 21, 87, 116, 176, 73, 135, 91, 48, 29, 75, 28, 84, 177], n: 1 } })",
+ "phase": "single-page",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [110, 9, 150, 21, 87, 116, 176, 73, 135, 91, 48, 29, 75, 28, 84, 177], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..c8ab9010abeb1131d737894eeb3fb44c8b715169
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-93A16790 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..7ddeca58dd2c7b57e11825dc0a319284a29f716d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-93a16790", "hostname": "ONE-M6-93A16790"}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..38eba53e6a5a657b4d7c0c1bb9a0ce4d50a1caf5
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..cdc2ab5593dc55a3583872109eb6c7070af6dec3
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..57a43504b4c77928e5198d82427aaad8a8704f6e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-93A16790",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44b1566221c50e6821525f93f72d60bc81136993
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3b0ec2f216a8f9b6dafadcd7f1ccecfe70156526
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6652fbe50f3749095636734b9746ce21875c814f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7603d49c667430797f145b901e97fe781127821b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8ac5e637cee0704db2a92d5ec24a120f5e2dd405
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7cd99d7cd5414a0e5e6ccb59393f5b9e7d14649d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee409bcc0cd27d3edcb508053f8dcd03e5c36afa
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8f9d5c7603940d983b8dab24891c621dc0f5ee4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9b55e22ed8ee2882b92983e7789193a45f9214dd
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d7c64626a68eecfb4c95ee16e7af8971246b22cb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/run.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..8cce9c0afa10af22b296e58c55baec431642ed41
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3_04860j",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/source.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..b6eda15f2ba61ad31cd3d765445a07fda7b6a6c3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 63080,
+ "sha256": "58f87ab34c5e56426faed56429ab10a15e3df0673851e8c9b4587cb107a13295",
+ "mtime_ns": 1790522182573126515
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/group-single-page/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..27b774b93f4e911e9b29c796b14ded69bb8968a3
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..29c027f0e4c048c77e3f1e3427ae7242d1b02710
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 0,
+ 239,
+ 121,
+ 46,
+ 116,
+ 217,
+ 98,
+ 67,
+ 148,
+ 55,
+ 113,
+ 147,
+ 21,
+ 237,
+ 19,
+ 130
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [56, 236, 133, 176, 92, 155, 147, 69, 157, 167, 5, 193, 82, 10, 39, 239], n: 1 } })",
+ "phase": "01-demoted-parent",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [56, 236, 133, 176, 92, 155, 147, 69, 157, 167, 5, 193, 82, 10, 39, 239], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..13d9803e370508d145bba3acfcd6f1098965734a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-2B44159D -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..1419dbb69e537148cbcf91335695d91227521f03
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-2b44159d", "hostname": "ONE-M6-2B44159D"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..bd8534ad4a898d49e486e64afd9582c598365214
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..eb66531356dca116be95c967e3a71eb8ced5ca27
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..ea8a016887547bd561053fd5fb7822b3dd385e8c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-2B44159D",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..884bb5dff3e757bb2ebfc17b59966a6dfb370c39
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..223b148ad261559b0ded332bc8a02e217213360c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cf67465ec21a41467a6911497a6174d66e6d0c5b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea1408fe42305ce467e90739acfb708dba8c3059
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9f3cf6b2f12b2ff448956f3822b3aad0612c8c45
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a5316232454e3de14e7dd9e1e3378c269cd98bf5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a604ef660606605f623262e2bbda9496c220a1f5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1fa01ed8490190767b503692570ed3249b3f209a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..56147df3ff8e101d7126550984c9b36fb6bcbc43
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d6a1daba41df165f72a549e68d1e70975eb231d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..b1d85b3f1cebf4cce67daba890ed0256154bc858
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmppgtomrlh",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..6234df699295ae77cdb87435f897f8a11fa1dbcf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 58888,
+ "sha256": "c19272d0b0a52889647b23a6eb10381e7d90d5d5d7ca2ad3be868aa585a8b21c",
+ "mtime_ns": 1790522182595778175
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-01-demoted-parent/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..83037b20ff2a5422b2b5edf136b86070a08170cc
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..70608549d8be3d4aed60977d9b403c549e295512
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 70,
+ 179,
+ 162,
+ 143,
+ 72,
+ 227,
+ 248,
+ 64,
+ 159,
+ 7,
+ 0,
+ 166,
+ 131,
+ 166,
+ 211,
+ 72
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [144, 208, 130, 2, 184, 145, 30, 67, 154, 106, 180, 175, 85, 128, 40, 126], n: 1 } })",
+ "phase": "02-promoted-parent",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [144, 208, 130, 2, 184, 145, 30, 67, 154, 106, 180, 175, 85, 128, 40, 126], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..601ef63aa978f183c731122bcb67efef88bf5957
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-3F9D5E9E -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..7c44e47be5abc71b9d390dbf46e7e754d1c67d0e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-3f9d5e9e", "hostname": "ONE-M6-3F9D5E9E"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..7a22fe1fea5cae151dfc4699eb40e1f716c6cb0a
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..da9e9cf3fd46d9c1b5356199c39409e04de3e62b
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..c32f092ab133cbf25d9df26b1d8f577fea24ab1f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-3F9D5E9E",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fc67ee981f1fc7a783681767c027c16011346e2e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4f3b59d45e8ade7e51b7fc198c78fecaac82aded
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d2536aed6db5af01476e31a77dcfc53ab728098f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5bc1809f3032a875b2eff2acbe983cea7eb98d39
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f600e9d6c3bfb7bfeba63b05068945a3a908204e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..34b5167cf2f30decae00735ffd5690f483737202
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9cd88f0e2070945a938c5878519dfb3efe6bc301
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1f3a0e49d37dc423dcf066a1063354b56ab25c2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b6d37a2ac2a93aa2c8ec2e420c749f10e190c7c9
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..514f4ba4c5beaa18f1c73a3f0cc1791cd0c690c0
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..c7e71c5c8614f475d76fd944f2e20828e6e63a8b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsa22lkkc",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..bf1cf882f890eb1bcad81bf39a499d2118cd27ee
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 60864,
+ "sha256": "02983cdd10e8f6ac52dfdd27ef63858d4d3351c2c78822c0f5c20794298fb0ca",
+ "mtime_ns": 1790522182572487438
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-02-promoted-parent/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..4d3c53e6a34bb1d31c1129dd25b84e011a65ced7
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..777cdbf0c63e88b48828f05408a9e0b1b20b4bce
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 206,
+ 208,
+ 7,
+ 135,
+ 27,
+ 66,
+ 90,
+ 66,
+ 171,
+ 221,
+ 251,
+ 160,
+ 36,
+ 192,
+ 100,
+ 24
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [226, 195, 144, 213, 163, 25, 255, 79, 131, 63, 105, 93, 194, 6, 124, 135], n: 1 } })",
+ "phase": "03-selected-group-move",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [226, 195, 144, 213, 163, 25, 255, 79, 131, 63, 105, 93, 194, 6, 124, 135], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..61999dc5997e36f31def71338ba1c6d81c0e9876
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-6DEF4909 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..3b72cde8c9d253751c8d3ecae94ff8e0d8ad935e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-6def4909", "hostname": "ONE-M6-6DEF4909"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..7c31334b86632d1e2e411a67419e85043105ea36
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..97a68a855cd820b192e1686c7452edcfba6b1465
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..f8d2d784b9271833d3f1ac376684a7ace2704f55
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-6DEF4909",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5e09e8cc01044f2c5b5999d3af82f640bd282236
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ab66442d740dd9c24a5bf4064cf3f912ac726f0f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a29a8e403028a0bd84dfdc9c8103f25ffd424cb4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e83854e5dde7d447ae93e9242f1da891224ed07
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca5c7e87a6540e104c9bb270fb3056ee0d44fc65
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ba392e376ae515d227f9ed62b6fb9c033829412f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0bcdd096e1147bd7109e3774fa1df4760cb370bd
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d1fafdc28a3e9bffb0eda4603b42157dfefd88d2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8e7952c17ced9dfd0b8d0c2be78cbbdb3a22a9db
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-007.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9433ea271ea67e2185b2d17d89b825576439c58b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..51c469570222c8a0d8a9e308e65fec862f4ef9b5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpb5gki0t4",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..c7262f9a9220989fa11dd8fbd6e4bf5a10fc2ff7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 62448,
+ "sha256": "62f0d051077351cfee81931153467cbf510700e94b46347a78e287801943f37c",
+ "mtime_ns": 1790522182574538544
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-03-selected-group-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..1d80bacb71ba9862f61a0b13af1347493b5d5655
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..6c9a24bada80ed825620b3cc32a9a9dc34273113
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 112,
+ 19,
+ 103,
+ 0,
+ 67,
+ 152,
+ 215,
+ 75,
+ 186,
+ 173,
+ 109,
+ 239,
+ 32,
+ 173,
+ 18,
+ 173
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [140, 1, 52, 173, 83, 155, 53, 75, 176, 124, 221, 5, 197, 47, 143, 47], n: 1 } })",
+ "phase": "04-subpage-move",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [140, 1, 52, 173, 83, 155, 53, 75, 176, 124, 221, 5, 197, 47, 143, 47], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..dcb0a33c23f893dd8fba613922160025f9f6b797
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-3CF1AD85 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..46c491524477cec3a99dfb29a236c699527483c3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-3cf1ad85", "hostname": "ONE-M6-3CF1AD85"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..25d4d179185ebbc3bee48a0bf5fdbddb77bab2a4
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..610aedc033e729db8371a9c2b0a7d37469c4e400
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..96d3617f583420e31494ab51f7782a84ec17c1a2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-3CF1AD85",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7f8345069445685fe2b1607bdca4865385906503
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..87130397ed72ddd4878037e90f0e1018d6fa7013
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee0ac0b06c18e3a9e51b023cfc7d0a750d49c0be
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b9107dce7edb3244ff790a9c24f237ae5e7d64e5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9695c4cd9b7f9e4052ec42114cec7ec6e22502f9
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a8e30e608c1e97d03fe964434fe9e89fef00d34
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2e5736fc07e325b75f2ade2f71560d7210351823
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..816056af81bec106ed6ca1a579b1889f55c0e6ab
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..60a38d166e4b9e050ed505aa5e9d858fb890ac7d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9dc35b289323796144a4f8653bd956ff83fdd30e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..eab5635be86890d2ae326f88257995790a790ff7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmplfmc8y5c",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..7663db594fff53e1cc95ace536274a251cf167d3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 65000,
+ "sha256": "e61b424191b7ddde476e498953e5fedb01566f5fdcf5ec5ad85b75dc81ae4b81",
+ "mtime_ns": 1790522182580783526
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-04-subpage-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..b2b6360bc5062df7c96bf226f306caf0b8a3fa31
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..b3484217fbef1cfc70dd3bb20e7d1229c4283432
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 4,
+ 56,
+ 164,
+ 224,
+ 230,
+ 112,
+ 75,
+ 69,
+ 132,
+ 225,
+ 72,
+ 65,
+ 90,
+ 35,
+ 245,
+ 82
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [217, 51, 175, 155, 204, 150, 117, 70, 128, 20, 45, 123, 132, 193, 234, 183], n: 1 } })",
+ "phase": "05-insert-before-subpage",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [217, 51, 175, 155, 204, 150, 117, 70, 128, 20, 45, 123, 132, 193, 234, 183], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..cfeb35ba8aab8bd68324d85c515d3b3d69c526bf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-C302208F -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..ee9e011fab2148891a4787fc6b3f4a44be8ebb7c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-c302208f", "hostname": "ONE-M6-C302208F"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..70e5bac896b69b68f12d446cb63597d87e621788
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..423f577f570bce6c3ea2e9073a224e33070b1ab7
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..ddb51fb0a7f9cd078002b9e57d7575b008a81486
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-C302208F",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..71991079f49f2c1ddafd353f13e5e8b125a19002
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..64d071860c3d1520f7e14765330b6f9d2f180ffa
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e628a80f579de1275765701fd94913d62e03a353
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f7d490717e9c7e344efb0aa64b76b4bdc23b595a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cf4fe64ebd434b161390cf59a1f1030a34a80af1
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..605d70cbb5a5abd6a4ac3f64c65a269ea072b59e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..570934618e08cb988d19f2141a0c851d402def0c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9bb13c7a601eaf2cd5de29da476359e1ea7c9377
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..90cdad99119bddd3683c30c7c020b0611db60cc0
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ad32730e6b27b544536b8a479475b7b8b07ca41
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..ca3ec51ef5025f8fb69e2e93608fb334e7fc3ebb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3bp2l4t4",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..610fe367a14ab912261e04c38cad39e7f9bf2348
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 66944,
+ "sha256": "b1f5d19ffee4ff89ab2a14066a729b5585179339be2b18227f92c0bf2b44c42e",
+ "mtime_ns": 1790522182565951458
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-05-insert-before-subpage/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..b4edff4d616f4235c59cf77726019a5da2e3d133
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..fe02d500178e58df64e1ae1c70caa782ba363cbf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 178,
+ 31,
+ 183,
+ 138,
+ 26,
+ 221,
+ 93,
+ 78,
+ 173,
+ 192,
+ 148,
+ 78,
+ 69,
+ 246,
+ 210,
+ 44
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [113, 37, 105, 136, 152, 116, 183, 79, 158, 85, 240, 239, 61, 75, 67, 196], n: 1 } })",
+ "phase": "06-promoted-level-two",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [113, 37, 105, 136, 152, 116, 183, 79, 158, 85, 240, 239, 61, 75, 67, 196], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..828e0ffc48099a11e9d203523f258545dc6e3935
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-BC497350 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..15c098bee852e17dccf82334414d8be9628320a5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-bc497350", "hostname": "ONE-M6-BC497350"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..3e6224ce30540ad4ceb32a0578aeb0f001c5634a
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..c5385581db8f6fcdf22ce6c46c9db7bf9877af09
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..42a8ef3731bff67846cd100b951bef1289994587
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-BC497350",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7795c8becf6e0ea65a3c8df80b6380e85a5c175b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..43146345a943425cfc6931b8c7e4423e9ad7aea3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bf17f047a37098ce5f4d0efd7381599df9d2438a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ab8daee0aec9a1393daa96839a707411c5dfd073
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7717be7a2d8f3c354c5fdcacaa133c136ad9449d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c792f281a18d1eb32184af0682865ac6c0f28997
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..43d6cf1d69a5f71126208d261dc3df712f6385e3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a499c003ac019e80793cb5b745471b6e049c11e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..847bd38902c23d6aed977038bb541f3d29603005
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7c06778085230bac3a32af7764cac7333339cec6
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..c827019ff6d8edea81626bfaabeca391c8ca8eb3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpjja19zue",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..7387099b51ea7ade63dc4536ab46bea7133f1417
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 70296,
+ "sha256": "8fa8fc3275cfb17da80d2f9e08baebd8c70b8489b5721460e17c771998226876",
+ "mtime_ns": 1790522182589845898
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-06-promoted-level-two/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..9e45d245a1a466237c648776c19d51af99c06c60
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..723b466d45eeb6c3eea61e63a98da62758c4495c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 73,
+ 128,
+ 226,
+ 10,
+ 127,
+ 157,
+ 145,
+ 66,
+ 185,
+ 120,
+ 232,
+ 117,
+ 193,
+ 31,
+ 151,
+ 68
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [20, 1, 234, 89, 89, 254, 82, 68, 168, 79, 107, 96, 254, 118, 67, 34], n: 1 } })",
+ "phase": "07-promoted-root",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [20, 1, 234, 89, 89, 254, 82, 68, 168, 79, 107, 96, 254, 118, 67, 34], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..d2b6fd6bfcd237078a4e35cc355f31718920c4cb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-90980D00 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..75aea416a80b9a9435bb0648d195ec398eec159e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-90980d00", "hostname": "ONE-M6-90980D00"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..ea9c659626bf01f1187ab0d3fa6a303221dd131b
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..91b10b51e1a279a68fb31613efef1795e12831d6
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..ef0dceca8124105875065f229b56297db0497fcf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-90980D00",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8ded209958e8a836904b0b56d57f9a6bdc1be87c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6c370677c832f4642634e27827eeca9ef82eecb5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7262db8713c5d9b65f39b8ed56e071aae3a8f0e8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e1083135472dcd2cfe53bd0654c8956921daab7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8eef9cd19c8d4e7f2834de65040504e5a490ae9b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..245bb2899d67d8cffd466f0284b94285f085d8ed
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0c5786d7468d46e4992029b3c54616674c44b763
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4ddff2703af96b31719c4719573178eac804c5c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9e1a8f675e640d3992eed7c2b539eca9ea381909
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b3e1d4b8235888aeb7307e938d94484c60369a68
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..0abe6d30e322c523c516eeaa4f580de375739b32
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn_4nbhkc",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..1777198c063fb1cde72dd2224b50dd5e8bf5d660
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 72360,
+ "sha256": "1ed669cc3afe6b391e13bab16f666b63900511499844b18e12a7e6f2abe89bad",
+ "mtime_ns": 1790522182573809675
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-07-promoted-root/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..323762dd8afdccf23cda30f8c317f123f350c043
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..93dbdaaec9527bd01dad042b3aa2df60bc8704ac
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 22,
+ 254,
+ 80,
+ 182,
+ 231,
+ 93,
+ 89,
+ 72,
+ 151,
+ 171,
+ 141,
+ 14,
+ 152,
+ 171,
+ 237,
+ 165
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [153, 10, 0, 185, 105, 82, 19, 78, 149, 135, 202, 5, 72, 113, 230, 157], n: 1 } })",
+ "phase": "08-collapsed-group-move",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [153, 10, 0, 185, 105, 82, 19, 78, 149, 135, 202, 5, 72, 113, 230, 157], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..43e8da07c5d43b11a2449c00dc2f6e4b8109f1e1
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-FADEB6C0 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..35bba73a78f5a44a7d33e4741e96eccfbdd4617b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-fadeb6c0", "hostname": "ONE-M6-FADEB6C0"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..80a9059986d243feb9eca115d3802a5d9b0529b2
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..c7dc4940476d8120f4a41dae2f6ab4f75ba21756
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..0035c5e5d41aaba579b520391868a391ba9f9966
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-FADEB6C0",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe9f720c325910530179de77762c4eb4b80b68a7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c4e667a8f4fb3e90eea4cdeaad4b6267375b923f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0363cf4430845b13a5baf37b702e2fee74a13d71
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4bfbe28495f9c5af9562a15040dddadca7b525e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2566e17ffa1776b619b45ae779bd5e3e35c3fae5
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..70b2dbcfe6690848d9989255938c9946cfce074b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..40d75de72b23cc587a6188c58f89730ea5174c23
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee7e58e6a41127040df2b7813e6a3a7b223b15a8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dd9af6c2137444328464db933ed7d81c685ea2a4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..576a361e162ab5fc40d1cd34f378fda7601c316b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..3830017edfccf911ed254efe4aa41ad837227834
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3g6qdqvi",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..5d57260487bfcbe5e554461bf05992ac6d81bab7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 73840,
+ "sha256": "18ac2501a9fd0d09d043b23d41f6d3a04a47c3866f9fd8114c2a76c773d71fcd",
+ "mtime_ns": 1790522182570877495
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-08-collapsed-group-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..9860520ee087972770fe42b27551ca7a128394f1
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..299b2015277e4f6bbe0f4f4da3a350edde854411
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/candidate/manifest.json
@@ -0,0 +1,35 @@
+{
+ "confirmations": 0,
+ "conflict": true,
+ "mode": "indent",
+ "original": [
+ {
+ "guid": [
+ 5,
+ 235,
+ 87,
+ 66,
+ 187,
+ 139,
+ 97,
+ 68,
+ 186,
+ 227,
+ 174,
+ 187,
+ 142,
+ 150,
+ 54,
+ 216
+ ],
+ "level": 3,
+ "position": "Keep",
+ "space": "{D7B1788B-A971-08DE-3324-F4DF82A3B46E},1"
+ }
+ ],
+ "page_receipt": "Some(Published { revision: ExGuid { guid: [141, 54, 145, 86, 191, 101, 228, 72, 142, 5, 46, 211, 83, 3, 119, 106], n: 1 } })",
+ "phase": "single-page",
+ "publications": 1,
+ "reviewed": [],
+ "text_receipt": "Some(Published { revision: ExGuid { guid: [141, 54, 145, 86, 191, 101, 228, 72, 142, 5, 46, 211, 83, 3, 119, 106], n: 1 } })"
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..b53324c443f6bcf3dc31f50d7d2d3904717fe8d1
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-B0D47B05 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..34b10cecc361b61b539da1e1665c090911118d84
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-b0d47b05", "hostname": "ONE-M6-B0D47B05"}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..027e07817f57d91b1b9f13824b71b837727e0d64
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..80e19ce98b03933b881e8921d97228358a1f7881
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..1a0dc4867908a574efb3981983aa855d51df7973
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-B0D47B05",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a17f17c8b9bd67be3a4454e5cc48a4518dc38e89
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3ba28c1c51c2ece5c192a9d5fdfa83795d6484fb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Offline Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..105863c907f43c5e417b0b9da5bc7ff368cc1264
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d3eebd12fe777bcb6e38b24673066aee40b21f4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cd48f98a22e0b2ced75c099865258b0e6e6d909b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6f897cd30900a1c2f76f0b697aa9c00504772fa1
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4db0ff889d334dca5d81a5394bf245f101dd3098
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d618e189642e21894d27750d3266e526d1308994
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..836beb5e9e1865d869b970a4c337a67acdea1929
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6451ddb5ec49cac502e9b1c20e65f9ee4668e95a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/run.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..e8cd958fea863b97d0ceaee427ce3aa71f076e6d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7q_s9zzh",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/source.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..765d902708f46c9a7f9ff3f67be3585dd6037caf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 63080,
+ "sha256": "81f1eecbaee6e55e8a6c3af4eb875fe943ab387e7b1e0c6ea76a32d7ed01d5b8",
+ "mtime_ns": 1790522182589020156
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/indent-single-page/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/offline-edits-series/provenance.json b/corpus/page-lifecycle/offline-edits-series/provenance.json
new file mode 100644
index 0000000000000000000000000000000000000000..50ef6a11bad6ace2b431976c4a232b893a49a005
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/provenance.json
@@ -0,0 +1,674 @@
+{
+ "generator": [
+ "crates/notebook/tests/sync_pages.rs::native_page_changes_reconcile_with_atomic_offline_batches",
+ "crates/notebook/tests/sync_pages.rs::twelve_disjoint_page_batches_merge_with_dependent_bodies_without_review"
+ ],
+ "evidence": "evidence/series",
+ "cold": {
+ "group-01-demoted-parent": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpxbgzk4zk",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-228507e9",
+ "hostname": "ONE-M6-228507E9"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 58888,
+ "sha256": "9a3b4662022dc604139192a1ce6e89e0a86fb2f4f28d612d0b21fc39cbb0321b",
+ "mtime_ns": 1790522182582306261
+ }
+ ]
+ },
+ "group-02-promoted-parent": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp2tw32xod",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-59e6b833",
+ "hostname": "ONE-M6-59E6B833"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 60864,
+ "sha256": "dac0d3baff9cba15171a7a49ad5e3fe5ae4f1d9486a282f73eca7bf12a4302cf",
+ "mtime_ns": 1790522182571809194
+ }
+ ]
+ },
+ "group-03-selected-group-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqu8gvf97",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-2f0cfd28",
+ "hostname": "ONE-M6-2F0CFD28"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 62448,
+ "sha256": "e8227277e0b943d76ff7f1317a204bc1c90d83edb14d57c1e4fc4b6025572d5a",
+ "mtime_ns": 1790522182601367622
+ }
+ ]
+ },
+ "group-04-subpage-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6no75z1i",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-1f7db150",
+ "hostname": "ONE-M6-1F7DB150"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 65000,
+ "sha256": "44eca1c10b54a10f3b8d08487d222d94aaac3b9a28f6b6f52ffd5d0d702aaf63",
+ "mtime_ns": 1790522182581472144
+ }
+ ]
+ },
+ "group-05-insert-before-subpage": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpy26z3j6d",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-4a72e5a4",
+ "hostname": "ONE-M6-4A72E5A4"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 66944,
+ "sha256": "2f144e06946d6424cb548a4b51fdd58c2be2be35fb93ddb8f80808dce7ef8ed8",
+ "mtime_ns": 1790522182575647033
+ }
+ ]
+ },
+ "group-06-promoted-level-two": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7i0tqm4j",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-2d9428ea",
+ "hostname": "ONE-M6-2D9428EA"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 70296,
+ "sha256": "30860c7715ac247a1f77d1d0c8c27edfcc248e719183cb7990381f5ad5230d89",
+ "mtime_ns": 1790522182588156289
+ }
+ ]
+ },
+ "group-07-promoted-root": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfsvvpr33",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-a2c6ce60",
+ "hostname": "ONE-M6-A2C6CE60"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 72360,
+ "sha256": "550991e8db44ff19e287605df0548e26e03d5f4b02ea3c56b37206fd4a122974",
+ "mtime_ns": 1790522182583277710
+ }
+ ]
+ },
+ "group-08-collapsed-group-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpfwhuw46n",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-150cfda8",
+ "hostname": "ONE-M6-150CFDA8"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 73840,
+ "sha256": "b68abccdc4c7c98c65311b2924f3903540b22c7f6e0bb8153b31bbe34fdf2c05",
+ "mtime_ns": 1790522182560292804
+ }
+ ]
+ },
+ "group-single-page": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3_04860j",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-93a16790",
+ "hostname": "ONE-M6-93A16790"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 63080,
+ "sha256": "58f87ab34c5e56426faed56429ab10a15e3df0673851e8c9b4587cb107a13295",
+ "mtime_ns": 1790522182573126515
+ }
+ ]
+ },
+ "indent-01-demoted-parent": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmppgtomrlh",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-2b44159d",
+ "hostname": "ONE-M6-2B44159D"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 58888,
+ "sha256": "c19272d0b0a52889647b23a6eb10381e7d90d5d5d7ca2ad3be868aa585a8b21c",
+ "mtime_ns": 1790522182595778175
+ }
+ ]
+ },
+ "indent-02-promoted-parent": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsa22lkkc",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-3f9d5e9e",
+ "hostname": "ONE-M6-3F9D5E9E"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 60864,
+ "sha256": "02983cdd10e8f6ac52dfdd27ef63858d4d3351c2c78822c0f5c20794298fb0ca",
+ "mtime_ns": 1790522182572487438
+ }
+ ]
+ },
+ "indent-03-selected-group-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpb5gki0t4",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-6def4909",
+ "hostname": "ONE-M6-6DEF4909"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 62448,
+ "sha256": "62f0d051077351cfee81931153467cbf510700e94b46347a78e287801943f37c",
+ "mtime_ns": 1790522182574538544
+ }
+ ]
+ },
+ "indent-04-subpage-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmplfmc8y5c",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-3cf1ad85",
+ "hostname": "ONE-M6-3CF1AD85"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 65000,
+ "sha256": "e61b424191b7ddde476e498953e5fedb01566f5fdcf5ec5ad85b75dc81ae4b81",
+ "mtime_ns": 1790522182580783526
+ }
+ ]
+ },
+ "indent-05-insert-before-subpage": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3bp2l4t4",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-c302208f",
+ "hostname": "ONE-M6-C302208F"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 66944,
+ "sha256": "b1f5d19ffee4ff89ab2a14066a729b5585179339be2b18227f92c0bf2b44c42e",
+ "mtime_ns": 1790522182565951458
+ }
+ ]
+ },
+ "indent-06-promoted-level-two": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpjja19zue",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-bc497350",
+ "hostname": "ONE-M6-BC497350"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 70296,
+ "sha256": "8fa8fc3275cfb17da80d2f9e08baebd8c70b8489b5721460e17c771998226876",
+ "mtime_ns": 1790522182589845898
+ }
+ ]
+ },
+ "indent-07-promoted-root": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn_4nbhkc",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-90980d00",
+ "hostname": "ONE-M6-90980D00"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 72360,
+ "sha256": "1ed669cc3afe6b391e13bab16f666b63900511499844b18e12a7e6f2abe89bad",
+ "mtime_ns": 1790522182573809675
+ }
+ ]
+ },
+ "indent-08-collapsed-group-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3g6qdqvi",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-fadeb6c0",
+ "hostname": "ONE-M6-FADEB6C0"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 73840,
+ "sha256": "18ac2501a9fd0d09d043b23d41f6d3a04a47c3866f9fd8114c2a76c773d71fcd",
+ "mtime_ns": 1790522182570877495
+ }
+ ]
+ },
+ "indent-single-page": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp7q_s9zzh",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-b0d47b05",
+ "hostname": "ONE-M6-B0D47B05"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 63080,
+ "sha256": "81f1eecbaee6e55e8a6c3af4eb875fe943ab387e7b1e0c6ea76a32d7ed01d5b8",
+ "mtime_ns": 1790522182589020156
+ }
+ ]
+ },
+ "twelve-clients": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqs9m09lz",
+ "expected_pages": 37,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-d9f15303",
+ "hostname": "ONE-M6-D9F15303"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "pages.one",
+ "bytes": 159240,
+ "sha256": "dba31b100d591e034dd53a5eaca768b2d104c6c7e005c1ab9d3fee9a9791bcfd",
+ "mtime_ns": 1790522182609793250
+ }
+ ]
+ }
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/manifest.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..006be63b4d70d92ba3fa55b246fe693d1e8ab5a8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/manifest.json
@@ -0,0 +1,2304 @@
+{
+ "expected_order": [
+ [
+ "{7F455609-2BEF-4BCB-A94A-0FEECE61F2D1},1",
+ 1
+ ],
+ [
+ "{B9E9B75B-7B33-4C60-A3D1-0BE78F314485},1",
+ 1
+ ],
+ [
+ "{C4B5EAED-3ABF-4B34-A1B5-06C8A6E2259F},1",
+ 1
+ ],
+ [
+ "{1C26F613-1AD8-417F-837C-6A2EB606D092},1",
+ 2
+ ],
+ [
+ "{F31C990F-D1E1-4840-BB4F-46ED372732A9},1",
+ 1
+ ],
+ [
+ "{021A914B-C467-4FDE-BF44-B4D695410F0B},1",
+ 1
+ ],
+ [
+ "{B0559E07-BA1D-4B20-B7AA-906C04AA5DFE},1",
+ 2
+ ],
+ [
+ "{544121FD-0E61-4A76-8191-A02ABA23A314},1",
+ 1
+ ],
+ [
+ "{4A597354-6867-49AB-B740-4C1E39E40E2E},1",
+ 1
+ ],
+ [
+ "{7F7E3DAF-B98B-4BBD-9EB2-4534A3C74123},1",
+ 2
+ ],
+ [
+ "{303BACE6-CEFC-4107-AC1E-D6F3BBC7D1AE},1",
+ 1
+ ],
+ [
+ "{8D4454DE-21E6-49FB-9438-B48408E348E4},1",
+ 1
+ ],
+ [
+ "{214F33C4-3F0A-4CEF-9BC9-F8D69687830E},1",
+ 2
+ ],
+ [
+ "{CE4D4557-358A-4401-8426-C7C794F5F2BE},1",
+ 1
+ ],
+ [
+ "{64E10720-B6D7-46D7-B810-BA636020102D},1",
+ 1
+ ],
+ [
+ "{FF359729-6EDF-4577-A968-7774CD55FB52},1",
+ 2
+ ],
+ [
+ "{3E3C7041-7C7E-4104-8755-CE045D331F8F},1",
+ 1
+ ],
+ [
+ "{3DDB5E8B-3245-43D0-B001-93E5BC5C8374},1",
+ 1
+ ],
+ [
+ "{7B267536-B0AE-4744-B0E4-C5628174834D},1",
+ 2
+ ],
+ [
+ "{1F097AAE-D72E-4A7A-8359-6DCE136F0E21},1",
+ 1
+ ],
+ [
+ "{BC956E6C-D057-409D-A618-A6BF06DD9AFC},1",
+ 1
+ ],
+ [
+ "{39C7177D-715E-417F-A5B2-596DCDE13027},1",
+ 2
+ ],
+ [
+ "{2C70EAEB-A51D-448F-8955-89156506CF95},1",
+ 1
+ ],
+ [
+ "{F924B8C7-66CA-4FEA-ADD7-5ECD6910D5AA},1",
+ 1
+ ],
+ [
+ "{95B02C61-106C-47DC-AC71-563A6AE3F6BE},1",
+ 2
+ ],
+ [
+ "{907D9244-8140-4F4C-8BA9-6E42C8F2F5CC},1",
+ 1
+ ],
+ [
+ "{232109B4-E38E-4D7A-AB6B-2C52BCD49511},1",
+ 1
+ ],
+ [
+ "{1A4EE170-3A3E-4E9E-9CDC-8DD17C510B26},1",
+ 2
+ ],
+ [
+ "{8679521F-8046-4611-A5A3-AB151635E26D},1",
+ 1
+ ],
+ [
+ "{CF289176-0CDB-4163-8A44-C51958D8B8A1},1",
+ 1
+ ],
+ [
+ "{99334A81-D662-4AC6-A49D-A0860B4E0DD8},1",
+ 2
+ ],
+ [
+ "{7BAB3EDA-868E-4B41-AD61-B32D463AB3E0},1",
+ 1
+ ],
+ [
+ "{BDFF266F-D35B-4408-B624-B3C5DE9DECED},1",
+ 1
+ ],
+ [
+ "{458A27E7-608E-467D-87C0-540AA0AF5AB6},1",
+ 2
+ ],
+ [
+ "{9F7A4423-B568-4CA7-BE9D-8003FAF044AD},1",
+ 1
+ ],
+ [
+ "{2EDB6F23-646D-4B69-A92A-14293B52E874},1",
+ 1
+ ],
+ [
+ "{E455C07B-77AB-4D41-91AE-3CAD15027F85},1",
+ 2
+ ]
+ ],
+ "operations": [
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 137,
+ 65,
+ 46,
+ 153,
+ 28,
+ 23,
+ 191,
+ 78,
+ 179,
+ 39,
+ 162,
+ 124,
+ 151,
+ 204,
+ 247,
+ 54
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{C4B5EAED-3ABF-4B34-A1B5-06C8A6E2259F},1"
+ },
+ "space": "{B9E9B75B-7B33-4C60-A3D1-0BE78F314485},1"
+ },
+ {
+ "guid": [
+ 214,
+ 18,
+ 186,
+ 71,
+ 69,
+ 135,
+ 163,
+ 67,
+ 162,
+ 241,
+ 219,
+ 185,
+ 146,
+ 144,
+ 160,
+ 212
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{1C26F613-1AD8-417F-837C-6A2EB606D092},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951600000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},2",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},1",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 0 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},3",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{B9E9B75B-7B33-4C60-A3D1-0BE78F314485},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 232,
+ 190,
+ 205,
+ 38,
+ 113,
+ 7,
+ 97,
+ 70,
+ 142,
+ 69,
+ 28,
+ 16,
+ 219,
+ 74,
+ 94,
+ 170
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{021A914B-C467-4FDE-BF44-B4D695410F0B},1"
+ },
+ "space": "{F31C990F-D1E1-4840-BB4F-46ED372732A9},1"
+ },
+ {
+ "guid": [
+ 240,
+ 152,
+ 226,
+ 6,
+ 125,
+ 5,
+ 59,
+ 78,
+ 159,
+ 199,
+ 217,
+ 224,
+ 167,
+ 207,
+ 69,
+ 206
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{B0559E07-BA1D-4B20-B7AA-906C04AA5DFE},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951600000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},5",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},4",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 1 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},6",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{F31C990F-D1E1-4840-BB4F-46ED372732A9},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 128,
+ 150,
+ 44,
+ 239,
+ 75,
+ 40,
+ 93,
+ 71,
+ 139,
+ 44,
+ 144,
+ 149,
+ 3,
+ 225,
+ 194,
+ 105
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{4A597354-6867-49AB-B740-4C1E39E40E2E},1"
+ },
+ "space": "{544121FD-0E61-4A76-8191-A02ABA23A314},1"
+ },
+ {
+ "guid": [
+ 77,
+ 215,
+ 146,
+ 157,
+ 207,
+ 140,
+ 1,
+ 70,
+ 160,
+ 237,
+ 173,
+ 17,
+ 181,
+ 152,
+ 129,
+ 117
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{7F7E3DAF-B98B-4BBD-9EB2-4534A3C74123},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951610000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},8",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},7",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 2 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},9",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{544121FD-0E61-4A76-8191-A02ABA23A314},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 60,
+ 24,
+ 102,
+ 131,
+ 237,
+ 125,
+ 96,
+ 68,
+ 140,
+ 15,
+ 56,
+ 134,
+ 76,
+ 94,
+ 75,
+ 241
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{8D4454DE-21E6-49FB-9438-B48408E348E4},1"
+ },
+ "space": "{303BACE6-CEFC-4107-AC1E-D6F3BBC7D1AE},1"
+ },
+ {
+ "guid": [
+ 43,
+ 187,
+ 225,
+ 181,
+ 143,
+ 57,
+ 100,
+ 71,
+ 156,
+ 65,
+ 221,
+ 123,
+ 106,
+ 144,
+ 24,
+ 42
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{214F33C4-3F0A-4CEF-9BC9-F8D69687830E},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951610000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},11",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},10",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 3 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},12",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{303BACE6-CEFC-4107-AC1E-D6F3BBC7D1AE},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 237,
+ 166,
+ 115,
+ 62,
+ 6,
+ 126,
+ 122,
+ 71,
+ 165,
+ 0,
+ 132,
+ 211,
+ 66,
+ 36,
+ 104,
+ 34
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{64E10720-B6D7-46D7-B810-BA636020102D},1"
+ },
+ "space": "{CE4D4557-358A-4401-8426-C7C794F5F2BE},1"
+ },
+ {
+ "guid": [
+ 20,
+ 190,
+ 251,
+ 94,
+ 101,
+ 42,
+ 0,
+ 68,
+ 150,
+ 161,
+ 251,
+ 52,
+ 113,
+ 3,
+ 175,
+ 41
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{FF359729-6EDF-4577-A968-7774CD55FB52},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951610000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},14",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},13",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 4 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},15",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{CE4D4557-358A-4401-8426-C7C794F5F2BE},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 148,
+ 253,
+ 150,
+ 142,
+ 238,
+ 167,
+ 15,
+ 78,
+ 187,
+ 244,
+ 152,
+ 219,
+ 101,
+ 253,
+ 64,
+ 204
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{3DDB5E8B-3245-43D0-B001-93E5BC5C8374},1"
+ },
+ "space": "{3E3C7041-7C7E-4104-8755-CE045D331F8F},1"
+ },
+ {
+ "guid": [
+ 121,
+ 181,
+ 255,
+ 117,
+ 85,
+ 146,
+ 190,
+ 70,
+ 147,
+ 88,
+ 216,
+ 245,
+ 1,
+ 13,
+ 103,
+ 107
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{7B267536-B0AE-4744-B0E4-C5628174834D},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951610000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},17",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},16",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 5 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},18",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{3E3C7041-7C7E-4104-8755-CE045D331F8F},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 156,
+ 157,
+ 179,
+ 162,
+ 123,
+ 147,
+ 117,
+ 70,
+ 181,
+ 60,
+ 138,
+ 82,
+ 124,
+ 75,
+ 38,
+ 187
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{BC956E6C-D057-409D-A618-A6BF06DD9AFC},1"
+ },
+ "space": "{1F097AAE-D72E-4A7A-8359-6DCE136F0E21},1"
+ },
+ {
+ "guid": [
+ 3,
+ 209,
+ 128,
+ 197,
+ 70,
+ 248,
+ 104,
+ 70,
+ 162,
+ 92,
+ 200,
+ 5,
+ 82,
+ 16,
+ 182,
+ 46
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{39C7177D-715E-417F-A5B2-596DCDE13027},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951610000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},20",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},19",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 6 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},21",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{1F097AAE-D72E-4A7A-8359-6DCE136F0E21},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 207,
+ 242,
+ 85,
+ 164,
+ 205,
+ 114,
+ 120,
+ 73,
+ 145,
+ 29,
+ 194,
+ 242,
+ 8,
+ 34,
+ 144,
+ 124
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{F924B8C7-66CA-4FEA-ADD7-5ECD6910D5AA},1"
+ },
+ "space": "{2C70EAEB-A51D-448F-8955-89156506CF95},1"
+ },
+ {
+ "guid": [
+ 38,
+ 126,
+ 122,
+ 127,
+ 151,
+ 38,
+ 229,
+ 76,
+ 135,
+ 62,
+ 181,
+ 209,
+ 254,
+ 240,
+ 31,
+ 157
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{95B02C61-106C-47DC-AC71-563A6AE3F6BE},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951610000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},23",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},22",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 7 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},24",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{2C70EAEB-A51D-448F-8955-89156506CF95},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 215,
+ 122,
+ 231,
+ 63,
+ 33,
+ 23,
+ 153,
+ 71,
+ 146,
+ 55,
+ 135,
+ 108,
+ 108,
+ 25,
+ 220,
+ 189
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{232109B4-E38E-4D7A-AB6B-2C52BCD49511},1"
+ },
+ "space": "{907D9244-8140-4F4C-8BA9-6E42C8F2F5CC},1"
+ },
+ {
+ "guid": [
+ 147,
+ 175,
+ 210,
+ 70,
+ 177,
+ 159,
+ 86,
+ 67,
+ 169,
+ 228,
+ 21,
+ 200,
+ 173,
+ 16,
+ 23,
+ 190
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{1A4EE170-3A3E-4E9E-9CDC-8DD17C510B26},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951620000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},26",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},25",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 8 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},27",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{907D9244-8140-4F4C-8BA9-6E42C8F2F5CC},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 114,
+ 248,
+ 161,
+ 39,
+ 180,
+ 234,
+ 235,
+ 74,
+ 172,
+ 83,
+ 92,
+ 166,
+ 243,
+ 74,
+ 0,
+ 10
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{CF289176-0CDB-4163-8A44-C51958D8B8A1},1"
+ },
+ "space": "{8679521F-8046-4611-A5A3-AB151635E26D},1"
+ },
+ {
+ "guid": [
+ 161,
+ 154,
+ 81,
+ 212,
+ 11,
+ 138,
+ 231,
+ 74,
+ 178,
+ 141,
+ 20,
+ 210,
+ 107,
+ 144,
+ 145,
+ 81
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{99334A81-D662-4AC6-A49D-A0860B4E0DD8},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951620000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},29",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},28",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 16,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 9 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},30",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{8679521F-8046-4611-A5A3-AB151635E26D},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 141,
+ 40,
+ 59,
+ 48,
+ 97,
+ 31,
+ 212,
+ 65,
+ 153,
+ 12,
+ 89,
+ 90,
+ 90,
+ 202,
+ 68,
+ 159
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{BDFF266F-D35B-4408-B624-B3C5DE9DECED},1"
+ },
+ "space": "{7BAB3EDA-868E-4B41-AD61-B32D463AB3E0},1"
+ },
+ {
+ "guid": [
+ 71,
+ 27,
+ 109,
+ 113,
+ 163,
+ 222,
+ 41,
+ 74,
+ 134,
+ 176,
+ 81,
+ 84,
+ 203,
+ 181,
+ 219,
+ 203
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{458A27E7-608E-467D-87C0-540AA0AF5AB6},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951620000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},32",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},31",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 17,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 10 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},33",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{7BAB3EDA-868E-4B41-AD61-B32D463AB3E0},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ],
+ [
+ {
+ "edit": {
+ "at": 133000000000000000,
+ "ops": [
+ {
+ "Section": {
+ "Pages": [
+ {
+ "guid": [
+ 141,
+ 240,
+ 28,
+ 163,
+ 72,
+ 70,
+ 7,
+ 72,
+ 187,
+ 241,
+ 188,
+ 124,
+ 179,
+ 164,
+ 65,
+ 183
+ ],
+ "level": 1,
+ "position": {
+ "Before": "{2EDB6F23-646D-4B69-A92A-14293B52E874},1"
+ },
+ "space": "{9F7A4423-B568-4CA7-BE9D-8003FAF044AD},1"
+ },
+ {
+ "guid": [
+ 134,
+ 79,
+ 134,
+ 224,
+ 23,
+ 71,
+ 222,
+ 68,
+ 132,
+ 196,
+ 140,
+ 39,
+ 58,
+ 135,
+ 58,
+ 234
+ ],
+ "level": 2,
+ "position": "Keep",
+ "space": "{E455C07B-77AB-4D41-91AE-3CAD15027F85},1"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "id": 1
+ },
+ {
+ "edit": {
+ "at": 134349951620000000,
+ "ops": [
+ {
+ "Page": {
+ "op": {
+ "Add": {
+ "before": null,
+ "object": {
+ "Outline": {
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},35",
+ "indents": [],
+ "layout": {
+ "max_height": null,
+ "max_width": null,
+ "reserved_width": null,
+ "width_set_by_user": null,
+ "x": 36.0,
+ "y": 36.0
+ },
+ "min_width": null,
+ "paragraphs": [
+ {
+ "collapsed": false,
+ "content": {
+ "Text": {
+ "date_field": null,
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},34",
+ "tags": [],
+ "text": {
+ "spans": [
+ {
+ "end": 17,
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": "Calibri",
+ "font_size": 11.0,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": 1033,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ }
+ }
+ ],
+ "text": "Actor 11 🦀 é"
+ }
+ }
+ },
+ "format": {
+ "alignment": null,
+ "bold": null,
+ "color": null,
+ "embedded_object": null,
+ "font": null,
+ "font_size": null,
+ "hidden": null,
+ "highlight": null,
+ "hyperlink": null,
+ "hyperlink_label": null,
+ "italic": null,
+ "language": null,
+ "line_spacing": null,
+ "list_spacing": null,
+ "math": null,
+ "math_object": null,
+ "rtl": null,
+ "space_after": null,
+ "space_before": null,
+ "strike": null,
+ "subscript": null,
+ "superscript": null,
+ "underline": null
+ },
+ "id": "{2A900876-A601-4591-B865-1DD52FFFDBE3},36",
+ "level": 1,
+ "lists": [],
+ "media": {
+ "recordings": [],
+ "time_ms": null
+ },
+ "parent": null,
+ "style": null,
+ "tags": []
+ }
+ ],
+ "title": false,
+ "unsupported": []
+ }
+ }
+ }
+ },
+ "space": "{9F7A4423-B568-4CA7-BE9D-8003FAF044AD},1"
+ }
+ }
+ ]
+ },
+ "id": 2
+ }
+ ]
+ ],
+ "pages": 37,
+ "publications": 12
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/pages.one b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/pages.one
new file mode 100644
index 0000000000000000000000000000000000000000..a07687258692a91cc8859b73e0451eb576e26fa3
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/twelve-clients/candidate/pages.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/commands.jsonl b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..02b59bcbcb66de5148ea66c4be94497e0fccd757
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-D9F15303 -ExpectedPages 37", "exit": 0, "stdout": "Read 1 sections and 37 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/machine.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..aea0658156ef2f41c4f06c96d842519a48035b28
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-d9f15303", "hostname": "ONE-M6-D9F15303"}
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..a97d8ec4557e250e16ecaec059688cebb3eb6826
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/pages.one b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/pages.one
new file mode 100644
index 0000000000000000000000000000000000000000..35734e5e858bc1119b182e977c32cc01f39e8262
Binary files /dev/null and b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/notebook/pages.one differ
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/environment.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..c54f03df5a38e25576176b34741a9eefea13cc9e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-D9F15303",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/hierarchy.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c1aa135b7c8263e1548d955afd6d1e2350cc1dea
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-000.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9728db3b902284b2bbf8294d27a8cdb4ee334a3d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-001.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d5aba6035a311dd12f0eff0af8b6b8f4df3c87b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-002.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ddb165926d17e008176ca57ba8deade0eababab8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-003.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dad7cae105ed24535759e0c6b93f030aba8823ed
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-004.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8404a1947cd1573644028528327a6ec0d18d489a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-005.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..594f89a36912ee18d9afee260f7cdb9968604c14
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-006.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c79c9b7fb5302e95caf3db8637f1d248a6000d66
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-007.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..81c6beec493dd338a48ad4091044b239ee2150f2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-007.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-008.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..64bec87fa2e8b8bf47b8eea002beb866bda491d0
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-009.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-009.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44b9036f45f840e10c39dc1f3f2ea7e2229a8aed
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-009.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-010.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-010.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b434321a62020c4ec6a2cbf95bb912c8a8a084b2
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-010.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-011.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-011.xml
new file mode 100644
index 0000000000000000000000000000000000000000..116dc6f41446aa830747a67a3366bb5088feb76d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-011.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-012.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-012.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8daadce17f8c369cc9285fb9af3e2fb4513caf9b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-012.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-013.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-013.xml
new file mode 100644
index 0000000000000000000000000000000000000000..14730456f24f6a35f9d4c2af510f6dd4f8d4f9cb
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-013.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-014.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-014.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f9745fef6c629d585c9bff07889e44f3e525cae7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-014.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-015.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-015.xml
new file mode 100644
index 0000000000000000000000000000000000000000..843125cebe4a565f6a7cfb13f0b397c29e45f2ae
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-015.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-016.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-016.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a9a225cef68a128ecc556fb5fe93dc48c7d54f02
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-016.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-017.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-017.xml
new file mode 100644
index 0000000000000000000000000000000000000000..554eabda19f7a561eb20762b134c7fd56ff54f39
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-017.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-018.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-018.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d2f023a51172c9234930edfb709ea3180eb391d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-018.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-019.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-019.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ce512da5fbe6c02e2c55746e70c3a07792b8050d
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-019.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-020.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-020.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9863fedb7d2d66dd0b660d1a66aa4885c9847471
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-020.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-021.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-021.xml
new file mode 100644
index 0000000000000000000000000000000000000000..348177c0bfbe5fd7361a678251ad7c59a5b02e2c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-021.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-022.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-022.xml
new file mode 100644
index 0000000000000000000000000000000000000000..180dec41de7f2df76a70d546f60a145973fc1ae1
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-022.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-023.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-023.xml
new file mode 100644
index 0000000000000000000000000000000000000000..909a3517147689a89b71f40937a657b5b42818d8
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-023.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-024.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-024.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2deb0ec5e7287198981ef9d06fdd422ebe9db91e
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-024.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-025.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-025.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d954632900e313640c4134f27777f742116468bf
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-025.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-026.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-026.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e2b2406bcd6493361666be0a542743508b05b56a
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-026.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-027.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-027.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0c0a166d0b02ace36c765aeed192932e84274537
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-027.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-028.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-028.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eb56ae3b6fa399326e25db7d6f0d89e17dec1c1c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-028.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-029.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-029.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2adcb4ba1b3f24c862991f3d1f3de0646e8a91a4
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-029.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-030.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-030.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f74cca2fc4c7a27c2eae9a5b2e3d654720e4ee3
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-030.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-031.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-031.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4f588a17b941a05eb10ca60db6e211dda7705ab7
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-031.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-032.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-032.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9421a43e81b9b46ea59c6698ea97c6d344a9311c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-032.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-033.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-033.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3f8296db5ff2d251715f449a9ec8ad677419c4a6
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-033.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-034.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-034.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3a659a3ee6da1aeeafdc430423e584ded0acbbbe
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-034.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-035.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-035.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f6e892435b4818c0887be4319a432a69c88a9669
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-035.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-036.xml b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-036.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bc9f7a8459f15fffcda7f6f42e9da22248b4e166
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/page-036.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/payloads.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/run.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..d8c3884b0335e33acbbadcdd0a65236751e497f6
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpqs9m09lz",
+ "expected_pages": 37,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/cold.ps1 b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/read.ps1 b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/source.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..e1004464b3b866e34c9bb2bdfc6c7783c71fa48c
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "pages.one",
+ "bytes": 159240,
+ "sha256": "dba31b100d591e034dd53a5eaca768b2d104c6c7e005c1ab9d3fee9a9791bcfd",
+ "mtime_ns": 1790522182609793250
+ }
+]
diff --git a/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/teardown.json b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/offline-edits-series/twelve-clients/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..54ba8a6290af552de506cb822f37cfeb2d7d1fa1
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..2dec7c4d07e35807302e338afef5ca75f957c2ed
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-161C24F1 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/machine.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..9583a6399f786e7b306579ab51e9d2be4ac963a4
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-161c24f1", "hostname": "ONE-M6-161C24F1"}
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..dd3adcb4f551b4776b55ff22756a63f6392eb148
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..a855452db2626b491b6feb1d205424e9bd140755
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..6db32dd36fda0b0dcd96f17440f23079eb8ca2b9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-161C24F1",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..22a818b828b4e8abda8458ff58433f1483d37ef6
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5686641379a99dc2e8144275022c249879cad8b0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..23484b43650c63b553f7427dec462318bf8a41b8
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe4c723bf5aaf8c9ee667bde404a96a695e93396
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e642f2c912a19a0322b1bfb418e42d6b03f16c07
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d80e102d9bb9c45bfd03a92ebde503d7fe8ba969
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..624d266d03482767b76444fa82f4d7113a3ba183
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..75f5996b23fbf5191a3de9a565f89ef896a54e58
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6da652f1205ac1a27138e7fc821d9b344b7bbda1
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d18c0a0cad935285f6076ebc7c170f266d2cfa23
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/run.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..3b07b74848a9114a75212459fccb8ae4d7785931
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn80ah_uu",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/source.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..9bab0d0182cda202b65ba15347055ca20a2838c1
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 58424,
+ "sha256": "e7065e4e043857c74bb8fa2ce6291c87378e3dc2224fad2fefe25e0396f645c4",
+ "mtime_ns": 1790522182627846620
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/03-selected-group-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/04-subpage-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..837c947f6ef2a46a44cbfe40272d0f20ff2ddeec
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/04-subpage-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..efe16cb85428c7c6a359443d437086719c5d97ee
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-24B26E2E -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/machine.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..6fb2a4d03ee5e86792162d28d5fcc845c8955d4b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-24b26e2e", "hostname": "ONE-M6-24B26E2E"}
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..d4f5dc7f31f75c852ba1ba9d08fe625a783e7642
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..b9aae4580851528248c007b1e54ed303f43621fb
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..8827e90e09bb9e80a60b9b936e4f9809f3a57bf2
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-24B26E2E",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d7eccff8143f3c603590038a615e2215700472fc
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec831c81a9a53fa0cfd58b5dc84016e493c9ff15
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..69597a914d3506d880b1d777ad0656d4e251173a
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d464237b73e1c2c4c66e63f82161d1f0a317b84f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..40e7d9b96a119dedde23d1330c5ca7d5bc08a977
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..609b6b45f77a6df6a9e2ea6f77046e4be8650820
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..16d1782363372443f82c1de631474c4ed61ab884
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a12694197949fae823d3030d32c90a05cce4dc9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0b24e00b0e829cbad9f0d0c4f708ff865bbb44f7
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-007.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..27115ed9b6c5f39ed294a8be02f96f9dd43a1df4
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/run.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..f8b69c3de736a586827f4c1d59c9f1931cd86543
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6we9ek5d",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/source.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..6232fb01897f23543f9a2ae8e6640329232fe429
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 60208,
+ "sha256": "1b91cd7a7b6d225d52155246d1913a5c94b96b3f834a9f75529af349cc598983",
+ "mtime_ns": 1790522182669188978
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/04-subpage-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..60324e05a077b20372090f4e51ce6798a086cca7
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..a6e14c258355f69ef1e9c817f44efa51eb869043
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-88FBA3A0 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/machine.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..b49f4cd9d52041c26b92dc76dd452a1059d4fb12
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-88fba3a0", "hostname": "ONE-M6-88FBA3A0"}
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..af4524373a05e6423894c3fac1b92c575535d5da
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..0f6f5f76653c5b4ffc77bc28cb7cdf2c6493233a
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..0f67aee843ea2efdf639ae24c4d83effa5764489
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-88FBA3A0",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a28f308af31c527f14d9c02de4063202c4009c9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e0505d826034374f2bcfebfd0555f20ac003ead3
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c61896d4a5b681e1854cd5f5316c0e950b54ee60
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8fbf7cc17652281521b071048f8e0dfaa9280c98
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b1de2a0ef039e91841c3f2035f2e1bbcb9261f7d
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..07da5fe2caac138351acf1aca2a5b6f97f68077f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a648feea3cc9d7b5f16213d59ba370effeb33261
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e2e8d021eeb5d3edb70c85eadf73f58f0c894f22
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3764c976a846847a36835a4a6cc740fcbbbc76e4
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-007.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9cb21221b6b95ffe316aa0c190328799dbb4d800
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/run.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..d3d52ef58e2829c430d1fea245403275d71aad00
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbkgvgbin",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/source.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..be80f82db4a89ea31253dfcbd65a41d20a0662fc
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 61944,
+ "sha256": "28d85faa977ed919a90b237e93ee7aec55a4d988fafa1994dd5fbfa2e5d038a3",
+ "mtime_ns": 1790522182622519129
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/05-insert-before-subpage/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..83f0dc5b48b730cc6238dea64b50f9545e02b248
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..9bd0480a051c39dc7d6788149c0f398d3d1b0cee
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-4CCC9DAE -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/machine.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..a91f11a466576e66ca88b1b846ed9eb26612d36f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-4ccc9dae", "hostname": "ONE-M6-4CCC9DAE"}
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..9f895785005c1199309fd44fef250abd4e310fbf
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..0efcd41819e8cbd4e6d5b93802941d4a2843e682
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..a46d5f6214d7ca4ca19392b498b4f2f45e55400e
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-4CCC9DAE",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..45b8311e0ae35657b193817306ffb457aa1f89d0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6387932e9b2557d9b942f5f8d42985e35ee9ede5
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..61f5f1908dfbb69d17fa20f693a793eabea205cf
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..aaa46fd0102e5ed3f7bb9e7f22b726f4f0fbf64f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f48bb3be6853ef0d7cfd5c0c359cf20e6f89ff4e
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..209c2495f44c051b3321dc268858c77d9767e1c9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..71b1783e7669bdff3b3651e73a762ef1effe72b3
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f69b2102248a85d4a521dc7b04c24d676a47f4d
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8dcdda7130c17d177890d97d3ed274184954c335
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ce67a4efc2c16546817f24cf0e6fa78797d23e89
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/run.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..26c570223ead39d1bdfff0f65093570429523616
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsvr31me6",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/source.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..340874609e470c5b2ce0ffca2b911e788f86fe1d
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 62696,
+ "sha256": "90732ec43728d3485a4ff5da2bb2960201961361ef084e8d97b93965875baa0d",
+ "mtime_ns": 1790522182647666599
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/06-promoted-level-two/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/07-promoted-root/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..957c361021c8a283d3be75168e737f59b0ff9f87
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/07-promoted-root/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..ee749b9055a7fe15a12326c4f73c873e031efc5e
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-AF60A95D -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/machine.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..66a0996903a512e15a33004f46c15c5e1b9fe114
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-af60a95d", "hostname": "ONE-M6-AF60A95D"}
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..f141c21e4e92ff53aaa53d51a3a308c396861003
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..996f9ae9b63bc2f62d3ed3abf7d78b71ca26d8e2
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..cf48a92d1a1137787922b699951aee2d52d6ea0d
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-AF60A95D",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f4f3581285bb967cf222f34296faa28690870e41
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..001f2a50a2492a78addfa8c8b9a16847b719934d
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cbe45bb7adc6b68492da8c30741b856c1311b7fc
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a3d3243f44caa5a989364fedba148ba61a423c0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cfcc8e338fd95a4e5efeb9bddbac3fbc9fd71d4c
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..38181c0da71e262777021b4a7de30d0a3478f56a
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4c5bf22811f36c29e5aabea3661a8874710b6bd1
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7c41a0f0e378d5556f3a80471d7c4d0b86901166
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f014a4e81b6ed9f7b61e3acf8b697003bbafb90b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d0b0bb47a6a00d4456af26336269550998fa87e0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/run.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..7b81ffee964972df2d8755c82cca16d39df649e0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpm0pgu6fk",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/source.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..ce34acb1d8ffc40ee4998b2f6f602edc4e10a58b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 64480,
+ "sha256": "eb79d7824c9c1135ef3b8aaaa111cdb1277ccf8175729a2d0637a4031742d74f",
+ "mtime_ns": 1790522182638013566
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/07-promoted-root/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..92020091770b2828bf26c2462d040849d6b2feca
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..275773a3f6ba208389772666aef406e24d410233
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-5DB5D160 -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/machine.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..23f12c2b1637172ac8ea917b0ef329b8d5f731a0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-5db5d160", "hostname": "ONE-M6-5DB5D160"}
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..2a3269838f3677db68016ca936ab6f642babc39a
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..a4344f8d1273f715d22fce77d4d245bbc8d7408e
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..4f04a100f94baf8fbd97e49e0cb8b38a5ef6d01b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-5DB5D160",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..42d9a69942412cc5f7198cf7d1ca219f2c44f82f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..91f8e020d77185a7938d137649d2a7aa076a72f0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b99efe530dd60a94f85632e91ea2086bb4d56d6f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0595b4f9c3930b38f40770404430b14e27964179
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c2f99a6bb4f4f185e0386fd129835eb44cacd058
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..05e89837882ed2d25524673de4f67160362323c9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d3d638457c2ed6f8cb39de56f9317d6c55049ee
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..94f6755437ef7c621d327b76649fa6db4d6b5a4d
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15d1818e89854f859403990286fa1488d38cb8ed
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cc468e2e228622439b00ad0e6c2f000f5cd2173e
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/run.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..6bea9926e97ec0d2d2d053b6d15a33f4b82950b9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3lrvn0ah",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/source.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..49cc642d338d9e00d9a3de42da0885a6eaff137b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 65584,
+ "sha256": "7ba31fe2131d88523503fe1ca412b74fe301d6668a8fcdc691209bf9243db10c",
+ "mtime_ns": 1790522182626875088
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/08-collapsed-group-move/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/corpus/page-lifecycle/page-edits-series/README.md b/corpus/page-lifecycle/page-edits-series/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d583620ac73d47ff86765e72d2ff699e2de4cad7
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/README.md
@@ -0,0 +1,11 @@
+# Rust page moves in series of their own
+
+`../page-edits` regenerated since a moved page heads a new page series, as OneNote's
+drag gives the dragged pages one (`../movement`); its following subpages join the series
+before it. `01` and `02` only indent and are unchanged. Each candidate reopened in a fresh
+OneNote 2010 clone with every byte after the header and every active graph unchanged;
+`provenance.json` records the captures (`evidence/series`) and removed clones.
+
+Export with `ONESTORE_PAGE_MOVEMENT_OUTPUT` on `explicit_page_edits_match_native_selection_and_indentation`
+in `crates/onestore/tests/page_movement.rs`, then capture each with `tools/native_runner.py
+INPUT OUTPUT --expected-pages 9 --collect-notebook`.
diff --git a/corpus/page-lifecycle/page-edits-series/provenance.json b/corpus/page-lifecycle/page-edits-series/provenance.json
new file mode 100644
index 0000000000000000000000000000000000000000..55de19db688cd6dd78d590cbb08c21203cf8e787
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/provenance.json
@@ -0,0 +1,253 @@
+{
+ "generator": [
+ "crates/onestore/tests/page_movement.rs::explicit_page_edits_match_native_selection_and_indentation"
+ ],
+ "evidence": "evidence/series",
+ "cold": {
+ "03-selected-group-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpn80ah_uu",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-161c24f1",
+ "hostname": "ONE-M6-161C24F1"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 58424,
+ "sha256": "e7065e4e043857c74bb8fa2ce6291c87378e3dc2224fad2fefe25e0396f645c4",
+ "mtime_ns": 1790522182627846620
+ }
+ ]
+ },
+ "04-subpage-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp6we9ek5d",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-24b26e2e",
+ "hostname": "ONE-M6-24B26E2E"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 60208,
+ "sha256": "1b91cd7a7b6d225d52155246d1913a5c94b96b3f834a9f75529af349cc598983",
+ "mtime_ns": 1790522182669188978
+ }
+ ]
+ },
+ "05-insert-before-subpage": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbkgvgbin",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-88fba3a0",
+ "hostname": "ONE-M6-88FBA3A0"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 61944,
+ "sha256": "28d85faa977ed919a90b237e93ee7aec55a4d988fafa1994dd5fbfa2e5d038a3",
+ "mtime_ns": 1790522182622519129
+ }
+ ]
+ },
+ "06-promoted-level-two": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpsvr31me6",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-4ccc9dae",
+ "hostname": "ONE-M6-4CCC9DAE"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 62696,
+ "sha256": "90732ec43728d3485a4ff5da2bb2960201961361ef084e8d97b93965875baa0d",
+ "mtime_ns": 1790522182647666599
+ }
+ ]
+ },
+ "07-promoted-root": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpm0pgu6fk",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-af60a95d",
+ "hostname": "ONE-M6-AF60A95D"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 64480,
+ "sha256": "eb79d7824c9c1135ef3b8aaaa111cdb1277ccf8175729a2d0637a4031742d74f",
+ "mtime_ns": 1790522182638013566
+ }
+ ]
+ },
+ "08-collapsed-group-move": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmp3lrvn0ah",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-5db5d160",
+ "hostname": "ONE-M6-5DB5D160"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 65584,
+ "sha256": "7ba31fe2131d88523503fe1ca412b74fe301d6668a8fcdc691209bf9243db10c",
+ "mtime_ns": 1790522182626875088
+ }
+ ]
+ },
+ "single-page": {
+ "run": {
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbiygu3ji",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+ },
+ "machine": {
+ "name": "m6-231ec95d",
+ "hostname": "ONE-M6-231EC95D"
+ },
+ "teardown": {
+ "absent": true
+ },
+ "source": [
+ {
+ "path": "Lifecycle.one",
+ "bytes": 55032,
+ "sha256": "eed7365c2054ffe32321b599ac4456d583130d3cb2e3aed41bf0baac4e27d8d2",
+ "mtime_ns": 1790522182633015571
+ }
+ ]
+ }
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/candidate/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/single-page/candidate/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..e1498b42342b06bb3cb8d92cfc45cb785b192118
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/single-page/candidate/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/commands.jsonl b/corpus/page-lifecycle/page-edits-series/single-page/cold/commands.jsonl
new file mode 100644
index 0000000000000000000000000000000000000000..744a57e574f73f5ad72e7e1620143814e0f07254
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/commands.jsonl
@@ -0,0 +1,3 @@
+{"command": "powershell -NoProfile -Command \"Expand-Archive -LiteralPath C:\\one-tests\\transfer.zip -DestinationPath C:\\one-tests\\runs\\capture\\notebook\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-M6-231EC95D -ExpectedPages 9", "exit": 0, "stdout": "Read 1 sections and 9 pages.\r\n", "stderr": "", "error": null}
+{"command": "powershell -NoProfile -Command \"Compress-Archive -Force -Path C:\\one-tests\\runs\\capture\\* -DestinationPath C:\\one-tests\\captured.zip\"", "exit": 0, "stdout": "", "stderr": "", "error": null}
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/machine.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/machine.json
new file mode 100644
index 0000000000000000000000000000000000000000..36f6b55cd29d91a9951c18307046073f52013df0
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/machine.json
@@ -0,0 +1 @@
+{"name": "m6-231ec95d", "hostname": "ONE-M6-231EC95D"}
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..a73626f63da589d306c759454573a14db8b66e5b
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..ecc0f9942014f028b3e497ac2ad1ad86ad165646
Binary files /dev/null and b/corpus/page-lifecycle/page-edits-series/single-page/cold/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/environment.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..81d12688904d4bf0ac2be7e0124283cedbe63c3e
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-231EC95D",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0ce54f65d111733335fb5a39f3bced8509b256c6
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-000.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..db4c21c92de9605679ba9e1b363c41f15d66a1c9
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-001.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c0898826d8ad249633826d0bf2c51c75bb57b402
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-002.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ce8fcc7575bc0e45e748e35d3093ef5ccbdfa00a
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-003.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4d010e983f9243d22579f4c0e25b092bdba74526
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-004.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a6ecd5ea63736042842ee723b04580958696d16c
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-005.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a35d05f727ea9a2e51c247852e3e3c7417759a8
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-006.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a21385b0be8e3662a80a859714c46e790bf63146
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-007.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..80c39a2398c4238e30e92984e03d6f1aca88b041
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-008.xml b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2bea51e9f276ad42a60a12067523b812b4abe0f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/page-008.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/read/payloads.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/run.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/run.json
new file mode 100644
index 0000000000000000000000000000000000000000..7fa6227c595802656e26d090c4dae6b469031500
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/run.json
@@ -0,0 +1,18 @@
+{
+ "notebook": "/private/var/folders/90/4f4rngds01j55ggdj_vglk_c0000gn/T/tmpbiygu3ji",
+ "expected_pages": 9,
+ "author": null,
+ "author_timeout_seconds": 600,
+ "inspect": false,
+ "collect_notebook": true,
+ "base": {
+ "file": "win7-office-base.qcow2",
+ "format": "qcow2",
+ "sha256": "a1a4f8fab782ee14885ff801ca2f6347c208fdcfc3513637096f314315c89346",
+ "virtual_size": 68719476736
+ },
+ "scripts": {
+ "cold.ps1": "c177fc72ae6c2634d186f5671a880de20b09f9716532c37c69cb13aa15c7e331",
+ "read.ps1": "04013bfcccee40a17e2a225f9b9e96f40a3a8daad9e350609654f8eda3ccbb41"
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/cold.ps1 b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/cold.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..a0b99e7aeb86f4dc10032537800501a52ad65b4f
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/cold.ps1
@@ -0,0 +1,27 @@
+param([Parameter(Mandatory=$true)][string]$Root, [string]$CloneHost = '')
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+if (Get-Process ONENOTE -ErrorAction SilentlyContinue) { throw 'Close OneNote before resetting its test cache.' }
+$key = 'HKCU:\Software\Microsoft\Office\14.0\OneNote'
+if ($CloneHost) {
+ if ($CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or [Environment]::MachineName -ne $CloneHost) {
+ throw 'The disposable clone hostname does not match this machine.'
+ }
+ New-Item "$key\Options\Paths" -Force | Out-Null
+ New-ItemProperty "$key\Options\Paths" -Name UnfiledNotesSection -PropertyType ExpandString -Value 'C:\one-tests\Loose.one' -Force | Out-Null
+} elseif ((Get-ItemProperty "$key\Options\Paths").UnfiledNotesSection -ne 'C:\one-tests\Loose.one' -or
+ -not (Test-Path 'C:\one-tests\profile-original-cache')) {
+ throw 'Park the personal OneNote profile before resetting the test cache.'
+}
+$cache = Join-Path $env:LOCALAPPDATA 'Microsoft\OneNote\14.0'
+$parked = Join-Path 'C:\one-tests\caches' ([IO.Path]::GetFileName($root))
+if (Test-Path $parked) { throw 'Choose a new run; its parked cache already exists.' }
+New-Item -ItemType Directory -Path 'C:\one-tests\caches' -Force | Out-Null
+if (Test-Path $cache) { Move-Item -LiteralPath $cache -Destination $parked }
+if (Test-Path "$key\OpenNotebooks") { Remove-Item "$key\OpenNotebooks" -Recurse }
+New-Item "$key\OpenNotebooks" | Out-Null
+New-ItemProperty "$key\OpenNotebooks" -Name '1' -PropertyType String -Value "$root\notebook" | Out-Null
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/read.ps1 b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/read.ps1
new file mode 100644
index 0000000000000000000000000000000000000000..476094ab1e0c47077988a6461db2080cf208642b
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/scripts/read.ps1
@@ -0,0 +1,142 @@
+param(
+ [Parameter(Mandatory=$true)][string]$Root,
+ [int]$ExpectedPages = -1,
+ [switch]$UseCurrentCache,
+ [switch]$Pdf,
+ [switch]$KeepOpen,
+ [string]$CloneHost = ''
+)
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+$root = [IO.Path]::GetFullPath($Root).TrimEnd('\')
+if ([IO.Path]::GetDirectoryName($root) -ne 'C:\one-tests\runs') {
+ throw 'Choose a run directly below C:\one-tests\runs.'
+}
+$notebook = Join-Path $root 'notebook'
+$output = Join-Path $root 'read'
+if (Test-Path $output) { throw 'Choose a new read destination.' }
+if ($UseCurrentCache) {
+ if ((Get-ItemProperty 'HKCU:\Software\Microsoft\Office\14.0\OneNote\Options\Paths').UnfiledNotesSection -ne 'C:\one-tests\Loose.one') {
+ throw 'Park the personal OneNote profile before reading test notebooks.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $root -CloneHost $CloneHost
+}
+New-Item -ItemType Directory -Path $output | Out-Null
+$app = New-Object -ComObject OneNote.Application
+$notebookId = ''
+$failure = $null
+try {
+ $app.OpenHierarchy($notebook, '', [ref]$notebookId, 0)
+ $process = Get-Process ONENOTE
+ @{ hostname = [Environment]::MachineName; onenote = $process.MainModule.FileVersionInfo.FileVersion;
+ powershell = $PSVersionTable.PSVersion.ToString(); schema = 'xs2010'; cold = (-not $UseCurrentCache.IsPresent) } |
+ ConvertTo-Json | Set-Content (Join-Path $output 'environment.json') -Encoding UTF8
+ $sections = @()
+ foreach ($file in @(Get-ChildItem $notebook -Recurse | Where-Object { $_.Extension -eq '.one' })) {
+ $id = ''
+ $app.OpenHierarchy($file.FullName, '', [ref]$id, 0)
+ $sections += $id
+ }
+ $deadline = [DateTime]::UtcNow.AddSeconds(300)
+ $previous = ''
+ $lastChange = ''
+ $stableSince = [DateTime]::UtcNow
+ $settled = $false
+ do {
+ $pages = @{}
+ foreach ($section in $sections) {
+ $hierarchy = ''
+ $app.GetHierarchy($section, 4, [ref]$hierarchy, 1)
+ [xml]$xml = $hierarchy
+ foreach ($node in $xml.SelectNodes('//*[@path]')) {
+ if (-not $node.GetAttribute('path').StartsWith("$notebook\", [StringComparison]::OrdinalIgnoreCase)) {
+ throw 'OneNote opened a section outside the copied notebook.'
+ }
+ }
+ foreach ($node in $xml.SelectNodes('//*[local-name()="Page"]')) {
+ $id = $node.GetAttribute('ID')
+ $content = ''
+ $app.GetPageContent($id, [ref]$content, 1, 1)
+ $pages[$id] = $content
+ }
+ }
+ $signature = [String]::Join('|', @($pages.Keys | Sort-Object | ForEach-Object { $_ + $pages[$_] }))
+ if ($signature -ne $previous) {
+ $lastChange = $previous
+ $previous = $signature
+ $stableSince = [DateTime]::UtcNow
+ }
+ if ((($ExpectedPages -ge 0 -and $pages.Count -eq $ExpectedPages) -or
+ ($ExpectedPages -lt 0 -and $pages.Count -gt 0)) -and
+ ([DateTime]::UtcNow - $stableSince).TotalSeconds -ge 2) { $settled = $true; break }
+ Start-Sleep -Milliseconds 250
+ } while ([DateTime]::UtcNow -lt $deadline)
+ if (-not $settled -or ($ExpectedPages -ge 0 -and $pages.Count -ne $ExpectedPages) -or ($ExpectedPages -lt 0 -and $pages.Count -eq 0)) {
+ [IO.File]::WriteAllText((Join-Path $output 'previous-signature.txt'), $lastChange, [Text.Encoding]::UTF8)
+ $index = 0
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('unsettled-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ $index++
+ }
+ $hierarchy = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$hierarchy, 1)
+ [IO.File]::WriteAllText((Join-Path $output 'unsettled-hierarchy.xml'), $hierarchy, [Text.Encoding]::UTF8)
+ throw "Expected $ExpectedPages stable pages; OneNote returned $($pages.Count), settled=$settled."
+ }
+ $index = 0
+ $payloads = @()
+ foreach ($id in @($pages.Keys | Sort-Object)) {
+ [IO.File]::WriteAllText((Join-Path $output ('page-{0:d3}.xml' -f $index)), $pages[$id], [Text.Encoding]::UTF8)
+ if ($Pdf) {
+ $pdfPath = Join-Path $output ('page-{0:d3}.pdf' -f $index)
+ $app.NavigateTo($id, '', $false)
+ $app.Publish($id, $pdfPath, 3, '')
+ if (-not (Test-Path $pdfPath) -or (Get-Item $pdfPath).Length -eq 0) { throw 'OneNote did not publish the page PDF.' }
+ }
+ [xml]$page = $pages[$id]
+ foreach ($file in $page.SelectNodes('//*[local-name()="InsertedFile" or local-name()="MediaFile"]')) {
+ $bytes = [IO.File]::ReadAllBytes($file.GetAttribute('pathCache'))
+ $hash = [BitConverter]::ToString([Security.Cryptography.SHA256]::Create().ComputeHash($bytes)).Replace('-', '').ToLowerInvariant()
+ [IO.File]::WriteAllBytes((Join-Path $output ($hash + '.attachment')), $bytes)
+ $payloads += @{ page = $id; object = $file.ParentNode.GetAttribute('objectID');
+ kind = $file.LocalName; name = $file.GetAttribute('preferredName');
+ sha256 = $hash; bytes = $bytes.Length }
+ }
+ $index++
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'payloads.json'), (ConvertTo-Json -InputObject $payloads -Depth 4), [Text.Encoding]::UTF8)
+ $all = ''
+ $app.GetHierarchy($notebookId, 4, [ref]$all, 1)
+ [xml]$finalTree = $all
+ $finalIds = @($finalTree.SelectNodes('//*[local-name()="Page"]') | ForEach-Object { $_.GetAttribute('ID') } | Sort-Object -Unique)
+ if ($finalIds.Count -ne $pages.Count -or @($finalIds | Where-Object { -not $pages.ContainsKey($_) }).Count -ne 0) {
+ throw 'The notebook hierarchy changed while collecting page evidence; repeat the cold read.'
+ }
+ [IO.File]::WriteAllText((Join-Path $output 'hierarchy.xml'), $all, [Text.Encoding]::UTF8)
+ Write-Output "Read $($sections.Count) sections and $($pages.Count) pages."
+} catch {
+ $failure = $_
+ [IO.File]::WriteAllText((Join-Path $output 'failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ throw
+} finally {
+ try {
+ try {
+ if ($notebookId -and $CloneHost) { $app.SyncHierarchy($notebookId) }
+ if ($notebookId -and -not $KeepOpen -and (-not $UseCurrentCache -or $CloneHost)) {
+ $app.CloseNotebook($notebookId, $false)
+ }
+ } catch {
+ if ($null -eq $failure) { throw }
+ [IO.File]::WriteAllText((Join-Path $output 'cleanup-failure.txt'), ($_ | Out-String), [Text.Encoding]::UTF8)
+ }
+ } finally {
+ [void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
+ }
+ $app = $null
+ [GC]::Collect()
+ [GC]::WaitForPendingFinalizers()
+ if (-not $UseCurrentCache -and -not $CloneHost) {
+ Get-Process ONENOTE -ErrorAction SilentlyContinue | Wait-Process -Timeout 10
+ }
+}
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/source.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/source.json
new file mode 100644
index 0000000000000000000000000000000000000000..98d198cb34329b050c99a0df79962d8b711be6a7
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/source.json
@@ -0,0 +1,8 @@
+[
+ {
+ "path": "Lifecycle.one",
+ "bytes": 55032,
+ "sha256": "eed7365c2054ffe32321b599ac4456d583130d3cb2e3aed41bf0baac4e27d8d2",
+ "mtime_ns": 1790522182633015571
+ }
+]
diff --git a/corpus/page-lifecycle/page-edits-series/single-page/cold/teardown.json b/corpus/page-lifecycle/page-edits-series/single-page/cold/teardown.json
new file mode 100644
index 0000000000000000000000000000000000000000..05a47793de40f322e745c4c4183727e3590ecf70
--- /dev/null
+++ b/corpus/page-lifecycle/page-edits-series/single-page/cold/teardown.json
@@ -0,0 +1 @@
+{"absent": true}
diff --git a/crates/notebook/README.md b/crates/notebook/README.md
index dd79930b674765da96546172bb80dfbba09d5144..e1e12b3928758918be6c3b00aa740fee0d30b9e5 100644
--- a/crates/notebook/README.md
+++ b/crates/notebook/README.md
@@ -242,12 +242,17 @@ directly from the core document model.
## Notebook structure
-`Notebook::create_section`, `create_group`, `rename`, `set_section_color`,
-`reorder` and `delete` change a notebook the way OneNote does: the table of
-contents (`Open Notebook.onetoc2`, created when a folder has none) gains,
-renames, reorders or loses entries; a section's colour lives in its own
-metadata; a deleted section moves into `OneNote_RecycleBin`, a group with its
-own TOC. Every created, renamed or moved file is placed with
+`Notebook::create`, `create_section`, `create_group`, `rename`, `move_entry`,
+`set_section_color`, `reorder` and `delete` change a notebook the way OneNote does: the
+table of contents (`Open Notebook.onetoc2`, created when a folder has none) gains,
+renames, reorders or loses entries; a new notebook holds "New Section 1", and a new
+section an empty section's file plus the page its `PageCreation` makes, in OneNote's
+new-section colour order; a section's colour lives in its own metadata; a deleted
+section moves into `OneNote_RecycleBin`, a group with its own TOC, and a deleted group's
+sections move there too before its folders go. `recycle_pages` keeps copies of pages a
+section is about to delete in `OneNote_RecycleBin/OneNote_DeletedPages.one`, with their
+identities, titles, dates and creation times, as OneNote does
+(`corpus/notebook-management`). Every created, renamed or moved file is placed with
`onestore::place_file`, which sets the header's ancestor to the parent TOC's
identity and the name CRC OneNote checks on open; a file without them is
re-identified and listed anew. They run over `Storage`: a mounted directory
diff --git a/crates/notebook/src/merge.rs b/crates/notebook/src/merge.rs
index f2f21fbb893ad8d4e23e8610011bb64d7c09838a..038402e7b264f2ebe92912cb17b499cba47b858b 100644
--- a/crates/notebook/src/merge.rs
+++ b/crates/notebook/src/merge.rs
@@ -37,6 +37,8 @@ pub(crate) struct Merged {
/// Pages whose local version the remote could not take, with who made the first edit
/// that did not replay and the objects the dropped ops named.
pub conflicts: BTreeMap)>,
+ /// Pages the base listed that the remote moved (`moved`).
+ pub moved: BTreeSet,
}
/// Replays `edits` on `new`, the remote section; `old` is the base they were made on.
@@ -54,7 +56,7 @@ pub(crate) fn rebase(
before,
after,
local: orders.0.clone(),
- unmoved: unmoved(old, new)?,
+ moved: moved(old, new)?,
orders,
created: BTreeSet::new(),
diffs: BTreeMap::new(),
@@ -62,6 +64,7 @@ pub(crate) fn rebase(
let mut merged = Merged {
rewritten: Vec::new(),
conflicts: BTreeMap::new(),
+ moved: state.moved.clone(),
};
for queued in edits {
let mut ops = Vec::new();
@@ -117,14 +120,11 @@ pub(crate) fn rebase(
}
Op::Section(section_op) => {
advance(&mut state.local, section_op);
- // The first form of the edit the remote's page list takes, or none.
- let mut kept = None;
- for form in state.forms(new, section_op)? {
- let form = Op::Section(form);
- if apply(&mut state, new, &form)? {
- kept = Some(form);
- break;
- }
+ let mut kept = state.form(new, section_op)?.map(Op::Section);
+ if let Some(form) = &kept
+ && !apply(&mut state, new, form)?
+ {
+ kept = None;
}
changed |= kept.as_ref() != Some(op);
ops.extend(kept);
@@ -179,15 +179,16 @@ fn named(op: &PageOp) -> Vec {
}
/// The edit keeping `page`, the version of page `space` the remote could not take, and
-/// applies it to `new`: a conflict page under the remote's page marking `objects` where
-/// `page` holds them, or, where the remote removed the page, the page put back as a copy
-/// where `local`, the section as the queue leaves it, has it. Content outside the page
-/// model stays on the remote's page only; `at` is now.
+/// applies it to `new`, the merged section: a conflict page under the remote's page
+/// marking `objects` where `page` holds them, or, where the remote removed the page, the
+/// page put back as a copy before the next page after it in `local`, the section as the
+/// queue leaves it, that the remote did not move (`moved`). Content outside the page model
+/// stays on the remote's page only; `at` is now.
#[allow(clippy::too_many_arguments)]
pub(crate) fn conflict_page(
new: &mut Section<'_>,
- old: &mut Section<'_>,
local: &mut Section<'_>,
+ moved: &BTreeSet,
space: ExGuid,
page: &Page,
author: &str,
@@ -217,7 +218,6 @@ pub(crate) fn conflict_page(
})]
} else {
// A copy under fresh identities, as OneNote 2010 puts a removed page back.
- let (base, unmoved) = (order(old)?, unmoved(old, new)?);
let queued = order(local)?;
let at = queued.iter().position(|(queued, _)| *queued == space);
let before = at
@@ -225,8 +225,7 @@ pub(crate) fn conflict_page(
.iter()
.map(|(next, _)| *next)
.find(|next| {
- listed.iter().any(|(listed, _)| listed == next)
- && (unmoved.contains(next) || base.iter().all(|(page, _)| page != next))
+ !moved.contains(next) && listed.iter().any(|(listed, _)| listed == next)
});
let creation = PageCreation::new(before, Some(&page.title), author)?;
let mut ops = vec![Op::Section(SectionOp::Import {
@@ -246,19 +245,20 @@ pub(crate) fn conflict_page(
Ok(edit)
}
-/// Pages the base and the remote both list that the remote left in place: in the same
-/// series at the same level, in base order among themselves. OneNote 2010 gives a page it
-/// moves a series of its own; a page moved within its series is out of base order.
-fn unmoved(old: &mut Section<'_>, new: &mut Section<'_>) -> Result> {
+/// Pages the base and the remote both list that the remote moved: into another series or
+/// level, or out of base order among the rest. OneNote 2010 and this writer give a moved
+/// page a series of its own; older builds of this writer moved a page within its series.
+fn moved(old: &mut Section<'_>, new: &mut Section<'_>) -> Result> {
let series = (old.series()?, new.series()?);
let base: BTreeMap = order(old)?
.into_iter()
.enumerate()
.map(|(at, (space, level))| (space, (at, level)))
.collect();
- let kept: Vec<(ExGuid, usize)> = order(new)?
- .into_iter()
- .filter_map(|(space, level)| {
+ let listed = order(new)?;
+ let kept: Vec<(ExGuid, usize)> = listed
+ .iter()
+ .filter_map(|&(space, level)| {
let (at, before) = base.get(&space)?;
(*before == level && series.0.get(&space) == series.1.get(&space)).then_some((space, *at))
})
@@ -281,7 +281,11 @@ fn unmoved(old: &mut Section<'_>, new: &mut Section<'_>) -> Result,
+ /// Pages the base listed that the remote moved (`moved`).
+ moved: BTreeSet,
/// Page spaces the replayed edits created.
created: BTreeSet,
/// Per page the remote changed, what it changed; `None` when it left the page alone.
@@ -403,57 +407,52 @@ impl Replay {
self.created.contains(&space) || self.orders.1.iter().any(|(page, _)| *page == space)
}
- /// Whether the remote moved or re-leveled a page the base listed.
- fn placed(&self, page: ExGuid) -> bool {
- !self.unmoved.contains(&page) && self.orders.0.iter().any(|(listed, _)| *listed == page)
- }
-
/// Where a page the queue put before `before` goes on the remote: before the first page
/// from `before` on, in the queue's order, that the remote lists where the base had it,
/// or last, as OneNote 2010 places a page series only one side changed.
fn anchor(&self, listed: &Order, page: ExGuid, before: Option) -> Option {
let from = self.local.iter().position(|(space, _)| Some(*space) == before)?;
self.local[from..].iter().map(|(space, _)| *space).find(|space| {
- *space != page && !self.placed(*space) && listed.iter().any(|(listed, _)| listed == space)
+ *space != page && !self.moved.contains(space) && listed.iter().any(|(listed, _)| listed == space)
})
}
- /// Forms of a section op to try on the remote section, in order: a page placed by
+ /// A section op as it replays on the remote section, or `None`: a page placed by
/// `anchor`, the page edits of pages the remote still has and did not move, removals of
/// pages the remote still has (a page it changed is not removed), a conflict page's
/// content as a page of its own where the remote removed its page.
- fn forms(&self, new: &mut Section<'_>, op: &SectionOp) -> Result> {
+ fn form(&self, new: &mut Section<'_>, op: &SectionOp) -> Result