Files
corp-v1-channel-architecture/tests/test_task_breakdown_policy.py
T

59 lines
3.8 KiB
Python

from pathlib import Path
import re
import unittest
COMMENT = re.compile(r"<!--.*?-->", re.DOTALL)
def task_section(skill: str) -> str:
operative = COMMENT.sub("", skill)
return operative.split("## Task and Dependency Breakdown", 1)[1].split("## Version Allocation", 1)[0]
def policy_failures(section: str, approval_rule: str) -> list[str]:
section = COMMENT.sub("", section)
patterns = {
"ownership": r"(?m)^Architecture owns complete Task decomposition for every Feature allocated to the release\.$",
"lifecycle": r"(?m)^1\. Architecture creates missing Tasks, reviews existing Tasks, and retains, revises, supersedes, or removes them .+ may freely revise or remove only draft Tasks .+;$",
"cardinality": r"(?m)^2\. define between two and six independently executable Tasks per Feature; permit one Task only when a recorded Architecture rationale proves it is the smallest atomic, independently verifiable boundary;$",
"mapping": r"(?m)^3\. map the Feature's Tasks collectively, exactly, and reciprocally to every acceptance-outcome ID and every applicable active `FR-\*` and `NFR-\*` record;$",
"dependencies": r"(?m)^4\. encode acyclic within-Feature sequencing and require every entry Task to depend on all terminal Tasks of every prerequisite Feature;$",
"contract": r"(?m)^5\. give each Task one specific outcome, repository/component owner, canonical/display identity, task-specific implementation artifacts, concrete inputs and outputs, failure boundaries, exclusions, verification steps, and future acceptance-evidence requirements;$",
"separate-gates": r"(?m)^6\. keep draft Tasks separate from implementation approval and Kanban Focus admission\.$",
"protected-history": r"(?m)^Approved, Kanban-admitted, in-progress, or completed Tasks must not be deleted or silently rewritten\. Retain an obsolete Task with a terminal Superseded or Cancelled status, its prior evidence and history, and explicit replacement links\.$",
"approval-invalidation": approval_rule,
}
return [name for name, pattern in patterns.items() if re.search(pattern, section) is None]
class TaskBreakdownPolicyTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.skill = Path(__file__).parents[1].joinpath("SKILL.md").read_text()
cls.task_section = task_section(cls.skill)
cls.approval_rule = (
r"(?m)^A material change to Task scope, outcome, dependency, repository, or component invalidates the Task's existing implementation approval, returns the Task to its pre-approval state, and always requires renewed human `Approved for Implementation` before implementation can resume\. After renewed approval, execution still requires a separate exact-task Kanban Focus admission\.$"
)
def test_operational_policy_is_complete_and_structured(self):
self.assertIn("version: 1.7.0", self.skill)
self.assertEqual(policy_failures(self.task_section, self.approval_rule), [])
def test_comments_and_weakened_rules_cannot_satisfy_policy(self):
self.assertTrue(policy_failures(f"<!--{self.task_section}-->", self.approval_rule))
mutations = {
"cardinality": ("between two and six", "at least two"),
"mapping": ("exactly, and reciprocally", "loosely"),
"dependencies": ("all terminal Tasks", "some Tasks"),
"approval": ("invalidates the Task's existing implementation approval", "invalidates prior readiness evidence"),
"renewal": ("always requires renewed human", "may require renewed human"),
}
for name, (old, new) in mutations.items():
with self.subTest(name=name):
self.assertTrue(policy_failures(self.task_section.replace(old, new), self.approval_rule))
if __name__ == "__main__":
unittest.main()