---
name: 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.
