mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(gateway): wire envelope introspection into qa.py + doc.py role mixins
Closes the Task 3 wiring loop: every Envelope construction site in the QA and Documenter mixins now stamps current_state + valid_next_verbs. Refactored doc._check_i_documented_inputs to take the loaded task as a parameter so it can pass through to .with_introspection() without re-fetching. Task 3 of the 2026-05-08 gateway introspection plan is now complete across _impl.py, qa.py, and doc.py.
This commit is contained in:
@@ -45,7 +45,7 @@ class DocMixin(_Base):
|
||||
),
|
||||
remediate="call give_me_work() to find an actionable doc task",
|
||||
context_briefing=await self._briefing_for(doc_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=t, role="documenter"),
|
||||
agent_id=doc_agent_id,
|
||||
task_id=task_id,
|
||||
verb="claim_doc_task",
|
||||
@@ -59,6 +59,7 @@ class DocMixin(_Base):
|
||||
skip_sequence=True,
|
||||
)
|
||||
if guard:
|
||||
guard.with_introspection(task=t, role="documenter")
|
||||
return await self._emit_rejection(
|
||||
self._with_briefing(
|
||||
guard,
|
||||
@@ -94,7 +95,7 @@ class DocMixin(_Base):
|
||||
),
|
||||
evidence=ev.as_dict(),
|
||||
context_briefing=await self._briefing_for(doc_agent_id, task_id),
|
||||
)
|
||||
).with_introspection(task=t, role="documenter")
|
||||
|
||||
async def _verify_doc_owner(
|
||||
self, doc_agent_id: UUID, task_id: UUID
|
||||
@@ -114,7 +115,7 @@ class DocMixin(_Base):
|
||||
message="not assigned to you",
|
||||
remediate="claim it via claim_doc_task(task_id) first",
|
||||
context_briefing=await self._briefing_for(doc_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=t, role="documenter"),
|
||||
agent_id=doc_agent_id,
|
||||
task_id=task_id,
|
||||
verb="i_documented",
|
||||
@@ -122,7 +123,12 @@ class DocMixin(_Base):
|
||||
return None, t
|
||||
|
||||
async def _check_i_documented_inputs(
|
||||
self, doc_agent_id: UUID, task_id: UUID, notes: str, files: list[str]
|
||||
self,
|
||||
doc_agent_id: UUID,
|
||||
task_id: UUID,
|
||||
notes: str,
|
||||
files: list[str],
|
||||
task: Any,
|
||||
) -> Envelope | None:
|
||||
"""Validate notes length + files non-empty. Returns rejection or None."""
|
||||
if not notes or len(notes) < settings.docs_notes_min_chars:
|
||||
@@ -135,7 +141,7 @@ class DocMixin(_Base):
|
||||
" Include each file in `files=...`."
|
||||
),
|
||||
context_briefing=await self._briefing_for(doc_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=task, role="documenter"),
|
||||
agent_id=doc_agent_id,
|
||||
task_id=task_id,
|
||||
verb="i_documented",
|
||||
@@ -149,7 +155,7 @@ class DocMixin(_Base):
|
||||
" listing the doc files written."
|
||||
),
|
||||
context_briefing=await self._briefing_for(doc_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=task, role="documenter"),
|
||||
agent_id=doc_agent_id,
|
||||
task_id=task_id,
|
||||
verb="i_documented",
|
||||
@@ -167,11 +173,11 @@ class DocMixin(_Base):
|
||||
|
||||
Transitions awaiting_documentation → awaiting_pm_review.
|
||||
"""
|
||||
rejection, _ = await self._verify_doc_owner(doc_agent_id, task_id)
|
||||
rejection, owned_task = await self._verify_doc_owner(doc_agent_id, task_id)
|
||||
if rejection is not None:
|
||||
return rejection
|
||||
input_rejection = await self._check_i_documented_inputs(
|
||||
doc_agent_id, task_id, notes, files
|
||||
doc_agent_id, task_id, notes, files, owned_task
|
||||
)
|
||||
if input_rejection is not None:
|
||||
return input_rejection
|
||||
@@ -199,4 +205,4 @@ class DocMixin(_Base):
|
||||
task_id=str(task_id),
|
||||
next="idle until PM completes",
|
||||
context_briefing=await self._briefing_for(doc_agent_id, task_id),
|
||||
)
|
||||
).with_introspection(task=t, role="documenter")
|
||||
|
||||
@@ -55,7 +55,7 @@ class QAMixin(_Base):
|
||||
),
|
||||
remediate="call give_me_work() to find an actionable QA task",
|
||||
context_briefing=await self._briefing_for(qa_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=t, role="qa"),
|
||||
agent_id=qa_agent_id,
|
||||
task_id=task_id,
|
||||
verb="claim_review",
|
||||
@@ -69,6 +69,7 @@ class QAMixin(_Base):
|
||||
skip_sequence=True,
|
||||
)
|
||||
if guard:
|
||||
guard.with_introspection(task=t, role="qa")
|
||||
return await self._emit_rejection(
|
||||
self._with_briefing(
|
||||
guard,
|
||||
@@ -106,7 +107,7 @@ class QAMixin(_Base):
|
||||
),
|
||||
evidence=ev.as_dict(),
|
||||
context_briefing=await self._briefing_for(qa_agent_id, task_id),
|
||||
)
|
||||
).with_introspection(task=t, role="qa")
|
||||
|
||||
async def _verify_qa_owner(
|
||||
self, qa_agent_id: UUID, task_id: UUID, verb: str
|
||||
@@ -126,7 +127,7 @@ class QAMixin(_Base):
|
||||
message="not assigned to you",
|
||||
remediate="claim it via claim_review(task_id) first",
|
||||
context_briefing=await self._briefing_for(qa_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=t, role="qa"),
|
||||
agent_id=qa_agent_id,
|
||||
task_id=task_id,
|
||||
verb=verb,
|
||||
@@ -150,7 +151,7 @@ class QAMixin(_Base):
|
||||
missing,
|
||||
task_id,
|
||||
await self._briefing_for(qa_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=t, role="qa"),
|
||||
agent_id=qa_agent_id,
|
||||
task_id=task_id,
|
||||
verb=verb,
|
||||
@@ -186,7 +187,7 @@ class QAMixin(_Base):
|
||||
task_id=str(task_id),
|
||||
next="idle until next QA work arrives",
|
||||
context_briefing=await self._briefing_for(qa_agent_id, task_id),
|
||||
)
|
||||
).with_introspection(task=t, role="qa")
|
||||
|
||||
@staticmethod
|
||||
def _check_qa_pass_gates(
|
||||
@@ -240,7 +241,7 @@ class QAMixin(_Base):
|
||||
message="fail_review requires at least one issue",
|
||||
remediate="pass issues=['<concrete actionable issue>', ...]",
|
||||
context_briefing=await self._briefing_for(qa_agent_id, task_id),
|
||||
),
|
||||
).with_introspection(task=t, role="qa"),
|
||||
agent_id=qa_agent_id,
|
||||
task_id=task_id,
|
||||
verb="fail_review",
|
||||
@@ -267,4 +268,4 @@ class QAMixin(_Base):
|
||||
task_id=str(task_id),
|
||||
next="idle — dev will revise and re-submit",
|
||||
context_briefing=await self._briefing_for(qa_agent_id, task_id),
|
||||
)
|
||||
).with_introspection(task=t, role="qa")
|
||||
|
||||
Reference in New Issue
Block a user