Add a comprehensive load verifier and fix the two issues it found:
- scripts/verify_skills.py: validates every loadable unit (flat root, suite sub-skill,
plugin skill) with real YAML parsing, name regex + global uniqueness, frontmatter
<=1024, description sanity, plugin.json JSON validity, and orphan detection. Read-only.
- 92-tui-design-template (root + code/SKILL.md): fix invalid YAML `triggers:` block
(`- "a", "b"` multi-scalar list items) -> one phrase per list item.
- 17-seo-schema-generator: remove ">" from description ("generate -> validate" ->
"generate then validate"); angle brackets are disallowed in descriptions.
Result: 75/75 loadable skills valid — 0 failures, 0 name collisions, 0 orphans,
0 plugin-manifest errors (65 flat + 3 plugins + 7 suite sub-skills).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
127 lines
6.6 KiB
Markdown
127 lines
6.6 KiB
Markdown
---
|
||
name: 17-seo-schema-generator
|
||
description: |
|
||
Generates validation-ready JSON-LD structured data for a site, covering BOTH
|
||
scenarios: (1) from an existing website — extract facts from live pages; and
|
||
(2) from collected sources for a not-yet-published site — reconcile conflicting
|
||
facts into a provenance-tracked claims register. Both modes emit the same claims
|
||
register, build pruned drafts from type templates (no placeholders shipped), and
|
||
hand off to 16-seo-schema-validator (generate then validate, gate = zero P0).
|
||
Triggers: generate schema, create JSON-LD, schema markup, structured data generator,
|
||
source-to-schema, pre-launch schema, claims register, 스키마 생성, 스키마 저작,
|
||
구조화 데이터 생성, 미발행 사이트 스키마, 기존 사이트 스키마 추출.
|
||
version: "2.0"
|
||
author: OurDigital / D.intelligence
|
||
environment: Code
|
||
---
|
||
|
||
# SEO Schema Generator (17)
|
||
|
||
Author JSON-LD for a site — whether the pages already exist or the site is not yet
|
||
published. Both cases are error-prone for the same reason: facts must be turned into
|
||
schema without leaking conflicts, gaps, or placeholders. This skill makes that reliable
|
||
by routing **both scenarios through one pivot — a claims register** — then generating
|
||
pruned drafts that hand off cleanly to the `16-seo-schema-validator` gate.
|
||
|
||
**Generate (17) → Validate (16).** This skill produces drafts; 16 is the QA gate.
|
||
|
||
## Two modes, one pipeline
|
||
|
||
The only thing that differs between the scenarios is **where facts come from**.
|
||
Everything after the claims register is identical.
|
||
|
||
| | **Mode 1 — from an existing site** | **Mode 2 — from collected sources** |
|
||
|---|---|---|
|
||
| When | Site has pages but lacks (or needs better) schema | Site not published yet (no DOM) |
|
||
| Source of truth | the live pages | scattered, conflicting sources (DART, Wikidata, brochures) |
|
||
| Seed the register with | `scripts/extract_site_claims.py` | manual research → `templates/claims-register.csv` |
|
||
| Hard part | extraction & mapping | authority hierarchy + entity reconciliation |
|
||
| Conflicts | rare (one source) | frequent → resolve before shipping |
|
||
|
||
```
|
||
Mode 1 (extract_site_claims.py)─┐
|
||
├─▶ claims_register.csv ─▶ build_schema_drafts.py ─▶ drafts/*.jsonld
|
||
Mode 2 (research + register)────┘ (the pivot) └─▶ schema_drafts_dataset.csv
|
||
│
|
||
16-seo-schema-validator ▼ (gate: zero P0)
|
||
```
|
||
|
||
## The claims register — the core idea
|
||
|
||
A **claims register** is a provenance-tracked, conflict-resolved fact table. Columns:
|
||
`entity_id, entity_type, property, value, lang, url, source_ids, authority, confidence,
|
||
conflict, status, note`. Dotted `property` paths nest (`address.streetAddress`);
|
||
pipe-separate array values (`a|b|c`).
|
||
|
||
**Only `CONFIRMED`, non-conflicting claims become schema.** Everything else (PENDING,
|
||
CONFLICT, REJECTED, EMPTY) is excluded and reported — never shipped. An unfilled
|
||
template slot is **deleted**, never emitted as `{{…}}` or `TODO` (placeholder leakage
|
||
is the #1 pre-launch P0).
|
||
|
||
## How to run
|
||
|
||
```bash
|
||
# Try the bundled sample first (Mode 2)
|
||
python scripts/make_sample.py
|
||
python scripts/build_schema_drafts.py fixtures/sample_claims.csv --out drafts_out
|
||
|
||
# MODE 1 — existing site → register (URLs, or local .html / a directory offline)
|
||
python scripts/extract_site_claims.py https://example.com/ https://example.com/about \
|
||
--out site_claims
|
||
# review site_claims/claims_register.csv (confirm PENDING rows), then build:
|
||
python scripts/build_schema_drafts.py site_claims/claims_register.csv --out drafts_out
|
||
|
||
# MODE 2 — collected sources → register (fill templates/claims-register.csv by hand)
|
||
python scripts/build_schema_drafts.py path/to/claims_register.csv --out drafts_out
|
||
|
||
# HAND OFF TO THE GATE (must reach zero P0)
|
||
python ../16-seo-schema-validator/scripts/validate_schema.py \
|
||
drafts_out/schema_drafts_dataset.csv --out qa_out
|
||
```
|
||
|
||
## Outputs
|
||
|
||
- `drafts/*.jsonld` — one pruned draft per entity (× language).
|
||
- `schema_drafts_dataset.csv` — directly consumable by `16-seo-schema-validator`.
|
||
- `build_report.md` — entities built + **excluded claims** (PENDING / CONFLICT / EMPTY) with reasons.
|
||
- (Mode 1 also) `claims_register.csv` + `extraction_report.md`.
|
||
|
||
## Stage gates (설계→개발→테스트→안정화→런칭 후)
|
||
|
||
- **G1 설계** — Lock the entity→type map (`references/entity-and-type-map.md`). Mode 2: source
|
||
register complete (≥2 sources/entity). *DoD:* every entity has an assigned type + required list.
|
||
- **G2 개발** — Seed the register (Mode 1 extract / Mode 2 research), reconcile to `CONFIRMED`,
|
||
conflicts = 0, run the builder → drafts have **zero placeholders**.
|
||
- **G3 테스트** — Validate (16): **zero P0**; triage P1; fact-accuracy sign-off via `templates/review-guide.md` (report-based, not raw JSON).
|
||
- **G4 안정화** — Google Rich Results Test green on a sample; re-run shows no regression.
|
||
- **G5 런칭 후** — live schema == drafts; GSC "Rich results" no new errors.
|
||
|
||
## References & templates
|
||
|
||
- Mode 1 SOP: `references/site-extraction-methodology.md`.
|
||
- Mode 2 SOP (9 steps): `references/source-to-schema-methodology.md`.
|
||
- Source authority ranking: `references/source-authority-hierarchy.md`.
|
||
- Entity→type scoping: `references/entity-and-type-map.md`.
|
||
- Registers + review guide: `templates/claims-register.csv`, `templates/source-register.csv`, `templates/review-guide.md`.
|
||
|
||
## Templates included
|
||
|
||
`scripts/type_templates.json` covers Organization, WebSite, Hotel, Person, JobPosting,
|
||
VideoObject, FAQPage. Required props are aligned with the validator's rule set, so a
|
||
fully confirmed entity passes the gate. **Add a type = add a template block (edit JSON only).**
|
||
|
||
## Limits & honesty
|
||
|
||
- Quality of drafts == quality of the register. Garbage-in still produces gaps — but
|
||
reported, never as placeholders.
|
||
- Mode 1 inference (title/OpenGraph) is seeded as `PENDING` and will NOT ship until a
|
||
human confirms it; existing JSON-LD is seeded `CONFIRMED`. If a site already has good
|
||
JSON-LD, prefer auditing it directly with `16` Mode B.
|
||
- Authoritative rich-result eligibility still needs Google's online test on a sample at G4.
|
||
|
||
## Integration
|
||
|
||
- **→ 16-seo-schema-validator**: the dataset CSV is the handoff; the gate is `zero P0`.
|
||
- **→ seo-comprehensive-audit**: post-launch (G5) uses the validator's Mode B as audit stage 4.
|
||
- This skill is a one-time-per-site authoring workflow, **not** an audit-pipeline stage.
|