Skip to content

feat: add cooperative cancellation requests and claim-bound delivery - #291

Merged
rmcdaniel merged 63 commits into
mainfrom
feat/cooperative-cancellation-service
Oct 6, 2026
Merged

rmcdaniel merged 63 commits into
mainfrom
feat/cooperative-cancellation-service

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Implements the Server cancellation surface for shared #136.

Supported release boundary

Whole-run cooperative requests expose immutable context and one bounded parent/child/Activity tree. Managed Activity stop receipts fence stale results. Original delivery and cleanup authority survive worker replacement. The diagnostics API explains the entire cascade and cleanup outcome. General independently cancellable scopes remain a disabled source preview outside the supported release claim.

Current pushed head deb8be3a1e7b98e38a12ec5579850bdd1ef442e5 prepares Server 2.5.0-rc.1 with worker protocol 1.20 and Helm 0.1.137-rc.1. Composer locks the published Native 2.4.0-rc.2 at 200a3c0ffa1e90557619221458deb3516b8cf955, including the qualified scheduler correction in Native #610. The installed package version, reference and watchdog bytes match that release. Rust's supported version range includes the approved 3.x major. Generated release consumers are synchronized, and RC chart versions retain immutable publication and ordering checks.

Qualification

Paired source qualification passes 321 cases / 12,123 assertions on each of SQLite, MySQL and PostgreSQL, plus affected SQLite checks. Server source is f862da30f895527fbdb4da6be8c021d8be0c37a5 with Native 22fc0885681a26b00681f19efce87298ec55d97a.

Final PHP/Python/Rust source qualification passes 50 cases / 2,789 assertions. Its required mixed cascade passes 237 assertions and completes both runs Cancelled 17.169470 seconds after the original request, before the original 30-second deadline. Physical callback stop without application heartbeats, stale fencing, actual cleanup-worker SIGKILL, replacement replay, duplicate identity/deadline and API/CLI inspection pass.

Captured canary deadlock and correction

The instrumented canary captured the actual cause behind the retained performance finding. At 05:51:37 one transaction held a leased workflow task and awaited its run, while repair held that run and awaited its tasks. This passing canary exposed the internal deadlock despite returning no 503 responses.

Correction f6ceecee makes the affected Server mutations acquire the run before the task, revalidate the task's run association under the lock, and preserve owner/attempt fencing inside the transaction. Failure responses also recheck ownership after acquiring the locks. Namespace checks remain part of every acquisition.

Eight actual two-process repair races pass with 240 assertions against the published Native RC on MySQL and PostgreSQL. They cover heartbeat, completion, failure and waiting-for-history responses. Each test observes a database waiter, proves that repair can still lock the task, and completes the real repair and HTTP request. Mounting the previous WorkerController into the same consumer makes the original heartbeat and completion tests fail with MySQL error 3572. Normal feature CI runs these cases on its existing isolated databases.

The next instrumented canary completed 22/22 checked standard workflows and 1,000/1,000 starts with no HTTP errors, but captured a separate scheduler deadlock at 06:24:21. Native's watchdog held the task and waited for the run held by operator repair. Its repair report recorded error 1213. Native #610 corrects lease and deadline acquisition order. Both actual races pass on MySQL and PostgreSQL with 43 assertions per database, and both fail with the original published watchdog.

The missing diagnostic envelope on task refusal is corrected and passes the existing ownership/error contracts and namespace regression: 11 cases / 278 assertions. Current affected checks against the actual published Native 2.4.0-rc.2 pass 174 cases / 26,633 assertions. Final feature CI passes 2,410 cases / 54,709 assertions. Replay/query HTTP, both database rolling-upgrade checks, chart source validation and the actual Helm installation pass.

The final instrumented canary passes unchanged workload and thresholds: 1,000/1,000 starts, 17/17 standard workflow completions, all 82 readiness requests successful, no HTTP errors and no scheduler repair failures. Its readable InnoDB trace contains no detected deadlock, and all-deadlock logging was enabled with error verbosity 3 throughout the workload. The attempted global status counter is unavailable on this MySQL build and returned no row, so the finding uses the actual engine trace and full log rather than claiming a numeric counter. Stable follow-through will collect MySQL's INNODB_METRICS.lock_deadlocks counter instead.

The preceding canary's single readiness refusal was a bounded Redis transport probe_timeout, not an observed SQL deadlock. It is tracked separately when inspecting the final canary. A passing HTTP summary alone will not substitute for checking its database and scheduler diagnostics.

Next actions

