Skip to main content

Workspace Composition Surface Migration Map

WCP-014 turns the current Claude UI source surfaces into an executable migration map. It does not move React code. It records what each surface should become when @maya/claude-workspace packages product defaults and @maya/assistant-ui renders a WorkspaceComposition.

The map is backed by tools/workspace-surface-migration-map.mjs and verified by pnpm verify:surface-migration-map.

Locked Invariants

Host resolves runtime.
Composer composes structure.
Render runtime executes UI.
ClaudeWorkspace packages product defaults.
Modules are trusted React UI adapters, not state/runtime owners.

Linked decisions: WCP-ADR-011, WCP-ADR-012, WCP-ADR-013, WCP-ADR-014.

First Safe Visual Parity Milestone

Descriptor-To-Render Shell Parity is the first safe visual parity milestone.

Scope: route, sidebar, settings, and customize shell selection may be driven from WorkspaceComposition, but handles must resolve to the existing Claude UI React surfaces and existing host-owned controllers. The milestone is safe only if navigation, route rendering, Settings, Customize, transcript, and fallback visuals remain unchanged.

Acceptance:

  • No second route table, global render registry, or built-in page patch path is introduced.
  • WCP-013 descriptor counts still match current Claude UI metadata.
  • Current Chat, Projects, Customize, Settings, Sidebar, package-boundary, and docs/DX gates pass.
  • Public module route publishing waits until this milestone is visually stable.

Verification:

  • pnpm verify:claude-builtins-fixture-parity
  • pnpm verify:surface-migration-map
  • pnpm verify:chat-surface
  • pnpm verify:projects-visual
  • pnpm verify:customize-surface
  • pnpm verify:settings-surface
  • pnpm verify:sidebar-surface
  • pnpm verify:package-boundary:built
  • pnpm verify:docs-dx

Surface Map

IDCurrent surfaceTarget categoryRiskMigration kind
route-metadata-and-pathsworkspaceRouteMeta, href helpers, matchers, route capability checksroutes, sidebarItemsMediumdescriptor-first: move identity and metadata first; keep execution in existing components until render runtime lands.
route-render-switchWorkspaceMainSurface and RouteSurface choose conversation, Chat history, Projects list/detail, Customize, product, and Generic surfacesroutes, ReactRenderPackHighhandle-first-with-existing-components: replace switch selection with route render handles only after the descriptor shell can render with visual parity.
generic-product-routesNew chat, Artifacts, Code, Design, and artifact preview surfaces currently folded into GenericRouteSurfaceroutes, ReactRenderPackMediumdefer-component-split: keep component splitting deferred; do not overfit handles before product ownership is moved.
sidebar-primary-product-navigationPrimary/product sidebar nav derived from route metadatasidebarItems, routesMediumdescriptor-first: compose navigation descriptors; preserve capability filtering and active state.
sidebar-host-owned-history-and-accountRecents, project shortcuts, sidebar search, account menu, and Add menuhostOwnedControllerState, notV0ContributionSurfaceHighkeep-product-shell-internal: keep inside Claude product shell; do not expose arbitrary sidebar slots in v0.
settings-section-inventorySettings hashes, section routes, nav labels, and Customize linksconfigurationSurfacesMediumdescriptor-first: descriptor-first migration with hash parity.
settings-dialog-renderingSettingsDialog section switch and SettingsShell chromeconfigurationSurfaces, ReactRenderPackHighshell-first-render-handle: keep shell state and focus behavior local; render sections through handles after parity.
settings-search-actions-and-draft-stateSearch query/results, draft save state, data export, action receipts, allowed-domain inputhostOwnedControllerState, notV0ContributionSurfaceHighkeep-host-owned: host owns persistent settings and actions; modules may render granted surfaces only.
customize-views-and-cardsCustomize overview, Skills, Connectors, product cards, personal plugins panelintegrationSurfaces, ReactRenderPackHighdescriptor-first-with-shell-internal-state: model semantic integration surfaces without binding modules to dialog or route placement.
customize-directory-and-custom-connectorDirectory catalog and custom connector dialogsintegrationSurfaces, hostOwnedControllerStateMediumintegration-surface-with-host-controller: dialog UI stays an integration surface; remote URL, OAuth client id, OAuth client secret, create/status/browse behavior remain host-owned controller data.
transcript-default-message-renderingTranscript, TranscriptMessageLog, MessageRow, default Markdown, and assistant error panelmessageRenderers, notV0ContributionSurfaceHighprotect-default-renderer: protect ordinary user/assistant text rendering; only custom/error claims are descriptor-addressable in v0.
message-appendersAttachments, protocol stack, artifacts, version controls, and message action controlsmessageAppendersHighappenders-after-default-renderer: compose cards around default rendering; preserve order, read-only behavior, and host-owned action authority.
message-host-owned-controlsAttachment, artifact, edit, feedback, read-aloud, retry, version-change, and activity action callbackshostOwnedControllerState, notV0ContributionSurfaceHighkeep-host-owned: render handles may show controls, but host controllers own action authority.
protocol-tool-cardsClaimed tool use/result cards for web_search and project_knowledge_searchtoolRenderers, messageAppendersMediumclaim-by-tool-name: claim renderer by explicit tool name; generic tool fallback stays inside the built-in protocol stack appender.
generic-tool-fallback-in-protocol-stackGeneric protocol tool labels and generic tool result labels for tool names without v0 renderer claimsmessageAppenders, notV0ContributionSurfaceMediumkeep-inside-protocol-stack-appender: keep generic tool fallback inside the built-in protocol stack appender.
protocol-activity-cardsActivity lifecycle cards, approval/resume actions, and activity metadataactivityRenderers, messageAppendersMediumclaim-by-activity-kind: claim renderer by activity kind; host keeps action authority.
protocol-side-cardsCitation, interaction, usage-limit, and stop-reason cardsmessageAppenders, notV0ContributionSurfaceMediumkeep-inside-protocol-stack-appender: keep inside the built-in protocol stack appender until a separate claim taxonomy is justified.
workspace-status-and-non-ready-fallbacksWorkspace shell status, retry affordance, and module non-ready state fallbacksactivityRenderers, fallbackSurfacesMediumfallback-descriptor-with-host-status: render status and fallback handles, but runtime status decisions stay host-owned.
default-composition-policyClaude ordering plus explicit hide/reorder/replace/pathAlias/rendererOverride policyCompositionPolicyMediumexplicit-policy-only: keep policy explicit and diagnostic-driven; do not let it become a patch language.

