feat(workbench): extract the host-agnostic core into packages/workbench (0406) - #644
Merged
Conversation
The workbench's chrome references 52 distinct app-local modules, so moving the whole directory in one PR would churn web's highest-traffic area for days. This lands the increment with the best value-to-risk: the host-agnostic CORE — platform port, workbench store, tab/preview grammar, navigation intent, surfaces, commands, focus, route titles, sidebar sections, explorer sort, and the new-doc identity — whose only dependencies are react, zustand, lucide-react, and @xnetjs/plugins. The package is private and source-consumed (main -> src/index.ts, the canvas-core pattern), so no build ordering or vite aliases are needed. Old paths under apps/web/src/workbench/ keep one-line shims (the 0280 layout-tree pattern); both roads resolve to one module instance, and consumers migrate opportunistically. Two things surfaced by the move, fixed rather than carried: - state.ts declared its own ChromePosture, twin to the canonical one in @xnetjs/plugins — 0277's copied-type drift in miniature, exposed the moment a barrel saw both. The canonical type wins. - newDocId/CreatableDocType graduate from lib/doc-creation into the package; the app file keeps routes and menu chrome and re-exports identity. The ESLint router ban now covers packages/workbench/src, and the package's 89 tests run under the dom project. With the core packaged, the desktop renderer can adopt useWorkbench, the LayoutTree, and the port TODAY — the parity test's "the moment desktop adopts them it consumes the SAME module as web" now covers the whole state layer, not just layout-tree. Verified live: boot, working-set open, and New->Page (URL + editor) all flow through the package modules with zero console errors. 992 web + 89 package + 149 electron tests green; repo-wide typecheck clean. Signed-off-by: xNet Test <test@xnet.dev>
Contributor
🖼️ UI changes in this PRNo visual differences detected in the changed UI. |
Contributor
|
Preview removed for PR #644. |
crs48
added a commit
that referenced
this pull request
Jul 29, 2026
Every box in exploration 0406 is checked — 23/23 implementation, 10/10 validation — so the filename flips to `[x]`. The arc, for the record: #641/#642/#644 (port + core extraction), #648 (AI panel on desktop), #650/#651 (chrome behind injection points, first Electron mount), #652 (desktop surfaces in the shell), #653 (flag removed, bespoke shell deleted), #655 (cold-open back under the 0.52s baseline), #656 (approval-gated writes — the last blocked item). The desktop and web apps now render one shell from one module, verified live at every step. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Continues exploration 0406 (12/33 after this). Follows #641 (the seam) and #642 (the migration onto it); this PR makes the core physically shareable.
Why the core first, not the whole directory
The workbench's chrome references 52 distinct app-local modules (views, comms, hooks, search). A whole-directory move would churn web's highest-traffic area for days and conflate relocation with API design. The host-agnostic core, by contrast, has exactly four dependencies —
react,zustand,lucide-react,@xnetjs/plugins— so it moves cleanly and delivers the thing desktop actually needs first: the state layer.@xnetjs/workbenchnow contains: thePlatformPort, the workbench store, tab/preview grammar, navigation intent, surfaces, command wiring, focus, route titles, sidebar sections, explorer sort, new-doc identity, and the test port. Private and source-consumed (main → src/index.ts, thecanvas-corepattern) — no build ordering, no vite aliases.Old paths keep one-line shims (the 0280
layout-tree.tspattern, this repo's own precedent). Both roads resolve to one module instance; consumers migrate opportunistically.What the move itself surfaced
state.tsdeclared its ownChromePosture, a twin of the canonical type in@xnetjs/plugins— 0277's copied-type drift in miniature, invisible until a barrel saw both declarations. Fixed at the source rather than papered over in the barrel.newDocId/CreatableDocTypegraduate into the package;lib/doc-creationkeeps routes + menu chrome and re-exports identity.Why this matters for the desktop
The parity test's founding condition — "the moment desktop adopts them it consumes the SAME module as web" — now covers the entire state layer, not just
layout-tree. Phase 3 (mounting the shell in Electron) can begin with desktop importinguseWorkbenchand the port directly.Verification
packages/workbench/src.skip-changelog: internal restructuring, no user-visible change. Private package → no changeset.🤖 Generated with Claude Code