feat(integration-ever-works): a change of the docs root moves the synced tree (OQ5, F94)
Owner decision OQ5 (a) for review finding F94 (REVIEW-2026-10-17-post-merge-findings, unit G6), owner queue item I6d.
Problem
The synced docs tree (Ever Works/Organization/…, Works/…) sits under the mapping's docs root. Changing that root (PUT /mappings/:id docsRootFolderId, or root() replacing a configured root that was archived) left the tree under the old root. Every later apply, push or sweep then compared the page's ancestry with the new root, never reached it, and unlinked each synced page for good ("moved out of the synced folders").
Change (EverWorksDocsStore)
- The tree follows the root.
root()andexistingRoot()place the tree before returning the root, and every ancestry or placement check goes through one of them first. A new mapping setting,DOCS_TREE_ROOT_ID, records the root the tree was last placed under. When the current root differs, theOrganization/andWorks/marker folders move from the recorded root to the new one (oneparentIdwrite each, appended last among the new root's children), with everything in them. Links and pages are untouched, so they keep syncing both ways. The old root folder stays. - Idempotent, and finishes after an interruption. A folder already under the new root is skipped, and the new root is recorded only after both folders have moved. A run cut off part-way finishes on the next step or sweep, and a second pass writes nothing. A mapping placed before this setting existed treats the tree folders' current parent as the recorded root.
- An archived configured root keeps being used (it still holds its pages). The sync no longer replaces it with a new "Ever Works" folder or overwrites the setting. A deleted configured root, or one inside the synced tree (the tree would end up under itself), still falls back to the sync's own "Ever Works" folder, and the tree moves there.
- Unchanged: a tree folder an admin moves out of the root on purpose still stops syncing what is in it. The move applies only to folders sitting directly under the recorded root.
- The README docs paragraph documents all of this. The one-word
cspell:ignoreaddition inever-works-docs.db.spec.tscovers a word #11107 added, which the spell check flags once the file is in a diff.
Verification
- Red first: on develop's store, the new
ever-works-docs.db.spec.tsblock plus the updated settings expectation fail 6 tests (move both ways, sweep plus cut-short move plus no-op second pass, archived root kept, deleted root, root inside the tree). With the change all pass. The "admin moves Organization/ out" test passes on both, which pins the behaviour that must not change. - Docs suites: 3 suites, 62 tests green.
tsc --noEmitstrict and with strict null checks off: 0 errors in scope. prettier (touched lines), cspell and the static gates (30/30) are green. - No migration: the new value is an
integration_settingrow.
After the first bot round (bc8c2ce573)
- A move survives a root that changes mid-move. The move writes its target first (
DOCS_TREE_MOVING_TO), and each pass gathers what sits under the recorded root or under an unfinished target. If A → B is cut short and the root is then changed to C, or set back to A, the whole tree still ends up together. - Legacy mappings (no
DOCS_TREE_ROOT_ID): the only earlier root the sync recognises is its own "Ever Works" folder, and a folder an admin placed anywhere else is never moved back. The root is recorded only once a tree folder sits under it. - The own folder as the fallback root goes back to the top first if it was dragged into the tree, so no folder can contain its own parent. An archived own folder is used as it is.
existingRoot(), used by the sweep and by pushes, falls back to the own folder when the configured root was deleted and the tree still exists.- 5 more tests (67/67 docs).
🤖 Generated with Claude Code
Summary by cubic
Changing the docs root (docsRootFolderId, or when the configured root is deleted) now moves the synced Organization/ and Works/ folders to the new root, so links and pages keep syncing instead of being unlinked.
- A new
DOCS_TREE_ROOT_IDsetting records the root the tree was last placed under; on a root change both marker folders move, each in one write, and the new root is recorded only after both moved, so the move is idempotent and finishes after an interruption. ADOCS_TREE_MOVING_TOsetting records the target while a move is in progress, so a root changed again mid-move still gathers the whole tree. - An archived configured root keeps being used; a deleted one, or a folder inside the synced tree, falls back to the sync's own "Ever Works" folder and the tree moves there. The own folder goes back to the top if it was dragged into the tree, so nothing contains its parent.
- Without a recorded root (mappings placed before the setting existed), only the sync's own "Ever Works" folder counts as an earlier root, so a tree folder an admin moved elsewhere on purpose is left where it is and its pages still stop syncing, as before.