Skip to content

a11y(frontend): complete color radio-group keyboard contract - #730

Closed
seonghobae wants to merge 22 commits into
mainfrom
palette/color-swatch-a11y-10094327760965026187
Closed

seonghobae wants to merge 22 commits into
mainfrom
palette/color-swatch-a11y-10094327760965026187

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 3, 2026 •

Copy link
Copy Markdown
Collaborator

What

Aligns the Business Group color selector with the WAI-ARIA radio-group interaction contract.

  • retains the role="radiogroup" container;
  • exposes each mutually exclusive swatch as role="radio" with aria-checked;
  • keeps only the selected radio in the tab sequence through roving tabIndex;
  • moves both selection and focus with Left/Right/Up/Down Arrow keys, including wraparound;
  • preserves native button click and Space activation;
  • preserves the selected visual state through the matching CSS selector.

Regression coverage

Focused tests verify checked state, a single tab stop, click and Space activation, forward and backward arrow navigation, wrapping at both ends, unrelated-key handling, and a safe first-radio fallback when an unknown color is supplied.

The repository-wide coverage contract also exercises the previously uncovered Prisma download, modal cancel/validation, malformed relation-handle, and singular back-relation paths. These are test-only additions; production behavior is unchanged.

Evidence

docs/doctoring/accessibility-radio-group.md records the W3C WAI-ARIA Authoring Practices implementation standard and the supporting keyboard-accessibility study with a full citation, DOI link, and concise applicability summary. CHANGELOG.md records the implemented user-visible behavior.

Scope

The branch changes the color-selector component and styles, accessibility evidence and changelog, focused component tests, and test-only repository coverage cases. It makes no dependency, package-manager, database, API, or runtime-service contract change.

Verification

Local evidence on the published tree:

  • focused tests: 4 files, 35 tests passed;
  • complete frontend suite: 28 files, 202 tests passed;
  • coverage: 100% statements (1513/1513), branches (1150/1150), functions (324/324), and lines (1368/1368);
  • TypeScript typecheck passed;
  • production build passed;
  • git diff --check passed.

Exact-head CI, Security Scan, Semgrep, zero unresolved valid findings, and qualifying independent current-head approval remain mandatory before merge. Queued or predecessor evidence is not treated as passing.

Protected-main reconciliation

Exact head e34178ec0c41f3e72ea611d097f2ef1481c53f8a is a two-parent reconciliation with protected main 3c1c7aae7b72e34ca9b48b578b0573736daba8fd.

  • The effective diff against protected main remains limited to the eight intended accessibility implementation, regression, evidence, style, and changelog files.
  • Protected-main search/polling implementation, tests, and doctoring evidence are preserved byte-for-byte.
  • Both unreleased changelog entries are preserved additively.
  • Focused verification: 4 files, 22 tests passed.
  • Complete frontend suite: 29 files, 206 tests passed.
  • TypeScript typecheck, production build, and git diff --check passed.

Exact-head CI, security scans, zero unresolved valid findings, and qualifying independent non-author approval remain mandatory before merge. Predecessor approvals or checks are not treated as current-head evidence.

@google-labs-jules

Copy link
Copy Markdown

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@seonghobae, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6dc7ae60-84d2-4cc7-b132-d460693be437

📥 Commits

Reviewing files that changed from the base of the PR and between cac4d09 and 91e73d5.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx
  • frontend/src/components/modals/GroupModal.tsx
📝 Walkthrough

Walkthrough

GroupModal의 색상 선택기를 WAI-ARIA 라디오 그룹으로 변경했습니다. 방향키 선택, 포커스 이동, 순환 동작과 단일 roving tab stop을 구현했습니다. 관련 스타일, 테스트, 접근성 문서와 변경 이력을 갱신했습니다.

Changes

색상 선택 접근성

Layer / File(s) Summary
색상 라디오 의미와 키보드 처리
frontend/src/components/modals/GroupModal.tsx, frontend/src/styles.css, frontend/src/components/modals/ModalCoverage.test.tsx
색상 요소가 role="radio"와 aria-checked를 사용합니다. 선택된 요소만 tabIndex=0을 사용합니다. 방향키 입력은 선택과 포커스를 순환 이동합니다. 스타일과 테스트 쿼리를 갱신했습니다.
라디오 동작 검증과 문서화
frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx, docs/doctoring/accessibility-radio-group.md, CHANGELOG.md
탭 순서, 방향키 순환, 무관한 키 입력, 팔레트 외 초기 색상을 검증합니다. 라디오 그룹 동작과 변경 이력을 문서화했습니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 색상 라디오 그룹의 키보드 접근성 계약 완성을 명확하게 요약하며 주요 변경 사항과 일치합니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch palette/color-swatch-a11y-10094327760965026187

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@seonghobae
seonghobae enabled auto-merge (squash) August 4, 2026 06:08

Copy link
Copy Markdown
Collaborator Author

@opencode-agent @cwl-noema-review Please independently review exact current head 87938821dc15818359ad018fc62a231623f85f48. Confirm the custom color selector exposes a coherent radio-group contract with role=radio, aria-checked, retained visual selection, and no keyboard/accessibility regression. Exact-head CI, Security Scan, and Semgrep are green; submit APPROVE only if no blocker remains.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/modals/GroupModal.tsx (1)

78-84: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

라디오 그룹의 키보드 동작을 구현하세요.

현재 각 button이 기본 Tab 순서에 포함되지만, 화살표 키 처리와 tabIndex 관리가 없습니다. 선택된 항목에만 tabIndex={0}을 설정하고 화살표 키로 선택과 포커스를 함께 이동하세요. 또는 네이티브 <input type="radio">를 사용하세요. 관련 키보드 동작을 테스트로 추가하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/components/modals/GroupModal.tsx` around lines 78 - 84, Update
the color swatch radio controls in GroupModal so only the selected color has
tabIndex={0} and all others have tabIndex={-1}; add keyboard handling for
ArrowUp/ArrowDown/ArrowLeft/ArrowRight to select and focus the corresponding
swatch, with appropriate wrapping, while preserving existing click behavior. Add
tests covering roving tabIndex and arrow-key selection/focus behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@frontend/src/components/modals/GroupModal.tsx`:
- Around line 78-84: Update the color swatch radio controls in GroupModal so
only the selected color has tabIndex={0} and all others have tabIndex={-1}; add
keyboard handling for ArrowUp/ArrowDown/ArrowLeft/ArrowRight to select and focus
the corresponding swatch, with appropriate wrapping, while preserving existing
click behavior. Add tests covering roving tabIndex and arrow-key selection/focus
behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 441e0e0e-4ced-417c-a2c0-3e4d7656efca

📥 Commits

Reviewing files that changed from the base of the PR and between 72afe6d and 85de93d.

⛔ Files ignored due to path filters (2)
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .Jules/palette.md
  • frontend/package.json
  • frontend/src/components/modals/GroupModal.tsx
  • frontend/src/components/modals/ModalCoverage.test.tsx
  • frontend/src/styles.css

Copy link
Copy Markdown
Collaborator Author

@opencode-agent Please review exact current head cbb049c553712b913a0dee0221091d015bd772f7 after queued checks complete. The branch was narrowed to exactly three frontend files; all npm downgrades, the second package-manager lock, and palette-history drift were removed. Verify WAI-ARIA radio-group semantics, CSS selected-state parity, and focused tests. Submit APPROVE only if no blocker remains.

Copy link
Copy Markdown
Collaborator Author

@cwl-noema-review Please independently review exact current head cbb049c553712b913a0dee0221091d015bd772f7 after checks complete. Confirm the branch contains only the radio-group accessibility change and tests, with no dependency or package-manager drift; submit APPROVE only if no blocker remains.

@seonghobae seonghobae changed the title 🎨 Palette: 커스텀 라디오 그룹(색상 선택기) 접근성 개선 a11y(frontend): complete color radio-group keyboard contract Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

@opencode-agent @cwl-noema-review Please independently review exact current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Current-head CI, Security Scan, and SAST Semgrep are successful. Verify WAI-ARIA radio-group semantics, one roving tab stop, ArrowLeft/Right/Up/Down selection-and-focus with wraparound, click and Space behavior, safe unknown-color fallback, visual checked-state selector, focused tests, and the APA 7th doctoring record. Submit APPROVE only for this exact head if no blocking finding remains.

Copy link
Copy Markdown
Collaborator Author

@opencode-agent Please review exact current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Verify the color selector implements the WAI-ARIA radio-group contract with one roving tab stop, arrow-key selection and focus in four directions with wraparound, click and Space compatibility, safe unknown-color fallback, complete focused coverage, and accurate APA 7 doctoring. Current-head CI, Security Scan, Semgrep, and CodeRabbit are green; submit APPROVE only if no blocking finding remains.

