mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[chore] logical-gaps: verb_runner trailing-None side-effect guard + actor_agent_id threading (3 gaps)
_verb_runner.py: - run_intent skips the side_effects loop when a TRAILING composed action returned None (its source-status check failed under a concurrent transition). Previously the loop ran unconditionally on the None task and _do_push_branch(None)/_do_pr_merge(None) crashed with a NoneType AttributeError, turning the clean INVALID_STATE the entry/intermediate guards give into a 500/respawn loop. The trailing None now flows to the caller's `if task is None` handler. Latent today (no shipped intent has both a None-capable compose and trailing side_effects) but the runner is generic. (gap: runner-side-effects-fire- on-trailing-none-task) - _do_push_branch / _do_create_pr / _do_create_root_pr forward actor_agent_id=agent.id into git_service (push_branch / create_pr), matching _do_pr_merge. Without it, a verb on a task whose assigned_to was cleared before the side effect falls through to created_by and pushes from / opens a PR against the wrong workspace. (gap: side-effect-handlers-drop-actor-agent-id) - _do_escalate_to_ceo forwards actor_agent_id=agent.id so the awaiting_ceo_approval audit row attributes to the specific PM/Board agent. (gap: do-escalate-to-ceo-drops-actor-agent-id) task.py: escalate_to_ceo gains actor_agent_id param, passed as audit_agent_id to _validate_and_set_status and recorded as escalated_by_agent_id in the event payload + log. escalate_to_ceo_for_agent forwards agent.agent_id. _impl.py: the main_pm complete->escalate path forwards actor_agent_id=main_pm_agent_id. TDD: 5 red->green tests (synthetic trailing-None intent, actor forwarding for push_branch/create_pr/create_root_pr/escalate_to_ceo) + real-DB audit test asserting the awaiting_ceo_approval row carries the actor UUID. Updated 3 board escalate_to_ceo tests to assert the forwarded actor.
This commit is contained in:
@@ -72,7 +72,7 @@ async def test_board_escalate_to_ceo_succeeds_for_product_owner() -> None:
|
||||
after = MagicMock(**{**t.__dict__, "status": "awaiting_ceo_approval"})
|
||||
task_svc = AsyncMock()
|
||||
task_svc.get.return_value = t
|
||||
task_svc.agent_for.return_value = MagicMock(role="product_owner")
|
||||
task_svc.agent_for.return_value = MagicMock(id=agent_id, role="product_owner")
|
||||
task_svc.escalate_to_ceo.return_value = after
|
||||
journal_svc = AsyncMock()
|
||||
journal_svc.has_decision_for_task.return_value = True
|
||||
@@ -87,6 +87,7 @@ async def test_board_escalate_to_ceo_succeeds_for_product_owner() -> None:
|
||||
task_id=task_id,
|
||||
agent_role="product_owner",
|
||||
notes="ready for CEO sign-off",
|
||||
actor_agent_id=agent_id,
|
||||
)
|
||||
|
||||
|
||||
@@ -102,7 +103,7 @@ async def test_board_escalate_to_ceo_succeeds_for_head_marketing() -> None:
|
||||
after = MagicMock(**{**t.__dict__, "status": "awaiting_ceo_approval"})
|
||||
task_svc = AsyncMock()
|
||||
task_svc.get.return_value = t
|
||||
task_svc.agent_for.return_value = MagicMock(role="head_marketing")
|
||||
task_svc.agent_for.return_value = MagicMock(id=agent_id, role="head_marketing")
|
||||
task_svc.escalate_to_ceo.return_value = after
|
||||
journal_svc = AsyncMock()
|
||||
journal_svc.has_decision_for_task.return_value = True
|
||||
@@ -117,6 +118,7 @@ async def test_board_escalate_to_ceo_succeeds_for_head_marketing() -> None:
|
||||
task_id=task_id,
|
||||
agent_role="head_marketing",
|
||||
notes="brand-affecting change",
|
||||
actor_agent_id=agent_id,
|
||||
)
|
||||
|
||||
|
||||
@@ -236,7 +238,7 @@ async def test_board_escalate_to_ceo_succeeds_for_main_pm() -> None:
|
||||
after = MagicMock(**{**t.__dict__, "status": "awaiting_ceo_approval"})
|
||||
task_svc = AsyncMock()
|
||||
task_svc.get.return_value = t
|
||||
task_svc.agent_for.return_value = MagicMock(role="main_pm")
|
||||
task_svc.agent_for.return_value = MagicMock(id=agent_id, role="main_pm")
|
||||
task_svc.escalate_to_ceo.return_value = after
|
||||
journal_svc = AsyncMock()
|
||||
journal_svc.has_decision_for_task.return_value = True
|
||||
@@ -251,6 +253,7 @@ async def test_board_escalate_to_ceo_succeeds_for_main_pm() -> None:
|
||||
task_id=task_id,
|
||||
agent_role="main_pm",
|
||||
notes="root task done",
|
||||
actor_agent_id=agent_id,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user