fix: persist scan data on exit and save partial reports#464
Conversation
…ix#294) Two related fixes for reports not being saved when Strix exits: 1. Call tracer.cleanup() in main.py's finally block before posthog.end() so that run data is always written to disk regardless of whether the atexit handlers registered in cli.py/tui.py fire (they can be skipped on Windows when the asyncio event loop tears down). 2. Replace the strict all-or-nothing validation in finish_actions.py with a graceful fallback: missing fields get the placeholder "[Not provided by model]" so partial reports are saved rather than silently discarded when the LLM omits a section. Co-Authored-By: Octopus <liyuan851277048@icloud.com>
Greptile SummaryThis PR fixes two related data-loss issues: it explicitly calls Confidence Score: 5/5Safe to merge — changes are targeted, idempotency is well-guarded, and the only finding is a trivial redundant Both changes are well-scoped: No files require special attention. Important Files Changed
|
Fixes #294
Problem
Two related issues cause scan reports to be lost when Strix exits:
1.
tracer.cleanup()never called inmain.py'sfinallyblockcli.pyandtui.pyregisteratexit+ signal handlers that calltracer.cleanup(), butmain.py'sfinallyblock only callsposthog.end(). On Windows (whereasyncio.WindowsSelectorEventLoopPolicy()is used), theatexithandlers may not fire reliably when the asyncio event loop tears down, so vulnerability reports and the final scan summary are never written to disk.2. Strict validation in
finish_actions.pysilently discards partial reportsfinish_scanrejects any call where one of the four required fields is empty and returns an error without saving. When the LLM doesn't populate every field, the entire report is dropped — even though vulnerabilities were already saved incrementally viaadd_vulnerability_report().Solution
Fix 1 (
strix/interface/main.py): Calltracer.cleanup()in thefinallyblock beforeposthog.end().cleanup()callssave_run_data(mark_complete=True)which is idempotent (tracks already-saved vuln IDs and the_run_completed_emittedflag), so calling it from both thefinallyblock and anatexithandler is safe.Fix 2 (
strix/tools/finish/finish_actions.py): Replace the all-or-nothing validation with a graceful fallback: missing or empty fields are filled with the placeholder"[Not provided by model]"so partial reports are saved rather than silently discarded.Testing
tracer.cleanup()is idempotent by reviewing_saved_vuln_idsset tracking and_run_completed_emittedflag intracer.py.tests/telemetry/test_tracer.pycallsave_run_data(mark_complete=True)multiple times, confirming the idempotency assumption holds.