Repository navigation
Release v0.25.0 - #101
Merged
Merged
Release v0.25.0#101
Conversation
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](https://claude.com/claude-code) <!-- This is an auto-generated description by cubic. --> --- ## 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.0` tag and generates `mthds.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 strict `JsonInteger` and `JsonNumber` types, and a `make check-error-registry` gate that fails when the vendored files, the declared version, and the generated module disagree. - `read_answer` reads any answer as a problem: a problem document as received, and HTML pages, empty or non-JSON bodies, and mistyped members under `client.response_unreadable` or the status readings. Success bodies decode from bytes as `Response.json()` does, keeping numbers as written (`10.0` stays a float) and refusing only NaN and Infinity, so a deeply nested or huge-integer output succeeds and non-UTF-8 bytes read as `client.outcome_unknown` on 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 as `client.not_configured` at construction, and an answer whose body cannot be decoded reads as `client.outcome_unknown` on run routes, `client.unreachable` on 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** - `ClientAuthenticationError` becomes `ClientNotConfiguredError`; a 202 or unreadable success on `execute` or `start`, including one with an empty run id, now raises `client.outcome_unknown`, naming the run when the body gives one. - A `/validate` verdict's `validation_errors` become `errors` of `ProblemItem`s; `ProblemDocument` and its lenient member reading are removed in favor of `Problem`, which reads a document as received and keeps undeclared members on `model_extra`. - `BlobUploadError` and the errors of the blob routes now carry a problem too: a runner's refusal reads as `request.invalid`, an object store's page, an unrequested blob named by a `missing_blobs` answer, or an upload target the client cannot send to, by URL or by its headers, as `client.response_unreadable`, and a refused `files` or `data` argument as `client.argument_invalid`; an upload that got no usable answer raises `BlobUploadError` with `client.unreachable` or `client.timeout`. An upload error's message names the blob and target only, never quoting a `missing_blobs` success 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 `PipelexRunner` keeps its own `PipelexRunnerError`. <sup>Written for commit e44e7d2. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/mthds-ai/mthds-python/pull/94?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="View guided diff" src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a> <a href="https://www.cubic.dev/action/auto-fix/pr/mthds-ai/mthds-python/94?returnTo=https%3A%2F%2Fgithub.com%2Fmthds-ai%2Fmthds-python%2Fpull%2F94&source=description" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img alt="Turn on auto-fix" src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MTPBJkbpj7cQMqEfePgfDU
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Release v0.25.0
Bumps version from
0.24.0to0.25.0. Promotesdev→main.Changelog
Added
mthds.protocol.problem.registryis generated from the standard's core error registry8.0.0, vendored byte for byte from the standard'sv8.0.0release invendor/mthds-error-registry/with its source tag and commit, and gives a constant per core code (CoreCode), a typed parameters model per code, reading a number strictly asJsonIntegerandJsonNumber(mthds.protocol.problem.json_types) do, never from a string or a boolean, each code's entry (CORE_CODE_SPECS) and the readings a client falls back on;CORE_ERROR_REGISTRY_VERSIONinmthds.protocol.protocoldeclares the version, andmake check-error-registryfails when the vendored files, the declared version and the generated module disagree.ProblemandProblemItem:mthds.protocol.problem.modelsreads the protocol's problem document as received, its undeclared members onmodel_extra, witheffective_domainandeffective_step_kindreading a value the protocol does not list by the code's family,effective_retryreading an unknown verdict asno,is_retryabletrue only for a retry ofyes,outcome_is_unknown,params_asto read the parameters as the code's model, and each fault oferrorsand itssuggested_fixtyped;make_client_probleminmthds.protocol.problem.client_problemsstates a client's own problem from the registry.Changed
8.0.0and Protocol2.0.0(Breaking):MTHDS_STANDARD_VERSIONmoved from7.0.0to8.0.0andPROTOCOL_VERSIONfrom1.0.0to2.0.0, the release of the standard in which every error is a problem document, so a manifest'smthds_versionis evaluated against8.0.0, and^7.0.0,~7.0.0,7.*or an exact7.0.0no longer pass.PipelineRequestError(message, *, problem)requires the failure as aProblem, read onexc.problem, and every error this package raises carries one under a registered code: an argument refused before any request leaves, byoptions,method_filesor the client, carriesclient.argument_invalidnaming the argument and the reason, andRunStillRunningError, raised on a202fromexecutethat names its run, carriesclient.follow_failedwith the run as the problem'spipeline_run_id, while a202naming no run raisesApiResponseErrorcarryingclient.outcome_unknown, since the run may exist.BlobUploadError, raised when an upload target refuses a blob, carries the target's own problem document, or else the problem its status names, its message never quoting the target's body, which an object store's refusal such as S3'sSignatureDoesNotMatchfills with the presigned signature and query that grant the write, whileresponse_bodykeeps it whole, and an upload that gets no usable answer raises it too, withstatus,status_textandresponse_bodyNone, carryingclient.unreachableorclient.timeoutas a request that creates nothing does, since a blob's upload is safe to repeat, orclient.response_unreadablewhen the target is malformed, no URL the client can send to or a header it cannot write, such as a value not in ASCII or holding a line break, its headers never quoted, and amissing_blobsanswer naming a blob the request did not list raisesApiResponseErrorcarryingclient.response_unreadable, as any success that is not its route's answer does. A subclass built elsewhere passes a problem to the constructor, and every error, thePipelineRequestErrorthatmake_argument_invalid_errorraises for a refused argument included, endsstr(exc)on the problem's next step, on a line of its own.ApiResponseErrorreads every answer as a problem by its code (Breaking): a failed answer raisesApiResponseErrorcarrying the runtime's problem document, withstatusandretry_afterfilled from the answer when the body leaves them out, and an answer that is no problem document reads asclient.outcome_unknownwhen it is a5xxonexecuteorstart, where a gateway may stand in front of a run that started, as the problem its status names for503on a route that creates nothing and for405on any route, and else asclient.response_unreadable. A success whose body is not the route's answer reads asclient.response_unreadableon a route that creates nothing, and onexecuteorstart, where the runtime accepted the request and the run may exist, asclient.outcome_unknown, naming the run as itspipeline_run_idwhen the body gives the run's id as a non-empty string; anexecuteorstartanswer whosepipeline_run_idis empty names no run, so it reads asclient.outcome_unknownnaming none, as a202onexecutedoes. Neither raises a pydantic or JSON error, andstr(exc)then quotes the start of the body the server sent, except amissing_blobssuccess's, whose upload URLs carry the permission to write and which onlyresponse_bodykeeps. An error body is decoded refusingNaN,Infinity, a number past the range of a double and nesting deeper thanMAX_BODY_NESTING(512 levels, checked before parsing), and reads an integral number such as2.0as the integer2, as a JavaScript client reads it, while a success body is decoded from its bytes asResponse.json()decodes it (decode_success_json): strictly as UTF-8, so that a body that is not UTF-8 is unreadable rather than read with its bytes replaced, refusingNaNandInfinity, and otherwise within Python's own limits, so that a run's output nested deeper or holding an integer past a double's range reads whole and its numbers stay as written, a pipe output's10.0reaching the caller as a float. The memberstype_uri,title,instance,server_message,error_type,error_domain,retryable,user_actionandvalidation_errorsare gone, read fromexc.probleminstead, and so areProblemDocumentandUserAction, whilerequest_idstays, the problem's ownrequest_idmember or else theX-Request-IDheader;mthds.runners.api.problem.read_error_answerreads an answer as anAnswerReading, its problem and whether that problem is the body's own, asmthds.protocol.problem.answers.read_answerdoes, and the protected_raise_api_response_errorreceives the problem andproblem_from_body.ApiTransportError(Breaking): httpx's transport and decoding exceptions no longer escape a route; the request raisesApiTransportError, carryingclient.unreachablewhen no request left,client.timeoutwhen none came back in time, and onexecuteandstartclient.outcome_unknownonce the request has left, since the run may exist. An answer whose body cannot be read, such as one whose content encoding cannot be decoded, is no usable answer either, whatever its status: it raisesApiTransportErrorcarryingclient.outcome_unknownonexecuteandstartandclient.unreachableon any other route, as the TypeScript client reads it. The client never repeats a request by itself.ClientNotConfiguredErrorreplacesClientAuthenticationError(Breaking): the client raises it, aPipelineRequestErrorcarryingclient.not_configuredand the setting, when no API key or base URL resolves at construction, when the API key holds a character an HTTP header cannot carry, such as a line break or a space at its end, which httpx would refuse to write at every request, when the base URL does not make a valid URL or does not start withhttp://orhttps://, or whenrequest_timeout_secondsis set to anything but anintor afloat, never abool, holding a finite number of seconds a float can hold, never negative, each reading as a setting to fix rather than as an unreachable runtime to retry; the key is never quoted, and neither is auser:password@written in the base URL, which this error's message andclient.unreachablename without its userinfo, query and fragment.InvalidValidationReport.errorsreplacesvalidation_errors, each fault aProblemItemwith itscode,detail,params,locationandsuggested_fix, both arms carry advisorywarningsin the same schema, and the invalid arm'smessageis optional; the reports are generic over the item type, andValidationDiagnosticis gone.🤖 Generated with Claude Code
https://claude.ai/code/session_01MTPBJkbpj7cQMqEfePgfDU
Summary by cubic
Promotes
devtomainfor the v0.25.0 release: bumps the version to 0.25.0 and implements the MTHDS standard 8.0.0 and Protocol 2.0.0, in which every error is a problem document. This is a breaking release.Breaking changes
PipelineRequestErrornow requires aproblem; every error this package raises carries one under a registered code.ApiResponseErrorreads any answer as a problem by code; run routes that get a202naming no run, or an unreadable success, raiseclient.outcome_unknown.ApiTransportError(client.unreachable,client.timeout, orclient.outcome_unknown) instead of leaking httpx exceptions.ClientAuthenticationErroris replaced byClientNotConfiguredError, carryingclient.not_configured.validation_errorsbecomeerrorsofProblemItems;ProblemDocumentandUserActionare removed.mthds_versionis now evaluated against8.0.0, so^7.0.0,~7.0.0,7.*, and7.0.0no longer pass.New
mthds.protocol.problem.registry: a constant (CoreCode) and typed parameters model per code, strictJsonInteger/JsonNumberreading, and amake check-error-registrygate that fails when the vendored files, declared version, and generated module disagree.ProblemandProblemItemread documents as received, keeping undeclared members onmodel_extra.BlobUploadErrornow carries problems too: an object store's refusal, an unrequested blob in amissing_blobsanswer, or an upload target the client cannot send to.Written for commit 8b8a905. Summary will update on new commits.