Skip to content

test: add structural guard for SavePendingOrchestration ordering#520

Merged
PureWeen merged 4 commits intomainfrom
fix/save-pending-orchestration-before-dispatch
Apr 6, 2026
Merged

test: add structural guard for SavePendingOrchestration ordering#520
PureWeen merged 4 commits intomainfrom
fix/save-pending-orchestration-before-dispatch

Conversation

@PureWeen
Copy link
Copy Markdown
Owner

@PureWeen PureWeen commented Apr 6, 2026

What

Adds a structural test that verifies SavePendingOrchestration() is called before ExecuteWorkerAsync/Task.WhenAll in both SendViaOrchestratorAsync and SendViaOrchestratorReflectAsync.

Why

Issue #517 describes a crash window where orchestration state could be lost if SavePendingOrchestration ran after worker dispatch. Upon investigation, the code already has the correct ordering — both methods save before dispatching workers. The issue's "Current Flow" diagram was inaccurate.

This PR adds a structural test to lock in the ordering and prevent future regressions, following the same pattern as the existing PendingOrchestration_ShouldClearInFinallyBlock test.

Testing

  • SavePendingOrchestration_MustAppearBeforeWorkerDispatch — verifies source ordering in both paths
  • Existing PendingOrchestration_ShouldClearInFinallyBlock continues to pass

Closes #517

Adds a structural test that verifies SavePendingOrchestration() appears
before ExecuteWorkerAsync/Task.WhenAll in both SendViaOrchestratorAsync
and SendViaOrchestratorReflectAsync. The code already has the correct
ordering — this test locks it in to prevent regressions.

Closes #517

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen
Copy link
Copy Markdown
Owner Author

PureWeen commented Apr 6, 2026

🔍 Multi-Model Code Review — PR #520

CI Status

⚠️ No CI checks reported on this branch.


All Findings Across 4 Review Rounds

# Severity Finding Status
1 🟡 MODERATE Reflect-path anchored to call site, not method definition ✅ FIXED (b5a4658)
2 🟢 MINOR Assertion ordering: reflectSave used before >= 0 check ✅ FIXED (b5a4658)
3 🟢 MINOR reflectWhenAll anchored from reflectSave (vacuous < assertion) ✅ FIXED (6ae0e4b)
4 🟡 MODERATE Non-reflect path IndexOf lacks upper bound — can fall through to method definition ✅ FIXED (07c66ba)
5 🟢 MINOR Reflect path missing ExecuteWorkerAsync check (future-proofing against eager materialization) ✅ FIXED (07c66ba)

All 5 findings resolved across 4 commits. Tests pass (2/2 structural tests green).


Round 5 — Final Review (commit 07c66ba, 3/3 reviewers)

No new issues found. All 3 reviewers independently verified:

  • Non-reflect path correctly bounded between Phase 3 marker and ExecuteWorkerAsync method definition
  • Reflect path anchored to method definition with independent position checks
  • All IndexOf searches match intended targets with no false-positive risk
  • Ordering invariant correctly validated in both paths

Final Recommendation

Approve — clean to merge.

PureWeen and others added 3 commits April 5, 2026 21:52
- Change IndexOf anchor from 'SendViaOrchestratorReflectAsync' (matches
  call site) to 'private async Task SendViaOrchestratorReflectAsync'
  (matches method definition) so the test actually guards the reflect path.
- Move Assert.True(reflectSave >= 0) before using reflectSave as
  startIndex to avoid ArgumentOutOfRangeException on failure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… assertion

Compute reflectWhenAll from reflectMethod (same independent anchor as
reflectSave) instead of from reflectSave, so the < comparison is
load-bearing. Previously it was vacuously true since IndexOf with
startIndex always returns >= startIndex.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nc check to reflect path

- Non-reflect path: substring from Phase 3 marker to ExecuteWorkerAsync
  method definition, preventing fall-through to later occurrences.
  Matches the bounding pattern used in PendingOrchestration_ShouldClearInFinallyBlock.
- Reflect path: also assert SavePendingOrchestration before
  ExecuteWorkerAsync (not just Task.WhenAll) to guard against future
  eager materialization refactors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@PureWeen PureWeen merged commit 56cd624 into main Apr 6, 2026
@PureWeen PureWeen deleted the fix/save-pending-orchestration-before-dispatch branch April 6, 2026 03:34
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.

fix: Save PendingOrchestration before first worker dispatch to prevent crash data loss

1 participant