Skip to content

feat: strengthen canonical cancellation context and propagation - #603

Merged
rmcdaniel merged 129 commits into
mainfrom
feat/cooperative-cancellation-model
Oct 6, 2026
Merged

rmcdaniel merged 129 commits into
mainfrom
feat/cooperative-cancellation-model

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Implements the Native cancellation model for shared #136.

Supported release

Whole-run cooperative requests carry immutable request identity, reason, requester, source, lineage and the original cleanup deadline. Parent-close RequestCancel propagates cooperation. Activities and Children have explicit operation policies. Physical stop receipts fence stale publication. Replacement workers replay the same preparation/delivery boundary and resume shielded durable cleanup under the original budget. Cascade inspection explains the whole tree.

Native 2.4.0-rc.1 advertises worker protocol 1.20 and surface contract 5. Existing accepted protocols remain compatible. Historical suite-v47 1.19 specifications and fixtures remain unchanged. Independently cancellable scopes stay disabled by default and outside the supported RC claim.

Qualification

Current reviewed head is 8e6a8ca042f9c11677a4542a63d4e91c042539f8. Current PR checks and complete default-1.20 qualification are green, including all database cells, Laravel 9–13 upgrades, source analysis, regression corpus and the required coverage ratchet. Release-contract checks pass 64 cases / 932 assertions. Frozen protocol contracts pass 16 cases / 738 assertions.

The expanded MySQL shard 3 completes 754 cases / 7,149 assertions in 12:42 with three existing projection-failure skips. The bounded MySQL check permits 15 minutes, with a 21-minute total job ceiling. No cases were removed, and the shard verifier confirms every feature file appears exactly once. Legacy tests explicitly retain protocol 1.19 and the frozen historical specifications. These final test and CI adjustments leave production code unchanged.

Server qualification passes 321 cases / 12,123 assertions on each of SQLite, MySQL and PostgreSQL. The final PHP/Python/Rust source cascade passes 237 assertions and finishes both runs Cancelled 17.169470 seconds after the original request, before its 30-second deadline. Physical callback stop, stale fencing, actual cleanup-worker SIGKILL, replacement replay, duplicate identity/deadline and API/CLI inspection pass.

Publication follow-through

Publish the immutable Native RC, lock it into Server 2.5.0-rc.1, then qualify the exact registry SDKs and image digest. PHP #91, Python #90, approved Rust #55 and CLI #38 are merged and their RCs published. Waterline #139 and site #149 complete the inspection/docs surface. Shared #136 stays open through the required published cascade and stable release verification.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The required closure scenario is now part of docs/architecture/cooperative-cancellation-model.md: PHP parent, Python child, Rust remote activity and PHP local activity, one root identity and original 30 second deadline, real callback stops without application heartbeats, stale-attempt rejection, workflow-worker SIGKILL, replay and resumed cleanup, stable duplicate requests, all runs Cancelled before the deadline, and one cascade inspection view. This remains an acceptance gate to implement and qualify using published artifacts. Workflow 2.3.3 deadline recovery is merged into this branch as a prerequisite. Shared issue 136 remains open.

@rmcdaniel rmcdaniel changed the title design: strengthen cooperative cancellation model and propagation feat: strengthen canonical cancellation context and propagation Oct 1, 2026
@rmcdaniel

Copy link
Copy Markdown
Member Author

Exact source head 50e67c9 passed its PR quality, unit, MySQL feature, replay/counterfactual corpus and build gates. Local focused tests passed 140 cases with 1,726 assertions, and full PHPStan passed without errors. The immutable request context and deterministic original-budget replay foundation are implemented in this draft. Genuine child propagation, operation policies, portable exposure and the required published mixed-language cascade remain open. This is not a shipped model.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Candidate context/propagation foundation is pushed at aa784150cb2ccee0e7fa47ead9a182dc450c24c1.

  • A descendant request reads its parent's accepted canonical context from storage and requires a recorded direct child link to the selected current run. Callers cannot supply a replacement root, requester or deadline.
  • Children receive distinct local request IDs and retain one root identity, original requested-at, immutable deadline, requester, reason and lineage. Acceptance stays cooperative. It does not immediately close the child.
  • The first accepted request owns a run's identity, route and deadline. Same-root propagation and later direct duplicates return it unchanged. A different root receives cancellation_root_conflict with both existing/incoming identities and deadlines.
  • Unlinked/unrequested parents, missing legacy context capability, mismatched stored context and ancestor cycles receive explicit diagnostics. Late propagation retains an already-expired budget, allowing the published deadline repair to enforce it without a fresh timeout. Transaction retries clear their by-reference results.

Local affected regression checks passed 131 tests / 1,833 assertions, with a fresh SQLite file and zero failures/errors/warnings. ECS and full phpstan analyse src tests passed. Exact-head GitHub CI is running.

The PR remains draft. This primitive is not yet wired to automatic delivery/parent-close propagation or per-operation policies. Simultaneous-request database qualification, continuation semantics, portable SDK context, and the cascade API/UI view remain required before publication. The full published mixed-language 30-second SIGKILL/cleanup recovery gate still controls shared issue 136 closure.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Exact-head CI at aa78415 passed: MySQL execution, unit contracts, static/style checks, replay/counterfactual corpus and repository/public-boundary checks. https://github.com/durable-workflow/workflow/actions/runs/36924880935. The PR stays draft for the automatic propagation/policy/SDK/inspection work and required published mixed-language recovery gate.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Implemented candidate child cancellation policies at d7eb0ae7b0cbf742279a61d9b0d9c7c56ab4ab1c.

