"Audit mattbutlerengineering.com: smoke/sweep/scout modes. Invoke: /site-audit [smoke|sweep|scout]."
Instal·la
npx skillscat add mattbutlerengineering/mattbutlerengineering/site-audit Instal·la des del registre de SkillsCat.
Site Audit
Inventory-tracked 3-mode audit: smoke (regression), sweep (zone rotation), scout (improvements).
Inventory
.audit-state/inventory.json tracks surfaces, check times, scores via agent-core: buildInventory(), loadInventory(), saveInventory(), mapFilesToSurfaces(), findStalestZone(), updateSurfaceScore(), detectRegression().
cat .audit-state/inventory.json 2>/dev/null || echo "No inventory"Persist every real check result — this is what feeds findStalestZone() and
regression detection; skipping it is why the inventory used to sit atcheckCount: 0 forever (#4899). One-time per session: pnpm --filter @mbe/agent-core build
(the script imports agent-core's compiled dist). Then, after each live check:
node scripts/record-audit-check.mjs --surface "$SURFACE_ID" \
--performance "$PERF" --accessibility "$A11Y" --best-practices "$BEST_PRACTICES" --seo "$SEO"
# check failed outright (5xx, timeout, blocked) — no scores, record the failure instead:
node scripts/record-audit-check.mjs --surface "$SURFACE_ID" --error "$ERROR_MESSAGE"Environment Reachability (preflight — run FIRST, before any live check)
The agent proxy gateway in remote (claude.ai/code) containers may reject CONNECT
tunnels to the live site with HTTP 403 ("policy denial or upstream failure").
This is a sandbox egress limitation, not a site defect — the site is healthy;
this container simply has no route out. It surfaces as a curl connection
failure (exit 56 / http_code == 000), NOT an HTTP 403 body (which is the
separate Cloudflare case — see Access Restrictions).
PROBE=$(curl -sS -o /dev/null -w "%{http_code}" --max-time 20 "https://mattbutlerengineering.com" 2>/dev/null)
PROBE_EXIT=$?
if [ "${PROBE:-000}" = "000" ]; then
echo "ENVIRONMENT-BLOCKED: sandbox cannot reach the live site (proxy/CONNECT denial, curl exit ${PROBE_EXIT})."
echo "The site is NOT down and NOT restricted — this container has no egress."
echo "Run the audit from a local checkout instead (no agent proxy):"
echo " /site-audit <mode>"
# Do NOT file 'site unreachable' / regression / infrastructure issues — a blinded
# audit cannot judge the site, and doing so files noise (see #2913). Exit clean.
exit 0
fiOnly proceed to the modes below once the probe returns a real HTTP status
(200/301/403/5xx). A 000 means "cannot see the site", never "site is broken".
Mode 1: Smoke (per-commit)
git diff HEAD~1 --name-only- Map via
mapFilesToSurfaces():apps/<app>/src/pages/*→ surface,components/**→ all app surfaces,packages/rialto/**→ all frontend,services/*→ all API,infrastructure/**→ all, else skip. - Parallel subagents: Pages → Lighthouse (perf+a11y), API → curl check.
Curl pattern:
AUDIT_CURL_OPTS=(-sf -A "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36")
[ -n "${AUDIT_TOKEN:-}" ] && AUDIT_CURL_OPTS+=(-H "X-Audit-Token: $AUDIT_TOKEN")
HTTP_STATUS=$(curl -o /dev/null -w "%{http_code}" "${AUDIT_CURL_OPTS[@]}" "$URL")
[ "$HTTP_STATUS" = "403" ] && echo "ACCESS-RESTRICTED: $URL"- Detect regressions (>0.05 drop vs lastScore), create issues (labels:
ci-fix+audit), then persist the result for every surface checked vianode scripts/record-audit-check.mjs --surface "$SURFACE_ID" --performance ... --accessibility ... --best-practices ... --seo ...(see Inventory).
Mode 2: Sweep (weekly zone rotation)
| Zone | Surfaces | Auth |
|---|---|---|
marketing |
1 | none |
hospitality |
11 | auth0 |
rialto |
7 | none |
gen |
1 | auth0 |
api:users |
1 | none |
api:reservations |
1 | none |
api:agent |
1 | none |
- Load inventory, find stalest via
findStalestZone(). - For each surface:
git log --since='$LAST_CHECKED' --name-only -- $SOURCE_FILES | head -1→ skip if empty, include if non-empty or never checked. - Parallel (5-wave max): availability (curl), Lighthouse, mobile (375x812), console errors, network (flag 4xx/5xx/>3s), dead links.
- Create issues <0.9 or console errors. >50% blocked → one
[Audit] Infrastructure: Site unreachable+ stop. For every surface checked, persist the result vianode scripts/record-audit-check.mjs --surface "$SURFACE_ID" --performance ... --accessibility ... --best-practices ... --seo ...(or--error "$MESSAGE"for a blocked/failed check) — see Inventory.
Mode 3: Scout (monthly)
- Analyze
checkHistory: degrading 3+, below-threshold. pnpm outdated | head -30grep -r "TODO\|FIXME" apps/ services/ packages/ --include="*.ts" --include="*.tsx" -l | head -20ls -lh apps/*/dist/assets/*.jsgh issue list --state closed --limit 20 --json title,labels,closedAt- Max 3 issues:
featureormeta-improvementwith evidence.
Issue Creation
Dedup: gh issue list --label audit --state open --search "<phrase>" --json number,title → skip if exists.
Title: [Audit] <Category>: <Finding>
Labels: audit+ready+category:
performance— perf, slow, bundlesaccessibility— labels, contrast, navseo— meta, scoresux— links, visuals, responsive
Regressions: +ci-fix.
Body:
## Finding
[Description]
## Evidence
[Score/error/trend]
## Location
[Surface/URL/component]
## Fix
[Suggestion or "Investigate"]
---
_Audit ({{mode}}) YYYY-MM-DD_Auth (Hospitality + Gen)
Auth0 surfaces via E2E fixture:
import { test, expect } from "./fixtures.js";
test("loads", async ({ authPage }) => {
await authPage.goto("/reservations");
await expect(authPage.getByTestId("dashboard-layout")).toBeVisible();
});Access Restrictions
403 from Cloudflare Bot Management (curl completes with an HTTP 403 body — distinct
from the preflight 000 CONNECT-denial case in Environment Reachability):
- Log
ACCESS-RESTRICTED: <url> - Mark
restrictedin inventory - Skip Lighthouse/Playwright
- Continue
50% blocked → one infrastructure issue + stop
Enable (one-time):
- Cloudflare Security → WAF → Custom Rules
X-Audit-Token == <secret>→ Skip Bot Fightwrangler secret put AUDIT_TOKEN- Export
AUDIT_TOKEN=<secret>
Lighthouse
Check availability:
if command -v google-chrome &>/dev/null || command -v chromium &>/dev/null || command -v chromium-browser &>/dev/null; then
LIGHTHOUSE_AVAILABLE=1
fiRun only if available. Missing → null, note report, no issues.
Config
Base: https://mattbutlerengineering.com
Threshold: 0.9 all categories
npx @lhci/cli collect --url="<url>" --settings.preset=desktop --numberOfRuns=1
npx @lhci/cli assert --assertions.categories:performance="error,minScore,0.9" --assertions.categories:accessibility="error,minScore,0.9" --assertions.categories:best-practices="error,minScore,0.9" --assertions.categories:seo="error,minScore,0.9"Rules
- Read-only
- Max 5 issues/run
- Dedup first
- Full down (5xx) → one issue + stop
- 403 ≠ down
ENVIRONMENT-BLOCKED(proxy/CONNECT denial, curl exit 56 / http000) ≠ down and ≠ restricted → run preflight, skip, run locally, file no issues- Regressions →
ci-fix