The corrected candidate gates pass and the canary trace has been checked. Publish both image architectures and the RC chart, then run the registry-only mixed cascade at the immutable digest. Waterline and the site complete the inspection and documentation surfaces. Shared #136 remains open until published acceptance and the qualified stable release are complete. No Cloud deployment or capacity claim is made by this PR.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Connected Python/Server source qualification now passes eleven SQLite cases at Python 119747bb2fb838f6dff64c9938c780414a074b99 and Server 2e2d6b31df981e98c1a054a8953e9efe95d17e6e. Scenario evidence covers actual SIGKILL/cold process replacement, shutdown grace and expiry, original request/deadline and one canonical marker, waiting timer, local async/synchronous execution, remote heartbeat/result/failure fencing, deadline, termination and a discarded successful delivery acknowledgment.

The current default remains protocol 1.19. Explicit source candidate protocol 1.20 now discovers the capability through the same policy used for request admission. Python's normal suite passes 1,618 local tests, Ruff and strict mypy. Server's affected filter passes 145 tests and 5,165 assertions, with Pint passing.

Normal Python CI, Server CI and an explicit exact-pair MySQL qualification are running. The candidate run's three supported Python, package, corpus and lint jobs pass. It retains connected JUnit evidence and removes its stack.

Next: finish those source gates, then PHP/Rust equivalents, coordinated protocol/specification activation and the exact published service tuple. These source drafts do not authorize a published cooperative capability claim. Completed local task resources are being removed.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Connected Python qualification complete

At Python 119747bb2fb838f6dff64c9938c780414a074b99 and Server 2e2d6b31df981e98c1a054a8953e9efe95d17e6e, normal Python CI, docs and boundaries pass. The explicit candidate MySQL run also passes every job. Its integration finished at 02:29:45 UTC on October 1, with 33 passed and one existing CLI-binary skip in 80.19 seconds. All eleven cooperative cases are present and passed in the downloaded JUnit artifact, retained through October 8. The log verifies the exact Server SHA and teardown passed.

Full scenario evidence covers original identity/deadline/one marker, a discarded successful delivery response, real SIGKILL and cold process replacement, local async/synchronous and remote fencing, shutdown grace/expiry, waiting timer, deadline and termination. Local SQLite passes all eleven cases. All local task containers, worktrees, dependencies, proofs and images are removed. Downloaded CI reports and transport files are removed after this handoff.

Server's source/corpus CI passes 2,279 tests and 47,800 assertions. MySQL replay/query topology passes. Polling bounded-growth smoke remains running. Both PRs remain drafts and default protocol remains 1.19.

Next: PHP/Rust request, delivery, canonical replay and shielded cleanup parity, remaining backend concurrency, coordinated specification/capability activation and the exact published Server/SDK tuple. No published cooperative capability is authorized by these source-only results.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Remote activity observation qualified at 073a516bbd4063f57d4ad65ad732ec423131c8ff

The additive candidate1.20 POST /worker/activity-tasks/{taskId}/status is implemented and all normal Server gates pass at this exact head. Full feature/corpus and source qualification runs 2,300 tests / 47,999 assertions, with six existing PHPUnit deprecations. MySQL replay/query HTTP topology, polling bounded-growth smoke/performance qualification and both public boundaries pass. Local PHP8.4.26 passes 184 tests / 7,982 assertions, Pint on all four changed PHP files, worker OpenAPI evolution23→25 and git diff --check.

The21 new status cases cover exact namespace/task/attempt/owner fencing, stale attempts, canonical activity cancellation, terminal cancel/terminate, lease expiry and authored heartbeat/execution deadlines before timeout repair. They prove preservation of attempt, execution, task, worker registration, required session and history. Required sessions must remain active, owned and inside their lease/TTL. Missing/replaced/closed/expired sessions refuse continuation without repair. Backend pressure returns retryable503 with the attempted fence and no continuation grant. Observation remains available under draining/fenced storage admission.

This uses the existing published Workflow2.3.0 attempt observation primitive. It never renews an attempt lease, user heartbeat, registration or required session. The existing five-minute activity lease and authored user heartbeat renewal behavior remain. A pending cooperative request is not delivered cancellation. Publication must independently validate the attempt fence, and a prior observation is not a reservation.

The worker OpenAPI candidate advances to25. Default released protocol1.19 and terminal endpoint behavior remain unchanged. PHP PR91 is wiring the actual owning Worker to bounded observations and the existing process supervisor, with user heartbeats proxied separately. Actual blocked remote callbacks, shutdown, owner death and cold workflow replacement are the next connected qualification. This Server result does not by itself establish that SDK lifetime behavior. The draft remains gated by per-language parity and exact published-tuple conformance before capability activation or release.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The cooperative Server candidate now consumes published Workflow 2.3.1 at fb3f3e59a4342fdebf8ced6160798906c3ee4387. Exact Server head is c32434cc784a1bf870dcf19568bef944a320f6a7. It merges the reviewed Server #292 dependency/release-metadata change into the previous 073a516bbd4063f57d4ad65ad732ec423131c8ff candidate. The candidate's service implementation is unchanged and protocol defaults remain 1.19. Normal source checks have restarted for this exact tuple.

