diff --git a/agents/geo-analyzer.md b/agents/geo-analyzer.md index 66f845c..ad26ddf 100644 --- a/agents/geo-analyzer.md +++ b/agents/geo-analyzer.md @@ -813,7 +813,14 @@ to act without your audit context. Embed per item: - **Templates + context** — G2/G6 paste the expected JSON-LD from `geo-schemas.md` + business context (entity name, sameAs, @id canonical) + framework note. G4 follows `llms-txt-template.md` exactly. G1 pastes - the correct variant from `ai-crawlers-2026.md`. + the correct variant from `ai-crawlers-2026.md`. When a G2 item needs a + `Reservation`/`OrderAction`/`DiscussionForumPosting`/`ProfilePage` block, + generate the skeleton via `fetch.sh schema_gen + [flags]` + (`~/.claude/lib/seo-data/fetch.sh`) and fill in the real values, rather + than hand-writing that markup. The data-integrity rule still applies on + top of it: `schema_gen` only generates STRUCTURE — unknown field values + stay `[À COMPLÉTER]`, never invented to fill a flag the verb needs. - **PERMISSIVE default** on G1 unless the client flagged premium/regulated. ### Output shape diff --git a/lib/seo-data/README.md b/lib/seo-data/README.md index 747a244..3b457d0 100644 --- a/lib/seo-data/README.md +++ b/lib/seo-data/README.md @@ -215,6 +215,39 @@ fetch.sh score --findings • Malformed input is an error, never a silently wrong number — unlike the fetch verbs, a degrade here would mean bad input, not a network fact. +fetch.sh schema_gen [flags] [--script-tag] + → {"status":"ok","source":"schema_gen","type":"<@type>","jsonld":{…}} + → {"status":"error","reason":"bad_usage"} # a REQUIRED flag omitted + → {"status":"degraded","reason":"…"} # a required flag given, empty + + fetch.sh schema_gen reservation --provider "Marea NYC" \ + --start 2026-06-04T19:30:00-04:00 --party-size 4 + fetch.sh schema_gen order --merchant "Acme Pizza" --order-url https://acme.example/order + fetch.sh schema_gen discussion --headline "…" --author "Sara Park" \ + --url https://forum.example.com/t/123 --date 2026-05-12T14:00:00Z + fetch.sh schema_gen profile --name "Daniel Agrici" --url https://agricidaniel.com/about \ + --same-as https://github.com/AgriciDaniel --knows-about "SEO" "Schema markup" + + Adapted from claude-seo's `schema_generate.py` (MIT) into this contract. + Our system only AUDITS existing markup elsewhere; this is the one verb + that GENERATES it — deterministic JSON-LD skeletons for the four v2 + high-leverage Schema.org types, so geo-analyzer's G2 batch stops + hand-writing markup by hand. It only generates STRUCTURE: unknown field + VALUES are the caller's job, `[À COMPLÉTER]` for anything unconfirmed — + this verb never invents a sameAs, an email, or a business name. + • Stdlib only, no network, no auth — runs even without the venv. + • `--script-tag` wraps the cleaned jsonld in + `` under a `script` key, + still inside the `ok` envelope. It must be given AFTER the type + (`schema_gen reservation … --script-tag`, not before) — argparse + subcommand flags only parse after their subcommand. + • Never emits a JSON `null`: fields left unset are omitted from the + `jsonld` object entirely rather than serialised as `null`. + • A REQUIRED flag omitted → `{"status":"error","reason":"bad_usage"}`, + exit 2 (bad usage, like every other verb). A required flag GIVEN but + empty (argparse cannot catch that) → `{"status":"degraded",...}`, + exit 0 — fail-open, never a traceback. + fetch.sh drift --url https://ex.com/sitemap.xml [--max 500] → {"status":"ok","baseline":true,"captured":"…","pages":24,"store":"…"} → {"status":"ok","baseline":false,"since":"…","gone":[…],"new":[…], diff --git a/lib/seo-data/fetch.sh b/lib/seo-data/fetch.sh index e2291be..9934db9 100644 --- a/lib/seo-data/fetch.sh +++ b/lib/seo-data/fetch.sh @@ -34,6 +34,8 @@ case "$cmd" in exec "$PY" "$HERE/sitemap.py" --store "$STORE" "$@" ;; score) exec "$PY" "$HERE/score.py" --store "$STORE" "$@" ;; + schema_gen) + exec "$PY" "$HERE/schema_gen.py" --store "$STORE" "$@" ;; drift) exec "$PY" "$HERE/drift.py" --store "$STORE" "$@" ;; rendercheck) @@ -52,6 +54,6 @@ case "$cmd" in fi echo '{"status":"error","reason":"usage: fetch.sh forget {--label