Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions containers/entrypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,13 +694,15 @@ async def run_reviewer_agent(
workspace: Path,
review_instructions: str,
task_key: str,
task_description: str = "",
) -> str:
"""Run reviewer agent with review.md instructions.

Args:
workspace: Path to the workspace directory.
review_instructions: Instructions from review.md body.
task_key: Jira task key for tracing.
task_description: Implementation context, including repository scope.

Returns:
The reviewer agent's output text.
Expand All @@ -725,6 +727,12 @@ async def run_reviewer_agent(
## Review Instructions
{review_instructions}

## Task Context and Repository Scope
{task_description}

Evaluate completeness only within the repository scope stated above. Requirements assigned
to other repositories are not missing from this implementation; they are handled separately.

## Verdict Format
After reviewing the code, you MUST output your verdict as either:
- APPROVED - if the implementation meets all requirements
Expand Down Expand Up @@ -861,6 +869,7 @@ async def run_review_loop(
workspace=workspace,
review_instructions=instructions,
task_key=task_key,
task_description=task_description,
)
except Exception as e:
logger.error(f"Reviewer agent failed: {e}")
Expand Down
7 changes: 7 additions & 0 deletions src/forge/workflow/nodes/task_takeover_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ async def execute_task_changes(state: TaskTakeoverState) -> TaskTakeoverState:

task_prompt = (
f"You are implementing changes for task takeover [{current_task}].\n\n"
f"## Repository Execution Scope\n"
f"Current repository: `{current_repo}`\n"
f"Implement and validate only the approved-plan steps that belong to "
f"`{current_repo}`. Do not search for, create, or modify files assigned to "
f"other repositories in the plan. Those repositories are handled in separate "
f"workspaces. Completion for this run is evaluated only against the current "
f"repository's scope.\n\n"
f"{feedback_section}"
f"## Approved Implementation Plan\n{plan_content}\n\n"
f"## Task Description\n{task_description}\n\n"
Expand Down
8 changes: 8 additions & 0 deletions src/forge/workflow/nodes/task_takeover_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ async def run_qualitative_review(state: WorkflowState) -> WorkflowState:
git_diff=git_diff,
workspace_path=workspace_path,
)
prompt_content = (
"## Repository Review Scope\n"
f"Current repository: `{current_repo}`\n"
"Review only requirements and changes belonging to this repository. Do not "
"reject this repository's work because plan steps assigned to other repositories "
"are absent; those are implemented and reviewed separately.\n\n"
f"{prompt_content}"
)

runner = ContainerRunner(settings)
result, response = await run_review_container(
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/containers/test_entrypoint_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,13 @@ async def test_returns_agent_output(self, tmp_path: Path):
workspace=tmp_path,
review_instructions="Check for bugs",
task_key="TEST-123",
task_description="Current repository: owner/repo",
)

assert result == "APPROVED"
system_prompt = mock_create.call_args.kwargs["system_prompt"]
assert "Current repository: owner/repo" in system_prompt
assert "handled separately" in system_prompt

@pytest.mark.asyncio
async def test_system_prompt_contains_instructions(self, tmp_path: Path):
Expand Down Expand Up @@ -305,6 +309,10 @@ async def mock_reviewer_side_effect(*_args, **_kwargs):
assert result is True
assert mock_reviewer.call_count == 2
mock_worker.assert_called_once()
assert all(
call.kwargs["task_description"] == "Description"
for call in mock_reviewer.call_args_list
)

# Check feedback was passed to worker
worker_call = mock_worker.call_args
Expand Down
4 changes: 4 additions & 0 deletions tests/unit/workflow/nodes/test_task_takeover_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ async def test_successful_execution(self) -> None:
assert kwargs["workspace_path"] == Path("/tmp/ws")
assert "Approved Implementation Plan" in kwargs["task_description"]
assert "inject at least one new or modified test file" in kwargs["task_description"]
assert "Current repository: `acme/backend`" in kwargs["task_description"]
assert "Do not search for, create, or modify files assigned to other repositories" in (
kwargs["task_description"]
)
assert "config" not in kwargs

# Verify GitOperations were performed
Expand Down
2 changes: 2 additions & 0 deletions tests/unit/workflow/nodes/test_task_takeover_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ async def test_run_qualitative_review_success(self, base_task_state: TaskTakeove
assert kwargs["repo_name"] == "owner/repo"
assert "previous_task_keys" not in kwargs
assert "config" not in kwargs
assert "Current repository: `owner/repo`" in kwargs["task_description"]
assert "Do not reject this repository's work" in kwargs["task_description"]
assert "task-takeover-review skill" in kwargs["task_description"]

@pytest.mark.asyncio
Expand Down
Loading