The Blog Generator That Published Its Own Editing Notes
I broke the blog pipeline twice in 72 hours. Both times, the symptom was identical: blog posts publishing their own editing instructions instead of content.
What Broke
Instead of a blog post, this appeared:
Here's what I polished and why:
1. Opening â Tightened 'The task was straightforward' to 'The task:'
2. Technical explanation â Added concrete example of the race condition
3. Conclusion â Removed redundant summary paragraph
Three consecutive days (March 3, 4, 5) published variations of this. The files also had mismatched dates and generic fallback titles instead of the real titles the pipeline had chosen.
How the Pipeline Works
The blog generator runs four passes through the Claude CLI:
- Draft â Generate initial post from transcripts
- Review â Critique the draft and identify improvements
- Revise â Implement the improvements
- Polish â Final readability pass before publication
Each pass feeds into the next. The polish prompt explicitly says: âOutput ONLY the blog post markdown, starting with # Title. Do NOT include any preamble, commentary, code fences, or explanatory notes.â
The Bug
The leaked reasoning looked like a permissions errorâClaude asking to save files and getting blocked. But the pipeline ran unattended via launchd. If it couldnât write, it would fail completely, not swap content.
The real issue: the polish pass was leaking its internal reasoning into the output. The pipeline captured whatever Claude returned and saved it as the blog post. So the published files contained editorial commentary, not content.
The Fix That Didnât Fix It
I added regex patterns to catch meta-commentary and reject it:
def _clean_claude_output(text):
# Strip markdown code fences if present
if text.startswith('```'):
lines = text.split('\n')
text = '\n'.join(lines[1:-1])
# Detect meta-commentary patterns
meta_patterns = [
r'^(Here\'s|I need|Would you like|Could you)',
r'^Changes made:',
r'write permission'
]
if any(re.match(p, text, re.IGNORECASE) for p in meta_patterns):
return None # Signal failure, fall back to previous pass
return text.strip()
This caught the broken output and rejected it. The pipeline fell back to the previous pass instead of publishing meta-commentary.
I tested the fix on the same broken posts, saw that it worked, and immediately hit the same failure mode again the next day.
The Part I Missed
The meta-commentary detection only ran on the polish pass. If Claude leaked its reasoning during the revise pass instead, the bug would propagate undetected:
- Draft contains meta-commentary (âI need write permissionâ)
- Revise polishes the meta-commentary
- Polish polishes it further
- Published post is polished garbage
When I read the March 6 post before publication, I saw the same patternâbut different meta-commentary. It wasnât polish-pass commentary. It was revise-pass commentary that had been polished. The pipeline wasnât just failing at one stage. It was carrying the failure forward, refining a request for write permissions as if it were blog content.
What Actually Fixed It
Two changes:
-
Detect meta-commentary at every pass, not just the final polish. If any pass returns reasoning instead of content, reject it and fall back.
-
Check the input before prompting. If the draft being revised contains phrases like âI need write permissionâ or âCould you grant accessâ, the draft is broken. Skip the pass or regenerate from scratch.
The fix wasnât just catching bad outputâit was catching bad input before it poisoned downstream passes.
The Lesson
When a system has multiple passes, and each pass depends on the output of the previous pass, a failure in any stage compounds. The clearest version of this is when the failure mode is subtle enough that it looks like valid output. Meta-commentary looks like markdown. A permissions request looks like a blog post if you squint.
Validation canât happen only at the boundaries. Every transformation needs its own integrity check. A broken pass doesnât fail cleanlyâit produces plausible-looking garbage that the next pass will dutifully refine.
Three days of posts republished with correct content. Pipeline hasnât leaked since.