Copy link
Copy Markdown
Collaborator Author

@cwl-noema-review Please independently review exact current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Confirm the semantic radio contract, focus movement, wrapping, visual state, and keyboard regressions match WAI-ARIA practice without introducing an inaccessible custom-control edge. Submit APPROVE only if no blocker remains.

@google-labs-jules

Copy link
Copy Markdown

@opencode-agent @cwl-noema-review Please independently review exact current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Current-head CI, Security Scan, and SAST Semgrep are successful. Verify WAI-ARIA radio-group semantics, one roving tab stop, ArrowLeft/Right/Up/Down selection-and-focus with wraparound, click and Space behavior, safe unknown-color fallback, visual checked-state selector, focused tests, and the APA 7th doctoring record. Submit APPROVE only for this exact head if no blocking finding remains.

Ignored as this is addressed to other review bots.

@google-labs-jules

Copy link
Copy Markdown

@opencode-agent Please review exact current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Verify the color selector implements the WAI-ARIA radio-group contract with one roving tab stop, arrow-key selection and focus in four directions with wraparound, click and Space compatibility, safe unknown-color fallback, complete focused coverage, and accurate APA 7 doctoring. Current-head CI, Security Scan, Semgrep, and CodeRabbit are green; submit APPROVE only if no blocking finding remains.

Ignored as this is addressed to other review bots.

@google-labs-jules

Copy link
Copy Markdown

@cwl-noema-review Please independently review exact current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Confirm the semantic radio contract, focus movement, wrapping, visual state, and keyboard regressions match WAI-ARIA practice without introducing an inaccessible custom-control edge. Submit APPROVE only if no blocker remains.

Ignored as this is addressed to other review bots.

Copy link
Copy Markdown
Collaborator Author

@opencode-agent @cwl-noema-review Please perform a fresh independent review of current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Repository CI, Security Scan, Semgrep, and CodeRabbit are green; no unresolved inline threads remain. The prior roving-tabindex and Arrow-key finding has been implemented with focused wraparound/focus regressions and WAI-ARIA doctoring.

@google-labs-jules

Copy link
Copy Markdown

@opencode-agent @cwl-noema-review Please perform a fresh independent review of current head 4ce05b341b7804ad1abd88486aa8446e02361d68. Repository CI, Security Scan, Semgrep, and CodeRabbit are green; no unresolved inline threads remain. The prior roving-tabindex and Arrow-key finding has been implemented with focused wraparound/focus regressions and WAI-ARIA doctoring.

Ignored as this is addressed to other review bots.

Copy link
Copy Markdown
Collaborator Author

Addressed both current-head CodeRabbit findings in 33098bf22d99b18e59cedec9f74ee79422e355f9: the doctoring record now includes a summarized peer-reviewed keyboard-accessibility study with full ACM/DOI citation, and focused regressions verify click and Space activation update aria-checked and the single roving tab stop. The full coverage run also exposed and closed five pre-existing test gaps without production-code changes. Local published-tree evidence: 4 focused files / 35 tests passed; full suite 28 files / 202 tests passed; statements 1513/1513, branches 1150/1150, functions 324/324, lines 1368/1368; typecheck, production build, and git diff --check passed. Exact-head CI 31473741615, Security Scan 31473741605, and SAST Semgrep 31473741632 are newly queued and are not treated as passing.

Copy link
Copy Markdown
Collaborator Author

Exact-current-head independent review request for 33098bf22d99b18e59cedec9f74ee79422e355f9. CI 31473741615, Security Scan 31473741605, and SAST Semgrep 31473741632 are terminal-success on this SHA, and there are zero unresolved review threads. Review only the radio-group keyboard contract, review remediation, and exact 100% owned frontend coverage on this exact head; no predecessor, queued, rate-limited, or status-only evidence transfers.

@coderabbitai review
@opencode-agent review
@cwl-noema-review review

Do not modify the branch, bypass protection, merge, tag, release, or publish.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected_sha="33098bf22d99b18e59cedec9f74ee79422e355f9"

printf '%s\n' '== Checked-out commit =='
git rev-parse HEAD
git status --short
git merge-base --is-ancestor "$expected_sha" HEAD && echo "EXPECTED_SHA_IS_ANCESTOR=true" || echo "EXPECTED_SHA_IS_ANCESTOR=false"

