@gurupanguji

Normalize Legacy wp:quote Blocks Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add a safe wp:quote normalization script that converts straightforward legacy WordPress quote blocks into native markdown blockquotes plus Source: lines, then use it to rewrite the clean batch of historical posts.

Architecture: Build one narrow Python normalizer that scans _posts/, parses only safe wp:quote shapes, reports skips explicitly, and defaults to dry-run mode. Drive the converter through TDD, keep the rewrite mechanical, then run the script across the repo and verify the resulting batch with unit tests, validators, and spot checks.

Tech Stack: Python 3, unittest, regex/string parsing, Jekyll markdown content, existing repository validators


Task 1: Add Failing Tests For Safe Quote Conversion

Files:

Write a test for a clean block like:

<!-- wp:quote -->
<blockquote class="wp-block-quote"><!-- wp:paragraph -->
<p>First paragraph.</p>
<!-- /wp:paragraph -->
<!-- wp:paragraph -->
<p>Second paragraph.</p>
<!-- /wp:paragraph --><cite><a href="https://example.com/story">Example Story</a></cite></blockquote>
<!-- /wp:quote -->

Assert the converted text becomes:

> First paragraph.
>
> Second paragraph.

Source: [Example Story](https://example.com/story)

Run: python3 -m unittest tests/test_normalize_wp_quotes.py Expected: FAIL because the normalizer module does not exist yet

Write a test for a safe quote block without <cite> and assert the output contains only the markdown blockquote, with no Source: line added.

Run: python3 -m unittest tests/test_normalize_wp_quotes.py Expected: FAIL because conversion helpers are still missing

Task 2: Implement The Minimal Safe Quote Converter

Files:

Implement helpers that keep YAML front matter intact and operate only on the body content.

Implement a matcher that recognizes only a straightforward wp:quote block with:

Map each paragraph to a > line block, separated by blank quoted lines where needed.

If the quote has <cite><a ...>Title</a></cite>, render:

Source: [Title](url)

Run: python3 -m unittest tests/test_normalize_wp_quotes.py Expected: PASS for the safe conversion cases

Task 3: Add Failing Tests For Skip Cases

Files:

Write a test with nested wp:quote wrappers and assert the normalizer skips it with a reason instead of converting it.

Write a test for a post body with more than one wp:quote block and assert it is skipped as ambiguous.

Write a test for a quote block containing image markup and assert it is skipped.

Write a test for a missing closing block marker and assert it is skipped cleanly.

Run: python3 -m unittest tests/test_normalize_wp_quotes.py Expected: FAIL because skip handling is not implemented yet

Task 4: Implement Skip Detection And Structured Reporting

Files:

Track, per file:

Refuse conversion when the body contains:

Skip blocks containing image or unsupported inner markup.

Print a summary that clearly separates:

Run: python3 -m unittest tests/test_normalize_wp_quotes.py Expected: PASS

Task 5: Add CLI And Dry-Run Versus Write Behavior

Files:

Write a test that runs the normalizer without --write and asserts no files are modified.

Write a test that runs with --write and asserts the file content is updated in place for a safe candidate.

If useful for debugging, support restricting the run to:

Run: python3 -m unittest tests/test_normalize_wp_quotes.py Expected: PASS with dry-run and write-mode behavior covered

Task 6: Audit The Real Candidate Set Before Writing

Files:

Run: python3 scripts/normalize_wp_quotes.py Expected:

Check that the candidate set looks reasonable and that the skip reasons match the design:

Open a representative sample from older, middle, and newer posts to confirm the dry-run classification makes sense before any write.

Task 7: Apply The Safe Batch Rewrite

Files:

Run: python3 scripts/normalize_wp_quotes.py --write Expected:

Open at least:

Verify:

Run: git diff --stat Expected: only the normalizer script, tests, plan/spec docs, and the converted safe posts appear

Task 8: Verify Repository Compatibility

Files:

Run:

python3 -m unittest tests/test_normalize_wp_quotes.py tests/test_validate_posts.py

Expected: PASS

Run: python3 scripts/validate_posts.py --today "$(date +%F)" Expected: PASS

Run: python3 scripts/check_markdown_in_html.py Expected: PASS, because this cleanup only touches markdown posts and should not create raw markdown links in HTML files

Run: python3 scripts/normalize_wp_quotes.py Expected: already-converted files no longer appear as candidates, and remaining skips still report cleanly

Task 9: Final Verification And Commit

Files:

Run:

python3 -m unittest tests/test_normalize_wp_quotes.py tests/test_validate_posts.py tests/test_generate_my_web_this_week.py tests/test_publish_social.py
python3 scripts/normalize_wp_quotes.py
python3 scripts/validate_posts.py --today "$(date +%F)"
python3 scripts/check_markdown_in_html.py
git status --short

Expected:

git add docs/superpowers/specs/2026-03-26-normalize-wp-quotes-design.md docs/superpowers/plans/2026-03-26-normalize-wp-quotes-implementation-plan.md scripts/normalize_wp_quotes.py tests/test_normalize_wp_quotes.py _posts/*.md
git commit -m "feat: normalize legacy wp quote blocks"