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: 7 additions & 2 deletions src/forge/orchestrator/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,11 @@ async def _post_resume_ack_comment(
if source_ticket_key and source_ticket_key != ticket_key
else ""
)
comment_target_key = (
source_ticket_key
if source_ticket_key and source_ticket_key != ticket_key
else ticket_key
)

if signal_type == "question":
message = (
Expand All @@ -1292,11 +1297,11 @@ async def _post_resume_ack_comment(
try:
jira = JiraClient()
try:
await post_status_comment(jira, ticket_key, message)
await post_status_comment(jira, comment_target_key, message)
finally:
await jira.close()
except Exception as e:
logger.warning(f"Failed to post resume acknowledgement to {ticket_key}: {e}")
logger.warning(f"Failed to post resume acknowledgement to {comment_target_key}: {e}")

@staticmethod
def _stage_label_for_node(current_node: str) -> str:
Expand Down
43 changes: 43 additions & 0 deletions tests/unit/orchestrator/test_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ async def test_question_comment_sets_is_question_flag(
assert result["revision_requested"] is False
assert result["is_paused"] is False
ack_comment_mocks.assert_awaited_once()
assert ack_comment_mocks.await_args.args[1] == "TEST-123"
ack_text = ack_comment_mocks.await_args.args[2]
assert "received your question" in ack_text
assert "the PRD" in ack_text
Expand Down Expand Up @@ -135,6 +136,7 @@ async def test_normal_feedback_still_works(
assert result["feedback_comment"] == "Please add more detail to the security section"
assert result["is_paused"] is False
ack_comment_mocks.assert_awaited_once()
assert ack_comment_mocks.await_args.args[1] == "TEST-123"
ack_text = ack_comment_mocks.await_args.args[2]
assert "received your revision request" in ack_text
assert "regenerating" in ack_text
Expand Down Expand Up @@ -176,9 +178,50 @@ async def test_task_phase_feedback_from_epic_sets_current_epic_key(
assert result["current_epic_key"] == "TEST-124"
assert result["current_task_key"] is None
ack_comment_mocks.assert_awaited_once()
assert ack_comment_mocks.await_args.args[1] == "TEST-124"
ack_text = ack_comment_mocks.await_args.args[2]
assert "from TEST-124" in ack_text

@pytest.mark.asyncio
async def test_plan_phase_feedback_from_epic_acknowledges_epic(
self,
worker: OrchestratorWorker,
base_message: QueueMessage,
base_state: dict,
ack_comment_mocks,
):
"""Comments on an Epic during plan review are acknowledged on that Epic."""
state = {
**base_state,
"current_node": "plan_approval_gate",
"epic_keys": ["TEST-124"],
}
payload = {
**base_message.payload,
"source_ticket_key": "TEST-124",
"comment": {"body": "!Please revise this epic plan"},
"changelog": {"items": []},
}
message = QueueMessage(
message_id=base_message.message_id,
event_id=base_message.event_id,
source=base_message.source,
event_type="comment_created",
ticket_key=base_message.ticket_key,
payload=payload,
)

result = await worker._handle_resume_event(message, state)

assert result["revision_requested"] is True
assert result["feedback_comment"] == "Please revise this epic plan"
assert result["current_epic_key"] == "TEST-124"
ack_comment_mocks.assert_awaited_once()
assert ack_comment_mocks.await_args.args[1] == "TEST-124"
ack_text = ack_comment_mocks.await_args.args[2]
assert "received your revision request" in ack_text
assert "from TEST-124" in ack_text

@pytest.mark.asyncio
async def test_retry_at_task_approval_gate_clears_stale_epic_and_task_keys(
self,
Expand Down
Loading