LearnNewsExamplesServices
Frontmatter
id15512
titleAgentCard: render the contracted State line + give StateDot an accessible name (D2 ruling)
stateClosed
labels
enhancementdesignai
assigneesneo-opus-grace
createdAtJul 18, 2026, 8:45 PM
updatedAtJul 18, 2026, 11:07 PM
githubUrlhttps://github.com/neomjs/neo/issues/15512
authorneo-opus-grace
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtJul 18, 2026, 11:07 PM

AgentCard: render the contracted State line + give StateDot an accessible name (D2 ruling)

Closed Backlog/active-chunk-7 enhancementdesignai
neo-opus-grace
neo-opus-grace commented on Jul 18, 2026, 8:45 PM

Context

Implementing leaf for the D2 design ruling on epic #14805 (ruling) — the last of the three design-authority items (#15493/D4 and #15500/D3 shipped). Origin: #14619's audit, re-derived from source before ruling.

The Problem

Session state reaches the operator by hue alone, which WCAG 2.1 1.4.1 (Use of Color, Level A) forbids as a sole visual carrier:

  • StateDot.mjs renders no text, title, or aria-label — it only swaps a state class.
  • StateDot.scss gives all seven states identical geometry (8px circle); only --fm-dot differs.
  • AgentCard.applyRecord sets only the dot (getReference('state-dot').set({live, state})) — no state text anywhere in the card or its SCSS.

And the pulse cannot carry the signal: TOKENS.md:41-43 is correct that the reduced-motion property holds because the pulse conveys nothing unique. Re-loading signal there would trade a 1.4.1 failure for a reduced-motion failure.

The Architectural Reality

The missing channel is already specified and simply was never built — CARD-CONTRACT.md:13:

State line (mock: "▲ WORKING") | lifecycle.state (+ confidence) | mono, state-colored; renders the DTO's literal state vocabulary

And the vocabulary resolver already exists: stateLabel(state), exported from HealthSwatch.mjs alongside the stateClass that StateDot already imports. HealthSwatch proves the pattern in-tree (same class + visible text); HealthBar inherits it by composition and is already compliant. The card is the surface that skipped it.

So this is a conformance gap against a contract we already wrote, not a new design.

The Fix

  1. Render the contracted State line on AgentCard, adjacent to the dot, consuming stateLabel(state) — never a second vocabulary.
  2. Give StateDot an accessible name from the same stateLabel. This is 4.1.2 / 1.1.1 — a separate criterion. It must not be treated as satisfying 1.4.1: an aria-label does nothing for a sighted operator who cannot separate hues. Both are required.
  3. Do not add shape/glyph-per-state as the primary channel (ruled out: seven distinguishable glyphs in an 8px dot is a legibility problem dressed as an accessibility fix, and it forks the vocabulary). Shape may later reinforce text.

Acceptance Criteria

  • AgentCard renders the DTO's literal state vocabulary as text beside the dot; state is legible with colour removed (greyscale check).
  • Text comes from stateLabel(state) — no second state→text mapping introduced.
  • StateDot exposes an accessible name from the same resolver.
  • AgentDetail's dot (:192) covered by the same reasoning or explicitly scoped out with rationale.
  • Card density holds at the measured fleet density — the design judgement this leaf owns (the SSOT mock places a state line; confirm it reads at real row counts).
  • CARD-CONTRACT.md's conformance checklist reflects the now-implemented State line.

Out of Scope

  • The pulse / reduced-motion treatment — deliberately untouched per the ruling.
  • D3 / D4 (shipped) · #15489 (Accounts block) · #14618 (visual-regression harness, the mechanical guard this composes with).

Related

#14805 (epic) · #14619 (the audit that recorded the 1.4.1 failure) · #14578 (TOKENS.md) · CARD-CONTRACT.md (#14605) · #15487 (the re-baseline that reopened the design lane).

Live latest-open sweep at 2026-07-18T18:45Z plus a targeted StateDot/1.4.1 search: no equivalent leaf exists.

Authored by Grace (Claude Opus 4.8, Claude Code).