Uh oh!
There was an error while loading. Please reload this page.
build(storybook): typecheck stories + export coverage guard - #482
Merged
Conversation
Add tsconfig.storybook.json and wire typecheck:stories into the desktop typecheck script so tsc --noEmit covers story files. Story files were previously excluded from the @maka/ui tsc build and never type-checked: build-storybook uses Vite which strips types without checking. This meant a component could change its props and the story would silently keep using the old API. Fix three drift issues caught by the new typecheck: - toggle.stories.tsx: toggleMultiple -> multiple (Base UI renamed the prop; the story still used the old name) - settings-pages.stories.tsx: UsageSummary fixture fields updated to match the current interface (range/fromMs/toMs/requestCount/ errorCount -> totalRequests/totalCostUsd/totalTokens/etc) - onboarding.stories.tsx: stop mutating readonly AppSettings fields via spread-based fixture construction - maka-bridge.tsx: narrow the window cast so delete-on-optional and MakaGlobal assignability errors go away
Add a contract test that scans all story files and asserts each public UI component name (Button, Badge, Input, ..., Toolbar, ToastProvider) appears in at least one story. Catches the 'new component, no story' drift class without manual grep audits. Verified red/green: deleting toolbar.stories.tsx turns the test red (Toolbar missing), restoring it turns green.
…gs story
Replace { ...createDefaultSettings(), ...patch } as ReturnType<...>
with mergeSettings(createDefaultSettings(), patch) in the settings
story bridge mock. The real IPC handler uses mergeSettings for deep
merge and normalization of nested settings (webSearch, localMemory,
botChat). The shallow spread + type assertion could return settings
with undefined nested fields, diverging from production behavior.The previous tsconfig included entire package source trees (packages/ui/src, packages/core/src, etc), causing typecheck:stories to surface errors in main-process files that stories never import. It also missed .storybook/ (main.ts, preview.tsx). Narrow include to: .storybook, stories, src/global.d.ts, and packages/ui/stories. Add paths mapping so @maka/ui, @maka/core, etc resolve to source entry points without including full source trees. Verified: a type error in .storybook/preview.tsx turns typecheck:stories red; a type error in src/main/main.ts does not.
Review feedback: the test claimed 'every public UI component export' but used a hand-written allowlist and \bName\b regex that matched comments and unused imports as 'coverage'. - Rename to 'covers curated primitive components with stories' and add a message clarifying this is a curated baseline, not an exhaustive export check; typecheck:stories is the primary guard. - Match '<Name' (JSX tag) instead of \bName\b so only real JSX usage counts as coverage, not comments or import-only references. - Fix component names to match actual JSX tags: Dialog -> DialogRoot, Tabs -> TabsRoot, Select -> SelectRoot (stories use the Root variants).
Astro-Hanforce-pushed
the
opencode/storybook-drift-guards
branch
from
July 3, 2026 12:17
631ad9b to
d95b53cCompareWhen no maka property existed before the bridge was installed, cleanup set it to undefined instead of deleting it, leaving a visible 'maka' key with value undefined for subsequent bridgeless stories. Record hadPrevious and delete the key when it was absent.
The <Name regex is a text scan, not a JSX AST check: comments or strings containing the tag pattern would be false positives. Rename the test and message to 'textual smoke check' so the promise matches the implementation.
Astro-Han added a commit
that referenced
this pull request
Jul 3, 2026
5 CSS files (daily-review, health-center, permission-center, settings/connection, tool-stream) took main's format (@layer removal, indentation) and re-applied foreground alias replacement (40/50→muted-foreground, 60/70/80→foreground-secondary).
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 freeto 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.
Summary
Add two drift-prevention guards so Storybook stories stay in sync with production components: type-check stories with tsc, and a contract test asserting a curated set of primitive components has JSX usage in at least one story.
Why
Story files were excluded from the
@maka/uitsc build and never type-checked.build-storybookuses Vite, which strips types without checking them. This meant a component could change its props and the story would silently keep using the old API. There was also no guard against a curated component losing its story coverage.Scope
Changed:
apps/desktop/tsconfig.storybook.json(new) — a dedicated tsconfig that includes only story/config entries (.storybook,stories,packages/ui/stories,src/global.d.ts) withpathsmapping for workspace packages. Narrow enough that main-process type errors do not surface; broad enough to cover.storybook/preview.tsx.apps/desktop/package.json— addedtypecheck:storiesscript; wired storybook tsconfig into the existingtypecheckscript.apps/desktop/src/main/__tests__/storybook-baseline-contract.test.ts— new contract test: scans all story files and asserts each curated primitive component has JSX tag usage (<Name) in at least one story. Named "curated baseline" to be honest that it is not an exhaustive export check;typecheck:storiesis the primary drift guard.packages/ui/stories/toggle.stories.tsx— fixed real drift:toggleMultiple->multiple(Base UI renamed the prop; story still used the old name).apps/desktop/stories/settings/settings-pages.stories.tsx— fixed real drift:UsageSummaryfixture fields updated to match the current interface;mergeSettingsreplaces shallow spread + type assertion so the story bridge mock matches production IPC behavior.apps/desktop/stories/onboarding.stories.tsx— fixed type errors: stop mutating readonlyAppSettingsfields via spread-based fixture construction.apps/desktop/stories/maka-bridge.tsx— fixed type errors: narrow the window cast sodelete-on-optionalandMakaGlobalassignability errors go away.Not included:
test: 'todo'first).export *component). The curated baseline covers 24 primitive components;ChoiceCard,InputGroup,Item,SettingsSelect,SettingsSwitchare public exports without standalone stories but are out of scope for this PR.Verification
npm run -w @maka/desktop typecheckpasses (includes the new storybook tsconfig).npm run -w @maka/desktop build-storybookpasses.npm run -w @maka/desktop testpasses (1712 tests green)..storybook/preview.tsxturnstypecheck:storiesred; a type error insrc/main/main.tsdoes not.toolbar.stories.tsxturns the test red (Toolbarmissing); replacing<Toolbarwith a comment-only reference also turns it red (JSX match required, not word boundary).User-facing impact
None. Storybook tooling and test-only changes; no runtime or build output changes. The story fixture fixes (toggle, settings, onboarding) correct stale mock data but do not affect the rendered app.
Reviewer notes
toggleMultiple->multiple(Base UI prop rename),UsageSummaryfields (interface changed), readonlyAppSettingsmutation. These were silent because Vite strips types.<Name), not word boundaries, so comments and unused imports do not count as coverage. Component names match actual JSX tags (DialogRoot,TabsRoot,SelectRoot) rather than export names.tsconfig.storybook.jsonusespathsto resolve@maka/ui,@maka/core, etc. to source entry points, so tsc follows imports without including entire package source trees.mergeSettingsis used in the settings story bridge mock to match the real IPC handler's deep-merge behavior, replacing a shallow spread +asassertion that could return settings with undefined nested fields.