Conversation
…c, preflight-cleared plan Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
…ing on origin main Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
…registration fix Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
… 944) Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
…erage run Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com
…me-marker-registration-races-removal-944
… and the pass-2 anchor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
EngineToggleStateCoordinatorin which a prime that completed before its marker was registered left a stale marker in_primeTasks, blocking every later re-prime of that engine for the session.StartPrimeIfNeedednow registers aTaskCompletionSource<bool>marker under_primeGatebefore the prime starts.StartObservedPrimecompletes the marker withSetResult(true)in afinallyafterCompletePrimereturns, so the marker never faults or cancels.CompletePrimeis unchanged. It still reports a fault before removing the marker, and it now always finds the marker it is meant to remove.EngineToggleStateCoordinatorTests.PrimeRegistration.cs. They cover registration order, re-prime after a synchronous fault, and re-prime after a synchronous cancellation.Why
StartPrimeIfNeededstored the prime's continuation task in_primeTasksonly afterStartObservedPrimereturned. A prime that faulted or was canceled synchronously, or quickly enough on another thread, ranCompletePrime's removal before that store. The later store then left a marker for a prime that had already finished, and the at-most-one-prime guard treated it as in flight. Registering the marker before the start removes that ordering dependency. The root-cause analysis is inspec.mdand the research record in the feature folder.What Changed
Production (
TaskMaster/Ribbon/EngineToggleStateCoordinator.cs)StartPrimeIfNeeded: creates the marker withTaskCreationOptions.RunContinuationsAsynchronously, stores it as_primeTasks[engineName] = marker.Taskinside the existing lock, then callsStartObservedPrime(..., marker).StartObservedPrime: now returnsvoidand takes the marker. The continuation wrapsCompletePrimeintry/finally { marker.SetResult(true); }, and the continuation task is discarded. The continuation options and scheduler are unchanged._primeGate,_primeTasksand theStartObservedPrimeremarks was updated to describe the registration marker.catch, lock, dependency or public API.GetPrimeTaskandCompletePrimeare unchanged.Tests
TaskMaster.Test/Ribbon/EngineToggleStateCoordinatorTests.PrimeRegistration.cs(new; MSTest, the fixture's strict Moq harness, FluentAssertions):GetPressed_WhenPrimeStarts_RegistersPrimeHandleBeforeActivationReadRunsGetPressed_AfterPrimeFaultsSynchronously_LaterReadStartsNewPrimeGetPressed_AfterPrimeIsCanceledSynchronously_LaterReadStartsNewPrimeTaskMaster.Test/TaskMaster.Test.csproj: oneCompile Includeentry for the new partial.Docs
docs/features/active/2026-09-30-engine-toggle-prime-marker-registration-races-removal-944/holds the spec, research, plan, evidence and three audit artifacts. The PR also adds the promotion record underdocs/features/potential/promoted/.Architecture / How It Fits Together
The ribbon
getPressedcallback readsEngineToggleStateCoordinator.GetPressed. On a cache miss,StartPrimeIfNeededtakes_primeGate, checks_primeTasksfor the engine, registers the marker and starts the prime.ApplyPrimeAsyncperforms the activation read. Its continuation runsCompletePrimeon the default scheduler, which logs a fault, removes a faulted or canceled marker, and invalidates the control. The continuation then completes the marker. Tests await the marker throughGetPrimeTaskrather than polling.Verification
Completed (local, recorded in the feature-folder evidence)
GetPressed_WhenPrimeStarts_RegistersPrimeHandleBeforeActivationReadRunsfailed on its registration-order assertion; 28 fixture tests were discovered and no compile or load failure occurred (evidence/regression-testing/prime-registration-fail-before.md).prime-registration-pass-after.md).CLAUDE.mdorder (evidence/qa-gates/toolchain-final-pass.md):dotnet tool run csharpier format .rewrote 0 files.dotnet tool run csharpier check .checked 1627 files and reported no differences./t:Rebuild,EnableNETAnalyzers,EnforceCodeStyleInBuild) and the nullable rebuild (/t:Rebuild,TreatWarningsAsErrors) each reported 0 errors and 0 warnings.EngineToggleStateCoordinator: 157/157 lines, 37/38 branches (the same missed branch as the baseline).StartPrimeIfNeeded,StartObservedPrimeandCompletePrimeare each at 100%.QuickFiler.Controllers.Tests.QfcDatamodelLivenessTestswall-clock tests. This PR neither changes nor covers that QuickFiler.Test project. A single full restart of the final loop was approved by the coordinator for that reason, and the restart passed with zero failures. Both attempts are recorded inevidence/qa-gates/coverage-summary.md.Recommended
UtilitiesCS.Testshell-icon test classes, which the local coverage route excludes on this workstation.Backward Compatibility / Migration Notes
None. All changed members are private, and observable behavior changes only in the failure paths the fix addresses. After a fault or cancellation, a later read now starts a new prime instead of being blocked.
Risks and Mitigations
finally, afterCompletePrimehas exited, so test awaits observe the logged fault and the removal. The fault-ordering tests from the upstream fix still pass unchanged.Review Guide
TaskMaster/Ribbon/EngineToggleStateCoordinator.cs: the lock block inStartPrimeIfNeededand theStartObservedPrimecontinuation.TaskMaster.Test/Ribbon/EngineToggleStateCoordinatorTests.PrimeRegistration.cs.code-review.2026-09-30T16-00.mdin the feature folder, which includes the analysis of why the keyedTryRemovecannot remove a newer marker.Follow-ups
Listed for the coordinator to file. This branch files no issues.
logErrorsink skips_primeTasks.TryRemoveunder report-then-clear, so the marker completes but stays registered, and the discarded continuation task faults unobserved (spec Rollout item 1).getPressedpoll re-primes and logs again. A back-off or a reset-based recovery is a separate decision (spec Rollout item 2).GetPrimeTask<returns>element still opens with "The prime task", although the value is now the registration marker. This is a one-sentence precision edit for the next change to that file.QfcDatamodelLivenessTestswall-clock flakiness and the transaction timing flakiness are being filed by the coordinator separately.GitHub Auto-close
🤖 Generated with Claude Code