Each artefact below is drawn in the shipped design system and shows the surface as it will read after the change. Highlighter marks the exact new wording. Docs and code identifiers are out of scope here — this sheet is the user-visible set only.
Signals is a feature: the Signals lens, the signal cards it makes, and the signal strength it reports.
Analysis is two things and keeps the word for both — (a) the pipeline running on data, the run the researcher commands, and (b) the human act of interpreting the results of that run.
Test for any string: does it name the signal feature, or does it name a run or an interpretation? Feature → Signals. Run or interpretation → Analysis.
Five changed surfaces. The nav rail and the lens title are the two a researcher sees every session; the rest are states and secondary chrome.
Patterns ranked by signal strength — concentration, participant breadth, and intensity combined.
frustration 5 participants · conc. 2.4×
doubt 4 participants · conc. 1.9×
Loading signals…
No signals yet. Run the pipeline or apply codebook tags to generate them.
Tag signal error: request timed out
No analysis data available. Run the pipeline or apply codebook tags to generate analysis.
No signals yet. Run the pipeline or apply codebook tags to generate them.
These three are rewrites, not swaps — the only strings on this sheet where the new wording is a judgement rather than a substitution. "No analysis data available … to generate analysis" said analysis twice for one idea; the replacement drops the repetition rather than carrying it over as "signals … signals".
analysis.tagError is the weakest of the three. "Tag signal error: {{error}}" is accurate and terse. A fuller rewrite — "Couldn't compute tag signals: {{error}}" — reads better but changes the string's shape; flagged rather than assumed.
The settings inside this category already say "signals" — Top N signals, Top N for elaboration. Only the category label lags. No environment variable changes; there are no ANALYSIS_* vars.
This category exists twice in the code — SettingsPanel.tsx and SettingsModal.tsx each carry a copy. Both render, so both change or half the panel disagrees.
List of interview sessions with duration, participant, and thumbnail. Click through to the full transcript with timecodes.
Signal concentration grids — which themes appear in which sessions, and how strongly. Helps identify patterns that cut across participants.
This heading is a hardcoded <h3>, not a locale key — so no locale gate can see it, in either direction. Its body paragraph already says "Signal concentration grids", so the heading was the only word out of step.
Two changed surfaces. Most of the Mac chrome already says Signals — the toolbar, the View menu and the window title shipped that way. Only the lens rail and the picker lag, plus one welcome cell.
frustration 5 participants
The window title and the toolbar button already read Signals — "12 Signals" and "Show Signals (⌘⌥L)" shipped that way. Highlighting only the three that change makes the current inconsistency visible: today this exact window says Analysis in the rail and the picker while saying Signals twice in the same chrome.
New doubling to check in the app. After the change the window subtitle and the page heading both read "Signals". Before, they read "Signals" and "Analysis". No test can see this — it wants one look in the real app.
This pair is the whole argument in two menus. View ▸ names the lenses; Project ▸ names the run. Only the ⌘5 item changes — "Hide Signals" already shipped. Project ▸ keeps every word: Analyse, Re-analyse…, Stop Analysis are what the researcher commands, not what Bristlenose computes.
The ⌘5 label resolves through Tab.localizedLabel, which builds its key from the enum's raw value — so the label and the route move in the same commit or the Mac silently falls back to English.
The Analysis tab shows where sentiment concentrates.
A signal marks a theme running hotter or cooler than you'd expect.
Signals →
The Signals tab shows where sentiment concentrates.
A signal marks a theme running hotter or cooler than you'd expect.
Signals →
One cell, one word. Its own link label already says Signals → and points at signals.html — the body was the last thing disagreeing with its own button.
Observed, not changed: this cell says "tab" where the rest of the app says "lens". Left alone deliberately — it is a separate inconsistency and folding it in would widen the rename past what was asked.
No highlighter here: none of these change. Split by sense, so the boundary can be checked twice — once against the run, once against the interpretation. If any of these reads wrong sitting next to a lens called Signals, the rule needs adjusting before implementation, not after.
Sense (b) is why the rename is worth doing, and the welcome screen already proves it. WelcomeHomeView.swift:131 says "Tagging is analysis — turn quotes into themes." Seven lines later, :138 names a different lens "Analysis". The same file, in the same scroll, asserts that analysis happens in the Quotes lens and then gives the word to a lens that is not it. That is the contradiction in miniature.
analysis.html earns its place by content, not by exemption. The page carries three sibling blocks — Key findings, Section × Sentiment, Theme × Sentiment. Two of the three are heatmaps, so signals.html would name a third of the page. It is also squarely a sense-(b) artefact: the thing you open in order to interpret.
The lens is the opposite case and survives the same objection: its heatmaps are the inspector, reached by drilling into a card and labelled "Heatmap sources". Evidence behind a signal, not a peer section.
Resolved: "Analysis updated" was flagged as worth a second look. It fires from LastRunStore on run completion, so it is sense (a) outright — a run finishing, not a lens being named.
Eleven user-visible strings plus one route. Everything else in the rename is code identifiers, locale keys and documents — invisible here by design.
Eight of the eleven are one-word swaps into a word all 21 locales already carry, reviewed, under toolbar.signals — Senyals, Signály, Signale, Señales, Signaux, Segnali, シグナル, 시그널, Сигналы, 訊號. Lift, don't translate.
Three are rewrites — loadingData, noData, tagError — and those need a translation pass in each locale rather than a lift. They are the only new translation work in the whole rename.
The lens title is load-bearing.
analysis.headingis the flush-to-datum first heading — the element the layout system aligns the pane to. Its three call sites are the loading, empty and loaded branches of one page, not three sections, so one value change covers all three.The URL change is Phase 2, not Phase 1. Shown together here because a researcher experiences them as one change.
/report/analysis/redirects, so bookmarks survive.