ChildWorkflowOptions::cancellationPolicy now supports TryCancel, WaitCancellationCompleted and Abandon. The default and historical schedules without a policy remain Abandon. Delivery reads the recorded policy, requests genuine child cooperation with the original root identity and deadline, and waits for canonical child terminal history when requested. Mixed parallel waits and selected child handles obey the same rule. A conflicting child root is preserved and reported, rather than overwritten.

ChildCancellationRequested and ChildCancellationResolved record both request identities, budgets, conflicts and the terminal history reference. The run timeline exposes the child cancellation details. A terminal projection alone cannot acknowledge cleanup completion.

Source verification completed:

  • 45 focused cases, 393 assertions, no errors, failures or skips. These cover authored child cleanup, all three policies, mixed waits, selected handles, duplicates, conflicting roots, historical policy fallback, immutable deadline expiry and the portable bridge.
  • Full PHPStan analysis passed. ECS and the whitespace check passed.
  • Exact-head PR CI: https://github.com/durable-workflow/workflow/actions/runs/36927319798 (running).
  • Full unit and unit coverage check are running locally with an isolated Redis dependency and a fresh SQLite database.

The portable bridge now reports delivered: false / cancellation_waiting_for_child while acknowledgement is pending. First-party SDK support for that pending state and connected qualification are next. Cooperative parent-close policy, activity policies, continuation and concurrent-root qualification, and the full published mixed-language cascade remain required. This draft stays open, protocol 1.20 stays unfrozen, and shared issue 136 stays open.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Child policy source verification is green at 224959965aac9dd3c172998c2da136ae29e699e3.

  • Exact-head PR CI passed: https://github.com/durable-workflow/workflow/actions/runs/36927802617. Quality, bounded MySQL feature selection, independent unit contracts, replay corpus/counterfactual checks and the final gate passed.
  • Full local unit suite: 2,167 tests, 16,553 assertions, no failures or errors. It reported 15 PHPUnit notices and 5 skips. Unit line coverage passed at 66.31%, above the repository's 60.00% unit floor.
  • Focused authored-child and portable-delivery suite: 45 tests, 393 assertions, no failures, errors or skips.

The temporary Redis dependency and its isolated network were removed after qualification. First-party SDK handling of pending child acknowledgement is now being implemented. This remains candidate source evidence. Full published mixed-language cascade, stronger-model qualification and shared issue 136 closure are still outstanding.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Parent claims park while child cleanup finishes

Holding a parent's workflow claim while awaiting child cancellation could occupy
the only PHP workflow worker and prevent it from running the child. The source
candidate now parks the parent in Server, completes its current task claim, and
returns claim_released: true. Canonical child terminal history wakes the parent
into a new task. That task replays the same authored boundary before cancellation
delivery and parent cleanup. The original root identity and deadline are retained.

Local source checks:

  • Native authored-child and portable bridge: 45 tests / 391 assertions, no
    failures, errors or skips. Full PHPStan passed.
  • PHP transport, worker and replay: 101 tests / 408 assertions, no failures,
    errors or skips. PHPStan passed. The transport fixture checks that one worker
    returns to polling, handles another workflow task, and replays the parent on
    a new claim. Connected single-worker qualification remains required.
  • Server response/schema: 24 tests / 576 assertions, no failures or errors.
    Pint passed. Worker OpenAPI evolution
    passed from main's version 23 to candidate version 25.

Native source is 6a32adbe442cd6a7aae3be8f891ce5e076041da7 and ECS passed.
PHP source is ac434c444a4330155a882c00eac0ff7bb7ed02e2. Server source is
4d9a4248d740579b99668ed97e94c893959fba0a. Both are pushed for exact-head CI.
Python and Rust still need this deferred-claim contract. Portable policy/context
exposure, genuine cooperative parent-close policy, activity policies, cascade
inspection and the complete mixed-language published 30-second SIGKILL scenario
remain required. Defaults stay protocol 1.19. Protocol 1.20 remains an unfrozen,
explicit source opt-in. No cooperative release or closure is claimed.

@rmcdaniel

rmcdaniel commented Oct 2, 2026 •

Copy link
Copy Markdown
Member Author

Next: durable local callback identity and physical stop

The existing remote stop receipt deliberately refuses local activities because
their authority is a workflow claim. Native embedded local execution records
ActivityScheduled and ActivityStarted before invoking application code.
Portable local completion currently reconstructs those rows from the completed
SDK report. That completed report cannot identify an in-flight callback that
must stop before cleanup.

Use the existing activity execution/attempt model for the stronger optional
local path. Before invoking a callback, prepare its durable identity under the
current workflow task, attempt and owner. A lost start acknowledgment must be
proved or retried idempotently before any application execution. Preserve authored
sequence and group metadata, normalized arguments/options and the original claim
snapshot. Reuse an existing prepared attempt when applying its eventual outcome.

The local stop receipt must bind to that original attempt and accepted
cancellation history. Mutable task ownership after replacement cannot substitute
for the original claim. It must support a confirmed stop before parent delivery
is deferred by child waiting. Report only after callback and supervisor join.
Unknown physical stop remains unknown, even when publication authority is gone.
Duplicate receipts keep their first identity, and late receipt evidence remains
explicit without renewing authority or the root budget.

