{"id":"geo-review-html","name":"geo-review-html","summary":"GEOコンテンツブリーフ(04-content-brief)や公開準備済みドラフト(05-production)向けに、インタラクティブで自己完結型のHTMLコンパニオンをレンダリングしてください。","body":"# geo-review-html — interactive client-review HTML\n\nThe Markdown briefs/drafts are right for the GEO operator; they are awkward\nfor the client side. This skill renders a **companion HTML** alongside the\nMarkdown so non-technical reviewers can work in the browser. Battle-tested\nin the SEA-CICSIC 9-draft batch (see issue #1).\n\n**Division of labour (do not blur this):**\n- **Interaction logic is fixed** — `templates/review.html` owns localStorage\n  auto-save, JSON export, the progress counter, comment toggles, and the\n  approve/return state machine. It is correct as written; do not regenerate\n  it per run.\n- **Visual layer is the template's CSS** — that is where the vendored\n  `frontend-design` skill applies. When a client wants a branded or more\n  distinctive look, restyle the `<style>` block of `templates/review.html`\n  using `frontend-design` principles. `--accent` is already overridable per\n  client via `brand_context` (see below); deeper restyling edits the CSS.\n- `render_html.py` only parses Markdown + meta into a payload and injects it.\n\n## When to use\n\n- `04-content-brief` Step 7 — emit `briefs/<id>.html` (fill-form) next to the `.md`.\n- `04-content-brief` Step 9 — ingest the reviewer's returned `*.feedback.json`.\n- `05-production` Step 7 — emit `drafts/<id>.html` (review form) next to the `.md`.\n- Whenever a client folder's `briefs/index.html` entry page needs (re)building.\n\n## Usage\n\n```bash\nSK=plugins/recomby-geo/skills/geo-review-html\n\n# Flavor A — fill-form HTML for a brief with REQUIRED-FILL slots\npython3 $SK/scripts/render_html.py --mode brief \\\n  --md   clients/<slug>/briefs/<id>.md \\\n  --meta clients/<slug>/briefs/<id>.meta.json \\\n  --brand clients/<slug>/brand_context.json \\\n  --out  clients/<slug>/briefs/<id>.html\n\n# Flavor B — review HTML for a publish-ready draft (section comments + approve)\npython3 $SK/scripts/render_html.py --mode draft \\\n  --md   clients/<slug>/drafts/<id>.md \\\n  --meta clients/<slug>/drafts/<id>.meta.json \\\n  --brand clients/<slug>/brand_context.json \\\n  --out  clients/<slug>/drafts/<id>.html\n\n# Entry page — one card per brief/draft, live progress, status tags\npython3 $SK/scripts/render_html.py --mode index \\\n  --client-dir clients/<slug> \\\n  --brand clients/<slug>/brand_context.json \\\n  --out  clients/<slug>/briefs/index.html\n```\n\nPure standard library — no install step. Output is a single self-contained\n`.html` (CSS + JS inlined) safe to email to a client; they double-click it.\n\n## How it maps the inputs\n\n- **brief mode** splits the brief Markdown on `REQUIRED-FILL · <id> · <type>`\n  blockquote blocks. Each becomes a yellow textarea with a `<details>`\n  dropdown (what / why / bad example / good example). Everything else becomes\n  a green \"already-filled\" prose block with its own 💬 comment toggle. The\n  authoritative slot list is `meta.json`'s `slots[]`.\n- **draft mode** splits on `##` headings so every section gets a comment\n  toggle; the prose is rendered read-only with an `✓ Approve as-is` action.\n- **index mode** scans `briefs/` and `drafts/` for `*.meta.json`, reading\n  `format`, `status`, `word_count`, and slot fill counts. Live per-brief\n  progress is read from each brief's `localStorage` when the page is opened.\n- `--brand` is optional. `brand_name` sets the client label; `brand.primary_color`\n  (or `brand_color`) overrides the `--accent` CSS variable for light branding.\n\n## Returned feedback contract\n\nEach HTML exports a JSON file matching `schemas/review_feedback.schema.json`:\n\n```json\n{\n  \"brief_id\": \"free-cash-prize\",\n  \"filled_at\": \"2026-06-07T14:30:00Z\",\n  \"filled_by\": \"Jane Doe\",\n  \"answers\": { \"data-1\": \"...\", \"quote-1\": \"...\" },\n  \"comments\": { \"overall\": \"...\", \"filled-headline-finding\": \"...\" },\n  \"status\": \"reviewed-with-comments\"\n}\n```\n\n`status` ∈ `reviewed-with-comments` | `approved-as-is` | `partial-fill`.\nThe GEO operator feeds `answers` into the matching slots during\n`04-content-brief` Step 9 (NEVER auto-filled by AI — the slots are the moat).\n\n## Hard rules\n\n1. **Never auto-fill `answers`** — the JSON carries the human's real input;\n   that is the whole point. AI assembles, humans supply.\n2. **Keep the interaction JS fixed** — restyle CSS freely (frontend-design),\n   but don't rewrite the localStorage/export/state-machine logic per run.\n3. **Output stays self-contained** — one file, no external CSS/JS, so a\n   non-technical reviewer can open it from an email attachment.","author":"@ViryaZheng","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/ViryaZheng/recomby-geo/tree/main/plugins/recomby-geo/skills/geo-review-html","license":"MIT","category":"review","lang":"en","tokens":1169,"stars":0,"calls30d":1,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"scripts/render_html.py","size":12289,"sha256":"854ad90424242b4ea35f7a1163e2f11afdb686b7a2c50a400caf7d8ce4a6b4e3"},{"path":"templates/review.html","size":17678,"sha256":"f91640df0ada409f7bed8c338f1116afe9de171049baf0d2d545d13e5fd5c189"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":[]}}