docs/plans/2026-04-09-slate-v2-non-react-headless-core-usability-completion-plan.md
Close the non-React / headless core usability lane in
master-roadmap.md
and turn the corresponding open bucket in
release-file-review-ledger.md
from partial to closed-by-proof.
For this lane, "100% completion" means:
withReact(...)The current repo already has a lot of real non-React value:
So this lane is not open because headless core is missing.
It is open because the current story is still fragmented across:
headless/core rows in
true-slate-rc-proof-ledger.mdwithReact(createEditor())That makes the current headless claim weaker than it should be, and it lets the remaining gap blur together with the broader public-surface lane.
Do not try to close this lane by collapsing the package split.
Do not treat headless as “single package with everything stuffed into core.”
Close the lane on the current architecture:
slate owns document meaning, refs, transforms, and fragment semanticsslate-history owns undo/redo batching over the same transaction modelslate-hyperscript owns test/fixture/document construction helpersslate-dom owns browser transport, not the headless laneslate-react is downstream of the headless lane, not its ownerThat is the correct target because architecture-contract.md already says not to confuse headless with single-package.
slate, slate-history, and
slate-hyperscriptslate-hyperscript as a restored contributor-facing slotdist/
luckheadless/core rows partial even though the
underlying contract tests are already strongThis lane is done when all of the following are true:
slateslate-historyslate-hyperscriptrange-ref-contract.ts and clipboard-contract.ts are treated as direct
headless capability proof, not orphan rows parked under oracle harvestheadless/core lane without pretending the
broader public-surface lane is also donebroad API / public surface reconciliation laneFiles:
/Users/zbeyens/git/slate-v2/packages/slate/test/headless-contract.ts (new)Work:
range-ref-contract.ts and clipboard-contract.ts as detailed proof
files, but make headless-contract.ts the batch owner that ties them
together into one honest usage storyReason:
Files:
/Users/zbeyens/git/slate-v2/packages/slate/test/headless-contract.ts (new)/Users/zbeyens/git/slate-v2/packages/slate-history/index.tsWork:
createEditor()withHistory(...)Editor.rangeRef(...) / Editor.getFragment(...) or
Transforms.insertFragment(...)slate-hyperscript document constructionRequired test scenarios:
slate,
slate-history, and slate-hyperscriptwithHistory(createEditor()) works in the same headless flowFiles:
Work:
withReact(createEditor()) is
the only serious way inRequired doc outcome:
Files:
Work:
headless/core only if the owner file plus package/readme/doc updates
are enough to defend the sentenceReason:
Primary proof surfaces:
/Users/zbeyens/git/slate-v2/packages/slate/test/headless-contract.tsRequired verification before declaring the lane closed:
yarn exec mocha --require ./config/babel/register.cjs ./packages/slate/test/headless-contract.tsyarn exec mocha --require ./config/babel/register.cjs ./packages/slate/test/range-ref-contract.ts ./packages/slate/test/clipboard-contract.tsyarn exec mocha --require ./config/babel/register.cjs ./packages/slate-hyperscript/test/index.js ./packages/slate-hyperscript/test/smoke.jsyarn test:customyarn lint:typescript/Users/zbeyens/git/slate-v2/packages/slate/test/headless-contract.ts now
owns the lane directlyyarn exec mocha --require ./config/babel/register.cjs ./packages/slate/test/headless-contract.tsyarn workspace slate-hyperscript run testyarn test:customyarn lint:typescriptyarn exec eslint packages/slate/test/headless-contract.ts