Skip to content

fix(public): net the live site against WCAG 2.2 tap-target drift without blocking PRs - #107

Closed
nish3451 wants to merge 9 commits into
mainfrom
fix/lane1-in-content-link-targets-live-net-20260812
Closed

fix(public): net the live site against WCAG 2.2 tap-target drift without blocking PRs#107
nish3451 wants to merge 9 commits into
mainfrom
fix/lane1-in-content-link-targets-live-net-20260812

Conversation

@nish3451

@nish3451 nish3451 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

What

The backlog item "In-content links stay below the WCAG 2.2 24px tap-target minimum" is fixed in the repo (PR #22 raised .footer-links a, PR #25 raised .top-nav a, .plain-list a, .product-links a, .rail-item strong a) but keeps re-opening because the live site still serves the pre-fix stylesheet (the June-20 bundle). Measured today:

State stylesheet In-content links (390px)
Worktree public/ (main, incl. #22+#25) 901 lines, all five tap-target rules >= 24px on all 13 pages (0 under 24x24)
Live tinystudio.in 874 lines, missing all five tap-target rules ~17px (grok's finding)

Change

This lands the drift detector without putting the live site in the blocking chain — PR #84 set the convention that npm test/npm run ci stay green on repo state alone:

  • scripts/check-public-live-tap-targets.mjs — fetches the deployed https://tinystudio.in/styles.css and re-asserts the same five link rules the local suite (test-public-link-targets.mjs) requires: .top-nav a, .plain-list a, .product-links a, .rail-item strong a, .footer-links a must each be a block-level box with min-height: 24px and >= 4px vertical padding.
  • npm run site:check-live now runs the soft-404 and tap-target live checks.
  • .github/workflows/live-site-check.yml gains a nightly + manual-dispatch live-tap-targets job.

Supersedes PR #66

PR #66 wired this same guard into the blocking npm test/npm run ci chain (its repo-checks are red and it conflicts with main). Per the PR #84 convention the blocking chain must stay green on repo state alone, so #66 cannot merge as-is. This PR is the #84-shaped replacement (detector + site:check-live + nightly net). Close #66 if this lands.

Expected: nightly live-site-check is RED until the deployment is refreshed

Against today's live sheet this check reports 11 failures and exits 1 — that failure is the point: public/ is compliant, the deployment is not. The red nightly run is the loud signal to re-deploy from origin/main. The deploy lane (deploy-public-site.yml + publish-public-site.mjs) is in place but fails closed until a Cloudflare Pages-scoped CLOUDFLARE_API_TOKEN is provisioned (one-time dashboard step documented in the script; tracked in PR #85) — the live refresh is the external dependency that unblocks the green net.

Verify

  • node --check scripts/check-public-live-tap-targets.mjs — clean
  • node scripts/check-public-live-tap-targets.mjs — 19 checks, 11 failures vs the current live sheet, exit 1 (expected drift signal)
  • npm test — exit 0, blocking chain untouched and green
  • git diff --check — clean

Summary by CodeRabbit

  • New Features

    • Added automated live-site checks for WCAG 2.2 tap-target requirements across key links.
    • Combined tap-target and soft-404 validation into the live-site check command.
    • Added retry handling and clear reporting for validation results.
  • Chores

    • Updated nightly validation guidance for stale deployments and temporary network failures.
    • Added an explicit option to bypass live checks when network access is unavailable.

…out blocking PRs

PR #22 (footer) and #25 (in-content) brought every link in public/styles.css
up to the WCAG 2.2 SC 2.5.8 24px minimum, but the backlog item keeps
re-opening because the live site still serves the pre-fix stylesheet
(June-20 bundle: 874 lines vs 901 in main, missing all five tap-target
rules), so rendered in-content links are ~17px. PR #66 wired a live guard
into the blocking npm test/ci chain, but PR #84 established that the
blocking chains must stay green on repo state alone.

Land the detector the same way #84 landed the soft-404 net:
- scripts/check-public-live-tap-targets.mjs: fetches the deployed
  https://tinystudio.in/styles.css and re-asserts the five link rules the
  local suite requires (.top-nav a, .plain-list a, .product-links a,
  .rail-item strong a, .footer-links a: block-level box, min-height 24px,
  >= 4px vertical padding). A non-2xx response or a stylesheet that misses a
  rule fails loudly (the CodeRabbit P1 on #66); only a network-level failure
  skips, and SKIP_LIVE_CHECKS=1 is honored like the sibling live checks.
- npm run site:check-live entry point now runs both live checks
- .github/workflows/live-site-check.yml gains a nightly + manual-dispatch
  live-tap-targets job

Verify: node --check clean; against the current live stylesheet the check
reports 11 failures and exits 1 (the point of the net: public/ is compliant,
the deployment is not - the red run is the signal to re-deploy from
origin/main); npm test stays green (blocking chain untouched); git diff
--check clean.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b93d5861-fe72-4c4c-8a3c-b3478db8b7da

📥 Commits

Reviewing files that changed from the base of the PR and between 228ce4a and 5120396.

📒 Files selected for processing (2)
  • .github/workflows/live-site-check.yml
  • package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


📝 Walkthrough

Walkthrough

The pull request adds a deployed stylesheet checker for five WCAG 2.2 tap-target selectors. It adds retry and skip handling for network failures, validates checker wiring, and runs the check from the npm script and nightly workflow.

Changes

Live tap-target validation

Layer / File(s) Summary
Tap-target rule assertions
scripts/check-public-live-tap-targets.mjs
The script checks five deployed link selectors for block-level display, a 24px minimum height, and at least 4px vertical padding.
Live fetch and result handling
scripts/check-public-live-tap-targets.mjs
The script fetches the live stylesheet with timeout and retries. It skips final network failures, reports missing rules, validates wiring, and exits nonzero for failed assertions.
Live-check pipeline wiring
package.json, .github/workflows/live-site-check.yml
site:check-live runs the tap-target check, and the nightly workflow adds a dedicated live-tap-targets job with Node setup and dependency installation.

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

Merge Risk: ⚪ Minimal · up to 51203

This change adds a non-blocking live-site accessibility drift check while keeping repository checks green; no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as live-site-check.yml
  participant Checker as check-public-live-tap-targets.mjs
  participant Site as tinystudio.in
  Workflow->>Checker: run live tap-target check
  Checker->>Site: fetch styles.css
  Site-->>Checker: return stylesheet
  Checker-->>Workflow: report validation result
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The detector meets the five-selector validation goal, but it is not wired into npm test or npm run ci as required by issue #66. Wire the detector into npm test and npm run ci, or explicitly revise issue #66 to accept the non-blocking integration.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: a non-blocking WCAG 2.2 tap-target drift check for the live public site.
Out of Scope Changes check ✅ Passed All changed files implement or document the live-site WCAG 2.2 tap-target detector and its scheduled or manual workflow integration.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/lane1-in-content-link-targets-live-net-20260812

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 809042570d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +73 to +74
const match = css.match(new RegExp(`${pattern}\\s*\\{([^}]*)\\}`))
return match ? match[1] : null

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Evaluate the effective CSS rule instead of the first match

When a later or more-specific rule overrides one of these selectors—for example, a mobile media query sets .top-nav a { min-height: 0; padding: 0; }String.match still returns the first compliant block, so the nightly check reports success while the rendered tap target is below 24px. Since this detector is intended to catch deployed CSS drift, it should account for the cascade (ideally by checking computed styles at representative viewports) rather than accepting the first textual occurrence.

Useful? React with 👍 / 👎.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4123145c29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +112 to +114
} catch (err) {
console.log(` ok skipped: ${LIVE_CSS_URL} unreachable (${err?.cause?.code ?? err?.name ?? "network error"}) - no tap-target assertions run`)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fail when the stylesheet fetch exhausts its retries

When /styles.css alone times out, resets, or returns a truncated body while the HTML endpoints remain reachable, this catch path reports an ok skipped result and the job exits successfully after the wiring checks. The separate live-soft-404 job in .github/workflows/live-site-check.yml never requests this asset, so the nightly workflow can stay green even though browsers cannot load the stylesheet and the tap-target guarantees are absent. Treat an exhausted stylesheet fetch as a monitoring failure; offline callers already have the explicit SKIP_LIVE_CHECKS=1 escape hatch.

Useful? React with 👍 / 👎.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea5a636443

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if (rule) {
ok(/display:\s*(inline-block|inline-flex|block)/.test(rule), `live ${selector} links are block-level boxes (hit area covers the line box)`)
ok(!/display:\s*inline\s*;/.test(rule), `live ${selector} links are not plain inline boxes`)
ok(/min-height:\s*24px/.test(rule), `live ${selector} links declare min-height: 24px`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Check both target dimensions

Add a width assertion as well as min-height: when a short label or icon link is added under any of these selectors, the existing HTML coverage test still accepts it and this live check remains green even though the rendered target can be narrower than 24px because every required rule has zero horizontal padding and no min-width. The guard therefore does not enforce the stated 24-by-24 target minimum for all content it permits.

Useful? React with 👍 / 👎.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps 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.

nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

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

Actionable comments posted: 2

🤖 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.

Inline comments:
In @.github/workflows/live-site-check.yml:
- Line 43: Update the actions/checkout step to set persist-credentials to false,
ensuring the GITHUB_TOKEN is not retained in .git/config after checkout.

In `@scripts/check-public-live-tap-targets.mjs`:
- Around line 67-87: The targetRuleOf/assert24pxRule validation currently only
reads the first direct selector match, missing grouped selectors and later
source-order overrides. Replace targetRuleOf with stylesheet rule parsing that
collects declarations from every rule containing the requested selector, then
evaluate the final effective declarations after applying source-order overrides;
add coverage for grouped selectors and later overriding rules.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bc89e226-73b6-45ed-95f6-9883f5d7cbfd

📥 Commits

Reviewing files that changed from the base of the PR and between 8b69101 and 228ce4a.

📒 Files selected for processing (3)
  • .github/workflows/live-site-check.yml
  • package.json
  • scripts/check-public-live-tap-targets.mjs

live-tap-targets:
runs-on: [self-hosted, linux, x64, vps-verify]
steps:
- uses: actions/checkout@v7

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Confirm this job has no later Git operation that requires checkout credentials.
sed -n '40,60p' .github/workflows/live-site-check.yml
rg -n -C 2 '\bgit\b|actions/checkout' .github/workflows/live-site-check.yml

Repository: nish3451/tinystudio-in

Length of output: 796


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- workflow ---'
cat -n .github/workflows/live-site-check.yml

printf '%s\n' '--- checkout and Git references in workflows ---'
rg -n -C 3 'actions/checkout|persist-credentials|\bgit\b|GITHUB_TOKEN|github\.token' .github/workflows

Repository: nish3451/tinystudio-in

Length of output: 4485


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for file in scripts/check-public-live-soft-404.mjs scripts/check-public-live-tap-targets.mjs; do
  if [ -f "$file" ]; then
    printf '%s\n' "--- $file ---"
    rg -n -C 2 'child_process|exec|spawn|git|GITHUB_TOKEN|github\.token' "$file" || true
  fi
done

printf '%s\n' '--- package scripts and Git dependencies ---'
rg -n -C 2 '"(prepare|preinstall|install|postinstall|ci)"|git[[:space:]]' package.json package-lock.json 2>/dev/null || true

Repository: nish3451/tinystudio-in

Length of output: 3367


Disable checkout credential persistence.

This self-hosted job performs no Git operations after checkout. Set persist-credentials: false so the GITHUB_TOKEN is not retained in .git/config during later steps.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 43-43: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 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 @.github/workflows/live-site-check.yml at line 43, Update the
actions/checkout step to set persist-credentials to false, ensuring the
GITHUB_TOKEN is not retained in .git/config after checkout.

Source: Linters/SAST tools

Comment on lines +67 to +87
const targetRuleOf = (css, selector) => {
const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
const pattern = selector
.split(",")
.map((s) => esc(s.trim()))
.join("\\s*,\\s*")
const match = css.match(new RegExp(`${pattern}\\s*\\{([^}]*)\\}`))
return match ? match[1] : null
}

const assert24pxRule = (selector, rule) => {
ok(rule !== null, `live styles.css has a ${selector} rule`)
if (rule) {
ok(/display:\s*(inline-block|inline-flex|block)/.test(rule), `live ${selector} links are block-level boxes (hit area covers the line box)`)
ok(!/display:\s*inline\s*;/.test(rule), `live ${selector} links are not plain inline boxes`)
ok(/min-height:\s*24px/.test(rule), `live ${selector} links declare min-height: 24px`)
const paddingMatch = rule.match(/padding:\s*([^;]+)/)
ok(paddingMatch !== null, `live ${selector} links declare vertical padding`)
if (paddingMatch) {
const vertical = parseFloat(paddingMatch[1].trim().split(/\s+/)[0])
ok(vertical >= 4, `live ${selector} vertical padding is at least 4px (${vertical}px), so 16px text + padding >= 24px`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Evaluate CSS rules after selector grouping and source-order overrides.

Line 73 only matches a selector directly before { and returns its first match. A grouped rule such as .top-nav a, .plain-list a { ... } does not match. A later rule for the same selector can override a compliant earlier rule and still pass this check.

Parse stylesheet rules, collect every matching selector, and evaluate the final effective declarations. Add cases for grouped selectors and later overrides.

🤖 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 `@scripts/check-public-live-tap-targets.mjs` around lines 67 - 87, The
targetRuleOf/assert24pxRule validation currently only reads the first direct
selector match, missing grouped selectors and later source-order overrides.
Replace targetRuleOf with stylesheet rule parsing that collects declarations
from every rule containing the requested selector, then evaluate the final
effective declarations after applying source-order overrides; add coverage for
grouped selectors and later overriding rules.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@nish3451

Copy link
Copy Markdown
Collaborator Author

Superseded by #152100% of this PR's changes are contained in it, plus a lane report and a broader workflow wiring. Closing in favour of #152.

@nish3451 nish3451 closed this Aug 19, 2026
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