forked from bchanot/claude
feat(agents): de-prescribe seo-analyzer for Opus 5 (C1 P2)
Choreography → when-guidance under the audience×mode-range invariant
(plan §4b Q3). Census 71/0 + model-routing 133/0 + seo-data 221/0 green
throughout; contract surface (§2a/2b) byte-identical; 1528→1503 lines.
- self-output verification: ':970 run it twice' → deterministic-engine
integrity guard (conf#8); ':1217 do not proceed' → single-shot-scoped
(conf#1); grouping sanity-check → when-guidance detector (rob#8)
- vestigial pre-BDR-061 'Transparency' line deleted; §15 ownership
folded into 'Dispatcher verifies'
- dedup (inspection-corrected: most annex 'twins' are distinct
obligations — kept): only true same-range dups removed ('Handoff to
dispatcher' ≈ sentinel note; 'Landing page rule' block ≈ payload
instance + RULES line)
- completeness checklist reshaped to routing map, rows verbatim (rob#3)
- caps softened: 'P0 rule' MUST/ALWAYS → plain content rules (CMS
plugin-first folded with STEP 2 twin, corr#3); First-action/ordering
emphasis dropped; C1a + sampling essays compressed (rules + LRN
citations kept); WebSearch → drifting-externals when-guidance (rob#6)
- FROZEN untouched: guard-first orderings :287, denominator-before-
sampling :550, R2 refuse, COVERAGE obligations, all STEP headers
- deltas: 'P0 rule' 2→0, ALWAYS 1→0, MUST 5→4; NEVER 9→9 (class-B
named bans, kept by design LRN-105)
This commit is contained in:
+54
-79
@@ -58,8 +58,8 @@ STEP 1-2 business/tech context is consumed by all later steps).
|
||||
|
||||
## STEP 0 — AUDIT DEPTH
|
||||
|
||||
**First action.** If a parent skill (`/seo` dispatcher) passed depth
|
||||
in $ARGUMENTS, use it. Otherwise:
|
||||
If a parent skill (`/seo` dispatcher) passed depth in $ARGUMENTS, use
|
||||
it. Otherwise:
|
||||
|
||||
```
|
||||
SEO AUDIT DEPTH — choose one:
|
||||
@@ -141,11 +141,10 @@ Record rendering: **SSR / SSG / SPA / hybrid / ISR**.
|
||||
|
||||
### CMS detection + SEO plugin presence (plugin-first strategy)
|
||||
|
||||
Before proposing any manual edit, detect if the site runs on a CMS
|
||||
and whether a SEO plugin is already handling the heavy lifting. If a
|
||||
CMS is detected WITHOUT a SEO plugin, the highest-priority quick win
|
||||
is to install the appropriate plugin — editing theme files manually
|
||||
is a last resort and creates maintenance debt.
|
||||
Detect whether the site runs on a CMS and whether a SEO plugin is
|
||||
already handling the heavy lifting; record the signals. The
|
||||
plugin-first ranking policy (CMS without plugin → installation is the
|
||||
top quick win) lives in STEP 10.
|
||||
|
||||
```bash
|
||||
# WordPress signals
|
||||
@@ -206,8 +205,7 @@ topology — TLS terminated upstream, the origin sees plain HTTP plus
|
||||
|
||||
`/harden` reuses this agent for its entire config-hardening axis, so a wrong
|
||||
topology call scores a client's server config against a file that never ran.
|
||||
geo-analyzer STEP 4 already carries the matching CDN/WAF-override check —
|
||||
keep the two consistent.
|
||||
(The same CDN/WAF-override check lives in geo-analyzer STEP 4.)
|
||||
|
||||
```bash
|
||||
# Server / hosting
|
||||
@@ -505,7 +503,7 @@ Fetch rendered HTML. Extract and analyze:
|
||||
|
||||
## STEP 5 — ON-PAGE AUDIT `[both]`
|
||||
|
||||
### Rendering gate — run this BEFORE anything else in STEP 5 (R2)
|
||||
### Rendering gate (R2) — it gates every on-page check below
|
||||
|
||||
```bash
|
||||
bash ~/.claude/lib/seo-data/fetch.sh rendercheck --url "https://$DOMAIN/"
|
||||
@@ -599,9 +597,9 @@ doorway-page risk — the exact thing the 30/70 rule exists to catch — is
|
||||
invisible. Group by shared parent AND by shared slug prefix; if ≥3 URLs share
|
||||
a prefix of 2+ hyphen tokens, that is a family whatever the depth.
|
||||
|
||||
Sanity-check the grouping before trusting it: a site whose sitemap yields
|
||||
almost as many families as URLs has probably defeated your heuristic, not
|
||||
proved it has no templates.
|
||||
A sitemap that yields almost as many families as URLs has probably
|
||||
defeated the heuristic, not proved the site has no templates — say so
|
||||
instead of trusting the grouping.
|
||||
|
||||
**Sample by finding class, because the classes need opposite samples:**
|
||||
|
||||
@@ -611,10 +609,9 @@ proved it has no templates.
|
||||
| **Duplication / 30-70 / cannibalisation** | **≥3 from the LARGEST family** | invisible with one page each. You cannot tell whether 25 city pages are 70% unique by reading one of them. |
|
||||
| Per-page content (title/description length, H1 wording) | spread across families + GSC position 4-10 quick wins | these vary per page even from one template. |
|
||||
|
||||
"One per template" is right for code and **wrong for the 30/70 rule** — a
|
||||
rule this spec mandates in §9. Sampling one page per family makes that check
|
||||
structurally impossible, so take the third page of the biggest family even
|
||||
though it is "the same template".
|
||||
The split is deliberate: one-per-family alone makes the §9 30/70 check
|
||||
structurally impossible — hence ≥3 pages from the biggest family, even
|
||||
though they share a template.
|
||||
|
||||
An un-sampled family is an un-audited family. Name the ones you skipped.
|
||||
|
||||
@@ -658,16 +655,11 @@ mapfile -t FEXCL < <(bash ~/.claude/lib/source-scope.sh findargs)
|
||||
find . "${FEXCL[@]}" -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" \) -printf "%s %p\n" 2>/dev/null | sort -rn | head -20
|
||||
```
|
||||
|
||||
**Why the guard, and why `find` specifically (C1a).** `grep` and `find`
|
||||
disagree about this repo and you use both. Claude Code routes `grep` through
|
||||
ugrep with `--ignore-files`, so it honours `.gitignore` and never descends
|
||||
into a gitignored `dist/`. `find` honours nothing. Measured on a real Astro
|
||||
repo: this command returned **92 images, 45 of them under `dist/`** — every
|
||||
asset twice, source and generated copy, byte-identical. So "top 20 by size"
|
||||
was ~10 real images dressed as 20, and a batch-C item
|
||||
(`cwebp -q 80 <img> -o <img>.webp`) could target `dist/og-image.png`, whose
|
||||
`.webp` the dispatcher's own `npm run build` then erases. The fix lands,
|
||||
verification passes, nothing survives.
|
||||
**Why the guard, and why `find` specifically (C1a).** Claude Code routes
|
||||
`grep` through ugrep with `--ignore-files` (honours `.gitignore`); `find`
|
||||
honours nothing. Measured on a real Astro repo: without the guard this
|
||||
command returned 92 images, 45 under `dist/` — and a batch-C item built
|
||||
on that targets an artifact the dispatcher's own `npm run build` erases.
|
||||
|
||||
`FEXCL` MUST be consumed as a quoted array. `find . $FEXCL …` lets the shell
|
||||
glob `*/dist/*` against the CWD and hand the matches to find as search paths
|
||||
@@ -967,8 +959,9 @@ disagree, and `/client-handover` gates on 17/20.
|
||||
**N/A is not a zero** and the engine will not let it behave like one.
|
||||
- `status: "error"` → malformed findings. Fix them; never fall back to
|
||||
eyeballing a number.
|
||||
- Run it twice on the same file before publishing. If the output moved, your
|
||||
findings moved, and that is the thing to explain.
|
||||
- The engine is deterministic: if you modified the findings JSON after
|
||||
scoring, re-run and explain the move — a shifted score means shifted
|
||||
findings, never engine noise.
|
||||
|
||||
**Technical axis note:** CWV scored on CrUX field data (75th percentile,
|
||||
real users, from STEP 4) when available; otherwise lab PageSpeed
|
||||
@@ -1144,22 +1137,19 @@ For each:
|
||||
- Expected impact (high / medium / low)
|
||||
- AUTO (bundled in STEP 12, applied by the dispatcher) or USER (in SEO.md §11, with automation options)
|
||||
|
||||
AUTO items are a commitment, not a suggestion.
|
||||
**CMS plugin first**: a CMS detected in STEP 2 without a SEO plugin
|
||||
makes plugin installation the top quick win —
|
||||
RankMath/Yoast/SEOPress (WordPress), Yoast SEO (Drupal), SEO Suite
|
||||
Ultimate (Magento), Plug in SEO (Shopify) deliver meta + sitemap +
|
||||
OG + breadcrumbs + JSON-LD in ~15 min of admin UI, where hand-editing
|
||||
theme files first creates duplication, conflicts, and maintenance
|
||||
debt. See `~/.claude/agents/resources/automation-catalog.md` CMS
|
||||
plugins section for the exact install path per CMS.
|
||||
|
||||
**P0 rule — CMS plugin first**: if STEP 2 detected a CMS without a
|
||||
SEO plugin, the FIRST quick win MUST be plugin installation. Reason:
|
||||
installing RankMath/Yoast/SEOPress (WordPress), Yoast SEO (Drupal),
|
||||
SEO Suite Ultimate (Magento), Plug in SEO (Shopify) takes ~15 min
|
||||
via admin UI and delivers meta + sitemap + OG + breadcrumbs + JSON-LD
|
||||
in one shot. Editing theme files by hand before this creates
|
||||
duplication, conflicts, and maintenance debt. See
|
||||
`~/.claude/agents/resources/automation-catalog.md` CMS plugins
|
||||
section for the exact install path per CMS.
|
||||
|
||||
**P0 rule — Bing Webmaster Tools**: on FULL audit, ALWAYS emit
|
||||
"Submit site to Bing Webmaster Tools" as a user action — ChatGPT
|
||||
Search uses the Bing index, so this is also a GEO signal. See
|
||||
automation-catalog.md for IndexNow + Bing.
|
||||
**Bing Webmaster Tools** (FULL audits): emit "Submit site to Bing
|
||||
Webmaster Tools" as a user action — ChatGPT Search uses the Bing
|
||||
index, so this is also a GEO signal. See automation-catalog.md for
|
||||
IndexNow + Bing.
|
||||
|
||||
### Medium term (1-3 months)
|
||||
City/service pages (30/70 rule: 30% shared, 70% unique per city),
|
||||
@@ -1214,7 +1204,8 @@ BATCH F — USER ACTIONS (N items, documented in SEO.md §11 with automation cat
|
||||
...
|
||||
```
|
||||
|
||||
Do not proceed to STEP 12 until this plan is printed.
|
||||
Single-shot runs (no MODE line) print this plan before STEP 12
|
||||
serializes it; `MODE: judge` simply ends here.
|
||||
|
||||
---
|
||||
|
||||
@@ -1306,18 +1297,19 @@ as the last line of the bundle — the dispatcher keys its apply step on it.
|
||||
Do NOT run any post-fix verification (build/lint, NAP consistency); the
|
||||
dispatcher does that after it applies. Your job ends at the sentinel.
|
||||
|
||||
### Bundle completeness checklist (did every finding reach the bundle?)
|
||||
### Finding-class → tier routing (complete map: every finding lands in
|
||||
exactly one tier; §11 mirrors USER ACTIONS)
|
||||
|
||||
- [ ] Meta/title/OG/canonical → AUTO (hotfixer)
|
||||
- [ ] JSON-LD LocalBusiness/Organization → AUTO (hotfixer/feater) — detailed GEO schema → geo-analyzer
|
||||
- [ ] Image alt/dimensions → AUTO (hotfixer); compression → AUTO (bash) or §11 if tools absent
|
||||
- [ ] robots.txt / sitemap.xml → AUTO (hotfixer) — AI-bot directives → geo-analyzer
|
||||
- [ ] .htaccess security headers, image/video sitemap, hreflang → AUTO (feater)
|
||||
- [ ] Legal pages, CMP, footer links → AUTO (feater)
|
||||
- [ ] Heading hierarchy, noindex on technical pages → AUTO (hotfixer)
|
||||
- [ ] Unverifiable aggregateRating removal → AUTO (hotfixer); stock-photo testimonials → GATED (E)
|
||||
- [ ] Structural / new pages → GATED (D)
|
||||
- [ ] Video transcripts, GMB, directories → USER ACTIONS (§11)
|
||||
- Meta/title/OG/canonical → AUTO (hotfixer)
|
||||
- JSON-LD LocalBusiness/Organization → AUTO (hotfixer/feater) — detailed GEO schema → geo-analyzer
|
||||
- Image alt/dimensions → AUTO (hotfixer); compression → AUTO (bash) or §11 if tools absent
|
||||
- robots.txt / sitemap.xml → AUTO (hotfixer) — AI-bot directives → geo-analyzer
|
||||
- .htaccess security headers, image/video sitemap, hreflang → AUTO (feater)
|
||||
- Legal pages, CMP, footer links → AUTO (feater)
|
||||
- Heading hierarchy, noindex on technical pages → AUTO (hotfixer)
|
||||
- Unverifiable aggregateRating removal → AUTO (hotfixer); stock-photo testimonials → GATED (E)
|
||||
- Structural / new pages → GATED (D)
|
||||
- Video transcripts, GMB, directories → USER ACTIONS (§11)
|
||||
|
||||
### Framework-specific notes
|
||||
|
||||
@@ -1339,23 +1331,6 @@ Carry the relevant note into each bundle item so the applier honors it:
|
||||
- **Ghost** — Native SEO strong (meta + OG + JSON-LD out of box). Usually no plugin needed; handle gaps via `default.hbs` edits.
|
||||
- **Wix / Squarespace / Webflow (hosted CMS)** — No theme file access. ALL SEO changes happen in the admin UI: meta, alt, sitemap, redirects, JSON-LD (partial). Agent emits detailed USER action list per panel to touch — cannot auto-apply anything.
|
||||
|
||||
### Landing page rule
|
||||
|
||||
Zero visible change on landing/homepage except:
|
||||
- Meta tags (invisible)
|
||||
- Footer links (discreet)
|
||||
- JSON-LD (invisible)
|
||||
- Image fixes: compression, alt, dimensions (invisible or quasi)
|
||||
|
||||
Anything else → batch D (confirmation).
|
||||
|
||||
### Handoff to dispatcher
|
||||
|
||||
Post-fix verification (build/lint, NAP consistency across JSON-LD /
|
||||
visible / GMB, revert-on-break) and the §15 change log are the
|
||||
DISPATCHER's responsibility, AFTER it applies the bundle at L1. You
|
||||
emitted the bundle terminated by the sentinel — stop here.
|
||||
|
||||
---
|
||||
|
||||
## STEP 13 — OUTPUT `[both]`
|
||||
@@ -1519,10 +1494,10 @@ PROCHAINE ETAPE : <highest-priority>
|
||||
### Process
|
||||
- **Every user action lists automation.** Mandatory from
|
||||
`~/.claude/agents/resources/automation-catalog.md`.
|
||||
- **WebSearch on FULL** to validate tool landscape + cross-check
|
||||
competitor state before emitting.
|
||||
- **WebSearch on FULL when naming drifting externals** — tool
|
||||
landscapes and competitor state shift; cross-check before a
|
||||
recommendation names them.
|
||||
- **Iterative SEO.md.** Preserve Historique section.
|
||||
- **Transparency.** Every automated change logged with file, change,
|
||||
reason.
|
||||
- **Dispatcher verifies.** Build/lint pass + revert-on-break happen in
|
||||
the dispatcher after it applies the bundle — never in this agent.
|
||||
- **Dispatcher verifies.** Build/lint pass, revert-on-break and the §15
|
||||
change log happen in the dispatcher after it applies the bundle —
|
||||
never in this agent.
|
||||
|
||||
Reference in New Issue
Block a user