Workflow's complete source matrix and all 16 published Laravel/PHP upgrade combinations pass. Server #292 is separately qualifying stable image 2.4.35. A focused ordinary-protocol signal drill reproduces the expired-workflow/older-active-activity defect on published Server 2.4.34 and PHP SDK 2.1.6, so this repair also affects existing service callers.

The entire Python candidate CI is dispatched at unchanged Python 88f0e31bf1736271deaabcc67d74df9ce98df491, with server_commit=c32434cc784a1bf870dcf19568bef944a320f6a7 and cooperative_qualification=true. It must pass the actual remote-worker supervision and SIGKILL cases using the published native correction. This is source-candidate qualification, separate from Server #292's published-image PHP/Python/Rust follow-through and shared #136's activation/reclaim/Rust gates.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Heartbeat ownership interleaving reproduced and fixed at source

The ordinary protocol 1.19 regression fails against unchanged main d0692b171a0cabe6eefdc8bfc0f82d249e16128d with locked published Native Workflow 2.3.1. Its two HTTP kernels perform actual Native status, claim and renewal. The fixture only provides an IPC barrier and clocks crossing the one-second lease expiry. It does not edit lease rows or fabricate Native results.

Observed baseline:

{"heartbeat":{"workflow_task_attempt":1,"lease_owner":"original","renewed":true},"replacement_claim":{"workflow_task_attempt":2,"lease_owner":"replacement"}}

The same Native task ID was present in both responses. The positive heartbeat therefore identified a claim that no longer owned the task.

The fix in #294 head 226025ffe3e0c1af98a77c01932a50f41799d8d8 holds the namespace-scoped task lock across ownership validation and Native renewal. Local Pint and 79 focused protocol, ownership/error, success and poll-pressure cases pass with 4,286 assertions. The controlled race now retains the original durable owner/attempt and the replacement poll returns no task. Command: php vendor/bin/phpunit --filter 'WorkflowTaskHeartbeatRaceTest|WorkerProtocolOwnershipErrorContractTest|WorkerProtocolSuccessContractTest|SqliteWorkerPollLockPressureTest|WorkerPollBackpressureTest'.

Cooperative cancellation draft #291 carries the same locked renewal, plus the pending observation read inside that transaction, at 6be6cd39 (full exact revision available in its CI). Its 24 focused cancellation protocol and concurrency cases pass locally with 545 assertions, preserving the original request/deadline and one canonical request without inventing delivery.

Normal CI is running for both heads. This source result does not claim a published image or Cloud deployment. Next finish exact-head CI/review, publish Server 2.4.36/Helm 0.1.132 independently of cooperative cancellation and verify the affected published worker cells. Rust coordinator qualification then uses the requalified #291 head. Default protocol 1.19 and ordinary capabilities remain unchanged.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Published Server 2.4.35 reproduces the ownership defect

The same committed regression ran inside the unchanged published Server image durableworkflow/server@sha256:49560f7f861271931125348a9d01638cd722e13ee976b5b732ef122548f15dab with its own PHP 8.3.35, Laravel and Native runtime code. PHPUnit 11.5.55 and Mockery 1.6.12 were mounted as separate test tools, together with the repository's tests. No application or vendor file was replaced. Reflection receipts verify that the controller and Native bridge load from the artifact, and both artifact provenance records name Native 2.3.1 at fb3f3e59a4342fdebf8ced6160798906c3ee4387.

The two actual HTTP kernels reproduce:

{"heartbeat_status":200,"heartbeat":{"workflow_task_attempt":1,"lease_owner":"original","renewed":true,"reason":null},"replacement_claim":{"workflow_task_attempt":2,"lease_owner":"replacement"}}

Both responses identify the same actual Native task. The unchanged published image therefore fails the ownership assertion, with 16 assertions reached. SQLite clocks and an IPC barrier control the interleaving; the harness does not edit any lease, owner or attempt row.

The original full CI result exposed an overly strict test assertion, not a valid positive acknowledgment. PHP 8.3 uses deferred SQLite transactions even when transaction_mode is configured, allowing replacement to win. The fixed transaction retries and returns a correct owner-mismatch refusal. The regression now requires either a positive acknowledgment matching the durable original claim or that exact refusal together with proof of the replacement claim. The same change preserves the cancellation request and cleanup deadline in #291. This still fails the old published image.

Next complete revised-head CI and review, publish Server 2.4.36, repeat this exact-image regression and verify the published PHP/Python/Rust lifecycle tuple before closing #293.

