[blogger-playbook] rewrite blogger around the SEO PLAYBOOK (SERP-steal, intent, bilingual, GEO) - #94
Conversation
…nt, bilingual, GEO) Distilled from field playbooks + our own 16-post / 0-click evidence. The blogger stopped inventing thesis essays; it now answers the live SERP in the language the demand is in. AGENT.md + ROUTINE.md: - read ../claude-knowcap/.../seo/PLAYBOOK.md first; playbook wins on conflict - classify INTENT (nav→skip, commercial→money-page, informational→post) - pick LANGUAGE from demand (native AR post for AR demand; hreflang pair) - STEAL THE SERP (inherit the seo routine's content-brief, else pull live top-3) is now a mandatory gate — no draft from imagination - hand the published URL to the seo routine for request-indexing (Law 6) write-blog-draft SKILL.md: - new `money-page` mode (the only format ranking #1 for us) - entry gates: ICP + serp-steal + intent - serp_steal input (brief or live top-3) drives structure + word-count target - bilingual frontmatter (lang/dir/hreflang), native-Arabic voice note - thesis prompt is now SERP-grounded; gates check SERP coverage + citable passages Pairs with claude-knowcap PR #27 (the shared PLAYBOOK + seo routine). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TwM4VYoHip5iUguBWCqStH
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe blogger agent, routine, and skill spec are rewritten to enforce a SERP-steal gate (refuse without a brief or live SERP), classify keyword intent (skip navigational/tool, route commercial to a new ChangesSERP-Grounded Bilingual Blogger Workflow
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
routines/_skills/write-blog-draft/SKILL.md (1)
94-116: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winFrontmatter
hreflang_pairnull handling emits literal string "null".Line 111 uses
hreflang_pair: "{hreflang_pair}"with string interpolation. If the upstream value is YAMLnull, the template emitshreflang_pair: "null"(a string) rather thanhreflang_pair: nullorhreflang_pair:(YAML null). The publish script atapp/lib/blog.tsmay treat"null"string as truthy. Verify this is intended, or use a conditional:-hreflang_pair: "{hreflang_pair}" # the other-language equivalent URL/slug, or null +hreflang_pair: {hreflang_pair} # the other-language equivalent URL/slug, or nullOr if the template engine supports conditionals:
+{%- if hreflang_pair %} +hreflang_pair: "{hreflang_pair}" +{%- else %} +hreflang_pair: null +{%- endif %}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/_skills/write-blog-draft/SKILL.md` around lines 94 - 116, The frontmatter template in SKILL.md is emitting a literal "null" string for hreflang_pair when the value is absent, which can be misread as a real value. Update the frontmatter generation around hreflang_pair to conditionally render YAML null/empty output instead of always interpolating the quoted placeholder. Use the existing template variables and check the publish flow in app/lib/blog.ts to ensure it receives a true null value, not the string "null".
🧹 Nitpick comments (7)
routines/blogger/AGENT.md (3)
76-78: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueHard rules Laws 1, 2, 4 are correct, but Laws 3, 5, 6, 7 are missing from the list.
The body text references Law 3 (money-page, line 57), Law 5 (GEO citation, line 145 in ROUTINE.md), and Law 6 (SEO handoff, line 67). Law 7 is mentioned in the playbook-first directive but never defined. For scannability and to prevent playbook drift, either:
- Add all 7 laws to the hard rules list, or
- Remove the "7 laws" claim and reference the playbook as the dynamic source of truth.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/blogger/AGENT.md` around lines 76 - 78, The hard rules list in AGENT.md is incomplete and currently claims a 7-law framework while only listing Laws 1, 2, and 4. Update the hard rules section to either include all seven laws consistently, referencing the existing playbook terms like Law 3, Law 5, Law 6, and Law 7, or remove the “7 laws” framing and point readers to the playbook as the source of truth. Keep the wording aligned with the existing law labels so the list is scannable and non-drifting.
7-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valuePlaybook-first directive is well-structured, but Law 7 is missing from AGENT.md.
The directive correctly establishes playbook supremacy and references the shared 7 laws. However, AGENT.md only explicitly references Laws 1–6 in its body (Law 6 at line 67, Law 5 in constraints). If the playbook defines a 7th law, it should be surfaced here or the "7 laws" claim should be qualified to avoid confusion with the downstream skill contract.
Not blocking — the playbook is the source of truth — but verify Law 7's existence and whether it affects the blogger.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/blogger/AGENT.md` around lines 7 - 13, AGENT.md claims the playbook contains 7 laws, but the body only surfaces Laws 1–6, so either add a clear reference to Law 7 or qualify the “7 laws” wording to match what the blogger contract actually enforces. Update the playbook-first directive near the existing “READ THE PLAYBOOK FIRST” block and keep the language aligned with the downstream seo routine and blogger guidance so there is no mismatch between the documented laws and the contract text.Source: Learnings
50-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMode selection logic is sound, but Law 3 is missing from the hard rules list.
The informational spines and commercial→money-page routing match the downstream SKILL.md contract. However:
Law 3 is not in the hard rules list (lines 76-78): Lines 57-58 reference "Law 3" for money-page mode, but only Laws 1, 2, and 4 appear in the hard rules section. Add Law 3 to the hard rules for consistency, or renumber if it's intentionally implicit.
"Zipper" is undefined jargon: The term "zipper landing page" (line 58) appears without explanation. A brief parenthetical or link to the playbook/SKILL.md definition would help future readers.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/blogger/AGENT.md` around lines 50 - 58, Add Law 3 to the hard rules section so the numbered laws match the mode-selection text and the SKILL.md contract; update the hard-rules list in AGENT.md to include the commercial “money-page mode” rule referenced by the existing Mode guidance. Also clarify the “zipper” terminology by either adding a short definition or linking it to the relevant playbook/SKILL.md reference near the Mode bullet so readers can identify the intended landing-page format.routines/blogger/ROUTINE.md (2)
35-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd language specifier to fenced code block; verify brief path slug convention.
The mode selection algorithm correctly orders intent → language → SERP-steal → spine, matching the AGENT.md and SKILL.md contracts. Two issues:
markdownlint MD040 (line 38): The fenced code block lacks a language specifier. Add
textormarkdownto suppress the warning and improve rendering.Brief path slug convention (line 48): Same concern as AGENT.md — if Arabic-demand keywords get
-arslug suffix, the brief lookup<keyword-slug>may fail if briefs use base slugs. Align the brief naming convention with the slugging rule.> Governed by `../claude-knowcap/marketing/digital-employees/seo/PLAYBOOK.md`. Intent + language + the > SERP-steal come BEFORE the content-spine choice. > -``` +```text 1. Pick persona via round-robin from state.json (if absent → default index 0 = odoo-partners, then create it — see "Persona rotation state")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/blogger/ROUTINE.md` around lines 35 - 58, The ROUTINE.md fenced block needs a language tag to satisfy markdownlint MD040, so update the code fence around the mode-selection algorithm with a specifier like text or markdown. Also verify the brief lookup in the STEAL THE SERP step uses the same slug convention as the language rule in the nearby language-specifier logic; if Arabic adds a -ar suffix, make sure the content-briefs/<keyword-slug>.md path resolves against the actual brief naming scheme used by the SEO playbook.
141-146: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConstraints are consistent, but AGENT.md omits the fallback word-count range.
ROUTINE.md line 145 specifies "Absent a SERP signal, default 1,300–1,600 body words," but AGENT.md line 60 only says "the SERP/brief target (beat top-10), not a fixed range." Add the fallback range to AGENT.md for parity, or remove it from ROUTINE.md if the playbook governs this.
The 134–167-word passage range and exactly-5 FAQ rule should be verified against the playbook if they are hard requirements.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/blogger/ROUTINE.md` around lines 141 - 146, AGENT.md and ROUTINE.md are out of sync on the fallback length rule, so update the playbook entry that defines article sizing to explicitly include the “absent a SERP signal, default 1,300–1,600 body words” fallback, or remove that fallback from the ROUTINE.md guidance if AGENT.md is the source of truth. Use the wording around the word-count rule in the blogger routine section to locate the mismatch, and keep the rest of the constraints aligned across both docs.routines/_skills/write-blog-draft/SKILL.md (2)
197-205: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winMissing validation gate for JSON-LD schema in
money-pagemode.The prompt requires "JSON-LD schema appropriate to the page type" (line 204), but the validation gates have no check for JSON-LD presence or validity. Since
app/lib/blog.tsgenerates FAQPage JSON-LD from FAQ sections, the money-page may need additional schema validation (e.g., checking that the draft contains a<script type="application/ld+json">block or that structured data is present). Consider adding a mode-specific gate, or clarifying that JSON-LD is generated downstream from the markdown.8. FAQ count → exactly 5 H3 questions in the FAQ section. +9. Money-page schema → if mode == money-page, a JSON-LD block is present and matches the page type (FAQPage, Product, or Comparison).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/_skills/write-blog-draft/SKILL.md` around lines 197 - 205, The money-page validation in `write-blog-draft` is missing a gate for JSON-LD schema presence/validity, even though the structure requires page-appropriate schema. Update the `money-page` checks to verify structured data is present or explicitly generated downstream, and align this with the FAQPage schema output from `app/lib/blog.ts`. If JSON-LD is expected in the draft, add a mode-specific validation for a `<script type="application/ld+json">` block; otherwise, clarify in the prompt/validator that schema is assembled later from the markdown.
87-90: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDefensive navigational gate is sound but comment is slightly misleading.
The comment on line 28 says "navigational was skipped upstream (Law 2)", yet Gate 3 still refuses it. This is defensible defense-in-depth, but the comment could clarify why the gate exists despite upstream filtering (e.g., "defensive gate in case upstream routing changes").
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@routines/_skills/write-blog-draft/SKILL.md` around lines 87 - 90, Clarify the Intent gate comment in write-blog-draft/SKILL.md so it reflects that the navigational check is a defensive backstop, not redundant with upstream filtering. Update the wording around the gate associated with the intent check (the section describing “Intent gate (Law 2)”) to explicitly say it refuses navigational/tool keywords as a fallback in case upstream routing changes, while keeping the existing REFUSED behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@routines/_skills/write-blog-draft/SKILL.md`:
- Around line 11-21: The modes table in SKILL.md includes a `comparison` mode,
but there is no corresponding prompt section below, so the routine can select an
undefined path. Update the `write-blog-draft` skill by either adding a dedicated
`comparison` prompt section that matches the existing mode naming used in the
table, or remove `comparison` from the Modes table if it is not supported yet.
Keep the mode list and the prompt sections in sync so runtime selection is
unambiguous.
In `@routines/blogger/AGENT.md`:
- Around line 59-67: The handoff at the end of the blogger workflow references a
nonexistent SEO task, so update the guidance in AGENT.md to point to the real
indexing step used in this repo or remove the handoff entirely. Locate the final
“After the PR opens” instruction in the blogger routine and replace the `seo`
TASK 9 / `request-indexing` reference with the correct documented workflow so
the `burn-state.json` and blog publishing steps remain accurate.
---
Outside diff comments:
In `@routines/_skills/write-blog-draft/SKILL.md`:
- Around line 94-116: The frontmatter template in SKILL.md is emitting a literal
"null" string for hreflang_pair when the value is absent, which can be misread
as a real value. Update the frontmatter generation around hreflang_pair to
conditionally render YAML null/empty output instead of always interpolating the
quoted placeholder. Use the existing template variables and check the publish
flow in app/lib/blog.ts to ensure it receives a true null value, not the string
"null".
---
Nitpick comments:
In `@routines/_skills/write-blog-draft/SKILL.md`:
- Around line 197-205: The money-page validation in `write-blog-draft` is
missing a gate for JSON-LD schema presence/validity, even though the structure
requires page-appropriate schema. Update the `money-page` checks to verify
structured data is present or explicitly generated downstream, and align this
with the FAQPage schema output from `app/lib/blog.ts`. If JSON-LD is expected in
the draft, add a mode-specific validation for a `<script
type="application/ld+json">` block; otherwise, clarify in the prompt/validator
that schema is assembled later from the markdown.
- Around line 87-90: Clarify the Intent gate comment in
write-blog-draft/SKILL.md so it reflects that the navigational check is a
defensive backstop, not redundant with upstream filtering. Update the wording
around the gate associated with the intent check (the section describing “Intent
gate (Law 2)”) to explicitly say it refuses navigational/tool keywords as a
fallback in case upstream routing changes, while keeping the existing REFUSED
behavior unchanged.
In `@routines/blogger/AGENT.md`:
- Around line 76-78: The hard rules list in AGENT.md is incomplete and currently
claims a 7-law framework while only listing Laws 1, 2, and 4. Update the hard
rules section to either include all seven laws consistently, referencing the
existing playbook terms like Law 3, Law 5, Law 6, and Law 7, or remove the “7
laws” framing and point readers to the playbook as the source of truth. Keep the
wording aligned with the existing law labels so the list is scannable and
non-drifting.
- Around line 7-13: AGENT.md claims the playbook contains 7 laws, but the body
only surfaces Laws 1–6, so either add a clear reference to Law 7 or qualify the
“7 laws” wording to match what the blogger contract actually enforces. Update
the playbook-first directive near the existing “READ THE PLAYBOOK FIRST” block
and keep the language aligned with the downstream seo routine and blogger
guidance so there is no mismatch between the documented laws and the contract
text.
- Around line 50-58: Add Law 3 to the hard rules section so the numbered laws
match the mode-selection text and the SKILL.md contract; update the hard-rules
list in AGENT.md to include the commercial “money-page mode” rule referenced by
the existing Mode guidance. Also clarify the “zipper” terminology by either
adding a short definition or linking it to the relevant playbook/SKILL.md
reference near the Mode bullet so readers can identify the intended landing-page
format.
In `@routines/blogger/ROUTINE.md`:
- Around line 35-58: The ROUTINE.md fenced block needs a language tag to satisfy
markdownlint MD040, so update the code fence around the mode-selection algorithm
with a specifier like text or markdown. Also verify the brief lookup in the
STEAL THE SERP step uses the same slug convention as the language rule in the
nearby language-specifier logic; if Arabic adds a -ar suffix, make sure the
content-briefs/<keyword-slug>.md path resolves against the actual brief naming
scheme used by the SEO playbook.
- Around line 141-146: AGENT.md and ROUTINE.md are out of sync on the fallback
length rule, so update the playbook entry that defines article sizing to
explicitly include the “absent a SERP signal, default 1,300–1,600 body words”
fallback, or remove that fallback from the ROUTINE.md guidance if AGENT.md is
the source of truth. Use the wording around the word-count rule in the blogger
routine section to locate the mismatch, and keep the rest of the constraints
aligned across both docs.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: eaa2767e-210f-40a1-b11d-35e537dee746
📒 Files selected for processing (3)
routines/_skills/write-blog-draft/SKILL.mdroutines/blogger/AGENT.mdroutines/blogger/ROUTINE.md
| ## Modes | ||
|
|
||
| Routine picks mode at runtime: first by INTENT (Law 2), then — for informational intent — by what spine is available. | ||
|
|
||
| | Mode | Spine of the post | When the routine uses it | | ||
| |---|---|---| | ||
| | **`thesis`** | Persona + audit + vision + positioning | Default. General positioning posts. NO Knowcap source needed. | | ||
| | **`case-study`** | A specific Knowcap recording + its confirmed memories + persona | When the routine finds at least 1 source in Demo org for the target persona with ≥3 confirmed memories. | | ||
| | **`comparison`** | Competitor research + persona + audit | When `../claude-knowcap/company/docs/research/competitors-*.md` is fresher than 30 days AND not already covered in last 5 shipped blogs. | | ||
| | **`money-page`** | A `/compare/*` or use-case "zipper" landing page | **Commercial** intent (best/software/tool/vs/for-persona/pricing). The only format ranking #1 for us (Law 3). NOT a blog post. | | ||
| | **`thesis`** | SERP-stolen answer + persona + vision + positioning | Default for informational intent. Answers the query the way the winning results do, beats their depth. NO Knowcap source needed. | | ||
| | **`case-study`** | A specific Knowcap recording + its confirmed memories + persona | When the routine finds ≥1 Demo-org source for the persona with ≥3 confirmed memories. | | ||
| | **`comparison`** | Competitor research + persona + audit | When `../claude-knowcap/company/docs/research/competitors-*.md` is < 30 days AND not covered in last 5 shipped. | | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Missing prompt for comparison mode.
The modes table lists four modes (money-page, thesis, case-study, comparison), but only thesis and money-page have dedicated prompt sections below. Either add a comparison mode prompt or remove it from the table to avoid runtime ambiguity when the routine selects it.
♻️ Suggested fixes
Option A — Add a comparison prompt (preferred if the mode is real):
## Mode `comparison` — the prompt
+
+```
+[comparison prompt here]
+```Option B — Remove from table if not yet implemented:
-| **`comparison`** | Competitor research + persona + audit | When `../claude-knowcap/company/docs/research/competitors-*.md` is < 30 days AND not covered in last 5 shipped. |🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@routines/_skills/write-blog-draft/SKILL.md` around lines 11 - 21, The modes
table in SKILL.md includes a `comparison` mode, but there is no corresponding
prompt section below, so the routine can select an undefined path. Update the
`write-blog-draft` skill by either adding a dedicated `comparison` prompt
section that matches the existing mode naming used in the table, or remove
`comparison` from the Modes table if it is not supported yet. Keep the mode list
and the prompt sections in sync so runtime selection is unambiguous.
| 7. **Write** via write-blog-draft SKILL → run ALL gates (banned words; word count = the SERP/brief target | ||
| (beat top-10), not a fixed range; keyword in title+H2+≥3; 134–167w citable passages; schema + exactly | ||
| 5 FAQ; correct `lang`/`dir` + hreflang pair; slug unique; frontmatter). Fail → regenerate/skip, never | ||
| ship thin. | ||
| 8. **Output** — draft → `docs/content-pipeline/drafts/<slug>.md`, open `[blog-draft]` PR to main. | ||
| Always report live URL: `https://knowcap.ai/blog/<slug>` — post goes live automatically on PR merge | ||
| via `.github/workflows/publish-blog-draft.yml` + `scripts/publish-draft.mjs` (no manual move needed). | ||
| Update `burn-state.json` (total_posts++, posts_this_week++). | ||
| Update `burn-state.json` (total_posts++, posts_this_week++). After the PR opens, hand the URL to the | ||
| `seo` routine's TASK 9 (request-indexing) so it gets indexed in ~1 day, not weeks (Law 6). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify SEO routine TASK 9 and citable passage source
# 1. Find seo routine TASK 9
rg -n 'TASK 9|request-indexing|request indexing' ../claude-knowcap/marketing/digital-employees/seo/ || echo "Not found in expected path"
# 2. Search for 134 or 167 in playbook or specs
rg -n '134|167' ../claude-knowcap/marketing/digital-employees/seo/PLAYBOOK.md 2>/dev/null || echo "Not in playbook"
rg -n '134|167' routines/_skills/write-blog-draft/SKILL.md 2>/dev/null || echo "Not in SKILL.md"
# 3. Check for burn-state.json update logic in scripts
rg -n 'burn-state' routines/blogger/scripts/ || echo "No script references found"Repository: Knowcap-V2/knowcap-website
Length of output: 1855
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the relevant files and search for the SEO handoff and URL rules.
git ls-files | rg '(^|/)(AGENT\.md|PLAYBOOK\.md|SKILL\.md|burn-state\.json|publish-blog-draft\.yml|publish-draft\.mjs|seo|blogger)'
printf '\n-- TASK 9 / request-indexing matches --\n'
rg -n 'TASK 9|request-indexing|request indexing|seo routine' routines .github scripts docs || true
printf '\n-- live URL / blog slug matches --\n'
rg -n 'https://knowcap\.ai/blog/|/blog/<slug>|hreflang|lang/dir|burn-state\.json|total_posts\+\+|posts_this_week\+\+' routines .github scripts docs || trueRepository: Knowcap-V2/knowcap-website
Length of output: 4482
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n-- audit-seo skill --\n'
ast-grep outline routines/_skills/audit-seo/SKILL.md --view expanded || true
printf '\n-- request-indexing matches in repo --\n'
rg -n 'request-indexing|request indexing|indexing|TASK 9' routines/_skills routines/blogger .github scripts docs || true
printf '\n-- blogger routine/AGENT relevant lines --\n'
sed -n '56,70p' routines/blogger/AGENT.md
printf '\n-- audit-seo file excerpt --\n'
sed -n '1,220p' routines/_skills/audit-seo/SKILL.mdRepository: Knowcap-V2/knowcap-website
Length of output: 3200
Remove the nonexistent SEO handoff
routines/blogger/AGENT.md:66-67 points to seo TASK 9 (request-indexing), but no such task exists in the repo. Point this to the real indexing step or drop the handoff.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~65-~65: The official name of this software platform is spelled with a capital “H”.
Context: ...s live automatically on PR merge via .github/workflows/publish-blog-draft.yml + `sc...
(GITHUB)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@routines/blogger/AGENT.md` around lines 59 - 67, The handoff at the end of
the blogger workflow references a nonexistent SEO task, so update the guidance
in AGENT.md to point to the real indexing step used in this repo or remove the
handoff entirely. Locate the final “After the PR opens” instruction in the
blogger routine and replace the `seo` TASK 9 / `request-indexing` reference with
the correct documented workflow so the `burn-state.json` and blog publishing
steps remain accurate.
Why
16 blog posts, 0 non-brand organic clicks in 28 days. The blogger invented thesis essays instead of answering the live SERP, and published English-only while the real demand is Arabic (محضر اجتماع 1300, تدقيق 480 — LOW comp, on-product). This rewires the engine to win clicks.
What changed
routines/blogger/AGENT.md+ROUTINE.mdPLAYBOOK.mdfirst (claude-knowcap PR [add-routines] add routines/ skeleton — scheduled work on this repo #27); playbook wins on conflict.lang: ar,dir: rtl,-arslug), hreflang pair.routines/_skills/write-blog-draft/SKILL.mdmoney-pagemode (the only format ranking 🔐 Add branch protection: Only Abdelaziz can push to master #1 for us).serp_stealinput (brief or live top-3) drives structure + the word-count target (beat the top-10).lang/dir/hreflang_pair) + native-Arabic voice rule.Pairs with
claude-knowcapPR [add-routines] add routines/ skeleton — scheduled work on this repo #27 — the shared PLAYBOOK + seo routine wiring.Verify on first run (flagged, not blocking)
scripts/publish-draft.mjscarrieslang/dir/hreflang_pairand the live/blogroute renders RTL (one AR post already shipped, so RTL path exists).serp_stealhandoff reads the brief slug the seo routine writes.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes