fix(ui): guard intelligence chart widths against zero baselines#3
Merged
t41372 merged 1 commit intoApr 17, 2026
Conversation
t41372
added a commit
that referenced
this pull request
May 21, 2026
Why: bun run check was failing at the 100% coverage gate (lines 96.63%, fns 94.38%) because (a) src/components/heatmap/year-heatmap.tsx had no remaining callers after the dashboard fake-data removal in c9a6189 — handoff §4.1 #3 anticipated this — and (b) nineteen files under src/components/ui/ (badge / button / command / dialog / dropdown-menu / input / label / popover / radio-group / scroll-area / select / separator / sheet / skeleton / slider / switch / tabs / textarea / tooltip) were unreferenced shadcn primitives sitting in the tree from an earlier phase, never imported by the active paper surface and never caught because the full coverage gate had not run end-to-end on a Linux box yet. AGENTS.md is explicit: zero-coverage active-runtime files are deleted, not excluded. Per user instruction (this turn) we remove them rather than smuggle them past the gate via exclusions. What: - git rm 20 files: year-heatmap.tsx + every file under src/components/ui/. Both src/components/heatmap/ and src/components/ ui/ become empty and git collapses them. No imports anywhere in src/**/*.{ts,tsx} reference any of the deleted symbols (verified by grep before deletion); inside-ui button.tsx had a single import from the also-deleted ui/dialog.tsx, both fall together. - vitest.config.ts: add three paper-shell re-export barrels to the coverage exclude list — src/components/cards/index.ts, src/components/explorer-paper/index.ts, src/components/shell/index.ts. These are pure `export {X} from './x'` files with no runtime semantics, matching the existing precedent for src/components/intelligence/workbench/index.ts and src/components/review/index.ts (both already excluded). The exclude list stays alphabetized. How: ran the full bun run check; the 100% coverage threshold reported the 20 zero-coverage files as the dominant gap. Confirmed zero-import status via `grep -rn "import.*from ['\"]@/components/ui/<name>['\"]" src/**` before each deletion. fmt / typecheck / test:unit will be re-validated by the next bun run check. Caveats: - No production behaviour change. The deleted shadcn primitives were unreachable; the paper components use their own primitives under src/components/primitives/ (skeleton.tsx etc. distinct from ui/skeleton.tsx). - If future work brings back any of these primitives, restore them fresh via the shadcn CLI rather than reviving the orphans — upstream has moved. Context: WORK-V03-PAPER-REDESIGN-A — Phase 0 dev-machine close-out.
t41372
added a commit
that referenced
this pull request
May 22, 2026
… i18n
Why
- Codex review flagged three Blocking/High issues against feat/v0.3-redesign-2:
(1) the ⌘K palette in shell.tsx sent `{ search, limit, offset }` to
query_history and tried to read `response.rows`, but the real
contract is `{ q, page, cursor, ... }` returning `items`. Result:
palette searches were silently empty on desktop, and the existing
tests had been mocking the wrong shape.
(2) Paper UI still leaked raw English copy (char/chars counter, "Remove
tag {tag}" aria, "Calendar" dialog label, "now"/"first" year-rail
footers, dashboard greetings). i18n is a shipping contract, not
polish.
(3) Theme was held twice — once by the shell as a private useState,
once by Settings → Appearance via applyPaperPreferences. Toggling
one didn't update the other, so the buttons drifted.
What
- shell.tsx: palette now calls `backend.queryHistory({ q, limit, sort })`
and maps `response.items` with the real HistoryEntry shape (id/url/
domain/title/visitedAt/visitTime). Removed the orphan PaletteRow
interface. shell.test.tsx mocks `backend.queryHistory` with valid
HistoryQueryResponse fixtures instead of the legacy rows shape.
- i18n: added 3-language entries for the paper detail panel's char
counter (singular + plural template), the remove-tag aria label, the
calendar dialog aria, the year-rail now/first footer captions, and
the dashboard morning/afternoon/evening greetings. The dashboard's
hand-rolled greeting map is gone — it now reads
`dashboard.greetingMorning/Afternoon/Evening` like every other copy
in that route. PaperDetailPanelCopy + PaperCalendarPopoverCopy +
PaperYearRailProps + paper-view.tsx copy interface all gained the
new keys; buildPaperDetailPanelCopy + buildPaperContactSheetCopy
thread them through. i18n parity 100% (2798 keys × 3 locales).
- paper-preferences.ts: applyPaperPreferences now dispatches a
`pathkeep.paperPreferencesChanged` CustomEvent (with the resolved
preferences in `detail.preferences`) after applying + persisting.
shell.tsx subscribes to that event so the topbar theme button stays
in sync with Settings → Appearance toggles; settings/appearance-
section.tsx subscribes too so flipping theme via the shell button
updates the radio without re-mount. shell.tsx's handleToggleTheme
now routes through applyPaperPreferences instead of mutating a
private useState — single source of truth, one persist call.
Context
- Codex findings #1, #5, #6. Findings #2 (paper pagination), #3
(og:image fetch trigger), #4 (coverage gate restoration) tracked
separately and remain pending in BACKLOG.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
t41372
added a commit
that referenced
this pull request
May 22, 2026
…age gate
Why
- Codex review flagged three more issues:
(2) Paper Explorer Browse exposed no pagination — the underlying
useExplorerUrlState had `goToHistoryPage` / `setHistoryPageSize`
handlers, but the paper UI dropped them. For a 1440 M-row archive
this caps the user at the first response page (≤200 rows).
(3) Card-mode og:image cache only loaded existing rows — there was no
production path that enqueued a fetch for cache-miss URLs, so a
fresh archive permanently rendered favicons.
(4) `check:coverage` ran `coverage:rust:quality` (a triage slice) not
the accepted full-scope `coverage:rust`. That's an unauthorised
gate weakening vs. docs/plan/program/quality-matrix.md.
What
- PaperContactSheet: new optional `pagination` prop renders a footer
with newer/older buttons (paper goes newest → oldest, so "next" is
the older direction), a "page X of Y · N rows" summary, and a
rows-per-page selector. Disabled buttons clamp at archive bounds.
Footer omitted entirely when route doesn't supply pagination (e.g.
the day-only insight surface).
- PaperExplorerView + Explorer route: thread the new pagination
descriptor through from useExplorerUrlState's existing
handleNextHistoryPage / handlePreviousHistoryPage / setHistoryPageSize
handlers. `visibleTimeResults` carries the authoritative page /
pageCount / total / hasNext / hasPrevious; the footer reads them.
- i18n: 5 new keys across all three locales — paginationOlder, Newer,
Summary, SummaryPending, PageSizeLabel. 2803 keys × 3 locales,
parity 100%.
- use-explorer-og-images.ts: after `loadHistoryOgImages` resolves,
the hook now diffs the response and enqueues
`triggerOgImageRefetch(batch)` for URLs that came back with a
non-`ok` status (missing or never-cached). Bounded at 20 URLs per
render so the worker pool can't be stampeded; `enqueuedFetchRef`
prevents re-enqueuing within the same cache epoch. The promise's
.catch swallows rate-limit / disabled-fetch rejections silently —
the Rust worker persists negative-cache rows on its own.
- og_images_fetch.rs: extracted `read_capped_bytes<R: Read>` from
`read_response_body` so the body-read fall-throughs (Io error,
TooLarge) can be unit-tested directly with synthetic Read impls,
closing line 336 of the production source. Three new cargo tests:
errors-mid-stream → Io, oversize → TooLarge, short stream → Ok.
- package.json: check:coverage now calls `coverage:rust` (full
scope), not the `:quality` triage slice. The Rust full gate still
has ~20 uncovered defensive lines (worker pool mutex poison,
sender disconnect, mid-stream Io in the live HTTP pipeline) — those
surface on `bun run check` so a release gate failure is honest.
Coverage delta
- JS: unchanged at 99.71 stmts / 98.89 branches / 99.77 funcs /
99.89 lines (existing threshold still 99/99/98/99 pending the
separate JS residual sweep).
- Rust full scope: 12 → 7 uncovered lines in og_images_fetch.rs.
archive_flows.rs worker pool internals (13 lines) still need an
integration harness — tracked in WORK-V03-RUST-COVERAGE-RESIDUAL.
Context
- Codex findings #2, #3, #4. Codex flagged the gate-weakening change
as a merge blocker — the check:coverage script is now restored to
full coverage. The remaining residual is documented in BACKLOG and
the gate fails until it closes, which matches the codex requirement
of "merge 前必須恢復".
Co-Authored-By: Claude Opus 4.7 <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.
Motivation
NaN%when the dataset baseline is zero (empty or all-zero early-profile states), causing visual glitches in the Core Intelligence UI.Description
Math.max(..., 1)inEngineRankingPanel,ConceptCloudPanel, andSearchEffectivenessSectioninsrc/pages/intelligence/index.tsxso divisions never use zero; computemaxReformulationsonce to avoid repeated zero-unsafe calculations.Testing
bun run buildwhich executedtscandvite buildand completed successfully.bunx eslint src/pages/intelligence/index.tsxwhich returned clean results for the changed file.bun run checkpipeline; the change did not introduce new errors, butbun run checkstill reports existing, unrelated React hooks lint violations elsewhere in the repo (pre-existing and outside this change's scope).Codex Task