seo-orchestrator — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited seo-orchestrator (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 -->
Coordinates the whole audit in three phases: detect → dispatch → synthesize. The scripts are the acquisition layer; the model only judges. Read the compact stdout summaries and the JSON files they name — never paste HTML into the conversation. Nothing is written to the user's project; every artifact lives under ${CLAUDE_PLUGIN_DATA}/runs/<host>/<run-id>/.
--pages, --max, --render, --ua, --vertical, --environment, --feed, --out; default --out "${CLAUDE_PLUGIN_DATA}/runs").audit.mjs acquires the target (it calls crawl.mjs for a URL, snapshot.mjs for --pages 1 or a local path, and skips acquisition entirely when handed a run directory), writes profile.json (platform / framework / cms plugins / hosting / environment / capabilities / write_targets / vertical_hints, plus a vertical guess), runs the checks registry, and calls report.mjs for a first deterministic-only report:node "${CLAUDE_PLUGIN_ROOT}/scripts/audit.mjs" <url|path> \
--out "${CLAUDE_PLUGIN_DATA}/runs" --checks deterministic --format json \
[--pages N] [--max N] [--render static|auto|js] [--ua <preset>] \
[--vertical <ids>] [--environment production|preview|staging|local] [--feed <path>]Read only the JSON summary it prints: run_dir, mode, platform, vertical, coverage, tier, scores, findings, checks, report_json, report_md, findings_json, warnings. --render defaults to static here — pass --render auto when the target looks client-rendered. Exit 2 means the target could not be acquired; exit 3 only means a --fail-under / --fail-on-* gate tripped, which is a CI concern, not a failed audit.
<run_dir>/crawl.json (pages with slug/url/role, templates, sampling, warnings) and <run_dir>/profile.json.parsed (<run_dir>/pages/<homepage-slug>.json) plus profile.vertical_hints. The script only guesses — profile.vertical.source is "inferred" unless --vertical was passed. If your reading adds or changes a vertical, re-run the deterministic pass over the same run (no re-crawl) so the conditional checks actually fire:node "${CLAUDE_PLUGIN_ROOT}/scripts/audit.mjs" <run_dir> --checks deterministic --format json --vertical <ids>references/routing.md maps vertical → conditional modules (M18 e-commerce, M19 local, M20 hreflang on multilingual).
<run_dir>/findings.deterministic.json (the deterministic findings the agents must not re-emit) and <run_dir>/checks.json (checks run, errors, needs_api, manual_review, dropped).Agent calls)Spawn the four read-only specialists in one message so their verbose intermediate output stays isolated. Each prompt = the envelope block + that agent's module list. Agents never rely on ${…} substitution: pass absolute paths.
ENVELOPE
plugin_root: <absolute ${CLAUDE_PLUGIN_ROOT}>
run_dir: <absolute run dir>
pages: [{slug, url, role}, …] # <run_dir>/pages/<slug>.json (+ <slug>.html, + <slug>.rendered.html when rendered)
site: robots=<run_dir>/site/robots.json sitemaps=<run_dir>/site/sitemaps.json discovery=<run_dir>/site/discovery.json
vertical: {primary: <v>, also: [<v>…], multilingual: <bool>}
platform: <run_dir>/profile.json # one line: <platform>/<framework>, env=<kind>, head_owner=<…>
platform_cards: [<plugin_root>/references/platforms/<id>.md, …] # omit when the platform is unknown
modules: [<M-ids for this agent>]
deterministic_findings: <run_dir>/findings.deterministic.json — do not re-emit these ids; add model-judged findings only
return: JSON array only — findings per schema/finding.schema.json, no prose| Agent | Modules |
|---|---|
technical-auditor | M1, M2 (+M3), M4, M7, M7b (mobile), M7c (headings), M8, M9, M10, M15, M17 — plus M20 (hreflang) when vertical.multilingual |
ai-search-geo-specialist | M6, M11, M12, M14, M21 (AI discovery & agent endpoints, weight 0), M22 (agent-readiness) |
content-eeat-analyst | M13, M16 |
schema-generator | M5 — plus M18 when ecommerce ∈ vertical, M19 when local-business ∈ vertical |
Subagents have no Write/Edit — the audit can never mutate files. If an agent returns prose around the array, keep only the array.
<run_dir>/agents/<agent>.json via a Bash heredoc (mkdir -p "<run_dir>/agents" && cat > "<run_dir>/agents/<agent>.json" <<'EOF' … EOF) — into the plugin data dir, never the project. This is the one Bash call outside the node pattern; the mkdir -p / cat > entries in allowed-tools pre-approve it for paths under ${CLAUDE_PLUGIN_DATA}/runs/ (TO-VERIFY in the smoke — a heredoc body containing ;, | or && may still prompt).node "${CLAUDE_PLUGIN_ROOT}/scripts/report.mjs" <run_dir> --merge "agents/*.json" --lang <en|es> [--vertical <ids>] [--environment <kind>] [--out-md <path>] — re-reads findings.deterministic.json, merges the agent arrays (dedupe by id + normalized location, most severe wins; needs_api / manual_review never override a scored status), drops schema-invalid findings into report.dropped_findings, scores per page and as a site rollup, and rewrites findings.json, report.json, report.md. Pass the same --vertical / --environment you used in step 1. --merge is repeatable and accepts a file, a directory, or a */? glob on the file name only.report.json (bands/interpretations per references/scoring-model.md):coverage.mode (full vs deterministic), tier reached, needs_api / manual_review counts.crawl.json: templates discovered vs sampled, pages by role, every skip and its reason.expected_impact.report.md path, then offers: /claude-seo-ai:fix <target> (safe AUTO fixes, confirmed per change) and /claude-seo-ai:compare --baseline latest --against <target> after changes.If node is missing, or a skills-only install ships no scripts/ directory: say so first. Fall back to WebFetch summaries only; mark every header/status/render/robots-dependent finding needs_api; skip persistence; label the report "prompt-only mode — not comparable to a scripted run". Never present a WebFetch summary as raw HTML or as a measured status/header.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.