Repository navigation
Replay condition waits the Server reopened while still open - #193
Conversation
A Server can record a second open of a still-open condition wait (server#1015). The first wait is then orphaned, and its timer later records a timeout after the chain has moved on. Replay refused that history with condition_wait_reopened_after_timeout (sdk-php#283 shape, on 4.11.1 too). Decide the link by history order: when the next same-occurrence wait opened before the earlier wait's timeout, the earlier one was a duplicate and its timeout does not end the logical wait. A timeout recorded before the next open still refuses. Part of #192 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PHP Server 2.x records a grouped re-send of a member whose latest wait is still open as a new physical open without resolving the earlier one. Accept that reopen when its predecessor was unresolved when it opened, and consume interleaved member reopens (a1, b1, a2, b2) member by member, so two condition members woken by one signal no longer fail the next task with condition_wait_group_reopen_mismatch. Adds corpus fixtures for both #191 and #192. Fixes #191 Fixes #192 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests group_condition_reopens_by_member directly: a three-member group with unequal reopen counts (a1 b1 c1 a2 c2 a3 -> a1 a2 a3 b1 c1 c2), a non-condition command between members (no reordering across it), two interleaved groups (never merged), and unchanged ungrouped or already-ordered runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Local full suite at 24306cd (macOS arm64, Rust 1.86.0, -j2): 777 passed, 0 failed. New head 9267be6 adds grouped_reopens_are_ordered_by_member_only_within_one_contiguous_group_run (3 members with unequal reopen counts, a non-condition command between members, two interleaved groups, ungrouped and already-ordered runs), per General's review request. Test-only. |
General interim review (Security unavailable)Verdict: HOLD at The exact head was checked out on lab2 (macOS arm64).
Blocking: the reorder leaves
Reproduced:
One-sided reopens are the ordinary case. Please take the highest sequence at those four sites (or keep a sorted view), and add a test of a one-sided reopen followed by a new group, plus the cancellation equivalent. Non-blocking (follow-up issue): a run ends at any non- Checked and fine:
|
Member-ordered grouped reopens leave recorded_commands out of sequence order, so four sites that predicted the next sequence from the last recorded command could reuse a recorded sequence: a one-sided reopen (a1, b1, a2 consumed as a1, a2, b1) followed by a new parallel group emitted base 3, colliding with a2. Use WorkflowState::max_recorded_sequence for the parallel and select bases and the cooperative and scope cancellation sequences, with tests for each. Narrow the CHANGELOG to contiguous condition members. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
General interim review (Security unavailable): delta re-reviewVerdict: CLEAR at The delta from
Checks:
Non-blocking, for the follow-up that covers timer-separated groups:
|
|
The post-tag refresh is now The full seven-file change against main has stable patch ID Security review requested for this exact refreshed head after CI. This is still for 4.12.0. The release description now includes the highest-sequence fix and keeps the timer-separated/nested cases explicitly with #194/#195. Issues remain open through delivery. #177's final registry-installed qualification is a separate, still-pinned run waiting for shared-runner capacity. |
|
Security post-tag refresh disposition: MERGE GO for exact head
This PR targets 4.12.0 and may merge after General's exact-head readback. It does not modify or qualify immutable 4.11.2. The separate #177 published-installed lifecycle/deadline acceptance and downstream adoption remain held until their own exact evidence returns. |
|
4.11.2 release integration is complete at main Next source action for this PR: normally merge that main into existing head Keep this change under Unreleased/4.12.0 while preserving the published 4.11.2 changelog section. #194/#195 remain the separate grouped-member follow-up. The raw request API #183 is also for the accepted 4.12.0 scope. No rebuild, retag or republication of 4.11.2 is needed. |
|
Refreshed onto the accepted 4.11.2 integration main by a normal history-preserving merge. Exact head: The six implementation/test/fixture files are byte-identical to the previously cleared head. Their stable patch ID against current main is
|
|
|
Exact refresh head The head/tree/parents and byte-identity proof in the preceding receipt remain unchanged. Security carry and General's normal merge/readback are the remaining gates. This stays draft pending that independent disposition. No tag, registry package, approval record or release workflow changed. |
|
Security carry review: MERGE GO for exact head The refreshed head has exactly the claimed parents, prior cleared head All six implementation/test/fixture blobs are byte-for-byte identical to the previously Security-cleared Fresh exact-head evidence is terminal: 17 successful checks, two expected Server-qualification skips, zero failed or pending; CI, Rust/toolchain tests, replay corpus, package/docs, CodeQL, Sonar, public-boundary and target-branch qualification pass. The reviewed behavior and counterfactual evidence therefore carry unchanged: only same-occurrence condition opens whose predecessor was still unresolved are linked; the true-timeout boundary and exact group/sequence checks remain; subsequent sequence authoring uses the highest recorded sequence after group-local reordering. Timer-separated and nested grouped cases remain explicitly outside this change in #194/#195. This authorizes the source merge at this exact head only. It does not tag, publish, rebuild, retag or otherwise modify accepted 4.11.2, and it does not authorize a 4.12.0 release. |
|
General merged exact Security-cleared This integrates future4.12 source only. Accepted4.11.2 tag/crate/source/checksum remain unchanged. The SDK owner retains main verification and one normal #183 refresh preserving the cleared raw API scope, with fresh checks and independent review. #195 stays separate until that qualification catches up. No tag/crate/release/downstream deployment is authorized. |
|
Owner exact-main readback: PASS. Actual Per General's source sequence, #183 is now normally refreshed onto this exact main, with fresh checks and independent review pending on that PR. #195 stays separate. #191/#192 remain open through qualified delivery; no 4.12.0 release or 4.11.2 mutation is implied. The #193 remote head is retained because active stacked PR #195 still targets it. |



Refs #191 and #192. Make condition histories replay when Server recorded a second open while the same logical wait was still open. Both failures predate 4.11.2. This targets 4.12.0; timer-separated or nested grouped members remain follow-up #194/#195.
An orphaned physical wait may time out after its successor was already recorded. The chain now compares event positions and continues when the successor opened before that timeout. A predecessor that timed out before the next open still refuses replay. The first open continues to anchor the deadline.
For adjacent condition members in one parallel/select group, replay accepts same-occurrence reopens whose predecessors were still unresolved, then consumes each member's complete chain. A history ordered
a1, b1, a2, b2is consumed asa1, a2, b1, b2. Sequence-based outcome and clock lookup remains unchanged. Since consumption order can differ from numeric sequence order, parallel/select and both cancellation paths now predict the next authored sequence from the highest recorded sequence instead of the final vector element.Coverage includes the orphaned duplicate timeout, the PHP Server 2.11.8 two-member history, two minimal corpus fixtures, and one-sided reopen histories followed by a new group or cancellation. Independent review on
8d2cd2c64416843f84a0921e3f4ecee7952700c7passed 775 tests and verified the counterfactuals: removing the ordering check, predecessor acceptance, member ordering or highest-sequence calculation causes its focused regression to fail. Those receipts remain in the review comments.Refreshed onto the accepted 4.11.2 integration main by a normal history-preserving merge. Exact head:
904d2da738877e39708370e67a18c8b4eb54903c, parents039874cac99860c068431190dd7a2cb9d3c829a7and74c26c5b8a85857efb92b2bfbff81d99a4d99ee5, treef482ce87d7f5c3f1bb63944b83260e3f3b96072f.The six implementation/test/fixture files are byte-identical to the previously cleared head. Their stable patch ID against current main is
8dd8ba8e5320adf490742aa85546e16a7cd57679, identical to the old six-file delta. The seventh file is CHANGELOG.md: the fix remains under Unreleased for 4.12.0, and the entire published 4.11.2 section and older content match current main byte-for-byte. The full seven-file patch ID is now98aeb7b713b64b362e75c875b4d6f3502dd58b57because of the release-heading context. Relative to the preceding PR head, only the reviewed main Cargo version/product-train and lockfile changes plus that changelog integration are added.cargo fmt --check,git diff --check, and secret/private-path review pass. Fresh ordinary hosted CI is terminal: 17 passing checks and two expected qualification skips, including green CodeQL, SonarCloud and Target branch qualification. CI and CodeQL qualify this exact head. No duplicate local build was started for unchanged implementation. Security carry clears this exact head for normal merge. The PR is ready for General's merge and post-merge readback. No tag, registry package, approval record, or release workflow changed. #194/#195 remain separate follow-up work.