printf '%s\n' '== Exact commit files and diff summary =='
git show --no-ext-diff --format=fuller --stat --summary "$expected_sha"
git diff-tree --no-commit-id --name-status -r "$expected_sha"
git show --no-ext-diff --format= --check "$expected_sha"
git show --no-ext-diff --format= "$expected_sha" -- \
  frontend/src/components/modals/GroupModal.tsx \
  frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx \
  frontend/src/components/modals/ModalCoverage.test.tsx \
  frontend/src/styles.css \
  docs/doctoring/accessibility-radio-group.md \
  CHANGELOG.md

printf '%s\n' '== Source outlines =='
ast-grep outline frontend/src/components/modals/GroupModal.tsx --items all
ast-grep outline frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx --items all
ast-grep outline frontend/src/components/modals/ModalCoverage.test.tsx --items all

printf '%s\n' '== Relevant implementation and test text =='
nl -ba frontend/src/components/modals/GroupModal.tsx | sed -n '1,280p'
nl -ba frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx | sed -n '1,260p'
nl -ba frontend/src/components/modals/ModalCoverage.test.tsx | sed -n '1,260p'
rg -n -C 4 'groupManager__swatch|aria-checked|aria-pressed' frontend/src/styles.css
nl -ba docs/doctoring/accessibility-radio-group.md | sed -n '1,220p'
rg -n -C 3 'radio|roving|Arrow|arrow|Group' CHANGELOG.md

printf '%s\n' '== GitHub exact-head metadata =='
gh pr view 730 --repo ContextualWisdomLab/pg-erd-cloud \
  --json headRefOid,mergeStateStatus,reviewDecision,statusCheckRollup,comments,reviews \
  --jq '{headRefOid,mergeStateStatus,reviewDecision,statusCheckRollup:[.statusCheckRollup[]|{name,conclusion,status,detailsUrl}],reviews:[.reviews[]|{author:.author.login,state,commit:.commit.oid}],commentCount:(.comments|length)}'

Length of output: 10909


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected_sha="33098bf22d99b18e59cedec9f74ee79422e355f9"
repo="ContextualWisdomLab/pg-erd-cloud"

printf '%s\n' '== Pull request base and cumulative scope =='
gh pr view 730 --repo "$repo" --json baseRefOid,headRefOid,changedFiles,files \
  --jq '{baseRefOid,headRefOid,changedFiles,files:[.files[]|{path,additions,deletions}]}'
base_sha="$(gh pr view 730 --repo "$repo" --json baseRefOid --jq '.baseRefOid')"
printf 'BASE_SHA=%s\nHEAD_SHA=%s\n' "$base_sha" "$expected_sha"
git diff --no-ext-diff --check "$base_sha" "$expected_sha"
git diff --no-ext-diff --name-status "$base_sha" "$expected_sha"
git diff --no-ext-diff --unified=80 "$base_sha" "$expected_sha" -- \
  frontend/src/components/modals/GroupModal.tsx \
  frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx \
  frontend/src/components/modals/ModalCoverage.test.tsx \
  frontend/src/styles.css \
  docs/doctoring/accessibility-radio-group.md \
  CHANGELOG.md

printf '%s\n' '== GroupModal implementation =='
sed -n '1,330p' frontend/src/components/modals/GroupModal.tsx

printf '%s\n' '== Radio-group focused tests =='
sed -n '1,280p' frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx

printf '%s\n' '== Selected-state styles =='
rg -n -C 5 'groupManager__swatch|aria-checked|aria-pressed|:focus' frontend/src/styles.css

printf '%s\n' '== Doctoring record =='
sed -n '1,240p' docs/doctoring/accessibility-radio-group.md

printf '%s\n' '== Exact-head GitHub checks and reviews =='
gh pr view 730 --repo "$repo" \
  --json headRefOid,mergeStateStatus,reviewDecision,statusCheckRollup,reviews \
  --jq '{headRefOid,mergeStateStatus,reviewDecision,statusCheckRollup:[.statusCheckRollup[]|{name,conclusion,status,detailsUrl}],reviews:[.reviews[]|{author:.author.login,state,commit:.commit.oid}]}'

