docs/plans/2026-05-22-slate-v2-root-location-authority-cleanup-ralplan.md
status: done created: 2026-05-22 completion_id: 019e46be-4ec4-7d11-bc6e-9fcf033a8803 current_pass: stopped-review-closeout current_pass_status: complete next_pass: none target_score: 0.94 score: 0.94
Hard take: this is a separate plan. It should not live inside the Pretext layout architecture plan anymore.
The root-location cleanup is its own core Slate lane:
PointRef and RangeRef behavior;The live .tmp/slate-v2 source already implements most of the intended
architecture: packages/slate/src/internal/root-location.ts centralizes root
inference and implicit-root stripping, point/range refs consume it, and the
accepted state-field replay-policy P2 is fixed.
The implementation and verification are closed for this lane:
PointRef / RangeRef
interfaces;.tmp/slate-v2;codex review --uncommitted loop was explicitly stopped
by the user, so this closeout records the verified local evidence instead of
pretending a final clean review verdict exists.Intent: split the root-location authority cleanup out of the Pretext/layout plan so the completed layout work stays closed and the remaining Slate core cleanup has one precise owner.
Desired outcome: a standalone root-location plan owns all remaining work for root metadata, ref root visibility, selection inverse roots, and replayable state-field patch policy.
In scope:
packages/slate/src/internal/root-location.ts;PointRef and RangeRef transform/root metadata behavior;OperationApi.inverse(set_selection) root derivation;Non-goals:
Path to include root;Decision boundaries:
PointRef / RangeRef root-surface concern must be
resolved by final review, not buried as a style preference.Principles:
unref().Top drivers:
__explicit*Root creates future drift.Options:
Consequence: the Pretext/layout plan can stay closed, while this plan owns only the core cleanup and final review gate.
| Surface | Current live source | Verdict |
|---|---|---|
| Internal root authority | .tmp/slate-v2/packages/slate/src/internal/root-location.ts:7 defines MAIN_ROOT_KEY; :24-:27 stores ref metadata in WeakMaps; :29-:69 owns operation/point/range/selection-patch root inference; :72-:99 owns implicit root injection and stripping. | keep |
PointRef transform | .tmp/slate-v2/packages/slate/src/interfaces/point-ref.ts:40 reads root metadata; :43 ignores sibling-root operations; :47-:50 injects then strips implicit roots. | keep |
RangeRef transform | .tmp/slate-v2/packages/slate/src/interfaces/range-ref.ts:46 reads root metadata; :49 ignores sibling-root operations; :53-:60 transforms and drafts public refs. | keep |
| Point ref creation | .tmp/slate-v2/packages/slate/src/editor/point-ref.ts:12 uses active operation root fallback; :26 writes root metadata. | keep |
| Range ref creation/publication | .tmp/slate-v2/packages/slate/src/editor/range-ref.ts:72 uses active operation root fallback; :97-:98 writes metadata; :125-:155 publishes/resets public drafts. | keep |
| Selection inverse | .tmp/slate-v2/packages/slate/src/interfaces/operation.ts:12 imports getSelectionPatchRoot; :530 and :537 derive inverse root from the restored selection patch. | keep |
| State-field replay policy | .tmp/slate-v2/packages/slate/src/core/public-state.ts:335 requires patch hooks when history !== 'skip' or collab === 'shared'; :348 rejects oversized unpatchable replay state. | keep |
| State-field regression | .tmp/slate-v2/packages/slate/test/document-state-patch-contract.ts:102 rejects large omitted-history fields without patch hooks. | keep |
Review cleanup applied:
PointRef and RangeRef no longer expose a public root?: string field.root-location.ts WeakMaps.editor-runtime-view-contract.ts asserts rootless refs do not gain a public
root property while still rebasing in the invoking view root.Target module:
packages/slate/src/internal/root-location.ts
Target ownership:
MAIN_ROOT_KEY;Public behavior:
current and unref() return the same root visibility the caller
supplied;history: 'skip'.Hard cuts:
__explicitRoot;__explicitAnchorRoot;__explicitFocusRoot;Focused coverage that must exist before closeout:
| File | Required coverage |
|---|---|
packages/slate/test/root-location-contract.ts | getOperationRoot, getPointRoot, getRangeRoot, getSelectionPatchRoot, implicit injection/stripping, mismatched range roots |
packages/slate/test/editor-runtime-view-contract.ts | rootless point/range refs created inside a header view shift on header ops and ignore main ops |
packages/slate/test/editor-runtime-view-contract.ts | rootless multi-block delete from a header view edits only header content |
packages/slate/test/rooted-operation-contract.ts | inverse set_selection restores main -> header, header -> null, and null -> header root behavior |
packages/slate/test/range-ref-contract.ts | public rangeRef.current, draft publication, and unref() preserve explicit/rootless input shape |
packages/slate/test/range-ref-contract.ts | public and internal range refs are removed only by matching-root operations |
packages/slate/test/transaction-contract.ts | committed root-scoped set_selection operation carries active root while middleware payload stays caller-shaped |
packages/slate/test/interfaces-contract.ts | point/range equality, compare, and intersection keep root-aware semantics |
packages/slate-history/test/document-state-history-contract.ts | undo/redo restores multi-root selection and root-scoped refs after edits |
packages/slate/test/document-state-patch-contract.ts | large omitted-history state field without patch hooks is rejected |
Coverage rejects:
Done in live source:
Closed:
done for this stopped-review closeout.| Lens | Decision |
|---|---|
tdd | applied: every behavior claim must be proven through public editor APIs, not private helper shape only |
testing | applied: focused contract tests are the right layer; no browser/e2e for this core-only cleanup |
performance-oracle | applied by plan: root checks stay O(1), WeakMap metadata avoids cloning except root inject/strip boundaries |
vercel-react-best-practices | skipped: no React render/subscription surface in this lane |
performance | skipped: no production RUM/cohort or DOM-count claim |
react-useeffect | skipped: no effects |
shadcn | skipped: no UI |
Claim decision:
Fixes #... or Improves #... issue claim from this cleanup.Reference docs:
docs/slate-v2/references/pr-description.md: unchanged, because no issue
claim or maintainer-facing PR line changes in this plan split.docs/slate-v2/ledgers/issue-coverage-matrix.md: unchanged for the same
reason.docs/slate-v2/ledgers/fork-issue-dossier.md: unchanged for the same reason.If final review changes the public/API story, this section must be revised before closeout.
| Change | Objection | Answer | Verdict |
|---|---|---|---|
| Move root-location follow-up out of Pretext/layout plan | Another plan file adds overhead. | The old plan was complete for layout. Root-location is Slate core and was making the layout plan lie about its owner. A separate plan lowers cognitive load and narrows gates. | keep |
| Internal root-location module | This is abstraction for a small bug. | The bug crossed point refs, range refs, operations, transforms, history, and state replay. One helper prevents drift across those callers. | keep |
| WeakMap/internal ref metadata | Hidden metadata is harder to inspect. | It keeps public point/range values caller-shaped and avoids dirty __explicit*Root fields on public-ish objects. | keep |
Potentially hide ref.root too | Ref root can be useful for debugging. | If it is public API, it leaks runtime metadata. Final review should decide whether to move it fully into the WeakMap authority. | revise if review accepts |
| No browser proof | Multi-root refs are core behavior but can surface in browser. | The touched code is package core and has direct editor/history contracts. Add browser proof only if a browser-visible regression appears. | keep |
| Pass | Status | Evidence added | Plan delta | Open issues | Next owner |
|---|---|---|---|---|---|
| current-state read | complete | Live .tmp/slate-v2 source and tests listed above | Created standalone root-location plan | none | plan split |
| plan split | complete | This plan owns root-location; old plan will point here | Pretext/layout plan no longer owns root-location closeout | none | final review |
| final-codex-review-closeout | stopped by user | Partial review sweeps ran; user explicitly stopped the broad review loop | Recorded no clean final review verdict claim | residual broad-review risk accepted by user stop | completion state |
| completion-closeout | complete | node tooling/scripts/completion-check.mjs passes after scoped state update | Completion file points at this plan with status: done | none | none |
Focused gates:
# cwd: /Users/zbeyens/git/plate-2/.tmp/slate-v2
bun test ./packages/slate/test/document-state-patch-contract.ts ./packages/slate/test/collab-document-state-contract.ts ./packages/slate/test/root-location-contract.ts ./packages/slate/test/editor-runtime-view-contract.ts ./packages/slate/test/rooted-operation-contract.ts ./packages/slate/test/range-ref-contract.ts ./packages/slate/test/transaction-contract.ts ./packages/slate/test/interfaces-contract.ts ./packages/slate-history/test/document-state-history-contract.ts
bun typecheck:packages
bun lint:fix
codex review --uncommitted
Broad gates before done:
# cwd: /Users/zbeyens/git/plate-2/.tmp/slate-v2
bun test:bun
bun typecheck:packages
bun lint
Planning gate:
# cwd: /Users/zbeyens/git/plate-2
node tooling/scripts/completion-check.mjs
Next owner: none.
Closed state:
codex review --uncommitted unless the user asks for another
review pass;This plan is done because:
status: done;node tooling/scripts/completion-check.mjs exits 0.Verified evidence:
bun lintbun test ./packages/slate-react/test/runtime-live-state-contract.ts ./packages/slate-history/test/history-contract.ts ./packages/slate-history/test/document-state-history-contract.ts ./packages/slate/test/editor-runtime-view-contract.ts
-> 87 pass, 0 failbun --filter ./packages/slate typecheckbun --filter ./packages/slate-history typecheckbun --filter ./packages/slate-react typecheckbun lint,
bun typecheck:root, git diff HEAD --check, slate-react Vitest, and
bun build:packagesCurrent status: done. The final broad Codex review verdict is intentionally not claimed.