…ellation-service

# Conflicts:
#	app/Http/Controllers/Api/WorkerController.php
@rmcdaniel

Copy link
Copy Markdown
Member Author

The ordinary-protocol heartbeat ownership fix has shipped independently as Server 2.4.36, and #293 now has exact published before/after regression and published PHP/Python/Rust lifecycle evidence.

This draft incorporates merged main at 898c51375ddcb2c25588eb63e41fed26a3fd61b2. Current draft head is 24b54c9f8b3f84cad93ec58d5d7cd2f95160458d. Ownership validation, renewal and the candidate cancellation delivery read share the locked transaction. Default protocol 1.19 and the explicit candidate protocol 1.20 boundary remain unchanged.

Local formatting and the focused ownership/cancellation cases pass 25 cases and 565 assertions. Exact-head feature CI passes 2,302 cases and 48,041 assertions. Boundary and replay/query checks pass. Polling smoke is still running at this handoff, so no completed all-checks claim is made yet.

Next product action remains Rust #55's real claim/heartbeat cancellation carrier, canonical delivery refresh and replay coordinator, including callback ownership, replacement and physical lifetime checks. Candidate Server/Native and per-language connected gates must use the updated exact source tuple before the final published tuple is released. This stable heartbeat patch does not qualify or activate cooperative cancellation.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The updated Server cancellation draft head 24b54c9f8b3f84cad93ec58d5d7cd2f95160458d now passes every normal exact-head check. Feature CI passes 2,302 cases and 48,041 assertions, and the formerly pending polling smoke passes. This source includes the independently released Server 2.4.36 ownership fence.

Rust #55 has advanced to 936303ddcea57789daf76889f5944d243758d7ce, with actual immutable claim/observation capture and bounded fenced history loading. All normal Rust exact-head CI passes, with 303 library cases and 24 integration/consumer/corpus cases.

Next action remains connecting that carrier to the Rust delivery/canonical-refresh/replay coordinator, preserving earlier command prefixes and proving committed delivery before application cancellation. The connected language and physical callback lifetime/ownership/replacement gates remain required before cooperative release or activation. Published Native remains Workflow 2.3.1.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Pending cancellation remains runnable after a command prefix

The real Rust Worker qualification found a missing Server successor. At Server 24b54c9f8b3f84cad93ec58d5d7cd2f95160458d, a worker correctly committed a side effect before its cancellation boundary. The run then stayed waiting, with the original request undelivered and its only workflow task completed. No successor existed. The other four connected scenarios passed.

Fixed in 555cf7ab4ed4e9a79b52475be76a6dfcf886dd70. Successful nonterminal completion by a cancellation-capable actual claim now ensures one workflow task remains available for an undelivered request. The check and creation share the existing fenced completion transaction and run lock. Existing ready/leased tasks are reused, delivered requests do not create successors, and terminal runs or expired cleanup authority cannot resume. The original request and deadline remain unchanged. Workflow remains the published 2.3.1 package at fb3f3e59a4342fdebf8ced6160798906c3ee4387.

Two regression cases cover request before and after claim, two prefix side effects, repeated completion rejection, a different successor owner, delivery at sequence 3, and no leftover runnable task after terminal cancellation.

Raw counterfactual on the preceding Server head:

test_prefix_completion_keeps_pending_cancellation_deliverable [before claim]
Failed asserting that actual size 0 matches expected size 1.
test_prefix_completion_keeps_pending_cancellation_deliverable [after claim]
Failed asserting that actual size 0 matches expected size 1.
Tests: 2, Assertions: 16, Failures: 2.

Focused protocol suite after the fix:

PHP 8.3.35 / PHPUnit 11.5.55
OK (23 tests, 496 assertions)

Local feature/Nexus/corpus/OpenAPI run:

Time: 03:24.539, Memory: 56.00 MB
Tests: 2304, Assertions: 47873, PHPUnit Deprecations: 6, Skipped: 9.

The local run omits nine external-service cases. Full Server CI supplies those services and is running. Exact-candidate connected qualification is also running for Rust, PHP, and Python.

Next: inspect those results, address any remaining actual Worker/recovery failures, then qualify the complete published tuple before activating the capability. This PR remains a draft. Default Worker protocol remains 1.19.

@rmcdaniel

rmcdaniel commented Oct 1, 2026 •

Copy link
Copy Markdown
Member Author

Current source qualification

Server 3c15bfb0f98e038febb657412f1ca97bbdb23ad8 retains the qualified successor-task fix for a pending cancellation after a prefix completion. Ordinary claims without the cooperative capability skip the extra task refresh.

All current normal gates passed:

Connected source checks use this exact Server commit and published Workflow 2.3.1:

Shared recovery and replay gates and complete published-tuple qualification remain open. This remains a draft. Published artifacts and ordinary Worker defaults remain unchanged.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Scoped cleanup transport implemented

Server 13114fafac00a7ef8aadc639af0883333e6bed48 now forwards the original scoped cleanup proof before single prepare/recover payload resolution. Atomic group validation accepts its exact scope/request/delivery shape. Native cd8c2ae08cd366d856adfc8241d9864e1b1a55ad checks canonical original authority before admitting any sibling.

Candidate document 45 defines strict root and scoped proof/snapshot alternatives. No caller deadline is accepted. Root shapes and default/published 1.19 are preserved. This source specification remains unfrozen, and scope execution remains unadvertised.

Local affected source checks pass 186/8747, zero errors/failures/skips. HTTP coverage includes duplicate prepare, claim replacement, unknown physical-stop state on recovery, second-attempt cleanup retaining the original snapshot and deadline, stale publication refusal and all-or-nothing groups. Forged request/scope/delivery identities and invented deadlines fail before payload resolution. Strict schema, Pint, public boundary and 44 → 45 evolution checks pass. Locked package metadata retains the same 118 versions/references, with Native source explicitly overlaid.

Ordinary CI and exact paired database qualification are running. Task-owned local resources are removed. Next is SDK cleanup/supervision and every hosting-claim renewal path, followed by real scoped SIGKILL recovery and operator inspection. The earlier unexplained Python recovery miss and the published/competitive gates remain open. This PR stays draft and #136 stays open.

@rmcdaniel

rmcdaniel commented Oct 4, 2026 •

Copy link
Copy Markdown
Member Author

Performance gate follow-up

The current Server head is 13114fafac00a7ef8aadc639af0883333e6bed48. The ordinary feature gate and paired Native/database qualification pass.

The first performance canary failed. One of 2,091 worker polls received HTTP 503 backend_lock_pressure from MySQL. The original artifact retains that response and the failed availability gate. All 1,000 synthetic start requests were accepted and 24 standard workflows completed with verified results/history. Health/readiness and standard workflow requests had no errors, all 24 measurement samples were retained, and final cache keys were zero. Those observations do not override the failed poll gate.

The source-built merge commit was 4888d39004a68697e901e7522fa5c6b98a10a856, with parents 7a592593c3a2c998626e819322e0117c002ef8b2 and the candidate head. Native remained the locked published 2.3.3 package, and the canary negotiated protocol 1.19. This workload does not exercise the new scoped cleanup admission, but attribution is still open.

The unchanged-threshold current main baseline, exact head 7a592593c3a2c998626e819322e0117c002ef8b2, and candidate repeat both pass. They each accept 1,000 synthetic starts and respectively complete 20/20 and 21/21 standard workflows with verified results/history. Both retain all 24 samples and finish with zero Server cache keys. Complete comparison and raw artifact links preserve all attempts. A passing repeat does not establish the cause or a fix. Keep this PR draft.

Next action: retain MySQL lock/deadlock evidence and diagnose the conflicting transaction path before claiming a correction. No performance limit was relaxed.

The paired source qualification subsequently passed: SQLite/MySQL/PostgreSQL
each 305 / 11,348, affected SQLite 317 / 3,667, zero errors/failures/skips.
Its exact provenance and raw XML/logs
were independently downloaded and checked for unique, complete case execution.

The preceding canary
also retained one MySQL backend_lock_pressure response and failed the same
availability gate. Its 1,000 synthetic starts were accepted and 19 standard
workflows completed with verified results/history.
The response cannot distinguish a deadlock from a lock-wait timeout. The canary
retains MySQL Docker logs but no database lock trace. The next diagnostic should
retain bounded MySQL lock/deadlock evidence before isolated-stack teardown,
then reproduce the actual conflicting transactions and verify claim fencing
and safe rollback before a runtime correction. Source inspection suggests
reviewing run/task lock order across claim and repair paths, but there is no
trace proving that explanation yet. A later passing repeat is not a fix.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Completed canary comparison

The exact current-main baseline and candidate repeat pass the unchanged
performance gate. Both use locked Native 2.3.3, protocol 1.19 and the same
120-second workload and threshold configuration. The candidate image is built
from merge 4888d39004a68697e901e7522fa5c6b98a10a856, combining main
7a592593c3a2c998626e819322e0117c002ef8b2 and candidate
13114fafac00a7ef8aadc639af0883333e6bed48.

Observation First candidate Main baseline Candidate repeat
Synthetic starts accepted 1,000 1,000 1,000
Standard workflows completed with verified result/history 24/24 20/20 21/21
Worker polls accepted / backpressured / errors 1,592 / 498 / 1 1,415 / 231 / 0 1,481 / 273 / 0
Retained measurement samples 24/24 24/24 24/24
Peak HTTP memory, MiB 134.3 144.0 141.0
Final Server cache keys 0 0 0
Gate Failed Passed Passed