printf '%s\n' '== Unresolved review threads =='
pr_id="$(gh pr view 730 --repo "$repo" --json id --jq '.id')"
gh api graphql -F prId="$pr_id" -f query='
query($prId: ID!) {
  node(id: $prId) {
    ... on PullRequest {
      reviewThreads(first: 100) {
        nodes {
          isResolved
          isOutdated
          path
          line
          comments(first: 20) {
            nodes { author { login } body }
          }
        }
      }
    }
  }
}' --jq '[.data.node.reviewThreads.nodes[] | select(.isResolved == false) | {isOutdated,path,line,comments:[.comments.nodes[]|{author:.author.login,body}]}]'

Length of output: 54073


@seonghobae Approved for exact head 33098bf22d99b18e59cedec9f74ee79422e355f9.

I found no blocking issue in the requested scope.

  • The selector has a radiogroup container and radio controls with accurate aria-checked.
  • The checked color is the only normal tab stop. An unknown color safely gives the first radio the single tab stop.
  • ArrowLeft, ArrowRight, ArrowUp, and ArrowDown update selection and focus. Navigation wraps at both ends.
  • Click and Space activation remain available through native buttons. Focused tests verify both paths and the roving tab stop.
  • The selected visual style now uses [aria-checked="true"].
  • The accessibility record describes the contract and includes the requested W3C and ACM/DOI references.
  • Exact-head GitHub checks report successful frontend, coverage, security, dependency, and SAST gates.
  • GitHub reports zero unresolved review threads.

[approve]

You are interacting with an AI system.

@opencode-agent

Copy link
Copy Markdown
Contributor

Queued @cwl-noema-review for PR #730 at head 33098bf22d99b18e59cedec9f74ee79422e355f9. Central exact-name Actions artifacts are the durable dispatch ledger; existing review workflows remain authoritative for the final verdict and failure evidence.

@opencode-agent

Copy link
Copy Markdown
Contributor

Queued @cwl-noema-review for PR #730 at head 33098bf22d99b18e59cedec9f74ee79422e355f9. Central exact-name Actions artifacts are the durable dispatch ledger; existing review workflows remain authoritative for the final verdict and failure evidence.

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

Please review exact head e34178ec0c41f3e72ea611d097f2ef1481c53f8a after its protected-main reconciliation. Predecessor findings, checks, and approvals are not current-head evidence.

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/pg-erd-cloud"
pr_number="730"
expected_sha="e34178ec0c41f3e72ea611d097f2ef1481c53f8a"

echo '== Exact-head identity =='
printf 'CHECKED_OUT_SHA='
git rev-parse HEAD
printf 'EXPECTED_SHA=%s\n' "$expected_sha"
git status --short
gh pr view "$pr_number" --repo "$repo" --json headRefOid,baseRefOid \
  --jq '{headRefOid,baseRefOid}'

echo '== Current PR scope against its live base =='
base_sha="$(gh pr view "$pr_number" --repo "$repo" --json baseRefOid --jq '.baseRefOid')"
git diff --check "$base_sha" "$expected_sha"
git diff --name-status "$base_sha" "$expected_sha"
git diff --stat "$base_sha" "$expected_sha"
git diff --unified=60 "$base_sha" "$expected_sha" -- \
  frontend/src/components/modals/GroupModal.tsx \
  frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx \
  frontend/src/components/modals/ModalCoverage.test.tsx \
  frontend/src/styles.css \
  docs/doctoring/accessibility-radio-group.md \
  CHANGELOG.md

echo '== Reconciliation commit and changed files =='
git show --format=fuller --stat --summary "$expected_sha"
git diff-tree --no-commit-id --name-status -r "$expected_sha"
git show --format= --check "$expected_sha"

echo '== Implementation map and relevant source =='
ast-grep outline frontend/src/components/modals/GroupModal.tsx --items all
ast-grep outline frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx --items all
sed -n '1,360p' frontend/src/components/modals/GroupModal.tsx
sed -n '1,320p' frontend/src/components/modals/GroupModal.radioKeyboard.test.tsx
sed -n '1,300p' frontend/src/components/modals/ModalCoverage.test.tsx
rg -n -C 6 'groupManager__swatch|aria-checked|aria-pressed|:focus' frontend/src/styles.css
sed -n '1,260p' docs/doctoring/accessibility-radio-group.md
rg -n -C 3 'radio|roving|Arrow|arrow|Group' CHANGELOG.md

