feat!: align CLI and supported-runtime contracts - #22
Merged
Conversation
`download_original` discarded its temporary on a transport drop, a 404 and an OS error. `httpx.DecodingError` is an `HTTPError` but not a `TransportError`, so a corrupt or truncated compressed stream escaped every handler and left the part-written temporary on disk. The published output stayed correct — promotion is hash-gated — but the litter accumulated across retries. `_paged_search` also called `int(page_token)` unguarded. `nextPage` is an ordinal in every spec version this client targets, so a server answering with an opaque cursor ended a half-finished export with a bare `ValueError` and no statement of what had happened. Both paths now have tests.
BREAKING CHANGE: exit codes have changed. `1` was "unexpected error" and is now
PARTIAL; unexpected failures and unwritable output are both FATAL (4); a partial
run no longer exits 5. Scripts that branch on the old numbers must be updated.
The three fileworks CLIs are driven from the same scripts, so a code has to mean
the same thing in each. It did not: `1` was "unexpected error" here and "partial
success" in `unpacksort`, and `3` and `4` disagreed the same way. `ExitCode`
mirrors `unpacksort.models.ExitOutcome`:
0 SUCCESS · 1 PARTIAL · 2 USAGE · 3 CONFLICT · 4 FATAL · 130 INTERRUPTED
Ctrl-C now exits 130 instead of falling through as an unexpected error. Tests
assert the names rather than the numbers, so the two cannot drift again.
Also converged onto unpacksort's tooling: `ruff select = ["ALL"]` with a
reviewed ignore list, and pinned dev dependencies so a gate cannot change under
you between two runs of the same commit. Two deliberate blind excepts now carry
their reason at the site. AGENTS.md added, as the sibling repos have.
All three READMEs opened the section with "the same codes mean the same thing …
so one script can drive all three", then gave three different meanings for code
3 — an unreachable Immich server, an unavailable Paperless API, an incompatible
destination journal.
`ExitCode.CONFLICT` is deliberately broader than any of them ("something this
tool depends on is unreachable or in a state it cannot proceed from"), so a
script branching on 3 was never actually misled. What the text got wrong was the
level: the tools share a vocabulary of outcome classes, not identical
conditions. Saying so makes each table's narrower wording read as the tool's
instance of the shared class rather than as a contradiction of the sentence
above it.
"Verified behavior" promised exit code 5 for asset-specific integrity failures. No such code exists: ExitCode runs 0, 1, 2, 3, 4, 130, and cli.py raises PARTIAL (1) when the report carries errors — which test_cli_returns_partial_and_publishes_successes already asserts. The 5 dates from ef1941f and survived the renumbering onto the shared vocabulary, so the one number a script would have been written against was the one number that was wrong. test_release_docs_are_bounded_and_preserve_v003_history asserted the README contained "exit code `5`", which is why the mistake survived: the guard was holding the wrong number in place. The assertion now requires the code the tool actually returns rather than being deleted.
`uv sync --all-extras --dev` was the only one of the three repos' Development blocks that did not pass --locked, so a contributor following this README could silently resolve past uv.lock and get a different tree than CI builds. --all-groups replaces the deprecated --dev spelling; --all-extras is retained for symmetry with paperless-export, which does declare an extra.
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.
Summary
Validation