@pipelex/sdk 0.46.1 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +20 -9
  2. package/dist/cli/script.d.ts +1 -1
  3. package/dist/cli/source.d.ts +8 -7
  4. package/dist/cli/source.js +11 -5
  5. package/dist/cli/source.js.map +1 -1
  6. package/dist/client.d.ts +455 -237
  7. package/dist/client.js +1067 -522
  8. package/dist/client.js.map +1 -1
  9. package/dist/errors.d.ts +49 -19
  10. package/dist/errors.js +50 -21
  11. package/dist/errors.js.map +1 -1
  12. package/dist/hooks/bundle-gather.d.ts +28 -40
  13. package/dist/hooks/bundle-gather.js +55 -230
  14. package/dist/hooks/bundle-gather.js.map +1 -1
  15. package/dist/hooks/claude-mthds-check.d.ts +7 -5
  16. package/dist/hooks/claude-mthds-check.js +8 -53
  17. package/dist/hooks/claude-mthds-check.js.map +1 -1
  18. package/dist/hooks/validate-stage.d.ts +27 -0
  19. package/dist/hooks/validate-stage.js +57 -0
  20. package/dist/hooks/validate-stage.js.map +1 -0
  21. package/dist/index.d.ts +7 -7
  22. package/dist/index.js +6 -3
  23. package/dist/index.js.map +1 -1
  24. package/dist/method-trees.d.ts +344 -0
  25. package/dist/method-trees.js +876 -0
  26. package/dist/method-trees.js.map +1 -0
  27. package/dist/models.d.ts +162 -59
  28. package/dist/prepare-inputs.d.ts +46 -27
  29. package/dist/prepare-inputs.js +123 -42
  30. package/dist/prepare-inputs.js.map +1 -1
  31. package/dist/product-models.d.ts +97 -75
  32. package/dist/runs.d.ts +5 -3
  33. package/dist/runs.js.map +1 -1
  34. package/dist/version.d.ts +1 -1
  35. package/dist/version.js +1 -1
  36. package/docs/architecture.md +20 -21
  37. package/docs/cli.md +1 -1
  38. package/docs/crate-routes.md +42 -20
  39. package/docs/errors.md +7 -6
  40. package/docs/hook-bundle.md +1 -1
  41. package/docs/input-preparation.md +15 -40
  42. package/docs/method-trees.md +199 -0
  43. package/docs/run-results.md +5 -2
  44. package/package.json +2 -2
  45. package/dist/bundle-resources.d.ts +0 -62
  46. package/dist/bundle-resources.js +0 -165
  47. package/dist/bundle-resources.js.map +0 -1
  48. package/dist/method-source.d.ts +0 -19
  49. package/dist/method-source.js +0 -50
  50. package/dist/method-source.js.map +0 -1
  51. package/docs/bundle-resources.md +0 -107
