mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
fix(gateway): let a dependent agent read its dependency via evidence
evidence is read-only, but the cross-agent ownership gate blocked a caller from inspecting a task its own work depends on (a frontend cell could not read the UX task it was waiting on). Exempt reads where the target is a dependency of a task assigned to the caller. Also dropped stale internal refs from the docstring.
This commit is contained in:
@@ -703,6 +703,17 @@ class ContentActions:
|
|||||||
context_briefing={},
|
context_briefing={},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _is_caller_dependency(self, agent_id: UUID, task: Any) -> bool:
|
||||||
|
"""True when ``task`` is a dependency of a task the caller is assigned to.
|
||||||
|
|
||||||
|
A dependent agent (e.g. a frontend cell waiting on a UX design task)
|
||||||
|
must be able to inspect what it is blocked on; read-only evidence is the
|
||||||
|
right tool, and the strict cross-agent ownership gate would otherwise
|
||||||
|
reject it.
|
||||||
|
"""
|
||||||
|
assigned = await self.task.list_assigned_for_agent(agent_id)
|
||||||
|
return any(task.id in (a.dependency_ids or []) for a in assigned)
|
||||||
|
|
||||||
async def evidence(
|
async def evidence(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
@@ -711,28 +722,28 @@ class ContentActions:
|
|||||||
) -> Envelope:
|
) -> Envelope:
|
||||||
"""Inspect a task's PR diff, commits, files.
|
"""Inspect a task's PR diff, commits, files.
|
||||||
|
|
||||||
Fetches dev branch into the agent's workspace before diffing.
|
Fetches the dev branch into the agent's workspace before diffing.
|
||||||
Allows inspection when caller is assignee OR task is unassigned
|
Allows inspection when the caller is the assignee, the task is
|
||||||
(post-handoff transient state) — strict ownership only blocks
|
unassigned, the caller co-reviews a shared board task, or the task is a
|
||||||
cross-agent inspection of an actively-owned task.
|
dependency the caller is waiting on — strict ownership only blocks
|
||||||
|
snooping an unrelated, actively-owned task.
|
||||||
|
|
||||||
Task #154: ``files_changed`` and ``pr_diff_summary`` are pulled
|
``files_changed`` and ``pr_diff_summary`` are pulled from git (against
|
||||||
from git (against the branch's parent) — the authoritative source.
|
the branch's parent — the authoritative source) rather than the latest
|
||||||
Earlier versions hard-coded ``files_changed=[]`` and used
|
commit's delta, so reviewers see the full multi-commit change set.
|
||||||
``HEAD~1`` for the diff base, so QA / reviewers saw an empty
|
|
||||||
change list and only the latest commit's delta even when the PR
|
|
||||||
on GitHub had a multi-commit change set.
|
|
||||||
"""
|
"""
|
||||||
t = await self.task.get(task_id)
|
t = await self.task.get(task_id)
|
||||||
if t is None:
|
if t is None:
|
||||||
return Envelope.not_found(message=f"task {task_id} not found")
|
return Envelope.not_found(message=f"task {task_id} not found")
|
||||||
# A board co-reviewer (HoM inspecting a PO-assigned board task, or vice
|
# Reads are allowed for the assignee, an unassigned task, a board
|
||||||
# versa) must be able to read the shared coordination task — the same
|
# co-reviewer of a shared coordination task, OR a caller whose own work
|
||||||
# allowance the content verbs grant via co-review.
|
# depends on this task. Strict ownership only blocks snooping an
|
||||||
|
# unrelated, actively-owned task.
|
||||||
if (
|
if (
|
||||||
t.assigned_to is not None
|
t.assigned_to is not None
|
||||||
and t.assigned_to != agent_id
|
and t.assigned_to != agent_id
|
||||||
and not await self._board_may_co_review(agent_id, t)
|
and not await self._board_may_co_review(agent_id, t)
|
||||||
|
and not await self._is_caller_dependency(agent_id, t)
|
||||||
):
|
):
|
||||||
return _ownership_violation(task_id)
|
return _ownership_violation(task_id)
|
||||||
if t.branch_name and t.work_session_id:
|
if t.branch_name and t.work_session_id:
|
||||||
|
|||||||
@@ -472,3 +472,41 @@ async def test_evidence_unassigned_task_allows_inspection() -> None:
|
|||||||
|
|
||||||
env = await ca.evidence(agent_id=agent_id, task_id=task_id)
|
env = await ca.evidence(agent_id=agent_id, task_id=task_id)
|
||||||
assert env.error is None
|
assert env.error is None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_evidence_allows_dependency_inspection() -> None:
|
||||||
|
"""A caller whose own assigned task depends on the target may read it.
|
||||||
|
|
||||||
|
A frontend cell waiting on a UX design task must be able to inspect the
|
||||||
|
dependency it is blocked on, even though another agent owns it.
|
||||||
|
"""
|
||||||
|
agent_id = uuid4()
|
||||||
|
other_id = uuid4()
|
||||||
|
dep_task_id = uuid4()
|
||||||
|
target = MagicMock(
|
||||||
|
id=dep_task_id,
|
||||||
|
status="in_progress",
|
||||||
|
assigned_to=other_id,
|
||||||
|
branch_name="feature/ux_ui/abc",
|
||||||
|
work_session_id=uuid4(),
|
||||||
|
commits=[],
|
||||||
|
pr_number=None,
|
||||||
|
pr_url="",
|
||||||
|
dev_notes="",
|
||||||
|
acceptance_criteria_status=[],
|
||||||
|
)
|
||||||
|
callers_task = MagicMock(id=uuid4(), dependency_ids=[dep_task_id])
|
||||||
|
task_svc = AsyncMock()
|
||||||
|
task_svc.get.return_value = target
|
||||||
|
task_svc.list_assigned_for_agent.return_value = [callers_task]
|
||||||
|
git_svc = AsyncMock()
|
||||||
|
git_svc.diff.return_value = ""
|
||||||
|
git_svc.list_changed_files.return_value = []
|
||||||
|
workspace_svc = AsyncMock()
|
||||||
|
deps = _make_deps(task=task_svc, git=git_svc, workspace=workspace_svc)
|
||||||
|
ca = ContentActions(deps)
|
||||||
|
|
||||||
|
env = await ca.evidence(agent_id=agent_id, task_id=dep_task_id)
|
||||||
|
assert env.error is None
|
||||||
|
task_svc.list_assigned_for_agent.assert_awaited()
|
||||||
|
|||||||
Reference in New Issue
Block a user