Expose this through an optional backend interface and explicit source capability.
Keep the stable 1.19 local contract and existing terminal routes. The stronger
mode keeps local routing on the workflow worker without an ordinary activity
queue, while explicitly documenting process isolation and its callback/connection
requirements. Do not silently revise the published same_process contract.

Deterministic budget helpers also need an explicit recorded clock boundary.
For example, Python's current ctx.now() is initialized from workflow start
and stays fixed during replay. Subtracting it from a later cancellation deadline
would not measure the remaining cleanup budget. Keep existing replay semantics
and define the cancellation clock from canonical authored boundaries before
adding a convenience helper. Transport observation or later diagnostic events
must not change a previously authored cleanup decision.

Next source work is the shared Native preparation/receipt primitive and its
claim replacement, response-loss and stale-publication cases, followed by the
Server route and SDK supervisors. Then qualify actual local callbacks and the
required published mixed-language 30-second cascade. Record workflow lease,
heartbeat and repair settings. This plan does not claim those pieces implemented
or the shared issue complete.

@rmcdaniel

rmcdaniel commented Oct 2, 2026 •

Copy link
Copy Markdown
Member Author

Local callback stop receipt bound to the original workflow claim

Source head: 956c72b953b16d492ddd5eac4283884556900972. The PR remains a draft for shared issue 136.

Added ActivityCancellationAcknowledgement::recordLocalStopped(). It binds the report to the original activity attempt, owner, workflow task attempt and accepted cancellation request. It requires the canonical local start saved before cancellation and its original task snapshot. Embedded local preparation already saves that snapshot before invoking application code, so this change reuses it.

The original owner can report after another worker takes over the workflow task. A replacement claim cannot impersonate the original claim. The receipt preserves the original task snapshot, root identity and deadline. It neither changes nor renews the replacement task, activity attempt or cleanup authority. Duplicate reports return the first event. Late reports remain explicitly late. Missing, malformed or post-cancellation preparation is refused. The remote receipt path still refuses local callbacks.

The timeline now describes a local receipt's original workflow claim correctly. It does not describe that workflow claim as a cancelled ordinary activity task.

Local qualification: PHP 8.3.35, isolated SQLite file and Redis, container UID/GID 1000:1000. The affected portable cancellation, child policy, ordinary local activity, timeline and payload-contract suites pass 144 tests / 865 assertions, zero failures, errors or skips, in 69.432 seconds. ECS and affected PHPStan pass. JUnit SHA256:

fb12d385b81bba62c519a1a8548554a058b94dda43f7e38347ea369d887dbf00

The new cases check the saved claim from inside the actual embedded executor's mock callback before requesting cancellation. Its returned result cannot publish. These tests qualify backend authority and evidence. They do not prove that an SDK callback process physically stopped.

Commands:

vendor/bin/ecs check <affected PHP paths> --fix
vendor/bin/phpstan analyse <affected PHP paths> --memory-limit=512M --no-progress
vendor/bin/phpunit --configuration <isolated affected suite XML> --log-junit <artifact>

Exact-head CI passes quality, unit contracts, regression corpus and MySQL features. The explicit local receipt step passes 14 cases / 190 assertions, with zero skips, in 8.521 seconds. The bounded changed-feature suite passes 77 / 800, plus MySQL smoke 4 / 56. Unit contracts pass 196 / 1,256, and the timeline step passes 71 / 158.

Retained MySQL raw JUnit and selection evidence was downloaded and verified. Local-receipt JUnit SHA256 is 1d31c4544e311373c02b691f2af20d5916682a74e8671432cbb59faf9b51ae72. Changed-feature JUnit SHA256 is 31d1f7f10dd1e2ba613db7df8b8ffa91c36a00277c3c355017a26c7f1c884fd7. All required PR policy checks pass. The PostgreSQL, MariaDB, full feature and coverage jobs are outside the bounded PR selection and were skipped, rather than reported as passed.

Next: portable local preparation must acknowledge durable identity before application execution, preserve the authored command prefix and reuse prepared rows at completion. Then expose the optional Server/backend route and qualify actual local supervisors. The required published PHP parent, Python child, Rust remote activity and PHP local activity cascade, actual SIGKILL during cleanup and convergence before the original 30-second deadline remain outstanding. No publication or closure is claimed.

