Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 55 additions & 12 deletions conformance/sdk-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Their SDK installation lists do not widen that scope.
| Signals and queries: Server `signals-queries-published-artifacts.sh` | PHP/Python/Rust clients and workers, including cross-language calls, Rust query immutability and cold-restarted instance state. | Read the direction-specific scenarios and histories. The crate pin alone proves none of them. |
| Workflow updates: Server `workflow-updates-published-artifacts.sh`; Sample App `scripts/sdk-updates.sh` | Server's embedded probe, directly driven worker-protocol validation controls, PHP SDK client/worker process boundary, Python installed-package surface fixtures, CLI and Waterline diagnostics. The Python fixture uses simulated HTTP responses. Sample App separately executes all nine PHP/Python/Rust client-to-handler directions and completed duplicate directions against a live published Server. It checks accumulated state, read-only queries, all-worker SIGKILL/replacement and queued updates in each worker runtime. Handler failure and validator refusal target Rust. Rust also checks original workflow input, three signal argument shapes and completion immediately after an acknowledged update. | Other command-ordering races and process loss during a handler's external effect require additional fixtures. Keep Server's protocol controls and simulated Python client fixtures distinct from authored SDK validator-worker evidence. PHP SDK validator authoring is absent and Rust refuses validator contracts. Their implementation and embedded PHP support remain in [#234](https://github.com/durable-workflow/.github/issues/234). |
| Deterministic replay: Server `replay-published-artifacts.sh` | Separate installed PHP, Python and Rust shards. Python reconstructs fixture history, including simulated restart controls. Rust uses actual Server calls and gracefully replaces Worker instances within one process. Inspect each selected package’s actual shard and outcome. | These surfaces do not establish OS process loss or registry-package upgrades. Pair affected histories with their runtime restart and upgrade cases. [Evidence boundaries](#interpret-replay-skew-and-migration-evidence). |
| History/list observation within existing experiments: Sample App readers and CLI `workflow:history` | The child, activity-recovery and update observers explicitly join Python history pages and guard repeated tokens. CLI history collects pages for JSON output or streams events as JSONL. These are inspection paths, separate from the worker's own history fetches. | [SDK iterator delivery](https://github.com/durable-workflow/.github/issues/247) needs actual multi-page history/list results through each claimed client binding. A manually paged observer or a constructed reader test does not establish that product API or a live multi-page SDK result. |
| History/list observation: SDK client iterators, Sample App readers and CLI `workflow:history` | PHP, Python and Rust publish lazy workflow-list and exact-run history iterators. The [binding-specific evidence](#read-complete-histories-and-lists) includes installed multi-page Python and Rust observations on separate tuples. Existing Sample App readers join pages explicitly; CLI history collects JSON or streams JSONL. These client paths are separate from worker history fetching. | PHP's installed multi-page qualification remains unfinished in [#247](https://github.com/durable-workflow/.github/issues/247). Source tests, manually paged observers and another binding's result do not establish it. Keep each installed tuple and its actual pages separate. |
| Workflow lifecycle: Server `workflow-lifecycle-host-published-artifacts.sh` | The host extracts probes from the selected published Server image. PHP runs an installed SDK worker subprocess. Python exercises an installed client with simulated HTTP and serializes workflow commands. Rust runs authored workers, separate continuation processes and concurrent cancellation replacement. [Interpret each surface separately](#interpret-lifecycle-execution-surfaces). | Python worker execution and process recovery need actual worker cases. Rust cancellation replacement inside one probe process does not establish SIGKILL/cold-process recovery. Select actual continuation, retry/timeout, cancellation and termination outcomes for the exact tuple. Terminal cancellation and cooperative cleanup are separate contracts. |
| Worker versioning: Server `worker-versioning-published-artifacts.sh` and `worker-versioning-rust-host-published-artifacts.sh` | PHP/Python protocol-client build cohorts and mixed pinning, plus Python no-compatible-worker, replay and adversarial shards. Managed Rust SDK workers execute registration, pinning, promotion, incompatible refusal, cache eviction, SIGKILL/cold replay and drain/resume with queued work and recovery diagnostics. Source-bound handlers exercise changed/missing-definition refusal, divergent peer conflicts, unchanged recovery and a changed-build positive control. Selecting `DW_RUST_SDK_PREVIOUS_VERSION` compiles identical application sources against two published registry crates and preserves an original unversioned run through the upgrade and another SIGKILL, including the older client's result, both signals and one recorded effect/completion. The focused command also executes all four Rust/PHP and Rust/Python build-cohort directions with actual SDK workers and durable results. | The crate upgrade covers the selected version pair and signal/side-effect history. Changed application code, other durable operations and adding build IDs to existing unversioned histories need their own upgrade cases. Mixed build routing does not establish interchangeable cross-language histories or a shared build identity. |
| Namespaces: Server `namespaces-published-artifacts.sh` and Sample App `sdk-namespaces.sh` | Server authorization/routing, PHP and Python SDK paths, CLI and Waterline namespace surfaces. Actual Rust clients/workers execute remote activities in two namespaces sharing queue/type names, use separate namespace-bound role credentials, reject wrong-role/cross-namespace reads, signals, starts, registrations and polls, and retain original runs/activity attempts/signal waits after SIGKILL and replacement. The published Server's cross-namespace workflow-ID reservation also rejects duplicate IDs explicitly. | Rust namespace selection and execution are covered through real SDK requests. Namespace CRUD remains the published Server API and PHP/Python/CLI surface. This does not establish namespace deletion/retention during active Rust work or Rust SDK namespace-administration methods. |
Expand Down Expand Up @@ -189,9 +189,13 @@ Default cleanup calls Compose down with volumes for the selected project.
`--keep-stack` retains the stack for inspection. Retire that same stack after
review, and remove this run's disposable results after recording the sanitized
outcomes. Backend recovery alone does not qualify SDK workflow continuity.
The audited c367 runner can [lose its JSON result when cleanup times out](https://github.com/durable-workflow/server/issues/325#issuecomment-6369070712).
A missing result is incomplete qualification. This documentation change does
not correct that runner defect.
The historical c367 runner could [lose its JSON result when cleanup timed out](https://github.com/durable-workflow/server/issues/325#issuecomment-6369070712).
[Server #700](https://github.com/durable-workflow/server/pull/700) merged the fix.
The [repaired runner](https://github.com/durable-workflow/server/blob/c40707776ba0ae424985024d2ea341a6bdbe71c9/scripts/conformance/single-region-failover-published-artifacts.py#L2216-L2290)
records cleanup failure separately and still writes the phase result. Check
the selected runner's bytes rather than assuming an older published copy has
that fix. A failed cleanup or a missing result remains incomplete qualification;
the source repair alone is not a new failover result.

## Run the MCP operator loop

Expand Down Expand Up @@ -407,11 +411,37 @@ records with the owning run's evidence; leave unexecuted cells unqualified.

## Read complete histories and lists

PHP `workflowHistory` and Python `get_history` return one page. Their workflow
listing methods also return pages. Follow the opaque `next_page_token` until
the response reports no next page when collecting complete evidence. Keep the
original namespace, workflow/run IDs and list filters fixed. A single page can
be a valid API result without being the complete history or workflow list.
The existing page methods still return one page. Use the installed SDK's lazy
iterator when collecting complete histories or lists:

| Binding | One-page methods | Lazy iterators |
| --- | --- | --- |
| [PHP client](https://github.com/durable-workflow/sdk-php/blob/f9483bb2b5b45f591a82d9e5419c5b60a6e967c6/src/Client.php#L584-L696) | `listWorkflows`, `workflowHistory` | `iterateWorkflows`, `iterateWorkflowHistory` |
| [Python client](https://github.com/durable-workflow/sdk-python/blob/9e77bc8eca77f8bff7bc6dad6ed4bb002c480cb9/src/durable_workflow/client.py#L4135-L4284) | `list_workflows`, `get_history` | `iter_workflows`, `iter_history` with `async for` |
| [Rust client](https://github.com/durable-workflow/sdk-rust/blob/8f752e024576420f62030cc539a73176d1a5d099/src/pagination.rs) | `list_workflows`, `get_workflow_history` | `iter_workflows`, `iter_workflow_history` with `next().await` |

For a prepared client and a synthetic original workflow/run pair, force small
pages so a short history crosses a real page boundary. Python iteration inside
the caller's async function is:

```python
async for event in client.iter_history(workflow_id, run_id, page_size=1):
print(event)
```

The corresponding PHP generator is:

```php
foreach ($client->iterateWorkflowHistory($workflowId, $runId, pageSize: 1) as $event) {
echo json_encode($event, JSON_THROW_ON_ERROR), PHP_EOL;
}
```

Iterators follow opaque continuation tokens and yield one page's items at a
time. Keep the original namespace, workflow/run IDs and list filters fixed.
Stopping early leaves a partial observation. A page or an iterator traversal
does not turn a changing workflow list into a snapshot, follow a successor run
or subscribe to future history events.

Rust 4.6.0 publishes one-page `Client::list_workflows` and
`Client::get_workflow_history`, plus lazy `Client::iter_workflows` and
Expand All @@ -429,6 +459,19 @@ three filtered runs across three list pages and twelve events across six
history pages. That tuple is separate from the recorded Sample App Rust 4.1.0 /
Server 2.10.0 cohort. The receipt does not qualify another SDK or newer tuple.

The [installed Python observation](https://github.com/durable-workflow/sdk-python/pull/332#issuecomment-6877373099)
uses the normally published SDK 2.17.2 with Server 3.9.2. It checks five target
runs across three filtered list pages and four exact-run history pages, opaque
resume, early close, namespace-change refusal and three excluded controls.
Its earlier failed attempt remains separate. The
[published guide and independent readback](https://github.com/durable-workflow/durable-workflow.github.io/pull/548#issuecomment-6877599067)
cover the iterator and one-page contracts.

PHP's published source provides both generators, but its
[installed pagination qualifier](https://github.com/durable-workflow/sdk-php/pull/425)
has not delivered the corresponding live result or guide. That remaining
binding does not require repeating the accepted Python or Rust observations.

The existing [child reader](https://github.com/durable-workflow/sample-app/blob/main/polyglot/python_worker/scripts/sdk_children.py)
and activity-recovery/update readers join history pages explicitly and reject
repeated tokens. Their constructed reader controls, such as the child's
Expand All @@ -452,9 +495,9 @@ The installed worker paged-tail/cache results in
[#124](https://github.com/durable-workflow/.github/issues/124) remain bound to
their recorded tuple and worker behavior. They do not qualify client history
or list iterators. Remaining SDK helpers and cross-SDK qualification stay in
[#247](https://github.com/durable-workflow/.github/issues/247). The separate Rust
receipt does not complete the PHP/Python requirement. Manual loops and
documentation corrections do not complete the accepted product capability.
[#247](https://github.com/durable-workflow/.github/issues/247). The separate Python
and Rust receipts do not complete PHP's installed acceptance. Manual loops and
documentation corrections do not complete that remaining qualification.
Use each installed SDK's actual supported API.

## Run the published Nexus caller cases
Expand Down
9 changes: 7 additions & 2 deletions sdk-metrics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ and [exporter guides in all eight locales](https://github.com/durable-workflow/d
Python's recorder correction and Prometheus adapter have a
[normal registry-installed receipt](https://github.com/durable-workflow/sdk-python/pull/213#issuecomment-6368689818)
and a published [metrics and exporter reference](https://python.durable-workflow.com/reference/metrics/).
PHP implementation, emitted worker-task controls, installed acceptance and
exporter guidance stay open in [#233](https://github.com/durable-workflow/.github/issues/233).
PHP's client and worker recorder is shipped, with
[normal registry-installed Worker acceptance](https://github.com/durable-workflow/sdk-php/actions/runs/43400585178)
and a published [OpenTelemetry/exporter guide](https://php.durable-workflow.com/operate/metrics/).
The original six-instrument feature in
[#233](https://github.com/durable-workflow/.github/issues/233#issuecomment-6839951301)
is complete. Later contract revisions and installed tuples retain their own
adoption and qualification receipts.
One SDK's delivery does not establish another SDK's adoption.

Consumers should pin the contract's Git commit. SDK tests load that one list
Expand Down
Loading