Implement ourdigital-presales-seo skill

SKILL.md orchestration (8 gated stages), references (rate_card.yaml,
findings_to_service rubric, competitor sets), findings.schema.json contract,
and scripts: kg_query.py (generalized KG examination), estimate.py
(findings→rate-card 견적 md/xlsx/json), build_deck.py (9-slide branded PPTX),
render_pdf.sh (Korean PDF via headless Chrome), plus client_brief.html template.

Validated on Sono Hotels & Resorts findings: estimate OD-2026-001
(23-47M KRW) and a 9-slide deck generated cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 23:10:53 +09:00
parent a55e77d1b0
commit ba88247496
10 changed files with 1034 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
# Default competitor benchmark sets (Korean market)
Used by Stage 3 (KG/entity) when the user doesn't supply competitors. Pick the set
matching the prospect's vertical; pass as `--competitors` to `kg_query.py`.
## hotel_resort (호텔·리조트)
- 롯데호텔 (Lotte Hotel) — strong KG, LodgingBusiness type, Korean Wikipedia
- 신라호텔 / 호텔신라 (Shilla)
- 조선호텔앤리조트 (Josun)
- 한화리조트 / 한화호텔앤드리조트 (Hanwha)
- 켄싱턴리조트 (Kensington)
## city_hotel (시티 호텔)
- 롯데호텔, 신라호텔, 조선호텔, 글래드호텔, 나인트리
## condo_membership (콘도·회원권)
- 한화리조트, 대명(소노), 한솔오크밸리, 금호리조트
## benchmark_signals
For each competitor record in `findings.json.entity.competitor_benchmark`:
`{name, score (KG result_score), type (@type), wikipedia (bool)}`.
The benchmark table contrasts the prospect's entity strength/type/Wikipedia
presence against these — the core competitive-gap visual in the deck.

View File

@@ -0,0 +1,26 @@
# Findings → service rubric
How `estimate.py` maps detected findings (from `findings.json`) to `rate_card.yaml`
service lines. The script reads the structured signals below; this file is the
human-readable source of truth for the rules.
| Trigger (signal in findings.json) | Service line(s) | Scope driver |
|---|---|---|
| `discovery.sitemap_status != 200` OR `discovery.robots_sitemap_declared == false` OR `discovery.discoverable_urls` low vs `estimated_pages` | `technical_audit` + `technical_remediation` | site size / # templates |
| `technical.cwv.perf < 0.5` OR `cls > 0.1` OR `lcp_ms > 2500` OR `ttfb_ms > 600` | `technical_audit` (if not already) + `technical_remediation` | # templates |
| `technical.schema.org == "bare"/"none"` OR `entity.panel != "hotel"` OR `entity.name_split` OR `entity.legacy_contamination` OR `entity.subbrands_with_entity == 0` | `schema_build` (one-time) + `onpage_entity` (retainer) | # sub-brands + # properties |
| `entity.properties_with_entity == 0` OR `url_hygiene` contains GBP/local mismatch | `local_seo` | # properties |
| `findings[].class` includes measurement gap / no GSC-GA4 | `ga4_impl` and/or `dashboard` (+ `gtm_setup` if tag gaps) | — |
| `technical.meta_dupe` OR `technical.title_i18n_mismatch` OR `technical.hreflang == "incomplete"` | `onpage_entity` | # templates |
**Severity → priority** (for the brief/deck ordering, not pricing):
- `critical`: crawl/index blocking, CWV failing, entity mistyped
- `high`: entity/sub-brand gaps, duplicate URLs, meta dupes
- `medium`: hreflang, H1, hygiene
**Quantity rules**
- `monthly` line items use `rate_card.defaults.retainer_months` (default 6).
- `local_seo` scope note scales with property count (`entity` / discovery counts).
- One-time items counted once even if triggered by multiple findings.
Edit this file and `rate_card.yaml` together when rates or rules change.

View File

@@ -0,0 +1,51 @@
# OurDigital service rate card — single source for estimate.py
# Mirrors the ourdigital-backoffice quote ranges. Values are KRW, treated as
# pre-sales estimate RANGES (finalize after a precise diagnostic with access).
quote_prefix: OD # quote number format: OD-YYYY-NNN
currency: KRW
services:
technical_audit:
label_ko: "Technical Audit / 기술 SEO 진단"
unit: one_time # one_time | monthly | project
min: 3000000
max: 5000000
technical_remediation:
label_ko: "기술 개선 실행 (sitemap/CWV/SSR)"
unit: project
min: 3000000
max: 8000000
onpage_entity:
label_ko: "On-Page / Entity Optimization (월 운영)"
unit: monthly
min: 1500000
max: 3000000
schema_build:
label_ko: "구조화 데이터(Schema) 구축 (1회)"
unit: one_time
min: 2000000
max: 4000000
local_seo:
label_ko: "Local SEO (프로퍼티 로컬 최적화)"
unit: monthly
min: 1000000
max: 2000000
gtm_setup:
label_ko: "GTM Setup / 태그 관리 구축"
unit: project
min: 2000000
max: 4000000
ga4_impl:
label_ko: "GA4 Implementation / 분석 환경 구축"
unit: project
min: 1500000
max: 3000000
dashboard:
label_ko: "Dashboard Development / 대시보드 개발"
unit: project
min: 3000000
max: 6000000
defaults:
retainer_months: 6 # default contract length for monthly line items
disclaimer_ko: "본 견적은 공개 데이터 기반 사전 추정 범위이며, Search Console/Analytics 권한 확보 후 정밀 진단을 통해 확정됩니다."