Blog Comment Moderator
Overview
Use this skill from the blog-backend repository root to moderate blog comments through make download-data, target/blog-cli, and the Makefile moderation targets.
Important data model:
- Local moderation review uses downloaded JSON snapshots. Prefer the private
.data/article-email-comments.json snapshot because it contains all comments; .data/article-comments.json is the public/frontend snapshot and should contain only approved comments.
- The SQLite database is the cloud/server runtime state, not the local source of truth.
- Do not trust local
.data/blog.db for current pending comments; it may be stale.
- State changes must run against the cloud DB, then local snapshots must be refreshed.
- Comment visibility and moderation are separate:
authorized=true,rejected=false is approved/public; authorized=false,rejected=false is pending review; authorized=false,rejected=true is rejected/kept unpublished.
- Only approved comments are exported to the frontend/public snapshot. Rejected comments remain in the private snapshot for audit/history.
Operating Rules
- Run commands from the repository root.
- Build the CLI first when
target/blog-cli is missing or stale:
make target/blog-cli
- Use
--format json when parsing output programmatically; use markdown/table only for user-facing summaries.
- Start by refreshing local snapshots:
make download-data
- If you have not refreshed snapshots in the current turn/session, explicitly tell the user the local comment source may be stale and should be updated with
make download-data before relying on review results.
- For local read-only review, use the snapshot-backed CLI commands. The comment CLI defaults to
--source snapshot; use --source db only when intentionally running against a known-good server DB context.
- Do not hand-write SQLite update statements for moderation. Use the Makefile targets
make comment-authorize ID=<id>, make comment-reject ID=<id>, or make comment-delete ID=<id> so the command runs against the cloud data dir.
- Do not send email automatically or open Gmail. Use the CLI-generated drafts and Gmail URLs as artifacts to show the user.
- When generating email drafts, always include the Gmail compose URL. If URLs are long, put clickable links in a markdown artifact and link that artifact in the final response; do not omit the compose links.
- Treat
delete as a moderation alias for reject: it marks rejected=true and authorized=false, not physical deletion.
- Treat
reject as "keep unpublished"; it does not physically delete comments.
- Ask before mutating comment state unless the user explicitly requested applying decisions. If the user explicitly says approve/authorize/reject/delete specific comment IDs, execute the matching Makefile targets directly and report the result.
Reporting Rules
- Default reports are moderation reports: list pending comments first, oldest to newest. If rejected comments are relevant, report them separately from pending.
- Do not automatically expand approved comments. If useful, mention only the approved count.
- Show approved comment details only when the user explicitly asks for all comments, approved comments, or a specific approved comment id.
- When multiple states are relevant, phrase the result as pending first, then rejected, then approved summary.
Workflow
- Refresh local snapshots:
make download-data
- List pending comments from the downloaded private snapshot:
target/blog-cli comment list --state pending --format json
or:
make comment-list
- Inspect each target comment with the review packet:
target/blog-cli comment review <id> --format markdown
Use JSON if the next step needs structured fields:
target/blog-cli comment review <id> --format json
or:
make comment-review ID=<id>
- Decide:
- Approve relevant, good-faith comments that are safe to publish.
- Reject/delete comments that are spam, abusive, malicious, doxxing, privacy-leaking, irrelevant, unreadable, or fake/test submissions. In this workflow, delete means reject/keep unpublished (
authorized=false,rejected=true), not physical removal.
- If the comment contains links, code, or unusual markup, inspect it carefully before recommending approval.
- If only
.data/article-comments.json is available, pending/rejected comments may be absent because the public snapshot is expected to contain only approved comments. Do not rely on it for moderation decisions unless .data/article-email-comments.json is unavailable and you explicitly state the limitation.
- If unsure, present the concern and keep the comment pending.
- Apply only after user confirmation or explicit instruction. Use the Makefile targets so mutation happens against the cloud DB and local snapshots are refreshed afterward:
make comment-authorize ID=<id>
make comment-reject ID=<id>
make comment-delete ID=<id>
The remote command exports article-comments.json and article-email-comments.json on the server by default, and the Makefile target then runs make download-data.
- Report the result:
- Comment id and final state.
- Any email drafts/Gmail URLs the user needs.
- Any comments left pending and why.
Command Reference
target/blog-cli comment list --state pending --format table
target/blog-cli comment list --state rejected --format table
target/blog-cli comment list --source snapshot --state pending --format table
target/blog-cli comment list --source db --state pending --format table
target/blog-cli comment show <id> --format markdown
target/blog-cli comment draft <id> --format markdown
target/blog-cli comment review <id> --format markdown
make comment-list
make comment-review ID=<id>
make comment-authorize ID=<id>
make comment-reject ID=<id>
make comment-delete ID=<id>
Useful global flags:
--data-dir <dir>: defaults to ./.data.
--db <path>: defaults to <data-dir>/blog.db.
--comments <path>: defaults to <data-dir>/article-comments.json.
--owner-email <addr>: defaults to Kamiya <camiyoru@gmail.com>.
1---2name: blog-comment-moderator3description: Review and moderate comments for the github.com/Myriad-Dreamin/blog-backend project by using the repository's Go blog-cli workflow. Use when Codex is asked to list pending blog comments, inspect a comment, decide whether a blog comment should be authorized, generate owner/author notification drafts, approve or reject comments, or replace the old Astro comment moderation frontend.4---56# Blog Comment Moderator78## Overview910Use this skill from the `blog-backend` repository root to moderate blog comments through `make download-data`, `target/blog-cli`, and the Makefile moderation targets.1112Important data model:1314- Local moderation review uses downloaded JSON snapshots. Prefer the private `.data/article-email-comments.json` snapshot because it contains all comments; `.data/article-comments.json` is the public/frontend snapshot and should contain only approved comments.15- The SQLite database is the cloud/server runtime state, not the local source of truth.16- Do not trust local `.data/blog.db` for current pending comments; it may be stale.17- State changes must run against the cloud DB, then local snapshots must be refreshed.18- Comment visibility and moderation are separate: `authorized=true,rejected=false` is approved/public; `authorized=false,rejected=false` is pending review; `authorized=false,rejected=true` is rejected/kept unpublished.19- Only approved comments are exported to the frontend/public snapshot. Rejected comments remain in the private snapshot for audit/history.2021## Operating Rules2223- Run commands from the repository root.24- Build the CLI first when `target/blog-cli` is missing or stale:2526```bash27make target/blog-cli28```2930- Use `--format json` when parsing output programmatically; use markdown/table only for user-facing summaries.31- Start by refreshing local snapshots:3233```bash34make download-data35```3637- If you have not refreshed snapshots in the current turn/session, explicitly tell the user the local comment source may be stale and should be updated with `make download-data` before relying on review results.38- For local read-only review, use the snapshot-backed CLI commands. The comment CLI defaults to `--source snapshot`; use `--source db` only when intentionally running against a known-good server DB context.39- Do not hand-write SQLite update statements for moderation. Use the Makefile targets `make comment-authorize ID=<id>`, `make comment-reject ID=<id>`, or `make comment-delete ID=<id>` so the command runs against the cloud data dir.40- Do not send email automatically or open Gmail. Use the CLI-generated drafts and Gmail URLs as artifacts to show the user.41- When generating email drafts, always include the Gmail compose URL. If URLs are long, put clickable links in a markdown artifact and link that artifact in the final response; do not omit the compose links.42- Treat `delete` as a moderation alias for `reject`: it marks `rejected=true` and `authorized=false`, not physical deletion.43- Treat `reject` as "keep unpublished"; it does not physically delete comments.44- Ask before mutating comment state unless the user explicitly requested applying decisions. If the user explicitly says approve/authorize/reject/delete specific comment IDs, execute the matching Makefile targets directly and report the result.4546## Reporting Rules4748- Default reports are moderation reports: list pending comments first, oldest to newest. If rejected comments are relevant, report them separately from pending.49- Do not automatically expand approved comments. If useful, mention only the approved count.50- Show approved comment details only when the user explicitly asks for all comments, approved comments, or a specific approved comment id.51- When multiple states are relevant, phrase the result as pending first, then rejected, then approved summary.5253## Workflow54551. Refresh local snapshots:5657```bash58make download-data59```60612. List pending comments from the downloaded private snapshot:6263```bash64target/blog-cli comment list --state pending --format json65```6667or:6869```bash70make comment-list71```72733. Inspect each target comment with the review packet:7475```bash76target/blog-cli comment review <id> --format markdown77```7879Use JSON if the next step needs structured fields:8081```bash82target/blog-cli comment review <id> --format json83```8485or:8687```bash88make comment-review ID=<id>89```90914. Decide:9293- Approve relevant, good-faith comments that are safe to publish.94- Reject/delete comments that are spam, abusive, malicious, doxxing, privacy-leaking, irrelevant, unreadable, or fake/test submissions. In this workflow, delete means reject/keep unpublished (`authorized=false,rejected=true`), not physical removal.95- If the comment contains links, code, or unusual markup, inspect it carefully before recommending approval.96- If only `.data/article-comments.json` is available, pending/rejected comments may be absent because the public snapshot is expected to contain only approved comments. Do not rely on it for moderation decisions unless `.data/article-email-comments.json` is unavailable and you explicitly state the limitation.97- If unsure, present the concern and keep the comment pending.98995. Apply only after user confirmation or explicit instruction. Use the Makefile targets so mutation happens against the cloud DB and local snapshots are refreshed afterward:100101```bash102make comment-authorize ID=<id>103make comment-reject ID=<id>104make comment-delete ID=<id>105```106107The remote command exports `article-comments.json` and `article-email-comments.json` on the server by default, and the Makefile target then runs `make download-data`.1081096. Report the result:110111- Comment id and final state.112- Any email drafts/Gmail URLs the user needs.113- Any comments left pending and why.114115## Command Reference116117```bash118target/blog-cli comment list --state pending --format table119target/blog-cli comment list --state rejected --format table120target/blog-cli comment list --source snapshot --state pending --format table121target/blog-cli comment list --source db --state pending --format table122target/blog-cli comment show <id> --format markdown123target/blog-cli comment draft <id> --format markdown124target/blog-cli comment review <id> --format markdown125make comment-list126make comment-review ID=<id>127make comment-authorize ID=<id>128make comment-reject ID=<id>129make comment-delete ID=<id>130```131132Useful global flags:133134- `--data-dir <dir>`: defaults to `./.data`.135- `--db <path>`: defaults to `<data-dir>/blog.db`.136- `--comments <path>`: defaults to `<data-dir>/article-comments.json`.137- `--owner-email <addr>`: defaults to `Kamiya <camiyoru@gmail.com>`.