test: add editorial style guide validation tests (#404)

Adds validation tests for the editorial style guide covering segment order, AI disclosure, corrections URL, and distinctiveness requirements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Juan Manuel Servera committed Jun 12, 2026 at 09:09 UTC cbed657c30b2affc9cb25b87305150061d8a0fef
1 file changed +100
tests/test_editorial_style_guide.py new
+100
@@ -0,0 +1,100 @@
1 +"""Validate the editorial style guide contains all required safety sections.
2 +
3 +This test ensures the Signal Check editorial style guide maintains required
4 +safety boundaries, disclosure requirements, and structural constraints that
5 +prevent unsafe content generation.
6 +"""
7 +
8 +from pathlib import Path
9 +
10 +import pytest
11 +
12 +GUIDE_PATH = Path(__file__).resolve().parent.parent / "docs" / "editorial-style-guide.md"
13 +
14 +
15 +@pytest.fixture
16 +def guide_content() -> str:
17 + assert GUIDE_PATH.exists(), f"Editorial style guide not found at {GUIDE_PATH}"
18 + return GUIDE_PATH.read_text(encoding="utf-8")
19 +
20 +
21 +class TestEditorialStyleGuideStructure:
22 + """Verify the guide contains all required structural elements."""
23 +
24 + def test_guide_exists(self):
25 + assert GUIDE_PATH.exists()
26 +
27 + def test_has_host_roles(self, guide_content: str):
28 + assert "Host A" in guide_content
29 + assert "Host B" in guide_content
30 + assert "Curator" in guide_content
31 + assert "Skeptic" in guide_content
32 +
33 + def test_has_all_segments_in_order(self, guide_content: str):
34 + required_segments = [
35 + "Cold Open",
36 + "The Signal",
37 + "The Noise Check",
38 + "The Gap",
39 + "Receipts Round",
40 + "Week Ahead",
41 + "Outro",
42 + ]
43 + for segment in required_segments:
44 + assert segment in guide_content, f"Missing segment: {segment}"
45 + # Verify locked order (segments must not be reordered)
46 + positions = [guide_content.index(s) for s in required_segments]
47 + assert positions == sorted(positions), (
48 + "Segments are not in the required locked order"
49 + )
50 +
51 + def test_has_word_count_target(self, guide_content: str):
52 + assert "1,200" in guide_content
53 + assert "1,700" in guide_content
54 +
55 +
56 +class TestEditorialStyleGuideSafety:
57 + """Verify safety boundaries are documented."""
58 +
59 + def test_ai_disclosure_requirement(self, guide_content: str):
60 + lower = guide_content.lower()
61 + assert "first 60 seconds" in lower, "Must require AI disclosure in first 60 seconds"
62 + assert "ai-generated voice" in lower or "ai_generated" in lower, (
63 + "Must mention AI-generated voice disclosure"
64 + )
65 + # Disclosure should also be required in the outro
66 + assert "outro" in lower
67 +
68 + def test_prohibited_content_section(self, guide_content: str):
69 + required_prohibitions = [
70 + "Real-person mimicry",
71 + "Copied expression",
72 + "Unsupported facts",
73 + "Defamatory motive",
74 + "Fake sponsorship",
75 + "Individual-targeting humor",
76 + ]
77 + for prohibition in required_prohibitions:
78 + assert prohibition in guide_content, f"Missing prohibition: {prohibition}"
79 +
80 + def test_corrections_path(self, guide_content: str):
81 + assert "corrections" in guide_content.lower()
82 + # Must link to the specific SquadScope issues page, not just any github.com URL
83 + assert "github.com/jmservera/SquadScope/issues" in guide_content, (
84 + "Corrections path must link to the SquadScope issues page"
85 + )
86 +
87 + def test_claim_ledger_requirement(self, guide_content: str):
88 + assert "claim ledger" in guide_content.lower()
89 + assert "must map" in guide_content.lower() or "MUST map" in guide_content
90 +
91 + def test_distinctiveness_requirements(self, guide_content: str):
92 + lower = guide_content.lower()
93 + assert "hard fork" in lower, "Must reference Hard Fork as distinctiveness example"
94 + assert "must not replicate" in lower, (
95 + "Must state the requirement not to replicate other podcasts"
96 + )
97 +
98 + def test_sponsorship_guardrails(self, guide_content: str):
99 + assert "FTC" in guide_content or "sponsorship" in guide_content.lower()
100 + assert "brought to you by" in guide_content.lower()