fix(demo,ui): correct /api/news handler shape + bump persist version v4→v5#240
Merged
Conversation
…v4→v5 Two coupled fixes. ## 1. News handler shape mismatch (the crash) PR #232's legacy-chat excision replaced the old notifications/news handler with a new `newsList.ts` that returns: { articles: [...], hasMore: false } with each article shaped { id, title, source, url, publishedAt, summary, tickers }. But the contract per ui/src/api/types.ts is NewsListResponse: { items: NewsArticle[], count, lookback } with each NewsArticle shaped { time, title, content, source, link, categories }. NewsPage calls `setArticles(res.items)` — wrong shape gives `articles = undefined`, then render does `[...articles].reverse()` which throws "undefined is not iterable" as an unhandled exception. React error boundary upstream catches it on the page level but the crash poisons any persisted tab state pointing at the news view. Rewires the handler to use `demoNewsArticles` (PR-4 Stage 2 fixture, correct NewsArticle shape, 6 realistic items) and the correct { items, count, lookback } wrapper. ## 2. Persist version bump (the recovery) A user who'd already opened the news tab has `selectedSidebar:'news'` + a news tab kind persisted to localStorage `openalice.workspace.v2`. Reload replays that selection → re-triggers the crash → loop. Bumping the persist version from 4 to 5 makes zustand drop the poisoned state on rehydrate (no migrate function — schema bump clears, per this store's loud-fail contract — matching v4's bump pattern from the legacy chat excision). Cost: users with healthy state lose their open-tabs/layout. Necessary trade-off — they were on the crash path too if they navigated to news. Verified: - pnpm -F open-alice-ui exec tsc -b: clean - pnpm -F open-alice-ui build (prod): main chunk has zero `demoNewsArticles` / fixture-string leaks - pnpm dev:demo + Playwright: /news lists 6 articles correctly, expand-article click works, single zustand info log "couldn't be migrated since no migrate function was provided" is the expected v4→v5 dropping behavior Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
pull Bot
pushed a commit
to bhardwajRahul/OpenAlice
that referenced
this pull request
Jun 1, 2026
…nging /api/* surfaces Three recent demo crashes (TraderAlice#235 / TraderAlice#238 / TraderAlice#240) all came from the same pattern: a refactor changed what production code returns or expects, but the parallel demo handler in `ui/src/demo/handlers/` kept the old (or invented an ad-hoc) shape. `pnpm test` doesn't catch it because esbuild doesn't enforce types. Adds demo mode to the existing "Subsystem guides" section alongside the event/listener/producer guide. The text names the two cheap habits that prevent the failure mode: 1. Import the canonical type from `ui/src/api/types.ts` (or wherever the contract lives) when writing a demo handler, instead of inlining an ad-hoc shape. 2. Run `pnpm -F open-alice-ui dev:demo` and walk the affected surface before declaring the refactor done. The catchAll's `[demo] unmocked …` warn surfaces missing endpoints; visible crashes surface shape mismatches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
Two coupled fixes for the news crash the user reported (demo mode):
clicking into News crashed the page AND poisoned the persisted UI
state so subsequent reloads kept crashing.
What was wrong
Fix 1: `/api/news` handler shape mismatch (the crash)
PR #232's legacy chat excision replaced the old news/notifications handler with a new `ui/src/demo/handlers/newsList.ts` that returned:
```ts
{ articles: [...], hasMore: false }
```
with each article shaped `{ id, title, source, url, publishedAt, summary, tickers }`.
But `ui/src/api/types.ts` defines the contract as `NewsListResponse`:
```ts
{ items: NewsArticle[], count, lookback }
```
with each `NewsArticle` shaped `{ time, title, content, source, link, categories }`.
`NewsPage` calls `setArticles(res.items)` — wrong shape → `articles = undefined` → render does `[...articles].reverse()` → throws "undefined is not iterable" as an unhandled exception.
Fix: rewires the handler to use `demoNewsArticles` (the PR-4 Stage 2 fixture that has the correct `NewsArticle` shape with 6 realistic items) and the correct `{ items, count, lookback }` wrapper.
Fix 2: persist version bump v4 → v5 (the recovery)
A user who'd already opened the news tab has `selectedSidebar:'news'` + a news-kind tab persisted to `localStorage["openalice.workspace.v2"]`. Reload replays that selection → re-triggers the crash → loop. Even after the handler fix, anyone who hit the bug once stays stuck.
Bumping the zustand persist version from 4 to 5 makes rehydrate drop the poisoned state (no migrate function — schema bump clears, per the store's loud-fail contract; matches the v4 bump pattern from the legacy chat excision).
Cost: users with healthy state lose their open-tabs/layout. Necessary — they were on the crash path too if they navigated to news.
Pattern note: same bug pattern as PR #235
PR #232 also introduced an inline ad-hoc type for the `pushToolGate` test probe that didn't match the real `AgentWorkResultProbe` interface (fixed in #235). This is the second case in the same merge where the rewrite introduced a structural shape mismatch that passed esbuild (no type enforcement) but breaks at runtime.
In both cases, importing/referencing the canonical type from `ui/src/api/types.ts` or `src/core/agent-work.ts` instead of writing inline shapes would have caught it at strict tsc time. Worth flagging for any future Stage-2-ish demo handler additions.
Verification
Boundary touch
`ui/src/tabs/store.ts` is non-demo UI code, but the change is a one-line version-number bump with a comment — same shape as v4's bump from PR #232 (commit 7415131 "bump tab-store persist version").
🤖 Generated with Claude Code