fix(supervisor): read reports that outgrew the 8 MiB control-record cap - #69
Open
Huang-404-Q wants to merge 1 commit into
Open
Huang-404-Q wants to merge 1 commit into
Huang-404-Q wants to merge 1 commit into
Conversation
A finished report embeds every round, so a long run can legally exceed the cap that the generic control-record reader enforces. The reader silently returns an empty dict for such files, every lifecycle poller treats that as *no report*, and the failure path then overwrites the real report with a synthetic stub. Add _read_report with the same nofollow-anchored bounded read and a 256 MiB hard ceiling, and use it at the report read sites. The resume task-field fallback keeps the small cap: it only reads the task key, and the owner record and ledger remain the source of truth.
prax211
added a commit
to cogniziocompany/LongHorizon-Harness
that referenced
this pull request
Sep 5, 2026
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
prax211
added a commit
to cogniziocompany/LongHorizon-Harness
that referenced
this pull request
Sep 6, 2026
…MAP-ML#68/AMAP-ML#69 merged, AMAP-ML#62 closed Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
report.jsonembeds the full transcript of every finished round, so a long run (up toMAX_ROUNDS=1000) can legally grow past the 8 MiB control-record cap that the supervisor uses to read JSON status files._read_json(backed bycontrol_bus._read_json_file) silently returns{}for any file larger than 8 MiB — it never reads the bytes and never complains.Every lifecycle poller treats
{}as no report. The consequences:failed("worker exited without a final report"), and_persist_failure_reportsees an empty report and overwrites the real report on disk with a synthetic failed stub — the completion evidence is physically destroyed, unrecoverable.failure_reasonis discarded in favour of the exit-code fallback text.Fix
Add
_read_reportinsupervisor/service.py: the same nofollow-anchored bounded read, with the ceiling raised to a 256 MiB hard cap (still bounded, so a hostile run directory cannot pin a parser on a multi-gigabyte file). Over-cap, missing, or non-dict files still return{}, so the fail-closed behaviour is unchanged for genuinely broken reports.All nine
report.jsonread sites in the lifecycle path switch to_read_report(refresh branches, stop/abort race reconciliation,finalize_attached_run, run listing, historical scan). The one exception is_resume_once's task-field fallback, which only reads thetaskkey while the owner record and ledger remain the authoritative sources — keeping that on the small 8 MiB cap avoids paying for a large JSON parse where the value is never used.Control records (
owner.json,status.json, …) keep the 8 MiB cap; they are small by design and the cap is there deliberately.Tests
New
tests/supervisor/test_oversized_report.py(5 tests, all red on the previous code):completedreport with exit 0 → run classifiedcompleted, nocrash_report.json, report file byte-for-byte untouched (no stub overwrite).failedreport with exit 1 →failure_reasontaken from the report itself, not the exit-code fallback.failed+crash_report.json, confirming the cap is enforced and fail-closed._read_reportunit tests: parses a >8 MiB report; returns{}for a missing path._read_reportunit test: past-cap sparse file returns{}without reading it.