echo '== Current exact-head checks and reviews =='
gh pr view "$pr_number" --repo "$repo" \
  --json headRefOid,mergeStateStatus,reviewDecision,statusCheckRollup,reviews \
  --jq '{headRefOid,mergeStateStatus,reviewDecision,statusCheckRollup:[.statusCheckRollup[]|{name,conclusion,status,detailsUrl}],reviews:[.reviews[]|{author:.author.login,state,commit:.commit.oid}]}'

echo '== Unresolved review threads =='
pr_id="$(gh pr view "$pr_number" --repo "$repo" --json id --jq '.id')"
gh api graphql -F prId="$pr_id" -f query='
query($prId: ID!) {
  node(id: $prId) {
    ... on PullRequest {
      reviewThreads(first: 100) {
        nodes {
          isResolved
          isOutdated
          path
          line
          comments(first: 20) {
            nodes { author { login } body }
          }
        }
      }
    }
  }
}' --jq '[.data.node.reviewThreads.nodes[] | select(.isResolved == false) | {isOutdated,path,line,comments:[.comments.nodes[]|{author:.author.login,body}]}]'

Length of output: 65195


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/pg-erd-cloud"
pr_number="730"
expected_sha="e34178ec0c41f3e72ea611d097f2ef1481c53f8a"
base_sha="$(gh pr view "$pr_number" --repo "$repo" --json baseRefOid --jq '.baseRefOid')"

echo '== Reconciliation source map =='
ast-grep outline frontend/src/App.tsx --items all
ast-grep outline frontend/src/App.searchPolling.test.tsx --items all

echo '== Reconciliation changes against the live PR base =='
git diff --check "$base_sha" "$expected_sha" -- \
  frontend/src/App.tsx \
  frontend/src/App.searchPolling.test.tsx \
  docs/doctoring/search-identity-and-sequential-polling.md
git diff --unified=80 "$base_sha" "$expected_sha" -- \
  frontend/src/App.tsx \
  frontend/src/App.searchPolling.test.tsx \
  docs/doctoring/search-identity-and-sequential-polling.md

echo '== Current reconciliation implementation and tests =='
sed -n '1,420p' frontend/src/App.tsx
sed -n '1,380p' frontend/src/App.searchPolling.test.tsx
sed -n '1,260p' docs/doctoring/search-identity-and-sequential-polling.md

echo '== Current exact-head checks =='
gh pr view "$pr_number" --repo "$repo" --json headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{headRefOid,mergeStateStatus,statusCheckRollup:[.statusCheckRollup[]|select(.name != null)|{name,conclusion,status,detailsUrl}]}'

Length of output: 36749


@seonghobae I reviewed exact head e34178ec0c41f3e72ea611d097f2ef1481c53f8a.

I found no blocking source-level issue.

  • The color selector uses radiogroup, radio, and accurate aria-checked.
  • The selected color is the only normal tab stop.
  • The fallback makes the first radio tabbable when the input color is unknown.
  • ArrowLeft, ArrowRight, ArrowUp, and ArrowDown update selection and focus. Navigation wraps at both ends.
  • Native button click and Space activation remain available.
  • The selected visual state uses [aria-checked="true"].
  • Focused tests cover the requested keyboard, activation, roving-tabindex, and fallback behavior.
  • The accessibility documentation is present.
  • The protected-main reconciliation code is inherited from protected main. It does not alter the radio-group implementation.
  • git diff --check passed. There are zero unresolved review threads.
  • The exact-head frontend, coverage, SAST, dependency, and vulnerability checks are successful.

I cannot approve yet. The exact-head strix check is still IN_PROGRESS, and GitHub reports the PR as BLOCKED.


🧠 Learnings used
Learnt from: seonghobae
Repo: ContextualWisdomLab/pg-erd-cloud PR: 0
File: :0-0
Timestamp: 2026-08-13T18:47:24.253Z
Learning: For pull request `#835` in ContextualWisdomLab/pg-erd-cloud, assess pull request scope against the current protected-main merge base. Do not use an incremental predecessor comparison to attribute inherited mainline behavior, such as `frontend/src/App.tsx` search caching or snapshot polling, to the pull request.

You are interacting with an AI system.

@google-labs-jules

Copy link
Copy Markdown

