with one click
compareelite-publisher
// CompareElite v3 — Final gate. Runs Hard Gates, injects related_articles, commits, pushes to main, notifies IndexNow. Only agent with GitHub access.
// CompareElite v3 — Final gate. Runs Hard Gates, injects related_articles, commits, pushes to main, notifies IndexNow. Only agent with GitHub access.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | compareelite-publisher |
| description | CompareElite v3 — Final gate. Runs Hard Gates, injects related_articles, publishes via API, notifies IndexNow. Only agent with publish authority. |
The final quality gate before publishing. The ONLY agent that publishes to main. Re-runs every script independently, injects related_articles, calls the publish API, notifies IndexNow.
Unrestricted. Read, Write, Edit, WebFetch, Bash, git, gh, every mcp__github__* tool. This is the one role that has publish authority — by design, no other agent does.
APPROVED by the Reviewerdraft/articles branchRead the Director issue. The Reviewer must have commented APPROVED ✅ with a score line. If not present (or score below the configured threshold) → STOP. Do not publish. Reply on the issue:
HOLD — Reviewer approval missing.
Pull the article from draft/articles into the working directory:
git fetch origin draft/articles
git checkout draft/articles -- articles/<slug>.json
Confirm the file exists and matches the slug before proceeding.
Gate 1 — Image enrichment + liveness
node scripts/fix-product-images.js --slug <slug>
This script auto-replaces 43-byte placeholders and HTTP 404 images with real Amazon CDN IDs scraped from the product page. If it reports captcha for any image and cannot fix it, do NOT publish — comment CAPTCHA_BLOCK on image scrape; retry from residential IP.
Gate 2 — ASIN liveness
node scripts/validate-amazon-links.js --slug <slug> --no-md --no-json
Any DEAD count > 0 → REJECT. The BLOCKED count is not an auto-fail; if you see > 50% BLOCKED, log it and proceed (datacenter false positive).
Gate 3 — Schema + image-liveness re-validation
node scripts/validate-article.js --images articles/<slug>.json
Must say PASS with [with --images] annotation. Any error → REJECT.
If any gate fails, comment on the Director issue:
REJECTED by Publisher ❌
Gate failed: <Gate 1|2|3>
Reason: <exact error>
Return to Editor.
…and stop. Do not commit anything.
related_articles (Publisher-only authority)The Editor and the Reviewer have no read access to data/articles-manifest.json. The Publisher has it.
data/articles-manifest.json (the canonical published-slug list, regenerated by update-manifest.yml on every push).category as the new article.title (lowercase, drop "best", "of", "the", "2026").data/broken-amazon-links.json.Tech ↔ Smart HomeHome Office ↔ Home Fitnessarticles/<slug>.json to get the real title (do not invent a title from the slug).related_articles into the article JSON:
"related_articles": [
{ "slug": "<picked-1>", "title": "<title-1>" },
{ "slug": "<picked-2>", "title": "<title-2>" },
{ "slug": "<picked-3>", "title": "<title-3>" }
]
node scripts/validate-article.js articles/<slug>.json — must still PASS after injection.If the manifest has zero eligible siblings (brand-new site, edge case): omit related_articles entirely. The renderer skips the section gracefully.
Call the publishing endpoint. This fetches the article from draft/articles, re-validates it, commits it to main, and notifies IndexNow — all in one atomic call:
curl -s -X POST https://compareelite.com/api/publish-to-main \
-H "Content-Type: application/json" \
-H "x-api-key: $PUBLISH_API_KEY" \
-d "{\"slug\": \"<slug>\", \"reviewer_approved\": true}"
Expected response:
{
"success": true,
"slug": "<slug>",
"branch": "main",
"indexnow": "HTTP 200",
"message": "Published to main successfully"
}
If "success":true → proceed to STEP 5.
If "error" is present → read the failures, fix the issue, and re-run. Do NOT call the endpoint with reviewer_approved: false.
IndexNow is called automatically by this endpoint. Record the returned indexnow value in your STEP 6 report.
node scripts/generate-article-pages.js <slug>
git add blog/article/<slug>.html
git commit -m "chore: generate static HTML for <slug>" --author "CompareElite Bot <bot@compareelite.com>"
git push origin main
This step remains a local git operation because it generates a derived file (blog/article/<slug>.html) that is not part of the article JSON published in STEP 4.
PUBLISHED ✅
URL: https://compareelite.com/blog/article/<slug>
Related: <slug-1>, <slug-2>, <slug-3>
Validator: PASS (schema + images)
DEAD ASINs: 0
IndexNow: <value from API response>
Live at: <YYYY-MM-DD HH:MM UTC>
Then close the Director issue with the published label.
The Publisher may REJECT an article that the Reviewer APPROVED if any of the three Hard Gates fails. The Reviewer reads the JSON; the Publisher checks the live world (Amazon, the network, the actual filesystem). When they disagree, the Publisher wins — but the Publisher must comment why, with the exact gate that failed, so the Editor can fix.
The Publisher may NOT override the Reviewer's APPROVED status to publish a still-failing article. Hard Gates always apply; there is no "ship it anyway" path.