Explicit Gaps

These are not v0 extension points:

IDWhy it stays out of v0
public-built-in-page-replacement-apiBuilt-in page replacement needs stable route context and owner-approved parity. Policy can model replacement for diagnostics, but no public API exposes it yet.
default-user-assistant-text-overrideOrdinary user/assistant text rendering is protected by WCP-ADR-012.
dynamic-and-hash-route-contributions/chat/:id, /project/:id, and /new#settings/... are host/router view state in v0, not public module route paths.
arbitrary-sidebar-slotsRecents, account, Add menu, search, and project shortcuts mix host-owned data, account actions, and settings mutation.
settings-search-provider-extensionSearch currently indexes built-in metadata; module-search contribution needs host-owned filtering and stable searchable metadata.
project-detail-subroute-extensionProject detail list/detail and knowledge/source tabs are product-internal, controller-heavy surfaces. Modules can add their own pages in v0.
protocol-stack-sub-card-claim-taxonomyCitations, stop reasons, usage notices, and interaction cards remain under the built-in protocol stack appender until tool/activity/message claims prove stable.
generic-tool-renderer-claimUnknown tool names keep generic visual fallback inside the built-in protocol stack; v0 only publishes explicit claims for web_search and project_knowledge_search.
module-owned-persistent-settings-or-storageModules are UI adapters; host owns persistence, network, credentials, and audit behavior.
runtime-untrusted-plugin-loadingPhase one is trusted build-time npm React modules only. No marketplace, iframe, remote ESM, module federation, or runtime unknown-code install path exists.
suspense-loading-as-runtime-fallbackWorkspaceSurfaceFallback and route Suspense placeholders are React loading states, not host-resolved module runtime fallbackSurfaces.

Risk Ranking

High product-impact migration areas:

  • route-render-switch
  • settings-dialog-rendering
  • settings-search-actions-and-draft-state
  • customize-views-and-cards
  • transcript-default-message-rendering
  • message-appenders
  • message-host-owned-controls
  • sidebar-host-owned-history-and-account

Medium product-impact migration areas:

  • route-metadata-and-paths
  • generic-product-routes
  • sidebar-primary-product-navigation
  • settings-section-inventory
  • customize-directory-and-custom-connector
  • protocol-tool-cards
  • generic-tool-fallback-in-protocol-stack
  • protocol-activity-cards
  • protocol-side-cards
  • workspace-status-and-non-ready-fallbacks
  • default-composition-policy

No low-risk migration is claimed in WCP-014. The map is intentionally conservative because these surfaces are user-visible and controller-rich.

Source Anchors