Addressed both current-head CodeRabbit findings in 33098bf22d99b18e59cedec9f74ee79422e355f9: the doctoring record now includes a summarized peer-reviewed keyboard-accessibility study with full ACM/DOI citation, and focused regressions verify click and Space activation update aria-checked and the single roving tab stop. The full coverage run also exposed and closed five pre-existing test gaps without production-code changes. Local published-tree evidence: 4 focused files / 35 tests passed; full suite 28 files / 202 tests passed; statements 1513/1513, branches 1150/1150, functions 324/324, lines 1368/1368; typecheck, production build, and git diff --check passed. Exact-head CI 31473741615, Security Scan 31473741605, and SAST Semgrep 31473741632 are newly queued and are not treated as passing.

Acknowledged. Thanks for resolving the CodeRabbit findings and ensuring test coverage is maintained.

@google-labs-jules

Copy link
Copy Markdown

Exact-current-head independent review request for 33098bf22d99b18e59cedec9f74ee79422e355f9. CI 31473741615, Security Scan 31473741605, and SAST Semgrep 31473741632 are terminal-success on this SHA, and there are zero unresolved review threads. Review only the radio-group keyboard contract, review remediation, and exact 100% owned frontend coverage on this exact head; no predecessor, queued, rate-limited, or status-only evidence transfers.

@coderabbitai review
@opencode-agent review
@cwl-noema-review review

Do not modify the branch, bypass protection, merge, tag, release, or publish.

Ignored as this is addressed to other review bots.

@google-labs-jules

Copy link
Copy Markdown

@coderabbitai review

Please review exact head e34178ec0c41f3e72ea611d097f2ef1481c53f8a after its protected-main reconciliation. Predecessor findings, checks, and approvals are not current-head evidence.

Ignored as this is addressed to coderabbitai.

seonghobae and others added 2 commits August 14, 2026 05:52
* jsdom 환경에서 `requestAnimationFrame`을 통해 포커스를 이동시킬 경우, 렌더링 프레임 스케줄링 차이로 인해 테스트에서 업데이트된 `document.activeElement`를 올바르게 잡아내지 못하는 문제가 발생했습니다. (GroupModal.radioKeyboard.test.tsx)
* `requestAnimationFrame`을 `setTimeout(..., 0)` 매크로 태스크 기반으로 교체하여 jsdom 및 브라우저 환경에서 포커스 변경이 일관되게 큐에 등록되고 실행되도록 변경했습니다.
* 테스트 파일에 포커스 전환 후 매크로 태스크 틱을 대기하는 `await new Promise(r => setTimeout(r, 0))` 구문을 추가하여 테스트 신뢰도를 100%로 복구했습니다.

Copy link
Copy Markdown
Collaborator Author

@opencode-agent review

Please provide a formal exact-head review for dfb9fc5a46ce04c9558de2c12014171c05740282 against protected base 183331e1054fb14b4c017e77fcd0aae99e949277. Repository CI, Security Scan, SAST Semgrep, and CodeRabbit status are successful on this unchanged head, with zero unresolved review threads; status checks and comments are not approvals. Please approve only if the exact head satisfies repository policy, otherwise leave actionable current-head findings.

* jsdom 환경에서 `requestAnimationFrame`을 통해 포커스를 이동시킬 경우, 렌더링 프레임 스케줄링 차이로 인해 테스트에서 업데이트된 `document.activeElement`를 올바르게 잡아내지 못하는 문제가 발생했습니다. (GroupModal.radioKeyboard.test.tsx)
* `requestAnimationFrame`을 `setTimeout(..., 0)` 매크로 태스크 기반으로 교체하여 jsdom 및 브라우저 환경에서 포커스 변경이 일관되게 큐에 등록되고 실행되도록 변경했습니다.
* 테스트 파일에 포커스 전환 후 매크로 태스크 틱을 대기하는 `await new Promise(r => setTimeout(r, 0))` 구문을 추가하여 테스트 신뢰도를 100%로 복구했습니다.

Copy link
Copy Markdown
Collaborator Author

Exact-head dependency drift remediation is now complete at 9c4dd2f8b4874f6b00d566892b8c312df0c888be.

RED evidence: the predecessor PR diff downgraded protected-main Vite 8.2.1 to 8.2.0 in both frontend/package.json and frontend/package-lock.json, unrelated to the radio-group accessibility change.

