55evidence references (dates, proof counts, local-environment paths).
66Stdlib only: re / pathlib. No external dependencies, no conftest.
77"""
8+
89import re
910from pathlib import Path
1011
2627DATE_PATTERN = re .compile (r"20\d\d-\d\d" )
2728
2829
29- def _split_frontmatter (path ) :
30+ def _split_frontmatter (path : Path ) -> tuple [ str , str , str ] :
3031 assert path .exists (), f"missing { path } "
3132 text = path .read_text (encoding = "utf-8" )
3233 m = FRONTMATTER_RE .match (text )
3334 assert m , f"{ path .name } : frontmatter delimiters (---) not found"
3435 return m .group (1 ), m .group (2 ), text
3536
3637
37- def test_agent_frontmatter ():
38+ def test_agent_frontmatter () -> None :
3839 """Both agents declare name/description/model; orchestrator's tools
3940 line excludes Edit/Write (structural guarantee: the commander cannot
4041 touch files directly). Word-boundary matching avoids false positives
@@ -59,7 +60,7 @@ def test_agent_frontmatter():
5960 )
6061
6162
62- def test_orchestrator_references_namespaced_worker ():
63+ def test_orchestrator_references_namespaced_worker () -> None :
6364 """orchestrator body must delegate via the namespaced worker
6465 (ConsiderateCoder:worker); a bare `subagent_type: worker` would not
6566 resolve once the agent is installed as a plugin.
@@ -74,31 +75,29 @@ def test_orchestrator_references_namespaced_worker():
7475 )
7576
7677
77- def test_structural_tool_guarantees ():
78+ def test_structural_tool_guarantees () -> None :
7879 """Structural guarantees on both sides of the delegation: the
7980 orchestrator cannot send async messages (no SendMessage — its own
8081 discipline bans round-trips), and the worker cannot re-delegate
8182 (Agent is disallowed). Discipline is culture; the tool list is law."""
8283 orchestrator_fm , _ , _ = _split_frontmatter (ORCHESTRATOR_PATH )
83- tools_line = re .search (
84- r"^ tools:\s*(.+)$" , orchestrator_fm , re . MULTILINE
85- ) .group (1 )
84+ tools_match = re .search (r"^tools:\s*(.+)$" , orchestrator_fm , re . MULTILINE )
85+ assert tools_match , "orchestrator frontmatter has no tools: line"
86+ tools_line = tools_match .group (1 )
8687 assert not re .search (r"\bSendMessage\b" , tools_line ), (
8788 f"orchestrator tools must not include SendMessage: { tools_line !r} "
8889 )
8990
9091 worker_fm , _ , _ = _split_frontmatter (WORKER_PATH )
91- disallowed_match = re .search (
92- r"^disallowedTools:\s*(.+)$" , worker_fm , re .MULTILINE
93- )
92+ disallowed_match = re .search (r"^disallowedTools:\s*(.+)$" , worker_fm , re .MULTILINE )
9493 assert disallowed_match , "worker frontmatter missing disallowedTools line"
9594 assert re .search (r"\bAgent\b" , disallowed_match .group (1 )), (
9695 f"worker disallowedTools must include Agent (no re-delegation): "
9796 f"{ disallowed_match .group (1 )!r} "
9897 )
9998
10099
101- def test_agents_preload_dev_rules ():
100+ def test_agents_preload_dev_rules () -> None :
102101 """Both agents preload dev-rules via the skills: frontmatter field —
103102 the official wiring that injects full rule content into a subagent's
104103 context at spawn (subagents don't receive the full Claude Code system
@@ -108,15 +107,14 @@ def test_agents_preload_dev_rules():
108107 skills_match = re .search (r"^skills:\s*(.+)$" , frontmatter , re .MULTILINE )
109108 assert skills_match , f"{ path .name } missing skills: preload line"
110109 assert "dev-rules" in skills_match .group (1 ), (
111- f"{ path .name } skills: must preload dev-rules: "
112- f"{ skills_match .group (1 )!r} "
110+ f"{ path .name } skills: must preload dev-rules: { skills_match .group (1 )!r} "
113111 )
114112
115113
116114STATUS_VOCAB = ("COMPLETED" , "PARTIAL" , "BLOCKED" , "RETURNED" )
117115
118116
119- def test_completion_status_vocabulary_symmetric ():
117+ def test_completion_status_vocabulary_symmetric () -> None :
120118 """The worker report opens with a one-word completion status, and a stop
121119 (3-Strike STOP / interruption / unverified work) is never written as
122120 COMPLETED; the orchestrator briefs and reviews with the same four-state
@@ -133,17 +131,15 @@ def test_completion_status_vocabulary_symmetric():
133131 )
134132
135133
136- def test_worker_reports_discovered_issues ():
134+ def test_worker_reports_discovered_issues () -> None :
137135 """Out-of-scope problems the worker notices must reach the report:
138136 staying hands-off is required, staying silent is forbidden (discovering
139137 an issue and not reporting it reads as a clean pass to the reviewer)."""
140138 _ , body , _ = _split_frontmatter (WORKER_PATH )
141- assert "黙過" in body , (
142- "worker.md missing the no-silent-discovery rule (黙過)"
143- )
139+ assert "黙過" in body , "worker.md missing the no-silent-discovery rule (黙過)"
144140
145141
146- def test_no_dev_evidence_refs ():
142+ def test_no_dev_evidence_refs () -> None :
147143 """Neither agent may carry development-session evidence: dates,
148144 proof-count callouts, local model assumptions, or local paths.
149145 """
0 commit comments