You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Make Astryx the sole component and design-system foundation of the desktop renderer.
This is not a compatibility-layer migration. The completed state has:
no @base-ui/react imports or dependencies;
no Streamdown;
no generic Maka primitive that duplicates an Astryx component;
no legacy component CSS or maka.legacy cascade layer;
no Tailwind dependency or utility bridge;
product-specific composition and state retained in Maka, built directly from the closest Astryx taxonomy.
The Astryx default theme, in light and dark mode, is the visual authority. The Phase 1 design package remains a loose composition reference; when it conflicts with Astryx-native rendering, Astryx wins.
This body supersedes the previous plan. Slice N always means a migration stage. PR #N always means a GitHub pull request. Do not use PR N as a synonym for a Slice. A Slice may use more than one flat PR only when each PR transfers a complete, independently buildable and reviewable ownership boundary.
First principles
Choose components by interaction taxonomy, not visual resemblance or old component names.
One component owns behavior, focus, ARIA, portal/top-layer behavior, and styling.
If an Astryx API differs, migrate consumers to the Astryx API and delete the replaced Maka/Base UI path in the same independently revertible cut.
Do not keep a generic compatibility wrapper merely to preserve a Base UI-shaped API.
Product state, data shaping, security, routing, runtime, IPC, and persistence remain Maka-owned.
Treat the published Astryx API and component model as a fixed migration constraint. When an existing Maka design cannot be expressed cleanly with Astryx, first redesign or remove that Maka behavior. Only an irreducible product invariant may remain as a narrowly scoped product-specific native or composed control. Do not recreate a missing generic primitive or compatibility API in Maka.
No new Tailwind utility usage in code touched by the remaining Slices.
Slice 4 is complete in #1678. The final compatibility cleanup for Slices 5–7 was merged in #1688.
Slice 8 is delivered as two flat PRs with independent behavior ownership: disclosures in #1711 and model selection/search in #1714. The remaining Toolbar, Item, Chip, SegmentedControl, Tabs, Button-row, and surface-composition work is assigned to Slices 9–11 by product interaction taxonomy rather than retained as generic shared wrappers.
Follow actual ownership dependencies. Rebase a ready branch when its real base changes; do not impose an unrelated time, file-count, queue-size, or worktree-count threshold.
Remaining Slices
Slice 4 — Form controls and consumer reclassification
Retire Maka's generic form-control system by reclassifying every consumer against the published Astryx component model:
when an old Maka interaction or visual treatment does not fit Astryx cleanly, redesign or remove that Maka behavior instead of emulating the old API, DOM, or styling;
when Astryx cannot express an irreducible product invariant, retain the smallest product-specific native or composed control, named for its product responsibility rather than as a generic primitive;
reclassify every ChoiceCard consumer by product intent; use RadioList or SelectableCard only when its native interaction matches, otherwise simplify the product design or retain a narrowly scoped product composition;
keep data validation, normalization, IPC boundaries, and persistence Maka-owned, while presenting their states through the closest supported Astryx composition;
keep page CSS responsible only for product layout; Astryx owns control chrome, focus appearance, disabled appearance, labels, descriptions, and error presentation.
Owns migration of every consumer away from the replaced generic Maka/Base UI form primitives, followed by deletion of those implementations, exports, stories, tests, focus recipes, and control chrome.
This Slice does not perform the final visual recomposition of Settings and module surfaces owned by Slice 10. It changes those consumers only as far as required to remove the retired generic form authorities cleanly.
Slice 8 — Shared disclosures and model selection
Transfer two remaining behavior-independent shared authorities before the product-surface cuts.
Tabs consumers → Slice 10 or 11 according to navigation, view-mode, filter, or workspace-tool intent.
Do not create generic Maka wrappers to preserve the retired APIs. Slice 12 remains deletion and proof, not the owner of migrations deferred from Slices 9–11.
Slice 9 — Conversation and Composer
Move the conversation surface onto direct Astryx composition:
Chat turns, response/tool/reasoning presentation, citations, status and actions;
artifact surface and conversation-owned disclosures;
streaming presentation and scroll anchoring;
empty, pending, interrupted, error, and long-content states.
Also owns:
migration of the artifact toolbar to Astryx Toolbar and reclassification of artifact listbox rows;
remaining conversation-side direct Base UI Button and raw-button seams;
deliberate classification of Composer mention, quote, attachment, revision, mode, retry, and media-trigger interactions;
correction of the task-ledger tree/treeitem semantic gap by adopting Astryx TreeList where its behavior fits, or by using honest list semantics;
direct evaluation of Astryx ChatLayout, ChatComposer, ChatComposerInput, ChatToolCalls, EmptyState, Spinner, and Kbd without compatibility wrappers;
inclusion of representative Chat and Composer states in the Storybook visual smoke manifest.
Keep stream pacing, runtime events, message identity, and scroll policy Maka-owned. Owns deletion of replaced chat/composer surface CSS and remaining Base UI behavior in the conversation subtree.
Slice 10 — Settings and Modules
Move Settings, onboarding forms, and module pages onto direct Astryx composition:
Providers, appearance, general, usage, permissions, memory, bots, data and remote access;
Skills, MCP, Plan Reminders, Daily Review, health and related module pages;
forms, cards, lists, tables, empty states, navigation, filters, status and actions;
all current module/settings Tabs consumers reclassified by product intent.
Also owns:
migration of remaining Item consumers away from the Base UI mergeProps/useRender seam, redesigning full-row button DOM and focus behavior against Astryx Item rather than preserving the old render API;
reclassification of Chip/status labels onto Astryx Token, Badge, StatusDot, Banner, or a narrowly named product-specific native composition;
migration of Base UI Segmented and settings/module Tabs consumers to Astryx SegmentedControl, TabList, Selector, SideNav, or another interaction-correct authority;
migration or explicit product-specific redesign of DataTable, EmptyState, Spinner, Skeleton, and loading/status surfaces;
migration of remaining Settings/MCP native <details> and BaseButton disclosure controls to Astryx Collapsible;
inclusion of Providers and representative Settings/module states in the Storybook visual smoke manifest.
Owns deletion of replaced settings*.css, module-pages/**, local row/card/list recipes, and remaining Base UI consumers in these surfaces.
Slice 11 — Shell and Navigation
Move shell chrome and navigation onto direct Astryx composition:
titlebar, SideNav, session navigation/history, project navigation and responsive shell;
command palette and search using Astryx CommandPalette, PowerSearch, Typeahead, Selector, or the closest semantic authority;
workspace workbar and remaining shell mode/navigation controls;
all shell Tabs consumers reclassified by product intent;
empty/loading/error shell states and keyboard routes.
Also owns:
reclassification of SessionSidebarNav and SessionHistoryList Base UI Button rows onto Astryx SideNavItem, TreeList, Item, Button, or narrowly scoped product-native composition;
migration of workspace tabs to Astryx TabList or Toolbar while keeping panel state and keepMounted policy Maka-owned;
evaluation of Astryx AppShell, Layout, SideNav, TopNav, List, Item, and TreeList as the shell composition authority;
a regression fix ensuring session-rename inputs retain Home, End, and Arrow key editing instead of bubbling into parent-list navigation;
removal of verified dead shell/sidebar/titlebar/shimmer CSS recipes and their pruning allowlist entries;
inclusion of real Shell/Nav states in the Storybook visual smoke manifest, backed by live Electron computed-style and hit-test evidence.
Owns shell host files, sidebar.css, shell-layout.css, search/command recipes, and remaining shell Base UI consumers.
Slice 12 — Base UI and legacy cleanup
This is deletion and proof, not a place to perform migrations omitted by earlier Slices.
prove all Base UI imports and consumers are gone;
remove @base-ui/react from manifests and lockfile dependency closure;
delete frozen compatibility exports and dead generic Maka primitives;
delete replaced component CSS, legacy tokens, stale comments, and maka.legacy;
remove the declared-subtree migration harness and migration-only contracts after the final surface comparison is accepted;
regenerate third-party notices and run dependency/dead-code audits.
Migration-period contracts that explicitly require Base UI components are not permanent exceptions. Replace them with product-behavior contracts in their owning Slice.
Before removing the dependency, prove that:
no production source imports @base-ui/react, including direct Button imports and Item/Chip mergeProps or useRender seams;
no Base UI requirement remains in source-shape contracts, Stories, comments, or allowlists;
@base-ui/react is absent from both workspace manifests, the lockfile dependency closure, and third-party notices;
every surviving native control is narrowly product-specific and documented by interaction responsibility rather than by compatibility with a retired generic API.
If this Slice is large, an earlier Slice under-removed. Move that ownership transfer back to Slice 4 or 8–11 rather than hiding migration work in cleanup.
Slice 13 — Tailwind removal
replace remaining renderer utility classes with Astryx layout, spacing, typography, and StyleX/theme APIs;
remove @import "tailwindcss";
remove @theme inline, @source, and the utility token bridge;
remove Tailwind packages, configuration, generated assumptions, and utility-governance contracts;
prove the production renderer and Storybook build without Tailwind.
Tabs and navigation
The old generic Maka Tabs API is not migrated one-to-one onto Astryx TabList.
Astryx 0.1.9 TabList is navigation: <nav> plus aria-current. The current Maka primitive is a panel-tabs system: tablist, tab, tabpanel, aria-selected, and tab/panel relationships. Wrapping the navigation primitive to reproduce panel semantics would create two behavior authorities.
Instead, Slice 10 and Slice 11 must reclassify every current Tabs consumer by product intent:
page or subpage navigation → Astryx TabList, SideNav, or TopNav;
view-mode switching → Astryx SegmentedControl;
category/filter selection → Astryx Selector or another selection primitive;
workspace tool switching → Astryx Toolbar or the closest explicit control;
a remaining true panel-tabs interaction → first land or adopt the missing semantic capability in Astryx, then migrate it.
The goal is to remove the generic Maka Tabs abstraction by eliminating or correctly reclassifying its consumers, not to preserve its old API.
Slice contract
Every remaining Slice must:
start from current main;
transfer a complete ownership boundary;
migrate every consumer in scope;
delete the replaced implementation, CSS, tests, stories, and exports in the same independently revertible cut;
remain independently buildable, reviewable, revertible, and mergeable;
add no Base UI or Tailwind usage;
preserve product outcomes, data correctness, accessibility, required keyboard workflows, light/dark behavior, and locale behavior;
treat old DOM shape, visual chrome, focus choreography, and interaction details as non-contractual unless they are demonstrated product invariants;
document intentional product-design changes and update behavior tests to assert the resulting user journey rather than the retired component structure;
declare every intentional visual subtree change;
keep all changes outside declared subtrees at zero;
pass hit-test on all five routes;
use Storybook for missing visual states and one live Electron screenshot for user-visible surface changes;
run formatting, lint, build, typecheck, relevant unit tests, representative E2E, visual contract, hit-test, and alignment audit;
receive an independent review before merge.
Split a Slice only when each resulting PR has a complete ownership boundary and can be independently reviewed and merged. Do not split by file count or to keep parallel implementations alive.
Coordination
The root checkout stays on clean main; each piece of work uses one branch/worktree and one PR.
Avoid concurrent ownership of:
packages/ui/src/index.ts;
packages/ui/src/ui.tsx;
apps/desktop/src/renderer/app-shell.tsx;
apps/desktop/src/renderer/app-shell-overlays.tsx;
apps/desktop/src/renderer/styles.css;
cascade and migration-harness files.
Slice 11 owns shell host files. Another Slice may change them only when the required behavior cannot be delivered through an existing call contract, and must document why.
Final acceptance
The issue closes only when all of the following are true:
rg '@base-ui/react' packages/ui/src apps/desktop/src returns no results;
@base-ui/react is absent from every manifest and the lockfile dependency closure;
Streamdown remains absent;
every generic renderer primitive is either an Astryx export or a genuinely product-specific composition;
no Astryx component is wrapped together with Base UI;
no parallel theme, icon, overlay, focus, motion, or component system remains;
conversation/composer, settings/modules, and shell use the Astryx default theme and Astryx-native component composition;
maka.legacy, replaced component CSS, legacy tokens, and the migration harness are deleted;
Tailwind, @import "tailwindcss", @theme inline, and renderer utility-source directives are deleted;
full CI, renderer E2E, visual contract, hit-test, alignment audit, Storybook smoke, light/dark, locale, and accessibility checks pass;
Maka titlebar, security, routing, runtime, IPC, persistence, and deterministic test boundaries remain intact.
Outcome
Make Astryx the sole component and design-system foundation of the desktop renderer.
This is not a compatibility-layer migration. The completed state has:
@base-ui/reactimports or dependencies;maka.legacycascade layer;The Astryx default theme, in light and dark mode, is the visual authority. The Phase 1 design package remains a loose composition reference; when it conflicts with Astryx-native rendering, Astryx wins.
This body supersedes the previous plan.
Slice Nalways means a migration stage.PR #Nalways means a GitHub pull request. Do not usePR Nas a synonym for a Slice. A Slice may use more than one flat PR only when each PR transfers a complete, independently buildable and reviewable ownership boundary.First principles
Current state
maka.legacyownershipSlice 4 is complete in #1678. The final compatibility cleanup for Slices 5–7 was merged in #1688.
Slice 8 is delivered as two flat PRs with independent behavior ownership: disclosures in #1711 and model selection/search in #1714. The remaining Toolbar, Item, Chip, SegmentedControl, Tabs, Button-row, and surface-composition work is assigned to Slices 9–11 by product interaction taxonomy rather than retained as generic shared wrappers.
Dependency graph
flowchart LR S3["Slice 3<br>Atoms ✓"] --> S4["Slice 4<br>Form controls + reclassification"] S4 --> S8["Slice 8<br>Remaining shared primitives"] S5["Slice 5<br>Floating kernel ✓"] --> S8 S6["Slice 6<br>Floating components ✓"] --> S8 S8 --> S9["Slice 9<br>Conversation + Composer"] S8 --> S10["Slice 10<br>Settings + Modules"] S8 --> S11["Slice 11<br>Shell + Navigation"] S7["Slice 7<br>Markdown ✓"] --> S9 S9 --> S12["Slice 12<br>Base UI + legacy cleanup"] S10 --> S12 S11 --> S12 S12 --> S13["Slice 13<br>Tailwind removal"]Follow actual ownership dependencies. Rebase a ready branch when its real base changes; do not impose an unrelated time, file-count, queue-size, or worktree-count threshold.
Remaining Slices
Slice 4 — Form controls and consumer reclassification
Retire Maka's generic form-control system by reclassifying every consumer against the published Astryx component model:
Owns migration of every consumer away from the replaced generic Maka/Base UI form primitives, followed by deletion of those implementations, exports, stories, tests, focus recipes, and control chrome.
This Slice does not perform the final visual recomposition of Settings and module surfaces owned by Slice 10. It changes those consumers only as far as required to remove the retired generic form authorities cleanly.
Slice 8 — Shared disclosures and model selection
Transfer two remaining behavior-independent shared authorities before the product-surface cuts.
Flat PR A, #1711:
Flat PR B, #1714:
The post-Slice-8 audit reclassified the other former “shared primitive” candidates by product ownership:
Do not create generic Maka wrappers to preserve the retired APIs. Slice 12 remains deletion and proof, not the owner of migrations deferred from Slices 9–11.
Slice 9 — Conversation and Composer
Move the conversation surface onto direct Astryx composition:
Also owns:
tree/treeitemsemantic gap by adopting Astryx TreeList where its behavior fits, or by using honest list semantics;Keep stream pacing, runtime events, message identity, and scroll policy Maka-owned. Owns deletion of replaced chat/composer surface CSS and remaining Base UI behavior in the conversation subtree.
Slice 10 — Settings and Modules
Move Settings, onboarding forms, and module pages onto direct Astryx composition:
Also owns:
mergeProps/useRenderseam, redesigning full-row button DOM and focus behavior against Astryx Item rather than preserving the old render API;<details>and BaseButton disclosure controls to Astryx Collapsible;Owns deletion of replaced
settings*.css,module-pages/**, local row/card/list recipes, and remaining Base UI consumers in these surfaces.Slice 11 — Shell and Navigation
Move shell chrome and navigation onto direct Astryx composition:
Also owns:
keepMountedpolicy Maka-owned;Owns shell host files,
sidebar.css,shell-layout.css, search/command recipes, and remaining shell Base UI consumers.Slice 12 — Base UI and legacy cleanup
This is deletion and proof, not a place to perform migrations omitted by earlier Slices.
@base-ui/reactfrom manifests and lockfile dependency closure;maka.legacy;Migration-period contracts that explicitly require Base UI components are not permanent exceptions. Replace them with product-behavior contracts in their owning Slice.
Before removing the dependency, prove that:
@base-ui/react, including direct Button imports and Item/ChipmergePropsoruseRenderseams;@base-ui/reactis absent from both workspace manifests, the lockfile dependency closure, and third-party notices;If this Slice is large, an earlier Slice under-removed. Move that ownership transfer back to Slice 4 or 8–11 rather than hiding migration work in cleanup.
Slice 13 — Tailwind removal
@import "tailwindcss";@theme inline,@source, and the utility token bridge;Tabs and navigation
The old generic Maka Tabs API is not migrated one-to-one onto Astryx
TabList.Astryx 0.1.9
TabListis navigation:<nav>plusaria-current. The current Maka primitive is a panel-tabs system:tablist,tab,tabpanel,aria-selected, and tab/panel relationships. Wrapping the navigation primitive to reproduce panel semantics would create two behavior authorities.Instead, Slice 10 and Slice 11 must reclassify every current Tabs consumer by product intent:
TabList,SideNav, orTopNav;SegmentedControl;Selectoror another selection primitive;Toolbaror the closest explicit control;The goal is to remove the generic Maka Tabs abstraction by eliminating or correctly reclassifying its consumers, not to preserve its old API.
Slice contract
Every remaining Slice must:
main;Split a Slice only when each resulting PR has a complete ownership boundary and can be independently reviewed and merged. Do not split by file count or to keep parallel implementations alive.
Coordination
The root checkout stays on clean
main; each piece of work uses one branch/worktree and one PR.Avoid concurrent ownership of:
packages/ui/src/index.ts;packages/ui/src/ui.tsx;apps/desktop/src/renderer/app-shell.tsx;apps/desktop/src/renderer/app-shell-overlays.tsx;apps/desktop/src/renderer/styles.css;Slice 11 owns shell host files. Another Slice may change them only when the required behavior cannot be delivered through an existing call contract, and must document why.
Final acceptance
The issue closes only when all of the following are true:
rg '@base-ui/react' packages/ui/src apps/desktop/srcreturns no results;@base-ui/reactis absent from every manifest and the lockfile dependency closure;maka.legacy, replaced component CSS, legacy tokens, and the migration harness are deleted;@import "tailwindcss",@theme inline, and renderer utility-source directives are deleted;References