fix(pr-795): honest scope for #628 building-block regression tests
Address REQUEST_CHANGES on PR #795: stop claiming all 21 umbrella ACs from a single unit-test module. Scope docs and cases to child issue #878 (CTH/format, ownership classify_skip, dependency edges). Does not close umbrella #628.
This commit is contained in:
@@ -1,10 +1,20 @@
|
|||||||
"""Integration tests for autonomous canonical handoffs and dependency-aware task orchestration (#628).
|
"""Regression tests for #628 building blocks (child scope only).
|
||||||
|
|
||||||
Verifies the 21 acceptance criteria specified in umbrella Issue #628:
|
Honest scope: unit coverage of pre-existing APIs used by umbrella #628.
|
||||||
- Non-terminal stage handoff generation and retrieval
|
This module does **not** implement or verify all 21 umbrella acceptance
|
||||||
- Multi-worker concurrency and exclusive task assignment isolation
|
criteria, automatic handoff store/retrieve, multi-worker product wiring,
|
||||||
- Structured dependency graph integration with the work allocator
|
or end-to-end orchestration.
|
||||||
- Head SHA invalidation and stale review decision protection
|
|
||||||
|
Covered building blocks:
|
||||||
|
- CTH format / parse / assess (`format_cth_body`, `parse_cth_comment`,
|
||||||
|
`assess_cth_comment`)
|
||||||
|
- Exclusive-ownership skip classification (`classify_skip` with
|
||||||
|
OWNERSHIP_FOREIGN vs OWNERSHIP_OWN)
|
||||||
|
- Durable dependency edges (`upsert_dependency_edge` / list) and skip
|
||||||
|
when dependency_unmet
|
||||||
|
- Edge state transition UNMET -> MET
|
||||||
|
|
||||||
|
Parent umbrella remains #628; this slice is a scoped child issue only.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
@@ -42,7 +52,7 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
self._tmp.cleanup()
|
self._tmp.cleanup()
|
||||||
|
|
||||||
def test_canonical_handoff_serialization_and_retrieval(self):
|
def test_canonical_handoff_serialization_and_retrieval(self):
|
||||||
"""AC1 & AC2: Every non-terminal stage stores and retrieves a valid canonical handoff."""
|
"""Building block: format/parse/assess a CTH body (not full AC1/AC2 product path)."""
|
||||||
handoff = format_cth_body(
|
handoff = format_cth_body(
|
||||||
cth_type="Author Handoff",
|
cth_type="Author Handoff",
|
||||||
status="completed",
|
status="completed",
|
||||||
@@ -51,7 +61,7 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
decision="Implementation complete, tests passing",
|
decision="Implementation complete, tests passing",
|
||||||
proof="pytest tests/test_issue_628_orchestration.py passed",
|
proof="pytest tests/test_issue_628_orchestration.py passed",
|
||||||
next_action="Review PR and run reviewer pre-flight",
|
next_action="Review PR and run reviewer pre-flight",
|
||||||
ready_to_paste_prompt="Review PR for issue #628",
|
ready_to_paste_prompt="Review PR for child issue #878 (parent #628)",
|
||||||
)
|
)
|
||||||
self.assertIn("CTH: Author Handoff", handoff)
|
self.assertIn("CTH: Author Handoff", handoff)
|
||||||
|
|
||||||
@@ -63,11 +73,11 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
self.assertFalse(assessment["block"])
|
self.assertFalse(assessment["block"])
|
||||||
|
|
||||||
def test_exclusive_task_unit_single_owner(self):
|
def test_exclusive_task_unit_single_owner(self):
|
||||||
"""AC5 & AC6: Concurrency isolation ensures an exclusive task unit has only one active owner."""
|
"""Building block: classify_skip foreign vs own ownership."""
|
||||||
candidate = WorkCandidate(
|
candidate = WorkCandidate(
|
||||||
kind="issue",
|
kind="issue",
|
||||||
number=628,
|
number=878,
|
||||||
title="Umbrella #628 test candidate",
|
title="Child #878 ownership classify candidate",
|
||||||
state="open",
|
state="open",
|
||||||
labels=["status:in-progress"],
|
labels=["status:in-progress"],
|
||||||
blocked=False,
|
blocked=False,
|
||||||
@@ -93,14 +103,14 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
self.assertIsNone(skip_self)
|
self.assertIsNone(skip_self)
|
||||||
|
|
||||||
def test_durable_dependency_graph_blocking(self):
|
def test_durable_dependency_graph_blocking(self):
|
||||||
"""AC8, AC9, AC10: Durable dependency edges exclude blocked tasks from assignment."""
|
"""Building block: unmet dependency edge + classify_skip on dependency_unmet."""
|
||||||
# Upsert a blocking dependency edge between issue 628 and blocker 601
|
# Upsert a blocking dependency edge between issue 878 and blocker 601
|
||||||
self.db.upsert_dependency_edge(
|
self.db.upsert_dependency_edge(
|
||||||
remote="prgs",
|
remote="prgs",
|
||||||
org="Scaled-Tech-Consulting",
|
org="Scaled-Tech-Consulting",
|
||||||
repo="Gitea-Tools",
|
repo="Gitea-Tools",
|
||||||
source_kind="issue",
|
source_kind="issue",
|
||||||
source_number=628,
|
source_number=878,
|
||||||
target_kind="issue",
|
target_kind="issue",
|
||||||
target_number=601,
|
target_number=601,
|
||||||
edge_type=dependency_graph.EDGE_ISSUE_BLOCKED_BY_ISSUE,
|
edge_type=dependency_graph.EDGE_ISSUE_BLOCKED_BY_ISSUE,
|
||||||
@@ -115,7 +125,7 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
org="Scaled-Tech-Consulting",
|
org="Scaled-Tech-Consulting",
|
||||||
repo="Gitea-Tools",
|
repo="Gitea-Tools",
|
||||||
source_kind="issue",
|
source_kind="issue",
|
||||||
source_number=628,
|
source_number=878,
|
||||||
)
|
)
|
||||||
self.assertEqual(len(edges), 1)
|
self.assertEqual(len(edges), 1)
|
||||||
self.assertEqual(edges[0]["state"], "unmet")
|
self.assertEqual(edges[0]["state"], "unmet")
|
||||||
@@ -124,13 +134,13 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
# When dependency is unmet, candidate is blocked from selection
|
# When dependency is unmet, candidate is blocked from selection
|
||||||
candidate = WorkCandidate(
|
candidate = WorkCandidate(
|
||||||
kind="issue",
|
kind="issue",
|
||||||
number=628,
|
number=878,
|
||||||
title="Blocked candidate",
|
title="Blocked candidate",
|
||||||
state="open",
|
state="open",
|
||||||
labels=[],
|
labels=[],
|
||||||
blocked=False,
|
blocked=False,
|
||||||
dependency_unmet=True,
|
dependency_unmet=True,
|
||||||
dependency_reason="issue#628 is blocked by unmet dependency issue#601",
|
dependency_reason="issue#878 is blocked by unmet dependency issue#601",
|
||||||
)
|
)
|
||||||
skip_reason = classify_skip(
|
skip_reason = classify_skip(
|
||||||
c=candidate,
|
c=candidate,
|
||||||
@@ -142,13 +152,13 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
self.assertIn("issue#601", skip_reason)
|
self.assertIn("issue#601", skip_reason)
|
||||||
|
|
||||||
def test_dependency_completion_reevaluation(self):
|
def test_dependency_completion_reevaluation(self):
|
||||||
"""AC11: Dependency completion updates edge state to MET."""
|
"""Building block: dependency edge state can transition UNMET -> MET."""
|
||||||
self.db.upsert_dependency_edge(
|
self.db.upsert_dependency_edge(
|
||||||
remote="prgs",
|
remote="prgs",
|
||||||
org="Scaled-Tech-Consulting",
|
org="Scaled-Tech-Consulting",
|
||||||
repo="Gitea-Tools",
|
repo="Gitea-Tools",
|
||||||
source_kind="issue",
|
source_kind="issue",
|
||||||
source_number=628,
|
source_number=878,
|
||||||
target_kind="issue",
|
target_kind="issue",
|
||||||
target_number=601,
|
target_number=601,
|
||||||
edge_type=dependency_graph.EDGE_ISSUE_BLOCKED_BY_ISSUE,
|
edge_type=dependency_graph.EDGE_ISSUE_BLOCKED_BY_ISSUE,
|
||||||
@@ -164,7 +174,7 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
org="Scaled-Tech-Consulting",
|
org="Scaled-Tech-Consulting",
|
||||||
repo="Gitea-Tools",
|
repo="Gitea-Tools",
|
||||||
source_kind="issue",
|
source_kind="issue",
|
||||||
source_number=628,
|
source_number=878,
|
||||||
target_kind="issue",
|
target_kind="issue",
|
||||||
target_number=601,
|
target_number=601,
|
||||||
edge_type=dependency_graph.EDGE_ISSUE_BLOCKED_BY_ISSUE,
|
edge_type=dependency_graph.EDGE_ISSUE_BLOCKED_BY_ISSUE,
|
||||||
@@ -179,7 +189,7 @@ class TestIssue628Orchestration(unittest.TestCase):
|
|||||||
org="Scaled-Tech-Consulting",
|
org="Scaled-Tech-Consulting",
|
||||||
repo="Gitea-Tools",
|
repo="Gitea-Tools",
|
||||||
source_kind="issue",
|
source_kind="issue",
|
||||||
source_number=628,
|
source_number=878,
|
||||||
)
|
)
|
||||||
self.assertEqual(len(edges), 1)
|
self.assertEqual(len(edges), 1)
|
||||||
self.assertEqual(edges[0]["state"], "met")
|
self.assertEqual(edges[0]["state"], "met")
|
||||||
|
|||||||
Reference in New Issue
Block a user