Raw local affected-suite JUnit
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
  <testsuite name="/evidence/affected.xml" tests="144" assertions="865" errors="0" failures="0" skipped="0" time="69.387166">
    <testsuite name="unit" tests="144" assertions="865" errors="0" failures="0" skipped="0" time="69.387166">
      <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" tests="60" assertions="553" errors="0" failures="0" skipped="0" time="50.987076">
        <testcase name="testOptionalCooperativeBridgeUsesTheExistingBinding" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="56" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="1" time="12.600108"/>
        <testcase name="testPortableChildWaitReleasesItsClaimUntilCanonicalChildCancellationCompletes" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="61" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="22" time="1.395666"/>
        <testcase name="testPortableWaitDoesNotTreatATerminalProjectionAsCanonicalAcknowledgement" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="118" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="6" time="0.948876"/>
        <testcase name="testPortableChildPolicyRejectsInvalidValuesBeforeCreatingAnyChild" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="147" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="16" time="0.418551"/>
        <testcase name="testExistingCustomBridgeDoesNotAcquireCooperativeCapability" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="164" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="2" time="0.113363"/>
        <testcase name="testDeliveryWithoutAScheduledCallReservesItsPositionAndPreservesCleanupAuthority" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="173" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="12" time="0.357011"/>
        <testcase name="testDeliveryRetryAfterCleanupSubmissionDoesNotCancelCleanupOrChangeIdentity" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="199" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.676056"/>
        <testcase name="testParallelDeliveryBeforeSchedulingReservesTheEntireAuthoredRange" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="225" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.554619"/>
        <testcase name="testDeliveryRevokesAnOpenActivityAttemptAndRefusesLateCompletion" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="243" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="10" time="0.749914"/>
        <testcase name="testDeliveryCancelsTheOriginalTimerAndItsQueuedTask" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="273" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="6" time="0.739202"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testWorkflowLeaseRecoveryPreservesAnOlderRunningActivity" tests="2" assertions="33" errors="0" failures="0" skipped="0" time="1.786153">
          <testcase name="testWorkflowLeaseRecoveryPreservesAnOlderRunningActivity with data set &quot;expired workflow lease&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="294" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="19" time="0.951201"/>
          <testcase name="testWorkflowLeaseRecoveryPreservesAnOlderRunningActivity with data set &quot;fresh workflow lease&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="294" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="14" time="0.834953"/>
        </testsuite>
        <testcase name="testRemoteCallbackStopReceiptIsSeparateFromFencingAndKeepsTheOriginalBudget" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="378" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="28" time="0.956495"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testRemoteStopReceiptRejectsAnotherOwnerAttemptOrRequest" tests="3" assertions="24" errors="0" failures="0" skipped="0" time="2.310876">
          <testcase name="testRemoteStopReceiptRejectsAnotherOwnerAttemptOrRequest with data set &quot;attempt&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="433" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.789709"/>
          <testcase name="testRemoteStopReceiptRejectsAnotherOwnerAttemptOrRequest with data set &quot;owner&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="433" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.760586"/>
          <testcase name="testRemoteStopReceiptRejectsAnotherOwnerAttemptOrRequest with data set &quot;request&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="433" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.760580"/>
        </testsuite>
        <testcase name="testMutableCancelledRowsCannotSubstituteForCanonicalCancellationHistory" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="453" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="6" time="0.700265"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testLegacyOrMalformedCancellationSnapshotCannotAuthorizeAWorkerStopReceipt" tests="2" assertions="14" errors="0" failures="0" skipped="0" time="1.595382">
          <testcase name="testLegacyOrMalformedCancellationSnapshotCannotAuthorizeAWorkerStopReceipt with data set &quot;attempt snapshot without identity&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="478" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.809038"/>
          <testcase name="testLegacyOrMalformedCancellationSnapshotCannotAuthorizeAWorkerStopReceipt with data set &quot;malformed attempt snapshot&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="478" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.786344"/>
        </testsuite>
        <testcase name="testLateStopReportRemainsLateAndCannotGrantAnotherCleanupBudget" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="507" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.771423"/>
        <testcase name="testRemoteStopReceiptCannotAuthorizeALocalActivityCallback" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="532" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.764814"/>
        <testcase name="testLocalStopReceiptKeepsTheOriginalWorkflowClaimAndDoesNotRenewCleanupAuthority" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="550" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="23" time="0.751122"/>
        <testcase name="testLocalOriginalOwnerCanReportAfterWorkflowTakeoverButTheReplacementCannotImpersonateIt" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="585" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="27" time="0.819992"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback" tests="8" assertions="88" errors="0" failures="0" skipped="0" time="5.196257">
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;legacy start without claim&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.657769"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;malformed claim&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.651474"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;another task&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.655920"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;ordinary activity task&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.658021"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;unclaimed task&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.646093"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;another original owner&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.650300"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;missing original attempt&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.646218"/>
          <testcase name="testLocalStopReceiptRequiresTheClaimSavedBeforeItsCallback with data set &quot;nonpositive original attempt&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="651" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.630463"/>
        </testsuite>
        <testcase name="testLocalStopReceiptCannotBorrowARemoteAttemptOrAnotherCancellationRequest" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="688" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="17" time="1.083465"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testLocalStopReceiptRejectsAnAbsentOrPostCancellationStart" tests="2" assertions="22" errors="0" failures="0" skipped="0" time="1.283522">
          <testcase name="testLocalStopReceiptRejectsAnAbsentOrPostCancellationStart with data set &quot;callback without durable preparation&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="712" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.657499"/>
          <testcase name="testLocalStopReceiptRejectsAnAbsentOrPostCancellationStart with data set &quot;post hoc callback start&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="712" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="11" time="0.626023"/>
        </testsuite>
        <testcase name="testLateLocalReceiptDoesNotRenewTheOriginalDeadlineOrReplacementLease" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="741" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="13" time="0.682531"/>
        <testcase name="testARecordedCallCannotBeRelabelledAsADifferentOperation" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="770" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="6" time="0.602392"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testOpenWaitsCanBeInterruptedWithoutRevokingCleanupAuthority" tests="4" assertions="30" errors="0" failures="0" skipped="0" time="3.001159">
          <testcase name="testOpenWaitsCanBeInterruptedWithoutRevokingCleanupAuthority with data set &quot;condition timeout unbounded&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="789" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.733894"/>
          <testcase name="testOpenWaitsCanBeInterruptedWithoutRevokingCleanupAuthority with data set &quot;signal timeout unbounded&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="789" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.752840"/>
          <testcase name="testOpenWaitsCanBeInterruptedWithoutRevokingCleanupAuthority with data set &quot;condition timeout 300&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="789" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.755899"/>
          <testcase name="testOpenWaitsCanBeInterruptedWithoutRevokingCleanupAuthority with data set &quot;signal timeout 300&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="789" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.758526"/>
        </testsuite>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testRecordedResultsBeforeTheRequestReplayNormally" tests="2" assertions="10" errors="0" failures="0" skipped="0" time="1.385638">
          <testcase name="testRecordedResultsBeforeTheRequestReplayNormally with data set &quot;result precedes request&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="830" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.679470"/>
          <testcase name="testRecordedResultsBeforeTheRequestReplayNormally with data set &quot;request precedes result&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="830" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.706168"/>
        </testsuite>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testInvalidDeliveryClaimsDoNotPartiallyApply" tests="9" assertions="45" errors="0" failures="0" skipped="0" time="3.511079">
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;another request&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.457423"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;future call&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.379129"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;zero call&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.379671"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;unknown kind&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.374346"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;zero range&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.385176"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;scalar range&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.388402"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;overflowing range&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.377773"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;absent selection member&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.391712"/>
          <testcase name="testInvalidDeliveryClaimsDoNotPartiallyApply with data set &quot;selection metadata on scalar&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="869" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.377446"/>
        </testsuite>
        <testcase name="testDeliveryCannotUseAnExpiredWorkflowLease" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="905" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.403811"/>
        <testcase name="testDeadlineExpiryClosesTheOriginalRequestWithoutDeliveringLate" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="920" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="6" time="0.460159"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testCleanupEndsWithTheOriginalCancellationOutcome" tests="3" assertions="21" errors="0" failures="0" skipped="0" time="1.569867">
          <testcase name="testCleanupEndsWithTheOriginalCancellationOutcome with data set &quot;return&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="941" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.516898"/>
          <testcase name="testCleanupEndsWithTheOriginalCancellationOutcome with data set &quot;throw&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="941" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.533060"/>
          <testcase name="testCleanupEndsWithTheOriginalCancellationOutcome with data set &quot;continue&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="941" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="7" time="0.519909"/>
        </testsuite>
        <testcase name="testTerminationRevokesCleanupAndCannotBeReplacedByCancellation" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="974" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.535415"/>
        <testcase name="testSelectionHandleDeliveryOnlyCancelsTheNamedOpenOperation" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="993" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="5" time="0.652635"/>
        <testsuite name="Tests\Feature\V2\V2PortableCancellationDeliveryTest::testRecordedParallelRangeIsCancelledAsOneAuthoredCall" tests="2" assertions="16" errors="0" failures="0" skipped="0" time="1.609256">
          <testcase name="testRecordedParallelRangeIsCancelledAsOneAuthoredCall with data set &quot;parallel barrier&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="1016" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.798940"/>
          <testcase name="testRecordedParallelRangeIsCancelledAsOneAuthoredCall with data set &quot;selection member range&quot;" file="/work/tests/Feature/V2/V2PortableCancellationDeliveryTest.php" line="1016" class="Tests\Feature\V2\V2PortableCancellationDeliveryTest" classname="Tests.Feature.V2.V2PortableCancellationDeliveryTest" assertions="8" time="0.810317"/>
        </testsuite>
      </testsuite>
      <testsuite name="Tests\Feature\V2\V2ChildCancellationPolicyTest" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" tests="8" assertions="118" errors="0" failures="0" skipped="0" time="16.337631">
        <testcase name="testWaitDefersParentDeliveryUntilChildCleanupHasCanonicalTerminalHistory" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="46" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="37" time="2.394106"/>
        <testcase name="testTryCancelRequestsCooperationButDoesNotWaitForChildCleanup" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="107" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="13" time="2.150710"/>
        <testcase name="testAbandonLeavesChildUntouched" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="128" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="7" time="1.319716"/>
        <testcase name="testMixedParallelWaitFencesActivityButStillWaitsForChildCleanup" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="140" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="14" time="2.513942"/>
        <testcase name="testHistoricalMissingPolicyRemainsAbandonOnColdExecution" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="158" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="5" time="1.358904"/>
        <testcase name="testSelectedChildHandleWaitsAtItsOriginalOperationRange" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="176" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="15" time="2.498814"/>
        <testcase name="testIndependentChildRequestKeepsItsRootAndReportsPropagationConflict" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="198" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="17" time="2.400740"/>
        <testcase name="testWaitingCannotExtendTheOriginalDeadlineWhenChildCleanupDoesNotFinish" file="/work/tests/Feature/V2/V2ChildCancellationPolicyTest.php" line="232" class="Tests\Feature\V2\V2ChildCancellationPolicyTest" classname="Tests.Feature.V2.V2ChildCancellationPolicyTest" assertions="10" time="1.700698"/>
      </testsuite>
      <testsuite name="Tests\Feature\V2\V2LocalActivityTest" file="/work/tests/Feature/V2/V2LocalActivityTest.php" tests="2" assertions="32" errors="0" failures="0" skipped="0" time="1.517829">
        <testcase name="testLocalActivityExecutesInWorkflowTaskAndRecordsMarkedHistory" file="/work/tests/Feature/V2/V2LocalActivityTest.php" line="30" class="Tests\Feature\V2\V2LocalActivityTest" classname="Tests.Feature.V2.V2LocalActivityTest" assertions="27" time="0.878552"/>
        <testcase name="testLocalActivityHeartbeatRenewsWorkflowTaskAndRecordsLocalMarker" file="/work/tests/Feature/V2/V2LocalActivityTest.php" line="108" class="Tests\Feature\V2\V2LocalActivityTest" classname="Tests.Feature.V2.V2LocalActivityTest" assertions="5" time="0.639278"/>
      </testsuite>
      <testsuite name="Tests\Unit\V2\CancellationHistoryTimelineTest" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" tests="71" assertions="158" errors="0" failures="0" skipped="0" time="0.543688">
        <testsuite name="Tests\Unit\V2\CancellationHistoryTimelineTest::testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata" tests="68" assertions="136" errors="0" failures="0" skipped="0" time="0.520450">
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;StartAccepted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007885"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;StartRejected&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007598"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowStarted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007748"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowContinuedAsNew&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007867"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildWorkflowScheduled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007299"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildCancellationRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007384"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildCancellationResolved&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007085"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildRunStarted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008117"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildRunCompleted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007281"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildRunFailed&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007103"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildRunCancelled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007178"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ChildRunTerminated&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008452"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ServiceCallStarted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007399"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ServiceCallCompleted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007145"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ServiceCallFailed&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007006"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ServiceCallCancelled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007095"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ConditionWaitOpened&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007657"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ConditionWaitSatisfied&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007390"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ConditionWaitTimedOut&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007939"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SignalWaitOpened&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007246"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SignalReceived&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007602"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SignalApplied&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007376"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;UpdateAccepted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007017"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;UpdateRejected&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007071"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;UpdateApplied&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007914"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;UpdateCompleted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008304"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;RepairRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007326"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;CancelRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007184"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;CooperativeCancellationRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007093"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;CooperativeCancellationDelivered&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007512"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowCancelled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007448"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;TerminateRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007791"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowTerminated&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007519"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ArchiveRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007589"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowArchived&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007458"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityScheduled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007254"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityStarted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007086"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityHeartbeatRecorded&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007132"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityRetryScheduled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008122"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityCompleted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008157"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityFailed&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007557"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityCancelled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007164"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityCancellationAcknowledged&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007532"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ActivityTimedOut&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007386"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;FailureHandled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007199"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SideEffectRecorded&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007063"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;VersionMarkerRecorded&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007490"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;TimerScheduled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008281"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;TimerFired&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007368"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;TimerCancelled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007130"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SelectionResolved&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007101"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SelectionOperationCancelled&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007446"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SearchAttributesUpserted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.016458"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;MemoUpserted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008718"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowTimedOut&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008207"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowCompleted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007857"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;WorkflowFailed&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007414"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ParentClosePolicyApplied&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007446"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ParentClosePolicyFailed&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007157"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ParentCloseCancellationRequested&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008129"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;MessageCursorAdvanced&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008225"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ScheduleCreated&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007712"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;SchedulePaused&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007294"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ScheduleResumed&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007504"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ScheduleUpdated&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007478"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ScheduleTriggered&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007095"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ScheduleDeleted&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.007118"/>
          <testcase name="testEverySupportedHistoryEventCanBeInspectedWithSparseMetadata with data set &quot;ScheduleTriggerSkipped&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="18" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="2" time="0.008093"/>
        </testsuite>
        <testsuite name="Tests\Unit\V2\CancellationHistoryTimelineTest::testStopReceiptExplainsTheOriginalAttemptAndBudgetWithoutGrantingAuthority" tests="2" assertions="18" errors="0" failures="0" skipped="0" time="0.015598">
          <testcase name="testStopReceiptExplainsTheOriginalAttemptAndBudgetWithoutGrantingAuthority with data set &quot;before original deadline&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="37" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="9" time="0.008215"/>
          <testcase name="testStopReceiptExplainsTheOriginalAttemptAndBudgetWithoutGrantingAuthority with data set &quot;after original deadline&quot;" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="37" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="9" time="0.007383"/>
        </testsuite>
        <testcase name="testLocalStopReceiptDoesNotDescribeItsWorkflowClaimAsACancelledActivityTask" file="/work/tests/Unit/V2/CancellationHistoryTimelineTest.php" line="80" class="Tests\Unit\V2\CancellationHistoryTimelineTest" classname="Tests.Unit.V2.CancellationHistoryTimelineTest" assertions="4" time="0.007640"/>
      </testsuite>
      <testsuite name="Tests\Unit\V2\HistoryEventPayloadContractTest" file="/work/tests/Unit/V2/HistoryEventPayloadContractTest.php" tests="3" assertions="4" errors="0" failures="0" skipped="0" time="0.000942">
        <testcase name="testEveryHistoryEventTypeHasAPayloadContractEntry" file="/work/tests/Unit/V2/HistoryEventPayloadContractTest.php" line="14" class="Tests\Unit\V2\HistoryEventPayloadContractTest" classname="Tests.Unit.V2.HistoryEventPayloadContractTest" assertions="1" time="0.000324"/>
        <testcase name="testPayloadContractRejectsUnknownProducerKeys" file="/work/tests/Unit/V2/HistoryEventPayloadContractTest.php" line="28" class="Tests\Unit\V2\HistoryEventPayloadContractTest" classname="Tests.Unit.V2.HistoryEventPayloadContractTest" assertions="2" time="0.000309"/>
        <testcase name="testSelectionResolutionAcceptsDurableWinnerMetadata" file="/work/tests/Unit/V2/HistoryEventPayloadContractTest.php" line="39" class="Tests\Unit\V2\HistoryEventPayloadContractTest" classname="Tests.Unit.V2.HistoryEventPayloadContractTest" assertions="1" time="0.000308"/>
      </testsuite>
    </testsuite>
  </testsuite>
