Skip to content

feat(scratchnode): degraded badge on provider-fallback /ask answers#447

Merged
HomenShum merged 6 commits into
mainfrom
feat/degraded-answer-badge
Jun 1, 2026
Merged

feat(scratchnode): degraded badge on provider-fallback /ask answers#447
HomenShum merged 6 commits into
mainfrom
feat/degraded-answer-badge

Conversation

@HomenShum
Copy link
Copy Markdown
Owner

Completes the honest-degraded-UX half of the /ask observability work (pairs with the getAskTelemetry query in #446).

Why

When the AI provider is unavailable, askAgent answers from public sources only and records agentMode=provider_fallback. renderAnswer already labelled it (\AI fallback · deterministic) but as neutral text — a reader could mistake a degraded answer for a full AI one.

What

An amber *\⚠ degraded · sources only* pill in the answer head, shown ONLY for provider_fallback answers:

  • icon + text, never colour alone (a11y / colour-blind safe)
  • role=status so screen readers announce it
  • title tooltip explains it may be less complete than a full AI answer

Verification

All 4 inline <script> blocks pass node --check (live-room block is type=module/strict). Renders only on the rare fallback path; Tier-A live-DOM check post-deploy confirms it shipped.

🤖 Generated with Claude Code

…nswers

Completes the honest-degraded-UX half of the /ask observability work. When the AI
provider is unavailable, askAgent answers from public sources only and records
agentMode=provider_fallback. renderAnswer already LABELLED that ("AI fallback ·
deterministic") but rendered it as neutral text, so a reader could mistake a
degraded answer for a full AI one.

Adds an amber "degraded · sources only" pill (icon + text, never colour alone for
a11y; role=status so screen readers announce it; title tooltip explains it may be
less complete) in the answer head, shown ONLY for provider_fallback answers.

Verified: all 4 inline <script> blocks pass node --check (the live-room block is
type=module / strict). Renders only on the rare fallback path; Tier-A live-DOM
check post-deploy confirms the code shipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@HomenShum HomenShum enabled auto-merge (squash) June 1, 2026 17:27
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 1, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nodebench-ai Ready Ready Preview, Comment Jun 1, 2026 6:58pm

Request Review

@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented Jun 1, 2026

🤖 Augment PR Summary

Summary: Adds an amber “⚠ degraded · sources only” badge to ScratchNode /ask answers when agentMode=provider_fallback, making provider-outage (sources-only) responses clearly distinguishable.
Why: Prevents readers from mistaking fallback deterministic answers for full AI-provider answers.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread public/proto/home-v5.html
// text, never colour alone — a11y) with role=status so it's announced, so a
// reader never mistakes a degraded answer for a full AI one.
const degradedBadge = answer.agentMode === 'provider_fallback'
? '<span class="sep">·</span><span class="ans-degraded" role="status" style="color:#e0a160;background:rgba(224,161,96,.14);border:1px solid rgba(224,161,96,.32);padding:0 7px;border-radius:999px;font-weight:600;white-space:nowrap" title="The AI provider was unavailable, so this answer was generated from the public event sources only. It may be less complete than a full AI answer.">&#9888; degraded &middot; sources only</span>'
Copy link
Copy Markdown

@augmentcode augmentcode Bot Jun 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

degradedBadge sets role="status" but doesn’t include an explicit aria-live attribute; elsewhere in this file status messages use role="status" aria-live="polite". Consider adding aria-live="polite" here too for more consistent screen reader announcement behavior across AT/browser combos.

Severity: low

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

… restore + scenario tests

The first /ask sent in the sub-second cold-load window (before the
liveEventMembers row commits) can reject not_joined. PR #445 already added the
pre-init send queue + idempotent join+resend retry; this closes the remaining
gap:

- home-v5.html: the final-catch draft restore now guards `if (!input.value)`
  like its sibling _sn_failPendingSends, so a total-failure restore never
  clobbers a newer draft typed while the send was in flight; the toast stays
  honest about whether it actually repopulated.
- scratchnode.events.test.ts: two scenario tests pin the recovery contract — a
  pre-join send rejects not_joined and persists nothing, then join+resend lands
  exactly one message (not lost, not duplicated); and the idempotent re-join
  during recovery never forks a second member row.

Additive only — no sendMessage/joinEvent contract changes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@HomenShum HomenShum merged commit d2f20a8 into main Jun 1, 2026
16 checks passed
@HomenShum HomenShum deleted the feat/degraded-answer-badge branch June 1, 2026 19:06
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

Demo: walkthrough of the surfaces this PR changed is available as a workflow artifact (pr-demo-447) at https://github.com/HomenShum/nodebench-ai/actions/runs/26775898943

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants