Files
our-claude-skills/custom-skills/16-seo-schema-validator/references/defect-taxonomy.md
Andrew Yim 4f48ba3c59 feat(seo-schema-validator): back the upgraded SKILL.md with a working 5-layer pipeline
The "Upgrade Schema Validator" commit added SKILL.md referencing files that did
not exist. Implement them so the skill actually runs:

- scripts/validate_schema.py — 5-layer offline validator (L0 coverage, L1 syntax,
  L2 vocabulary/value-format, L3 rich-result, L4 consistency) with xlsx/csv/jsonl/
  json/dir/live-URL adapters. Gate = zero P0; exits 1 on failure.
- scripts/schema_rules.json — curated hotel-focused, offline rule set (edit-only
  extension point).
- scripts/make_sample.py + fixtures/sample_schema.csv — deliberately flawed fixture
  seeding ≥1 defect per layer; used to self-test.
- references/ — validation-methodology, defect-taxonomy (25 codes), hotel-type-map.
- templates/ — client-qa-report, decision-log.
- code/CLAUDE.md — redirect legacy single-URL tool to the new pipeline.

Noise control: MISSING_RECOMMENDED aggregated one-line-per-node; unexpected-property
checks opt-in via --strict. Generalized client-specific shilla-type-map → hotel-type-map.
Self-tested: default P0=5/P1=4/P2=14 FAIL, --strict --no-recommended P2=0, adapters verified.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 23:48:51 +09:00

4.7 KiB
Raw Blame History

Defect Taxonomy

Every code validate_schema.py can emit, its default severity, and what to do. The validator writes these to defect_log.csv (columns: entry_id, url, node_type, layer, code, severity, message, status, owner, note) and results.json.

Severity model

Severity Definition Owner action
P0 Blocker — breaks parsing, blocks the rich result, or ships wrong/placeholder data. Fails the gate. Must fix before the entry reaches client review.
P1 Real defect, doesn't block the rich result. Fix before launch; track in the triage log.
P2 Optimization — recommended properties, formatting, orphan URLs. Backlog; fix opportunistically.

--strict promotes vocabulary/format warnings (and unknown types) from P2 to P1 and turns on UNEXPECTED_PROPERTY. --no-recommended drops MISSING_RECOMMENDED entirely. Neither changes the gate — the gate is always "zero P0."

Code reference

Layer 0 — Coverage

Code Sev Trigger Fix
COVERAGE_MISSING P1 Inventory URL has no authored entry. Author the entry, or remove the URL from the inventory.
COVERAGE_ORPHAN P2 Entry URL isn't in the inventory. Fix the URL typo, or update the canonical list.

Layer 1 — Syntax

Code Sev Trigger Fix
INVALID_JSON P0 JSON does not parse. Fix the JSON (trailing comma, unquoted key, smart quotes).
NO_SCHEMA_IN_HTML P0 Live page has no ld+json block (Mode B). Confirm the tag deployed and renders.
MISSING_CONTEXT P1 No top-level @context. Add "@context": "https://schema.org".
WRONG_CONTEXT P1 @context isn't schema.org. Correct the context URL.
NO_TYPE P1 No @type anywhere in the entry. Add the intended @type.
ENCODING_CORRUPTION P1 Replacement char <EFBFBD> present. Re-export as UTF-8; check the source pipeline.
FETCH_ERROR P1 Live URL could not be fetched (Mode B). Check the URL/network; retry.

Layer 2 — Vocabulary & value formats

Code Sev (strict) Trigger Fix
UNKNOWN_TYPE P2 (P1) @type not in the curated rule set. If intended, add it to schema_rules.json; else correct the type.
UNEXPECTED_PROPERTY — (P1) Property unknown for a known type (strict only). Remove the typo'd property, or add it to the type's allowed.
BAD_URL P2 (P1) A URL property isn't an http(s) URL. Use an absolute URL.
BAD_DATE P2 (P1) A date property isn't ISO-8601. Use YYYY-MM-DD (or full datetime).
BAD_LANG P2 (P1) inLanguage/availableLanguage isn't a BCP-47 code. Use ko, en, ja, zh, …
BAD_CURRENCY P2 (P1) priceCurrency isn't a 3-letter ISO-4217 code. Use KRW/USD, not /$.
BAD_NUMBER P2 (P1) A numeric property isn't numeric. Remove units/commas; keep digits.

Layer 3 — Rich-result requirements

Code Sev Trigger Fix
MISSING_REQUIRED P0 A Google-required property is absent. Add the property — the rich result is blocked without it.
MISSING_RECOMMENDED P2 Recommended properties absent (one line per node, lists all). Add what applies to improve eligibility/appearance.

Layer 4 — Consistency

Code Sev Trigger Fix
PLACEHOLDER_TEXT P0 Boilerplate token in a string (예시, 수정필요, lorem, {{, …). Replace with real content.
NAP_PHONE_MISMATCH P0 Same business, different telephone across entries. Reconcile to the canonical phone.
NAP_ADDRESS_MISMATCH P0 Same business, different streetAddress. Reconcile to the canonical address.
DUPLICATE_ID P1 One @id defined ≥2× with differing content. Make definitions identical, or split the @id.
DANGLING_ID P1 {"@id": …} reference to a node never defined. Define the node, or fix the reference.
GEO_SWAPPED P1 latitude/longitude transposed (swapping fixes it). Swap the values.
GEO_OUT_OF_RANGE P1 Coordinates impossible (lat∉[-90,90] or lon∉[-180,180]). Correct the coordinates.
DUPLICATE_DESCRIPTION P1 Same description reused across ≥3 entries. Write distinct descriptions per page.

Triage workflow

  1. Sort defect_log.csv by severity (already sorted P0→P1→P2 on write).
  2. P0: assign an owner, fix, re-run. No P0 may survive into client review.
  3. P1: set owner + status, decide fix-now vs accept; log accepted ones in templates/decision-log.md.
  4. P2: schedule into the optimization backlog.
  5. Re-run after fixes and confirm no regressions before advancing the stage gate.