</testsuites>

@rmcdaniel

Copy link
Copy Markdown
Member Author

Portable local preparation kernel qualified

Source effe23dda3fbd63b3bebdc62557e68c012065654 adds an internal, explicit protocol 1.20 preparation primitive. It records normalized local Scheduled/Started events and the original claim, canonical attempt, SDK attempt ID and deadlines before callback admission. Same-claim response-loss retries preserve that preparation without renewing authority. Cancellation, changed inputs/options or a reclaimed task refuse invocation. Encoded Avro aliases work without PHP class admission or an ordinary activity queue task.

Local history now identifies the original workflow claim for local activity events, including its leased status when the activity terminates. The canonical stop receipt remains bound to its saved original start snapshot.

Verification: isolated PHP 8.3.35, SQLite/Redis affected suite 171 tests / 997 assertions, no failures/errors/skips. Affected PHPStan and ECS pass. Exact-head CI passes quality, regression corpus, MySQL and unit gates. Explicit preparation 18 / 114, original-claim receipts 14 / 190, changed features 95 / 914 plus smoke 4 / 56, unit contracts 196 / 1,256, timeline 80 / 176.

Raw MySQL JUnit artifact, preparation XML SHA-256 545197d22385cbfef41c18144a41b9871f70b5caa6006b370cccf77d1f4c8509. Local affected XML SHA-256 fdc6b73b61a0d478ec4e7b3105ea595f2afcf228edcce45a872410f80655ae2e.