package/dist/runs.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"runs.js","sourceRoot":"","sources":["../src/runs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runs.js","sourceRoot":"","sources":["../src/runs.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -3,4 +3,4 @@
3
3
  * `User-Agent` without importing the public barrel. Kept in sync with
4
4
  * `package.json` — enforced by `tests/index.test.ts`.
5
5
  */
6
- export declare const SDK_VERSION = "0.46.1";
6
+ export declare const SDK_VERSION = "0.48.0";
package/dist/version.js CHANGED
@@ -3,5 +3,5 @@
3
3
  * `User-Agent` without importing the public barrel. Kept in sync with
4
4
  * `package.json` — enforced by `tests/index.test.ts`.
5
5
  */
6
- export const SDK_VERSION = "0.46.1";
6
+ export const SDK_VERSION = "0.48.0";
7
7
  //# sourceMappingURL=version.js.map
@@ -57,18 +57,18 @@ The ruling is about the artifacts, not about one envelope: `RunResults` carries
57
57
 
58
58
  ### Run sources
59
59
 
60
- A run request carries its method inline exactly one of three ways: `mthds_contents` text, a `files` bundle map, or a `bundle_b64` zip. Those three are *encodings* of a bundle the caller ships, and they are mutually exclusive. Two selectors sit beside them on separate axes: the Pipelex-API `method_ref` (an address the RUNNER resolves by git fetch — a complete run source that pairs with nothing; see [Pipelex API run extensions](#pipelex-api-run-extensions-method_ref) below) and the hosted `method_id` (a catalog id the PLATFORM resolves — legal on its own, and legal alongside one inline encoding, where the inline source runs and the id rides along as run-history linkage; see [Hosted run extensions](#hosted-run-extensions-method_id) below). The rules — and crucially, _where they live_ — are:
60
+ A run request carries its method as its **tree**, the MTHDS protocol's one method source, given in exactly one of four forms: `files` (the protocol's map from tree path to file entry, posted as given), `tree` (the protocol's listed `MethodTreeSource`), and the client's own `directory` (a directory on disk, listed by the `mthds` package's lister) and `contents` (each file's bytes or text by tree path). The last three are sent inline or by hash by the `mthds` package's rule ([method-trees.md](./method-trees.md#how-a-tree-travels)), so whatever the form, the wire carries one `files` map. Two selectors sit beside the tree on separate axes: the Pipelex-API `method_ref` (an address the RUNNER resolves by git fetch — a complete run source that pairs with nothing; see [Pipelex API run extensions](#pipelex-api-run-extensions-method_ref) below) and the hosted `method_id` (a catalog id the PLATFORM resolves — legal on its own, and legal alongside the tree, where the tree runs and the id rides along as run-history linkage; see [Hosted run extensions](#hosted-run-extensions-method_id) below). The rules — and crucially, _where they live_ — are:
61
61
 
62
- - **Exclusivity is enforced from the standard, not restated here.** `assertExclusiveRunSources` and `hasBundlePayload` are imported from `mthds/protocol`; they are pure predicates over `RunRequest`, so this client and the MTHDS runners cannot drift on which combinations they reject. A second local copy would be free to disagree about what is legal. The `method_ref` pairings (`assertMethodRefPairsWithNothing` in `client.ts`) and the linkage form's bare `method_id` (`assertLinkageMethodIdIsBare`) are the local additions, because the protocol knows neither field — the wording of the `method_ref` errors mirrors the server's own validator.
63
- - **Exclusivity keys off presence, the run-source precondition keys off runnability.** Supplying `files: {}` _and_ `bundle_b64` is rejected — the caller expressed two encodings — while an empty encoding on its own carries no method and so is neither shipped on the wire nor counted as "something to run".
64
- - **`files` / `bundle_b64` / `bundleMain` / `method_ref` / `method_id` are reserved keys on `extra`.** `extra` merges last into the body, so smuggling a run source through it would overwrite the validated fields and bypass the exclusivity check; `buildExtensions` rejects any reserved key — the named run sources, the two method selectors, _and_ the client-only `bundleMain` hint. `buildExtensions` also strips prototype-pollution keys (`__proto__` / `constructor` / `prototype`), which `JSON.parse`-sourced `extra` can carry, so the client never emits a pollution gadget on the wire.
65
- - **`bundleMain` is client-only and never serialized.** It is an entrypoint hint for a _local_ runner; the request builders name wire fields explicitly, and it is reserved on `extra`, so it cannot leak onto the wire by either path.
62
+ - **The tree's own rule is the standard's, not restated here.** `assertOneMethodSource` is imported from `mthds/protocol` and applied to `files` and `tree` on every run and on `validate`, so this client and the MTHDS runners cannot drift on which combinations they reject: both at once, or either holding no file, is refused. A second local copy would be free to disagree about what is legal. The client adds the refusals of its own two forms (two forms at once, `contents` holding no file), the `method_ref` pairings (`assertMethodRefPairsWithNothing` in `client.ts`) and the linkage form's bare `method_id` (`assertLinkageMethodIdIsBare`), because the protocol knows none of them — the wording of the `method_ref` errors mirrors the server's own validator.
63
+ - **An empty `directory` and a `null` member are absent; an empty map is not.** `directory: ""` names no directory and counts as no form, while `files: {}` or `contents: {}` is refused, as the standard refuses a tree holding no file, rather than read as "nothing to run".
64
+ - **`files` / `tree` / `directory` / `contents` / `bundleMain` / `method_ref` / `method_id` are reserved keys on `extra`.** `extra` merges last into the body, so smuggling a run source through it would overwrite the validated fields and bypass the exclusivity check; `buildExtensions` rejects any reserved key — the protocol's own fields, the client's tree forms, the two method selectors, _and_ the client-only `bundleMain` hint. A field this client no longer names, such as a runner's legacy `mthds_contents`, is not reserved, and passes through `extra` to a runner that still reads it. `buildExtensions` also strips prototype-pollution keys (`__proto__` / `constructor` / `prototype`), which `JSON.parse`-sourced `extra` can carry, so the client never emits a pollution gadget on the wire.
65
+ - **`bundleMain`, `directory` and `contents` are client-only and never serialized as such.** `bundleMain` is an entrypoint hint for a _local_ runner, and the two tree forms become the wire's `files`; the request builders name wire fields explicitly, and each is reserved on `extra`, so none can leak onto the wire by either path.
66
66
 
67
67
  ### Pipelex API run extensions (`method_ref`)
68
68
 
69
69
  `method_ref` is the layer-2 sibling of the hosted `method_id`: a globally resolvable address (`github.com/<owner>/<repo>[/<selector>][@<tag>]`) that any pipelex-api deployment resolves itself — git fetch at the tag, package located by manifest identity — with no catalog anywhere. It lives in its own `PipelexApiRunExtensions` interface rather than in `PipelexHostedRunExtensions`, because the two selectors belong to different layers: an address is meaningful against a bare runner; a catalog id is not. Served by pipelex-api >= 0.21.0; on `api.pipelex.com` availability follows the platform deploy that forwards it.
70
70
 
71
- - **A complete run source, so it pairs with nothing.** The fetched package carries its `.mthds` and its entry pipe. The client rejects `method_ref` beside inline `mthds_contents`, beside a bundle encoding, and beside `method_id` — mirroring the server's 422s, with no linkage exception (an address run has its own provenance and needs no linkage id). `pipe_code` beside it is legal: it overrides the manifest's `main_pipe`.
71
+ - **A complete run source, so it pairs with nothing.** The fetched package carries its `.mthds` and its entry pipe. The client rejects `method_ref` beside the method's tree in any form and beside `method_id`, before any directory is listed or any blob uploaded, — mirroring the server's 422s, with no linkage exception (an address run has its own provenance and needs no linkage id). `pipe_code` beside it is legal: it overrides the manifest's `main_pipe`.
72
72
  - **Provenance comes back typed.** A `method_ref` run's start ack (`PipelexRunResultStart`) and execute result (`PipelexExecuteResult`) carry `method_provenance` — `{address, tag, commit_sha}`, the SHA being what keeps the run explainable when a tag moves.
73
73
  - **It rides the blocking fallback too**, like `method_id` — a bare runner reached through `startAndWaitForResult`'s degrade runs the same fetched package.
74
74
  - **An empty string is treated as absent**, same as `method_id`.
@@ -79,22 +79,21 @@ A run request carries its method inline exactly one of three ways: `mthds_conten
79
79
 
80
80
  - **It is a named option, not an `extra` entry.** Typing its own platform's arguments is the one job a layer-3 client exists to do; `extra` stays the escape hatch for extensions this client does not know about (a third-party server, or a newer version of ours). That split, and the reserved-keys guard that enforces it, are normative for every client in the layered stack: a client types the arguments of the platform it is built for, and only the layer that owns an argument may validate or reject it. It was previously passed as `extra: { method_id }`, which worked but documented nothing and validated nothing.
81
81
  - **The guard is per layer.** `method_id` is reserved on `extra` _here_ and must never become reserved in `mthds` / `mthds-python`: a protocol client talking to another vendor's server has no business rejecting that vendor's arguments.
82
- - **Pure pass-through — nothing is expanded client-side.** The platform resolves the id against the org's catalog. The same posture holds across the tooling routes: `validate` / `resolve` / `codegen` / `pipeIo` take a typed `method_id` the platform resolves server-side (see the surface list below), and so does `prepareInputs`, which composes a `pipeIo` of its own. `getMethodClosure` stays public as the local expansion utility, for a caller that wants a stored method's files in hand or talks to a bare runner, which has no catalog to resolve an id against.
82
+ - **Pure pass-through — nothing is expanded client-side.** The platform resolves the id against the org's catalog. The same posture holds across the tooling routes: `validate` / `resolve` / `codegen` / `pipeIo` take a typed `method_id` the platform resolves server-side (see the surface list below), and so does `prepareInputs`, which composes a `pipeIo` of its own. A caller that wants a stored method's files in hand, or talks to a bare runner, which has no catalog to resolve an id against, reads them with `getMethod` or `getMethodVersion` and writes them to disk with `writeMethodTree` ([method-trees.md](./method-trees.md)).
83
83
  - **Alone it is a run source; alongside an inline source it is linkage.** With no inline source the platform resolves and runs the version the id names. With one, the inline source is what RUNS (precedence) and the id is recorded as run-history linkage on the Run row — the index key `GET /v1/runs?method_id=` queries. Rejecting the combination is not an option: it once orphaned every unsaved-bundle run from its method. The client therefore counts `method_id` towards its "something to run" precondition, and never treats it as an exclusivity violation.
84
84
  - **It rides the blocking fallback too.** `startAndWaitForResult` degrades to `POST /v1/execute` against a runner with no run store, and the selector goes with it — so a bare `pipelex-api` answers a `422` that names the key (its Rule 4 diagnosis: "a hosted-only selector must be sent to the hosted API") instead of the client silently dropping it and running something else.
85
85
  - **An empty string is treated as absent.** `method_id: ""` selects no method and links nothing, so it is not sent and does not satisfy the precondition.
86
- - **It may name a version.** A bare `mt_…` runs the method's latest published version, `mt_…@<n>` the fixed version `n` and `mt_…@draft` its draft; the suffix is part of the string and passes through untouched, on the run routes and the tooling routes alike, since the platform parses it at its edge. On the linkage form, beside an inline source, the id must be bare: the inline source is what runs, so a suffix there would claim a version that did not run. The platform refuses it with a `422`, and `execute` and `start` refuse it first with a `RequestArgumentError`, before anything is sent, counting an inline source only when it reaches the wire: an empty `mthds_contents`, `files: {}` or `bundle_b64: ""` is no source, so a suffixed id beside one runs the version it names. The start ack and the execute response carry `method_version`, the version a `method_id` run runs, so a caller learns which version a bare id ran from the answer that started it. `parseMethodSelector` splits a selector into its bare id and version locally, for a caller that reads the method by its bare id.
86
+ - **It may name a version.** A bare `mt_…` runs the method's latest published version, `mt_…@<n>` the fixed version `n` and `mt_…@draft` its draft; the suffix is part of the string and passes through untouched, on the run routes and the tooling routes alike, since the platform parses it at its edge. On the linkage form, beside an inline source, the id must be bare: the inline source is what runs, so a suffix there would claim a version that did not run. The platform refuses it with a `422`, and `execute` and `start` refuse it first with a `RequestArgumentError`, before anything is sent, counting the tree in any of its forms; an empty `directory` is no tree, so a suffixed id beside one runs the version it names. The start ack and the execute response carry `method_version`, the version a `method_id` run runs, so a caller learns which version a bare id ran from the answer that started it. `parseMethodSelector` splits a selector into its bare id and version locally, for a caller that reads the method by its bare id.
87
87
 
88
88
  ## Module layout
89
89
 
90
90
  Flat `src/` (mirrors `mthds-js`'s `runners/api` flatness — the SDK has one client, so no runner/registry abstraction):
91
91
 
92
92
  - `client.ts` — `PipelexApiClient`: the `request()` pipeline (auth, base URL, timeouts/abort, problem-details parsing) and every route. It implements the standard's `MTHDSProtocol<DictPipeOutput>` for every route but `validate`, so the protocol-execution methods stay shaped like the standard: `validate` answers Pipelex's own verdict, `PipelexValidationResult`, because the hosted plane still sends the verdict that predates the protocol's problem items, where the standard's `ValidationResult` lists them.
93
- - `models.ts` — Dict-serialized concretes (`DictStuff` / `DictWorkingMemory` / `DictPipeOutput` / `DictRunResultExecute`), the `/v1/validate` surface (`PipelexValidationResult`, whose two arms are declared whole rather than as narrowings of the standard's `ValidationResult`, `ValidationErrorItem`, and the `SuggestedFix` / `FixOp` repair vocabulary its items carry — the hosted plane's shapes, which predate the standard's problem items, their operation and safety vocabularies pinned to the standard's by a type-level test, see [errors.md](./errors.md#a-validation-item--validationerroritem)), the tools surface (`Diagnostic` / `LintResponse` / `FormatResponse`), and the crate-route request/response models — the shared `MthdsFileItem` / `CrateRequestBase` / `CrateInvalidReport` vocabulary plus the `/v1/resolve`, `/v1/codegen` and `/v1/pipe-io` shapes built on it, `GeneratedArtifact` among them.
93
+ - `models.ts` — Dict-serialized concretes (`DictStuff` / `DictWorkingMemory` / `DictPipeOutput` / `DictRunResultExecute`), the `/v1/validate` surface (`PipelexValidationResult`, whose two arms are declared whole rather than as narrowings of the standard's `ValidationResult`, `ValidationErrorItem`, and the `SuggestedFix` / `FixOp` repair vocabulary its items carry — the hosted plane's shapes, which predate the standard's problem items, their operation and safety vocabularies pinned to the standard's by a type-level test, see [errors.md](./errors.md#a-validation-item--validationerroritem)), the tools surface (`Diagnostic` / `LintResponse` / `FormatResponse`), and the crate-route request/response models — the shared `CrateRequestBase` / `CrateInvalidReport` vocabulary plus the `/v1/resolve`, `/v1/codegen` and `/v1/pipe-io` shapes built on it, `GeneratedArtifact` among them.
94
94
  - `product-models.ts` — the snake_case wire shapes for the hosted-product management routes (profile, methods catalog, organizations, billing, API keys, onboarding, storage, runs list/detail/update). Each interface models only the fields the product actually consumes — no speculative mirrors.
95
95
  - `error-models.ts` — the error-report wire models: `RunErrorReport`, the runner's `ErrorReport` typed with every field it carries (with `UserAction`, `ProviderErrorMetadata` and `MigrationErrorBlock`), which is the one type for a failed run's report on `RunPublic.error`, `PipelineRun.error`, `RunHistoryItem.error`, the failed arm of `RunResultState` and `RunFailedError.error`; and `ProblemDetails` / `FieldError`, the typed members of a problem document that `ApiResponseError` exposes. Every field is optional and every interface keeps an index signature, because the runner owns the shape and adds fields without asking. It also holds the one function that checks a stored report, the internal `readRunErrorReport`, which every read handing a report back applies: each named field is kept only when it has its declared type, and members the SDK does not name are relayed as sent. It imports the `ValidationErrorItem` type and nothing else. See [errors.md](./errors.md#a-failed-run--runerrorreport).
96
- - `bundle-resources.ts` — the files a bundle's steps read, sent as the request's `resources`: the `BundleResources` and `BundleResourceBytes` types the barrel exports, the runner's path rule (`bundleResourcePathRefusal`) and canonical spelling, and `encodeBundleResources`, which checks every key before it reads any value and turns the bytes into standard base64 through `upload.ts`'s `bytesToBase64`. Internal apart from its types; the hook's bundle gatherer reuses its path rule. See [bundle-resources.md](./bundle-resources.md).
97
- - `method-source.ts` — `methodSourceToContents`, the canonical parser turning a stored method's polymorphic `mthds` source (raw single-bundle text XOR a JSON `{name, content}[]` file array) into a flat list of file contents. A verbatim port of the platform's `method_source_to_contents` so the SDK and runtime read a stored source identically; exported from the barrel and consumed by `getMethodClosure`. See [input-preparation.md](./input-preparation.md#getmethodclosure--the-explicit-expansion-utility).
96
+ - `method-trees.ts` — a saved method's tree on the client side: `MethodTreeSource`, the shape a save reads a tree from, which the `mthds` package's `MethodTree` satisfies; the choice between sending a tree inline and by hash (`INLINE_TREE_MAX_BYTES`), the wire types of `POST /v1/blobs/missing` and the upload of a blob the platform lacks; `redactSignedLinks`, which every error built from an answer holding signed links reads its body through; the tree of an in-memory map; the tree limits a version handshake announces; the listing of a `directory`, which loads the `mthds` package's root entry, and with it Node's file system, by a dynamic `import("mthds")` only when a directory is given; and the Node-only write of a saved listing to disk, whose Node modules it loads when called. It is the one module that reaches past `mthds/protocol`, and only by that dynamic import, which `dependency-cruiser` holds it to. Its tree-sending half mirrors the `mthds` package's own helpers, which the `mthds/protocol` subpath does not export yet, so it holds the same rules with Web Crypto's SHA-256 and a Base64 writer of its own. See [method-trees.md](./method-trees.md).
98
97
  - `codegen-check.ts` — `runCodegenCheck`, the **pure** offline drift check over a committed codegen tree: the stamp grammar, the `codegen.lock` parser, the hash, and the drift taxonomy, ported from pipelex's `codegen/check.py` so a verdict computed here equals the one `pipelex codegen check` computes over the same bytes (the drift `detail` sentences included, verbatim). It touches neither the client nor `mthds/protocol` — its only runtime imports are `smol-toml` and the plain-object guard of the pure `error-models.ts` — and it hashes through WebCrypto rather than `node:crypto` so it adds no Node builtin to the barrel's import graph (`upload.ts` still names `node:fs/promises`, so a browser-targeting bundler must mark `node:*` external). It raises `CodegenLockError`, which extends `Error` rather than the protocol base and declares the error verdict itself (`input`, not retryable). No filesystem, no fetch, no API key — the caller walks its own tree and hands in the text. See [crate-routes.md](./crate-routes.md#the-offline-check--runcodegencheck).
99
98
  - `upload-grant.ts` — `uploadWithGrant`, the sender of an upload grant (`requestUploadGrant`, `POST /v1/upload/grant`): the file as the raw body of a `PUT` to the grant's URL with its signed headers unchanged, redirects refused, the whole exchange bounded by a time limit scaled by the file's size unless the caller passes `timeoutMs`, only the first 16 KiB of storage's error body read, and storage's refusals mapped onto the input-preparation errors (`RejectedAssetError` with a `code` for a `4xx` such as the `412` of a used grant or the `403` of a signature mismatch, `UploadTransportError` with a `code` for the time limit running out, a `5xx`, storage's `RequestTimeout`, a `409` conflict, a redirect or no response). It is the browser-safe `@pipelex/sdk/upload` entry, so it imports the error classes, the timer bound in `timers.ts` and the wire types only, never the client. See [input-preparation.md](./input-preparation.md#uploading-with-a-grant--requestuploadgrant--uploadwithgrant).
100
99
  - `artifacts.ts` — the artifact stack, the download twin of `prepareInputs`, in layers: `locateArtifacts` (a pure, exported walk for `pipelex-storage://` references, each with every `$`-rooted path it sits at) and `collectArtifacts` (the same walk's bare references), `resolveArtifacts` (the bulk resolve route over a whole list, chunked at its bound), `fetchArtifact` (one reference as a bounded `Response`) and `downloadArtifacts` (Node-only, a run's produced files saved under a directory as a produced verdict), plus `artifactFilename`, the rule that names a saved file after the field it fills. The three network operations are client methods over a small structural seam (`ArtifactCapableClient`: the raw `resolveStorageUrls` call and `getRunResult`); the module's static import graph stays free of Node builtins, because `node:fs/promises`, `node:path` and `undici` are loaded by dynamic import behind `isNodeRuntime()` — a browser-targeting bundler still has to mark `node:*` and `undici` external, as it already must for `upload.ts`. `undici` is a runtime dependency for one reason: the fetch runs on an `Agent` carrying `headersTimeout` and `bodyTimeout`, the per-stall bounds an `AbortSignal` budget does not give, and Node exposes its bundled undici's `fetch` but not its `Agent`. See [artifact-download.md](./artifact-download.md).
@@ -113,14 +112,14 @@ Flat `src/` (mirrors `mthds-js`'s `runners/api` flatness — the SDK has one cli
113
112
 
114
113
  ## Client surface (current)
115
114
 
116
- - **Protocol execution:** `execute` (returns a `PipelexExecuteResult` with a resolved `.main_stuff`), `start`, `validate` (returns `PipelexValidationResult`), `validateFiles`, `models`, `version`.
115
+ - **Protocol execution:** `execute` (returns a `PipelexExecuteResult` with a resolved `.main_stuff`), `start`, `validate` (returns `PipelexValidationResult`), `models`, `version`.
117
116
  - **Two independent opt-in lists on `validate`.** `render` asks the server to render a *view format* and adds a `rendered_<format>` field; `views` asks for a *structured view* and adds a same-named top-level field — today `input_form` and `output_form`, the per-pipe form descriptors. A caller that wants the forms without the dry-run verdict reads `pipeIo` instead, which derives them with no dry run. Each resolves its own tokens against its own supported set and unknown tokens are lenient-ignored on both, never a `422`. The client always asks for `render: ["markdown"]` but sends `views` only when a caller names a token, because an opt-in view exists precisely so the default response stays byte-identical for the consumers that discard it. `pipelex-api` gates `input_form` on the token as of 0.18.0; a 0.17.0 runner resolved no token and emitted the field on every valid verdict, which is why `PipelexValidationReport.input_form` is typed optional rather than required — the one typing that reads a response from either runner correctly.
118
- - **Method-bundle transport (pipelex-api extension):** `execute` / `start` / the blocking fallback accept the whole method — the `.mthds` plus its `funcs/*.py`, `structures/*.py`, `requirements.txt` — instead of only the inline `mthds_contents` text, so custom PipeFunc Python travels with the method. Two equivalent, mutually exclusive encodings: `files` (a `{ relativePath: text }` map) and `bundle_b64` (the same bundle as a base64 zip). A bundle is self-contained, so it satisfies the "something to run" precondition on its own — neither `pipe_code` nor `mthds_contents` is required beside it. See [run-sources](#run-sources) above.
117
+ - **The method's tree:** `execute` / `start` / `startAndWaitForResult` (both paths) and `validate` take the whole method as its tree — every `.mthds` bundle, its `funcs/*.py`, `structures/*.py` and `requirements.txt`, and every file a step reads, such as a `PipeDocGen` step's template — in one of four forms, `directory`, `contents`, `tree` or `files`, sent inline or by hash. `startAndWaitForResult` prepares the tree once, under its `signal`, before it starts the run, so its fallback to the blocking execute sends the same files without reading or uploading them again. A tree is self-contained, so it satisfies the "something to run" precondition on its own — `pipe_code` is not required beside it. See [run-sources](#run-sources) above and [method-trees.md](./method-trees.md).
119
118
  - **Method selectors on the run methods:** `execute` / `start` / `startAndWaitForResult` take the Pipelex API's `method_ref` (an address the runner resolves; provenance comes back typed as `method_provenance`) and the platform's `method_id` as **typed named options** (`PipelexRunOptions` / `PipelexStartOptions`), never `extra` entries. See [Pipelex API run extensions](#pipelex-api-run-extensions-method_ref) and [hosted run extensions](#hosted-run-extensions-method_id) above.
120
119
  - **An idempotency key on a run start (hosted):** `start` and `startAndWaitForResult` take `idempotencyKey` (`PipelexStartRequestOptions`, intersected into `PipelexStartOptions`), sent as the `Idempotency-Key` header of `POST /v1/start` and never in the body; with no key there is no header. The hosted API binds the key to the run, answers a repeat of the same start with that run, and refuses the key with other options; a bare runner ignores the header. The client refuses a key that is not 1 to 255 visible ASCII characters with a `RequestArgumentError` before any request, the blocking `execute` fallback of `startAndWaitForResult` sends none, and the key leaves the error verdict as it is: a start that may have reached the server stays `runMayHaveStarted`, and the caller who sent a key recovers the run by sending the same start again under it. [errors.md](./errors.md#a-starts-idempotency-key--idempotencykey) holds the contract.
121
- - **Method selectors on `validate`:** the first argument is inline contents (`string[]`) or a `ValidateMethodSelector` — `{ method_ref }` (runner-resolved by address) or `{ method_id }` (hosted, platform-resolved) — under the strict tooling XOR: exactly one selector, no linkage exception, `mthds_sources` legal only beside inline contents. A selector-resolution failure is a non-2xx `ApiResponseError`, never an `is_valid: false` verdict.
122
- - **The files a bundle's steps read (`resources`, pipelex-api extension):** `validate` / `validateFiles` (in their last options argument), `execute` / `start` / `startAndWaitForResult` (both paths), the crate routes and `prepareInputs` (beside inline `files`) take `resources`, the files a `PipeDocGen` step's `template_file` names, keyed by the path the step names, each as its bytes (`Uint8Array`, `ArrayBuffer` or `Blob`), and send them as the wire's base64 map. `bundle-resources.ts` encodes them and refuses, before any request, a key the runner's path rule refuses and two keys for one file; the run routes and `validate` also mirror the runner's pairing refusals (beside a `method_ref`, or with no source on a run), while the crate routes leave theirs to the server, as they do the selector XOR. `resources` is reserved on `extra`, so it cannot bypass those checks. The valid verdict's `warnings` carry the template check's `template_check_warning` items, whose `template_file` and `template_location` `ValidationErrorItem` declares ahead of `mthds`, a difference the type-level pin states. See [bundle-resources.md](./bundle-resources.md).
123
- - **Crate routes (`/v1/resolve`, `/v1/codegen`, `/v1/pipe-io`):** `resolve` emits the **normalized library crate** (the MTHDS standard's Library Crate Format, fingerprint riding inside the payload); `codegen` projects that crate through two explicit axes — `kind` (`types`) × `target` (`ts-zod` / `python-pydantic` / `python-structures`) — into stamped artifacts plus their `codegen.lock`. All three share one closure envelope (`files: [{content, source?}]` XOR a `method_ref`, the address form server-resolved and the registry form a `501`) and return a **discriminated 200 verdict** (`is_valid`, with `CrateInvalidReport` as the shared invalid arm) rather than a bare payload, the same discipline as `validate`. They also take the hosted `method_id` (`PipelexHostedToolingExtensions`) as a third closure form under the strict three-way XOR — a pass-through the platform resolves, meaningless against a bare runner. Writing the artifacts and lock verbatim reproduces a local `pipelex codegen types` run byte-for-byte, so the offline `pipelex codegen check` passes — the SDK stays transport-only and does not write files. Verifying such a tree afterwards is `runCodegenCheck`, a standalone pure helper rather than a client method, because it needs no server at all. `pipeIo` derives a method's three I/O artifacts — the standard's `PipeIOContracts`, `InputForm` and `OutputForm`, imported from `mthds/protocol` — for the pipe the route selects (the request's qualified `pipe_ref`, else the method's own entry pipe) or for every pipe under `all_pipes`, with the runnability facts beside them and the closure's files echoed on `include_files`, and it runs no dry run; a selection it refuses is a `422` typed `EntryPipeNotFoundError` or `EntryPipeAmbiguousError`. See [crate-routes.md](./crate-routes.md).
120
+ - **Method selectors on `validate`:** the first argument is a `PipelexValidateSource` — the method's tree in one of its four forms, `{ method_ref }` (runner-resolved by address) or `{ method_id }` (hosted, platform-resolved) — under the strict tooling XOR: exactly one, no linkage exception, refused with a `RequestArgumentError` before any request. Its options (`ValidateOptions`: `render`, `views`, `timeoutMs`, `signal`) ride the third argument. A selector-resolution failure is a non-2xx `ApiResponseError`, never an `is_valid: false` verdict.
121
+ - **The files a step reads ride the tree.** A `PipeDocGen` step's `template_file` is a file of the method's tree like any other, at the tree path the step names; the separate `resources` field is gone from every route. The valid verdict's `warnings` carry the template check's `template_check_warning` items, whose `template_file` and `template_location` `ValidationErrorItem` declares ahead of `mthds`, a difference the type-level pin states, and its optional `tree_files_read` and `tree_file_readers` name the files of the method's tree each step reads, whatever form the method was sent in ([which step reads which file](./method-trees.md#which-step-reads-which-file)). See [method-trees.md](./method-trees.md#the-files-a-step-reads).
122
+ - **Crate routes (`/v1/resolve`, `/v1/codegen`, `/v1/pipe-io`):** `resolve` emits the **normalized library crate** (the MTHDS standard's Library Crate Format, fingerprint riding inside the payload); `codegen` projects that crate through two explicit axes — `kind` (`types`) × `target` (`ts-zod` / `python-pydantic` / `python-structures`) — into stamped artifacts plus their `codegen.lock`. All three share one closure envelope (the method's tree, in one of the four forms a run takes, XOR a `method_ref`, the address form server-resolved and the registry form a `501`) and return a **discriminated 200 verdict** (`is_valid`, with `CrateInvalidReport` as the shared invalid arm) rather than a bare payload, the same discipline as `validate`. They also take the hosted `method_id` (`PipelexHostedToolingExtensions`) as a third closure form under the strict three-way XOR — a pass-through the platform resolves, meaningless against a bare runner. Writing the artifacts and lock verbatim reproduces a local `pipelex codegen types` run byte-for-byte, so the offline `pipelex codegen check` passes — the SDK stays transport-only and does not write files. Verifying such a tree afterwards is `runCodegenCheck`, a standalone pure helper rather than a client method, because it needs no server at all. `pipeIo` derives a method's three I/O artifacts — the standard's `PipeIOContracts`, `InputForm` and `OutputForm`, imported from `mthds/protocol` — for the pipe the route selects (the request's qualified `pipe_ref`, else the method's own entry pipe) or for every pipe under `all_pipes`, with the runnability facts beside them and the closure's files echoed on `include_files`, and it runs no dry run; a selection it refuses is a `422` typed `EntryPipeNotFoundError` or `EntryPipeAmbiguousError`. See [crate-routes.md](./crate-routes.md).
124
123
  - **Model reference check (`/v1/models/check`):** `checkModelReference(reference, category?)`, a Pipelex API extension served by any `pipelex-api` runner from pipelex 0.78.0 and on the hosted API, whose platform relays it byte-identically. It is a **diagnostic endpoint** like `validate`: a reference that resolves nowhere is a `200` verdict with `resolution: "not_found"` and the names the caller may have meant (`suggestions`, `other_kinds`, `other_categories`), never a thrown error. Only a request that cannot produce a verdict throws `ApiResponseError`, a `422` typed by its `errorType`: `InvalidModelReference` for a reference that is blank, a sigil or a namespace alone, or past the runner's length limit, `InvalidModelCategory` for an unknown `type`, `ValidationError` for a missing or repeated parameter. The SDK validates none of it, so the runner's rule is the only one. `ModelReferenceVerdict` is a union of one arm per reference kind, discriminated on the wire's own `kind` (`PresetReferenceVerdict`, `AliasReferenceVerdict`, `WaterfallReferenceVerdict`, `HandleReferenceVerdict`): a `matches` entry carries no kind of its own, but every entry of one verdict shares the verdict's, so narrowing on `kind` types `matches` as `PresetMatch[]`, `AliasMatch[]`, `WaterfallMatch[]` or `HandleMatch[]` without a field the wire does not carry. `ModelCheckCategory` is the protocol's model categories plus `doc_gen`, the family of `PipeDocGen`, which the protocol and so `models` leave out but a method's `model` field can name. `resolution` is typed open, `ModelReferenceResolution | (string & {})`, under the spec's reader rule that a client reading a value it does not know treats the reference as unresolved, and so is every category a verdict names, `ModelCheckCategory | (string & {})` as `mthds` types `ModelInfo.type`, since a runner of a later version may add one; the `category` a request names stays closed. A match's `resolves_to` is `null` when the reference resolves by name but a run through it would reach no model the runner can call, which a consumer shows as a warning rather than as an unknown name.
125
124
  - **Tools (`/v1/lint`, `/v1/format`):** `lint`, `format` — single-file static diagnostics and canonical formatting, served by any pipelex-api runner (no inference, no bundle load). Both are **diagnostic endpoints** like `validate`: a malformed `.mthds` file is a produced verdict on a **200** carrying `diagnostics[]`, never a thrown error — `format` additionally echoes the content back unchanged with `changed: false`. Only a no-verdict condition is non-2xx: a malformed body, **malformed formatter `options`** (e.g. a non-numeric `column_width` ⇒ 422), auth, or a server fault, all mapped to the typed `ApiResponseError`. `lint` is the cheap static check (syntax / schema / semantic); it does not replace `validate`, which loads the bundle, resolves across files, and dry-runs the pipes.
126
125
  - **Durable run lifecycle (hosted extension — NOT protocol):** `getRunStatus`, `getRunProgress` (`GET /v1/runs/{id}/progress`, the run's progress snapshot, see [run-results.md](./run-results.md#following-a-run-while-it-runs--onprogress-and-getrunprogress)), `getRunResult` (with an optional `artifacts` selection sent as `?artifacts=`, see [run-results.md](./run-results.md#reading-only-some-artifacts--artifacts)), `waitForResult` (whose `onProgress` reads the progress route on each poll that finds the run running and delivers each fresher snapshot by `isFresherRunProgress`, a failed progress read never failing the wait), `startAndWaitForResult` (handshakes `/v1/version`, takes the durable start+poll path on a hosted deployment, and self-heals to the blocking `execute` against a bare runner). The handshake's outcome is cached for the client's lifetime, under the rule the Python SDK follows too: an answer that is not a usable version assumes hosted and lets the start surface the real error, while no answer at all throws its `ApiUnreachableError` at once, caches nothing and sends no start. An answer is anything the server sent back: an error status, a body that is not JSON, not UTF-8 or no version, and a body that arrived but could not be decoded, such as a broken gzip stream, which fetch fails with the decompressor's code (`Z_DATA_ERROR` and the other zlib codes, brotli's `ERR__ERROR_…`, zstd's `ZSTD_error_…`). A run that ended without completing answers the results read with a `409` whose `run_status` and `error` members carry its status and its stored error report; `getRunResult` turns it into the `failed` arm (`status`, `message` from `detail`, `error`) and the waiting calls on the durable path into a `RunFailedError` carrying the same (the blocking fallback's failure is the runner's `ApiResponseError`), the status read from the member, or from the `detail` sentence on a platform that does not send it yet. The status read serves the same report as `RunRead.error`. See [errors.md](./errors.md#a-failed-run--runerrorreport). The status read also carries `degraded` and the `degradation` that explains it, whose `reason` tells a status the platform could not refresh (`status_unavailable`) from a run whose workflow task keeps failing until the platform ends it (`workflow_task_failing`), checked field by field so it never fails the poll, and the run's `request_id`, the id to quote to support. See [run-results.md](./run-results.md#a-degraded-status--degraded-and-degradation). Reading what a completed run consumed is `summarizeUsage(results)`, a standalone pure helper rather than a client method, because it folds the usage pair the results already carry and needs no server. See [run-usage.md](./run-usage.md#summarizing-a-run--summarizeusage).
@@ -128,21 +127,21 @@ Flat `src/` (mirrors `mthds-js`'s `runners/api` flatness — the SDK has one cli
128
127
 
129
128
  ### Product routes (hosted management surface)
130
129
 
131
- The hosted catalog/account routes the webapp drives. All ride the same `{base}/v1/*` + `Authorization: Bearer` + org-from-JWT contract as the protocol routes, go through the shared `requestProduct<T>` helper (30s management timeout, empty-body tolerant), and map a non-2xx RFC 9457 `problem+json` to a typed `ApiResponseError`. Every route parses a 2xx body through one private helper, so an answer that is not JSON (a gateway's HTML page, an empty body where one was due) is an `ApiResponseError` carrying its status and raw text, `runtime` and not retryable, rather than a bare `SyntaxError`. A product route whose answer the SDK or its caller reads before anything else (`listMethods`, `listRuns`, `getRunDetail`, `upload`, `requestUploadGrant`, `resolveStorageUrls`, and the methods routes answering one stored method) goes through `requestProductObject` or a helper built on the same read instead, which also refuses an empty body and JSON that is not an object; the two paged routes then refuse, the same way, through one page reader, a page whose `items` is not an array or whose `next_cursor` is neither a string nor `null`, `upload` an answer with no non-empty string `uri`, and the methods routes a stored `mthds` field that is neither a string nor absent and a stored `python` field that is not the serialized file list. Consumers branch on **`type` and `errorDomain`**, as the hosted-envelope spec (`conformance/specs/pipelex-hosted-envelope.md`, in the `conformance` repository) says, never on the HTTP status. The platform's `type` is `https://pipelex.com/errors/<code>`, one-to-one with its native `code` (`conflict`, `not_found`, `pipelex_api_key_limit_reached`, …), the finer surface-specific code, on which a client of the platform alone may branch as well: the two read the same answer, and a refusal the platform relays from the runner carries the runner's `type` and `errorType` and no `code`. The SDK reads the `error_domain` and `retryable` the server sent first, and where the platform sends none on a refusal it renders itself, as its Lambda-backed routes do not yet, `errorDomain` and `retryable` are the SDK's fallback, read from the status; every error carries both, decided. See [errors.md](./errors.md).
130
+ The hosted catalog/account routes the webapp drives. All ride the same `{base}/v1/*` + `Authorization: Bearer` + org-from-JWT contract as the protocol routes, go through the shared `requestProduct<T>` helper (30s management timeout, empty-body tolerant), and map a non-2xx RFC 9457 `problem+json` to a typed `ApiResponseError`. Every route parses a 2xx body through one private helper, so an answer that is not JSON (a gateway's HTML page, an empty body where one was due) is an `ApiResponseError` carrying its status and raw text, `runtime` and not retryable, rather than a bare `SyntaxError`. A product route whose answer the SDK or its caller reads before anything else (`listMethods`, `listRuns`, `getRunDetail`, `upload`, `requestUploadGrant`, `resolveStorageUrls`, and the methods routes answering one stored method) goes through `requestProductObject` or a helper built on the same read instead, which also refuses an empty body and JSON that is not an object; the two paged routes then refuse, the same way, through one page reader, a page whose `items` is not an array or whose `next_cursor` is neither a string nor `null`, `upload` an answer with no non-empty string `uri`, and `getMethod` and `getMethodVersion` a `files` member that is not a listing of files, each with its string `path`, `sha256`, `url` and `expires_at` and a non-negative integer `size`. Consumers branch on **`type` and `errorDomain`**, as the hosted-envelope spec (`conformance/specs/pipelex-hosted-envelope.md`, in the `conformance` repository) says, never on the HTTP status. The platform's `type` is `https://pipelex.com/errors/<code>`, one-to-one with its native `code` (`conflict`, `not_found`, `pipelex_api_key_limit_reached`, …), the finer surface-specific code, on which a client of the platform alone may branch as well: the two read the same answer, and a refusal the platform relays from the runner carries the runner's `type` and `errorType` and no `code`. The SDK reads the `error_domain` and `retryable` the server sent first, and where the platform sends none on a refusal it renders itself, as its Lambda-backed routes do not yet, `errorDomain` and `retryable` are the SDK's fallback, read from the status; every error carries both, decided. See [errors.md](./errors.md).
132
131
 
133
132
  - **User profile:** `getMe` (`GET /v1/me`).
134
- - **Methods catalog:** `listMethods`, `getMethod`, `createMethod`, `writeDraft`, `renameMethod`, `publishMethod`, `listMethodVersions`, `getMethodVersion`, `deleteMethod`. **A saved method has a draft and immutable published versions.** Its content fields (`mthds`, `python`, `input_data`) are its draft, which `writeDraft` (`PUT /v1/methods/{id}/draft`) replaces without validating it; `updated_at` is the draft's token, which moves on every draft write and nothing else, and `draft_digest` the SHA-256 of its two file sets. A draft write may carry `expected_updated_at`, the token the caller last saw, and is then a compare-and-swap: a draft that moved since is a `409` `method_update_conflict` and nothing is written. `renameMethod` (`PATCH /v1/methods/{id}`) changes the name alone and moves no token. `publishMethod` (`POST /v1/methods/{id}/publish`) takes the required `expected_draft_updated_at` and answers a `MethodPublishResult` discriminated on `outcome` — `published` with the new version, `unchanged` with the existing latest version when the draft's digest equals it, `refused` with a `reason` (`invalid` or `not_runnable`), a `message` and the runner's `validation` verdict — every arm carrying the `method`; the SDK reads the nested method as `getMethod` does, and an answer whose `outcome` is none of these is an answer it cannot read. A publish that produced no verdict is thrown rather than answered: only a draft that differs from the latest version reaches the runner, and a runner that cannot be reached, answers unusably or does not finish within the platform's deadline is a `502` or `503` with nothing written, so a retry is safe, and a retry of a publish that landed while its answer was lost answers `unchanged` with the version it wrote. A method is stored as one item that keeps room for the summary a publish adds, so a draft that saves can always be published: a creation or a draft write is a `413` `payload_too_large` when it would grow the method past that room, below the store's item limit, and a rename is the same `413` for a name so long it would leave the method too large to publish. A version is numbered from 1, never reused, and holds the draft's files as they stood, its `source_digest`, its `crate_fingerprint` (`null` when the runner could not resolve the bundle in memory), the runner's version, and when and by whom it was published; `listMethodVersions` pages the summaries newest first (`MethodVersionPage`, `{items, nextCursor}`, a `limit` from 1 to 100, 20 by default, and a `422` outside that range), and `getMethodVersion` reads one with its sources, its `python` parsed as a method's is. A method read carries `latest_version` and `latest_published`, both `null` until the first publish, so the publish state is derived: never published, draft unchanged (`draft_digest === latest_published.source_digest`), or draft ahead. The method routes take a bare id and address the method itself, never one of its versions; the platform does not parse a suffix there, so `mt_x@3` would answer a `404` that reads as a method that does not exist, and each route refuses a suffixed id with `RequestArgumentError` before anything is sent, naming `parseMethodSelector` and `getMethodVersion`. The whole-method `updateMethod` is gone, replaced by the draft write and the rename. **`deleteMethod` is asynchronous and its return type says so:** `DELETE /v1/methods/{id}` answers `202` with a `MethodDeletionAccepted` (`method_id`, `deletion_state`, `deletion_job_id`) the moment the platform has claimed the method and terminated its in-flight workflows — the rest of the cascade (runs, events, S3 objects) is enqueued. A resolved promise means "accepted", never "gone"; completion is the row disappearing from `listMethods`, not any field of that body. The claim is a conditional write, so a double-clicked delete is a `409 method_being_deleted` rather than a second cascade over the same runs, and an unknown or foreign-org id is a `404`. The erasure deletes the method's versions with the rest. (This doc previously stated the SDK had no `delete` because the platform had no such route — the route has always existed; the claim was simply false.) `listMethods` returns **one page**, not the whole catalog — a `MethodPage` (`{items, nextCursor}`) served from a narrow index projection, so its cost is the page size rather than the size of the catalog. It used to return every method with its full `.mthds` bundle attached, which hit DynamoDB's 1 MB page cap at a couple hundred methods and came back truncated with no error and no flag, so methods silently vanished from the UI. Rows are therefore `MethodSummary`, **not** `MethodData`: no `mthds`, no `python`, no `updated_at`, because none of them is in the projection and putting `mthds` back is what restored the truncation. Reach for `getMethod(id)` when you need a method's source. `query.q` is applied server-side across the whole catalog, not over the page — filtering one page client-side would be searching 50 rows of 10,000 and calling it a search. `query.published` filters the same way, sent as `published=true` (the methods with a published version) or `published=false` (those never published), and combines with `q`. Each row carries the method's publish state, so a list tells its methods apart without reading each one: `latest_version` and `latest_published` (a `MethodVersionSummary`), both `null` when the method was never published, and `draft_digest`, which is `null` on a row that never stored one until its next draft write, unlike on `MethodData`, because the list reads an index that holds no bundle to digest; all three are optional, absent from a platform that does not serve them. Never published is `latest_version === null`, the draft unchanged is `draft_digest === latest_published.source_digest`, and the draft ahead is two digests that differ. Both filters run after the index read, so **a filtered page can come back empty and still carry a `nextCursor`**: an empty page is not the end of the list, and only a `null` cursor is. `iterateMethods` is the async iterator that follows the cursor for callers who genuinely want everything (`for await (const m of client.iterateMethods())`); it keeps going **past empty pages**, since `{items: [], nextCursor: "…"}` means "nothing matched in the slice I just read, keep going". A server that keeps minting fresh cursors forever stops it at a page ceiling far past any real catalog with a `PagingNotTerminatingError` carrying `pageLimit`, never a silently truncated stream; `iterateRuns` shares the same loop. It gives up only when the server stops advancing its cursor, and **throws** rather than returning a partial answer; like `iterateRuns` it is deliberately not a `listAllMethods(): Promise<MethodSummary[]>`, because an all-at-once helper needs a page cap and a cap means silently returning a truncated list. `MethodSummary.deletion_state` rides the list rows: a method mid-erasure stays listed so the UI can render it as "Deleting…", while `getMethod` refuses it with a 409. Full read responses (`MethodData`, from `getMethod`) carry `org_id`, `created_by_user_id`, a server-derived `description` (recomputed from the draft's top-level `description` on every draft write), the draft token and digest and the latest version's summary on top of the write contract's `name` / `mthds` / `input_data`. `getMethodClosure` is a client-side semantic layer over `getMethod` (not a route) that parses the draft's polymorphic `mthds` source into a runnable, provenance-labelled closure — the draft, not what a bare id runs — see [input-preparation.md](./input-preparation.md#getmethodclosure--the-explicit-expansion-utility).
133
+ - **Methods catalog:** `listMethods`, `getMethod`, `createMethod`, `writeDraft`, `renameMethod`, `publishMethod`, `listMethodVersions`, `getMethodVersion`, `deleteMethod`. **A saved method has a draft and immutable published versions.** Its draft is a method tree with its `input_data`, which `writeDraft` (`PUT /v1/methods/{id}/draft`) replaces whole, without validating it; `updated_at` is the draft's token, which moves on every draft write and nothing else, and `draft_digest` the draft's tree digest (`sha256:` and 64 hex digits), `null` for an empty draft. A save takes the tree as `files`, sent as given, or as `directory`, `tree` or `contents`, sent inline or by hash after uploading the blobs the organization lacks, and a read lists the tree's files, each with a short-lived link to its bytes, which `writeMethodTree` writes to disk ([method-trees.md](./method-trees.md)). A draft write may carry `expected_updated_at`, the token the caller last saw, and is then a compare-and-swap: a draft that moved since is a `409` `method_update_conflict` and nothing is written. `renameMethod` (`PATCH /v1/methods/{id}`) changes the name alone and moves no token. `publishMethod` (`POST /v1/methods/{id}/publish`) takes the required `expected_draft_updated_at` and answers a `MethodPublishResult` discriminated on `outcome` — `published` with the new version, `unchanged` with the existing latest version when the draft's digest equals it, `refused` with a `reason` (`invalid` or `not_runnable`), a `message` and the runner's `validation` verdict — every arm carrying the `method`; the SDK reads the nested method as `getMethod` does, and an answer whose `outcome` is none of these is an answer it cannot read. A publish that produced no verdict is thrown rather than answered: only a draft that differs from the latest version reaches the runner, and a runner that cannot be reached, answers unusably or does not finish within the platform's deadline is a `502` or `503` with nothing written, so a retry is safe, and a retry of a publish that landed while its answer was lost answers `unchanged` with the version it wrote. A method is stored as one item that keeps room for the summary a publish adds, so a draft that saves can always be published: a creation or a draft write is a `413` `payload_too_large` when it would grow the method past that room, below the store's item limit, and a rename is the same `413` for a name so long it would leave the method too large to publish. A version is numbered from 1, never reused, and holds the draft's tree as it stood, its `tree_digest` (`null` for a version stored before methods were trees), its `crate_fingerprint` (`null` when the runner could not resolve the bundle in memory), the runner's version, and when and by whom it was published; `listMethodVersions` pages the summaries newest first (`MethodVersionPage`, `{items, nextCursor}`, a `limit` from 1 to 100, 20 by default, and a `422` outside that range), and `getMethodVersion` reads one with its `files` listed as a method's are, or answers a `409` `conflict`, whose verdict is `runtime`, for a version stored before methods were trees and never rewritten as one. A method read carries `latest_version` and `latest_published`, both `null` until the first publish, so the publish state is derived: never published, draft unchanged (`draft_digest` not `null` and equal to `latest_published.tree_digest`), or draft ahead. The method routes take a bare id and address the method itself, never one of its versions; the platform does not parse a suffix there, so `mt_x@3` would answer a `404` that reads as a method that does not exist, and each route refuses a suffixed id with `RequestArgumentError` before anything is sent, naming `parseMethodSelector` and `getMethodVersion`. The whole-method `updateMethod` is gone, replaced by the draft write and the rename. **`deleteMethod` is asynchronous and its return type says so:** `DELETE /v1/methods/{id}` answers `202` with a `MethodDeletionAccepted` (`method_id`, `deletion_state`, `deletion_job_id`) the moment the platform has claimed the method and terminated its in-flight workflows — the rest of the cascade (runs, events, S3 objects) is enqueued. A resolved promise means "accepted", never "gone"; completion is the row disappearing from `listMethods`, not any field of that body. The claim is a conditional write, so a double-clicked delete is a `409 method_being_deleted` rather than a second cascade over the same runs, and an unknown or foreign-org id is a `404`. The erasure deletes the method's versions with the rest. (This doc previously stated the SDK had no `delete` because the platform had no such route — the route has always existed; the claim was simply false.) `listMethods` returns **one page**, not the whole catalog — a `MethodPage` (`{items, nextCursor}`) served from a narrow index projection, so its cost is the page size rather than the size of the catalog. It used to return every method with its full `.mthds` bundle attached, which hit DynamoDB's 1 MB page cap at a couple hundred methods and came back truncated with no error and no flag, so methods silently vanished from the UI. Rows are therefore `MethodSummary`, **not** `MethodDetail`: no `files`, no `updated_at`, because neither is in the projection and putting the source back is what restored the truncation. Reach for `getMethod(id)` when you need a method's files. `query.q` is applied server-side across the whole catalog, not over the page — filtering one page client-side would be searching 50 rows of 10,000 and calling it a search. `query.published` filters the same way, sent as `published=true` (the methods with a published version) or `published=false` (those never published), and combines with `q`. Each row carries the method's publish state, so a list tells its methods apart without reading each one: `latest_version` and `latest_published` (a `MethodVersionSummary`), both `null` when the method was never published, and `draft_digest`, `null` for an empty draft; all three are optional, absent from a platform that does not serve them. Never published is `latest_version === null`, the draft unchanged is a `draft_digest` that is not `null` and equals `latest_published.tree_digest`, and the draft ahead is two digests that differ. Both filters run after the index read, so **a filtered page can come back empty and still carry a `nextCursor`**: an empty page is not the end of the list, and only a `null` cursor is. `iterateMethods` is the async iterator that follows the cursor for callers who genuinely want everything (`for await (const m of client.iterateMethods())`); it keeps going **past empty pages**, since `{items: [], nextCursor: "…"}` means "nothing matched in the slice I just read, keep going". A server that keeps minting fresh cursors forever stops it at a page ceiling far past any real catalog with a `PagingNotTerminatingError` carrying `pageLimit`, never a silently truncated stream; `iterateRuns` shares the same loop. It gives up only when the server stops advancing its cursor, and **throws** rather than returning a partial answer; like `iterateRuns` it is deliberately not a `listAllMethods(): Promise<MethodSummary[]>`, because an all-at-once helper needs a page cap and a cap means silently returning a truncated list. `MethodSummary.deletion_state` rides the list rows: a method mid-erasure stays listed so the UI can render it as "Deleting…", while `getMethod` refuses it with a 409. Full read responses (`MethodDetail`, from `getMethod`) carry `org_id`, `created_by_user_id`, a server-derived `description` (recomputed from the draft's top-level `description` on every draft write), the draft token and digest, the latest version's summary and the draft's `files` on top of the write contract's `name` / `input_data`; the writes and the rename answer `MethodData`, the same method without `files`.
135
134
  - **Method examples:** `createMethodExample`, `listMethodExamples`, `iterateMethodExamples`, `getMethodExample`, `updateMethodExample`, `recordMethodExampleLatestRun`, `deleteMethodExample`, on `/v1/methods/{id}/examples`. An example is a named set of inputs saved on a method, shared across the organization, with an `input_revision` that rises each time its inputs change and the `latest_run_id` of those inputs, which an inputs edit clears. `recordMethodExampleLatestRun` records a run against the revision whose inputs it used and answers a `MethodExampleLatestRunResult` discriminated on `outcome`, `recorded` or `stale`, each arm carrying the `example`: a run that outlasted an edit is a verdict, never thrown, and an answer off the union is one the SDK cannot read; one helper, `readVerdict`, reads this verdict and `publishMethod`'s, the example checked once, by the reader every example goes through. Every answer carrying an example is read with `parseExactJson` and every request body written with `stringifyExactJson`, so an integer past `Number.MAX_SAFE_INTEGER` in the inputs reads as a `bigint` and goes back digit for digit, to an edit or as a run's inputs; `3.0` still reads as `3`, and inputs holding one sent back unchanged are an edit for the platform, which compares inputs as canonical JSON. Every example the client hands back, the page rows and the verdict's `example` included, is checked by `readMethodExample` against the fields the Python SDK's model requires, with the strict types it holds them to, an example breaking one being an answer the SDK cannot read. The list is paged oldest first by an opaque cursor, and a page may be short while `nextCursor` is set; `iterateMethodExamples` follows it through the loop `iterateMethods` and `iterateRuns` share, and refuses a method id at the call rather than at the first pull. Every method takes a bare catalog id, and the client refuses an example id that is empty, `.` or `..` or holds a lone surrogate, a create without its name or inputs or whose `run_id` is given but empty, an edit naming neither `name` nor `inputs`, and a latest-run write without a run id or a positive integer revision before sending. See [method-examples.md](./method-examples.md).
136
135
  - **Organizations:** `listMemberships`, `createOrganization`, `renameOrganization` (`PATCH`). Each membership carries the caller's `role_in_org`, an `OrgRole` (`admin`, `member` or `runner`) read open: a role a later platform adds arrives as its raw string, so a `switch` over it says what an unknown role does. The role is for display; what it may do is the platform's to decide, and a call refused to the caller's role is an `ApiResponseError`. The org "switch" is a WorkOS-session op (`/api/active-org`), not a `/v1` route — out of SDK scope.
137
136
  - **Billing:** `getSubscription`, `listPlans`, `listInvoices`, `createCheckout`, `changePlan` (409 `conflict` ⇒ no subscription), `getBillingPortal` (409 `conflict` ⇒ no subscription).
138
137
  - **Pipelex API keys (`plx_sk_…`):** `listPipelexApiKeys`, `createPipelexApiKey` (409 `pipelex_api_key_limit_reached`), `revokePipelexApiKey`, `rotatePipelexApiKey`. The plaintext `api_key` is returned once, on create/rotate.
139
138
  - **Onboarding:** `submitOnboarding`.
140
- - **Storage:** `resolveStorageUrl`, `resolveStorageUrls` (`POST /v1/resolve-storage-url/bulk` — the single route applied to a list of at most 100 references, one verdict per reference in request order, a refused reference a value on its item; a deployment without the route answers a `404` `ApiResponseError`), `upload` (JSON base64 — the multipart hop is browser→BFF only), `requestUploadGrant` (`POST /v1/upload/grant` — a presigned, create-only `PUT` for one new object, which the holder of the bytes sends with the standalone `uploadWithGrant`, also exported from the browser-safe `@pipelex/sdk/upload` entry; a declared size over the cap is a `413` `ApiResponseError`). The higher-level `uploadFile` / `prepareInputs` preparation surface is built on top of `upload`; `prepareInputs` additionally composes one `pipeIo` call, which selects the pipe and answers with the input-form descriptor it walks, and takes the method as inline `files`, a `method_ref` or a `method_id` like every other method-taking operation — see [input-preparation.md](./input-preparation.md). The download twin — `locateArtifacts`, `collectArtifacts`, `resolveArtifacts`, `fetchArtifact`, `downloadArtifacts` — is built on top of `resolveStorageUrls` and `getRunResult`, never on the embedded `public_url`, and is documented on [artifact-download.md](./artifact-download.md); downloading is a separate explicit gesture, and no run call takes a `download` option.
141
- - **Runs list/detail/update:** `listRuns` (by `method_id`) returns **one page**, not the whole history — a `RunPage` (`{items, nextCursor}`) served from a time-ordered index, so its cost is the page size rather than the size of the history. Its rows are `RunHistoryItem`, **not** `PipelineRun`: the id, `status`, `created_at`, `finished_at`, `pipe_code`, for a failed run `error`, and `method_version` and `source_digest`, which version of the method the run ran (a number, `"draft"`, or `null` for an inline source) and the digest of what it ran — what a history row shows. The history lists the runs of every version and of the draft together, by the bare id. `method_version` and `source_digest` are optional on every run record (`RunPublic`, `RunRead`, `PipelineRun`, `RunDetail`, `RunHistoryItem`), since a run recorded before the platform recorded them carries neither. The run's organization, creator, method, workflow id and result location are not on the list; `getRunDetail` returns them. `iterateRuns` is the async iterator that follows the cursor for callers who genuinely want everything (`for await (const run of client.iterateRuns(id))`); it is deliberately not a `listAllRuns(): Promise<RunHistoryItem[]>`, because an all-at-once helper needs a page cap and a cap means silently returning a truncated list. Both accept `createdFrom` / `createdTo`, applied server-side as index key conditions — these are **instants, not days** (ISO-8601 with a UTC offset; a naive timestamp is a 400), because only the caller knows which timezone's day it means. Both also accept `createdBy: "me"`, sent as `created_by=me`, which keeps the runs the caller started (the platform resolves "me" from the authenticated identity and takes no other value), and `status`, a list of `RunStatus` sent as one repeated `status=` parameter per status, deduplicated into the platform's order, which keeps the runs in any of them: the caller's own latest unfinished run is `{ createdBy: "me", status: ["PENDING", "STARTED", "RUNNING"], limit: 1 }`. An empty `status` list would be sent as no parameter at all, which lists every status, so it is a `RequestArgumentError` before any request, as is a name that is no `RunStatus`. These two are filters applied after the index read, so **a filtered page can hold fewer runs than `limit`, or none, and still carry a `nextCursor`**: an empty page is not the end of the history, a `null` cursor is, and `iterateRuns` keeps following the cursor through one. It runs the same loop as `iterateMethods`, so it also stops on a cursor the server failed to advance and throws `PagingNotTerminatingError` past the same page ceiling. `getRunDetail` (`GET /v1/runs/{id}`) is the only call returning `mthds_contents` — what the run actually executed — and `inputs`; it is kept off the status read that pollers hit every few seconds and off the list, where the bundle would be multiplied by the page size. `updateRun` is the admin/manual status patch. The status/results/start lifecycle routes live in the run-lifecycle section above.
139
+ - **Storage:** `resolveStorageUrl`, `resolveStorageUrls` (`POST /v1/resolve-storage-url/bulk` — the single route applied to a list of at most 100 references, one verdict per reference in request order, a refused reference a value on its item; a deployment without the route answers a `404` `ApiResponseError`), `upload` (JSON base64 — the multipart hop is browser→BFF only), `requestUploadGrant` (`POST /v1/upload/grant` — a presigned, create-only `PUT` for one new object, which the holder of the bytes sends with the standalone `uploadWithGrant`, also exported from the browser-safe `@pipelex/sdk/upload` entry; a declared size over the cap is a `413` `ApiResponseError`). The higher-level `uploadFile` / `prepareInputs` preparation surface is built on top of `upload`; `prepareInputs` additionally composes one `pipeIo` call, which selects the pipe and answers with the input-form descriptor it walks, and takes the method as its tree, a `method_ref` or a `method_id` like every other method-taking operation — see [input-preparation.md](./input-preparation.md). The download twin — `locateArtifacts`, `collectArtifacts`, `resolveArtifacts`, `fetchArtifact`, `downloadArtifacts` — is built on top of `resolveStorageUrls` and `getRunResult`, never on the embedded `public_url`, and is documented on [artifact-download.md](./artifact-download.md); downloading is a separate explicit gesture, and no run call takes a `download` option.
140
+ - **Runs list/detail/update:** `listRuns` (by `method_id`) returns **one page**, not the whole history — a `RunPage` (`{items, nextCursor}`) served from a time-ordered index, so its cost is the page size rather than the size of the history. Its rows are `RunHistoryItem`, **not** `PipelineRun`: the id, `status`, `created_at`, `finished_at`, `pipe_code`, for a failed run `error`, and `method_version` and `source_digest`, which version of the method the run ran (a number, `"draft"`, or `null` for an inline source) and the SHA-256 of the sources it sent as text, 64 hex digits with no prefix and `null` for a run whose `files` held bytes as Base64 or by hash — what a history row shows. `getRunDetail` also carries the run's `tree_digest` and `crate_fingerprint`, each `null` for a run that recorded none. The history lists the runs of every version and of the draft together, by the bare id. `method_version` and `source_digest` are optional on every run record (`RunPublic`, `RunRead`, `PipelineRun`, `RunDetail`, `RunHistoryItem`), since a run recorded before the platform recorded them carries neither. The run's organization, creator, method, workflow id and result location are not on the list; `getRunDetail` returns them. `iterateRuns` is the async iterator that follows the cursor for callers who genuinely want everything (`for await (const run of client.iterateRuns(id))`); it is deliberately not a `listAllRuns(): Promise<RunHistoryItem[]>`, because an all-at-once helper needs a page cap and a cap means silently returning a truncated list. Both accept `createdFrom` / `createdTo`, applied server-side as index key conditions — these are **instants, not days** (ISO-8601 with a UTC offset; a naive timestamp is a 400), because only the caller knows which timezone's day it means. Both also accept `createdBy: "me"`, sent as `created_by=me`, which keeps the runs the caller started (the platform resolves "me" from the authenticated identity and takes no other value), and `status`, a list of `RunStatus` sent as one repeated `status=` parameter per status, deduplicated into the platform's order, which keeps the runs in any of them: the caller's own latest unfinished run is `{ createdBy: "me", status: ["PENDING", "STARTED", "RUNNING"], limit: 1 }`. An empty `status` list would be sent as no parameter at all, which lists every status, so it is a `RequestArgumentError` before any request, as is a name that is no `RunStatus`. These two are filters applied after the index read, so **a filtered page can hold fewer runs than `limit`, or none, and still carry a `nextCursor`**: an empty page is not the end of the history, a `null` cursor is, and `iterateRuns` keeps following the cursor through one. It runs the same loop as `iterateMethods`, so it also stops on a cursor the server failed to advance and throws `PagingNotTerminatingError` past the same page ceiling. `getRunDetail` (`GET /v1/runs/{id}`) is the only call returning `mthds_contents` — what the run actually executed — and `inputs`; it is kept off the status read that pollers hit every few seconds and off the list, where the bundle would be multiplied by the page size. `updateRun` is the admin/manual status patch. The status/results/start lifecycle routes live in the run-lifecycle section above.
142
141
 
143
142
  ## Hook bundle (`dist-hooks/check.mjs`)
144
143
 
145
- `src/hooks/` holds the post-edit `.mthds` hook pipeline (local lint/format via `@pipelex/tools-wasm`, then a `POST /v1/validate` verdict through this SDK), bundled into a single dependency-free ESM file by `npm run build:hook`. Its validate client is built by `src/hooks/validate-client.ts` with `appInfo: { name: "pipelex-mthds-check", version: SDK_VERSION }`, the `hook` surface's registry token, so the platform attributes its calls to the hook rather than to a plain SDK caller. The one specifier left external is `undici`, reached only by the artifact fetch path through a dynamic import the hook never executes, so the bundle does not inline an HTTP client it cannot use. **Distribution is source-checkout vendoring, not npm:** `pipelex-plugins` runs `make vendor-hook`, which builds `dist-hooks/check.mjs` in a sibling checkout of this repo and copies it in as a static hook asset — the published `@pipelex/sdk` tarball deliberately does not ship the bundle (it inlines the ~4 MB WASM engine, and no npm consumer of the SDK's library API uses it). `dist-hooks/` is gitignored; the consumer repo's own checks gate a stale vendored copy. `@pipelex/tools-wasm` is pinned to an exact version in `package.json`, because the engine carries the MTHDS schema the hook lints against: a newer schema reaches the hook only by a deliberate bump followed by a rebuild and a re-vendor, and the bundle's provenance line (`@pipelex/sdk <version> (<commit>) + @pipelex/tools-wasm <version> (npm)`) names the engine it embeds. Its bundle gatherer (`src/hooks/bundle-gather.ts`) parses each `.mthds` file it sends with `smol-toml`, which the bundle inlines, to find the template files its `PipeDocGen` steps name, and sends them as the request's `resources`. Which file the hook checks on each platform, what it sends with it, and how it finds the file a Codex patch run through the shell wrote, is in [`hook-bundle.md`](./hook-bundle.md).
144
+ `src/hooks/` holds the post-edit `.mthds` hook pipeline (local lint/format via `@pipelex/tools-wasm`, then a `POST /v1/validate` verdict through this SDK), bundled into a single dependency-free ESM file by `npm run build:hook`. Its validate client is built by `src/hooks/validate-client.ts` with `appInfo: { name: "pipelex-mthds-check", version: SDK_VERSION }`, the `hook` surface's registry token, so the platform attributes its calls to the hook rather than to a plain SDK caller. The one specifier left external is `undici`, reached only by the artifact fetch path through a dynamic import the hook never executes, so the bundle does not inline an HTTP client it cannot use. **Distribution is source-checkout vendoring, not npm:** `pipelex-plugins` runs `make vendor-hook`, which builds `dist-hooks/check.mjs` in a sibling checkout of this repo and copies it in as a static hook asset — the published `@pipelex/sdk` tarball deliberately does not ship the bundle (it inlines the ~4 MB WASM engine, and no npm consumer of the SDK's library API uses it). `dist-hooks/` is gitignored; the consumer repo's own checks gate a stale vendored copy. `@pipelex/tools-wasm` is pinned to an exact version in `package.json`, because the engine carries the MTHDS schema the hook lints against: a newer schema reaches the hook only by a deliberate bump followed by a rebuild and a re-vendor, and the bundle's provenance line (`@pipelex/sdk <version> (<commit>) + @pipelex/tools-wasm <version> (npm)`) names the engine it embeds. Its tree gatherer (`src/hooks/bundle-gather.ts`) lists the edited file's directory with the `mthds` package's lister, which the bundle inlines, under the hook's own caps, and the validation sends that tree, the template files its `PipeDocGen` steps name included. The networked stage is `src/hooks/validate-stage.ts`: it holds the whole stage, the version handshake, the blob route, the uploads and the validation, to one deadline (`VALIDATE_TIMEOUT_MS`, ten seconds) whose signal it hands to `validate`, so the request or upload under way stops when it runs out and the stage reads as `unavailable`. Which file the hook checks on each platform, what it sends with it, and how it finds the file a Codex patch run through the shell wrote, is in [`hook-bundle.md`](./hook-bundle.md).
146
145
 
147
146
  ## Testing
148
147
 
package/docs/cli.md CHANGED
@@ -96,7 +96,7 @@ A `--method` path is read by the command's own reader (`src/cli/bundle.ts`), who
96
96
 
97
97
  - **A `.mthds` file** is a one-file bundle, sent under its own file name. A file of any other name is refused.
98
98
  - **A directory** is every `.mthds` file under it, at any depth, each sent under its path relative to the directory, with `/` between segments.
99
- - **The order** is the order of those names compared code point by code point, which is the order of their UTF-8 bytes: `Zeta.mthds` before `main.mthds`, `steps/score.mthds` before `steps2.mthds`, and `~.mthds` (U+FF5E) before `🧾.mthds` (U+1F9FE), where UTF-16 order would put them the other way round. A run sends the contents in this order as `mthds_contents`, and the pipe I/O route gets them as `files`, each with its name as `source`.
99
+ - **The order** is the order of those names compared code point by code point, which is the order of their UTF-8 bytes: `Zeta.mthds` before `main.mthds`, `steps/score.mthds` before `steps2.mthds`, and `~.mthds` (U+FF5E) before `🧾.mthds` (U+1F9FE), where UTF-16 order would put them the other way round. A run sends the contents in this order as `mthds_contents`, a field the SDK no longer names and so passes through the request's `extra`, and the pipe I/O route gets them as the method's tree, the `files` map, each under its name as its tree path, sent inline as given.
100
100
  - **A hidden entry**, a file or a directory whose name starts with `.`, is skipped, so a `.venv/` or a `.git/` inside a bundle is never read.
101
101
  - **Any file not named `.mthds`** is ignored, Python files included: the command sends only the MTHDS sources.
102
102
  - **A symbolic link** is judged by its own name. One named `.mthds` that leads to a file is read through, under the link's name; one that leads to a directory is not descended into, which keeps a link cycle from looping; one that leads nowhere is refused. The `--method` path itself may be a link, and is followed.
@@ -12,13 +12,17 @@ Three routes project a **closure** of MTHDS files into the artifacts downstream
12
12
 
13
13
  ## The shared envelope
14
14
 
15
- All three take the same closure selector — inline `files`, a `method_ref`, or a hosted `method_id`, exactly one (the strict tooling XOR):
15
+ All three take the same closure selector — the method's tree, a `method_ref`, or a hosted `method_id`, exactly one (the strict tooling XOR) — and the tree may bring its dependencies:
16
16
 
17
17
  ```ts
18
18
  interface CrateRequestBase {
19
- files?: MthdsFileItem[]; // [{ content, source? }] — `source` is the provenance label
20
- method_ref?: string; // address form server-resolved (pipelex-api >= 0.21.0); registry form reserved → 501
21
- resources?: BundleResources | null; // beside `files`: the files the steps read, keyed by the path a step names
19
+ files?: MethodFiles; // the protocol's map: tree path → text, { base64 } or { sha256, size }
20
+ directory?: string; // or a directory on disk, listed by the mthds package (Node only)
21
+ tree?: MethodTreeSource; // or a listed tree, sent inline or by hash
22
+ contents?: Readonly<Record<string, Uint8Array | string>>; // or each file's bytes or text by tree path
23
+ dependencies?: Record<string, MethodFiles>; // beside the tree: the packages it calls by address
24
+ method_ref?: string; // address form server-resolved; registry form reserved → 501
25
+ read_scope?: string; // Pipelex-API extension; the hosted platform stamps its own
22
26
  }
23
27
 
24
28
  interface PipelexHostedToolingExtensions {
@@ -26,30 +30,45 @@ interface PipelexHostedToolingExtensions {
26
30
  }
27
31
  ```
28
32
 
29
- `source` is why the envelope carries files rather than bare strings. A closure is a set of files, and a diagnostic that cannot say _which_ file it came from is much harder to act on. Pass a filename (or any label) per file and, **when the engine can attribute the diagnostic to a file**, it comes back as `source` on the corresponding `validation_errors[]` item.
33
+ **The tree is the MTHDS protocol's `files` map**, the shape `validate`, the runs and the method catalog take: each key a tree path, each value the file's text, `{ base64 }` for bytes that are not text, or `{ sha256, size }` naming a blob the organization already holds. The runner writes the tree whole and loads it as the method's library directory, so every `.mthds` bundle is named by its tree path and every other file, a `PipeDocGen` template beside its bundle for instance, is one a step may read. The tree is given in exactly one of four forms, as a run, a validation and a save take it ([method-trees.md](./method-trees.md)):
30
34
 
31
- Treat that attribution as best-effort, not a guarantee — which is why `ValidationErrorItem.source` is typed optional and why the `resolve` sample below reads `err.source ?? "?"`. Some arms don't populate it: graph-level `dry_run` and `pipe_factory` items have no single owning file, and a `main_pipe` naming a nonexistent pipe currently reports its provenance in the message prose while leaving the structured field unset. The syntax-error arm, the common case, does thread it.
35
+ - `files`, the map, posted as given with no round trip;
36
+ - `directory`, a directory on disk, listed by the `mthds` package's lister under the standard's membership rule and the deployment's limits, in Node only;
37
+ - `tree`, a listed source such as the `MethodTree` the `mthds` package's `listMethodTree` returns;
38
+ - `contents`, each file's bytes or text keyed by its tree path.
32
39
 
33
- > `MthdsFileItem` is not the same type as `MthdsFile` (the one `validateFiles()` takes). `/v1/validate` spells the provenance label `uri` and carries it in a parallel `mthds_sources` array; this envelope spells it `source` and carries it inline. The two collapse into one only if `/v1/validate` ever migrates onto `files[]` — a protocol-level change owned by the MTHDS standard, not ours to make here.
40
+ A `directory`, `tree` or `contents` travels as a run or a save sends it ([method-trees.md](./method-trees.md#how-a-tree-travels)): the client reads the version handshake first, then sends the tree inline when its map weighs no more than the lower of `INLINE_TREE_MAX_BYTES` (256 KiB) and the announced `max_inline_bytes`, and otherwise, against an API that declares a blob store, by hash after asking `POST /v1/blobs/missing` which blobs the organization lacks and uploading each one once; against an API with no blob store it sends the tree inline whatever its weight, refusing one past `max_inline_bytes`. A blob that fails to upload throws `MethodFileTransferError`, whose message ends "so the request was not sent", and the route is never asked. Two forms at once, a directory the lister refuses, and a `tree` holding no file, are refused with `RequestArgumentError` before any request. A `files` map is never checked client-side: a key or an entry the tree's rule refuses is the server's `422`.
34
41
 
35
- An **address-form** `method_ref` (`github.com/<owner>/<repo>[/<selector>][@<tag>]`) is resolved by the server through the same fetch path as a `method_ref` run: the repository fetched at the tag, the package located by manifest identity, the package's real relative paths feeding the per-file `source` labels. Any non-address reference stays reserved and answers `501`.
42
+ **An empty map is absent**, as in the Python SDK: `files: {}` or `files: null`, `contents: {}`, `directory: ""` and `dependencies: {}` are not sent, so an empty map never reaches the wire as a second selector, and `{ files: {}, method_id: "mt_…" }` posts the `method_id` alone. A value that is not a map, such as a list, is not absent: it is posted as given and refused by the server.
36
43
 
37
- `method_id` is the hosted platform's selector, and it is a **pass-through**: nothing is expanded client-side — the platform resolves the id against the org's catalog and injects the stored source before the runner sees the request. A bare `mt_…` names the method's latest published version, `mt_…@<n>` the fixed version `n` and `mt_…@draft` its draft, and the suffix rides the string untouched. It is meaningless against a bare runner (no catalog), and on `api.pipelex.com` its availability follows the platform deploy that adds the tooling-route transform. An unknown or foreign-org id is a `404` (indistinguishable by design); a bare id of a method never published is a `409` `method_not_published`, whose detail names `mt_…@draft`; a version the method never published is a `404` `method_version_not_found`; a malformed suffix is a `422`; a stored method with no MTHDS source is a `422`.
44
+ When the request carries a `read_scope`, the blob route is asked under it, as `POST /v1/blobs/missing?read_scope=…`, so the missing blobs are uploaded into the store the request's hash entries are read from; each upload target the runner answers is signed for that scope, so the uploads need nothing more. The hosted platform's own blob route reads the caller's organization and ignores the query, as it does the request's `read_scope`.
38
45
 
39
- Supplying **no** selector or **more than one** is a request-shape `422` — the tooling routes are stateless, so there is no linkage exception; a second selector could only be ignored, which is the worst contract of the three. The SDK does not model the XOR in the type system — the union would force the overwhelmingly common `{ files }` call site to pick a branch for no gain, and the server's answer is a typed `ApiResponseError` either way.
46
+ **Stopping a call.** Each route takes a second argument, `CrateRouteOptions`, whose `signal` is read before each step a `directory`, `tree` or `contents` costs — the version handshake, the directory's listing, the blob route, each read and each upload of a missing blob — and before the request itself, and is handed to each of those steps, so an abort stops the handshake, the blob route, a read or an upload already under way. Once it has aborted, nothing further starts and the call throws the abort; the route's own request, once sent, runs to its end, since the routes take no transport options (a static route's budget is the client's own). `prepareInputs` passes its `signal` here, so an abort during the handshake stops it and leaves the blob route, the uploads and `POST /v1/pipe-io` unasked.
40
47
 
41
- The old advice to expand a stored method client-side (`resolve({ files: await client.getMethodClosure(methodId) })`) remains valid — `getMethodClosure` stays public as the local expansion utility, and it is what a caller uses against a bare runner, which has no catalog to resolve an id against.
48
+ When the engine can attribute a diagnostic to a file, the `validation_errors[]` item's `source` names it by its tree path. Treat that attribution as best-effort, not a guarantee — which is why `ValidationErrorItem.source` is typed optional and why the `resolve` sample below reads `err.source ?? "?"`. Some arms don't populate it: graph-level `dry_run` and `pipe_factory` items have no single owning file, and a `main_pipe` naming a nonexistent pipe currently reports its provenance in the message prose while leaving the structured field unset.
42
49
 
43
- Beside inline `files`, `resources` carries the files the closure's steps read, such as a `PipeDocGen` step's `template_file`, keyed by the path the step names, each as its bytes. It is the one member the client does not post as given: it encodes the bytes into the wire's base64 map, after refusing a key the runner's path rule refuses. A step whose template file was not sent makes the closure invalid, a `200` verdict saying so; `resources` beside a `method_ref` is the server's `422`. The rules, the limits and the refusals are in [`bundle-resources.md`](./bundle-resources.md).
50
+ `dependencies` carries the method packages the tree calls by address, each a `files` map keyed by its address, posted as given. They are loaded beside the method, never merged into it, so a cross-package call resolves without the server fetching anything. A call into a package nothing shipped makes the closure invalid, a `200` verdict whose `unresolved_package_dependency` item names the package; `dependencies` without the tree is the server's `422`.
44
51
 
45
- A `method_ref` makes the server fetch the repository before it answers, so the client gives a call carrying one a fetch-sized budget (three minutes) instead of the 30-second default. A call carrying `resources` gets the 20-minute execute ceiling that `start` and `validate` give the same files, because uploading them can take longer than the default on its own. On the hosted API the gateway caps every request at about 30 seconds whatever the client allows, so a cold `method_ref` clone can answer a `502`; retrying clears it once the runner has cached the clone.
52
+ An **address-form** `method_ref` (`github.com/<owner>/<repo>[/<selector>][@<tag>]`) is resolved by the server through the same fetch path as a `method_ref` run: the package's whole tree is read from the commit at the tag and loaded as a sent tree is, with the packages it ships under its own `.mthds/methods/` beside it. Any non-address reference stays reserved and answers `501`.
53
+
54
+ `method_id` is the hosted platform's selector, and it is a **pass-through**: nothing is expanded client-side — the platform resolves the id against the org's catalog and injects the stored tree as `files` before the runner sees the request. A bare `mt_…` names the method's latest published version, `mt_…@<n>` the fixed version `n` and `mt_…@draft` its draft, and the suffix rides the string untouched. It is meaningless against a bare runner (no catalog). An unknown or foreign-org id is a `404` (indistinguishable by design); a bare id of a method never published is a `409` `method_not_published`, whose detail names `mt_…@draft`; a version the method never published is a `404` `method_version_not_found`; a malformed suffix is a `422`; a stored method with no MTHDS source is a `422`.
55
+
56
+ `read_scope` is a Pipelex-API extension naming the scope the request reads the method under: a hash entry of the tree resolves in that scope's blob store. A caller of a bare runner may send it; **the hosted platform stamps it from the caller's organization and drops one the caller sent**, so a hosted caller never needs it.
57
+
58
+ Supplying **no** selector or **more than one** is a request-shape `422` — the tooling routes are stateless, so there is no linkage exception; a second selector could only be ignored, which is the worst contract of the three. The SDK does not model the XOR in the type system — the union would force the overwhelmingly common `{ files }` call site to pick a branch for no gain, and the server's answer is a typed `ApiResponseError` either way. Only the four forms of the tree are checked client-side, because the client has to choose how to send it.
59
+
60
+ A caller facing a bare runner, which has no catalog to resolve an id against, expands a stored method itself: it reads the method's tree with `getMethod` or `getMethodVersion`, writes it to disk with `writeMethodTree`, and sends it from there as a `tree` ([method-trees.md](./method-trees.md)).
61
+
62
+ The files the closure's steps read, such as a `PipeDocGen` step's `template_file`, are files of the tree like any other, at the tree path the step names. A step whose template file the tree does not hold makes the closure invalid, a `200` verdict saying so ([method-trees.md](./method-trees.md#the-files-a-step-reads)).
63
+
64
+ A `method_ref` makes the server fetch the repository before it answers, so the client gives a call carrying one a fetch-sized budget (three minutes) instead of the 30-second default. A call whose `files` carry more than `INLINE_TREE_MAX_BYTES` (256 KiB) inline, as a tree sent to an API keeping no blob store does whatever its weight, and as a `files` map given as is may, gets the client's request ceiling (`requestTimeoutMs`) instead, since uploading the body is charged against the budget; a tree sent by hash keeps the default, its files uploaded before the request. On the hosted API the gateway caps every request at about 30 seconds whatever the client allows, so a cold `method_ref` clone can answer a `502`; retrying clears it once the runner has cached the clone.
46
65
 
47
66
  ## `resolve` — the normalized crate
48
67
 
49
68
  Resolution is a first-class language operation alongside validation: the closure is loaded and statically validated, then emitted with fully qualified refs, refinement flattened, natives materialized, and a fingerprint set.
50
69
 
51
70
  ```ts
52
- const result = await client.resolve({ files: [{ content: src, source: "method.mthds" }] });
71
+ const result = await client.resolve({ files: { "method.mthds": src } });
53
72
 
54
73
  if (!result.is_valid) {
55
74
  for (const err of result.validation_errors) console.error(`${err.source ?? "?"}: ${err.message}`);
@@ -62,7 +81,7 @@ console.log(result.crate.fingerprint); // rides INSIDE the crate, not beside it
62
81
  Two things to internalize:
63
82
 
64
83
  - **`fingerprint` and `mthds_version` are crate members**, not siblings of `crate`.
65
- - **Compare `fingerprint` values; never hash the crate yourself.** The fingerprint is a property of the _logical_ crate, not of an encoding: the server hashes `{concepts, pipes, domains}` with provenance `source` stripped, excluding `source_map`, `mthds_version` and `fingerprint` itself. And these are not the bytes `pipelex resolve --format json` prints — the CLI pretty-prints, the route answers compact JSON. Same logical crate, different serialization. Hashing `JSON.stringify(result.crate)` and comparing it against `result.crate.fingerprint` will mismatch on every call, and will look like tampering.
84
+ - **Compare `fingerprint` values; never hash the crate yourself.** The fingerprint is a property of the _logical_ crate, not of an encoding: the server hashes `{concepts, pipes, domains}` with each provenance `source` stripped, excluding `source_map`, `mthds_version` and `fingerprint` itself. And these are not the bytes `pipelex resolve --format json` prints — the CLI pretty-prints, the route answers compact JSON. Same logical crate, different serialization. Hashing `JSON.stringify(result.crate)` and comparing it against `result.crate.fingerprint` will mismatch on every call, and will look like tampering.
66
85
  - **`crate` is typed as opaque transport** (`Record<string, unknown>`). Its schema belongs to the MTHDS standard; restating it here would be a second source of truth, free to drift from the one the server emits.
67
86
 
68
87
  `resolve` runs **no dry-run sweep**. A valid verdict says the library resolves, never that it runs — runnability is `validate`'s vocabulary.
@@ -111,9 +130,9 @@ The request is the shared envelope plus three optional fields, posted verbatim:
111
130
  | --------------- | ------- | --------------------------------------------------------------------------------------------------------- |
112
131
  | `pipe_ref` | none | The qualified `domain.pipe_code` to describe. Omitted, the server's selection chain decides. |
113
132
  | `all_pipes` | `false` | Describe every pipe the closure loads instead of the selected one. |
114
- | `include_files` | `false` | Echo the resolved closure's `.mthds` files as `files`, in the request's own `{ content, source? }` shape. |
133
+ | `include_files` | `false` | Echo the text of the method's own `.mthds` bundles as `files`, a map from tree path to text. |
115
134
 
116
- **Selection.** The request's `pipe_ref`; else a fetched package's manifest `main_pipe`; else the closure's `main_pipe`, when exactly one domain declares one. A `pipe_ref` that names no pipe, and — without `all_pipes` — a chain that finds no entry pipe or several, are refused with a `422` whose `errorType` names the refusal (see [What throws](#what-throws)). The server does not refuse a bare code yet: a bare ref that matches one pipe resolves across domains, and the answer reports the qualified ref. With `all_pipes: true` the route never refuses for want of an entry pipe, so a method that declares none is still describable.
135
+ **Selection.** The request's `pipe_ref`; else the `main_pipe` of the `METHODS.toml` at the tree's root, sent in the tree or fetched with a package; else the closure's `main_pipe`, when exactly one domain declares one. A `pipe_ref` that names no pipe, and — without `all_pipes` — a chain that finds no entry pipe or several, are refused with a `422` whose `errorType` names the refusal (see [What throws](#what-throws)). The server does not refuse a bare code yet: a bare ref that matches one pipe resolves across domains, and the answer reports the qualified ref. With `all_pipes: true` the route never refuses for want of an entry pipe, so a method that declares none is still describable.
117
136
 
118
137
  The valid arm (`PipeIOValidReport`):
119
138
 
@@ -121,7 +140,7 @@ The valid arm (`PipeIOValidReport`):
121
140
  - `pipe_io_contracts`, `input_form`, `output_form` — the three maps, sharing one key set: the resolved `pipe_ref` alone by default, every pipe under `all_pipes`. For a closure `validate` also accepts, each equals `validate`'s same-named field restricted to the same keys, null members such as a contract's `item_count: null` included.
122
141
  - `default_pipe_ref` — the method's own entry pipe, the selection chain without the request's `pipe_ref`, or `null` when that chain finds none or several. A request that omits `pipe_ref` always answers `pipe_ref === default_pipe_ref`. It is **not** `validate`'s field of the same name, which is the run default and names the first of several declaring domains where this route refuses to choose.
123
142
  - `pending_signatures`, `is_runnable` — what they mean on `validate`, read off the loaded library with no dry run, so a method whose dry run would fail is still reported runnable here.
124
- - `files` — present only with `include_files: true`: the request's files for inline `files`, the fetched package's `.mthds` files under their package-relative paths for a `method_ref`, the stored files under their stored names for a hosted `method_id`. Absent, not empty, otherwise.
143
+ - `files` — present only with `include_files: true`: the text of each `.mthds` bundle of the method's own tree, keyed by its tree path — the request's bundles for a sent tree, whatever form or entry carried them, the fetched package's bundles keyed by their path from the package root for a `method_ref`, the stored tree's bundles for a hosted `method_id`. The tree's other files and the bundles of its dependencies are never included. Absent, not empty, otherwise.
125
144
 
126
145
  `is_valid: true` means what it means on `resolve`: the closure parsed, loaded and passed static validation. The invalid arm is the shared `CrateInvalidReport`, and it carries no artifacts, no selection and no files, whatever the request asked for.
127
146
 
@@ -137,19 +156,22 @@ Only a **no-verdict** condition, as the typed `ApiResponseError` — branch on i
137
156
 
138
157
  | Status | Cause |
139
158
  | ------------- | --------------------------------------------------------------------------------------------------------- |
140
- | `422` | Request shape: no closure selector or more than one, an over-limit file, an unknown `kind`/`target`, a `pipe_ref` on `kind: "types"`, a fetched package with no `.mthds` file, a stored method with no MTHDS source, a `method_id` whose version suffix is malformed. |
141
- | `422` / `413` / `400` | On `resources`: `InvalidResourcePath`, `BundleResourceNotNamedError` (a file no step names), `ValidationError` (beside a `method_ref`), `PayloadTooLarge`, `BundleResourcesTooLargeError`, `InvalidBase64` — see [`bundle-resources.md`](./bundle-resources.md#what-the-server-refuses). |
159
+ | `422` | Request shape: no closure selector or more than one, `dependencies` without the tree, an unknown `kind`/`target`, a `pipe_ref` on `kind: "types"`, a fetched package with no `.mthds` file, a stored method with no MTHDS source, a `method_id` whose version suffix is malformed. |
160
+ | `422` | The tree's refusals, as on `validate`: `InvalidMethodFiles` for a key or an entry the tree's rule refuses (a `files` that is not a map among them), `MissingBlobs` for a hash the server does not hold, `MethodTreeTooLarge` past the tree's limits, `InvalidBundle` for a tree holding no `.mthds` bundle. |
142
161
  | `422` | On `pipeIo`, a pipe selection the route refuses: `errorType` `EntryPipeNotFoundError` for a `pipe_ref` that names no pipe or a method with no entry pipe, `EntryPipeAmbiguousError` for a code that matches pipes in several domains or several `main_pipe` declarations. The `serverMessage` names the candidates where there are some. |
143
162
  | `404` | Unknown or foreign-org `method_id` (indistinguishable by design); no package at a `method_ref` address. |
144
163
  | `404` | `code` `method_version_not_found`: a `mt_…@<n>` naming a version the method never published. |
145
164
  | `409` | `code` `method_not_published`: a bare `method_id` of a method never published; `mt_…@draft` reaches its draft. |
146
165
  | `501` | Registry-form `method_ref` — reserved, not implemented (the address form resolves). |
147
166
  | `401` / `403` | Auth, or on a hosted origin a route the gateway does not list yet (`403 {"message":"Forbidden"}`). |
167
+ | `403` | `CustomCodeRequiresSandbox` for a tree holding a `.py` file on a deployment that is not sandbox-hosted, `MethodStructuresRefusedError` for one whose Python declares a structure class on one that is; `ReadScopeForbidden` for a `read_scope` a `jwt` caller may not read under. |
148
168
  | `502` | On a hosted origin, a cold `method_ref` clone that outran the gateway's 30-second cap; a retry clears it. |
149
169
  | `5xx` | Server fault, including on `pipeIo` a pipe whose artifacts cannot be derived. |
150
170
 
151
171
  Note the split: a bad **closure** is a 200 verdict; a bad **request** throws.
152
172
 
173
+ Before any request, a `directory`, `tree` or `contents` can also throw: `RequestArgumentError` for two forms of the tree, a directory the lister refuses, a tree holding no file or one too heavy to send inline to an API with no blob store, and `MethodFileTransferError` for a blob that could not be uploaded, so the request was not sent ([errors.md](./errors.md)).
174
+
153
175
  (The offline check below is not a route and throws its own `CodegenLockError` instead — it never reaches the network.)
154
176
 
155
177
  ## The offline check — `runCodegenCheck`