Skip to content

refactor(stream-react): migrate to live-docs orchestrator + custom-ui contract#33

Open
oliverlaz wants to merge 7 commits into
mainfrom
stream-react-live-docs
Open

refactor(stream-react): migrate to live-docs orchestrator + custom-ui contract#33
oliverlaz wants to merge 7 commits into
mainfrom
stream-react-live-docs

Conversation

@oliverlaz

@oliverlaz oliverlaz commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

Completes stream-react's migration from bundled blueprints to the live-docs orchestrator pattern established in #24 (iOS), adds the bespoke-UI completion contract, and removes the Task A.2 frontend-skill install gate. Two follow-up commits then address an xhigh code review of the migration and add a screenshot -> one-shot design-matching capability.

Commits

  • 70634c0 refactor: live-docs migration + custom-ui contract
  • 82e74d2 fix: close the custom-ui contract escape + add a version-pinning gate (code-review fixes)
  • 9040f1d feat: design-matching runbook for screenshot one-shot builds
  • efce6be fix: harden design-matching verify (no backend seeding) + add preview/header contracts (Codex adversarial-review fixes)

What changed (migration - 70634c0)

  • docs-map.md (renamed from DOCS.md): teaches the .md-twin convention, the per-product live CLI index, and a URL-grounding rule so the router self-heals instead of rotting. Fixes a stale Feeds quick-start path.
  • custom-ui.md (new): prebuilt-vs-bespoke decision rubric, the headless Chat/Video path (context hooks), a route-to-live table, and a REQUIRED completion contract - each region's sub-features must be reproduced, marked N/A - <design reason>, or labelled GAP - not implemented. Stops a custom message row from silently dropping attachments, reactions, quoted replies, receipts, and threads.
  • Router fix: writing your own component for a prebuilt region now routes through custom-ui.md before building - at all three decision points (RULES.md, docs-map.md, SKILL.md) - even when wired via the documented Message= / WithComponents prop.
  • Surgical blueprint trim: CHAT-blueprints.md -688, VIDEO-blueprints.md -473. Removed the doc-mirroring markup; kept the canonical provider trees and the prebuilt happy path (still deterministic/offline for the Track A scaffold). Light trims to CHAT.md / VIDEO.md; the Track F audit checklist is preserved.
  • Remove Task A.2: stream-react no longer installs third-party frontend skills or prompts for consent. If such packs are already present in the session it uses them for generic UI polish only; Stream references remain authoritative for SDK wiring.

Divergence note

stream-builder still shares the older web references and retains its Task A.2. That divergence is intentional (this PR is scoped to stream-react) and is documented inline in stream-react/RULES.md. stream-builder is the follow-up migration target.

Follow-up: code-review fixes (82e74d2)

An xhigh multi-angle review of the migration surfaced defects in the PR's own new files; this commit fixes the load-bearing ones:

  • custom-ui.md self-cancelling gate: the completion-contract file opened "read this only when the user wants fully hand-built UI" while the router sent single-region WithComponents / Message= overrides to it - so an agent could read the opening, conclude "not me", and bail past the contract. Rewrote the opening + Step 0 so the gate is "are you writing your own component for a region? yes -> the contract applies"; fully-headless vs injection is now framed as an architecture choice, not a contract escape. (GREEN: 3/3 subagents apply the contract, none bail.)
  • version-pinning gate: enhance.md / scaffold now read the installed Stream major before applying blueprint API names (blueprints assume Chat React v14: MessageComposer, css/index.css), so a v13 project routes to its own docs instead of shipping v14-only imports.
  • predicate de-duplication: collapsed the "custom component for a region" predicate to one wording across RULES.md (canonical), SKILL.md, enhance.md, CHAT.md, VIDEO.md, builder-ui.md (they had drifted; some still said "fully bespoke UI").

Follow-up: design-matching / screenshot one-shot (9040f1d)