Commands: vendor/bin/phpunit -c <isolated affected-suite XML> --fail-on-warning --log-junit <artifact>, affected vendor/bin/phpstan analyse, vendor/bin/ecs check. CI explicitly runs tests/Feature/V2/V2PortableLocalActivityPreparationTest.php --testsuite feature --fail-on-warning and retains its JUnit.

This kernel is not connected to an endpoint or SDK callback path. Next: retained-claim prefix checkpoint and prepared outcome/retry/replay, followed by Server admission and physical local supervisors. Published protocol 1.19 remains unchanged. This PR remains draft and the shared published 30-second cascade remains required.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The PostgreSQL fixture comparison correction is committed/pushed as c30428e.

The first full gate at c8be089 completed with two failures in the new pending/expired request fixtures. They compared the saved model's timestamp strings against PostgreSQL's round trip, which removes the textual zero-fraction suffix. Downloaded shard JUnit independently verifies 567 / 5676, zero errors, those two failures and four existing skips. The actual request-before-preparation recovery case passed there.

Both before snapshots now read the stored rows and still compare every claim field. Only one test file changes. Corrected complete request class: 33 / 242, zero errors/failures, the same three existing SQLite database-lock race skips and unchanged case inventory. ECS/syntax, host/runtime test hash and all 125 pinned dependency tuples verify. All 581 runtime/composer file hashes are byte-identical to c8be089.