Synthetic growth counts accepted starts. Only the separate standard workflow
rows count verified completions. The comparison establishes the observed
canary outcomes, not maximum capacity or a throughput improvement. Variation
is retained in the complete summaries. No threshold or workload was changed.

First candidate artifact,
baseline artifact,
repeat artifact
retain complete summaries, samples, errors, image provenance and logs. Both
repeat stacks, networks and volumes have successful cleanup receipts. No local
or provider resource remains from these canaries.

The first MySQL poll lock-pressure failure remains unexplained. The preceding
candidate also had that response. Next: preserve MySQL lock/deadlock evidence
before isolated canary teardown and reproduce the real conflicting transactions
before claiming a correction. #291 stays draft for the unfinished cancellation
model and exact published tuple. Current ordinary and paired source gates pass.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Pair Server with scoped hosting recovery

Server draft #291 base 13114fa, Native exact
acfb821f0d946857429e2c08f835528eb1167df8. Native ordinary/full database/unit/
coverage gates pass, with all 130 feature files / 2241 unique cases per database
and 89.36 percent coverage. Protocol 1.19 stays default/published, 1.20 unfrozen
and scope execution unadvertised. Shared .github #136 remains open.

First paired run
is in progress with the original Server fixtures. Inspection found four raw
claim comparisons that still require the pre-delivery long hosting lease.
Update this source-only HTTP fixture to require a live lease of at most ten
seconds, shorter than the original ordinary lease, while comparing every other
claim field except its updated timestamp exactly. Preparation remains unchanged
at this Native head. Original request/preparation/delivery identity and deadline
remain asserted. No Server runtime or published protocol dependency changes.

Run the affected scope-delivery HTTP class with the exact Native source overlay,
style and syntax before committing. Then qualify the corrected Server head
across supported databases and affected HTTP/schema suites. Retain any preceding
failure as diagnostic evidence, not a passing gate. Pending pre-delivery recovery,
SDK supervision/authorship, physical scoped SIGKILL, operator inspection and
published mixed-language/competitive qualification remain required.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Scoped hosting Server source pairing qualifies

Server 30063a6, Native source overlay
acfb821f0d946857429e2c08f835528eb1167df8. This Server component changes only
two HTTP test classes and their shared assertion helper. The lease stays live,
at most ten seconds and shorter than the original ordinary claim. Every other
claim field except its update timestamp stays exact. Original request,
preparation and delivery identity/deadline remain asserted. Preparation itself
does not shorten ownership at Native acfb. Pending actor receipts preserve the
original frame and unrelated work.

Ordinary CI
and complete paired qualification
pass at the exact Server head. SQLite, MySQL and PostgreSQL each pass
305 tests / 11,379 assertions, with zero errors, failures or skips. Affected
SQLite HTTP regressions pass 317 / 3,667, also without errors, failures or
skips. Downloaded JUnit independently confirms every case exactly once and
the unchanged case inventory against the preceding diagnostic, normalizing
only the deliberately renamed fixture method.

The separate locked-package feature suite passes 2,397 / 48,774, retaining
published Workflow 2.3.3 at 70d4fe48efd7dd796c35c1078b3d5ac43f738f4f,
with 55 reported skips and six PHPUnit deprecations. The source overlay is
explicit and separate. Local complete affected classes pass 56 / 3,844,
without errors, failures or skips. Pint, syntax and whitespace pass. All 118
installed metadata version/source/dist tuples match the unchanged lock.
All 581 Native source/config/Composer file hashes match qualified acfb and all
three Server changed file hashes match the local runtime.

Hosted raw source evidence
retains all supported database JUnit, affected regressions, command logs and
exact provenance. Native's full supported database/unit/coverage/quality gates
qualify acfb separately. Failed first pairing and cancelled intermediate pairing
remain diagnostic evidence. This Server component makes no runtime, dependency,
OpenAPI, release, image, SDK conformance or managed deployment change.

Next: authenticated preparation recovery
is under separate qualification because waiting for child/actor receipts must
not postpone recovery. Request-only recovery, SDK scope authoring/supervision,
physical scoped worker SIGKILL, coherent inspection and the exact published
PHP/Python/Rust +30-second cascade remain delivery gates. Shared #136 stays open,
all cancellation PRs draft, default/published 1.19 and unfrozen 1.20 unchanged.
The prior MySQL canary lock-pressure and Python recovery findings remain
unresolved. Local test containers and scratch are removed after raw evidence
retention. Evidence review January 2, 2027.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Source pairing update at Server 4429d5815f71410aeeaa9e250253f1b799336240 / Native 6880706bad722cce69c19dd94a42d54df9771a41.

