diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/01-demoted-parent/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/01-demoted-parent/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..6163f4bc08e3231fc79ece13ab200008054412d1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/environment.json b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..bebdcaf8e471f317349192bc99d97e8ab058739c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-97B05910",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a70599b6f16aebc7c60581d4114c99a4720a0c4d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5987af3daa8f89d12ef9929ed461a94302021f04
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..10bc4d0959e2781383687f4afe614fa0c8c502aa
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7fece52d344fe955087cff59c52459807a0fa6d0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8fdcafdb4ea6de5cc1c35c43d5ba6051908e4a39
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f9548b2f76cdc972cbd2240e5a9d8ecd0422afcd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..08efdf434f151c7cd3191af06505c82f5ae7cdd8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f2c64d1d78c95f2020c6da29be55235b5a91f599
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..501303773ac1ae6afffbc6bb2ddda7b864dadc2e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..42bcc08851ddebbf6e0f0f965a9774c2f85a13d9
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/payloads.json
new file mode 100644
index 0000000000000000000000000000000000000000..1ce91a413d6fff4d58765187b76756f0e97ae843
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/cold/read/payloads.json
@@ -0,0 +1,3 @@
+[
+
+]
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.ahk b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..cdf84e10c9e048d42b4040fdf73be8f2ac7db2fd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.ahk
@@ -0,0 +1,2 @@
+Click(578,365)
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.json b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.json
new file mode 100644
index 0000000000000000000000000000000000000000..72c76c05cb4f31b1ae3cee4c317b84156370a286
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "Same title - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.png b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..b6f960d64e9f255b0c7c3f4d97f2bbf3d384f86a
Binary files /dev/null and b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.ahk b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..4e3170c7ca98dc0801477214b0775f53977a3e59
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.ahk
@@ -0,0 +1,2 @@
+Click(710,186,"Right")
+Sleep(500)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.json b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.json
new file mode 100644
index 0000000000000000000000000000000000000000..f43854a7a42d5bb99c0b443513bc0c0993c2716c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "",
+ "class": "Net UI Tool Window",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.png b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..c889199067ec198d91918e1abc24bbe98be9af1c
Binary files /dev/null and b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/0-menu.png differ
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.ahk b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..0a53bb546576a962bc247f13c69837d4b574a817
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{4CD54D6D-C056-4314-85A1-8E416C1D523F}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{4CD54D6D-C056-4314-85A1-8E416C1D523F}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.json b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..339ef5fc1ff99f7ba3964cc379b5ee6e891b692f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.json
@@ -0,0 +1 @@
+0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.png b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..f7990012231488c512fa7e082345a84ba64d8264
Binary files /dev/null and b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f81c14187009f2cca0065716fa7091c501c30c2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/01-demoted-parent/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..63d1c13c88e1707b5c62a91de04af76bc02c77e6
Binary files /dev/null and b/corpus/page-lifecycle/movement/01-demoted-parent/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/01-demoted-parent/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..1b454592cc89534c31e455cb9b8196a9732d0dbb
Binary files /dev/null and b/corpus/page-lifecycle/movement/01-demoted-parent/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/hierarchy.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..666ef3f21eb26789e49f4d019e0994ae747787f6
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-000.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..50af31aca7a1fb75b716512e634b2f76efdfe347
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-001.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d0b8e66205e1af45b343e50f1d556526876fa4ab
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-002.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d64e250528acc9ece08e2af6933d540a3246620
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-003.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..421e144e767dff8b334939ddbdaa72dea5009478
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-004.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..469bf743284ba50d15ac64db589b4b25ff874b6e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-005.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e04ec79e007e7d72381df856415d527344334
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-006.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..df4f17976f35079fb523a5ac22069936ba0fbe71
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-007.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5b40ebb08bba7fc768299391ddd2a2a9d9d24042
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/page-008.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a543d36d37e1a6b6c281caec72b12199c90d74e6
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/01-demoted-parent/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/01-demoted-parent/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/01-demoted-parent/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/02-promoted-parent/cold/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..6449e36f8e30499c26fcc84c05a5a48b63b0dad9
Binary files /dev/null and b/corpus/page-lifecycle/movement/02-promoted-parent/cold/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/02-promoted-parent/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/environment.json b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..922bfec1b6d1aee7564e1b1c12b5010bc33dff4f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-2AEEA4F2",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..be483a3b75fe49c2d9223d8a6bc83bda61b65aaf
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-000.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d5b431981969b020009a4aa32c59df445bc8b00
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-001.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..af1fac13f511ec2a95bba5805e73daf6dd242392
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-002.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a763285feb70ec21fc49151cc27aa1c44c6ff6bf
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-003.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..18cfdd0a328af6b99ae365138b5dffb28b5c84d1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-004.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f560f83aeedfbefac98369d8139ef28f5b52edc8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-005.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fcfcf6aed2fc800f03b201a796d49b3b1739221f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-006.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c9b0a3e514ecfd751658f255ebd26f8316d6247c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-007.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0571e6f22e3bc4de033223b1a57181adcfee672b
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-008.xml b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7b8949d44683bf2cb0321bc317c315b7c47c5896
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/payloads.json b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.ahk b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..1a0d68f669fe9ea1b1ef30d751eb009a4802b557
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.ahk
@@ -0,0 +1,2 @@
+Click(578,388)
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.json b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..37ede9e237a3e07f1e0a9ec7cd9c58918be1a2dd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.png b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..31eff09b390fd8745df683822dcffed592de31b0
Binary files /dev/null and b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.ahk b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.ahk
new file mode 120000
index 0000000000000000000000000000000000000000..8be8b85cb870048402765c937695f6931fa8f5d2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.ahk
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-menu.ahk
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.json b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.json
new file mode 120000
index 0000000000000000000000000000000000000000..fb45a099ab00782fa0d53240ce914c72c13a586a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-menu.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.png b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..7fb4f09a6fdf9c029d8058f42ec576350193b696
Binary files /dev/null and b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/0-menu.png differ
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.ahk b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..8744f0d4f73f75b0f313ed6c3d3a74605bc607de
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{314E5C08-C2A4-4256-9F71-B03A39F61663}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{314E5C08-C2A4-4256-9F71-B03A39F61663}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.json b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..37ede9e237a3e07f1e0a9ec7cd9c58918be1a2dd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.png b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fce13cef6dc8bbb2c6522db3bc949a0a382ae8a
Binary files /dev/null and b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fc16a6362f64947d8df385a7c0bbf3315c5d62f9
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/02-promoted-parent/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..2a49d865977f6406d99a5feca45d8e9cfb07a788
Binary files /dev/null and b/corpus/page-lifecycle/movement/02-promoted-parent/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/02-promoted-parent/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/hierarchy.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eb22f439fc85629d2d9a77a30e0b3f42f5753d23
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-000.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2e15c8b14a399998c02663ad422eb202dafc9d8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-001.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..335045daa72b97df0661c88ef933f438f6a7b80d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-002.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..73c009294656b2e25d57c2369b3effcffe28daeb
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-003.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b3d43e616c58c24f36ff5cb9e5b1d6c7206f3704
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-004.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3737d3468ef8bf25bf8801ba69bf6a8cad7ccf11
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-005.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15eed456c387d01d101379cfc5ddf7aa0d673be4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-006.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7104627d597d6515e563bc308ac4e17b2011a51c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-007.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d3a797896db5f67f5b4c4bb90c7444d4401f7ac7
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/page-008.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..985b05ef5f022946a34435b77f0b5ad0b8b1d616
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/02-promoted-parent/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/02-promoted-parent/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/02-promoted-parent/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/03-selected-group-move/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/03-selected-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/environment.json b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..dcdd87b4994d938751c1e161ddb94e2ec96c1bbc
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-CD0FAACB",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d35eae328aaf9691f30a656f26df603b63dfe65
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0c6ddb58c7d7905b92fe6a7fd405a25e7369fea4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2c557e87c8a9cf0c58ad07ebb3fefe3e521b43b4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..858bb4314b211644183a1400dc96af3d2dd2412e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12b086179e54e8d092cd77d388f2941822004ccc
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4d0a6149a0096b1a32c6d6144ea8ae16825af5da
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2e85ea70ce550de00bf8a2b5a841797eee52c8eb
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9da50ed33abb54777d32cff592f6a6e512ec89e6
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..55e3080d3be908a4d6076a5bc19839b2520d6aa6
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0dfab4b809d29f7a09a6e23cbbbab62877c59f21
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/payloads.json b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.ahk b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..3568a3b0db5b58db1e65e78034cd51b5bc7efcc8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.ahk
@@ -0,0 +1,5 @@
+Click(710,186)
+Send("{Shift down}")
+Click(710,230)
+Send("{Shift up}")
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.json b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.json
new file mode 100644
index 0000000000000000000000000000000000000000..0db5c357111d5ef45130f32a1118fcb57b667bda
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "grandchild - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.png b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6af84fa2d88c46b7629365df60a0c64e9d9ed90
Binary files /dev/null and b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.ahk b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..ef90c088bf18afbaac60208db8066278de9a4a37
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.ahk
@@ -0,0 +1,7 @@
+MouseMove(710,186)
+Send("{LButton down}")
+Sleep(250)
+MouseMove(710,308)
+Sleep(500)
+Send("{LButton up}")
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.json b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..37ede9e237a3e07f1e0a9ec7cd9c58918be1a2dd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.png b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..9af1bb27c10f5a6d6c14eaaf2710cb9869da1519
Binary files /dev/null and b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/1-action.png differ
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.ahk b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..7e6efc74b68f892160aa7d654120b7082cfa11aa
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{91800C75-A7A7-479D-8862-C7C4BC378FA7}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{91800C75-A7A7-479D-8862-C7C4BC378FA7}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.json b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..37ede9e237a3e07f1e0a9ec7cd9c58918be1a2dd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.png b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.png
new file mode 120000
index 0000000000000000000000000000000000000000..0f968834f186f95751b9d9784b1afb68bb9fccbd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/navigate.png
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/navigate.png
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d2c0362901559b06e8a4890b85981ca9b3ac48de
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/03-selected-group-move/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..d24bad6b5878a531136f03ddd7f3a639228ae050
Binary files /dev/null and b/corpus/page-lifecycle/movement/03-selected-group-move/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/03-selected-group-move/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/hierarchy.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..671bc1098945b0d04040ae4b8b4c112ca39dc4fe
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-000.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..31c94372b7e945a675e7099eb005a0ca57a4e0cc
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-001.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..72e3b4077892ac593ff145d760045233cdf50157
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-002.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e9946d8b42845e1dc6dfc4efdccc64741f2a4062
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-003.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6a42477c3308282046cd28351b5d682626b07420
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-004.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6a252f7d941736dd96201d680fa6069151fc4b88
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-005.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1b59f19977dc315061eeccc95613d667eee88c08
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-006.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..681f311c0ee5e70c82e0df40ba0ae3e7404b505c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-007.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f3dd52f815a6d019983ae708d1fe766ee64c2cfe
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/page-008.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..81681209ce24ee228effc116afbd5e9002c07bce
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/03-selected-group-move/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/03-selected-group-move/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/03-selected-group-move/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/04-subpage-move/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/04-subpage-move/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/environment.json b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..9ef0743043f88aa2efd7176cc76877494f5f2a30
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-554A4076",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee536c7a893d0d06ae422d4de477bac088069645
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-000.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..58048c2f24fe4391c0b4511871799a787d67589f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-001.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b5bd338d31b7f352e2868d82620367d2b90b5075
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-002.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f3e63c18ee337b53818fbcd4fa604b046f659f65
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-003.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d17fbdfa67f1533999a86317916b4c021d7e3f29
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-004.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5b73a0b1b94a696fbaebca741e2468ff72222e05
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-005.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..030864768507a799db2585945d95b83bc7e1195d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-006.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..92583df270c13f71df37ce3875a136ed9e7b8e20
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-007.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..805138adb3b500726e8a94128c136a99b9e45816
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-008.xml b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..89f9c133f20603ec24161b8492ebae0cbcaec730
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/cold/read/payloads.json b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.ahk b/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..4799d15dd6b3b417d0bf726650f77456be0521f1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.ahk
@@ -0,0 +1,7 @@
+MouseMove(710,274)
+Send("{LButton down}")
+Sleep(250)
+MouseMove(710,182)
+Sleep(500)
+Send("{LButton up}")
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.json b/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.json
new file mode 100644
index 0000000000000000000000000000000000000000..1988636a33f61c0deab23d818d5fe38db652f37b
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.json
@@ -0,0 +1,13 @@
+{
+ "exit": 0,
+ "stdout": "",
+ "stderr": "",
+ "w": 800,
+ "h": 600,
+ "error": null,
+ "win": {
+ "title": "child - Microsoft OneNote",
+ "class": "Framework::CFrame",
+ "dialog": false
+ }
+}
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.png b/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..3ed6351e8ff63f02d564ae07993503859bfcff51
Binary files /dev/null and b/corpus/page-lifecycle/movement/04-subpage-move/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.ahk b/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..3b437767c3c01454515712de7306eeb7fa5e5ea7
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{09635BCD-78E5-43FE-9942-2D72EEDDF95D}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{09635BCD-78E5-43FE-9942-2D72EEDDF95D}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.json b/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..339ef5fc1ff99f7ba3964cc379b5ee6e891b692f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.json
@@ -0,0 +1 @@
+0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.png b/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..4ab247b225fd463821eadb660fa0fc3ffb84e189
Binary files /dev/null and b/corpus/page-lifecycle/movement/04-subpage-move/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/04-subpage-move/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bfb58b551904ee975ef1089747b6e3c6cdd3efd3
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/04-subpage-move/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..4d0d0f9d44a46928680ad182d09676bcc503f6d5
Binary files /dev/null and b/corpus/page-lifecycle/movement/04-subpage-move/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/04-subpage-move/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/hierarchy.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bc178e241d17f0aed9027548ce93567df12556ea
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-000.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..23adc0ae542274a463dfebb3bd9d3d62278dd120
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-001.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8fa424991df2b306a743f3f1675c2b1aa8cd2a50
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-002.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7211143803c2893699952adf06c74a44cf29c757
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-003.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1b208a21181cef9e8ffc80153b6ba81d63da12cf
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-004.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3aebec3e565b954c8288cb074b11cfad2c17d16f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-005.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d7f89206dfc6340bac3d3ad5bc737453d338192
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-006.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..efd0ecd22e5397b3868b782b2cf231a55c6da477
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-007.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..78cf7fb6d48ccd367ce04ea384d1c3aaace24e3e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/page-008.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7a9feb7d718fe6ea63b74b8476a364c0db2c0872
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/04-subpage-move/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/04-subpage-move/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/04-subpage-move/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/environment.json b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..ef6d4e891cbd7f0025d7b19ac66b1deaac6a47f5
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-982B068D",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..90739d18990f37c7cfaf63ec10dc8709e6992eb2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-000.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2ab69594b455ab82fe7b25c25ddb556f50aec27b
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-001.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a1b3ede2f01a4b8413398651b64ba60ec4cace15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-002.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cdc04a59913f780ebef312cca83c309a447cb23b
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-003.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f8eb15059ac3e4a765b90e9d95a8ea47e571f3e9
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-004.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4226ab8965811b45c8eb522b14b11791e9589b0c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-005.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2815189d7589e1f333d3bfe8dddac0d21b258107
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-006.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..90a94d2c0f13a2a8d1d5435e2519fed801bcf7b3
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-007.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b9b6ebbbb0feec643adf4b3b6959d19e3839e6c6
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-008.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f2fbd3abc1a8a2428e538715e82b00d6ad216ec9
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/payloads.json b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.ahk b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..8504a3cfcc8733def5cbe59d7993786f1789c829
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.ahk
@@ -0,0 +1,7 @@
+MouseMove(710,186)
+Send("{LButton down}")
+Sleep(250)
+MouseMove(710,286)
+Sleep(500)
+Send("{LButton up}")
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.json b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.png b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f7ac41e87c547b16c13ce97abeb756c7604f2fb
Binary files /dev/null and b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.ahk b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..c2173c94b9faedffc235ed56aaeaa55d43ae2b57
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{0E35BE68-3DA5-48FD-A37B-EE19F4FA2C41}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{0E35BE68-3DA5-48FD-A37B-EE19F4FA2C41}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.json b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.png b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..7f7daa79e78ae0d5ddba38571bbb1272f20be813
Binary files /dev/null and b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6419f5ccecb610b2d2b4a84ed3361335c1dd9d63
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/05-insert-before-subpage/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..61a834cc12534d22b33faf33f061c39dd8832dfa
Binary files /dev/null and b/corpus/page-lifecycle/movement/05-insert-before-subpage/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/05-insert-before-subpage/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/hierarchy.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d578b0d68c3bb351d3c26c132fcf310b78c6db60
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-000.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a9b4fc56db3aeacf356c2158a0d8aa52b09ebe8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-001.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..585ccbda8ffdef03b20f39811ae4d5a79cfc6c0d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-002.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..28c60e0117e63640ff7e6246bcea223156c14936
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-003.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..881abe572ffed8e557eb1b736124500f89946440
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-004.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cf4758902f77c8912273c188e0163e215a75e85c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-005.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e65983f4948a194a21857383d324278419c88dea
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-006.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d19ca28b8e917fbddcd522da6b9c05ac2010cbf1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-007.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bdf15c04e9f805cadc524b49d7c86b19cb6c3715
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-008.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bda42fd0ead3e2600ec7e3696391099fbfead4a7
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/05-insert-before-subpage/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/05-insert-before-subpage/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/environment.json b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..d33c728f81c1958065063f4db1150052eb5c3b34
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-1DC0856B",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..80f0f69e84c2687c16fb00cb3bf3c82ba0d64d03
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-000.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c8296f01598a7941540afa7df7a50179a54abe59
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-001.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9e17a2d697b4490aa9f35d83c2b4d35dbeece39c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-002.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3401d9e86949fcf70a6f75cb044e96b24fb7deab
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-003.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..364a6ebba14e03472ad4e3bc79bfa5edd96bdf25
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-004.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6f3f3177d8e8944fc221ee0f88bf933e7282d714
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-005.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c87b7d53fc9679d7ce5a22e6dd145737b0d12e28
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-006.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9bddfbb9589a66fcc5f001628efafe04573cd20c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-007.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d77c3a50550ef65b1c639b6eabb8a93e58fa1f6f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-007.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-008.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..21e382796794d5d2765ae31a69fe1d603c2d9fce
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/payloads.json b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.ahk b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..089d722cfb4f605d81a904b1506145ad12655db8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.ahk
@@ -0,0 +1,2 @@
+Click(578,476)
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.json b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.png b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..fa9d9d3d34551a538070b585a2d0bb8e64c45b61
Binary files /dev/null and b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.ahk b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..36c73a0f2908ee0020667c6b394aad78a07f0f67
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.ahk
@@ -0,0 +1,2 @@
+Click(710,274,"Right")
+Sleep(500)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.json b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.json
new file mode 120000
index 0000000000000000000000000000000000000000..fb45a099ab00782fa0d53240ce914c72c13a586a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-menu.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.png b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..78c959e8340d8a1aaea90cbe2024faa49ffceaa6
Binary files /dev/null and b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/0-menu.png differ
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.ahk b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..070caafd193467ace7a0c5faf6fd2387514664df
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{5A2F2B1E-5560-41EF-8323-49E6567546A9}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{5A2F2B1E-5560-41EF-8323-49E6567546A9}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.json b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.png b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..3669a6577267a7028dfeb43e3a0f8e61b77a107f
Binary files /dev/null and b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9f68e53e81a0547575c703cc5a673f5fcd2fc960
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/06-promoted-level-two/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..f369d48a37b4e35b441aee9ca017316b1c15f11a
Binary files /dev/null and b/corpus/page-lifecycle/movement/06-promoted-level-two/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/06-promoted-level-two/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/hierarchy.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..96de6e02c0e91dd81a363ab9c91b92343e24b943
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-000.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..88dc2517b98585692a159399783987b0b66403e4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-001.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..efcd7a8df62a7195ceaeeca36029a46f4d4feb70
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-002.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5944d9314321bbde3ce5753d94ed520333e3fbae
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-003.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de2094df71c32598fa7d337dfdb11be07ed3fa13
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-004.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..06eade20a3e286462ae9c161bc2740f89667708b
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-005.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7ef4fcb5526ae5c398858ee9a2cf8c2ee9b54fc8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-006.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3adba5b98572f2654364f834cbf1b87acba85105
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-007.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..028ee24b26965549c4f93364345ea4bd30688d97
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-008.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dc039eabb9cf4d95cfa51cda0eb30abf208e8d85
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/06-promoted-level-two/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/06-promoted-level-two/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/06-promoted-level-two/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/07-promoted-root/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/07-promoted-root/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/environment.json b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..2d246d7f3c22f7ccc9d846c561ed25de232456ad
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-93230663",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca438ac4826f80918641a1da76989b367cb49cb4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-000.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e61367d63d344a2155fbd5a8b1de743ed5925845
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-001.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b359b57c288ca4021e3063ae14a0225a73dcd96d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-002.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8dc3c349be8fa0630a9e11d8d642daf7d4bcf2d2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-003.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e4f97918211ea021db46e8d6f1fb482fe8874250
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-004.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e2da5b653d0b3ba12503f0dec041a5aed63c5b8d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-005.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cc38e2c19d6908287c9f305a15011842c6e84544
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-006.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e3cb907121c62a30c1da62f0f230d7f2d32ea9c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-007.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..40c827a630a938c62bcd1a44621ff611144d997a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-008.xml b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e83a15acd1b6ddef115be480c77ed6755fda869f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/cold/read/payloads.json b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.ahk b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.ahk
new file mode 120000
index 0000000000000000000000000000000000000000..7768765dd8e83fbf19d4db2061672ed137a90090
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.ahk
@@ -0,0 +1 @@
+../../06-promoted-level-two/desktop/0-action.ahk
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.json b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.png b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..a7a1f9e2d2ffb5bb40cdcd210e54a400b8074ce1
Binary files /dev/null and b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.ahk b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.ahk
new file mode 120000
index 0000000000000000000000000000000000000000..87308c3f3e05ee7628b443f9f62e776e6fe3feed
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.ahk
@@ -0,0 +1 @@
+../../06-promoted-level-two/desktop/0-menu.ahk
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.json b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.json
new file mode 120000
index 0000000000000000000000000000000000000000..fb45a099ab00782fa0d53240ce914c72c13a586a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-menu.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.png b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..c53ff72bcd072dd7a81de834e969e0ed2b7ac3c7
Binary files /dev/null and b/corpus/page-lifecycle/movement/07-promoted-root/desktop/0-menu.png differ
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.ahk b/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..e06c2cbde1645b2bef8295040fe24c5385bbf74c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{90F6D9E4-5056-4A2A-B83D-26F482FE1391}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{90F6D9E4-5056-4A2A-B83D-26F482FE1391}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.json b/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.png b/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..4fd39a2088fb867369219c1d416e4b7889d01b44
Binary files /dev/null and b/corpus/page-lifecycle/movement/07-promoted-root/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/07-promoted-root/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f7a670c58c3773cb435d7b189dc3290d85d8904a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/07-promoted-root/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..13ab48fb1ceada1d93145757d936cf3949a0609f
Binary files /dev/null and b/corpus/page-lifecycle/movement/07-promoted-root/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/07-promoted-root/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/hierarchy.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..33e7311b1bee307b8263995ddacaf987260a8b76
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-000.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..55796527a67030d742f9137037b998d62f4de885
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-001.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4190d4c5d34afedb22f8cc809a9c229e8a4b88a4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-002.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eb5efd5aa30181e51a5514551995392a19416a71
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-003.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4e7efc8f7040a9f8b7e22574a3c76054f3f6f80e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-004.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c034d5762a75c617e0e2d22b2576043f99a04b87
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-005.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..70865297f8f06c2669d39435b19e4cec3f8989f2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-006.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d1ba8039fbace2c844f62f7079be21b69965313
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-007.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f8280b2d8e19d8b0a1f8aaf72ae94bb888c29627
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/page-008.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ddf01f6a393bcf1a14ad37467f7d298e0a8c75e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/07-promoted-root/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/07-promoted-root/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/07-promoted-root/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..5b2262b1a78df2dd40aeb7d8a86fec1ae3b43b15
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/environment.json b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..0490cb0e466a1586034e24854aa51b40af5ea9e1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-6F5064DB",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5817fff0785efe373a4f95565eff28e4fdd699dc
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-000.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7ce4df03aca9b6ab65d7bf98335f5599f6088008
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-001.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..83b1de5120baa56a0ba1ac4feb7801105feaee0c
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-002.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4078d6f0fc9d9d02022ae3a678db60d8b50cf375
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-003.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..36e399cd54fa56e479a0b6bed5febc50c0f5351f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-004.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..251aa2064b9ce3da5ec2a8c0da06ab9477e9977a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-005.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..55b778a80a682c8d5392b51162b3cd7cc953ac2e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-006.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e52480a9a5210762e500b565e25d5e02131b9f2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-007.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..699d1623f812a7f0ebb500e0582e8f2fb70792e1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-008.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..988d328a7c4940316e462fa94ef237707ab65de4
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/payloads.json b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.ahk b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..cd7872c6685bd6f6fdb26072d6e8d9be99e14e3b
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.ahk
@@ -0,0 +1,2 @@
+Click(578,498)
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.json b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.png b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..ceb9cd089b97652028952eb23853b9af290b99c3
Binary files /dev/null and b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.ahk b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.ahk
new file mode 120000
index 0000000000000000000000000000000000000000..87308c3f3e05ee7628b443f9f62e776e6fe3feed
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.ahk
@@ -0,0 +1 @@
+../../06-promoted-level-two/desktop/0-menu.ahk
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.json b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.json
new file mode 120000
index 0000000000000000000000000000000000000000..fb45a099ab00782fa0d53240ce914c72c13a586a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-menu.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.png b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..9ec10f76f121516e804ac404bd839f43f08fafb3
Binary files /dev/null and b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/0-menu.png differ
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.ahk b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..9b01bafd2fb18ad0be684d29908b8660957f99f8
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.ahk
@@ -0,0 +1,7 @@
+MouseMove(710,274)
+Send("{LButton down}")
+Sleep(250)
+MouseMove(710,117)
+Sleep(500)
+Send("{LButton up}")
+Sleep(700)
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.json b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.png b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..36ba3037aeb7fbcdc5edf2af708ce12f4d120ce7
Binary files /dev/null and b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/1-action.png differ
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.ahk b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..7b1c00b5321013c583d352c2e6de44ebd428c275
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{866856EB-A00E-45A8-AB04-E632519D762C}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{866856EB-A00E-45A8-AB04-E632519D762C}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.json b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..11c3a73df7790947579264dc2fcf5f35677e35ac
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.json
@@ -0,0 +1 @@
+../../04-subpage-move/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.png b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..7de13152a1964b9a4bc16fa7af76538b2597909a
Binary files /dev/null and b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4d4ccc43d9e0ac08d76d492d277e28a335dee2af
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/08-collapsed-group-move/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..dc206ede4803fc3a1c44489b487d9b98b3a2a7af
Binary files /dev/null and b/corpus/page-lifecycle/movement/08-collapsed-group-move/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/08-collapsed-group-move/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..e2ebaf009b50f6521974fdeebbaa1fa927ebfae0
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../01-demoted-parent/notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/hierarchy.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c4ca496870a04aa397b66aaa222569a33d3cfd0e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-000.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e2b5df3e9b1163078a5be138752d322e56f78f4d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-001.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bfb4003628afcf3ded2907a22210764291856381
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-002.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68ae63f6223e2bf05b947f8b5741a10e6b32373f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-003.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1bee9cbce0563d1ddadadd2409f34d2c1e326fdb
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-004.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..58b0e05d4a0bfa4b2bc13d79dcf5629bb5ce3fbc
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-004.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-005.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..273103c31f96bd98df17ee8d7ded5a2d9cbd6d32
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-006.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a045cbfb065bb75fc35b523a4b3285b945d247b6
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-007.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ef8f76ac25ab07a53b43c45591a4a05b63dadeb2
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-008.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ad2994b5797a8267ab062c92cd889883de5aed37
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/08-collapsed-group-move/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/08-collapsed-group-move/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/README.md b/corpus/page-lifecycle/movement/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5f252f9cfeeea77517e276070d7fdbedf9679634
--- /dev/null
+++ b/corpus/page-lifecycle/movement/README.md
@@ -0,0 +1,36 @@
+# Native page movement controls
+
+Nine OneNote 2010 reference outcomes from the synthetic `04-nested` section.
+Every outcome has a closed notebook, native page XML, an independent cold reopen,
+and saved desktop actions/screenshots. `provenance.json` records the controllers,
+source, machines and teardown. Identical files link to one stored copy.
+
+The controls distinguish three operations:
+
+- Moving an expanded, individually selected tab moves that page alone. Its
+ following subpages retain their levels and join the preceding series.
+- Moving an explicitly selected range moves every selected page. Moving a
+ collapsed top-level tab also moves its hidden subpages.
+- Promotion/demotion changes only the selected page's level. A level-3 page can
+ directly follow a level-1 page; indentation is not a conventional subtree.
+
+`tools/native_page_movement.py OUTPUT` replays the eight numbered phases in an
+owned 800×600 clone. The `single-page` reference comes from an earlier replay
+whose group-movement expectation was rejected; its actual single-page outcome
+was retained and independently validated. Its exact desktop actions are saved
+alongside the notebook. The subsequent ordinary-click replay reproduced it.
+Cold-capture each numbered phase with `tools/native_runner.py INPUT OUTPUT
+--expected-pages 9 --collect-notebook`.
+
+Run `PYTHONPATH=tools python3 -m unittest tools.test_page_movement -v` after
+building the document example. The test verifies stable page identities, order,
+levels, series membership, content-tree relationships, text and formatting,
+then compares native XML and all active graphs across each cold reopen.
+
+In `02-promoted-parent`, native OneNote left one section metadata copy at level 2
+while the authoritative page metadata was level 1. Its cold reopen refreshed
+that copy to 1. MS-ONE §2.2.81 product-behavior footnote 9 explicitly permits
+temporary differences and describes subsequent native refresh. This fixture
+accepts exactly one such level refresh; every other graph field must match.
+The default comparison still rejects this change and remains strict for Rust
+publication fixtures.
diff --git a/corpus/page-lifecycle/movement/provenance.json b/corpus/page-lifecycle/movement/provenance.json
new file mode 100644
index 0000000000000000000000000000000000000000..5749f06b0c559b24663514de194c40f6a703e605
--- /dev/null
+++ b/corpus/page-lifecycle/movement/provenance.json
@@ -0,0 +1,109 @@
+{
+ "source": "corpus/page-lifecycle/04-nested/notebook/Lifecycle.one",
+ "author_capture": "evidence/m10/page-movement-native-05",
+ "author_machine": {
+ "name": "m6-4a2dfcf5",
+ "hostname": "ONE-M6-4A2DFCF5"
+ },
+ "author_teardown": {
+ "absent": true
+ },
+ "scripts": {
+ "controller_sha256": "5630c0252072b92d4a8ac04b7b577106cef550aad93ed41fc50f145eaabf0af7",
+ "helper_sha256": "881fcdcc88eabecf965737085faede5cb39dda6f3f832b3875b0c62345ffbde6"
+ },
+ "single_page_capture": "evidence/m10/page-movement-native-03",
+ "single_page_expectation": "The controller rejected a group-move expectation; the captured single-page outcome was independently cold-validated.",
+ "cold": {
+ "01-demoted-parent": {
+ "capture": "evidence/m10/page-movement-cold-01-demoted-parent",
+ "machine": {
+ "name": "m6-97b05910",
+ "hostname": "ONE-M6-97B05910"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "02-promoted-parent": {
+ "capture": "evidence/m10/page-movement-cold-02-promoted-parent",
+ "machine": {
+ "name": "m6-2aeea4f2",
+ "hostname": "ONE-M6-2AEEA4F2"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "03-selected-group-move": {
+ "capture": "evidence/m10/page-movement-cold-03-selected-group-move",
+ "machine": {
+ "name": "m6-cd0faacb",
+ "hostname": "ONE-M6-CD0FAACB"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "04-subpage-move": {
+ "capture": "evidence/m10/page-movement-cold-04-subpage-move",
+ "machine": {
+ "name": "m6-554a4076",
+ "hostname": "ONE-M6-554A4076"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "05-insert-before-subpage": {
+ "capture": "evidence/m10/page-movement-cold-05-insert-before-subpage",
+ "machine": {
+ "name": "m6-982b068d",
+ "hostname": "ONE-M6-982B068D"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "06-promoted-level-two": {
+ "capture": "evidence/m10/page-movement-cold-06-promoted-level-two",
+ "machine": {
+ "name": "m6-1dc0856b",
+ "hostname": "ONE-M6-1DC0856B"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "07-promoted-root": {
+ "capture": "evidence/m10/page-movement-cold-07-promoted-root",
+ "machine": {
+ "name": "m6-93230663",
+ "hostname": "ONE-M6-93230663"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "08-collapsed-group-move": {
+ "capture": "evidence/m10/page-movement-cold-08-collapsed-group-move",
+ "machine": {
+ "name": "m6-6f5064db",
+ "hostname": "ONE-M6-6F5064DB"
+ },
+ "teardown": {
+ "absent": true
+ }
+ },
+ "single-page": {
+ "capture": "evidence/m10/page-movement-single-cold",
+ "machine": {
+ "name": "m6-d98e3a6d",
+ "hostname": "ONE-M6-D98E3A6D"
+ },
+ "teardown": {
+ "absent": true
+ }
+ }
+ }
+}
diff --git a/corpus/page-lifecycle/movement/single-page/cold/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/single-page/cold/notebook/Lifecycle.one
new file mode 120000
index 0000000000000000000000000000000000000000..0c82f1045162a6bde2dc5f5fe0881c0130aca14d
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/notebook/Lifecycle.one
@@ -0,0 +1 @@
+../../notebook/Lifecycle.one
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/single-page/cold/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/single-page/cold/notebook/Open Notebook.onetoc2
new file mode 120000
index 0000000000000000000000000000000000000000..6163f4bc08e3231fc79ece13ab200008054412d1
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/notebook/Open Notebook.onetoc2
@@ -0,0 +1 @@
+../../notebook/Open Notebook.onetoc2
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/environment.json b/corpus/page-lifecycle/movement/single-page/cold/read/environment.json
new file mode 100644
index 0000000000000000000000000000000000000000..7c0ad9b64f90b93c7374ebdfbea6a33314fc1a6a
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/environment.json
@@ -0,0 +1,7 @@
+{
+ "powershell": "5.1.14409.1005",
+ "schema": "xs2010",
+ "hostname": "ONE-M6-D98E3A6D",
+ "cold": true,
+ "onenote": "14.0.4763.1000"
+}
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/hierarchy.xml b/corpus/page-lifecycle/movement/single-page/cold/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..14e4fbc6b12c7f3a5a27ddc54bc8bf319135b609
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-000.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..08239952f154c1493ac9de5049515afe4c1f17bc
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-000.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-001.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a3d0381c58b63e95a03420fa4844b86470f92266
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-001.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-002.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e986dc3676d49e0752ef2a3ea356df26d29f513
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-002.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-003.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a70d5f7088cc5b1f13352bfeb85ee3e8422cd48
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-003.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-004.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d8f8d3cc54923e01f7bf344b56d63cd164206b1f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-005.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12a93e5059821fc14e10f3245cabe07b57467721
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-005.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-006.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0212262197787238f57269b6fc85b42c6b2fe99f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-006.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-007.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bbe527a0c93a18f95f8b3a973be9c129d095c390
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/page-008.xml b/corpus/page-lifecycle/movement/single-page/cold/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3e30ee5f35bfafd47d2319f5cb2e0037244c128f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/cold/read/payloads.json b/corpus/page-lifecycle/movement/single-page/cold/read/payloads.json
new file mode 120000
index 0000000000000000000000000000000000000000..3e9efde26e8b7e90a6e6e5fb61fe1be52686aa5e
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/cold/read/payloads.json
@@ -0,0 +1 @@
+../../../01-demoted-parent/cold/read/payloads.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/0-action.ahk b/corpus/page-lifecycle/movement/single-page/desktop/0-action.ahk
new file mode 120000
index 0000000000000000000000000000000000000000..92b164c7e8d8bd60741871ecd31f13cae720eb59
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/desktop/0-action.ahk
@@ -0,0 +1 @@
+../../03-selected-group-move/desktop/1-action.ahk
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/0-action.json b/corpus/page-lifecycle/movement/single-page/desktop/0-action.json
new file mode 120000
index 0000000000000000000000000000000000000000..37ede9e237a3e07f1e0a9ec7cd9c58918be1a2dd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/desktop/0-action.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/0-action.png b/corpus/page-lifecycle/movement/single-page/desktop/0-action.png
new file mode 100644
index 0000000000000000000000000000000000000000..609b31f60b701f5344b836e9b64f1620045182a4
Binary files /dev/null and b/corpus/page-lifecycle/movement/single-page/desktop/0-action.png differ
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/navigate.ahk b/corpus/page-lifecycle/movement/single-page/desktop/navigate.ahk
new file mode 100644
index 0000000000000000000000000000000000000000..23f8f94889e610444e13d73315b6c5a7eb46255f
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/desktop/navigate.ahk
@@ -0,0 +1,15 @@
+if A_ScreenWidth != 800 || A_ScreenHeight != 600
+ throw Error("This fixture requires an 800 by 600 desktop")
+OnError((exception, mode) => (FileAppend(exception.Message, "**"), ExitApp(1)))
+DetectHiddenWindows false
+app := ComObject("OneNote.Application")
+app.NavigateTo("{C6DF1EEC-1EB0-4FE5-815D-5159ABCB4C73}{1}{B0}", "", false)
+hwnd := WinWait("ahk_class Framework::CFrame ahk_exe ONENOTE.EXE",, 10)
+if !hwnd
+ throw Error("OneNote window did not appear")
+WinMaximize(hwnd)
+WinActivate(hwnd)
+if !WinWaitActive(hwnd,, 10)
+ throw Error("OneNote window did not become active")
+app.NavigateTo("{C6DF1EEC-1EB0-4FE5-815D-5159ABCB4C73}{1}{B0}", "", false)
+Sleep 300
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/navigate.json b/corpus/page-lifecycle/movement/single-page/desktop/navigate.json
new file mode 120000
index 0000000000000000000000000000000000000000..37ede9e237a3e07f1e0a9ec7cd9c58918be1a2dd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/desktop/navigate.json
@@ -0,0 +1 @@
+../../01-demoted-parent/desktop/0-action.json
\ No newline at end of file
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/navigate.png b/corpus/page-lifecycle/movement/single-page/desktop/navigate.png
new file mode 100644
index 0000000000000000000000000000000000000000..04a83487dbc08638f3c4e793af9ab8497454e4be
Binary files /dev/null and b/corpus/page-lifecycle/movement/single-page/desktop/navigate.png differ
diff --git a/corpus/page-lifecycle/movement/single-page/desktop/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/single-page/desktop/reopened-hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dc399f2022d130fca1d6023bb99b3264223fba24
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/desktop/reopened-hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/notebook/Lifecycle.one b/corpus/page-lifecycle/movement/single-page/notebook/Lifecycle.one
new file mode 100644
index 0000000000000000000000000000000000000000..770790661186944e722d0b7ae44671a528aba17e
Binary files /dev/null and b/corpus/page-lifecycle/movement/single-page/notebook/Lifecycle.one differ
diff --git a/corpus/page-lifecycle/movement/single-page/notebook/Open Notebook.onetoc2 b/corpus/page-lifecycle/movement/single-page/notebook/Open Notebook.onetoc2
new file mode 100644
index 0000000000000000000000000000000000000000..943deac01aaecd495028b23dde952cbd85bc612c
Binary files /dev/null and b/corpus/page-lifecycle/movement/single-page/notebook/Open Notebook.onetoc2 differ
diff --git a/corpus/page-lifecycle/movement/single-page/read/hierarchy.xml b/corpus/page-lifecycle/movement/single-page/read/hierarchy.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ff9a6a710848544daa087975021f6a9b46ab3b86
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/hierarchy.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-000.xml b/corpus/page-lifecycle/movement/single-page/read/page-000.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8c7b5ed74f9cf6e09b6f78a79b7ce859fb528b96
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-000.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-001.xml b/corpus/page-lifecycle/movement/single-page/read/page-001.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0b607102250f05f66002550436a626f678d0f1be
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-001.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-002.xml b/corpus/page-lifecycle/movement/single-page/read/page-002.xml
new file mode 100644
index 0000000000000000000000000000000000000000..01f7ef543fd27ab9daca9f7507e8cdff6b380590
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-002.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-003.xml b/corpus/page-lifecycle/movement/single-page/read/page-003.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7d54ad5bdc515cca2c4a438928ec511a3821f0bd
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-003.xml
@@ -0,0 +1,4 @@
+
+Body child 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-004.xml b/corpus/page-lifecycle/movement/single-page/read/page-004.xml
new file mode 100644
index 0000000000000000000000000000000000000000..482f2d2f4f39cb4a93fecc6055e4c9d51fcf4116
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-004.xml
@@ -0,0 +1,4 @@
+
+Body grandchild 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-005.xml b/corpus/page-lifecycle/movement/single-page/read/page-005.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0e8d7d84ac4b9ee0839ad2f687d6525c77c17428
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-005.xml
@@ -0,0 +1,4 @@
+
+Body duplicate 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-006.xml b/corpus/page-lifecycle/movement/single-page/read/page-006.xml
new file mode 100644
index 0000000000000000000000000000000000000000..66d0f69c96045153c74b7dccf42b5d5a3dc6e2aa
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-006.xml
@@ -0,0 +1,4 @@
+
+Body trailing 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-007.xml b/corpus/page-lifecycle/movement/single-page/read/page-007.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3a18dd043a7de0263189bb9b6ba11e40de727a57
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-007.xml
@@ -0,0 +1,4 @@
+
+Body automatic 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/read/page-008.xml b/corpus/page-lifecycle/movement/single-page/read/page-008.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f4540a128ccab2d1a26d5d23f6571c6f05ba8dba
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/page-008.xml
@@ -0,0 +1,4 @@
+
+Body parent 🦀 é preserved]]>
diff --git a/corpus/page-lifecycle/movement/single-page/read/reopened-hierarchy.xml b/corpus/page-lifecycle/movement/single-page/read/reopened-hierarchy.xml
new file mode 120000
index 0000000000000000000000000000000000000000..348ac27226596a9e9589588b3c8f7a93c1d2f637
--- /dev/null
+++ b/corpus/page-lifecycle/movement/single-page/read/reopened-hierarchy.xml
@@ -0,0 +1 @@
+../desktop/reopened-hierarchy.xml
\ No newline at end of file
diff --git a/tools/native/page-lifecycle.ps1 b/tools/native/page-lifecycle.ps1
index 0dd412ed6bb9d87efb72adc8f9546b19d8687a8d..f9421c76eff8c4e163601ff35d5be2aa1b1ca0e3 100644
--- a/tools/native/page-lifecycle.ps1
+++ b/tools/native/page-lifecycle.ps1
@@ -1,7 +1,16 @@
-param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost)
+param([Parameter(Mandatory=$true)][string]$Root, [Parameter(Mandatory=$true)][string]$CloneHost,
+ [string]$CaptureOnly = '')
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
-& "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost
+if ($CaptureOnly) {
+ if ($CaptureOnly -notmatch '^[a-z0-9-]+$' -or $CloneHost -notmatch '^ONE-[A-Z0-9-]+$' -or
+ [Environment]::MachineName -ne $CloneHost -or
+ [IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($Root).TrimEnd('\')) -ne 'C:\one-tests\runs') {
+ throw 'Choose a named capture in the owned clone run.'
+ }
+} else {
+ & "$PSScriptRoot\cold-current.ps1" -Root $Root -CloneHost $CloneHost
+}
$app = New-Object -ComObject OneNote.Application
$notebook = ''
$section = ''
@@ -66,7 +75,7 @@ function Save-Phase([string]$Name) {
}
}
}
- $pages | ConvertTo-Json | Set-Content (Join-Path $destination 'pages.json') -Encoding UTF8
+ if ($pages.Count) { $pages | ConvertTo-Json | Set-Content (Join-Path $destination 'pages.json') -Encoding UTF8 }
Write-Output $Name
}
@@ -89,6 +98,10 @@ function Set-Order([string[]]$Names, [int[]]$Levels) {
try {
$app.OpenHierarchy((Join-Path $Root 'notebook'), '', [ref]$notebook, 0)
$app.OpenHierarchy('Lifecycle.one', $notebook, [ref]$section, 3)
+ if ($CaptureOnly) {
+ Save-Phase $CaptureOnly
+ return
+ }
foreach ($style in 0..2) {
$page = ''
$app.CreateNewPage($section, [ref]$page, $style)
@@ -118,7 +131,7 @@ try {
$app.DeleteHierarchy($pages['parent'], [DateTime]::MinValue, $false)
Save-Phase '06-deleted-parent'
} finally {
- if ($notebook) { $app.CloseNotebook($notebook, $false) }
+ if ($notebook -and -not $CaptureOnly) { $app.CloseNotebook($notebook, $false) }
[void][Runtime.InteropServices.Marshal]::FinalReleaseComObject($app)
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
diff --git a/tools/native_page_movement.py b/tools/native_page_movement.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1dadae279eb5a729b6cc17784e08f513d73b60f
--- /dev/null
+++ b/tools/native_page_movement.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+"""Capture native page indentation and tab movement in an owned clone."""
+import argparse
+import base64
+import hashlib
+import json
+from pathlib import Path
+import shutil
+import signal
+from tempfile import TemporaryDirectory
+import xml.etree.ElementTree as ET
+
+import native_runner as runner
+
+NAMES = ['Untitled page'] * 3 + [
+ 'Same title', 'child', 'grandchild', 'Renamed 🦋 é',
+ 'Body trailing 🦀 é preserved', 'Body automatic 🦀 é preserved']
+PHASES = [
+ ('01-demoted-parent', 3, [('menu', 179)], list(range(9)), [1, 1, 1, 2, 2, 3, 1, 1, 1]),
+ ('02-promoted-parent', 3, [('menu', 202)], list(range(9)), [1, 1, 1, 1, 2, 3, 1, 1, 1]),
+ ('03-selected-group-move', 3, [('select', 2), ('drag', 308)], [0, 1, 2, 6, 7, 8, 3, 4, 5], [1, 1, 1, 1, 1, 1, 1, 2, 3]),
+ ('04-subpage-move', 4, [('drag', 182)], [0, 1, 2, 4, 6, 7, 8, 3, 5], [1, 1, 1, 1, 1, 1, 1, 1, 3]),
+ ('05-insert-before-subpage', 4, [('drag', 286)], [0, 1, 2, 6, 7, 8, 3, 4, 5], [1, 1, 1, 1, 1, 1, 1, 3, 3]),
+ ('06-promoted-level-two', 4, [('menu', 202)], [0, 1, 2, 6, 7, 8, 3, 4, 5], [1, 1, 1, 1, 1, 1, 1, 2, 3]),
+ ('07-promoted-root', 4, [('menu', 202)], [0, 1, 2, 6, 7, 8, 3, 4, 5], [1, 1, 1, 1, 1, 1, 1, 1, 3]),
+ ('08-collapsed-group-move', 4, [('menu', 224), ('drag', 117)], [4, 5, 0, 1, 2, 6, 7, 8, 3], [1, 3, 1, 1, 1, 1, 1, 1, 1]),
+]
+
+
+def ui(target, source, destination):
+ destination.with_suffix('.ahk').write_text(source)
+ result = runner.windows.do_exec(source, target=target, timeout_ms=15000, shot_delay_ms=300)
+ destination.with_suffix('.json').write_text(json.dumps({k: v for k, v in result.items() if k != 'png_b64'}, indent=2))
+ if result.get('png_b64'):
+ destination.with_suffix('.png').write_bytes(base64.b64decode(result['png_b64']))
+ if result.get('exit') != 0 or result.get('error') or not result.get('png_b64'):
+ raise RuntimeError('Native desktop action failed; inspect its saved capture.')
+
+
+def interact(target, output):
+ helper = runner.ROOT / 'tools/native/page-lifecycle.ps1'
+ shutil.copy2(helper, output / 'scripts/page-lifecycle.ps1')
+ shutil.copy2(__file__, output / 'controller.py')
+ (output / 'interaction.json').write_text(json.dumps({
+ 'controller_sha256': hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
+ 'helper_sha256': hashlib.sha256(helper.read_bytes()).hexdigest(),
+ }, indent=2))
+ result = runner.windows.do_put(helper, r'C:\one-tests\page-lifecycle.ps1', target)
+ if result.get('error'):
+ raise RuntimeError(result['error'])
+ hierarchy = output / 'read/hierarchy.xml'
+ for phase, selected, actions, order, levels in PHASES:
+ pages = list(ET.parse(hierarchy).getroot().iter('{http://schemas.microsoft.com/office/onenote/2010/onenote}Page'))
+ row, page = next((i, page) for i, page in enumerate(pages) if page.get('name') == NAMES[selected])
+ destination = output / 'desktop' / phase
+ destination.mkdir(parents=True)
+ ui(target, 'if A_ScreenWidth != 800 || A_ScreenHeight != 600\n throw Error("This fixture requires an 800 by 600 desktop")\n'
+ + runner.navigation_script(page.get('ID')), destination / 'navigate')
+ y = 120 + row * 22
+ for ordinal, (action, value) in enumerate(actions):
+ if action == 'menu':
+ ui(target, f'Click(710,{y},"Right")\nSleep(500)', destination / f'{ordinal}-menu')
+ script = f'Click(578,{y + value})\nSleep(700)'
+ elif action == 'select':
+ script = f'Click(710,{y})\nSend("{{Shift down}}")\nClick(710,{y + value * 22})\nSend("{{Shift up}}")\nSleep(700)'
+ else:
+ script = f'MouseMove(710,{y})\nSend("{{LButton down}}")\nSleep(250)\nMouseMove(710,{value})\nSleep(500)\nSend("{{LButton up}}")\nSleep(700)'
+ ui(target, script, destination / f'{ordinal}-action')
+ runner.command(target, 'powershell -NoProfile -ExecutionPolicy Bypass -File C:\\one-tests\\page-lifecycle.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-' + target.upper() + ' -CaptureOnly ' + phase, output, 60000)
+ hierarchy = destination / 'reopened-hierarchy.xml'
+ result = runner.windows.do_get('C:\\one-tests\\runs\\capture\\' + phase + '\\reopened-hierarchy.xml', hierarchy, target)
+ if result.get('error'):
+ raise RuntimeError(result['error'])
+ pages = list(ET.parse(hierarchy).getroot())
+ actual = [(page.get('name'), int(page.get('pageLevel'))) for page in pages]
+ expected = [(NAMES[i], level) for i, level in zip(order, levels, strict=True)]
+ if actual != expected:
+ raise AssertionError((phase, actual, expected))
+ print('Verified native desktop phase: ' + phase, flush=True)
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument('output', type=Path)
+ args = parser.parse_args()
+ def interrupted(_signum, _frame):
+ raise KeyboardInterrupt
+ signal.signal(signal.SIGTERM, interrupted)
+ with TemporaryDirectory() as temporary:
+ source = Path(temporary)
+ shutil.copy2(runner.ROOT / 'corpus/page-lifecycle/04-nested/notebook/Lifecycle.one', source / 'Lifecycle.one')
+ runner.capture(source, args.output, expected_pages=9, collect_notebook=True, interaction=interact)
diff --git a/tools/native_runner.py b/tools/native_runner.py
index 2433cb12917812fa905511ee0c5878b994d41143..5ca947d7bb6b90c09842a6aefeb215fe4aedf81f 100644
--- a/tools/native_runner.py
+++ b/tools/native_runner.py
@@ -131,7 +131,9 @@ def clone(output):
(output / 'teardown.json').write_text(json.dumps({'absent': not vm.instance_path(name).exists()}) + '\n')
-def capture(notebook, output, expected_pages=-1, author=None, screenshots=False, pdf=False, author_timeout=600, inspect=False, collect_notebook=False):
+def capture(notebook, output, expected_pages=-1, author=None, screenshots=False, pdf=False, author_timeout=600, inspect=False, collect_notebook=False, interaction=None):
+ if inspect and interaction is not None:
+ raise ValueError('Choose manual inspection or an interaction callback.')
notebook = notebook.resolve(strict=True)
if not notebook.is_dir():
raise ValueError('Choose a notebook directory.')
@@ -180,7 +182,7 @@ def capture(notebook, output, expected_pages=-1, author=None, screenshots=False,
if result.get('error'):
raise RuntimeError(result['error'])
command(name, 'powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\author.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-%s' % name.upper(), output, author_timeout * 1000)
- command(name, 'powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-%s -ExpectedPages %d%s' % (name.upper(), expected_pages, (' -UseCurrentCache' if author else '') + (' -Pdf' if pdf else '') + (' -KeepOpen' if screenshots or inspect else '')), output, 600000)
+ command(name, 'powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-%s -ExpectedPages %d%s' % (name.upper(), expected_pages, (' -UseCurrentCache' if author else '') + (' -Pdf' if pdf else '') + (' -KeepOpen' if screenshots or inspect or interaction is not None else '')), output, 600000)
collect_artifacts(name, output, '*' if author or collect_notebook else 'read')
if screenshots:
for page in sorted((output / 'read').glob('page-*.xml')):
@@ -193,11 +195,14 @@ def capture(notebook, output, expected_pages=-1, author=None, screenshots=False,
page.with_suffix('.png').write_bytes(base64.b64decode(result['png_b64']))
if result.get('error') or result.get('exit') != 0 or not result.get('png_b64'):
raise RuntimeError('The native page screenshot failed; inspect its navigation record.')
- if inspect:
- print(f'Inspection ready: {name}; create {output / "finish"} to capture and close it.', flush=True)
- deadline = time.monotonic() + 1800
- while not (output / 'finish').exists() and time.monotonic() < deadline:
- time.sleep(.2)
+ if inspect or interaction is not None:
+ if interaction is not None:
+ interaction(name, output)
+ else:
+ print(f'Inspection ready: {name}; create {output / "finish"} to capture and close it.', flush=True)
+ deadline = time.monotonic() + 1800
+ while not (output / 'finish').exists() and time.monotonic() < deadline:
+ time.sleep(.2)
command(name, 'powershell -NoProfile -Command "Rename-Item C:\\one-tests\\runs\\capture\\read before-read"', output)
(output / 'read').rename(output / 'before-read')
command(name, 'powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File C:\\one-tests\\read-current.ps1 -Root C:\\one-tests\\runs\\capture -CloneHost ONE-%s -UseCurrentCache -ExpectedPages -1%s' % (name.upper(), ' -Pdf' if pdf else ''), output, 600000)
diff --git a/tools/test_page_movement.py b/tools/test_page_movement.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c71db44a10f26937f6f2037ca5d9007c2d019a4
--- /dev/null
+++ b/tools/test_page_movement.py
@@ -0,0 +1,58 @@
+import json
+from pathlib import Path
+import subprocess
+from tempfile import TemporaryDirectory
+import unittest
+
+from document_model import EXPORTER, ordered_pages, view, walk
+from native_page_movement import PHASES
+from verify_page_creation import compare
+
+FIXTURE = Path(__file__).resolve().parent.parent / 'corpus/page-lifecycle'
+
+
+class PageMovementTest(unittest.TestCase):
+ def test_native_selection_indentation_and_order_survive_cold_reopen(self):
+ with TemporaryDirectory() as temporary:
+ temporary = Path(temporary)
+ subprocess.run([EXPORTER, FIXTURE / '04-nested/notebook/Lifecycle.one', temporary / 'baseline'], check=True)
+ baseline = json.loads((temporary / 'baseline/document.json').read_text())
+ original = list(ordered_pages(baseline))
+ expected = [(phase, order, levels) for phase, _, _, order, levels in PHASES]
+ expected.append(('single-page', [0, 1, 2, 4, 5, 6, 7, 8, 3], [1, 1, 1, 2, 3, 1, 1, 1, 1]))
+ for phase, order, levels in expected:
+ with self.subTest(phase=phase):
+ fixture = FIXTURE / 'movement' / phase
+ if phase == '02-promoted-parent':
+ with self.assertRaises(AssertionError):
+ compare(fixture / 'notebook', fixture / 'cold')
+ refreshed = compare(fixture / 'notebook', fixture / 'cold',
+ refresh_metadata_levels=phase == '02-promoted-parent')
+ self.assertEqual(refreshed, int(phase == '02-promoted-parent'))
+ output = temporary / phase
+ subprocess.run([EXPORTER, fixture / 'notebook/Lifecycle.one', output], check=True)
+ document = json.loads((output / 'document.json').read_text())
+ pages = list(ordered_pages(document))
+ self.assertEqual([(sid, page) for sid, _, _, page in pages],
+ [(original[i][0], original[i][3]) for i in order])
+ self.assertEqual([r['nodes'][r['roots']['2']]['kind']['level'] for _, _, r, _ in pages], levels)
+ groups = []
+ for (sid, _, revision, page), index, level in zip(pages, order, levels, strict=True):
+ if level == 1:
+ groups.append([])
+ groups[-1].append(sid)
+ old = dict(walk(original[index][2], original[index][3]))
+ current = dict(walk(revision, page))
+ self.assertEqual(old.keys(), current.keys())
+ for oid in old:
+ for field in ('children', 'content', 'structure', 'format'):
+ self.assertEqual(old[oid][field], current[oid][field], (phase, oid, field))
+ if oid != page:
+ self.assertEqual(old[oid]['kind'], current[oid]['kind'], (phase, oid))
+ _, section = view(document, document['root'])
+ self.assertEqual([section['nodes'][oid]['spaces']
+ for oid in section['nodes'][section['roots']['1']]['children']], groups)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tools/verify_page_creation.py b/tools/verify_page_creation.py
index 01d3d6a533550f36ba45d1cdd2ee7d44ea2eb208..f94c595cb54a052ae7f9eafd8f41a633a5655067 100644
--- a/tools/verify_page_creation.py
+++ b/tools/verify_page_creation.py
@@ -14,7 +14,7 @@ from document_model import EXPORTER, ordered_pages, view
compare_document = runpy.run_path(str(Path(__file__).with_name('verify-document.py')))['compare']
-def compare(source, capture):
+def compare(source, capture, *, refresh_metadata_levels=False):
files = list(source.glob('*.one'))
assert len(files) == 1
with TemporaryDirectory() as temporary:
@@ -36,7 +36,7 @@ def compare(source, capture):
(sid, page) for sid, _, _, page in ordered_pages(after)]
assert before['root'] == after['root']
assert before['spaces'].keys() == after['spaces'].keys()
- filled = 0
+ filled = refreshed = 0
for sid in before['spaces']:
_, original = view(before, sid)
_, observed = view(after, sid)
@@ -46,6 +46,14 @@ def compare(source, capture):
series = expected[series_id]
existing = [p for p in series['extra'][0] if p['id'] == 0x24003442]
added = [p for p in observed['nodes'][series_id]['extra'][0] if p['id'] == 0x24003442]
+ if existing and refresh_metadata_levels:
+ for copy, page_sid in zip(existing[0]['value']['Objects'], series['spaces'], strict=True):
+ (_, _, page_view, _), = [p for p in pages if p[0] == page_sid]
+ metadata = expected[copy]['kind']
+ assert metadata['type'] == 'Metadata'
+ level = page_view['nodes'][page_view['roots']['2']]['kind']['level']
+ refreshed += metadata['level'] != level
+ metadata['level'] = level
if existing or not added:
continue
copies = []
@@ -62,7 +70,8 @@ def compare(source, capture):
series['extra'][0].append({'id': 0x24003442, 'value': {'Objects': copies}})
assert original['roots'] == observed['roots']
assert expected == observed['nodes'], sid
- print(f'Passed: {len(pages)} ordered pages and preserved active graphs; {filled} missing section metadata copies filled natively')
+ print(f'Passed: {len(pages)} ordered pages and preserved active graphs; {filled} missing section metadata copies filled natively; {refreshed} section metadata levels refreshed')
+ return refreshed
if __name__ == '__main__':