arazzo-executor: prepare checked workflows before execution - #285
Conversation
Assisted-by: Codex Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
|
Reviewed at The central risk in this design is that a prepared run and a lazy run could disagree, since Confirmed Issues1. Expression references are reported with
for It matters most where preparation is most valuable — the shared-component case reports Fix: emit 2. The byte offset is printed twice — Low
Fix: add the location prefix only for issues that do not describe their own position — Possible Risks3. The condition offset is recovered by parsing an error message — Medium, and this release is the window
ExecutionError::Criterion(CriterionError::Syntax { message, .. }) => message
.strip_prefix("at byte ")
.and_then(|message| message.split_once(':'))
.and_then(|(offset, _)| offset.parse().ok()),This depends on 4. The cached branch of
Nice-to-Have Improvements5. Diagnostics sort lexicographically, not by location — Low
6. Instrumentation indices are unnamed — Low
7. Module layout and docs — Low
— Reviewed by Claude Opus 5 |
Assisted-by: Codex Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
|
Re-reviewed at No major issues detected. 1. Expression references now use and the 2 and 3. Offsets are now a real The nested case is the one I'd have expected to regress, and it does not — The README migration section covers the field change, including that the standalone 4. The cached- 5. 6 and 7. The instrumentation hooks now name their parser ( — Reviewed by Claude Opus 5 |
) Add the optional `source-graph` executor feature, following the checked preparation work in #285. Complete documents now retain opaque registry handles, retrieval locations, resolved Arazzo `$self` identities, effective reference bases and written versions. Supplied Arazzo documents are fully parsed and indexed before resolution; aliases and source/API-base overrides are scoped to the owning document. Source traversal uses caller-configured `roas::Loader` fetchers, with shared documents, explicit back edges, separate document/depth budgets, root-source selection, and located errors that preserve readable parts of a graph. Later identity discovery can repair an earlier unresolved reference, including a newly discovered shorter path. A qualified operation may prepare with an unrelated source missing; a bare operation ID still requires enough sources to prove uniqueness. The loader adds unchanged-document/retrieval-metadata APIs with default methods for existing sync/async fetchers. HTTP fetchers expose final redirect URLs and retain caller redirect/timeout policy. YAML sniffing respects explicit content types and, when absent or generic, either the requested or final URL's extension. Thus `/source.yaml` redirecting to `/blob` retains legacy parsing behavior. Legacy reference readers retain requested-URI rewriting and store only one full document plus changed-reference strings. A raw view is materialized only on demand, without another fetch. Shared-document APIs let the loader, graph and cloned Options retain the same immutable raw value; both full views are retained only if both are requested. All loader types are also exported at the roas crate root. `Options::source` remains compatible, and explicit source/base overrides take precedence. The CLI keeps selected-workflow source discovery by default. New flags expose `--source-document`, `--load-all-sources`, `--source-max-documents`, `--source-max-depth`, and `--allow-source-retrieval-aliases`; none enables IO beyond the existing `--load` policy. Canonical Arazzo identities are strict by default; retrieval aliases are an explicit compatibility extension. Fetched unrelated failures are reported without unnecessarily blocking a qualified checked run. Each diagnostic is rendered once with its owning document identity, location and source alias, without opaque registry IDs; quiet mode suppresses optional warnings but retains failure details. Relative sources under a non-hierarchical `$self` name the two remedies: an absolute source URL or a hierarchical `$self`. `crates/roas-cli/tests/fixtures/source-graph/root.json` links JSON/YAML branches sharing `shared.yaml` and `api.json`, with `shared.yaml` pointing back to the root. For identity resolution, a document retrieved from `https://example.test/cache/child.json` with `"$self":"../identity/child.json"` is identified by `https://example.test/identity/child.json`, and resolves its relative sources there. Recognized families are Arazzo 1.0/1.1, OpenAPI 2.0/3.0/3.1/3.2, and AsyncAPI 2.6/3.0/3.1. API documents retain complete raw values with model-checked versions, not structural/schema validation. Broker execution, external workflow calls, referenced OpenAPI Path Items and relative API-server resolution remain deferred. The additive loader/fetcher APIs bump roas to 0.20.1 and roas-http-fetcher to 0.2.5; the executor remains on unreleased 0.2.0. Those dependency minimums ensure downstream builds receive the metadata APIs. Consumers inherit the workspace dependency versions while explicitly preserving their existing feature selections. No existing execution signatures are changed. --------- Signed-off-by: Sergey Vilgelm <sergey@vilgelm.com>
Add IO-free
prepareandrequired_sourcesAPIs and an immutable, reusablePreparedWorkflow. Preparation aggregates deterministic diagnostics with fieldpaths, workflow/step context and byte offsets before a checked run can send a
request. It composes structural validation with static expression/reference,
capability, effective-parameter, operation and dependency checks across the
selected workflow's potential calls and recovery branches.
Prepared runs reuse condition/runtime-expression syntax, interpolation templates,
constant regex/JSONPath programs, endpoints and ordering while keeping inputs,
attempts and outputs independent. A named condition profile and optional
portability warnings make implementation policy explicit. Retained token offsets
keep diagnostics accurate with quoted expression lookalikes and cached ASTs.
The CLI now prepares before execution and prints available partial history on
terminal runtime errors unless quiet. Source discovery avoids loading unrelated
documents for qualified operations while preserving bare operation-ID uniqueness
checks. Existing validation-ignore options remain honored.
This intentionally makes the CLI stricter: a criterion such as
{"condition":"true || $steps.typo.outputs.value"}, a typed criterion withoutits required context, or a constant malformed regex fails before requests,
including on a potential recovery branch. Runtime-dependent criterion failures
retain the recovery/reporting behavior from #284. Existing
execute,execute_async,execute_v1_0andRun::startsignatures and lazy validationremain unchanged; strict preparation is opt-in for library callers.
The unreleased 0.2 API also adds
CriterionError::Syntax::offsetand removes thelocation prefix from that variant's
message. Downstream code constructing ordestructuring all fields must adapt; consumers should read the typed byte offset
instead of parsing display text. The README migration notes cover this breaking
change. Preparation uses the runtime's typed missing-reference errors, displays
syntax offsets once, and sorts bracketed diagnostic indices numerically. Cached
condition validation remains per use site, including shared reusable actions.
XPath, AsyncAPI, external workflow calls, non-RFC9535 JSONPath and nested workflow
calls that require their own dependency scheduling are explicit checked-path
capability errors. Input schemas remain available for caller validation; fetching,
cross-document resolution and JSON Schema execution stay in later stages.