Synced from GitHub
fix(copy): raw error strings and copy that promises things the app cannot do#1538
Summary
This ticket groups 13 usability or accessibility findings from the driven UI pass, so they can be fixed together.
UI findings
- A failed case-archive import prints the raw Electron IPC error (medium, Dashboard, finding). The red strip renders the bridge rejection verbatim, naming the IPC channel and the path, with no plain-language message and no
aria-liveanywhere in the dashboard tree. The refuter reproduced the same leak for an ordinary wrong-file pick and an empty zip.- App:
src/renderer/components/dashboard/Dashboard.tsx:80
- App:
- A bad archive file surfaces the raw Electron IPC error (medium, New Case wizard, finding). The inline strip prints the bridge wrapper, the channel name and a doubled error prefix around the app's own sentence, which is fine on its own, and says nothing about what to do next.
- App:
src/renderer/components/dashboard/Dashboard.tsx:60
- App:
- Both export failure paths print the raw Electron IPC string (medium, Export dialog, finding). The dialog prepends its own error prefix to a bridge message that already begins with one, naming the channel and an absolute path, and the archive banner does the same, while the toast beside them manages a plain sentence.
- App:
src/renderer/components/export/ExportDialog.tsx:150
- App:
- The footer prints a version the build does not have (medium, Dashboard, finding). The footer hard-codes a 2.0.0 string in every state and both themes while
package.jsonreads 1.0.1-beta.21, so an operator asked which build produced an exhibit reads a version that does not exist, and the beta label is absent.- App:
src/renderer/components/dashboard/DashboardFooter.tsx:13
- App:
- All three footer links are inert buttons (medium, Dashboard, finding). Documentation, Changelog and GitHub are buttons with no
href, no handler andcursor: default; clicking changes nothing and fires nothing, yet all three sit in the tab order as consecutive no-op stops.- App:
src/renderer/components/dashboard/DashboardFooter.tsx:24
- App:
- Quick Start describes a capability that does not exist, in a marketing register (medium, Dashboard, finding). Step one promises entity types to extract, and a grep for that term over
src/returns the string itself and one CSS comment; the app has Selectors. Step two says pages are saved by our extension, which is first-person-plural register the guide rules out, and names source code rather than MHTML and Extracted Text.- App:
src/renderer/components/dashboard/QuickStartGuide.tsx:12
- App:
- Two card actions promise surfaces the app does not have (medium, Case Overview, finding). Recent captures View all, Capture activity Open timeline and Top sources All sources all navigate to the unfiltered Captures list, with no filter, anchor or scroll target, so two of the three labels name a destination that does not exist.
- App:
src/renderer/components/overview/CaseOverview.tsx:160
- App:
- The pro tip names an extension control that does not exist (medium, Captures list, finding). The empty-captures panel tells the operator to pick a capture command from the toolbar icon, and no such string exists anywhere in
extension/src; the popup's manual control has a different label. Open issue #1276 covers the other copy lines in this panel and not this one.- App:
src/renderer/components/captures/CapturesGettingStarted.tsx:157
- App:
- Report a problem tells a public user to attach the bundle to the tester chat (medium, Settings, finding). The subtitle and the closing disclosure both name a private round-one programme surface that a public user of an open-source app has no access to and cannot infer, so the one workflow for reporting a fault ends in an instruction the reader cannot follow.
- App:
src/renderer/components/diagnostics/ReportProblemDialog.tsx:81
- App:
- The Staging node subtitle cites an internal architecture decision number (medium, Data explorer, finding). The pane header names an ADR the operator cannot resolve and that appears nowhere else in the interface, while every other node subtitle on the screen is plain.
- App:
src/renderer/components/dashboard/cases/DataExplorer.tsx:66
- App:
- The action button in the Purge confirm dialog says Delete (medium, Settings, finding). The trigger, the card and the dialog title all say Purge while the button reads Delete, because the label is chosen by a restore-or-delete test, so Clean Orphans gets Delete too. The action drops every archived case with its captures, tags, selectors and notes.
- App:
src/renderer/components/settings/db/DbUtilities.tsx:482
- App:
- Recent slow operations lists operations that took no measurable time (medium, Settings, finding). On a fresh profile with two seeded captures the panel reported two slow operations, both extraction runs at zero milliseconds, because the recorder appends unconditionally with no duration threshold.
- App:
src/main/services/diagnostics.ts:101
- App:
- The row editor gives no reason a save failed (medium, Settings, finding). A blank submit on the cases table leaves the modal open and empty, while the real constraint error renders in the page behind the overlay, clipped by the modal; the only other feedback is a toast with no cause. The operator has to cancel, losing what they typed, to read why.
- App:
src/renderer/components/settings/db/DbTables.tsx:88
- App:
Related open issues
#1178
Source
- Design rows:
docs/plans/2026-09-19-mock-reconciliation.mdat5902b28f0b71. Mock line numbers refer todocs/design-handoff/2026-09-14-design-project-export/Birdbrain.dc.html. - UI findings:
docs/plans/2026-09-19-ui-ux-pass.mdat5902b28f0b71. Screenshot paths there live only in the sweep worktree.