Skip to content

docs(spec): ChatMessageBubble records its shipped contract as current - #9136

Merged
cixzhang merged 5 commits into
mainfrom
spec-backfill/ChatMessageBubble
Nov 1, 2026
Merged

cixzhang merged 5 commits into
mainfrom
spec-backfill/ChatMessageBubble

Conversation

@cixzhang

Copy link
Copy Markdown
Contributor

Exact decision needed

Promote component:ChatMessageBubble from draft to current. No behavior, prop, default, target, or export changes.

Existing authority searched

Decision

component:ChatMessageBubble, authority: current, approved by cixzhang. Draft and audit wording is removed, basis cells read from current source and tests, and the verification map credits only tests that fail when a claim breaks, with a "Read from source, with no focused test yet" list for the rest. No implementation gap. OQ1–OQ3 stay open.

Rejected alternatives

None.

Claim scope and non-goals

Claims are scoped to what main's source and tests show.

Evidence and implementation relationship

The component's colocated tests, as listed in the verification map.

Writing rubric results

  • R1 narration: none.
  • R2 research in the record: none.
  • R3 evidence naming a change: none.
  • R4 rejected alternatives over one line or outside a decision: none.
  • R5 pull request or issue references remaining: none.
  • R6 ruled open questions still listing options: none; open questions are unruled.

Scope

  • This PR contains specification records only.
  • It records observable behavior and preserves equivalent internal implementations.
  • Any named internal mechanism is intentionally public, names its dependent caller/system, and explains why an equivalent implementation would not satisfy the contract: none.
  • Verification states the evidence layer and failure signal without prescribing CI job/workflow topology.
  • It records one intentional durable decision, not a rescue for a separable tagalong.
  • The canonical knowledge owner, affected current claims, and overlapping open work are named; no ownership collision.
  • Adjacent API, visual, accessibility, composition, and implementation facts remain outside scope unless this exact decision depends on them.
  • Public text and artifacts contain no internal Meta context.

Validation

  • pnpm check:knowledge: aligned
  • Prettier: clean
  • git diff --check: clean

@vercel

vercel Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
astryx Ready Ready Preview Nov 1, 2026 6:36am UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 31, 2026
@astracat-bot

astracat-bot Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
❓ Needs maintainer input (for maintainers only) Nov 1, 2026, 6:46 AM UTC

@cixzhang
cixzhang marked this pull request as ready for review October 31, 2026 14:25
@github-actions github-actions Bot added the needs:spec-owner-review Current knowledge records await owner approval label Oct 31, 2026

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Promoting component:ChatMessageBubble to current waits on an engineering owner, who records the decision by commenting /approve-spec <full head SHA> on this pull request; the author may do this as an engineering owner. First, please correct the verification map so it credits only tests that fail when a claim breaks. That changes the spec text, so the approval should name the head that carries the fix.

  • FR1 (no root for children={null}), FR3 (the standalone balanced fallback and the compact radius) and FR4 (ghost removing the fill and block padding) have no failing test, so they belong in the "Read from source" list unless focused tests are added.
  • AR4 is already covered by the Chromium visible-state test's 4.5:1 contrast assertion and can move into the map.

[Automated review]

| AR1–AR4 | scoped axe report; Chromium receipts and pixels; narrow fixture | all visible states, light/dark, RTL, 320px | a semantic violation, low-contrast pair, or horizontal overflow fails its owning evidence layer | `audit:ChatMessageBubble/accessibility` |
| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
| -------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------- |
| FR1–FR3 | `ChatMessageBubble.test.tsx` children, sender, fallback, and compact density tests | standalone; user and assistant; compact | A missing root, fallback, or reflected axis fails. | `audit:ChatMessageBubble/behavior` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No test fails if the bubble renders no root for children={null} (FR1), if a standalone bubble falls back to compact instead of balanced, or if the compact radius is dropped (FR3). With each of those changes applied, ChatMessageBubble.test.tsx, ChatMessage.test.tsx and themingTargets.test.ts all still pass. Move these partitions to the read-from-source list, or add focused tests.

| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
| -------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------- |
| FR1–FR3 | `ChatMessageBubble.test.tsx` children, sender, fallback, and compact density tests | standalone; user and assistant; compact | A missing root, fallback, or reflected axis fails. | `audit:ChatMessageBubble/behavior` |
| FR4, FR9 | `ChatMessageBubble.test.tsx` variant and ghost tests; `themingTargets.test.ts` | filled; ghost at each density | Dropping reflection, the ghost alignment, or the target fails. | `audit:ChatMessageBubble/theming` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The ghost tests compare inline-padding classes only, so a ghost bubble that keeps the sender fill and block padding passes every test. List FR4's fill and block-padding removal as read from source, or add a focused test.

- FR3: the `spacious` inset.
- FR8: `className`, `style`, and `xstyle` composition.
- AR1: no role, tab stop, or name of the component's own.
- AR4: rendered text contrast in light and dark.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