Adds the ability to reproduce a design from a single screenshot / Figma / "make it look like X" - which the skill previously had zero support for (the review's biggest gap). Ports the stream-swift design-matching pattern to React:

  • references/design-matching.md (new): decompose the image into a written region / color / type / dimension spec (measure + sample, don't eyeball) -> route each region to a Stream component + mechanism (theming / WithComponents injection -> the completion contract / bespoke) -> match the palette via the shadcn preset + str-chat theming (not globals.css) -> ground names on the live page + installed major -> build batched -> verify with a throwaway seed + render-and-compare (Preview MCP: preview_start / preview_screenshot / preview_inspect / preview_resize), then delete the seed.
  • hooks: a styling-depth flag in SKILL.md dispatch routes screenshot requests through the runbook before building (Track A + E); Step 1b skips the theme question when a reference design already dictates it; a RULES.md design-matching exception to the "don't edit globals.css" rule; a custom-ui.md back-pointer.
  • Dry-run GREEN (2/2, Track A + Track E): both route through design-matching, skip the redundant theme question, decompose a spec, bind custom regions to the completion contract, and plan the render-and-compare verify loop.

Follow-up: Codex adversarial-review fixes (efce6be)

An adversarial review of design-matching.md flagged two issues, both fixed:

  • Verification no longer seeds the configured Stream app (high). Step 6 (and custom-ui.md's Verify) now default to local fixtures - render custom components against hand-authored message / channel objects, zero backend writes - and gate any backend seeding behind explicit user confirmation + a disposable / dev app with tracked, verified teardown. This defers to the no-auto-seeding invariant instead of carving it out.
  • Completion contracts added for channel preview + header (medium). The design-matching router sent these regions to injection, but custom-ui.md had no checklist for them, so unread / active state could be silently dropped. Both now have contract tables; the composer + call-layout contracts were also upgraded from prose to checkbox tables (closing the earlier review's finding feat(skills): add stream-docs #3).

Testing

Validated with subagent pressure tests (RED -> GREEN), not just inspection:

  • Custom-row completeness (migration): prose "don't drop sub-features" was non-binding (0/6 complete across control + prose arms, each dropping a different subset); the structural completion contract drove 3/3 complete with variance collapsed.
  • Routing reachability (migration): a live run proved a correct contract in an unreachable file is still RED - the router fix made it 3/3 reachable.
  • N/A loophole (migration): closed the "deferred = N/A" escape hatch; retest under amped time pressure showed 0/3 laundering (omissions surface as explicit GAPs).
  • Contract-escape fix (82e74d2): 3/3 subagents reading the fixed files apply the contract for a single WithComponents override; none bail on the "it's only one component" framing.
  • Design-matching (9040f1d): 2/2 dry-runs (Track A build + Track E enhance) route through the runbook and execute the decompose -> map -> contract -> verify flow.
  • Codex-review fixes (efce6be): seed-safety 2/2 (fixtures default, no unprompted backend writes, gated behind confirmation + disposable app) + preview-contract 1/1 (unread badge + active state reproduced, not dropped).

All changed files are ASCII-only per repo policy.

oliverlaz added 7 commits July 1, 2026 10:09
… contract

Complete stream-react's transition from bundled blueprints to the PR #24
live-docs pattern, add the bespoke-UI completion contract, and remove the
Task A.2 frontend-skill install gate.

- docs-map.md (was DOCS.md): teach the .md-twin convention + per-product live
  CLI index + URL-grounding rule so the router self-heals instead of rotting;
  fix a stale Feeds quick-start path.
- custom-ui.md (new): prebuilt-vs-bespoke rubric, headless Chat/Video path,
  route-to-live table, and a REQUIRED completion contract (reproduce /
  N/A-with-design-reason / GAP) that stops custom rows from silently dropping
  attachments, reactions, quoted replies, receipts, threads.
- Router fix: writing your own component for a prebuilt region now loads
  custom-ui.md first (RULES/docs-map/SKILL), even via Message=/WithComponents.
- Surgical blueprint trim: CHAT -688, VIDEO -473 (drop doc-mirror; keep the
  canonical provider trees + prebuilt happy path). Light trims to CHAT/VIDEO.
- Remove Task A.2: stream-react no longer installs third-party frontend skills
  or prompts for consent; uses them only if already present. stream-builder
  retains A.2 (divergence documented in RULES.md).

Validated RED->GREEN with subagent pressure tests (custom-row completeness,
routing reachability, N/A-loophole). ASCII-clean.
…ing gate

Address xhigh code-review findings on the live-docs migration.

- custom-ui.md: the entry gate contradicted the router - it opened "read this
  only when the user wants fully hand-built UI" and Step 0 scoped bespoke to
  "replace message row + composer + list + header at once", so an agent routed
  in for a single WithComponents/Message= override could read the opening and
  bail past the completion contract. Rewrite the opening + Step 0 so the gate is
  "are you writing your own component for a region? yes -> contract applies";
  fully-headless vs injection is now framed as an architecture choice, not a
  contract escape. (GREEN: 3/3 subagents apply the contract, none bail.)
- enhance.md / SKILL.md: add a version-detect step - read the installed Stream
  major before applying blueprint API names (blueprints assume Chat React v14:
  MessageComposer, css/index.css), so a v13 project routes to its own docs
  instead of shipping v14-only imports.
- Collapse the "custom component for a region" predicate to one wording across
  RULES.md (canonical), SKILL.md, enhance.md, CHAT.md, VIDEO.md, builder-ui.md
  (they had drifted; enhance + product files still said "fully bespoke UI").
…ot builds

New references/design-matching.md + hooks so a screenshot / Figma / "make it look
like X" request reproduces the design region by region instead of falling through
to a generic scaffold. Ports the stream-swift design-matching pattern to React
(shadcn + str-chat theming + Preview-MCP verify).

- design-matching.md (new): work-in-batches; decompose the image into a written
  region/color/type/dimension spec (measure + sample, don't eyeball); route each
  region to a Stream component + mechanism (theming / WithComponents injection ->
  the custom-ui completion contract / bespoke); match the palette via the shadcn
  preset + str-chat theming (not globals.css); ground names on the live page +
  installed major; build batched; verify with a throwaway seed + render-and-compare
  (Preview MCP), then delete the seed.
- SKILL.md: a styling-depth flag in dispatch routes screenshot/Figma/"look like X"
  requests through design-matching.md before building (Track A + E); Step 1b skips
  the theme question when a reference design already dictates it.
- RULES.md: a design-matching exception to the "don't edit globals.css" rule (match
  via preset + documented str-chat variables).
- custom-ui.md: back-pointer to design-matching.md.

Dry-run GREEN (2/2, Track A + Track E): both route through design-matching, skip the
redundant theme question, decompose a spec, bind custom regions to the completion
contract, and plan the render-and-compare verify loop.
… contracts

Address the Codex adversarial review of design-matching.md.

- Verification no longer seeds the configured Stream app. design-matching.md
  Step 6 and custom-ui.md's Verify now default to LOCAL fixtures (render custom
  components against hand-authored message/channel objects, zero backend writes);
  backend seeding is gated behind explicit user confirmation + a disposable/dev
  app with tracked, verified teardown. Defers to the no-auto-seeding invariant
  instead of carving it out. (GREEN 2/2: agents use fixtures, refuse to seed the
  configured app under time pressure.)
- custom-ui.md now defines completion-contract tables for the two regions the
  design-matching router sends to injection but that previously had no checklist:
  Channel preview (display name, last message, timestamp, unread badge, active
  state, avatar/presence, muted/pinned) and Channel header. (GREEN 1/1: agent
  reproduces the unread badge + active state instead of dropping them.)
- Upgrade the composer + call-layout contracts from prose to checkbox tables so
  every router-governed region has an executable checklist (closes the earlier
  review's finding #3); folds back dropped gotchas (keystroke/stopTyping,
  hasAudio/hasVideo, listDevices-returns-an-Observable).
…tep + fix citation

Address review findings #8 (CSS dedup), #11 (grounding), #12 (citation).

- #8c CSS imports: sdk.md > CSS imports is now the single canonical home (v14
  alias, v13 path, dist/css/index.css also resolves, and the separate
  EmojiPicker stylesheet). CHAT.md, builder-ui.md, enhance.md point there instead
  of each restating the variants - fixes the inconsistency where the
  emoji-picker note existed in only some copies.
- #11 grounding: custom-ui.md gains a runnable "ground the symbol before wiring"
  step (node -e require(...) / grep the installed .d.ts) so a version-wrong
  export name is caught against the installed package, not just prose "confirm on
  the page".
- #12 citation: CROSS-PRODUCT.md cited a non-fetchable numbered content-repo path
  (video/react/10-advanced/06-chat-with-video.md); replaced with the grounded
  docs-map URL (Video React > Advanced Guides > Chat Integration).

Not changed (deliberate, to avoid over-dedup): #8a the strict-mode client snippet
stays inline in CROSS-PRODUCT.md's AppShell (a complete runnable example) with
VIDEO.md the canonical it mirrors; #8b the composer-rename one-liners are
consistent and low-drift, CHAT.md > Gotchas canonical.
… + fill-parent layout

Fresh references/design-matching.md (Classify -> Spec -> Route -> Ground -> Build
-> verify loop): per-product signal->concept taxonomy (chat/video/feeds), fidelity
tiers + viewport derivation, and an empirical verify loop - isolated .design-verify
Playwright harness, capture recipe + probe spec, per-region discrepancy table, loop
cap, GAP-not-matched vocabulary, anti-rationalization table. Includes ChannelList /
MessageList empty + loading states.

references/custom-ui.md: feeds completion contracts (activity card / comment row /
feed composer) + headless-Feeds path + routing rows; empty/loading regions; fix a
stale ../../stream/RULES.md relative link.

builder-ui.md: Stream regions must grow to fill their parent (flex + min-w-0 +
height chain; override the SDK default channel-list width via the documented
str-chat variable).

RULES.md + SKILL.md: repoint design-matching citations to section names; add the
Playwright verify-loop install-trust row + a narrow Bash(node .design-verify/*)
permission; reword the styling-depth flag to the new pipeline.
…auth flow

builder-ui.md: add the Reference-design override (the reference's frame wins over
the generic shell) and make the App Header a default-shell element that is omitted
when the reference design shows no top-bar.

SKILL.md: move Step 1 auth to `getstream init` (opens the browser as its own
invocation when unsigned); drop the removed pre-1.0 `OrganizationRead` probe and
note `getstream api` is now product-namespaced; reword the Step 1b app pick around
the configured-app default.
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.

1 participant