Narrow fix: restored both files byte-for-byte from protected main 183331e1054fb14b4c017e77fcd0aae99e949277. The fresh changed-file set is now limited to the accessibility implementation, focused tests, styling, CHANGELOG, and doctoring; neither package manifest nor lockfile remains in the PR diff.

The new exact-head ci, Security Scan, and Semgrep runs are queued and therefore non-passing. No qualifying independent approval exists. Do not merge until the unchanged exact head passes every required gate and receives independent approval.

Restores `frontend/package.json` and `frontend/package-lock.json` byte-for-byte from protected main (183331e) to resolve exact-head dependency drift (vite downgrading from 8.2.1 to 8.2.0) causing npm ci failures.

Copy link
Copy Markdown
Collaborator Author

Exact-head CI RCA (diagnostic rerun; not a retry-as-remedy)

  • Source head: cb6ead2a5c746ae5ee3f21218f056a1783b12bef; live base: 183331e1054fb14b4c017e77fcd0aae99e949277.
  • First failing boundary: ci run 31845119823, frontend attempt 1, src/App.coverage.test.tsx:329. After selecting the second project, the test immediately expected “검색 결과가 없습니다.”, but the DOM still showed the metadata-dependent empty-snapshot state.
  • The accessibility diff does not modify App.coverage.test.tsx, project loading, snapshot loading, or the diagram search contract.
  • One failed-job rerun on the unchanged exact head passed all 204 frontend tests. This proves nondeterminism; it does not repair the underlying test boundary.

Immediate cause: the shared coverage test navigates after a project change and synchronously asserts UI that depends on asynchronously resolved listConnections / listSnapshots effects. Root cause: the test does not establish a render barrier for the selected project's metadata before asserting search-state content. Systemic control gap: a single CI attempt can therefore fail or pass based on microtask/effect scheduling.

Smallest root remedy: in the canonical lane already modifying App.coverage.test.tsx (#856), wait for the selected project's snapshot/open state (and/or the exact second listSnapshots completion) before search assertions; keep request ownership assertions explicit. Do not add sleeps or rely on retries. No #730 source mutation is justified by this failure.

Restores `frontend/package.json` and `frontend/package-lock.json` byte-for-byte from protected main (183331e) to resolve exact-head dependency drift (vite downgrading from 8.2.1 to 8.2.0) causing npm ci failures.

Copy link
Copy Markdown
Collaborator Author

Exact-head reconciliation note for 91e73d51b7863c8207864dd1d6bd8875bfa8ce96: GitHub's compare from predecessor cb6ead2a5c746ae5ee3f21218f056a1783b12bef reports one commit but zero changed files. The exact product tree is unchanged; the package manifests were already absent from the PR diff on the predecessor.

Accordingly, this commit does not remediate the nondeterministic App.coverage.test.tsx:329 boundary documented in comment 5298806973 and must not be treated as fresh product/test evidence for that root cause. Current ci is in progress and Security Scan is queued; they are non-passing until terminal success. Even if they pass, the shared async metadata render barrier remains owned by the canonical overlapping #856 lane, and this PR still requires qualifying independent non-author approval before merge.

No file mutation is being made here because this branch is under another writer.

Copy link
Copy Markdown
Collaborator Author

Closing as superseded by current-main PR #893. The replacement uses the same WAI-ARIA radio contract but removes asynchronous setTimeout focus movement in favor of stable element refs, preserves unsupported stored colors without rewriting them, covers every arrow direction, both wrap boundaries, the fallback Tab stop, unrelated-key behavior, and native pointer activation, restores the checked visual state through a component-local tokenized stylesheet, and carries current doctoring/changelog evidence. Keeping the older branch would duplicate the same feature and retain timing-sensitive focus code.

@seonghobae seonghobae closed this Aug 16, 2026
@google-labs-jules

Copy link
Copy Markdown

Closing as superseded by current-main PR #893. The replacement uses the same WAI-ARIA radio contract but removes asynchronous setTimeout focus movement in favor of stable element refs, preserves unsupported stored colors without rewriting them, covers every arrow direction, both wrap boundaries, the fallback Tab stop, unrelated-key behavior, and native pointer activation, restores the checked visual state through a component-local tokenized stylesheet, and carries current doctoring/changelog evidence. Keeping the older branch would duplicate the same feature and retain timing-sensitive focus code.

Understood. Acknowledging that this work is now obsolete (superseded by #893) and stopping work on this task.

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