Skip to content

feat(loop): wire ui_review drive + deck-fit to pass viewport/interaction to the state slug#1331

Merged
mfittko merged 3 commits into
mainfrom
issue-1321
Jul 11, 2026
Merged

feat(loop): wire ui_review drive + deck-fit to pass viewport/interaction to the state slug#1331
mfittko merged 3 commits into
mainfrom
issue-1321

Conversation

@mfittko

@mfittko mfittko commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Wires the production ui_review callers to the Stage-4 named-state slug seam (<state>-<viewport>-<interaction>). Stage 4 baked viewport + interaction-state into the slug and added a fail-closed duplicate-slug guard, but no production caller passed viewport/interaction — the discriminator was exercised only by the harness/unit contract. This ships the callers; it does not touch the seam or the slug format.

Scope and context

  • packages/core/src/config/config.mjs: the drive-step schema gains optional viewport ({ width, height }) and interactionState (route-named enum) leaves, so a flow can declare a responsive/stateful render.
  • scripts/loop/ui-review-drive.mjs: makeRunStep resizes the page to a declared viewport (via setViewportSize) and passes viewport + interactionState through to captureNamedUiState, so responsive/stateful renders become distinct slugged directories in production, not just in tests. Because the Playwright page stays resized across steps, an undeclared later step inherits the last explicitly-set viewport — so its slug faithfully reflects the size the page is actually at rather than mislabelling it default; default still applies to a never-resized flow.
  • test/playwright/harness/deck-fit-harness.mjs: drops the (mobile 390) name-hack from the mobile captures and passes viewport: MOBILE instead — the slug now carries the viewport rather than the state-name string.
  • test/contracts/deck-fit-harness-viewport-contract.test.mjs (new): a source-level pin (runs under test:assets, so part of verify) asserting the harness makes ≥2 viewport: MOBILE capture calls and embeds no viewport hack (mobile/390) in any stateName — so a revert of the name-hack removal is caught by verify, not only by a live browser spec.
  • docs/ui-review-recipe-contract.md + test/docs/ui-review-recipe-doc.test.mjs: document the two new schema fields (three leaves: viewport.width, viewport.height, interactionState) and update the leaf count accordingly.

Acceptance criteria

Satisfies #1321's ACs (checked off at merge): the live drive passes viewport/interactionState to captureNamedUiState so responsive/stateful renders slug distinctly in production; the deck-fit harness passes viewport instead of encoding it into the state name; harnesses that capture a state at multiple viewports use the slug discriminator, not a name hack; npm run verify green with existing named-state artifacts still validating.

Non-goals

