Skip to content

agent investigate loses the investigation record when stdout closes mid-run #44

Closed

Description

@shipmill-romamo

What happens

With the streaming agent investigate from #39, closing the command's stdout mid-run loses the investigation record. For example, pipe cloudfall agent investigate ... into a reader that exits after the first lines. A decision the model already proposed stays on disk, but no investigation record is saved, and the command exits 0.

Before #39 the same run kept the record. The review of #39 reproduced this both on its branch and on main (#39 (comment)). The maintainer chose to merge #39 first and fix this in a follow-up (#39 (comment)).

Expected

A run cut short still leaves an investigation record, and the exit code says the run didn't finish.

Options raised in the review

  1. When the generator is closed, it returns its record, and the record gets a new status (say stopped) in the investigation record schema. This changes stored state, so it goes through the design gate
  2. No schema change: when the reader goes away, save the record with its current status and exit non-zero

Found in the review of #39.

Activity

  1. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: implement, once #39 merges and the design is settled. Waits on #39 and on your decision in the next comment.

    The streaming code this fixes is on #39's branch, not on main yet, so no fix can branch from main before #39 lands. The fix changes stored state (the investigation record), so it goes through the design gate. No decisions log exists yet.

  2. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    @romamo Decision needed: when the reader closes stdout mid-run, how should agent investigate record the run it couldn't finish?

    1. A new stopped status (recommended): the record is saved as stopped, and the command exits non-zero. Anyone reading why or the record can see the run was cut short. Additive schema value; agent investigate hasn't been released, so no stored record depends on the old set
    2. No schema change: save the record with whatever status it had when the reader went away, and exit non-zero. Smaller, but the saved record may look like a run that is still going or that ended normally

    Reply here with a number or your own answer; shipmill takes this up on the tick after your reply.

  3. romamo commented on Oct 9, 2026

    @romamo
    Collaborator

    1 — a new stopped status: save the record as stopped and exit non-zero

    (decision by @romamo, given in chat; posted by Claude on his behalf)

  4. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: implement, taking up the answer above (option 1), recorded as D-3 in #51. #39 merged (8:13 UTC), so the fix branches from main.

    Plan: when the stream's reader goes away (a closed stdout, or the generator closed), agent investigate saves the investigation record with a new stopped status (additive enum value in agent-investigation.schema.json) and exits non-zero. Decisions already proposed stay on disk as they are. A regression test closes the reader after the first lines and checks the saved record and the exit code.

    #50 also changes investigation.py and the same schema; the same implementer builds both on separate branches.

  5. removed
    needs-decisionA shipmill session asked a question here; waits for a reply
    on Oct 9, 2026
  6. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    PR: #54. When the reader closes stdout mid-run, the investigation is saved as stopped and the command exits 94 INVESTIGATION_STOPPED, with nothing more written to stdout and no traceback on stderr. Trade-offs: treaty gives a streaming handler no say in the exit code once stdout closes, so cloudfall.cli maps treaty's 0/141 to 94 through a process-wide flag; an exit-code hook in treaty would replace that. A run ended by Ctrl-C, SIGTERM or a timeout is now also saved as stopped, and keeps treaty's exit code for that case. If stdout closes exactly while the final record line is written, the record is already saved with its real status but the exit stays 0.

  7. romamo commented on Oct 9, 2026

    @romamo
    Collaborator

    Decision by @romamo, given in chat; posted by Claude on his behalf.

    1. A new stopped status: the record is saved as stopped and the command exits non-zero.

  8. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Correction to the PR comment above: the review of #54 found that a run stopped by Ctrl-C, SIGTERM or a timeout while it waits on the model exits with treaty's code (130 for Ctrl-C) and leaves no record. treaty closes the stream only once the handler's current step returns, and the process exits first. The PR's CHANGELOG entry now says so. Only a reader closing stdout is recorded stopped, which is what D-3 covers.

    One gap the review found, filed separately: if saving the stopped record itself fails, the run still exits 0 (as it did before #54).

  9. added a commit that references this issue on Oct 9, 2026
    1a60ba8
  10. shipmill-romamo commented on Oct 9, 2026

    @shipmill-romamo
    ContributorAuthor

    Released in v0.6.0rc9.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions