fix(cli): split permanent identifier failures out of exit 3 (WI-P1)#96
Merged
Conversation
Two defects on the same path.
First, unwrap.py raised ParseFailureError without importing it — a third
import-loss regression from the 0.2.3 file-split refactor, still live in
0.2.4 and therefore in the published PyPI latest. Every unwrap failure
produced a NameError traceback instead of the JSON envelope the CLI
contract promises. Restore the import and pin it with a test.
Second, a nonexistent identifier exited 3 with "일시적 … 잠시 후 재시도"
discipline. law.go.kr answers a detail lookup for a bad identifier with an
empty body ({} on eflawjosub), which is a permanent fact about the
identifier — telling the caller to retry sent it into a loop that could
never succeed, and "법령 부재 아님" actively misled it. Classify the empty
body as NoResultError so it emits no_result (exit 4) and steers to
search-*. The empty test is deliberately conservative: a payload we merely
failed to recognize still raises ParseFailureError rather than being
mislabeled a missing record.
exit 3 now carries two kinds and the catalog says so: source_access_error
is the genuinely transient one worth retrying, parse_error is an
unrecognized shape where a retry changes nothing.
Verified live: get-article --law 999999 제3조 → exit 4; a simulated DNS
failure → exit 3 source_access_error.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 19, 2026
Merged
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
exit 3conflated two unrelated situations, and one of them could not produce an envelope at all.1. Missing import — a third 0.2.3 refactor regression, live in 0.2.4.
_normalization/unwrap.pyraisesParseFailureErrorbut the file-split refactor dropped it from the imports. Every unwrap failure hard-crashed with aNameErrortraceback instead of the JSON envelope the CLI contract promises. This is the same class as 50169cf and 41bcd43 and it shipped to PyPI in 0.2.4.2. Bad identifiers were sold as transient failures.
law.go.kr answers a detail lookup for a nonexistent identifier with an empty body (
{}oneflawjosub) rather than the일치하는 …sentence it returns ontarget=law. That empty body becameparse_error→ exit 3, whose discipline read일시적 소스 접근 실패 … 잠시 후 재시도— advice for a lookup that can never succeed, with법령 부재 아님steering the caller away from the actual cause.How
ParseFailureErrorimport; pin it with a test that fails on aNameError.NoResultError→no_result(exit 4), with discipline that says a retry is pointless and points atsearch-*.is_empty_payloadis deliberately conservative — only blank scalars and empty containers count, so an unrecognized-but-populated shape still raisesParseFailureErrorrather than being mislabeled a missing record.parse_errorat exit 3 but drop the transient story: retrying an unrecognized shape changes nothing, so the discipline now says to rule out an identifier error first.constants.pynow state that exit 3 carries two kinds and which one is worth retrying.Verification
get-article --law 999999 제3조→ exit 4,no_result, no "일시 장애" narrative (live).source_access_error, retry discipline intact (live).🤖 Generated with Claude Code