fix(public): guard the live Promptly support page against the skipped-heading finding (closes 2026-08-08 scout item) - #77
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: 41 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 (3)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 71af6f69ca
ℹ️ 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 (!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.
Treat non-2xx live responses as failures
If a monitored page is deleted or misrouted and returns 404, this branch returns null, so the caller runs no assertions and the guard can exit successfully. That hides a production regression affecting the exact support pages this live check is intended to protect; HTTP error responses should increment failures rather than be treated like transport-level unreachability.
Useful? React with 👍 / 👎.
71af6f6 to
66fe607
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.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66fe607f29
ℹ️ 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".
| "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 && node scripts/test-public-deploy-bundle.mjs && find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --check", | ||
| "site:publish": "node scripts/publish-public-site.mjs", | ||
| "site:publish:check": "node scripts/publish-public-site.mjs --prepare-only" | ||
| "site:publish:check": "node scripts/publish-public-site.mjs --prepare-only" (fix(public): guard the live Promptly support page against the skipped-heading finding) |
There was a problem hiding this comment.
Remove the stray text that invalidates package.json
The parenthetical after the script value is not valid JSON; with this commit checked out, every npm command fails immediately with EJSONPARSE. This blocks npm ci, the test suites, and the public-site deployment workflow before any script can run, so the extraneous text must be removed.
Useful? React with 👍 / 👎.
| ok( | ||
| pkg.scripts.test.includes("test-public-live-heading-hierarchy.mjs"), | ||
| "npm test runs the public live heading-hierarchy guard" |
There was a problem hiding this comment.
Remove the assertion that makes the standalone guard fail
Once package.json is made parseable, this condition is always false because the unchanged scripts.test command does not contain test-public-live-heading-hierarchy.mjs. The dedicated npm run site:check-live-heading-hierarchy command therefore exits with a failure even when every live assertion passes; either remove these wiring assertions, as the file header says the guard is deliberately standalone, or actually align the intended wiring.
Useful? React with 👍 / 👎.
| // It runs as `npm run site:check-live-heading-hierarchy`, from the deploy | ||
| // lane's post-deploy verification, and on demand. It is deliberately NOT |
There was a problem hiding this comment.
Invoke the new guard from post-deploy verification
The inspected .github/workflows/deploy-public-site.yml runs publish-public-site.mjs --deploy, but verifyLive in that publisher invokes only check-public-live-deploy.mjs; a repo-wide search finds no deployment-path invocation of this new script. Consequently the added Drishti, Privacy Choices, and stylesheet checks never run after a deployment despite this stated contract, so the post-deploy verifier needs to call the guard explicitly.
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
66fe607 to
3f9a8d5
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.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3f9a8d5e45
ℹ️ 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".
|
|
||
| // Count <h2> used as .info-card card titles (inside <article class="info-card">). | ||
| const infoCardTitleCount = (html) => | ||
| (html.match(/<article class="info-card[^"]*"[^>]*>[\s\S]*?<h2\b/gi) || []).length |
There was a problem hiding this comment.
Keep card-heading matches within each article
When an .info-card lacks an H2 but any later section contains one, [\s\S]*? crosses the closing </article> and counts that later heading as the card title. For example, if the final card regresses to H3 and an additional section H2 appears before the footer, this count remains three, the total H2 count remains at least four, and the no-jump check can also pass, so the live guard misses the card-heading regression it claims to detect. Restrict each match to the corresponding article contents or parse the HTML structure.
Useful? React with 👍 / 👎.
…-heading finding (fresh, superseding stale PR #77) The 2026-08-08 scout item named /promptly/support/: the source outline was repaired by PR #20 (H1 -> H2 cards) and origin/main carries the fixed markup, but production still serves the June-20 bundle - the deployed page jumps H1 -> H3 (verified live 2026-08-12) and the deployed stylesheet keeps the old .info-card h3-only rule, so the finding stays open against tinystudio.in. The closed live-delivery item's guard (PR #77, fix/lane1-promptly-support- heading-hierarchy-live-guard) was never merged: it conflicts with current main and its script asserted npm test/ci wiring that its own header forbids. This lands the guard fresh from origin/main following the fleet's settled convention (standalone, out of the blocking chain, in the nightly net - matching PR #118 for the other two repaired pages): - scripts/test-public-heading-hierarchy.mjs now asserts public/promptly/support/index.html (68 checks, 0 failures; the scout's own page was previously unasserted in source) - scripts/test-public-live-promptly-support-heading.mjs (new): re-asserts the repaired outline + card-heading CSS rule against the live site; network-tolerant skip, fails loudly while the stale bundle is served (verified: 14 checks, 8 failures against the current deployment) - npm run site:check-live-promptly-support-heading on-demand entry point - .github/workflows/live-site-check.yml: nightly job alongside soft-404 The deploy acceptance (scripts/check-public-live-deploy.mjs, already on main) verifies H2-after-H1 on /promptly/support/ the moment the release lane publishes; the lane stays dormant until the Pages-scoped CLOUDFLARE_API_TOKEN secret is provisioned (documented NEEDS-NISH step).
Problem
The 2026-08-08 scout item:
/promptly/support/exposes a broken heading hierarchy. The source repair is already onmain(PR #20 merged the same day — the worktree page has a clean H1 → H2 cards → H2 footer → H3 columns outline), but the live site still serves the June-20 bundle:/promptly/support/outline is[1,3,3,3,2,3,3,3]— H1 jumps straight to H3 cards/styles.csskeeps the old.info-card h3-only rule (no shared:is(h2, h3)pairing)Two guard gaps let this finding stay silent:
test-public-heading-hierarchy.mjsnever assertedpublic/promptly/support/index.html(the scout's own page is missing fromAFFECTED_PAGES)./promptly/support/.What
scripts/test-public-heading-hierarchy.mjs: addpublic/promptly/support/index.htmltoAFFECTED_PAGES→ 50 checks, 0 failures.scripts/test-public-live-heading-hierarchy.mjs(new): re-asserts the repaired outline (single H1 first, three H2 card titles inside.info-card, flat H2 band before footer H3s, no jumps > 1) and the shared card-heading CSS rule against the pages the live site actually serves —/promptly/support/plus the two pages PR fix(public): guard the live site against skipped heading levels (closes Drishti support and Privacy Choices finding) #76 covers, so the script is complete on its own. Network-tolerant: skips when unreachable, fails loudly when stale.npm testandnpm run ci.Deploy status (the "restore in production" half)
Publishing the fixed bundle from this box is still blocked, exactly as documented in PR #70 (release lane):
api.cloudflare.comtoday)CLOUDFLARE_*repo secrets, no wrangler on this box, and PR fix(public): repair the tinystudio.in production deploy path #70 is unmergedmainfrom this laneThis PR closes the loop on the scout item the way the fleet's other live-guard PRs do (#62/#66/#67/#69/#76): the stale deployment now fails
npm test/CI loudly instead of silently re-opening the finding, and flips green automatically once the release lane publishes.Verify
node scripts/test-public-heading-hierarchy.mjs— 50 checks, 0 failuresnode scripts/test-public-live-heading-hierarchy.mjs— fails loudly on the current deployment (25 checks, 14 failures, all stale-deployment detections incl. 4 new ones for Promptly support)npm test— otherwise clean (only the live-guard stale-deployment failures)find scripts -name '*.mjs' -print0 | xargs -0 -n1 node --checkclean;git diff --checkcleanMerge note
PR #76 adds the same new file (
test-public-live-heading-hierarchy.mjs); whichever merges first, the other resolves trivially (union = this branch's version, which is a superset covering all three pages).