fix(company): make delegation review lifecycle durable

This commit is contained in:
LZH-YS1998
2026-07-14 10:52:22 +08:00
parent 4bc18dcd27
commit 5e02364eb4
19 changed files with 3150 additions and 1087 deletions
+125
View File
@@ -29,6 +29,7 @@ from opc.layer2_organization.communication import CommunicationManager
from opc.layer2_organization.company_mode import (
CompanyWorkItemExecutor,
MAX_VERDICT_PARSE_RETRIES,
report_work_item_id_for_attempt,
review_work_item_id_for_attempt,
)
from opc.layer2_organization.org_engine import OrgEngine
@@ -238,6 +239,130 @@ class VerdictParseRetryTests(unittest.IsolatedAsyncioTestCase):
finally:
await store.close()
async def test_retry_card_save_failure_stays_in_review_and_reconciles(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)
store = OPCStore(root / "tasks.db")
await store.initialize()
try:
executor = _build_executor(store, _make_org_engine(root))
child, review_id_v1 = _build_review_setup(store)
report_id = report_work_item_id_for_attempt("wi-child", 1)
child.metadata = {
**dict(child.metadata or {}),
"report_attempt_count": 1,
}
report = DelegationWorkItem(
work_item_id=report_id,
run_id="run-1",
cell_id="team::cto",
team_id="team::cto",
role_id="engineer",
seat_id="seat::team::cto::engineer",
manager_role_id="cto",
manager_seat_id="seat::team::cto::cto",
parent_work_item_id="wi-child",
title="Report #1: Build feature",
summary="Durable worker report.",
kind="report",
projection_id=report_id,
phase=Phase.APPROVED,
batch_index=1,
metadata={
"runtime_model": "multi_team_org",
"work_kind": "report",
"report_execution_work_item": True,
"report_attempt": 1,
"report_target_work_item_id": "wi-child",
"report_card_outcome": "applied",
"completion_report": "Durable worker report.",
"review_evidence": {
"completion_summary": "Durable worker report."
},
},
)
review = _make_review_card(review_card_id=review_id_v1)
review.metadata = {
**dict(review.metadata or {}),
"review_source_report_work_item_id": report_id,
}
await store.save_delegation_work_item(child)
await store.save_delegation_work_item(report)
await store.save_delegation_work_item(review)
original_insert = store.insert_delegation_work_item_if_absent
review_id_v2 = review_work_item_id_for_attempt("wi-child", 2)
injected = False
async def fail_first_retry_card_insert(
item: DelegationWorkItem,
) -> bool:
nonlocal injected
if not injected and item.work_item_id == review_id_v2:
injected = True
raise RuntimeError("injected review retry save failure")
return await original_insert(item)
store.insert_delegation_work_item_if_absent = AsyncMock(
side_effect=fail_first_retry_card_insert
)
review_task = _make_review_task(
review_card_id=review_id_v1,
structured_verdict={"unparseable": True},
)
try:
await executor._finalize_review_work_item(review_task)
finally:
store.insert_delegation_work_item_if_absent = original_insert
self.assertTrue(injected)
child_after_failure = await store.get_delegation_work_item(
"wi-child"
)
failed_review = await store.get_delegation_work_item(review_id_v1)
self.assertEqual(
child_after_failure.phase,
Phase.AWAITING_MANAGER_REVIEW,
)
self.assertFalse(
child_after_failure.metadata.get(
"review_verdict_parse_failed_auto_done", False
)
)
self.assertEqual(failed_review.phase, Phase.CANCELLED)
self.assertEqual(
failed_review.metadata.get("review_work_item_outcome"),
"verdict_parse_failed",
)
self.assertIsNone(
await store.get_delegation_work_item(review_id_v2)
)
run_items = await store.list_delegation_work_items("run-1")
await executor._reconcile_missing_review_chain(run_items)
await executor._reconcile_missing_review_chain(
await store.list_delegation_work_items("run-1")
)
retry = await store.get_delegation_work_item(review_id_v2)
self.assertIsNotNone(retry)
self.assertEqual(retry.phase, Phase.READY)
self.assertEqual(
retry.metadata.get("review_source_report_work_item_id"),
report_id,
)
self.assertEqual(
retry.metadata.get("review_retry_reason"),
"verdict_parse_failed",
)
self.assertIsNone(
await store.get_delegation_work_item(
report_work_item_id_for_attempt("wi-child", 2)
)
)
finally:
await store.close()
async def test_retry_preserves_review_owner_when_runtime_task_lost_owner_metadata(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
root = Path(tmpdir)