Naming review · 20 Sep 2026 · not implemented

Analysis → Signals: every UX surface

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.

artefact — real pixels, what ships commentary — not the product new wording
Palette Highlighter

1 · Web report — the SPA

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.

Nav rail, lens title, and the URL
after
localhost:8150/report/signals/
Project Sessions Quotes Codebooks Signals

Signals

Patterns ranked by signal strength — concentration, participant breadth, and intensity combined.

Checkout friction concentrates in onboarding

frustration  5 participants · conc. 2.4×

Pricing raises doubt across three sections

doubt  4 participants · conc. 1.9×

Commentary

The lens title is load-bearing. analysis.heading is 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.

Loading and empty states
after

Signals

Loading signals…

Signals

No signals yet. Run the pipeline or apply codebook tags to generate them.

Tag signal error: request timed out

before — analysis.noData

No analysis data available. Run the pipeline or apply codebook tags to generate analysis.

after

No signals yet. Run the pipeline or apply codebook tags to generate them.

Commentary

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.

Settings ▸ Configuration reference
after
AI provider Transcription Privacy Quotes Signals
Top N signalsDEFAULT_TOP_N · 12
Min quotes per cellMIN_QUOTES_PER_CELL · 2
Strong: concentration >hardcoded · 2
Commentary

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.

About ▸ what each lens does
after

Sessions

List of interview sessions with duration, participant, and thumbnail. Click through to the full transcript with timecodes.

Signals

Signal concentration grids — which themes appear in which sessions, and how strongly. Helps identify patterns that cut across participants.

Commentary

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.

2 · macOS app

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.

Lens rail and lens picker
after
Projects
▸ Acme onboarding 12
Lenses
◎ Project
◍ Sessions
❝ Quotes
⬚ Codebooks
▦ Signals
Acme onboarding — 12 Signals
ProjectSessionsQuotesCodebooksSignals Show Signals

Signals

Checkout friction concentrates in onboarding

frustration  5 participants

Commentary

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.

View menu — already correct, shown for the boundary
unchanged
Commentary

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.

Welcome screen — the drift caught mid-act
before

The Analysis tab shows where sentiment concentrates.

A signal marks a theme running hotter or cooler than you'd expect.

Signals →

after

The Signals tab shows where sentiment concentrates.

A signal marks a theme running hotter or cooler than you'd expect.

Signals →

Commentary

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.

3 · Staying "Analysis" — confirm the boundary

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 (a) — the pipeline running on data
Analyse
Project menu · button
Re-analyse…
Project menu · context menu
Stop Analysis  ⌘.
Project menu
Analysing…
sidebar row · status
Analysed 2 hours ago
sidebar row · status
+3 unanalysed
sidebar subtitle
3 files to analyse
new-files sheet
Analysis updated
screen-reader announce · on run completion
Analysis in progress
sleep assertion reason
AI-Powered Analysis
consent sheet title
Analysis finished but found no quotes
empty state
Drop a folder of interviews to start analysis
empty state
Sense (b) — the human act of interpreting the results
Tagging is analysis — turn quotes into themes.
welcome screen · shipped
…read and work with your Bristlenose analysis
Help ▸ guide intro
Rich — 11 columns for sorting and analysis
export menu hint
that revision is the analysis
website · tag-for-meaning
analysis.html
output folder · the artefact you interpret
Commentary

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.

4 · The complete change set

Eleven user-visible strings plus one route. Everything else in the rename is code identifiers, locale keys and documents — invisible here by design.

after
common.json
nav.analysisAnalysis → Signals
analysis.headingAnalysis → Signals
analysis.loadingData→ Loading signals…
analysis.noData→ No signals yet…
analysis.tagError→ Tag signal error: {{error}}
help.guide.signalsBody"the analysis page" → "the Signals lens"
help.signals.intro"the analysis page" → "the Signals lens"
settings.json
configReference.categories.analysisAnalysis → Signals
hardcoded — no locale key
AboutPanel.tsx <h3>Analysis → Signals
WelcomeHomeView.swift cell**Analysis** → **Signals**
Tab.swift English fallbackAnalysis → Signals
route — Phase 2
React Router · Tab.route/report/analysis/ → /report/signals/
Commentary

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.