__tests__/ChatMessageBubble.a11y.chromium.spec.ts (lines 389–399) already fails below 4.5:1 bubble text contrast in light and dark, so AR4 can move into the map next to FR5 and AR3.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Promoting component:ChatMessageBubble to current waits on an engineering owner, who records the decision by commenting /approve-spec <full head SHA> on this pull request; the author may do this as an engineering owner. The earlier verification-map corrections are in, but one row still overstates coverage, and fixing it changes the spec text, so the approval should name the head that carries the fix.

  • The FR4/FR9 row credits ghost alignment at each density, but a ghost bubble that takes the wrong density's inline inset passes every test, because both ghost tests only check that the ghost and the name row share some class, and they always share display: flex: narrow the row to removing the inset and list per-density ghost alignment as read from source, or tighten the tests.
  • The new AR4 row is missing its Audit section cell (audit:ChatMessageBubble/accessibility).

[Automated review]

| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
| -------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------- | --------------------------------------- |
| FR1–FR3 | `ChatMessageBubble.test.tsx` children, sender, fallback, and compact density tests | standalone; user and assistant; compact | A missing root, fallback, or reflected axis fails. | `audit:ChatMessageBubble/behavior` |
| FR4, FR9 | `ChatMessageBubble.test.tsx` variant and ghost tests; `themingTargets.test.ts` | filled; ghost at each density | Dropping reflection, the ghost alignment, or the target fails. | `audit:ChatMessageBubble/theming` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A ghost bubble that takes the wrong density's inline inset passes every test: both ghost tests only assert sharedClasses(ghost, nameSlot).length > 0, and the bubble root and name row always share the display: flex class. Only removing the inset entirely fails. Narrow this row to that, and list per-density ghost alignment as read from source (or tighten the tests).

| FR7 | `ChatMessageBubble.test.tsx` slot tests; the Chromium visible-state test's numeric alignment | zero; true; false; empty string; nullish | A truthiness check loses zero's alignment or restores an empty wrapper. | `audit:ChatMessageBubble/behavior` |
| FR8, AR2 | `ChatMessageBubble.test.tsx` "forwards the ref and neutral DOM props to the bubble root" and `data-testid` test | ref; DOM, data, and ARIA props | Dropped forwarding fails. | `audit:ChatMessageBubble/public-api` |
| AR3 | `ChatMessageBubble.a11y.chromium.spec.ts` "keeps long content inside a 320px fixture" | 320 CSS px | Horizontal overflow fails. | `audit:ChatMessageBubble/accessibility` |
| AR4 | `ChatMessageBubble.a11y.chromium.spec.ts` visible-state test's contrast assertion | light and dark | Bubble text below 4.5:1 fails. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This row has four cells under the five-column header; add the Audit section cell, audit:ChatMessageBubble/accessibility.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Promoting component:ChatMessageBubble to current waits on an engineering owner, who records the decision by commenting /approve-spec <full head SHA> on this pull request; the author may do this as an engineering owner. The earlier verification-map fixes are in, but one gap remains, and because fixing it changes the spec text, the approval should name the head that carries the fix.

  • The FR4/FR9 row lists filled as a covered state, yet a filled bubble that loses its fill passes every test: add "FR4: filled painting the sender fill" to the "Read from source, with no focused test yet" list, or add a test that fails when the fill is lost.

[Automated review]

| Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
| -------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------- |
| FR1–FR3 | `ChatMessageBubble.test.tsx` children, sender, fallback, and compact density tests | standalone; user and assistant; compact | A missing root, fallback, or reflected axis fails. | `audit:ChatMessageBubble/behavior` |
| FR4, FR9 | `ChatMessageBubble.test.tsx` variant and ghost tests; `themingTargets.test.ts` | filled; ghost | Dropping reflection, removing the ghost inset entirely, or losing the target fails. | `audit:ChatMessageBubble/theming` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This row lists filled as a covered state, but a filled bubble painted with the ghost's transparent surface, or with no sender style, passes every ChatMessageBubble, ChatMessage and theming-target test: the variant test only checks data-variant, and the Chromium visible-state test asserts contrast and corners, not the fill. Add "FR4: filled painting the sender fill" to the read-from-source list below, or add a test that fails when the fill is lost.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Promoting component:ChatMessageBubble to current now waits only on an engineering owner, who records the decision by commenting /approve-spec <full head SHA> on this pull request; the author may do this as an engineering owner. The earlier verification-map points are fixed: every credited test fails when its claim breaks, and the read-from-source list now names the filled sender fill. No other change is needed.

[Automated review]

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Promoting component:ChatMessageBubble to current now waits only on an engineering owner, who records the decision by commenting /approve-spec <full head SHA> on this pull request; the author may do this as an engineering owner. The record matches the shipped source, and its verification map credits only tests that fail when their claim breaks. Optionally, add an ORD2 line (consumer styling applied after an explicit width) to the read-from-source list, since no test covers that order.

[Automated review]

@cixzhang

cixzhang commented Nov 1, 2026

Copy link
Copy Markdown
Contributor Author

/approve-spec 4b6c358

@github-actions github-actions Bot removed the needs:spec-owner-review Current knowledge records await owner approval label Nov 1, 2026
@cixzhang
cixzhang merged commit 9b6d03e into main Nov 1, 2026
51 checks passed
@cixzhang
cixzhang deleted the spec-backfill/ChatMessageBubble branch November 1, 2026 17:33

This branch was successfully deployed

1 active deployment
Preview — 4b6c358d Deployed Nov 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant