Repository navigation
fix(ribbon): contain a throwing log sink at both engine-toggle coordinator call sites - #963
Merged
drmoisan merged 13 commits intoOct 1, 2026
Conversation
Restore the promoted record from the parent session branch and create the active bug folder with an explicit Acceptance Criteria section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3r7uhChZ6XRKuQntGLpsG
Recommend containing the sink exception inside CompletePrime before the marker clear, and tighten the no-unobserved-fault criterion to a testable form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N3r7uhChZ6XRKuQntGLpsG
Planning stopped twice on an external stop directive before the phase sections were written; the plan header records the remaining task decomposition and citation corrections. Not preflight-cleared. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…e and extend the plan design (pass A) Adds AC6 and AC7 per the maintainer comment of 2026-10-01T15:57:04Z, extends the plan design and delivered source to guard both sink calls, applies citation corrections c1 to c4, and adds a research addendum. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
… (pass B) Adds Phase 0 to Phase 2 (15, 12 and 23 tasks), the PLANNER-INTERNAL-REVIEW record mapping AC1 to AC7, and the self-review enumeration. Awaiting MCP plan validation and executor preflight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…plan The phase sections govern; the HTML comment on line 4 duplicated them in an older form. Line endings verified LF; MCP plan validator returns ok. The parent completed this edit and authored no plan content. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
Corrects five defects reported by atomic-executor preflight round 1: the fact 1 line citation for the catch token, the CSharpier width claim for the NotBeSameAs statement, the D-7 method-span rule for the internal async case, the fact 6 description of the claude-segment exclusion, and the CMD-VSTEST MESSAGE transcription so a multi-line trx message is evaluated on one line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
Atomic-executor preflight round 2 returned PREFLIGHT: ALL CLEAR with CONVERGENCE: NO FURTHER ROUNDS EXPECTED. Replaces the planner status marker with the returned signal, updates the plan Status line, and adds the committed clearance record under evidence/other. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…owing-log-sink-leaves-stale-prime-marker-947
…sink fix Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…es (issue 947) CompletePrime and HandleToggleClickAsync now guard their logError call, so a throwing sink no longer leaves a stale prime marker or escapes the async click boundary. Adds four regression tests in EngineToggleStateCoordinatorTests.ThrowingSink.cs, observed failing before the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…ce check-offs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NcieP6KJzhzgHkRh4F21Po
…ink fix Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 1, 2026
drmoisan
deleted the
bug/engine-toggle-throwing-log-sink-leaves-stale-prime-marker-947
branch
October 7, 2026 10:57
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.
Suggested title
fix(ribbon): contain a throwing log sink at both engine-toggle coordinator call sites
Summary
EngineToggleStateCoordinator.CompletePrimenow guards itslogErrorcall, so a throwing sink no longer skips the prime-marker clear. Before this change, the stale marker blocked every later re-prime for that engine for the rest of the session.EngineToggleStateCoordinator.HandleToggleClickAsyncnow guards its ownlogErrorcall inside the click-boundarycatch, so a throwing sink no longer escapes into theasync voidOffice ribbon handler.CompletePrimeis unchanged. The sink is still invoked before the marker is removed, and the existingPrimeFaultOrderingtest file is byte-identical and passes.TaskMaster.Test/Ribbon/EngineToggleStateCoordinatorTests.ThrowingSink.cscover both call sites. All four were observed failing on the pre-fix code and pass after the fix.issue.mdare checked off with evidence.Why
logErrorsink is the coordinator's last reporting channel. When it threw insideCompletePrime, the exception escaped before_primeTasks.TryRemove(...)ran. The marker stayed registered, so a laterGetPressedreturned at theContainsKeycheck and never started a new prime. The exception also faulted the discarded continuation without anything observing it.HandleToggleClickAsync. Its caller is anasync voidOffice handler, so the exception would become unobserved. The maintainer added this second call site to the issue's scope on 2026-10-01.What Changed
Production (
TaskMaster/Ribbon/EngineToggleStateCoordinator.cs, 442 to 476 lines)CompletePrime: wraps_logError(BuildPrimeFailedMessage(engineName), failure)intry/catch (Exception)with the comment// Intentionally discarded: see the remarks on this method.._primeTasks.TryRemovestays after the block.HandleToggleClickAsync: wraps_logError(BuildToggleFailedMessage(engineName), ex)the same way inside the existingcatch (Exception ex). The toggle fault is still reported and is still not rethrown.HandleToggleClickAsyncsummary and remarks, theGetPrimeTaskreturns, theStartObservedPrimeremarks, and theCompletePrimesummary and remarks. The docs now describe threecatchclauses (one click boundary, two sink guards) and the "report has been attempted" guarantee.RibbonCommandBoundary.SafeLog.Tests
TaskMaster.Test/Ribbon/EngineToggleStateCoordinatorTests.ThrowingSink.cs(215 lines, MSTest + Moq + FluentAssertions, no harness changes):GetPressed_WhenLogSinkThrowsOnFaultedPrime_LaterReadStartsNewPrimeGetPressed_WhenLogSinkThrowsOnCanceledPrime_LaterReadStartsNewPrimeGetPressed_WhenLogSinkThrows_FirstPrimeCompletesAndMarkerIsClearedHandleToggleClickAsync_WhenLogSinkThrowsOnToggleFault_DoesNotThrowAndAttemptsReportTaskMaster.Test/TaskMaster.Test.csproj: one<Compile Include>entry for the new partial.Docs
docs/features/active/2026-09-30-engine-toggle-throwing-log-sink-leaves-stale-prime-marker-947/contains:issue.mdacceptance-criteria check-offs;policy-audit,code-review,feature-audit, all dated 2026-10-01T19-30).Architecture / How It Fits Together
GetPressedstarts a prime throughStartPrimeIfNeeded, which registers a marker in_primeTasks. The continuation inStartObservedPrimecallsCompletePrimeand then completes the marker in afinally.CompletePrimereports any non-success outcome through the sink and then clears the marker. A sink failure is now contained between those two steps, so the clear always runs.HandleToggleClickAsyncis the only boundary that observes an engine fault. Its sink call is now guarded, so the method never throws to itsasync voidcaller when the sink throws.Verification
Completed (from the committed evidence)
EngineActiveAsyncinvoked 1 time, expected 2;InvalidOperationException: sink failedescapingHandleToggleClickAsync.dotnet tool run csharpier format .anddotnet tool run csharpier check .: no changes.msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true: exit 0.msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:TreatWarningsAsErrors=true: exit 0.EngineToggleStateCoordinator.cs167/167 lines;catch (Exception)arms covered;Recommended
Backward Compatibility / Migration Notes
internalorprivate.Risks and Mitigations
RibbonCommandBoundary.SafeLog, and the remarks on each method state it.Review Guide
TaskMaster/Ribbon/EngineToggleStateCoordinator.cs: the two guarded sink calls inCompletePrimeandHandleToggleClickAsync, then the documentation edits.TaskMaster.Test/Ribbon/EngineToggleStateCoordinatorTests.ThrowingSink.cs.evidence/regression-testing/throwing-sink-fail-before.mdandthrowing-sink-pass-after.md.Follow-ups
Listed for the coordinator to file; none were filed from this branch:
_notifyUnavailable(and_enginesAccessor) on theHandleToggleClickAsyncrefusal path. A throwing notify sink can still escape into theasync voidhandler, so the "never throws" remark is currently overstated for that path. The fix could also extract a shared private sink-guard helper for the two duplicated guards.GetPrimeTask<returns>opening wording ("The prime task"). The returned value is the registration marker.EngineToggleStateCoordinator.cs(476 of 500 lines) before its next change.coverage/output directory.GitHub Auto-close
🤖 Generated with Claude Code