Auto-enumerating interaction states (the spec/route names them; #1300 non-goal). Changing the slug format or the fail-closed guards shipped in #1300.

Validation

  • node --test test/loop/ui-review-drive.test.mjs test/loop/ui-smoke-harness.test.mjs — 50 pass (a caller now emits distinct viewport-slugged directories; the deck-fit name hack is gone); packages/core/test/config.test.mjs — 313 pass; test/docs/ui-review-recipe-doc.test.mjs — 2 pass.
  • npm run verify — green (test:assets 191, test:scripts 2700, test:extension 81, test:core, test:docs, test:pack, test:dev-loop 32); generate-claude-assets --check clean.

Closes #1321

Copilot AI review requested due to automatic review settings July 10, 2026 23:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR completes the Stage-4 ui_review wiring by ensuring production callers pass viewport and interactionState through to captureNamedUiState, so named-state artifact slugs (<state>-<viewport>-<interaction>) uniquely and correctly represent responsive/stateful renders outside of the test harness.

Changes:

  • Extend the ui_review drive-step config schema to allow optional viewport {width,height} and interactionState.
  • Update the live UI-review drive to apply a declared viewport and forward viewport/interactionState into captureNamedUiState.
  • Remove the deck-fit “(mobile 390)” state-name hack and instead pass viewport: MOBILE; update the recipe contract docs and schema-leaf count test.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/playwright/harness/deck-fit-harness.mjs Passes viewport: MOBILE so mobile/desktop captures disambiguate via slug rather than state-name text.
test/loop/ui-review-drive.test.mjs Adds regression coverage for viewport/interactionState slugging in the production drive wiring.
test/docs/ui-review-recipe-doc.test.mjs Updates the expected uiReview/worktree schema leaf count to reflect new keys.
scripts/loop/ui-review-drive.mjs Applies step viewport before actions and forwards viewport/interactionState to the named-state capture seam.
packages/core/test/config.test.mjs Adds schema validation tests for the new step leaves and fail-closed invalid values.
packages/core/src/config/config.mjs Extends UiReviewFlowStepConfig with optional viewport and interactionState.
docs/ui-review-recipe-contract.md Documents the new schema leaves and includes them in the canonical key list.

Comment thread scripts/loop/ui-review-drive.mjs Outdated
@mfittko mfittko marked this pull request as draft July 10, 2026 23:38
@mfittko

mfittko commented Jul 10, 2026

Copy link
Copy Markdown
Owner Author

Gate review: draft_gate

Reviewed head SHA: 051092dcedab578a109e6ff9711193f4c6d2b2d8
Verdict: clean
Execution mode: fanout_fanin

Findings summary: 6 angles reviewed; no findings (see per-angle breakdown below).

  • pr-description → clean
  • scope → clean
  • correctness → clean
  • coverage → clean
  • code-conformance → clean
  • contract-surface → clean

Next action: Draft gate clean at head 051092d (6 distinct reviewers; contract-surface carried from 28b5c58). Mark ready; request Copilot review.

@mfittko mfittko marked this pull request as ready for review July 10, 2026 23:38
Wire production callers to the Stage 4 slug discriminator. A drive flow step
may now declare a viewport (resized before the step) and an interactionState;
both are passed to captureNamedUiState so responsive/stateful renders land in
distinct slugged directories instead of colliding. The deck-fit harness drops
its "(mobile 390)" name hack and passes viewport: MOBILE, letting the slug
carry the viewport.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177JAWNT67FY6d48qQJeDwo

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Comment thread docs/ui-review-recipe-contract.md Outdated
Comment thread test/contracts/deck-fit-harness-viewport-contract.test.mjs
…oc sticky viewport

The source-pin regex only matched backtick template literals, so a name-hack
reintroduced via normal quotes or concatenation would evade it; anchor on the
stateName: assignment and forbid a viewport word on that line in any string
form. Also document that a step viewport is sticky — it persists to later steps
and an omitted viewport inherits the last set size rather than resetting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177JAWNT67FY6d48qQJeDwo

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread docs/ui-review-recipe-contract.md Outdated
Returning a later step to a different or the original size requires giving that
step an explicit viewport with the exact dimensions; omitting it inherits the
last set size. Removes the ambiguous 'return to the default dimensions' wording.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177JAWNT67FY6d48qQJeDwo
@mfittko

mfittko commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

Gate review: pre_approval_gate

Reviewed head SHA: 980a74eb8514ba7f896f577f5fcb3c9286fe3c8e
Verdict: clean
Execution mode: fanout_fanin

Findings summary: 5 angles reviewed; no findings (see per-angle breakdown below).; Copilot review rounds exhausted (2/2); current head has zero unresolved threads and green or credibly green CI, so pre_approval_gate fallback is allowed without another Copilot re-request.

  • pr-checklist-matrix → clean
  • acceptance-criteria → clean
  • yagni → clean
  • contradiction-lens → clean
  • correctness-final → clean

Next action: Pre-approval gate clean at head 980a74e (5 distinct reviewers). CI green; Copilot converged (3 rounds; doc-only bump carried forward, round-cap-clean). Proceed to merge.

@mfittko mfittko merged commit bd6f720 into main Jul 11, 2026
12 checks passed
@mfittko mfittko deleted the issue-1321 branch July 11, 2026 00:24
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.

feat(loop): wire ui_review callers (drive + deck-fit) to pass viewport/interaction to the state slug (follow-up to #1300)

2 participants