New full qualification and ordinary CI are running at c30428e. Server 92e9f12866be51e86d35b043597af3e705ff8122 passes local 57 / 4069 HTTP checks and its supported-database pairing is running with explicit c8be089 input, whose runtime bytes match the current Native head. Keep these source inputs and their artifact provenance explicit. Shared #136 remains open and the model PRs draft.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Accepted scoped cancellation is now recoverable before preparation in qualified source Native c30428e and Server 92e9f12866be51e86d35b043597af3e705ff8122. 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 c8be089. Its 581 runtime/composer file hashes match c30428e. 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

Copy link
Copy Markdown
Member Author

Scope recovery documentation now matches request acceptance at
6fcba5c64e9c5f673969b04906a35717e4b83421. Accepted requests bound shared
hosting ownership before the first preparation, allowing replacement to reach
that boundary within the original budget. The contradictory paragraph describing
an ordinary pre-preparation lease is removed.

The change is documentation only. Production source and tests are unchanged
from qualified c30428e47720bab40aee290253f33f6d4006a669.
Ordinary CI
and the public boundary check pass at the documentation head. PR #603 remains
draft, and published scoped SDK execution/recovery is still an acceptance gate.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Namespace repair reproduced and corrected

Workflow#605 is an independently shippable released-runtime defect, with
draft PR606 at
5a01b502a2cdc8e0f518a34c2341c569dcbf35c2. All seven missing task paths omitted
the run namespace. Namespace-scoped discovery could not see those tasks.
Eligible redispatch/recovery now also restores a missing namespace, preserving
existing namespaces and fresh tasks/current leases.