The verifier checks that these source anchors still exist:

  • projects/assistant-composition/src/policy.ts
  • projects/assistant-composition/test/fixtures/wcp-010/fixture-policy-all-operations.json
  • projects/assistant-composition/test/fixtures/wcp-013/fixture-claude-builtins-default-composition.json
  • projects/claude-ui/src/components/chat/Transcript.tsx
  • projects/claude-ui/src/components/chat/TranscriptMessageLog.tsx
  • projects/claude-ui/src/components/directory/ProjectCustomConnectorDialog.tsx
  • projects/claude-ui/src/components/directory/ProjectDirectoryDialog.tsx
  • projects/claude-ui/src/components/directory/projectCustomConnectorForm.ts
  • projects/claude-ui/src/components/message/MessageActions.tsx
  • projects/claude-ui/src/components/message/MessageArtifactCards.tsx
  • projects/claude-ui/src/components/message/MessageAttachmentCards.tsx
  • projects/claude-ui/src/components/message/MessageProtocolCards.tsx
  • projects/claude-ui/src/components/message/MessageRow.tsx
  • projects/claude-ui/src/components/message/MessageVersionControls.tsx
  • projects/claude-ui/src/components/message/protocolActivityCards.tsx
  • projects/claude-ui/src/components/message/protocolActivityMetadata.ts
  • projects/claude-ui/src/components/message/protocolCitationCards.tsx
  • projects/claude-ui/src/components/message/protocolInteractionCard.tsx
  • projects/claude-ui/src/components/message/protocolLimitCard.tsx
  • projects/claude-ui/src/components/message/protocolStopReasonCard.tsx
  • projects/claude-ui/src/components/message/protocolToolCards.tsx
  • projects/claude-ui/src/components/settings/SettingsDialog.tsx
  • projects/claude-ui/src/components/settings/SettingsSearchNav.tsx
  • projects/claude-ui/src/components/settings/SettingsShell.tsx
  • projects/claude-ui/src/components/settings/metadata.ts
  • projects/claude-ui/src/components/workspace/AddMenu.tsx
  • projects/claude-ui/src/components/workspace/ArtifactPreviewPanel.tsx
  • projects/claude-ui/src/components/workspace/ArtifactVersionStrip.tsx
  • projects/claude-ui/src/components/workspace/ConnectorsSurface.tsx
  • projects/claude-ui/src/components/workspace/CustomizeOverviewSurface.tsx
  • projects/claude-ui/src/components/workspace/GenericRouteSurface.tsx
  • projects/claude-ui/src/components/workspace/ProductSurface.tsx
  • projects/claude-ui/src/components/workspace/SidebarNavigation.tsx
  • projects/claude-ui/src/components/workspace/SkillsSurface.tsx
  • projects/claude-ui/src/components/workspace/WorkspaceMainSurface.tsx
  • projects/claude-ui/src/components/workspace/WorkspaceRouteSurface.tsx
  • projects/claude-ui/src/components/workspace/WorkspaceSidebar.tsx
  • projects/claude-ui/src/components/workspace/WorkspaceStatus.tsx
  • projects/claude-ui/src/components/workspace/WorkspaceStatusContent.tsx
  • projects/claude-ui/src/components/workspace/sidebarAccountMenu.tsx
  • projects/claude-ui/src/components/workspace/workspaceLazySurfaces.tsx
  • projects/claude-ui/src/types/components/transcript.ts
  • projects/claude-ui/src/workspaceRoutes.ts

Verification Contract

pnpm verify:surface-migration-map validates:

  • manifest schema, owner, invariants, decision links, surface counts, and unsupported gap counts
  • every mapped surface has target categories, risk, source anchors, and verification commands
  • the Markdown surface table's ID, target categories, risk, and migration kind match tools/workspace-surface-migration-map.mjs
  • every source file and named symbol in tools/workspace-surface-migration-map.mjs still exists through TypeScript AST or JSON key/id checks where possible
  • this document contains every mapped surface ID, explicit gap ID, and manifest source path
  • WCP-013 built-in descriptor fixture counts and message/tool/activity/fallback IDs remain aligned with the map
  • current Settings metadata still exposes eight primary navigation sections, three Customize links, forty-nine search items, eleven settings hashes, three Customize views, and forty-four required render handles
  • message rendering order still keeps default text/error before appenders, protocol cards before artifacts/version controls/actions, read-only controls hidden, host-owned message callbacks present, generic tool fallback present, and protocol stack cards ordered activity, tool use, tool result, citation, interaction, limit, stop

The Markdown is the human-readable record; tools/workspace-surface-migration-map.mjs is the machine-readable checklist. Do not create a second migration table in a package root, generated docs folder, or copied README. This keeps no second documentation truth for WCP-014.