Uh oh!
There was an error while loading. Please reload this page.
refactor(ui): align chat chrome with Astryx message composition - #1768
Merged
Conversation
Remove product chrome around ChatReasoning (no reasoning copy button) and route user/assistant meta through ChatMessageMetadata while keeping product actions and hover-gate behavior.
Reasoning, tool calls, and product trow fallbacks now share one trigger language in the turn body: supporting size, body family, medium weight, 14px/0.75rem chevron, overlay-hover, and trailing chevron alignment.
Row-level tool resultDetail mounts without Astryx's group grid motion; wrap it (and product trow bodies) so expand matches ChatReasoning. Ordinary text/diff/terminal wells render through CodeBlock per Astryx ChatToolCalls guidance; live stream, PTY, and rich cards stay product-owned.
Align failed tool detail with Astryx ChatToolCalls: status=error + errorMessage on the row, CodeBlock/panel as resultDetail. Keep the product sandbox-denial warning banner only.
Drop the terminal "失败 · 退出码" footer and destructive CodeBlock border; keep Astryx neutral CodeBlock. Pin chat tool/reasoning/trow triggers to default cursor with no overlay hover wash.
Chat tool/reasoning/trow triggers restore overlay-hover feedback while cursor stays default (native-cursor convention).
Remove narrative and superseding-PR comments from the Astryx chat alignment path; keep only non-obvious constraints (redaction, tokenizer, cursor convention).
…o ToolTrow Remove ToolErrorDetails, ordinary Alert banner branch, unused copy/CSS, and assert production ToolTrow + CodeBlock wells instead of the boxed ToolActivity path.
Resolve chat chrome conflicts: keep ToolTrow failure contracts and pure ChatReasoning; use Astryx Banner for sandbox-only denials.
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 1, 2026
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
The smoke this branch wired into CI verified 12 stories out of 141. The manifest is curated on purpose — its 51 checks assert layout geometry across three viewports and both colour schemes, which is expensive and only worth paying for where layout actually varies. But that left ~130 stories verified by nothing: build-storybook bundles a story without ever mounting it, so a render that throws, a play function that rejects, or a console error all ship green. "Storybook can no longer rot unobserved" was not true as written. The catalog pass renders every unmanifested story once at wide/light and asks one question: does it mount and finish its play function without errors. It reuses smokeStory, so it already catches storyThrewException, playFunctionThrewException, unhandledErrorsWhilePlaying, console errors and empty roots. Four pages run concurrently: 124 renders in ~35s, against 217s serial. The manifest jobs stay serial and unbaselined — they measure geometry, which is why they pin a viewport. The first run found seven already-broken stories, which is the argument for the pass. Each is a play function whose selector went stale during the Astryx migration with nothing executing it — model-picker looks for the exact placeholder '搜索模型' while shared-ui-copy.ts now reads '搜索模型…'; ask-user-question wants an accessible name user-question-prompt no longer exposes; tool-activity predates the #1768 disclosure dialect. They span four components and each needs that component's current DOM to fix, which is a different change from wiring up the guard. So they go in storybook-catalog-baseline.json, keyed by story id with the reason — the same shape as check-dead-css-baseline.json. Unlisted failures fail the build. A listed story that starts passing ALSO fails, demanding its removal; without that a baseline quietly turns into a permanent exemption, and the list stops being a to-do.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
check-dead-css was red on main: `.astryx-collapsible-trigger` is rendered by Astryx's own Collapsible and targeted by chat-message.css to give reasoning and tool disclosures one trigger dialect (#1768), but it never appears as a className literal, so the scanner counted it dead. It joins the astryx-button / astryx-badge entries already in DYNAMIC_STYLE_HOOKS. The regression stayed invisible because the guard only ran under `check:release`. It now runs in the typecheck job alongside knip, which is the same class of source-scanning governance. Storybook had no CI coverage of rendering at all. Story typechecking already rides along in `typecheck` via tsconfig.storybook.json, but the static build and the 51-check render/play smoke ran only when someone remembered them locally. Both now run at the end of the e2e job, next to the alignment audit. That job drives Electron through `_electron.launch`, which uses Electron's own binary and never downloads a browser; the smoke calls `chromium.launch()`, so Chromium is installed explicitly. Locally the build takes 7s and the smoke 17s cold, which is noise next to the Electron suite. The e2e route also had to widen. It keys on direct workspace changes so backend work does not drag the renderer suites along, and that stays. But .storybook/preview.tsx reads THEME_PALETTES straight out of packages/core, so a core change could break the Storybook build while routing away from the only job that builds it.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
The smoke this branch wired into CI verified 12 stories out of 141. The manifest is curated on purpose — its 51 checks assert layout geometry across three viewports and both colour schemes, which is expensive and only worth paying for where layout actually varies. But that left ~130 stories verified by nothing: build-storybook bundles a story without ever mounting it, so a render that throws, a play function that rejects, or a console error all ship green. "Storybook can no longer rot unobserved" was not true as written. The catalog pass renders every unmanifested story once at wide/light and asks one question: does it mount and finish its play function without errors. It reuses smokeStory, so it already catches storyThrewException, playFunctionThrewException, unhandledErrorsWhilePlaying, console errors and empty roots. Four pages run concurrently: 124 renders in ~35s, against 217s serial. The manifest jobs stay serial and unbaselined — they measure geometry, which is why they pin a viewport. The first run found seven already-broken stories, which is the argument for the pass. Each is a play function whose selector went stale during the Astryx migration with nothing executing it — model-picker looks for the exact placeholder '搜索模型' while shared-ui-copy.ts now reads '搜索模型…'; ask-user-question wants an accessible name user-question-prompt no longer exposes; tool-activity predates the #1768 disclosure dialect. They span four components and each needs that component's current DOM to fix, which is a different change from wiring up the guard. So they go in storybook-catalog-baseline.json, keyed by story id with the reason — the same shape as check-dead-css-baseline.json. Unlisted failures fail the build. A listed story that starts passing ALSO fails, demanding its removal; without that a baseline quietly turns into a permanent exemption, and the list stops being a to-do.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
check-dead-css was red on main: `.astryx-collapsible-trigger` is rendered by Astryx's own Collapsible and targeted by chat-message.css to give reasoning and tool disclosures one trigger dialect (#1768), but it never appears as a className literal, so the scanner counted it dead. It joins the astryx-button / astryx-badge entries already in DYNAMIC_STYLE_HOOKS. The regression stayed invisible because the guard only ran under `check:release`. It now runs in the typecheck job alongside knip, which is the same class of source-scanning governance. Storybook had no CI coverage of rendering at all. Story typechecking already rides along in `typecheck` via tsconfig.storybook.json, but the static build and the 51-check render/play smoke ran only when someone remembered them locally. Both now run at the end of the e2e job, next to the alignment audit. That job drives Electron through `_electron.launch`, which uses Electron's own binary and never downloads a browser; the smoke calls `chromium.launch()`, so Chromium is installed explicitly. Locally the build takes 7s and the smoke 17s cold, which is noise next to the Electron suite. The e2e route also had to widen. It keys on direct workspace changes so backend work does not drag the renderer suites along, and that stays. But .storybook/preview.tsx reads THEME_PALETTES straight out of packages/core, so a core change could break the Storybook build while routing away from the only job that builds it.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
The smoke this branch wired into CI verified 12 stories out of 141. The manifest is curated on purpose — its 51 checks assert layout geometry across three viewports and both colour schemes, which is expensive and only worth paying for where layout actually varies. But that left ~130 stories verified by nothing: build-storybook bundles a story without ever mounting it, so a render that throws, a play function that rejects, or a console error all ship green. "Storybook can no longer rot unobserved" was not true as written. The catalog pass renders every unmanifested story once at wide/light and asks one question: does it mount and finish its play function without errors. It reuses smokeStory, so it already catches storyThrewException, playFunctionThrewException, unhandledErrorsWhilePlaying, console errors and empty roots. Four pages run concurrently: 124 renders in ~35s, against 217s serial. The manifest jobs stay serial and unbaselined — they measure geometry, which is why they pin a viewport. The first run found seven already-broken stories, which is the argument for the pass. Each is a play function whose selector went stale during the Astryx migration with nothing executing it — model-picker looks for the exact placeholder '搜索模型' while shared-ui-copy.ts now reads '搜索模型…'; ask-user-question wants an accessible name user-question-prompt no longer exposes; tool-activity predates the #1768 disclosure dialect. They span four components and each needs that component's current DOM to fix, which is a different change from wiring up the guard. So they go in storybook-catalog-baseline.json, keyed by story id with the reason — the same shape as check-dead-css-baseline.json. Unlisted failures fail the build. A listed story that starts passing ALSO fails, demanding its removal; without that a baseline quietly turns into a permanent exemption, and the list stops being a to-do.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
check-dead-css was red on main: `.astryx-collapsible-trigger` is rendered by Astryx's own Collapsible and targeted by chat-message.css to give reasoning and tool disclosures one trigger dialect (#1768), but it never appears as a className literal, so the scanner counted it dead. It joins the astryx-button / astryx-badge entries already in DYNAMIC_STYLE_HOOKS. The regression stayed invisible because the guard only ran under `check:release`. It now runs in the typecheck job alongside knip, which is the same class of source-scanning governance. Storybook had no CI coverage of rendering at all. Story typechecking already rides along in `typecheck` via tsconfig.storybook.json, but the static build and the 51-check render/play smoke ran only when someone remembered them locally. Both now run at the end of the e2e job, next to the alignment audit. That job drives Electron through `_electron.launch`, which uses Electron's own binary and never downloads a browser; the smoke calls `chromium.launch()`, so Chromium is installed explicitly. Locally the build takes 7s and the smoke 17s cold, which is noise next to the Electron suite. The e2e route also had to widen. It keys on direct workspace changes so backend work does not drag the renderer suites along, and that stays. But .storybook/preview.tsx reads THEME_PALETTES straight out of packages/core, so a core change could break the Storybook build while routing away from the only job that builds it.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
The smoke this branch wired into CI verified 12 stories out of 141. The manifest is curated on purpose — its 51 checks assert layout geometry across three viewports and both colour schemes, which is expensive and only worth paying for where layout actually varies. But that left ~130 stories verified by nothing: build-storybook bundles a story without ever mounting it, so a render that throws, a play function that rejects, or a console error all ship green. "Storybook can no longer rot unobserved" was not true as written. The catalog pass renders every unmanifested story once at wide/light and asks one question: does it mount and finish its play function without errors. It reuses smokeStory, so it already catches storyThrewException, playFunctionThrewException, unhandledErrorsWhilePlaying, console errors and empty roots. Four pages run concurrently: 124 renders in ~35s, against 217s serial. The manifest jobs stay serial and unbaselined — they measure geometry, which is why they pin a viewport. The first run found seven already-broken stories, which is the argument for the pass. Each is a play function whose selector went stale during the Astryx migration with nothing executing it — model-picker looks for the exact placeholder '搜索模型' while shared-ui-copy.ts now reads '搜索模型…'; ask-user-question wants an accessible name user-question-prompt no longer exposes; tool-activity predates the #1768 disclosure dialect. They span four components and each needs that component's current DOM to fix, which is a different change from wiring up the guard. So they go in storybook-catalog-baseline.json, keyed by story id with the reason — the same shape as check-dead-css-baseline.json. Unlisted failures fail the build. A listed story that starts passing ALSO fails, demanding its removal; without that a baseline quietly turns into a permanent exemption, and the list stops being a to-do.
Astro-Han added a commit
that referenced
this pull request
Aug 1, 2026
…ory per surface (#1783) * ci: guard dead CSS and Storybook rendering check-dead-css was red on main: `.astryx-collapsible-trigger` is rendered by Astryx's own Collapsible and targeted by chat-message.css to give reasoning and tool disclosures one trigger dialect (#1768), but it never appears as a className literal, so the scanner counted it dead. It joins the astryx-button / astryx-badge entries already in DYNAMIC_STYLE_HOOKS. The regression stayed invisible because the guard only ran under `check:release`. It now runs in the typecheck job alongside knip, which is the same class of source-scanning governance. Storybook had no CI coverage of rendering at all. Story typechecking already rides along in `typecheck` via tsconfig.storybook.json, but the static build and the 51-check render/play smoke ran only when someone remembered them locally. Both now run at the end of the e2e job, next to the alignment audit. That job drives Electron through `_electron.launch`, which uses Electron's own binary and never downloads a browser; the smoke calls `chromium.launch()`, so Chromium is installed explicitly. Locally the build takes 7s and the smoke 17s cold, which is noise next to the Electron suite. The e2e route also had to widen. It keys on direct workspace changes so backend work does not drag the renderer suites along, and that stays. But .storybook/preview.tsx reads THEME_PALETTES straight out of packages/core, so a core change could break the Storybook build while routing away from the only job that builds it. * docs(storybook): drop the Astryx showcase and legacy-token stories Eleven stories documented something other than this product. Five were straight Astryx pass-throughs. Button, Badge and Astryx Atoms render re-exports from packages/ui/src/index.ts; Menu and Dialog import @astryxdesign/core/DropdownMenu, /Dialog and /Layout directly. Astryx publishes its own Storybook for all of them, so ours could only ever be a staler copy. Six were catalogues of the token layer #1565 is deleting. Typography, Elevation, Layering, Palette Matrix and Spacing were last touched before the first Astryx commit; Design System/Tokens is newer but documents the same set. All of them hand-render --shadow-minimal, --border-strong and --font-sans through inline styles, under a namespace that presents them as current truth. Rewriting them against Astryx tokens now would mean writing them twice, and once the token contract is settled the useful artifact is one Maka/Astryx integration story that can act as an oracle for the migration — not six generic catalogues that duplicate upstream. Kept: Primitives/Toast wraps Maka's own toast.tsx (the toast.confirm() queue) and product-smoke-manifest.json pins primitives-toast--confirm-queued; Primitives/StatTile covers a Maka primitive. Design System/Icons, Animation Catalog and Interaction States also reference legacy variables, but what they document — the Maka icon set, Maka motion tokens, interaction states — outlives the token rename, so they move with it rather than out. Storybook still builds and the smoke still passes its 51 render/play checks. * docs(storybook): stop claiming a retired test enforces the fidelity convention FIDELITY.md described `story-annotation-contract.test.ts` as the thing that checks every product story carries a `// Real path:` sentence, and spent a paragraph on how it derives its file list and refuses to skip exports it cannot classify. #1724 deleted that test with the rest of the source-scanning contract suite. A document that promises enforcement nobody runs is worse than one that admits there is none — it tells reviewers the check already happened. The convention itself is worth keeping, so it now says plainly that it is a review convention and that it decays like one. It had already decayed: AstryxNativeConversation was the one product story with no annotation. It is reachable — a long session accumulates reasoning, tool calls and prose, and an image can sit staged in the composer — but it stacks those states deliberately, which FIDELITY.md requires a story to say out loud. Its comment now says both. Every `Product/*` story carries the sentence again; the remaining gaps are all `Primitives/*` and `Design System/*`, which the document exempts. * docs(renderer): correct the Astryx tailwind-theme.css note The header said tailwind-theme.css stays out "until Tailwind leaves", which has it backwards. That file's own header calls it a Tailwind Bridge: it maps Astryx tokens onto Tailwind v4 @theme variables so utilities resolve against the theme. It is only useful while Tailwind is present, and the slice in question deletes Tailwind — so it should never be imported at all. Anyone reading the old note while planning that slice would go looking for an import that must not happen. Also corrects the slice number: Tailwind removal is Slice 13, not 12, and #1565 asks that "PR N" never be used as a synonym for a slice. * docs(storybook): apply the deletion rule to the retained motion and state stories The earlier cut used the wrong test. It asked "is this Maka's own?" and kept whatever answered yes. The question that matters is whether Astryx already owns the domain — if it does, a Maka catalogue of the same thing is a parallel vocabulary being documented as the contract, which is exactly what the six deleted token stories were. Animation Catalog failed that test. Its DurationScale and EasingScale presented --duration-quick/base/emphasized/large and the four --ease-* tokens as the motion scale, while the Astryx theme already ships --duration-fast/medium/slow. Both are gone. What remains is the spinner and the streaming shimmer — load-bearing, not decorative, and they outlive the token rename — so the file is now Design System/Functional Motion, which is what it actually shows. Interaction States failed it too, in the part nobody flagged: ButtonStates, NeutralButtonStates and SolidButtonStates are state matrices for Astryx's Button, the same component whose Primitives/Button story this branch already deleted. ListRowStates stays, and it is the reason the file stays: it compares hover and focus across two DIFFERENT row components — Astryx's side-nav item and its list item — as the sidebar composes them. session-list-panel.stories.tsx owns SessionListPanel's own states; nothing else covers the seam between the two. The file is now Design System/Composite Row States. Design System/* is left holding Icons and Functional Motion — the Maka icon set, the brand mark, and two functional animations — plus that one cross-component seam. Nothing in it catalogues a token scale any more. * ci: enforce the mechanical half of the story fidelity convention The previous commit had FIDELITY.md admit that nothing checks the `// Real path:` annotations. That was honest but it was the wrong repair: presence of the sentence is mechanically decidable, and this branch had just proved review does not hold that line — chat-surface.stories.tsx reached thirteen stories with twelve annotations and nobody noticed until a script counted them. So the convention now splits along what a machine can decide. Existence is checked by scripts/check-story-annotations.mjs in CI; truth stays with the reviewer, where it has to stay — a schema is satisfied by a plausible lie just as easily. This is not a revival of story-annotation-contract.test.ts. #1724 was right to delete 149 tests that read source text and charged every refactor a rewrite of its own guards, and it explicitly kept the fast scripts/check-*.mjs commands for non-cosmetic invariants. This is one of those: ~110 lines, no build, runs beside check-dead-css in the typecheck job. It keeps the one property of the retired test that mattered: it fails on any top-level export it cannot classify rather than skipping it, because a guard that ignores what it cannot parse passes *because* it did not understand. It also fails if .storybook/main.ts stops loading a directory it scans, so a story tree cannot drift out of coverage. Eight tests cover both, including the case that caught a real bug while writing this: both story roots end in `stories`, so the config check originally matched only the last path segment and stayed green when either root was removed. * ci(storybook): render the whole catalog, not just the manifest The smoke this branch wired into CI verified 12 stories out of 141. The manifest is curated on purpose — its 51 checks assert layout geometry across three viewports and both colour schemes, which is expensive and only worth paying for where layout actually varies. But that left ~130 stories verified by nothing: build-storybook bundles a story without ever mounting it, so a render that throws, a play function that rejects, or a console error all ship green. "Storybook can no longer rot unobserved" was not true as written. The catalog pass renders every unmanifested story once at wide/light and asks one question: does it mount and finish its play function without errors. It reuses smokeStory, so it already catches storyThrewException, playFunctionThrewException, unhandledErrorsWhilePlaying, console errors and empty roots. Four pages run concurrently: 124 renders in ~35s, against 217s serial. The manifest jobs stay serial and unbaselined — they measure geometry, which is why they pin a viewport. The first run found seven already-broken stories, which is the argument for the pass. Each is a play function whose selector went stale during the Astryx migration with nothing executing it — model-picker looks for the exact placeholder '搜索模型' while shared-ui-copy.ts now reads '搜索模型…'; ask-user-question wants an accessible name user-question-prompt no longer exposes; tool-activity predates the #1768 disclosure dialect. They span four components and each needs that component's current DOM to fix, which is a different change from wiring up the guard. So they go in storybook-catalog-baseline.json, keyed by story id with the reason — the same shape as check-dead-css-baseline.json. Unlisted failures fail the build. A listed story that starts passing ALSO fails, demanding its removal; without that a baseline quietly turns into a permanent exemption, and the list stops being a to-do. * test(storybook): delete the broken stories instead of baselining them The catalog pass found seven stories whose play functions had gone stale during the Astryx migration. The previous commit recorded them in a baseline so the guard could land without also fixing four components. Deleting them is the better answer: a story that has not verified anything since the migration is not coverage waiting to be restored, and the states they claimed to cover are either already covered elsewhere or were asserting behaviour rather than appearance. model-picker Search / NoResults filtering the catalog; the empty result is EmptyCatalog's job tool-activity DisclosureInteraction aria-expanded, computed display, hit-area width and chevron centring — geometry that audit-alignment.mjs and e2e own ask-user-question OtherAnswerSelected typing into the free-text answer settings-pages WebSearch/Voice ×3 provider round-trips reaching a status text Three more went with them under the same rule — a story earns its place only if someone opens it to make a visual judgement that no other story supports: model-picker Pending Default with the control disabled tool-activity CopyFeedback same fixture as ErrorsAndPermissionDenied plus a transient label tool-activity FileDiffAndWebSearch denseMixedResultItems already contains all three of its items, expanded So storybook-catalog-baseline.json and the reconcile step are gone with them. Without known-broken entries the catalog pass is just "every story renders", and a future breakage has two honest options — fix it or delete it — rather than a third that defers both. 136 stories → 126; the smoke now runs 51 manifest checks and 114 catalog renders in ~64s with nothing exempted. * test(storybook): keep one story per surface, drop the state enumerations 126 stories down to 58. The rule: a story earns its place only if someone opens it to make a visual judgement no other story supports. In practice that leaves, per surface, the densest reachable state — plus an empty state where the layout genuinely differs, plus whatever product-smoke-manifest.json pins. What went: state enumerations SearchModal's Loading / NoResults / Error / Blocked next to Results; onboarding's four gate variants of one hero; provider-settings' Loading / LoadError / Empty behaviour, not paint CommandPaletteKeyboardFocusedSelection, RowActions, RowMenuOpen — interaction the E2E suite owns states contained by Usage and UsageEmpty under UsageRequestsPopulated; a denser sibling Memory under MemoryPopulated; app-shell's PlanModeActive and SwarmModeActive; tool-activity's StatusOverview, TerminalAndLiveOutput and SubagentAndExplore, all inside denseMixedResultItems duplicated elsewhere app-shell's MarkdownCore against markdown.stories.tsx Every story the manifest pins survives, including the eight module-hubs entries and primitives-toast--confirm-queued. Deleting stories orphans their fixtures, and tsconfig.storybook.json does not set noUnusedLocals, so nothing would have reported them. Compiling once with the flag on found fourteen — bridges, settings fixtures, voice capture helpers — and they go too. Two guards caught mistakes made while doing this, which is the argument for having wired them up: validateCoverageManifest rejected a build after a regex with a shared name prefix took ExtensionsSkillsInstalled out along with ExtensionsSkills, and check-story-annotations rejected the next one after a cleanup pass ate the `// Real path:` line above Models. The catalog pass is now 47 renders instead of 114, and the whole smoke runs in 34s instead of 64s. * fix(storybook): restore the three states the prune should not have cut Three of the cuts failed the retention rule they were made under — "keep the state no other story supports" — and an independent review of the branch caught all three. Palette Matrix was dropped as a token catalog Astryx now owns. It is not one: THEME_PALETTES is a product feature, the palettes a user picks in 设置 → 外观, and the catalog pass renders wide/light/default only. Ten of the eleven had no oracle at all. The file's header now records why the other five token stories still went, since "Astryx already owns this domain" was the wrong reason for all of them — maka-tokens.css is still the single authority and dies with Slice 13; a table of var names is simply low review value with a short life. Permission Center kept the collapsed state and cut the expanded one, which is backwards: the capability layers grid and guidance block only exist once diagnostics are expanded, and the deleted story's own comment says that is where the last overflow bug was hiding. Everything the collapsed story showed is still on screen in the expanded one, so this stays one story. VoicePermissionDenied comes back because the surviving Voice story is idle and the page's only error surface had no coverage anywhere — the E2E suite checks fields and persistence, not capture outcomes. It comes back without the 120-line MediaRecorder decorator the old story carried: permissionSnapshot already reports microphone `denied` on darwin and runCaptureSmoke returns on that snapshot before it ever reaches getUserMedia, so the real path needs no browser mocking. The catalog pass then failed the restored story immediately, for the same reason the originals rotted: the result lives in one of six `[role="status"]` regions and `querySelector` had picked an empty one. Also drops two doc comments the prune orphaned, which now described stories that no longer exist. * fix(ci): close the holes in the story-annotation guard The guard claimed to fail on anything it could not classify. Review found five inputs where it did not, each now covered by a test: - `.storybook/main.ts` loads `*.stories.@(ts|tsx)`; the scanner only opened `.stories.tsx`, so a `.ts` story was never read at all. - `export { Story }` and `export async function Story()` reach the browser as stories and matched nothing, so they passed in silence — the exact failure the "fail on what you cannot parse" rule exists to prevent. - `export const X: Story =` wrapping onto the next line was reported as a malformed export. A guard that reddens on formatting teaches people to ignore it. - The title regex took the first `title:` in the file, not meta's. A fixture literal above meta decided the file's namespace, and a `Design System/…` one exempted every story in it. - An empty `// Real path:` counted as an annotation. checkStorybookRoots claimed to catch a root added to main.ts but not scanned here; it only checked that the two known roots were still present. It now compares both directions, and the test covers the addition case and the accept-the-real-config case — the latter previously asserted `[] deepEqual []` against a function that returns undefined, so it verified nothing. FIDELITY.md now also says what the check is: a convention guard that must fail in seconds inside typecheck, approximating a story set only Storybook's index truly knows. Every gap above was closed by widening what it fails on, never by widening what it skips. * ci: run the Storybook smoke when its own runner changes `scripts/**` only sets scriptMode, so a change to the smoke runner was verified by nothing but the run it never triggered — the one file most able to make the guard silently stop guarding.
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
Aligns chat turn composition with Astryx so reasoning, tool calls, and message actions share one disclosure dialect instead of stacked Maka chrome.
ChatMessage/ bubble / metadata; thinking is ejectedChatReasoning.ChatToolCalls; product trow only covers permission, sandbox, and interrupted.CodeBlock(neutral card); ordinary failures drop the Maka "工具调用失败" Alert, nested raw disclosure, and "失败 · 退出码" footer.Verification
npm --workspace @maka/ui run test— 288 passnode --test apps/desktop/dist/main/__tests__/tool-error-collapse-contract.test.js apps/desktop/dist/main/__tests__/tool-activity-result-preview-contract.test.js— passNot run: full desktop E2E suite; Playwright browser smoke.