The new 35-case creation/recovery/guard inventory has twenty expected failures
against original main, then the full task-dispatch class passes 56 / 387,
zero errors/failures/skips. Original dependency lock and all 125 installed
tuples are unchanged. Static analysis and shard inventory pass locally.
Ordinary PR CI
passes. Full supported-database/quality CI
is running. Product-train is prepared for Workflow 2.3.4. No publication yet.

The cancellation candidate receives the same runtime correction plus a
deterministic test that forces the repair pass between Wait claim release
and the original stop acknowledgement. Original Native fails 1 / 7 at the
missing namespace. Corrected affected classes pass 135 / 1190. A final
additional before-deadline assertion passes in the exact case 1 / 24.
The request ID, deadline, callback ownership, original stop receipt, single
resume identity and stale publication fence are preserved. Candidate static
analysis passes with a 1 GiB analysis limit after the original 512 MiB analysis
process exhausted its configured memory. No container resource ceiling changed.

This reproduces the ready/unclaimed and queue/run visibility pattern from the
failed PHP connected run. That original artifact did not capture the task row's
namespace, so this deterministic proof does not fabricate that missing field.
Another connected run will use the corrected Native source, with the same PHP,
Server, Python, Rust and CLI inputs. The original failed run stays retained.
Shared #136 remains open and all cooperative source PRs remain drafts.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Corrected connected source qualification

Run 37266432981
passes on the frozen source tuple PHP 92c0f05f, Server 92e9f128, Native
89f46d44, Python 3c77a010, Rust 08824f29, CLI 933c554f.
Only Native changed from the preceding retained failed tuple.

  • Cancellation: 39 tests / 2157 assertions, zero errors/failures/skips.
    The preceding 39-case inventory is unchanged.
  • Memo restart: 1 / 67, zero errors/failures/skips.
  • Mixed PHP parent, Python child, Rust remote Activity and PHP local Activity:
    237 assertions / 24.347335 seconds, within the original 30-second budget.
  • All eight remote stop evidence sets retain the original request/deadline,
    task/attempt/owner fence, actual callback stop and canonical acknowledgement.
    The lost-reply case now resumes and completes cleanup. Application heartbeat
    remains absent in its no-heartbeat cases.
  • Hosted task stack and images were removed successfully.

The artifact is 11327325939,
retained until 2027-01-03 05:08:14 UTC. An independent verifier checked the exact
tuple, complete case inventory, receipts, worker diagnostics and cleanup.
Its initial assumption that the history API exposed event row IDs was corrected
against the actual response. IDs are verified through the accepted receipt and
worker diagnostic, with the canonical history payload independently matched.

The deterministic repair ordering reproduction and runtime correction are owned
by Workflow #605.
The original failed run remains retained. Candidate protocol 1.20 remains
unfrozen and unpublished, worker scope execution disabled, and shared #136 open.
The remaining scope model, inspection surfaces and exact published-artifact
qualification are still required before closing the customer outcome.

@rmcdaniel

Copy link
Copy Markdown
Member Author

The native cancellation draft now incorporates Workflow 2.3.4 main at
0471f1ebbb98c61fe53663086d62dc2db74db9e3. The namespace repair was already
present. Runtime source, tests, schemas, scripts and docs are unchanged from
89f46d4. The merge updates main ancestry, release metadata and coverage-upload
handling.

Ordinary PR CI
and full source CI
pass. Both databases execute 2291 unique cases, with 21723 MySQL and
21664 PostgreSQL assertions, zero errors/failures and the existing 3/8
skips. Quality, corpus, MariaDB probes and Laravel 9–13 source upgrades pass.
Measured line coverage is 89.39%, above the 87.85% ratchet. Both public
boundary runs also pass.

The connected PHP qualification
passes 39 / 2161, preserving the exact preceding 39-case inventory, with no
errors/failures/skips. Memo restart passes 1 / 67. The mixed PHP parent,
Python child, Rust remote Activity and PHP local Activity cascade passes 237
assertions in 23.124097 seconds, within its original 30-second budget.
Independent verification of the retained raw artifact checks all eight original
remote stop cases, original root/request/deadline/attempt fences, actual callback
stop diagnostics and successful hosted stack/image cleanup.

Exact source tuple: PHP 92c0f05f9761f8e2aa625fca8096f7149f0b6825, Server
92e9f12866be51e86d35b043597af3e705ff8122, Native
0471f1ebbb98c61fe53663086d62dc2db74db9e3, Python
3c77a01059964cd093f4d7214f1917741818c97a, Rust
08824f2950460ec590e2f16272adc6ddf9a890ed, CLI
933c554f8bffa2bf7d188ced712b69b20844ac2d.

This qualifies the new source tuple. #603 stays draft and shared #136 stays open.
Protocol 1.20 is unfrozen/unpublished and scope execution remains disabled.
Next: complete SDK replay of populated timer/wait/child/descendant scope receipts,
selective callback supervision and mixed groups, then qualify all consumers and
the coherent API/CLI/Waterline view. The exact installable published tuple and
fair competitive demonstration remain required before closure.

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 6, 2026 05:26
@rmcdaniel
rmcdaniel merged commit dd23e5e into main Oct 6, 2026
40 checks passed
@rmcdaniel
rmcdaniel deleted the feat/cooperative-cancellation-model branch October 6, 2026 05:57
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