fix(doctor): undecodable contract bytes are a typed finding, never a traceback - #109
Conversation
…traceback Closes #107. _read_json catches UnicodeDecodeError and reports it as the existing invalid_encoding issue - the same rule _validate_jsonl already applies to ledgers - so loop doctor on a terminal_state.json holding invalid UTF-8 returns ok:false with a typed issue instead of tracebacking (exit 1). read_manifest gains the matching guard, failing safe to {} exactly like its malformed-YAML branch. loop/verdict.py's _terminal_record widens its read guard to include UnicodeDecodeError: that path became REACHABLE the moment doctor_report stopped raising, and the site-agnostic typed-contract test planted in 3e26e91 flips to depending on it - probe-proven (reverting the widen fails exactly that test). TDD red->green; probes P1/P2/P3 (each site reverted) all KILLED, tree restored; extras 1353/18 (+2), pyyaml-only 1256/115 (+2), zero regressions. Touches loop/ - a CODEOWNERS gate-defining path; the ruleset half of ADR 0002 decision 6 is not yet in force (PR #106 body point 2), and this lands under the repo's standing autonomous-merge procedure with the full evidence bar. Claude-Session: https://claude.ai/code/session_01JK76jSm45nHcoRoP1SdxXF
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e6ea1345d6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| except UnicodeDecodeError as exc: | ||
| # Same rule as _validate_jsonl: undecodable bytes fail the file closed | ||
| # with a typed finding, never a traceback out of doctor_report (#107). | ||
| issues.append(ContractIssue("invalid_encoding", f"{path.name}: not valid UTF-8: {exc}", path)) |
There was a problem hiding this comment.
Catch encoding failures during event-store reconciliation
When events.db is present, this catch only protects the first contract-validation pass: doctor_report subsequently calls event_consistency_issues, whose _terminal_desync and _state_divergence reread these files but do not catch UnicodeDecodeError. I reproduced a scaffolded workspace with a valid contract_opened event and an invalid-UTF-8 terminal_state.json; doctor_report still raises a raw traceback from runtime.py:212 instead of returning the new invalid_encoding finding. The reconciliation reads need the same encoding-error handling for event-backed workspaces.
Useful? React with 👍 / 👎.
Closes #107 (found while adjudicating a Slice 4a review advisory).
Three sites, one rule — an errored check fails typed, it never crashes:
_read_json:UnicodeDecodeError→ the existinginvalid_encodingissue (the_validate_jsonlprecedent), soloop doctorreports instead of tracebacking.read_manifest: undecodable bytes fail safe to{}, mirroring its own malformed-YAML branch.loop/verdict.py::_terminal_record: the guard widen that was dead code before this fix becomes the live conversion site once doctor stops raising — the site-agnostic test planted in3e26e91proves it (probe: reverting the widen fails exactly that test).Evidence: TDD red→green; 3 mutation probes KILLED, tree restored byte-identical; extras 1353/18 (+2), pyyaml-only 1256/115 (+2), zero regressions.
Note: touches
loop/, a CODEOWNERS gate-defining path. The ruleset half of ADR 0002 decision 6 is not yet in force (see PR #106 body point 2); this lands under the repo's standing autonomous-merge procedure with the full evidence bar — flag if that should change now.https://claude.ai/code/session_01JK76jSm45nHcoRoP1SdxXF