Only three Server test files change. First authenticated preparation must shorten the original ordinary claim into a live interval of at most ten seconds. Valid preparation/delivery retries may renew an already bounded interval. All other claim fields remain identical. Pending stop-receipt checks keep run/activity/history snapshots unchanged. The replacement HTTP fixture now uses watchdog repair and worker polling instead of manually incrementing the attempt.

Both complete affected HTTP classes pass locally: 56 unique tests / 3,848 assertions, no errors, failures or skips. The case inventory matches the preceding two-class qualification. All three changed files pass Pint and syntax. All 118 ordinary installed metadata tuples match the unchanged Server lock. Three Server file hashes and 581 Native source/composer hashes match. The Native source overlay is explicit and separate from installed published Workflow 2.3.3 metadata.

Full source pairing 37238088120 and ordinary package CI 37238035885 are running at this exact head. The new pairing results are pending. The prior Server 30063 / Native acfb pairing remains qualified separately.

This is source evidence, not physical scoped worker SIGKILL, SDK-authored scope execution or the complete published mixed-language scenario. Default protocol remains 1.19, candidate 1.20 unfrozen, scope execution unadvertised, and this PR draft. Shared #136 stays open through its complete stronger-model acceptance gates.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The Server 4429d58 / Native 6880706b source pairing 37238088120 hit the source job's 20-minute CI limit. It is not a complete paired qualification.

Downloaded JUnit independently verifies SQLite and MySQL each pass 305 unique cases / 11,383 assertions, zero errors/failures/skips, preserving the preceding complete case inventory. Affected SQLite HTTP regressions pass 317 / 3,667, zero errors/failures/skips. PostgreSQL was interrupted with an empty JUnit file, so no PostgreSQL pass is claimed. Artifact 11316419748 binds Server 4429d58 and Native 6880706b in its provenance. Raw log, artifact and independent timing/inventory checks are retained.

The MySQL suite took 854.001 seconds, versus 684.953 seconds in the preceding qualified pairing. That preceding entire source job used 18 minutes 52 seconds, leaving little room in a 20-minute budget. Multiple classes increased in duration. These CI timings do not establish an application performance regression or its cause.

Increase only this source job's limit to 30 minutes, retaining the same three databases, 305 source cases, 317 regression cases, fail-on-skipped rule and exact Native overlay. No application timeout or original cancellation budget changes. Requalify the exact resulting Server commit and retain the interrupted run separately. Ordinary package CI, replay/query and the automatic performance canary pass at 4429d58. The earlier intermittent canary 503 remains a separate unresolved finding.

The complete published mixed-language, scoped SDK, physical recovery, operator-view and competitive gates remain open. Protocol 1.20 stays unfrozen and this PR stays draft. All local task containers and scratch were already removed before their deadlines.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Scoped preparation hosting recovery qualified in source

Exact pairing: Server d0d7e43, Native 6880706bad722cce69c19dd94a42d54df9771a41.

Authenticated preparation bounds recovery before a delivery can wait on child completion or activity stop receipts. Valid retries preserve original frame/root/deadline and may renew the existing recoverable hosting interval. Expired/replaced owners cannot revive it. Server's three changed test files exercise first preparation, valid retries, unchanged run/activity/history and actual watchdog replacement through HTTP polling.

Local affected HTTP classes pass 56 unique tests / 3848 assertions, zero errors/failures/skips. Three files pass Pint/syntax and source hashes. All 118 ordinary locked installed version/source/dist tuples match. Native's 581 source/composer hashes match the explicitly labeled overlay.

Full exact-head pairing passes. Downloaded JUnit independently verifies every 305 source case exactly once per database, with the preceding source inventory unchanged. SQLite/MySQL/PostgreSQL each 305 / 11383, affected SQLite HTTP regressions 317 / 3667, zero errors/failures/skips. Raw source artifact records both exact revisions. The separate locked published-package suite passes 2397 / 48774, retaining Workflow 2.3.3, with 55 reported skips and six deprecations. Ordinary CI, replay/query CI and automatic performance canary pass at the same Server head. Native's full qualification passes at 6880706b.

The first paired run at source component 4429d58 hit its twenty-minute job limit after complete SQLite/MySQL and affected SQLite passes. PostgreSQL has no complete report there. Current d0d7e43 differs only in allowing thirty minutes for that source CI job. All tests/databases/assertions remain required. Runtime timeouts and original cancellation deadlines are unchanged. Variation in hosted job times is not a runtime-performance result.

