Fix broken-link audit: 4 real defects + CI gate - #386
Conversation
The homepage CTA "Get a Free Code Audit" landed on /free-consultation/, a page that never mentioned an audit: H1 "Free Consultation", a generic lede about a "technical strategy & planning session", and a five-item list of company brags (years in business, talent network, cost structure). Voice guide §4 requires a CTA to name what the reader receives, and ICP 90.10 §7 makes the named deliverable the answer to Alex's "all dev shops are the same" objection. So the page now states the offer: - H1 "Get a free code audit"; lede gives the shape - one senior developer, 45 minutes, a one-page written assessment, no contract, no follow-up call. Wording follows the voice guide §4 example and the three live blog CTAs. - The trust list becomes a deliverable list: what you get, plus "we read your repository, we do not change anything in it" for the burned founder. - Submit label is now content-driven via `formSubmitLabel`, defaulting to "Request Consultation" so the shared /contact-us/ form is untouched. The audit page sets "Request my code audit". - Frontmatter title/description rewritten around the audit offer. - Footer/company nav label follows the page: "Free Code Audit". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ICP 90.10 §5 weighs transparency proof at 25% of Alex's buying decision and names the artifact he looks for: a sample weekly report. The homepage promised "weekly plain-English reports" three times (meta description, hero subtitle, services intro) and never showed one. Adds a #weekly-report section between use-cases and testimonials - proof of how we work, just before proof of what clients say. It renders the three sections the voice guide already approves as canon phrasing: what shipped, what's blocked, what's next. Honesty note: no delivered client report exists in this repo, so this is labelled as the format, not passed off as a redacted real artifact. The caption says so explicitly. The Friday cadence follows the two live service pages; the course chapter teaching founders to demand a Monday report from their own team is a different audience and is left alone. Implementation notes: - Styles live in homepage-sections.css, the designated last-in-bundle layer for .jt-home-* sections, so plain single-class selectors win without !important. - The CTA link class starts with "cta" on purpose: navigation.css exempts [class^="cta"] from the site-wide brand-blue link rule, which otherwise beats any reasonable specificity via its :not() chain. Verified ruby #cc342d renders. - home-* prefix is already in the postcss greedy list, and the rules were confirmed present in the production bundle after PurgeCSS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…OS baselines
The two free_consultation tests asserted on "Free Consultation", the H1 that
the audit rewrite removed, so they would have failed. They now assert the
behaviour that matters: the destination names the deliverable.
- desktop + mobile free_consultation: assert "Get a free code audit" and
"one-page written assessment" instead of the old page title.
- desktop homepage_sections: new verify_section_for("homepage",
"weekly-report") with its baseline.
- Regenerated macOS baselines. The wide churn across 404, blog, course,
contact_us and services shots is the footer/company nav label change
("Free Consultation" -> "Free Code Audit"), which renders on every page.
Linux baselines follow in the next commit; CI runs Linux.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test:critical excludes the use-cases tests, so the first regeneration left
nav/use_cases and mobile/use_cases stale against the footer/company nav
label change ("Free Consultation" -> "Free Code Audit"), which renders on
every page. bin/qtest homepage caught it, and that failing run overwrote
the two baselines - restored with git checkout before regenerating.
Rule this confirms: a site-wide chrome change needs test:system, not
test:critical, before the baselines can be trusted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GA showed a 404 spike; wiring lychee in gives an offline internal-link check (test:links) plus optional external/html-proofer checks, so this class of regression is catchable locally and in CI.
Without a slug, Hugo derived the URL from the title (.../falcon-web-server-async-ruby-in-production), which didn't match the post's own canonical_url or the cross-link from falcon-web-server-production-tuning-benchmarks — a real 404.
single.html already renders the cover via Resources.GetMatch("cover.*")
before the body. A body-markdown  line for a post whose
cover file is literally named cover.<ext> renders the same image twice.
These posts referenced a cover image in frontmatter that was never committed, producing broken image links. Generated per the repo's cover-image pipeline (.stitch/design.md).
Runs bundle exec rake test:links (offline lychee scan against a production-mode build) so link regressions are caught in CI, not just via manual local runs.
|
Warning Review limit reached
Next review available in: 52 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: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe PR adds generated-site link validation through Rake tasks and GitHub Actions, introduces a homepage weekly report, updates free code audit messaging and form labels, adjusts article metadata and cover images, and updates related system assertions. ChangesLink validation
Site presentation and content
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant GitHubActions
participant Rakefile
participant HugoBuild
participant Lychee
GitHubActions->>Rakefile: run test:links
Rakefile->>HugoBuild: build production site
HugoBuild->>Rakefile: provide generated HTML
Rakefile->>Lychee: validate internal links
Lychee-->>GitHubActions: return check status
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Local bundle install on arm64-darwin-25 dropped the linux platform, breaking bundle install on GitHub Actions ubuntu-latest runners.
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
test/system/desktop_site_test.rb (1)
281-284: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the custom form submit button label.
Both the desktop and mobile system tests successfully verify the updated body text but miss checking the new custom submit button label introduced in this PR. Adding an explicit assertion for the button value ensures the front-matter configuration is rendering correctly and prevents future regressions.
test/system/desktop_site_test.rb#L281-L284: Addassert_button "Request my code audit"after the text assertions.test/system/mobile_site_test.rb#L170-L171: Addassert_button "Request my code audit"after the text assertions.🤖 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 `@test/system/desktop_site_test.rb` around lines 281 - 284, In test/system/desktop_site_test.rb lines 281-284 and test/system/mobile_site_test.rb lines 170-171, extend the existing audit destination assertions by adding an explicit button assertion for “Request my code audit” after the body-text assertions.
🤖 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/publish.yml:
- Line 57: Update the actions/checkout step to set persist-credentials to false,
preventing the GitHub token from being stored in the local git configuration
while preserving the existing checkout behavior.
In `@Rakefile`:
- Line 72: Update both lychee invocations in Rakefile, including the commands at
lines 72-72 and 84-84, to pass "#{dir}/**/*.html" as a single argument instead
of splatting html_files. Preserve the existing lychee options and scanning
behavior at both sites.
In `@themes/beaver/layouts/partials/page/contact-form.html`:
- Line 33: Update the submit input’s value expression to access the Hugo
parameter as .Params.formsubmitlabel, preserving the existing default "Request
Consultation" fallback so custom submit labels render correctly.
---
Nitpick comments:
In `@test/system/desktop_site_test.rb`:
- Around line 281-284: In test/system/desktop_site_test.rb lines 281-284 and
test/system/mobile_site_test.rb lines 170-171, extend the existing audit
destination assertions by adding an explicit button assertion for “Request my
code audit” after the body-text assertions.
🪄 Autofix (Beta)
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 157e4370-5f17-4712-88a7-4bb5dddda7ca
⛔ Files ignored due to path filters (73)
Gemfile.lockis excluded by!**/*.lockcontent/blog/ai-powered-code-reviews-transforming-development-workflows-2025/cover.jpegis excluded by!**/*.jpegcontent/blog/rails-performance-at-scale-10k-to-1m-users-roadmap/rails-scaling-roadmap.jpgis excluded by!**/*.jpgcontent/blog/ruby-on-rails-development-cost-guide-2025/cover.jpgis excluded by!**/*.jpgtest/fixtures/screenshots/macos/desktop/404.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/about_page/_achievements.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/about_page/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/about_page/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/about_page/_missions.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/about_page/_testimonials-header.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/about_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/index.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/index/_pagination.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/post.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/special/codeblocks/bare.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/special/codeblocks/html.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/special/codeblocks/indented.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/blog/special/youtube_post.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/careers.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/careers/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/careers/_newsletter.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/careers/_offers.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/careers/junior-ruby-on-rails-developer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/careers/junior-ruby-on-rails-developer/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/_technologies.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/_testimonials-header.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/_testimonials.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/agent-inbox/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/agent-inbox/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/agent-inbox/_overview.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/agent-inbox/_solution.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/clients/agent-inbox/_testimonial.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/course/chapter.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/course/landing.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/free_consultation.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/homepage/_clients.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/homepage/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/homepage/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/homepage/_weekly-report.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/nav/use_cases.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/privacy-policy.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/_testimonials-header.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/app_web_development.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/app_web_development_hero.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/fractional-cto/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/fractional-cto/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/services/fractional_cto.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/_overview.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/_technologies.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/_testimonials-header.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/startup-mvp-prototyping-development/_cta-contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/startup-mvp-prototyping-development/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/desktop/use-cases/startup-mvp-prototyping-development/_overview.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/404.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/about_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/blog/index.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/blog/index/_pagination.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/blog/post.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/careers.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/clients.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/contact_us.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/course/chapter.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/course/landing.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/free_consultation.pngis excluded by!**/*.pngtest/fixtures/screenshots/macos/mobile/use_cases.pngis excluded by!**/*.png
📒 Files selected for processing (17)
.github/workflows/publish.ymlBrewfileGemfileRakefileconfig/_default/hugo.tomlcontent/blog/ai-powered-code-reviews-transforming-development-workflows-2025/index.mdcontent/blog/falcon-web-server-async-ruby-production/index.mdcontent/blog/ruby-on-rails-development-cost-guide-2025/index.mdcontent/pages/free-consultation/index.mdlychee.tomltest/system/desktop_site_test.rbtest/system/mobile_site_test.rbthemes/beaver/assets/css/homepage-sections.cssthemes/beaver/layouts/home.htmlthemes/beaver/layouts/page/free-consultation.htmlthemes/beaver/layouts/partials/homepage/weekly-report.htmlthemes/beaver/layouts/partials/page/contact-form.html
💤 Files with no reviewable changes (2)
- content/blog/ai-powered-code-reviews-transforming-development-workflows-2025/index.md
- content/blog/ruby-on-rails-development-cost-guide-2025/index.md
- publish.yml: set persist-credentials: false on the link_check checkout so the GitHub token is not left in the runner's git config (zizmor artipacked). - Rakefile: pass the glob string to lychee instead of splatting every matched path, avoiding an ARG_MAX/E2BIG crash as the page count grows (lychee expands the glob natively; verified same file set gets scanned). - contact-form.html: Hugo lowercases front-matter keys, so .Params.formSubmitLabel was always nil and the button silently fell back to "Request Consultation". Use .Params.formsubmitlabel so the free-consultation page's "Request my code audit" label renders. - desktop/mobile system tests: assert the submit button reads "Request my code audit", which catches exactly the case-sensitivity regression above. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…platforms The audit-page rework (492f034) rewrote the free-consultation page but only macOS baselines were regenerated; the linux baselines still showed the old "Free Consultation" copy. Regenerate desktop + mobile linux baselines via bin/dtest so they match the shipped "Get a free code audit" page and the new submit-button label. Gemfile.lock: add aarch64-linux-musl (the bin/dtest Alpine/ARM container), parallel to the earlier x86_64-linux addition, so bundle install is satisfied on every platform this repo builds on. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The nav-label + weekly-report + use-cases/clients section changes updated the macOS baselines site-wide, but the matching linux baselines were never regenerated. Ran the full system suite under bin/dtest and refreshed the seven linux screenshots that actually differ; each has a committed macOS counterpart in this PR, so these are real cross-platform changes, not renderer noise. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New quick_test job runs bin/qtest scoped to the branch's changed pages with a ~90s budget, so CI catches functional regressions (page loads, copy, buttons, nav) on the pages a PR actually touches - without running the full visual suite. Because the committed baselines are captured on the docker gate's OS/font stack and CI runs on ubuntu, the pixel comparison is made configurable and loosened in CI (SCREENSHOT_TOLERANCE, SCREENSHOT_PERCEPTUAL_THRESHOLD) to absorb antialiasing while still flagging layout-level regressions. Both knobs default to today's strict local values, so local/dtest runs are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
quick_test failed on its first run - the :vips comparison driver FFI-loads the libvips shared library, which ubuntu-latest doesn't ship (macOS and the docker gate already have it). Install libvips-dev before running qtest. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Swap the raw apt-get for awalsh128/cache-apt-pkgs-action so libvips-dev is restored from cache on subsequent runs instead of re-fetched every time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Temporary diagnostic step - libvips-dev installs but require "vips" still fails; print apt state, ldconfig, and the real LoadError snap_diff swallows.
The screenshot-diff :vips driver dlopens libvips.so.42 at runtime, which ships in the libvips42 runtime package - not libvips-dev (headers only). The cache-apt action did not resolve the transitive runtime dependency, so libvips-dev alone left the .so.42 target of its symlink missing (apt list NONE, ldconfig NONE, LoadError on require "vips"). List libvips42 explicitly, bump the cache salt, run ldconfig, and fail fast with the real LoadError instead of 28 swallowed per-screenshot errors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two Actions-minute reductions on PRs: - link_check: the 144k-link crawl now runs only every 3rd PR (by PR number); non-PR events (nightly schedule, push to master, manual) still run so master stays fully covered. Gated per-step so the check still reports a real success status if it becomes required. - quick_test: this branch's five themes/ files each mapped to :all and escalated qtest to the full bin/rake test:critical suite, which ignores --budget and blew the 10-min timeout (cancelled). Add --no-escalate so a site-wide change smoke-tests the homepage (densest shared chrome) within budget instead of running the big suite the user explicitly excluded from CI; full coverage stays with the docker/nightly gate. Map the shared contact-form.html partial to its only two consumers (free-consultation, contact-us) for precise scoping. Changed set now resolves to a bounded [blog, homepage, free-consultation, contact-us] run, no escalation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… 3rd PR Replace the every-3rd-PR modulo gate with a path gate: on PRs the crawl runs only when a change could move an internal link - content (blog/ course/pages), templates (themes/*/layouts), menu/baseURL config, the data records rendered into links, or the checker config (lychee.toml/ Rakefile). CSS/test/workflow-only PRs skip it. Stacking the modulo on top would have skipped exactly the content-heavy PRs that most need the check, so the count gate is dropped in favour of this precise trigger. Non-PR events (nightly schedule, push to master, manual dispatch) always run for full master coverage. The PR file list comes from the API via the default token (pull-requests: read added) - cheaper than a full-history checkout just to diff. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cross-OS pixel diffing is unworkable here: baselines come from the docker gate (Alpine/musl, aarch64) but CI runs Ubuntu (glibc, x86_64). Measured divergence on c35d026 ran 3-28% (mobile code blocks 0.28, plain content pages up to 0.21) - above any tolerance that still catches a real regression. Set FORCE_SCREENSHOT_UPDATE so CI captures screenshots without failing on the diff; the functional assertions in the same system tests still gate (page renders, buttons/text present, no broken elements). True visual regression stays with the same-OS bin/test + bin/dtest gates. Revert the env-configurable tolerance/perceptual knobs added earlier for the abandoned loosen-tolerance approach - their comments described a CI behaviour that no longer exists, and defaults already equalled master. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
With cross-OS pixel diffing unworkable (docker Alpine/aarch64 baselines vs Ubuntu/glibc CI diverge 3-28%) and the functional-smoke fallback only unevenly valuable, the job's cost isn't justified: visual regression is already gated before merge by the mandatory same-OS bin/test (macOS) + bin/dtest (docker-linux). Remove the job and revert bin/qtest to master (the --no-escalate flag and contact-form mapping existed only to serve it). CI keeps the cheap, high-signal gates: build, unit_tests, and the path-scoped link_check. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the hand-rolled gate (gh api pulls/files + grep + a run= output guarding five steps, plus a pull-requests: read grant) with GitHub's native on.pull_request.paths in a dedicated link-check.yml. Same behaviour - PRs crawl only when content/templates/config/data/checker files change; schedule/push/dispatch/workflow_run carry no paths filter so they always run for full master coverage - with far less machinery. Per-job path filtering was impossible inside publish.yml (it also builds/ deploys), which is the only reason the gate existed; a separate workflow removes that constraint. Trade-off: on a PR that touches no link-relevant files the workflow does not run, so it reports no check (fine unless link_check becomes a required status check - say so and I will add a skip-reporting companion). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/link-check.yml:
- Around line 10-16: Update the path filters for the link-check workflow to
include the runtime inputs used by the setup and build steps:
.github/actions/setup-hugo, Gemfile, and Gemfile.lock. Preserve the existing
content, theme, config, data, lychee.toml, and Rakefile entries.
🪄 Autofix (Beta)
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ccfabfc1-7838-4c3c-ba7d-69eb7baf3545
⛔ Files ignored due to path filters (10)
Gemfile.lockis excluded by!**/*.locktest/fixtures/screenshots/linux/desktop/clients/_technologies.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/desktop/free_consultation.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/desktop/homepage/_footer.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/desktop/homepage/_weekly-report.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/desktop/nav/use_cases.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/desktop/use-cases/_overview.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/desktop/use-cases/_technologies.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/mobile/free_consultation.pngis excluded by!**/*.pngtest/fixtures/screenshots/linux/mobile/use_cases.pngis excluded by!**/*.png
📒 Files selected for processing (5)
.github/workflows/link-check.ymlRakefiletest/system/desktop_site_test.rbtest/system/mobile_site_test.rbthemes/beaver/layouts/partials/page/contact-form.html
🚧 Files skipped from review as they are similar to previous changes (3)
- themes/beaver/layouts/partials/page/contact-form.html
- test/system/mobile_site_test.rb
- Rakefile
…file) Per CodeRabbit: the crawl runs against a Hugo-built site using bundled tooling, so changes to the Hugo setup action or the Bundler runtime can move generated links without the current content/template/config paths firing. Add .github/actions/setup-hugo/**, Gemfile, Gemfile.lock so a build/dependency change still validates internal links on the PR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Maintain the OKF bundle after PR #386: new build/ci-gates.md documents what GitHub Actions enforces (build, unit, path-scoped lychee link check in link-check.yml) and records that visual regression is intentionally not a CI gate - cross-OS pixel diffs (Alpine/musl baselines vs Ubuntu/ glibc CI) diverge 3-28%, so bin/test + bin/dtest are the sole visual coverage. Cross-link test-gates, refresh build/index, log the change. CLAUDE.md: add @.okf/index.md to the mandatory session-start reads so the bundle is loaded up front for build/test/CI/content context. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Summary
GA showed a 404 spike. Wired
lycheeinto the repo for broken-linkchecking (
Rakefile,lychee.toml,Brewfile,Gemfile), ran itagainst a full production-mode build, and root-caused every finding
down to 4 real defects — all fixed here, plus a CI gate so this class
of regression is caught before merge.
falcon-web-server-async-ruby-productionhad no
slug:frontmatter, so Hugo derived a URL that didn't matchits own
canonical_urlor the cross-link pointing at it. Added themissing
slug:.frontmatter that was never committed. Generated all three per the
repo's cover-image pipeline (
.stitch/design.md).single.htmlalready renders the covervia
Resources.GetMatch("cover.*")before the body. Two of theabove posts also had a body-markdown
line, so thesame image rendered twice. Removed the redundant markdown line.
link_checkjob topublish.ymlrunningbundle exec rake test:links(offline lychee scan), matching localbehavior exactly.
Two other findings were confirmed non-issues and excluded via
lychee.tomlrather than "fixed":/contact-us/returns 403 from anintentional firewall/bot blocker, and
jtway.corate-limits scanners(third-party, not actually broken). A third — the
falcon-web-server-production-tuning-benchmarkspost and itsblog/tags/benchmarkstag page — 404s only because the post isfuture-dated relative to today; it self-resolves once the publish
date passes, confirmed by the before/after evidence below.
Evidence
bundle exec rake test:linksagainst a full production build:images, plus noise from the two documented exclusions before
lychee.tomlexisted)blog/tags/benchmarkspage, which is expected and self-resolving(144,416 links checked total, 143,932 excluded/OK)
Test plan
bundle exec rake test:links— 0 real errors (1 expected,self-resolving future-dated non-issue remains)
bin/hugo-build— clean production buildlink_checkjob added topublish.yml, will run on thisPR itself as first real-world validation
pages
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Content Improvements
Quality Improvements