docs/plans/2026-05-26-slate-v2-dry-view-boundary-runtime.md
Objective:
Implement the accepted DRY Slate v2 view-boundary runtime slice in
.tmp/slate-v2, complete only when public API stays stable (<Editable root>,
slots.contentRoot, slots.contentBoundary), duplicated content-root /
hidden-boundary navigation-selection-command-history ownership is consolidated
into one internal graph/target owner where feasible, shared conformance coverage
proves examples/multi-root-document, examples/synced-blocks, and
examples/hidden-content-blocks across arrow navigation, Shift selection,
Cmd/Meta boundaries, history restore, copy/delete/type behavior or explicit
degraded capability rows, focused .tmp/slate-v2
package/browser/typecheck/lint verification passes, autoreview has no
accepted/actionable findings, changesets exist if published package behavior
changes, and
node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-26-slate-v2-dry-view-boundary-runtime.md
passes.
Flow mode: one-shot execution
Goal plan: docs/plans/2026-05-26-slate-v2-dry-view-boundary-runtime.md
Template: docs/plans/templates/task.md
Primary template: docs/plans/templates/task.md
Applied packs:
Task source:
docs/plans/2026-05-26-slate-v2-unified-view-boundary-navigation-architecture.mdCompletion threshold:
.tmp/slate-v2 without replacing public
Editable root, slots.contentRoot, or slots.contentBoundary.multi-root-document, synced-blocks, and hidden-content-blocks; any
unsupported native behavior is recorded as an explicit capability/degradation
row..tmp/slate-v2 typecheck/lint gates pass or any failure is proven
unrelated with exact evidence..tmp/slate-v2 implementation diff returns no
accepted/actionable findings.node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-26-slate-v2-dry-view-boundary-runtime.md passes.Verification surface:
.tmp/slate-v2/packages/slate-react/test/*projection*,
*content-root*, *keyboard-input*, *clipboard*, or new focused contract
tests for view-boundary graph/selection/command behavior..tmp/slate-v2/playwright/integration/examples/multi-root-document.test.ts,
synced-blocks.test.ts, and hidden-content-blocks.test.ts focused rows..tmp/slate-v2: owning package typecheck, site typecheck if examples change,
scoped lint/format, and final focused browser route proof.plate-2: this goal plan and final autogoal checker.Constraints:
Boundaries:
docs/plans/2026-05-26-slate-v2-unified-view-boundary-navigation-architecture.md..tmp/slate-v2/packages/slate-react/**,
.tmp/slate-v2/packages/slate-dom/** if hidden-boundary helper changes are
required, .tmp/slate-v2/playwright/integration/examples/**,
.tmp/slate-v2/site/examples/ts/** only when fixture/proof needs it,
.tmp/slate-v2/.changeset/** if package behavior changes, and this plan./examples/multi-root-document, /examples/synced-blocks,
/examples/hidden-content-blocks.ViewSelection API exposure.Blocked condition:
.tmp/slate-v2
verification cannot run because of a persistent tool/environment blocker that
survives the repo-approved local-env retry.Task state:
Current verdict:
Completion rule:
update_goal(status: complete) after autoreview has no accepted
actionable findings and the checker command passes.Start Gates:
| Gate | Applies | Evidence |
|---|---|---|
| Skill analysis before edits | yes | Loaded autogoal, task, and changeset; user explicitly invoked autogoal. |
| Active goal checked or created | yes | Active goal continued with .tmp/slate-v2 objective and this plan. |
| Source of truth read before edits | yes | Read accepted unified view-boundary plan and current goal prompt. |
| Tracker comments and attachments read | no | N/A: no tracker item. |
| Video transcript evidence required | no | N/A: no video evidence. |
docs/solutions checked for non-trivial existing-code work | yes | Previous planning pass covered multi-root DX, native caret, rootless selection, operation-root, and DOMCoverage solution notes. |
| TDD decision before behavior change or bug fix | yes | Added/refactored focused contract tests and used browser rows as behavior proof. |
| Branch decision for code-changing task | no | N/A: no branch or PR requested; repo says no proactive git hygiene. |
| Release artifact decision | yes | Added patch changesets for slate-react and slate-dom. |
| Browser tool decision for browser surface | yes | Used focused Playwright Chromium proof for the three affected examples. |
| PR expectation decision | no | N/A: no PR requested. |
| Tracker sync expectation decision | no | N/A: no tracker item. |
| Browser pack selected | yes | browser pack applied. |
| Browser route / app surface identified | yes | /examples/multi-root-document, /examples/synced-blocks, /examples/hidden-content-blocks. |
| Browser tool decision recorded | yes | Playwright is the owning browser proof for .tmp/slate-v2 integration examples. |
| Console/network caveat policy recorded | yes | Playwright page-level failures would fail the rows; no console/network failure surfaced in passed runs. |
| Package/API pack selected | yes | package-api pack applied. |
| Public surface or package boundary identified | yes | slate-react and slate-dom runtime behavior changed; public API names stayed stable. |
| Release artifact path selected | yes | .tmp/slate-v2/.changeset/focused-roots-restore-selection.md and .tmp/slate-v2/.changeset/dom-focus-sync-selection.md. |
changeset skill loaded when .changeset is required | yes | Loaded .agents/skills/changeset/SKILL.md and used patch changesets, one package per file. |
| Barrel/export impact decision recorded | yes | No public exports or exported file layout changed; no barrel generation needed. |
Work Checklist:
<video-transcripts> XML, or marked N/A with reason..agents/**, .claude/**,
.codex/**, skills, hooks, commands, prompts, or user-action tooling..changeset, registry changelog, or explicit no-artifact reason..changeset work loads changeset and follows its package/version/prose rules.docs/components/changelog.mdx instead of adding a package changeset.main.Completion Gates:
| Gate | Applies | Required action | Evidence |
|---|---|---|---|
| Named verification threshold | yes | Run named package/browser/lint/review/checker gates | Focused tests/typechecks/lint/browser proof and clean autoreview are recorded below; checker is the remaining command. |
| Bug reproduced before fix | yes | Record failing repro | Reproduced stale focus/selection with Playwright rows and manual instrumentation; final rows pass. |
| Targeted behavior verification | yes | Run focused test/proof | slate-react vitest contracts: 9 files, 59 tests passed. |
| TypeScript or typed config changed | yes | Run relevant typecheck | bun --filter slate-dom typecheck and bun --filter slate-react typecheck passed in .tmp/slate-v2. |
| Package exports or file layout changed | no | Barrel generation decision | N/A: no public exports or exported file layout changed. |
| Package manifests, lockfile, or install graph changed | no | Install graph check | N/A: no manifest or lockfile changes. |
| Agent rules or skills changed | no | Agent sync check | N/A: no agent files changed. |
| Workspace authority proof | yes | Run checks in owning repo | All package/browser commands ran from .tmp/slate-v2, the owning workspace. |
| Browser surface changed | yes | Prove route interactions | Playwright Chromium: 31/31 passed across the three affected example files. |
| Browser final proof | yes | Record artifact/caveat | Playwright trace would attach on failure; final passed run has command evidence and no failure artifact. |
| CI-controlled template output changed | no | Restore or record reason | N/A: no templates touched. |
| Package behavior or public API changed | yes | Add changeset or reason | Added patch changesets for slate-react and slate-dom. |
| Registry-only component work changed | no | Registry changelog decision | N/A: no registry component work. |
| Docs or content changed | yes | Verify source-backed plan edits | This goal plan was updated as execution evidence only; no user docs changed. |
| High-risk mini gate | yes | Record failure mode and proof plan | Failure mode: stale native selection overwrites model/restored root selection; proof: unit contracts, repeated flaky row, and three-example browser sweep. Boundary is right because root focus and DOM selection export own the issue, not each example. |
| Agent-native review for agent/tooling changes | no | Agent-native decision | N/A: no agent/tooling files changed. |
| Local install corruption suspected | no | Reinstall decision | N/A: failures matched runtime behavior and were fixed in code. |
| Autoreview for non-trivial implementation changes | yes | Run autoreview local mode | .tmp/slate-v2: local autoreview rerun clean with no accepted/actionable findings. |
| PR create or update | no | PR decision | N/A: no PR requested. |
| PR proof image hosting | no | PR image decision | N/A: no PR requested. |
| Tracker sync-back | no | Tracker decision | N/A: no tracker item. |
| Final handoff contract | yes | Fill final fields | Filled below with outcome, proof, caveats, and design decision. |
| Final lint | yes | Run scoped lint/format | bunx biome check ... --fix passed; bunx eslint ... returned 0 errors and ignored-file warnings for unmatched config files. |
| Goal plan complete | yes | Run checker | To run after autoreview evidence is added. |
| Browser interaction proof | yes | Exercise target routes | Playwright Chromium exercised hidden-content, multi-root, and synced-block interactions. |
| Browser console/network check | yes | Record result | No pageerror/console/network failure surfaced in passed Playwright rows; failure traces were used during debugging. |
| Browser final proof artifact | yes | Record proof | Final command evidence: 31 passed in 25.8s. |
| Public API / package boundary proof | yes | Source-audit public API/export impact | No public API names changed; Editable root, slots.contentRoot, and slots.contentBoundary remain stable. |
| Release artifact classification | yes | Classify package delta | Published runtime behavior changed in slate-react and slate-dom; patch changesets added. |
| Published package changeset | yes | Add one file per package | Added focused-roots-restore-selection.md and dom-focus-sync-selection.md; no forbidden minor. |
| Registry changelog | no | Registry-only decision | N/A: no registry-only changes. |
| No release artifact | no | No-artifact decision | N/A: package runtime behavior changed. |
| Package typecheck/build/test | yes | Run owning package checks | slate-dom/slate-react typecheck and build passed; slate-react focused tests passed. |
| Barrel/export generation | no | Barrel decision | N/A: no exports or public file layout changed. |
Phase / pass table:
| Phase | Status | Evidence | Next |
|---|---|---|---|
| Intake and source read | done | source map below | closed |
| Implementation | done | shared view-boundary-graph, focus/root interaction, history, and DOM focus fixes landed | closed |
| Verification | done | focused unit/typecheck/lint/build/browser evidence below | autoreview |
| PR / tracker sync | n/a | no PR or tracker requested | closed |
| Closeout | done | changesets added; autoreview clean; checker runs before final response | final response |
Findings:
Editable root, slots.contentRoot, and
slots.contentBoundary; consolidate internal ownership around one graph-like
view-boundary model.projection-graph owns visible-order segmentation;
view-selection owns model sidecar/history identity;
projected-selection-target duplicated segment endpoint resolution and
repeated-root ambiguity checks; content-root-navigation duplicated node/root
boundary point traversal for arrow/enter/vertical navigation; DOMCoverage
boundary contracts already covered hidden-content policy rows.Decisions and tradeoffs:
view-boundary-graph is internal only; no public API was added.Implementation notes:
packages/slate-react/src/view-boundary-graph.ts as the shared owner
for rooted points, boundary point traversal, range endpoint resolution,
repeated-root ambiguity, and command target creation.view-selection, projected-selection-target,
content-root-navigation, browser-handle, and
projected-collab-substrate through the shared helper.focus-slate-editable.ts,
root-interaction-controller.ts, root-interaction-resolver.ts,
use-slate-history.ts, and slate-dom focus export.Review fixes:
site/next-env.d.ts imported the dev-only .next/dev/types/routes.d.ts.
Restored it to .next/types/routes.d.ts..tmp/slate-v2 returned clean: no
accepted/actionable findings.Error attempts:
| Error / failed attempt | Count | Next different move | Resolution |
|---|---|---|---|
| Multi-root padding click selected first paragraph start | 1 | Inspect event target and focus ordering | Fixed by making Slate focus export model selection before raw fallback. |
| Root chrome restore intermittently inserted at header start | 2 | Stop accepting stale root chrome event ranges and capture focus selection once | Fixed in resolver/controller; flaky row passed 10/10 repeats. |
| Hidden-content materialize row failed once in full sweep | 1 | Repeat focused row and rerun full sweep | Focused row passed 5/5; final full sweep passed 31/31. |
Verification evidence:
.tmp/slate-v2/packages/slate-react: bun test:vitest test/view-boundary-graph-contract.test.ts test/view-selection-contract.test.ts test/projected-command-contract.test.ts test/projected-clipboard-contract.test.ts test/content-root-navigation-contract.test.ts test/keyboard-input-strategy-contract.test.ts test/use-slate-root-chrome.test.tsx test/use-slate-history.test.tsx test/root-interaction-resolver.test.ts -> 9 files, 59 tests passed..tmp/slate-v2: PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun playwright playwright/integration/examples/multi-root-document.test.ts playwright/integration/examples/synced-blocks.test.ts playwright/integration/examples/hidden-content-blocks.test.ts --project=chromium -> 31 passed in 25.8s..tmp/slate-v2: PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun playwright playwright/integration/examples/multi-root-document.test.ts --project=chromium --grep "visible root chrome restores" --repeat-each=10 -> 10 passed..tmp/slate-v2: PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun playwright playwright/integration/examples/hidden-content-blocks.test.ts --project=chromium --grep "controls selection policy" --repeat-each=5 -> 5 passed..tmp/slate-v2: bun --filter slate-dom typecheck, bun --filter slate-react typecheck, bun --filter slate-dom build, and bun --filter slate-react build passed..tmp/slate-v2: scoped bunx biome check ... --fix passed with no fixes; scoped bunx eslint ... returned 0 errors and ignored-file warnings for unmatched config files..tmp/slate-v2: local autoreview initially reported one generated
site/next-env.d.ts dev-route type path; after restoring the production path,
local autoreview rerun passed with no accepted/actionable findings.Final handoff contract:
bun check:full mobile/browser matrix was run.view-boundary-graph plus root focus and DOM focus owners.Final handoff / sync:
multi-root-document, synced-blocks, and hidden-content-blocks.Timeline:
browser/package-api packs.view-boundary-graph and routed duplicated
callers through it.slate-react and slate-dom.Reboot status:
| Question | Answer |
|---|---|
| Where am I? | Closeout |
| Where am I going? | Checker, final response |
| What is the goal? | DRY the Slate v2 view-boundary runtime without public API churn and prove it across the three examples. |
| What have I learned? | The shared graph was the right DRY boundary; the last visible bugs were focus/export ownership bugs. |
| What have I done? | Implemented the shared helper, fixed root focus/selection/history behavior, added changesets, and passed focused proof. |
Open risks: