seo-local — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited seo-local (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<!-- Portions Copyright (c) 2026 Enrique Rocha (@soyenriquerocha) - see LICENSE for original authors · tododeia.com · id er-d03758e1 -->
Local pages live and die on consistent, machine-readable place data. Conditional module: only runs when the page is classified local-business (storefront, service-area, multi-location, contact/location page). Reference: references/schema-tier1.md (LocalBusiness row).
Work from the PageSnapshot named in your dispatch envelope: read parsed from <run_dir>/pages/<slug>.json (jsonld[], text_sample, iframes for maps) and vertical from the envelope; Grep pages/<slug>.html for verbatim evidence; site artifacts live in <run_dir>/site/{robots.json,sitemaps.json,discovery.json}. Deterministic findings already emitted by audit.mjs are listed in <run_dir>/findings.deterministic.json — do not re-emit those ids; add model-judged findings only. If invoked directly with a URL/path and no snapshot exists, first run node "${CLAUDE_PLUGIN_ROOT}/scripts/snapshot.mjs" <target> --out "${CLAUDE_PLUGIN_DATA}/runs" and use the printed snapshot path.
Working from the PageSnapshot (parsed_rendered when render.used is not none, else parsed), only for local-business pages:
LocalBusiness (or correct subtype, e.g. Restaurant, Dentist) JSON-LD block with required props — name, address (PostalAddress), telephone.geo (GeoCoordinates with latitude/longitude) present and plausible for the stated address.openingHoursSpecification present, structured (dayOfWeek, opens, closes), and agreeing with any visible hours.areaServed declared rather than (or alongside) a PostalAddress storefront.LocalBusiness JSON-LD block from user-confirmed NAP, hours, geo, and service-area, with a stable @id. The block is a diff for fix.Never fabricate an address, phone, coordinates, or hours — ask the user or leave a clearly-marked TODO placeholder they fill before injection.
node "${CLAUDE_PLUGIN_ROOT}/scripts/validate-jsonld.mjs" --snapshot <pages/<slug>.json> (or --url <u>) (schema_validator) — JSON validity + required LocalBusiness props; dom_assert confirms visible NAP matches schema.needs_api — never a false pass.Emit findings per schema/finding.schema.json. On a non-local page these are not_applicable (severity 0); on local pages severity is 4, axis both. Severity policy: 5 is reserved for catastrophic, eligibility-killing facts at site/template scope; 4 major · 3 moderate · 2 minor · 1 cosmetic · 0 informational — and only an established severity-5 fail in an active category can cap a score (references/scoring-model.md). Examples:
M19.localbusiness.missing — local page with no LocalBusiness schema (status fail, severity 4, fixable: auto, axis both, confidence established). evidence.observed quotes the visible address/phone with no matching ld+json; verification.reproduce runs the validator above.M19.nap.inconsistent — footer phone differs from schema telephone (status warn, severity 4, fixable: proposed, axis both, confidence directional). evidence.observed quotes both strings; verified by dom_assert.M19.hours.missing — no openingHoursSpecification despite visible hours (status warn, severity 4, fixable: auto, axis both, confidence established).Each finding: evidence.observed quotes the page; expected_impact is banded + confidence-tagged (no naked %).
geo/openingHoursSpecification will not by itself move local rankings without an accurate, verified GBP; never ship that as a guaranteed win.TODO.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.