Skip to content

Commit 411c64b

Browse files
fix: relax sign-off validation to only block on explicit PENDING/FAIL
Agents that participate but never mention SIGN-OFF: (e.g., Chief Architect doing analysis work) are not reviewers and should not block termination. Only agents that explicitly say SIGN-OFF: PENDING or SIGN-OFF: FAIL will block. This prevents the Coordinator from looping when worker agents complete without reviewer sign-off text. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 89ec3fc commit 411c64b

3 files changed

Lines changed: 54 additions & 12 deletions

File tree

src/processor/src/libs/agent_framework/groupchat_orchestrator.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -427,17 +427,19 @@ def _validate_sign_offs(self, conversation: list[Message]) -> tuple[bool, str]:
427427
and name != self.get_result_generator_name()
428428
]
429429

430-
# Validate sign-offs
430+
# Validate sign-offs — only for agents that explicitly attempted one.
431+
# Agents like Chief Architect may participate without issuing a
432+
# sign-off (they do analysis work, not reviews). We only block
433+
# termination when an agent explicitly said SIGN-OFF: PENDING/FAIL.
431434
missing_or_invalid = []
432435
for agent_name in reviewer_agents:
433436
status = sign_offs.get(agent_name)
434-
if status != "PASS":
435-
if status == "PENDING":
436-
missing_or_invalid.append(f"{agent_name}: PENDING")
437-
elif status == "FAIL":
438-
missing_or_invalid.append(f"{agent_name}: FAIL")
439-
else:
440-
missing_or_invalid.append(f"{agent_name}: missing")
437+
if status == "PENDING":
438+
missing_or_invalid.append(f"{agent_name}: PENDING")
439+
elif status == "FAIL":
440+
missing_or_invalid.append(f"{agent_name}: FAIL")
441+
# If status is None (agent never mentioned SIGN-OFF:), skip —
442+
# not all agents are reviewers.
441443

442444
if missing_or_invalid:
443445
reason = f"Cannot terminate: {', '.join(missing_or_invalid)}. All reviewers must have SIGN-OFF: PASS."

src/processor/src/tests/unit/libs/agent_framework/test_groupchat_orchestrator_internals.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,21 @@ def test_fail_blocks(self):
239239
assert ok is False
240240
assert "FAIL" in reason
241241

242-
def test_missing_blocks(self):
242+
def test_missing_does_not_block(self):
243+
"""Agents that never mention SIGN-OFF: are not reviewers and should not block."""
243244
orch = _make_orch()
244245
msgs = [_Msg(author_name="A", text="some text without signoff")]
245246
ok, reason = orch._validate_sign_offs(msgs)
247+
assert ok is True
248+
assert reason == ""
249+
250+
def test_pending_blocks(self):
251+
"""Agents that explicitly say SIGN-OFF: PENDING should block."""
252+
orch = _make_orch()
253+
msgs = [_Msg(author_name="A", text="SIGN-OFF: PENDING")]
254+
ok, reason = orch._validate_sign_offs(msgs)
246255
assert ok is False
247-
assert "missing" in reason
256+
assert "PENDING" in reason
248257

249258
def test_excludes_coordinator_and_resultgenerator(self):
250259
orch = _make_orch()

src/processor/src/tests/unit/libs/agent_framework/test_groupchat_orchestrator_termination.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,12 @@ async def _run():
6161
asyncio.run(_run())
6262

6363

64-
def test_coordinator_complete_rejected_when_signoffs_missing():
64+
def test_coordinator_complete_accepted_when_no_explicit_signoffs():
65+
"""Agents that never mention SIGN-OFF: are treated as non-reviewers."""
6566
async def _run():
6667
orch = _make_orchestrator()
6768

68-
# Agent participated but never produced a SIGN-OFF.
69+
# Agent participated but never produced a SIGN-OFF — should NOT block.
6970
orch._conversation = [
7071
_Msg(author_name="AKS Expert", text="Reviewed; looks good."),
7172
]
@@ -84,6 +85,36 @@ async def _run():
8485

8586
await orch._complete_agent_response("Coordinator", callback=None)
8687

88+
# No explicit SIGN-OFF: in any message → termination allowed.
89+
assert orch._termination_requested is True
90+
91+
asyncio.run(_run())
92+
93+
94+
def test_coordinator_complete_rejected_when_signoffs_pending():
95+
"""Agents with explicit SIGN-OFF: PENDING should block termination."""
96+
async def _run():
97+
orch = _make_orchestrator()
98+
99+
# Agent participated and said SIGN-OFF: PENDING → should block.
100+
orch._conversation = [
101+
_Msg(author_name="AKS Expert", text="SIGN-OFF: PENDING - need more info"),
102+
]
103+
104+
orch._current_agent_start_time = datetime.now()
105+
orch._current_agent_response = [
106+
json.dumps(
107+
{
108+
"selected_participant": None,
109+
"instruction": "complete",
110+
"finish": False,
111+
"final_message": "done",
112+
}
113+
)
114+
]
115+
116+
await orch._complete_agent_response("Coordinator", callback=None)
117+
87118
assert orch._termination_requested is False
88119

89120
asyncio.run(_run())

0 commit comments

Comments
 (0)