You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
agent investigate exits 0 when saving a stopped investigation fails #56
Found in the review of #54 (#44). When agent investigate streams and the reader closes stdout mid-run, the run saves the investigation as stopped and exits 94 INVESTIGATION_STOPPED. If that save fails (repro: make investigations/ a file instead of a folder, then close the reader after the first line), treaty prints a traceback on stderr and the command exits 0. The stream_stopped flag is never set because the save raised first.
That breaks D-3 (docs/decisions.md): a run that couldn't finish must exit non-zero. Before #54 the same case also exited 0, so this isn't a regression.
Expected
A failed save of the stopped record exits non-zero with no traceback, probably with the code the repo already uses when the investigation store can't be written. Code: sdk/src/cloudfall/app.py, the GeneratorExit handler in agent_investigate.
Triage: implement, once the exit code is settled. Waits on your decision in the next comment.
Confirmed on main (after #54): InvestigationStore.save (sdk/src/cloudfall/investigation.py) lets an OSError from the write escape unwrapped, so it isn't only the stopped path: any run whose record can't be written ends in treaty's HANDLER_CRASHED traceback. In the stopped path the crash happens before stream_stopped is set, so the exit stays 0, which breaks D-3. A fix wraps the write error in the store and maps it in agent_investigate, which needs an exit code (a contract).
@romamo Decision needed: what should agent investigate exit with when it can't write the investigation record?
PRECONDITION, with the store's error naming the folder (recommended): the store's folder isn't writable, the same kind of refusal the repo already gives for a bad --decisions folder; for a stopped run, the record is lost but the exit is non-zero, as D-3 asks
A new exit code (say 95 RECORD_UNWRITABLE): a script can tell "couldn't save" apart from other preconditions, at the cost of one more code to document
Keep the stopped run's 94 even when its save fails, and use 1 for the rest
Reply here with a number or your own answer; shipmill takes this up on the tick after your reply.
Triage: implement, with the answer above (option 1), recorded as D-5 in #59.
Design:
InvestigationStore.save (sdk/src/cloudfall/investigation.py) wraps an OSError from the write in the store's own error, naming the investigations folder
agent_investigate (sdk/src/cloudfall/app.py) maps that error to PRECONDITION, with no traceback, on every path that saves: the normal end, the GeneratorExit (stopped) path, and any other save
A stopped run whose save fails exits PRECONDITION instead of 0; its record is lost, as the answer accepts
PR: #61. InvestigationStore.save raises InvestigationError (agent_investigations_unwritable, naming the folder) when it can't create the folder or write the record, and agent investigate exits 4 PRECONDITION with no traceback. On the stopped path, treaty would print a raised error as a traceback and exit 0, so the handler keeps the error and cloudfall.cli writes it to stderr as one JSON line and exits 4. Trade-off: that stopped run's record is lost, as D-5 accepts.
Activity
shipmill-romamo commentedon Oct 9, 2026
Triage: implement, once the exit code is settled. Waits on your decision in the next comment.
Confirmed on
main(after #54):InvestigationStore.save(sdk/src/cloudfall/investigation.py) lets anOSErrorfrom the write escape unwrapped, so it isn't only the stopped path: any run whose record can't be written ends in treaty'sHANDLER_CRASHEDtraceback. In the stopped path the crash happens beforestream_stoppedis set, so the exit stays 0, which breaks D-3. A fix wraps the write error in the store and maps it inagent_investigate, which needs an exit code (a contract).shipmill-romamo commentedon Oct 9, 2026
@romamo Decision needed: what should
agent investigateexit with when it can't write the investigation record?PRECONDITION, with the store's error naming the folder (recommended): the store's folder isn't writable, the same kind of refusal the repo already gives for a bad--decisionsfolder; for a stopped run, the record is lost but the exit is non-zero, as D-3 asksRECORD_UNWRITABLE): a script can tell "couldn't save" apart from other preconditions, at the cost of one more code to documentReply here with a number or your own answer; shipmill takes this up on the tick after your reply.
romamo commentedon Oct 9, 2026
1 — exit
PRECONDITION, with the store's error naming the folder(decision by @romamo, given in chat; posted by Claude on his behalf)
shipmill-romamo commentedon Oct 9, 2026
Triage: implement, with the answer above (option 1), recorded as D-5 in #59.
Design:
InvestigationStore.save(sdk/src/cloudfall/investigation.py) wraps anOSErrorfrom the write in the store's own error, naming the investigations folderagent_investigate(sdk/src/cloudfall/app.py) maps that error toPRECONDITION, with no traceback, on every path that saves: the normal end, theGeneratorExit(stopped) path, and any other savePRECONDITIONinstead of 0; its record is lost, as the answer acceptsA PR follows.
shipmill-romamo commentedon Oct 9, 2026
PR: #61.
InvestigationStore.saveraisesInvestigationError(agent_investigations_unwritable, naming the folder) when it can't create the folder or write the record, andagent investigateexits 4PRECONDITIONwith no traceback. On the stopped path, treaty would print a raised error as a traceback and exit 0, so the handler keeps the error andcloudfall.cliwrites it to stderr as one JSON line and exits 4. Trade-off: that stopped run's record is lost, as D-5 accepts.Merge pull request #59 from cloudfall-dev/docs/decisions-56-57-58
shipmill-romamo commentedon Oct 9, 2026
Released in v0.6.0rc10.