fix(public): guard the live site against skipped heading levels (closes Drishti support and Privacy Choices finding) - #76
Conversation
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
|
Warning Review limit reached
Next review available in: 2 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe pull request adds a live-site heading hierarchy and stylesheet validation script. It checks configured public pages, reports assertion failures, skips unavailable deployments, and runs through both npm test and CI commands. ChangesLive heading validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant NpmScripts
participant LiveHeadingTest
participant PublicPages
participant PublicStylesheet
NpmScripts->>LiveHeadingTest: run live validation
LiveHeadingTest->>PublicPages: fetch configured pages
PublicPages-->>LiveHeadingTest: return HTML
LiveHeadingTest->>PublicStylesheet: fetch deployed CSS
PublicStylesheet-->>LiveHeadingTest: return stylesheet text
LiveHeadingTest-->>NpmScripts: report assertions and exit status
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 74a5f71e7f
ℹ️ 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".
| "mobbin:run": "node scripts/run-design-system-proving-lab.mjs", | ||
| "mobbin:check": "node scripts/run-design-system-proving-lab.mjs --dry-run", | ||
| "ci": "node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-brand-disambiguation.mjs && node scripts/test-public-heading-hierarchy.mjs && node scripts/test-public-link-targets.mjs && node scripts/test-public-social-preview.mjs && node scripts/test-public-soft-404.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check", | ||
| "ci": "node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-brand-disambiguation.mjs && node scripts/test-public-heading-hierarchy.mjs && node scripts/test-public-live-heading-hierarchy.mjs && node scripts/test-public-link-targets.mjs && node scripts/test-public-social-preview.mjs && node scripts/test-public-soft-404.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check", |
There was a problem hiding this comment.
Keep the live-site probe out of blocking CI
When production is stale or briefly differs from the checked-out revision, this makes every pull request fail even if its local code is correct. The repo-checks job in .github/workflows/codex-ci.yml runs npm run ci on every pull request before any deployment step, while this new script exits nonzero for the currently deployed pages; consequently, unrelated changes—and even a deployment repair that must merge before production can be refreshed—can be blocked by the required check. Run this probe as a post-deployment or non-blocking monitoring check rather than as part of the repository CI gate.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 `@package.json`:
- Around line 88-90: The npm test and ci scripts currently include the
production-dependent public live heading hierarchy guard, causing pre-merge
checks to fail against the known stale deployment. Remove
test-public-live-heading-hierarchy.mjs from both scripts, and move it to a
post-deployment job or dedicated production-monitoring workflow while keeping
the remaining pre-merge checks unchanged.
In `@scripts/test-public-live-heading-hierarchy.mjs`:
- Around line 52-55: Update the response-handling branch in the test request
flow so any completed fetch with res.ok false increments failures and is
reported as a test failure. Reserve the existing skip/return-null behavior only
for transport or timeout errors caught from fetch, ensuring reachable 404 and
5xx responses cannot allow the guard to pass.
- Around line 69-78: Update the heading validation around cardH2s and the levels
loop to require a contiguous footer H3 band immediately after the flat H2 band,
and reject any H2 appearing after that H3 band. Keep the existing jump
detection, but anchor the checks to the ordered heading levels so unrelated H2
elements cannot satisfy the requirement without the required H2-to-H3 footer
sequence.
🪄 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: 68f86d6e-6a22-4ca3-9180-61f3f614e055
📒 Files selected for processing (2)
package.jsonscripts/test-public-live-heading-hierarchy.mjs
| "ci": "node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-brand-disambiguation.mjs && node scripts/test-public-heading-hierarchy.mjs && node scripts/test-public-live-heading-hierarchy.mjs && node scripts/test-public-link-targets.mjs && node scripts/test-public-social-preview.mjs && node scripts/test-public-soft-404.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check", | ||
| "check": "npm test", | ||
| "test": "node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-brand-disambiguation.mjs && node scripts/test-public-heading-hierarchy.mjs && node scripts/test-public-link-targets.mjs && node scripts/test-public-social-preview.mjs && node scripts/test-public-soft-404.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check" | ||
| "test": "node scripts/test-service-engine.mjs && node scripts/test-sales-intake-contract.mjs && node scripts/test-active-offer-projection.mjs && node scripts/test-active-operator-surfaces.mjs && node scripts/test-direction-proof-gate.mjs && node scripts/test-client-readiness-contract.mjs && node scripts/test-validated-service-client.mjs && node scripts/test-client-acceptance-gates.mjs && node scripts/check-product-truth.mjs && node scripts/check-human-service-kit.mjs && node scripts/test-design-system-proving-lab.mjs && node scripts/check-retention-automation.mjs && node scripts/test-retention-automation.mjs && node scripts/check-agency-defaults.mjs && node scripts/check-outbound-claim-safety.mjs && node scripts/check-outbound-send-readiness.mjs && node scripts/test-outbound-send-readiness.mjs && node scripts/test-public-conversion-signal.mjs && node scripts/test-public-structured-data.mjs && node scripts/test-public-brand-disambiguation.mjs && node scripts/test-public-heading-hierarchy.mjs && node scripts/test-public-live-heading-hierarchy.mjs && node scripts/test-public-link-targets.mjs && node scripts/test-public-social-preview.mjs && node scripts/test-public-soft-404.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
Do not run a known-failing production assertion before deployment.
The PR objectives state that the current deployment has 11 expected failures. The live guard exits with status 1 on those failures. Since .github/workflows/codex-ci.yml runs npm run ci, both npm test and CI now fail until an out-of-band production deployment completes.
Run this guard in a post-deployment job or a dedicated production-monitoring workflow. Keep pre-merge test and ci independent of the stale production state.
🤖 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 `@package.json` around lines 88 - 90, The npm test and ci scripts currently
include the production-dependent public live heading hierarchy guard, causing
pre-merge checks to fail against the known stale deployment. Remove
test-public-live-heading-hierarchy.mjs from both scripts, and move it to a
post-deployment job or dedicated production-monitoring workflow while keeping
the remaining pre-merge checks unchanged.
| if (!res.ok) { | ||
| console.log(` ok skipped: ${url} answered ${res.status}, deployment not reachable - no assertions run for it`) | ||
| return null | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Fail reachable HTTP error responses.
fetch() completed when res.ok is false. The deployment is reachable in this case. Lines 52-55 skip 404 and 5xx responses without incrementing failures, so the guard can exit successfully while a required public page or stylesheet is unavailable. Only transport and timeout errors should skip.
Proposed fix
if (!res.ok) {
- console.log(` ok skipped: ${url} answered ${res.status}, deployment not reachable - no assertions run for it`)
+ ok(false, `live endpoint ${url} answered ${res.status}`)
return null
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!res.ok) { | |
| console.log(` ok skipped: ${url} answered ${res.status}, deployment not reachable - no assertions run for it`) | |
| return null | |
| } | |
| if (!res.ok) { | |
| ok(false, `live endpoint ${url} answered ${res.status}`) | |
| return null | |
| } |
🤖 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/test-public-live-heading-hierarchy.mjs` around lines 52 - 55, Update
the response-handling branch in the test request flow so any completed fetch
with res.ok false increments failures and is reported as a test failure. Reserve
the existing skip/return-null behavior only for transport or timeout errors
caught from fetch, ensuring reachable 404 and 5xx responses cannot allow the
guard to pass.
| const cardH2s = levels.filter((l) => l === 2).length | ||
| ok(cardH2s >= 4, `live ${name} page keeps the flat H2 band (card H2s plus the footer H2) before the footer H3s`) | ||
| let jumps = 0 | ||
| for (let i = 1; i < levels.length; i++) { | ||
| if (levels[i] - levels[i - 1] > 1) { | ||
| jumps++ | ||
| console.error(` bad transition H${levels[i - 1]} -> H${levels[i]} on ${name}`) | ||
| } | ||
| } | ||
| ok(jumps === 0, `live ${name} page has no heading-level jump greater than one (no H1 -> H3 skip)`) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Validate the required H2-to-H3 footer sequence.
cardH2s counts every H2 in the document. It does not require any H3 footer column headings. A page with one H1 and four unrelated H2 elements passes these checks if it has no level jump. Require an H3 band after the H2 band and reject H2 elements after that band.
Proposed fix
- const cardH2s = levels.filter((l) => l === 2).length
- ok(cardH2s >= 4, `live ${name} page keeps the flat H2 band (card H2s plus the footer H2) before the footer H3s`)
+ const firstH3 = levels.indexOf(3)
+ ok(
+ firstH3 >= 5 &&
+ levels.slice(1, firstH3).every((level) => level === 2) &&
+ levels.slice(firstH3).every((level) => level >= 3),
+ `live ${name} page keeps the flat H2 band before the footer H3s`
+ )📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const cardH2s = levels.filter((l) => l === 2).length | |
| ok(cardH2s >= 4, `live ${name} page keeps the flat H2 band (card H2s plus the footer H2) before the footer H3s`) | |
| let jumps = 0 | |
| for (let i = 1; i < levels.length; i++) { | |
| if (levels[i] - levels[i - 1] > 1) { | |
| jumps++ | |
| console.error(` bad transition H${levels[i - 1]} -> H${levels[i]} on ${name}`) | |
| } | |
| } | |
| ok(jumps === 0, `live ${name} page has no heading-level jump greater than one (no H1 -> H3 skip)`) | |
| const firstH3 = levels.indexOf(3) | |
| ok( | |
| firstH3 >= 5 && | |
| levels.slice(1, firstH3).every((level) => level === 2) && | |
| levels.slice(firstH3).every((level) => level >= 3), | |
| `live ${name} page keeps the flat H2 band before the footer H3s` | |
| ) | |
| let jumps = 0 | |
| for (let i = 1; i < levels.length; i++) { | |
| if (levels[i] - levels[i - 1] > 1) { | |
| jumps++ | |
| console.error(` bad transition H${levels[i - 1]} -> H${levels[i]} on ${name}`) | |
| } | |
| } | |
| ok(jumps === 0, `live ${name} page has no heading-level jump greater than one (no H1 -> H3 skip)`) |
🤖 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/test-public-live-heading-hierarchy.mjs` around lines 69 - 78, Update
the heading validation around cardH2s and the levels loop to require a
contiguous footer H3 band immediately after the flat H2 band, and reject any H2
appearing after that H3 band. Keep the existing jump detection, but anchor the
checks to the ordered heading levels so unrelated H2 elements cannot satisfy the
requirement without the required H2-to-H3 footer sequence.
The skipped-heading-level finding (Drishti support and Privacy Choices pages) was repaired in source by PR #23 (H1 -> H2 cards, no outline jumps), and the local suite (test-public-heading-hierarchy.mjs) guards the worktree HTML. But the live site still serves the June-20 bundle: both pages jump H1 -> H3 and the deployed stylesheet keeps the old .info-card h3-only rule, so the finding silently re-opens against tinystudio.in. Add scripts/test-public-live-heading-hierarchy.mjs, wired into npm test and npm run ci: it fetches the deployed pages and stylesheet and re-asserts the repaired outline (single H1 first, H2 card titles inside .info-card, flat H2 band before footer H3s, no jumps greater than one) and the shared .info-card :is(h2, h3) rule. Network-tolerant: skips when the site is unreachable, fails loudly when it serves stale pages. verify: node scripts/test-public-live-heading-hierarchy.mjs fails loudly on the current deployment (19 checks, 11 failures, all stale-deployment detections), node scripts/test-public-heading-hierarchy.mjs 44 checks 0 failures, npm test otherwise clean, find scripts -name '*.mjs' node --check clean, git diff --check clean
74a5f71 to
e70424b
Compare
There was a problem hiding this comment.
nish3451 has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.
…-heading finding The 2026-08-08 scout item named /promptly/support/: it was repaired in source by PR #20 (H1 -> H2 cards, no outline jumps) and origin/main already carries the fixed outline, but the live site still serves the June-20 bundle: the deployed page jumps H1 -> H3 (live outline [1,3,3,3,2,3,3,3]) and the deployed stylesheet keeps the old .info-card h3-only rule, so the finding silently stays open against tinystudio.in. The local suite (test-public-heading-hierarchy.mjs) did not even assert public/promptly/support/index.html, and the live heading-hierarchy guard from PR #76 checks Drishti support and Privacy Choices but not the scout's own page. Add /promptly/support/ to the local suite's affected pages (50 checks, 0 failures) and add scripts/test-public-live-heading-hierarchy.mjs guarding /promptly/support/ plus the two pages PR #76 covers, wired into npm test and npm run ci. Network-tolerant: skips when the site is unreachable, fails loudly while it serves the stale bundle. Once the release lane (PR #70) publishes the fixed bundle, the guard flips green. Publishing from this box is still blocked: the fleet Cloudflare token returns 403 on the Pages projects API (no Pages:Edit), and no Pages-scoped secret or wrangler exists here. intended-outcome: the Promptly support heading hierarchy can no longer regress silently on the live site; the stale June-20 deployment fails npm test/ci loudly until the fixed bundle is published. verify: node scripts/test-public-heading-hierarchy.mjs 50 checks 0 failures; node scripts/test-public-live-heading-hierarchy.mjs fails loudly on the current deployment (25 checks, 14 failures, all stale-deployment detections); npm test otherwise clean; find scripts -name '*.mjs' node --check clean; git diff --check clean
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e70424b724
ℹ️ 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".
| console.log("C. npm test/ci wiring") | ||
| const pkg = JSON.parse(read("package.json")) | ||
| ok( | ||
| pkg.scripts.test.includes("test-public-live-heading-hierarchy.mjs"), |
There was a problem hiding this comment.
Remove the contradictory CI-wiring assertions
After the live probe was removed from test and ci, this assertion still requires it to be present there. In this revision both package scripts omit test-public-live-heading-hierarchy.mjs, so npm run site:check-live-heading-hierarchy always records two failures and exits 1 even when every live response is correct; the new command therefore cannot serve as a successful post-deployment check.
Useful? React with 👍 / 👎.
| "client:proof-review": "node scripts/review-client-proof.mjs", | ||
| "retention:automation-check": "node scripts/check-retention-automation.mjs", | ||
| "site:prepare": "node scripts/prepare-static-site-bundle.mjs", | ||
| "site:check-live-heading-hierarchy": "node scripts/test-public-live-heading-hierarchy.mjs", |
There was a problem hiding this comment.
Invoke the guard from post-deploy verification
This only exposes a manual npm command; the inspected publish path in .github/workflows/deploy-public-site.yml invokes publish-public-site.mjs, whose verifyLive() runs only check-public-live-deploy.mjs. A repo-wide reference search found no deployment invocation of this new command, so deployments with stale headings on these two pages can still complete without running the guard this change is intended to add.
Useful? React with 👍 / 👎.
| if (!res.ok) { | ||
| console.log(` ok skipped: ${url} answered ${res.status}, deployment not reachable - no assertions run for it`) | ||
| return null |
There was a problem hiding this comment.
Fail when a live endpoint returns an HTTP error
When either guarded page or styles.css responds with a 404 or 5xx, the server is reachable but this branch treats the response as an allowed skip and performs no assertions. Once the contradictory wiring assertions are corrected, a deployment that removes all three resources can therefore pass this live guard; only genuine transport failures should receive the intended network-tolerant handling, while non-2xx responses should count as failures.
Useful? React with 👍 / 👎.
…-heading finding The 2026-08-08 scout item named /promptly/support/: it was repaired in source by PR #20 (H1 -> H2 cards, no outline jumps) and origin/main already carries the fixed outline, but the live site still serves the June-20 bundle: the deployed page jumps H1 -> H3 (live outline [1,3,3,3,2,3,3,3]) and the deployed stylesheet keeps the old .info-card h3-only rule, so the finding silently stays open against tinystudio.in. The local suite (test-public-heading-hierarchy.mjs) did not even assert public/promptly/support/index.html, and the live heading-hierarchy guard from PR #76 checks Drishti support and Privacy Choices but not the scout's own page. Add /promptly/support/ to the local suite's affected pages (50 checks, 0 failures) and add scripts/test-public-live-heading-hierarchy.mjs guarding /promptly/support/ plus the two pages PR #76 covers, wired into npm test and npm run ci. Network-tolerant: skips when the site is unreachable, fails loudly while it serves the stale bundle. Once the release lane (PR #70) publishes the fixed bundle, the guard flips green. Publishing from this box is still blocked: the fleet Cloudflare token returns 403 on the Pages projects API (no Pages:Edit), and no Pages-scoped secret or wrangler exists here. intended-outcome: the Promptly support heading hierarchy can no longer regress silently on the live site; the stale June-20 deployment fails npm test/ci loudly until the fixed bundle is published. verify: node scripts/test-public-heading-hierarchy.mjs 50 checks 0 failures; node scripts/test-public-live-heading-hierarchy.mjs fails loudly on the current deployment (25 checks, 14 failures, all stale-deployment detections); npm test otherwise clean; find scripts -name '*.mjs' node --check clean; git diff --check clean
Why
The skipped-heading-level finding for the Drishti support and Privacy Choices pages was repaired in source by PR #23 (card headings promoted from H3 to H2, outline H1 → H2s → H3s with no jumps), and
scripts/test-public-heading-hierarchy.mjsguards the worktree HTML. The finding re-opened because the live site still serves the June-20 bundle: both deployed pages jump H1 → H3 and the deployed stylesheet keeps the old.info-card h3-only rule — verified live on 2026-08-11.This PR follows the fleet's live-guard pattern (like
fix/lane1-live-soft-404-detector,fix/lane1-live-social-preview-guard,fix/lane1-live-tap-targets,fix/lane1-footer-tap-targets-live-guard).What
scripts/test-public-live-heading-hierarchy.mjs: fetches the deployed/drishti/support/,/privacy-choices/, and/styles.css, then re-asserts the repaired outline (exactly one H1 first, three H2 card titles inside.info-card, flat H2 band before footer H3s, no heading-level jump greater than one) and the shared.info-card :is(h2, h3)rule at the former card scale.npm testandnpm run ci.Current status
The guard intentionally fails against the live site right now (19 checks, 11 failures — all stale-deployment detections), keeping this item visibly open until the production deploy path is repaired and main is published. Deploy repair is tracked separately by PR #70 (
fix/lane1-public-release-lane); once the deployment refreshes, this guard goes green and the finding stays closed.Verify
node scripts/test-public-live-heading-hierarchy.mjs→ 19 checks, 11 failures (stale-live detection, expected until redeploy)node scripts/test-public-heading-hierarchy.mjs→ 44 checks, 0 failuresnpm test→ only the guard's stale-live failures; all other suites pass (126/127/11/44 checks)find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check→ cleangit diff --check→ cleanSummary by CodeRabbit