PROPOSED
PROPOSED — not built.
The “freshness” that does exist (ServeManager, AgentActivity) is the MCP tool-call window, an unrelated thing.
Mockup · P5 / decision D4-B

Report freshness banner

Today a failed re-run hides the report the researcher already had: detect_status intercepts /report/* whenever the last terminus isn’t completed, so a provider outage takes away finished work. D4-B serves the last good report instead and discloses the failure. This is the surface that does the disclosing.

Palette Appearance
Artefact — real pixels, product only
Commentary — not the product

1 · What a failed re-run does today

The report exists on disk and is perfectly readable. The researcher cannot reach it.

before
✗

Last run failed.

Provider returned 503 — the service is temporarily unavailable.

2 · What it would do instead

The last good report, with the two facts the researcher is owed: what they are reading, and that the run they started since then failed.

after

Showing the report from 28 August. The latest run failed.

Show details
category: api_server
code: 503
stage: s10_quote_extraction
provider: anthropic

Provider returned 503 — the service is temporarily unavailable.

Findings

“I couldn’t tell whether it had saved, so I just pressed it again.”

p2confusion

“The price at the top and the price in the bag were different.”

p3trust
Commentary — why this shape

Kind: WARNING, not ERROR. The five-kind taxonomy (bristlenose/ui_kinds.py) is explicit that a sixth is not to be invented, so the banner picks from what exists. ERROR means “did not complete; action needed” — right for the status page, where there is nothing to show. Here a complete artefact is on screen and only its currency is in question, which is what WARNING (“recoverable / partial / soft-degrade”) names. Reaching for ERROR would teach the researcher to distrust a report that is fine.

It is the status page folded to one line. Same glyph, same kind colour (--bn-sentiment-surprise), same <details> + <pre> disclosure carrying the same cause block. Nothing new is being said, so nothing new is being drawn — the two surfaces are one message at two sizes.

Genuinely new element, flagged. No banner/notice component exists in frontend/src/components/ or in theme/{atoms,molecules,organisms} — I checked before drawing. Every value above is an existing token; the component is new and needs your nod. Home would be theme/molecules/report-notice.css plus a small React component, not inline styles.

3 · The boundary — when the banner does not apply

A failed first run, or a destructive re-analysis that consumed the artefact, leaves nothing coherent to serve. The status page keeps that case, unchanged.

after · no prior report
✗

Last run failed.

Provider returned 503 — the service is temporarily unavailable.

Commentary — the integrity gate underneath

Which of the two you get is decided by evidence, never by how bad the failure looked: is there a coherent last-good artefact? That keeps us out of the business of maintaining a severity taxonomy of failures.

It also needs a real fix underneath, and this is the part worth scrutinising. The pipeline rewrites intermediate JSON stage by stage, so a failed run can leave stages 1–9 new and 10–12 old. A running serve only re-imports on a completed terminus, so today’s common case (provider outage, network, crash) never touches the DB — yesterday’s report is intact. The hole is a serve restart, whose startup import would happily ingest that mixed state. So the rule is one line with two consumers: the DB advances only on a completed terminus — the importer skips, and the page gate reads the same fact.

4 · The variants to settle

All three are one component in different states. Copy is deliberately unsettled — English first, then 21 locales.

states

Showing the report from 28 August. The latest run failed.

Show details
category: api_server
code: 503
stage: s10_quote_extraction
provider: anthropic

Showing the report from 28 August. The latest run failed.

Show details
category: api_server
code: 503
stage: s10_quote_extraction
provider: anthropic

Provider returned 503 — the service is temporarily unavailable.

— recent log —
2026-09-02 19:04:11 INFO  s09_topic_segmentation complete (51 sessions)
2026-09-02 19:04:12 INFO  s10_quote_extraction start
2026-09-02 19:04:44 ERROR provider says: 503 upstream unavailable

Showing the report from 28 August. The latest run was cancelled.

Commentary — four open questions, yours to settle

Copy, unsettled on purpose (English gets hand-tuned before it is seeded to 21 locales). Three candidates for the leading sentence:

Commentary — what this does NOT change

The desktop sidebar row keeps its own failure glyph and diagnostic popover. That is a different fact in a different place — the row says this study’s run failed, the banner says this report predates it — and per the house rule status lives where its subject lives. Browser and CLI have no row at all, so the banner is their only signal either way.

One consequence to accept knowingly: with D4-B in, a failed-but-previously-analysed project serves the SPA, so its lenses are live and correctly lit. That is the same one-line flip in ArtifactPrior the lens work left waiting, and it lands in the same commit as the serve rule — the prior must always mirror the serve that is actually running.