feature/Python-problem-by-code · L-261015-339eba
mthds-python vendors the MTHDS core error registry's snapshot, generates its codes, parameters models and constants from it, and reads every runtime answer as a problem document by code, so MthdsAPIClient raises one coded problem for every failure, including the answers that are no problem document and the transport failures. It agrees with the TypeScript twin on a shared case file of answers and their readings, and records the breaking changes in the changelog.
Closes L-261015-339eba
🤖 Generated with Claude Code
Summary by cubic
mthds now implements MTHDS standard 8.0.0 and protocol 2.0.0, vendors the core error registry from the v8.0.0 release, and reads every request failure as a problem document by code, so MthdsAPIClient raises PipelineRequestError subclasses that always carry a problem.
New Features
- Vendors the core error registry 8.0.0 byte for byte from the standard's
v8.0.0tag and generatesmthds.protocol.problem.registry: a constant per core code, a typed parameters model per code, each code's entry with its fallback family and status readings, the strictJsonIntegerandJsonNumbertypes, and amake check-error-registrygate that fails when the vendored files, the declared version, and the generated module disagree. read_answerreads any answer as a problem: a problem document as received, and HTML pages, empty or non-JSON bodies, and mistyped members underclient.response_unreadableor the status readings. Success bodies decode from bytes asResponse.json()does, keeping numbers as written (10.0stays a float) and refusing only NaN and Infinity, so a deeply nested or huge-integer output succeeds and non-UTF-8 bytes read asclient.outcome_unknownon run routes.- Client-state failures (
client.argument_invalid,client.unreachable,client.timeout,client.outcome_unknown,client.not_configured) are built from the registry with their parameters filled in; a base URL or API key HTTP cannot carry, or a time limit that is no finite number of seconds, is refused asclient.not_configuredat construction, and an answer whose body cannot be decoded reads asclient.outcome_unknownon run routes,client.unreachableon the others. - The client's answers are pinned against a shared case file that the TypeScript twin also reads, which the merge from dev extended to the blob and files routes.
Breaking changes
ClientAuthenticationErrorbecomesClientNotConfiguredError; a 202 or unreadable success onexecuteorstart, including one with an empty run id, now raisesclient.outcome_unknown, naming the run when the body gives one.- A
/validateverdict'svalidation_errorsbecomeerrorsofProblemItems;ProblemDocumentand its lenient member reading are removed in favor ofProblem, which reads a document as received and keeps undeclared members onmodel_extra. BlobUploadErrorand the errors of the blob routes now carry a problem too: a runner's refusal reads asrequest.invalid, an object store's page, an unrequested blob named by amissing_blobsanswer, or an upload target the client cannot send to, by URL or by its headers, asclient.response_unreadable, and a refusedfilesordataargument asclient.argument_invalid; an upload that got no usable answer raisesBlobUploadErrorwithclient.unreachableorclient.timeout. An upload error's message names the blob and target only, never quoting amissing_blobssuccess or an object store's refusal, since their bodies and URLs can carry the permission to write.- Base URLs are written into problems and messages without their userinfo, query, or fragment.
- Only the API runner raises these problem-carrying errors; the local
PipelexRunnerkeeps its ownPipelexRunnerError.