Skip to content

🤖 fix: best-of grouped finalization can ship a report artifact a fast sibling continuation already replaced #4074

Description

@ibetitsmike

Summary

Follow-up from Codex on #4058 (round 23, P1), filed rather than fixed there under Mike's stopping rule for that PR (best-of orchestration is outside that PR's startup/shutdown thesis).

TaskService.buildBestOfCompletedTaskToolOutput (src/node/services/taskService.ts around line 12813 on b795316c1e) reads every sibling's report artifact, then re-checks that no non-reporting sibling is executing again (isBestOfSiblingExecutingAgain) before assembling the grouped task-tool output. Codex:

When a sibling continuation starts after its old artifact was read and finishes quickly enough to write a replacement before this final pass, the sibling is no longer executing or streaming, so this check succeeds and the parent is permanently finalized with the old report already stored in reports. [...] the second pass samples only current activity and never verifies that each artifact is still the revision that was read; compare/re-read artifact identities or serialize assembly with sibling continuation completion.

Suggested direction

Either re-read each artifact after the activity check and compare a revision marker (nowMs/persistedAtMs from upsertSubagentReportArtifact) with the one first read, or take the per-child report lock (or deferredBestOfLocks) around the whole assembly so a continuation's report write cannot interleave with it.


Generated with xum • Model: anthropic:claude-fable-5-1 • Thinking: xhigh • Cost: $202.20

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions