4.8 KiB
4.8 KiB
Task 015: SEO And Language Review
Development description: Implement SEO and linguistic review jobs, issue reports, editor accept/reject/edit flows, and versioned application of accepted suggestions.
Implementation Details
- Backend endpoints:
POST /api/articles/{article_id}/seo/reviewGET /api/articles/{article_id}/seo/reportPOST /api/articles/{article_id}/language/reviewGET /api/articles/{article_id}/language/report- endpoints to accept/reject/edit individual suggestions.
- SEO checks:
- Title length.
- Meta title length.
- Meta description length.
- H1/H2 structure.
- Keyword placement.
- Internal links.
- External citations.
- Schema type.
- Slug.
- FAQ eligibility.
- Image alt text.
- Readability.
- Duplicate headings.
- Language checks:
- Grammar.
- Spelling.
- Sentence length.
- Passive voice.
- Jargon density.
- Brand tone.
- Forbidden phrases.
- Repetition.
- Weak claims.
- Unsupported certainty.
- CTA consistency.
- Accepted suggestions create a new draft version when they change approval-relevant content.
Public Interface
- Editor runs SEO and language review.
- Editor accepts, rejects, or edits suggestions.
- UI shows issues with severity and locations.
Acceptance Criteria
- TDD pre-requirement: before implementation, write one failing behavior test that runs an SEO review and returns a visible issue through the public API; proceed one review behavior at a time and record evidence in
Result. - SEO report includes score, issues, suggested fixes, recommended slug/title, and schema JSON.
- Language report includes severity, location, message, and suggested rewrite.
- Editor can accept, reject, or edit each suggestion.
- Accepted content changes create a new immutable draft version.
- Target-site SEO and tone rules override global defaults.
- Final review can show unresolved SEO/language issues.
- Fake review runner produces deterministic demo reports.
Verification
- Run review API tests.
- Run draft-versioning tests for accepted suggestions.
- Run frontend review UI tests.
- Run Docker Compose smoke flow from draft to SEO/language reports.
Result
- Status: Completed (pre-requirement RED + implementation GREEN).
- TDD plan (done):
- Prepare article through public flow to assembled draft state.
- Run SEO and language review via public endpoints.
- Fetch reports and verify issue visibility through API.
- Apply suggestion actions (accept/reject/edit) and verify immutable draft versioning.
- Verify unresolved issues in final review context and deterministic fake-runner behavior.
- Red evidence:
- Pre-requirement test initially failed with
404 Not FoundonPOST /api/articles/{article_id}/seo/review.
- Pre-requirement test initially failed with
- Green evidence:
- Added review domain contracts, persistence tables, repository, application service, and routes:
POST /api/articles/{article_id}/seo/reviewGET /api/articles/{article_id}/seo/reportPOST /api/articles/{article_id}/language/reviewGET /api/articles/{article_id}/language/report- suggestion actions:
POST /api/articles/{article_id}/seo/suggestions/{suggestion_id}/accept|reject|editPOST /api/articles/{article_id}/language/suggestions/{suggestion_id}/accept|reject|edit
- unresolved issues endpoint:
GET /api/articles/{article_id}/final-review/issues
- Reports are generated deterministically from assembled draft + site rules and stored in review tables.
- Accept/edit actions that modify content/metadata create a new immutable draft version through existing draft versioning flow.
- Site-level overrides are applied from
target_sites.seo_rules(seo_review/language_review) over defaults. - Added frontend review feature model + UI and API bindings.
- Regenerated shared contracts:
packages/shared/openapi.jsonpackages/shared/src/api-types.ts
- Added review domain contracts, persistence tables, repository, application service, and routes:
- Refactor notes:
ContentReviewReportSummary.schema_jsoncurrently emits a pydantic shadow warning; behavior is correct and contracts remain stable.
- Verification output:
PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_seo_language_review_public_api.py->OK (6 tests)PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_draft_assembly_public_api.py->OK (5 tests)PYTHONPATH=/private/tmp/pupline-backend-deps python3 -m unittest apps/backend/tests/integration/test_assets_media_library_public_api.py->OK (7 tests)node apps/frontend/tests/draft_editor.model.test.mjs->OKnode apps/frontend/tests/article_assets.model.test.mjs->OKnode apps/frontend/tests/article_review.model.test.mjs->OKpnpm --dir apps/frontend typecheck->OK