Local test resources are removed. This completes this source pairing. Request-only recovery before preparation, SDK-authored scopes/selective supervision, physical scoped SIGKILL/replay, coherent operator inspection, the exact published mixed-language +30-second cascade and fair competitive qualification remain required. Shared #136 stays open, both model PRs remain draft, default protocol stays 1.19, candidate 1.20 remains unfrozen and scopes remain unadvertised.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Pair the current Server source with Native c8be089f68cde92fa8289f2200e5b0cf939b181c request-before-preparation recovery. Native local qualification passes 489 / 4369 with three existing SQLite database-lock race skips, while its supported-database and ordinary CI gates are running at that exact commit.

Assert shortening at acceptance, where the original ordinary lease changes. Preparation and delivery can renew the already bounded claim. Add an unprepared request case: expired original HTTP owner is refused without mutation, TaskWatchdog repairs, HTTP poll acquires the replacement, duplicate preserves original identity/deadline without renewing it, old attempt stays fenced and replacement prepares/delivers under that same budget.

Qualify both complete affected HTTP classes and the existing supported-database source matrix with the immutable Native overlay. Ordinary locked-package CI remains separate. This is source qualification, with no dependency/runtime/protocol change and no physical worker kill, SDK-authored scopes, publication or deployment claim. Shared #136 remains open and the model PRs draft.

@rmcdaniel

rmcdaniel commented Oct 4, 2026 •

Copy link
Copy Markdown
Member Author

Current scoped request pairing

Server 92e9f12 pairs with Native
c8be089f68cde92fa8289f2200e5b0cf939b181c. One Server test file changes.
The fixture asserts ordinary-lease shortening at request acceptance and
bounded live renewal at preparation/delivery. The new unprepared-request case
refuses the expired original HTTP owner without mutation, repairs through
TaskWatchdog, polls the replacement over HTTP and preserves original request
identity/deadline on duplicate. The old attempt stays fenced. Replacement
prepares and delivers the first boundary under that original budget.

Both complete affected HTTP classes pass 57 unique tests / 4069 assertions,
zero errors/failures/skips. Independent inventory retains all preceding 56
cases and adds exactly that one recovery case. Pint/syntax pass. The changed
Server file and all 581 Native source/composer hashes match. All 118 ordinary
locked installed metadata tuples match, with the Native overlay separate from
the ordinary published Workflow 2.3.3 metadata.

Full source pairing
is running at this exact tuple, alongside separate locked-package CI.
Native's full gate at c8be089f reports two PostgreSQL fixture comparisons where
saved in-memory timestamps differ from their database round trip. The actual
recovery case passed. Native c30428e47720bab40aee290253f33f6d4006a669
corrects those before snapshots to read the stored row. Its complete request
class passes 33 / 242 with three existing SQLite database-lock race skips.
All 581 runtime/composer hashes match the c8be089f overlay used here. That
input commit remains explicitly c8be089f. Native's replacement full gate
is running at c30428e4. Supported-database completion and exact artifact verification remain
required before this component is qualified.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Accepted scoped cancellation is now recoverable before preparation in qualified source Native c30428e47720bab40aee290253f33f6d4006a669 and Server 92e9f12. Acceptance bounds the hosting lease under the original deadline. The real watchdog recovers the unprepared task, the stale owner remains fenced, and the replacement prepares the first delivery boundary. Duplicate requests preserve identity, deadline and current ownership.

Native full qualification and ordinary CI pass. Downloaded JUnit independently verifies all 130 feature files and 2255 unique cases exactly once per database. MySQL 2255/21479, PostgreSQL 2255/21420, zero errors/failures, three/eight existing skips. Unit 2400/17412, five skips/fifteen notices. Combined coverage 89.36% (62061/69444) exceeds the 87.85% baseline.

Server paired qualification passes with explicit Native input c8be089f68cde92fa8289f2200e5b0cf939b181c. Its 581 runtime/composer file hashes match c30428e4. Downloaded JUnit verifies all preceding 305 cases plus exactly one HTTP request-before-preparation recovery case on each supported database: SQLite/MySQL/PostgreSQL each 306/11604, affected SQLite 317/3667, zero errors/failures/skips. Separate published-package qualification 2397/48774 retains Workflow 2.3.3, 55 reported skips/six deprecations.

Both model PRs stay draft and shared #136 stays open. Default/published protocol is 1.19. Candidate 1.20 remains unfrozen. Next is SDK-authored scope execution and selective callback supervision, physical scoped cleanup-worker replacement and the coherent operator view. Published PHP/Python/Rust artifacts, the complete original-budget cascade and fair competitive qualification remain required. Local qualification resources are removed.

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 6, 2026 07:20
@rmcdaniel
rmcdaniel merged commit cd76bdd into main Oct 6, 2026
15 checks passed
@rmcdaniel
rmcdaniel deleted the feat/cooperative-cancellation-service branch October 6, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants