fix(kanban): stage review-bound handoff artifacts in request_review

request_review ignored artifacts entirely, so a review-bound card lost every
file its handoff named: the reviewer's complete_task is what runs
_cleanup_workspace over the managed scratch workspace.

Stage declared (explicit artifacts argument or metadata["artifacts"]) and
prose-referenced files into the task's durable attachments dir at the review
handoff, exactly as complete_task already does, carry the staged paths in the
review_requested event payload, and let the gateway notifier upload them (its
guard widens from completed to review_requested). ArtifactPreservationError
still rolls the whole transition back: the task stays running and retryable
with no attachments and no event.
This commit is contained in:
yoyodine-industries
2026-09-12 11:42:36 -04:00
committed by Teknium
parent 2292c64738
commit f3357b5031
6 changed files with 262 additions and 28 deletions
+6 -3
View File
@@ -548,9 +548,12 @@ class _KanbanNotification:
raise RuntimeError(f"adapter send() reported failure: {getattr(_send_res, 'error', None) or 'unknown error'}")
logger.debug("kanban notifier: delivered %s event for %s to %s/%s on board %s",
ev.kind, self.task_id, self.platform_str, sub["chat_id"], self.board_slug)
# Upload artifact paths from the completion payload / legacy result as
# native files. Only on ``completed`` so retries never spam attachments.
if ev.kind == "completed":
# Upload artifact paths from the handoff payload / legacy result as
# native files. Both handoff kinds stage files for exactly this: a
# review-bound card's files exist precisely so the human sees them at
# handoff time. Retry exposure matches ``completed`` (the sub cursor is
# rewound only when a send failed).
if ev.kind in ("completed", "review_requested"):
try:
await self.runner._deliver_kanban_artifacts(
adapter=adapter, chat_id=sub["chat_id"], metadata=metadata,