| name | ad-claim-compliance |
| description | Kiểm tra tuân thủ Luật Quảng cáo về từ ngữ tuyệt đối trên content/website — phát hiện 'nhất', 'duy nhất', 'tốt nhất', 'số một', 'số 1', 'hàng đầu' và từ ngữ ý nghĩa tương tự (vị thế dẫn đầu/độc bản/tuyệt đối) theo TT 12/2026 + khoản 11 Điều 8 Luật Quảng cáo. 2-stage: Pass 1 detect→verdict+nguyên tắc reword (OPT 2, quét toàn portfolio, nhẹ); Pass 2 on-demand auto-generate câu thay thế giữ keyword + đúng char-limit (OPT 1). Verdict: VIOLATION/NEEDS_PROOF/PROOF_NOT_CITED/REVIEW/OK. Risk score = vị trí × page type × ngành YMYL. Evidence Registry per-client (tài liệu Điều 3.2 → claim OK; check citation Điều 3.4). 2 mode: standalone audit domain/portfolio + embedded gate trong qc-content/xay-dung-noi-dung/optimize-seo-page/refresh-content. Trigger: check tuân thủ quảng cáo, compliance từ ngữ, kiểm tra 'nhất'/'duy nhất'/'tốt nhất'/'số 1', superlative check, từ ngữ tuyệt đối, content vi phạm, audit ad claim. MCP: sf-enhanced, search-console, data-cache. Output Excel + terminal dashboard. Confirm cost trước crawl. |
Ad Claim Compliance — Kiểm tra từ ngữ quảng cáo tuyệt đối
Mục tiêu duy nhất: Không để client bị xử phạt vì dùng từ ngữ tuyệt đối ("nhất", "duy nhất", "tốt nhất", "số một", "hàng đầu"...) trong content/website mà không có tài liệu hợp pháp chứng minh.
Triết lý: Detect trước, review sau, fix sau cùng. KHÔNG auto-reword mù toàn portfolio (đốt token + tạo bản nháp vô dụng cho claim mà writer chưa quyết giữ/bỏ). User phải XEM finding + verdict + nguyên tắc trước, rồi mới chọn claim nào cần auto-generate câu thay thế.
Cơ sở pháp lý (hiệu lực 05/07/2026):
- Khoản 11 Điều 8 Luật Quảng cáo: cấm dùng "nhất", "duy nhất", "tốt nhất", "số một" hoặc từ ngữ ý nghĩa tương tự mà không có tài liệu hợp pháp chứng minh.
- TT 12/2026/TT-BVHTTDL Điều 3: định nghĩa "từ ngữ tương tự" + 2 loại tài liệu chứng minh + quy định hiển thị citation.
- TÊN SKILL KHÔNG gắn số TT — Thông tư đổi số nhưng Điều 8 Luật QC là nền tảng bền. Khi luật cập nhật chỉ sửa
references/lexicon.md + cơ sở pháp lý, không đổi skill.
⚖️ Giới hạn: Skill là heuristic compliance ở mức vận hành, KHÔNG phải tư vấn pháp lý. Vùng REVIEW (gray zone) + claim client ngân hàng/tài chính/y tế nên để legal client confirm trước khi sửa hàng loạt.
2 CHẾ ĐỘ
| Mode | Input | Dùng khi |
|---|
| Standalone | 1 domain HOẶC list domain (portfolio) | Audit trước deadline 5/7, onboard client mới, audit định kỳ |
| Embedded gate | 1 bài/URL/raw content | Tự trigger trong content pipeline, chặn superlative TRƯỚC khi lên production |
⚡ TỰ TRIGGER (Embedded gate)
Skill chạy như 1 gate compliance trong các pipeline content. KHÔNG cần user gọi tay:
qc-content → sau khi chấm 12-dim, gate compliance TRƯỚC verdict PASS
xay-dung-noi-dung → sau khi viết, TRƯỚC khi xuất DOCX/đăng
optimize-seo-page → khi rewrite title/meta/H1 → check claim mới sinh ra
refresh-content → khi update content cũ → check claim trong bản mới
research-quotation → check claim trong sample content client gửi pitch
client-report-monthly → flag claim risk trong "Technical/Content" section nếu có
Hành vi gate: chỉ chạy Pass 1 (detect + verdict + nguyên tắc) trên content đang xử lý. Nếu có VIOLATION ở title/meta/H1 → BLOCK, báo finding, không cho pipeline xuất bản cho tới khi xử lý. Body VIOLATION → WARN, cho qua nhưng note vào output.
Opt-out: "skip compliance", "không cần check quảng cáo".
ENGINE — 4 LAYER
Layer 1 — DETECTION
Lexicon đầy đủ ở references/lexicon.md (3 nhóm theo Điều 3.1 + exception list + EN). Đọc file đó khi chạy.
Nguồn quét (Standalone, ưu tiên field hiển thị công khai):
- Title tag · Meta description · H1 · H2/H3 · Body · Schema (name, description) · Image alt · OG title/description
3 nhóm match (Điều 3.1):
- Nhóm A — Vị thế dẫn đầu: hàng đầu, dẫn đầu, đứng đầu, tiên phong, đầu ngành, top 1, đầu tiên · EN: leading, #1, no.1, market leader, pioneer
- Nhóm B — Tính độc bản: duy nhất, độc nhất, độc quyền, chỉ có tại, không nơi nào có, có một không hai · EN: only, the only, exclusive, one-of-a-kind
- Nhóm C — Tính tuyệt đối: nhất, số một, số 1, tốt nhất, hoàn hảo, tuyệt đối, vô địch, vượt trội, xuất sắc nhất, uy tín nhất · EN: best, finest, ultimate, perfect, unmatched, world-class
Pattern VN X nhất (chỗ khó nhất — false positive cao):
- Match mọi cụm
\S+\s+nhất → candidate.
- BẮT BUỘC lọc qua exception list (
references/lexicon.md): thống nhất, đồng nhất, nhất quán, nhất trí, thứ nhất, hợp nhất, nhất thời, nhất loạt, nhất là, nhất định, nhất thiết... → KHÔNG phải claim, loại bỏ.
- "duy nhất / độc nhất / đệ nhất / hạng nhất" → GIỮ (là claim).
- Khi không chắc 1 cụm
X nhất có phải claim → đưa vào verdict REVIEW, không tự loại.
EN superlative: word list ở trên + pattern \b\w+est\b (cheapest, fastest, finest), lọc stopword (honest, interest, latest-as-recent...).
Mỗi finding lưu: url | location | matched_term | nhom | snippet (±8 từ ngữ cảnh) | page_type | industry.
Layer 2 — RISK SCORE
RiskScore = base(location) × mult(page_type) × mult(industry)
| location | base | | page_type | mult | | industry | mult |
|---|
| Title tag | 5 | | Money/PLP/Landing/Home | 1.5 | | Banking/Finance/Insurance | 1.5 |
| Meta desc | 4 | | Service/Product detail | 1.3 | | Health/Pharma/Dental | 1.5 |
| H1 | 4 | | About/Profile | 1.0 | | Khác | 1.0 |
| Schema name/desc | 3 | | Blog informational | 0.7 | | | |
| Body (đầu trang) | 3 | | | | | | |
| Body (sâu) / alt | 2 | | | | | | |
Tier: HIGH ≥6 · MED 3–6 · LOW <3.
Hard rule (override): superlative ở Title/Meta trên Money page ngành YMYL = auto HIGH bất kể điểm.
Layer 3 — VERDICT
| Verdict | Điều kiện | Handling |
|---|
| VIOLATION | Claim KHÔNG có trong Evidence Registry + page type là quảng cáo (không phải blog trung lập) | → OPT 1 hoặc OPT 2 |
| NEEDS_PROOF | Claim có thể giữ NẾU client cấp tài liệu Điều 3.2 (đáng để xin proof — claim mạnh, trang quan trọng) | → request doc; có doc → register → OK; không có → VIOLATION |
| PROOF_NOT_CITED | Claim CÓ proof trong Registry, nhưng page CHƯA hiển thị tên tài liệu + số/ký hiệu + thời gian (vi phạm hình thức Điều 3.4) | → bổ sung dòng citation lên page, không cần đổi claim |
| REVIEW | Gray zone: blog informational, hoặc cụm X nhất không chắc là claim, hoặc ngữ cảnh mơ hồ | → human phán, không auto |
| OK | Trong Registry còn hiệu lực + đã cite đúng Điều 3.4 · HOẶC false-positive đã loại · HOẶC ngữ cảnh thông tin trung lập rõ ràng | → bỏ qua |
Layer 4 — EVIDENCE REGISTRY (per-client)
Input optional: file registry per-client (template assets/evidence-registry-template.csv). Liệt kê các claim ĐÃ có tài liệu hợp pháp:
claim_text | claim_normalized | proof_type(survey/award) | proof_name | proof_number | issuer | valid_from | valid_to | source_url
Logic:
- Normalize claim text (lowercase, bỏ dấu câu) → match finding với registry.
- Match + còn hiệu lực (
valid_to ≥ hôm nay) + page đã cite → OK.
- Match + còn hiệu lực + page CHƯA cite → PROOF_NOT_CITED.
- Match nhưng
valid_to < hôm nay → VIOLATION (proof hết hạn, Điều 3.3) + cờ expired.
- Không có registry → mọi claim chạy verdict bình thường (không claim nào auto-OK).
Layer này tách "vi phạm thật" khỏi "claim hợp lệ có giấy tờ". Thiếu nó → skill spam false alarm cho client có chứng nhận thật.
🔑 2-STAGE FLOW — OPT 1 & OPT 2
Đây là logic cốt lõi. Hai option là action per-finding, KHÔNG phải mode toàn skill. Default chạy Pass 1 cho tất cả, OPT 1 chỉ chạy khi user chọn ở Pass 2.
PASS 1 — Detect + Verdict + Nguyên tắc (= OPT 2, luôn chạy, nhẹ)
Quét toàn bộ → mỗi finding ra: url · location · term · risk tier · verdict · NGUYÊN TẮC reword áp dụng.
NGUYÊN TẮC reword (không generate câu, chỉ chỉ hướng — references/reword-playbook.md):
- P1 — Quantify: thay claim tuyệt đối bằng số liệu provable ("giảm 30% thời gian" thay "nhanh nhất").
- P2 — Hedge: "một trong những...", "được nhiều khách hàng tin chọn".
- P3 — Factual scope: dữ kiện chứng minh được ("10 năm kinh nghiệm", "5.000+ khách hàng").
- P4 — Strip: bỏ superlative, giữ noun ("dịch vụ SEO" thay "dịch vụ SEO tốt nhất").
- P5 — Substantiate: giữ nguyên claim, đi xin tài liệu Điều 3.2 (chỉ khi NEEDS_PROOF + đáng đầu tư).
→ Output Pass 1 (dashboard + Excel) cho user review. DỪNG ở đây. Hỏi user chọn xử lý.
PASS 2 — Auto Reword (= OPT 1, on-demand, chỉ chạy khi chọn)
User chọn scope cần auto-generate: theo verdict (vd "tất cả VIOLATION"), theo client, theo URL list, hoặc từng finding. Với mỗi finding được chọn, generate 2–3 câu thay thế tuân thủ:
- Giữ target keyword — bản thay thế phải SEO-tương đương, không giết keyword. (Đây là value của agency, không phải chỉ "an toàn pháp lý".)
- Đúng char-limit slot: Title ≤60 ký tự · Meta 150–160 · H1 linh hoạt · giữ nguyên format slot.
- Áp nguyên tắc P1–P4 theo
references/reword-playbook.md, ưu tiên P1/P3 (provable) cho ngành YMYL.
- Mỗi variant kèm note: nguyên tắc dùng + variant nào giữ keyword mạnh nhất + char count.
Output Pass 2: bảng finding → 2-3 variants → recommended append vào Excel (sheet Reword) + ghi đè được nếu user duyệt.
Routing handling theo verdict:
VIOLATION → user chọn OPT 1 (auto reword) hoặc OPT 2 (giao writer tự sửa theo nguyên tắc)
NEEDS_PROOF → action = request tài liệu Điều 3.2 từ client
→ có tài liệu: thêm vào Registry → OK
→ không có: chuyển VIOLATION → OPT 1/OPT 2
PROOF_NOT_CITED → action = bổ sung dòng citation (tên TL + số + thời gian) lên page; KHÔNG đổi claim
REVIEW → human phán; nếu xác định là claim → VIOLATION → OPT 1/OPT 2
OK → no action
CONFIRM DIALOG (Standalone, trước khi crawl)
KHÔNG auto-run crawl. Hiển thị estimate trước:
═══ AD CLAIM COMPLIANCE — CONFIRM ═══
Domain(s): {list}
URL ước tính: {N} (từ sitemap/GSC)
Crawl scope: Title + Meta + H1 + H2/H3 + Body + Schema + Alt
Ngành: {industry} (YMYL multiplier: {×})
Evidence Registry: {có / không có — nếu không, mọi claim chạy verdict đầy đủ}
Cost ước tính: sf-enhanced crawl {N} URL (~{phút})
Chọn:
(A) Full crawl toàn site
(B) Sample — chỉ URL có GSC impressions (ưu tiên trang đang hiển thị SERP)
(C) Hủy
Mặc định gợi ý (B) cho portfolio lớn — sửa trang đang hiển thị SERP trước là ưu tiên thực tế.
OUTPUT
Phần 1 — Terminal dashboard (BẮT BUỘC, render đầu tiên — visualize:show_widget)
Cho CEO/Account nắm nhanh. ≥5 sections:
┌─ AD CLAIM COMPLIANCE ─────────────────────────────┐
│ Domain | Audit date | URLs scanned | Industry │
├───────────────────────────────────────────────────┤
│ TỔNG: {N} findings → HIGH {n} · MED {n} · LOW {n}│
│ VERDICT: VIOLATION {n} · NEEDS_PROOF {n} · │
│ PROOF_NOT_CITED {n} · REVIEW {n} · OK {n} │
├───────────────────────────────────────────────────┤
│ Top URL rủi ro (HIGH, có GSC impressions) │
│ Phân bố theo location (Title/Meta/H1/Body) │
│ Phân bố theo nhóm từ (A/B/C) │
│ QC Score: {N}/100 [verdict] │
└───────────────────────────────────────────────────┘
═══ Excel saved: {path} ═══
Phần 2 — Excel (sheets)
| Sheet | Nội dung |
|---|
| 1. Dashboard | Tổng hợp số liệu, charts (verdict pie, location bar, risk histogram), QC badge |
| 2. Findings | url · location · term · nhom · snippet · page_type · industry · risk_score · risk_tier · verdict · nguyên_tắc (OPT 2 luôn có) |
| 3. Action List | Group theo client → verdict → URL. Cột: action (reword/request-doc/add-citation/review) · priority (P1–P5) · GSC impressions |
| 4. Reword | (chỉ điền sau Pass 2) finding · variant_1/2/3 · principle · recommended · char_count · keyword_kept |
| 5. Needs Proof | Claim đáng xin tài liệu Điều 3.2 → checklist gửi client |
| 6. Evidence Registry | Mirror registry đã load + cờ expired/not-cited |
Sort Findings + Action theo GSC impressions desc (trang hiển thị SERP nhiều = ưu tiên).
Path: ~/compliance/{domain}-adclaim-{date}.xlsx
QC RUBRIC
BẮT BUỘC self-check trước khi output. PASS ≥80/100. FIX/FAIL → fix hoặc rebuild.
| Dim | Hạng mục | Điểm | Check |
|---|
| D1 | Detection coverage | 15 | Quét đủ Title/Meta/H1/H2-3/Body/Schema/Alt? Cả 3 nhóm + pattern X nhất + EN? |
| D2 | False-positive control | 15 | Đã lọc exception list nhất? Không flag thống nhất/đồng nhất/thứ nhất...? Spot-check 5 finding X nhất đúng là claim? |
| D3 | Risk score | 10 | Công thức location × page_type × industry áp đúng? Hard rule YMYL+Title/Meta = HIGH áp dụng? |
| D4 | Verdict đúng | 15 | 5 verdict gán đúng logic? NEEDS_PROOF vs VIOLATION phân biệt rõ? PROOF_NOT_CITED check Điều 3.4? |
| D5 | Evidence Registry | 10 | Có registry: match + check hiệu lực (3.3) + check citation (3.4)? Không registry: không auto-OK claim nào? |
| D6 | 2-stage tách bạch | 10 | Pass 1 KHÔNG auto-generate reword? OPT 1 chỉ chạy khi user chọn? Routing per-verdict đúng? |
| D7 | Reword chất lượng (nếu Pass 2) | 10 | Variant giữ keyword? Đúng char-limit? Áp P1-P4 đúng? YMYL ưu tiên provable? |
| D8 | Confirm + Dashboard | 10 | Standalone: confirm dialog trước crawl, không auto-run? Render terminal dashboard NGAY ĐẦU, ≥5 sections? |
| D9 | Output & Formatting | 5 | Excel đủ sheets? Sort theo GSC impressions? Save đúng path? Báo path? Font TNR? Gridlines ẩn? Border có? Text canh giữa? |
Verdict: 90-100 EXCELLENT · 80-89 PASS · 65-79 FIX · <65 FAIL
Auto-FAIL:
- Pass 1 tự ý generate reword toàn bộ (vi phạm 2-stage)
- Flag thống nhất/đồng nhất/thứ nhất là claim (false-positive cơ bản)
- Auto-OK claim không có trong registry
- Standalone skip confirm dialog (auto crawl trái rule)
- Không render terminal dashboard
Inline trong output: dòng QC Score: {N}/100 [verdict]. Nếu FIX/FAIL → note lý do → tự fix → rerun QC → output.
CROSS-SKILL
- qc-content: thêm gate compliance — finding VIOLATION ở title/meta/H1 chặn verdict PASS của qc-content.
- xay-dung-noi-dung / optimize-seo-page: check title/meta/H1 mới sinh trước khi xuất.
- data-cache: cache crawl result theo domain (TTL 48h) tránh re-crawl khi chạy lại trong ngày.
- client-report-monthly: đưa compliance status vào section content nếu client thuộc nhóm rủi ro.
EXCEL FORMATTING STANDARD
BẮT BUỘC áp cho MỌI sheet trong output Excel. Không có ngoại lệ.
4 quy tắc cứng
| # | Quy tắc | Chi tiết |
|---|
| F1 | Font Times New Roman | Toàn bộ cell (kể cả header) dùng name='Times New Roman'. Không dùng Calibri, Arial hay font mặc định. |
| F2 | Text canh giữa ô | Alignment(horizontal='center', vertical='center', wrap_text=True) cho tất cả cell. Ngoại lệ duy nhất: cell chứa URL dài → horizontal='left'. |
| F3 | Tạo bảng có border | Mọi vùng data dùng Border với Side(style='thin') cho 4 cạnh. Header row dùng Side(style='medium') bottom để phân tách. |
| F4 | Ẩn Gridlines | Mỗi sheet: ws.sheet_view.showGridLines = False. Áp TRƯỚC KHI save. |
Code snippet chuẩn (import 1 lần, dùng lại cho mọi skill)
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
TNR = 'Times New Roman'
def fmt_cell(ws, row, col, val,
bg=None, bold=False, sz=10,
fg='00000000', align_h='center'):
"""Cell chuẩn: TNR + canh giữa + border."""
c = ws.cell(row=row, column=col, value=val)
c.font = Font(name=TNR, bold=bold, size=sz, color=fg)
c.alignment = Alignment(
horizontal=align_h,
vertical='center',
wrap_text=True
)
if bg:
c.fill = PatternFill('solid', fgColor=bg)
thin = Side(style='thin', color='FFD1D5DB')
medium = Side(style='medium', color='FF9CA3AF')
c.border = Border(left=thin, right=thin, top=thin, bottom=thin)
return c
def fmt_header(ws, row, col, val, bg='FF1E293B', sz=10):
"""Header: TNR bold white + medium bottom border."""
c = fmt_cell(ws, row, col, val, bg=bg, bold=True, sz=sz, fg='FFFFFFFF')
thin = Side(style='thin', color='FFD1D5DB')
medium = Side(style='medium', color='FF9CA3AF')
c.border = Border(left=thin, right=thin, top=thin, bottom=medium)
return c
def hide_gridlines(ws):
"""Ẩn gridlines — gọi mỗi sheet trước khi save."""
ws.sheet_view.showGridLines = False
Checklist apply (trước wb.save)
for sheet in wb.worksheets:
hide_gridlines(sheet)
REFERENCES
references/lexicon.md — lexicon đầy đủ 3 nhóm + exception list nhất + EN superlative + stopword. ĐỌC khi chạy Layer 1.
references/reword-playbook.md — nguyên tắc P1–P5 + before/after patterns theo ngành. ĐỌC khi chạy Pass 2 (OPT 1) hoặc khi cần nêu nguyên tắc chi tiết ở Pass 1.
assets/evidence-registry-template.csv — template registry giao client điền.
MCP & COST
sf-enhanced (crawl, primary — requires local Screaming Frog + MCP server) · search-console (GSC impressions) · data-cache (optional, tránh re-crawl).
Community fallback: nếu không có sf-enhanced, skill dùng search-console (GSC impressions), vẫn không có search-console thì dùng web_fetch để crawl Title/Meta/H1 trực tiếp (chậm hơn, giới hạn ~50 URLs).
MỞ RỘNG (skeleton, chưa implement)
- Module 2 — Comparative claims: so sánh trực tiếp đối thủ (khoản 10 Điều 8 Luật QC cấm). Detect "hơn [tên đối thủ]", "tốt hơn X".
- Module 3 — Industry claims: y tế/TPCN ("chữa khỏi", "điều trị", "100% an toàn"), tài chính ("cam kết lợi nhuận", "lãi suất cao nhất"). Lexicon ngành riêng.