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()