fix(440): let repeated Left walk the Qfc breadcrumb chain to the root - #689
Merged
drmoisan merged 6 commits intoAug 29, 2026
Merged
Conversation
Preparation-mode orchestration for issue #440. Adds the active feature folder with research, spec, and an atomic plan cleared through five preflight rounds. Research established that most of issue #440 already landed on main as a secondary payload of feature 498. The residual defect is Qfc-only: BreadcrumbStateModel.LeftArrow gates its parent-select transition on a leaf-anchored conjunct, so Left walks up exactly one level while the Efc surface already walks to the root. Scope is one production file plus two existing test files. No production or test source file is modified by this commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Persists three agent-memory entries written during the issue #440 preparation run, plus their index lines. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Removes the leaf-anchored conjunct `activeIndex.Value == row.Chain.Count - 1` from the LeftArrow() transition guard in UtilitiesCS/OutlookObjects/Folder/BreadcrumbStateModel.cs. That single clause was the whole of the residual #440 defect: it held only while the active segment was still the leaf, so Left performed the parent-select exactly once and every later press fell through to TryCollapseLeaf(), which reported an unhandled arrow and let the legacy handler dismiss the QuickFiler folder drop-down. The remaining guard reads: no subfolder selected, an active segment index exists, and ActivateSegment(activeIndex.Value - 1) succeeds. The root boundary is now enforced by BreadcrumbStateRow.ActivateSegment, which already refuses a negative index, so Left at the root still returns false and the pre-existing fall-through is preserved unchanged. The _selectedSubfolderIndex < 0 conjunct is retained, so Left with a subfolder highlighted still resets that selection. The adjacent #440 comment is rewritten to describe the walk rather than a single leaf-anchored step. Two landed tests encoded the one-step limit and are corrected: - Arrows_RightExpandsThenLeftCollapses_UnhandledWhenNothingChanges in UtilitiesCS.Test/OutlookObjects/Folder/BreadcrumbStateModelSequenceTests.cs is extended to the root before asserting the unhandled press, per decision D1. - Route_LeftArrow_NothingToCollapse_ReportsUnhandledLeft in UtilitiesCS.Test/OutlookObjects/Folder/FolderBreadcrumbBridgeRouterTests.cs is corrected in place, reusing the file's ArrowAsync helper so the change is net line-negative against the 500-line limit. Two new tests cover the walk and the open-leaf-expansion edge case, asserting the active segment index after every press. Both were red before the fix and green after. The Efc surface is untouched; it already satisfied the contract. Full suite 6859/6859 green, up from a 6857 baseline by exactly the two added tests. Refs #440 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BmFjm2aSpooVerwWWWuN8S
Records the policy-audit, code-review, and feature-audit produced for the issue #440 breadcrumb left-arrow walk-to-root fix. All three verdicts are PASS with zero blocking findings, so no remediation cycle was opened. The reviewer re-derived the coverage figures independently rather than accepting the executor's report, and re-ran the affected Qfc and Efc breadcrumb suites. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BmFjm2aSpooVerwWWWuN8S
Captures two entries written while delivering the breadcrumb left-arrow walk-to-root fix: the executor's note that estimated evidence timestamp labels can drift ahead of real write times, and the reviewer's residual findings for this branch. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BmFjm2aSpooVerwWWWuN8S
…dex) # Conflicts: # .claude/agent-memory/atomic-planner/MEMORY.md
5 tasks
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.
fix(440): let repeated Left walk the Qfc breadcrumb chain to the root
Summary
LeftArrow()transition guard inBreadcrumbStateModel, so repeated Left presses walk the breadcrumb ancestor chain all the way to the root instead of stopping after one level.BreadcrumbBridgeRouter.Arrows.csalready walked to the root.Why
BreadcrumbStateModel.LeftArrow()gated its parent-select onactiveIndex.Value == row.Chain.Count - 1, which is true only while the active segment is the leaf. After the first Left press the active index is no longer the leaf, so the guard failed and every subsequent press fell through as unhandled. The user-visible effect was that Left could ascend exactly one level of a breadcrumb chain and then stopped.The clause is unnecessary for safety.
BreadcrumbStateRow.ActivateSegment(int)already refuses a negative index, so the root boundary and the pre-existing unhandled fall-through are preserved without it.Most of the original issue #440 statement already landed on
mainas a secondary payload of feature #498. The residual defect addressed here is Qfc-only, and the narrowed scope is recorded in the feature spec.What Changed
Core fix
UtilitiesCS/OutlookObjects/Folder/BreadcrumbStateModel.cs— deleted theactiveIndex.Value == row.Chain.Count - 1conjunct from theLeftArrow()transition guard. The_selectedSubfolderIndex < 0conjunct and therow.ActivateSegment(activeIndex.Value - 1)call are retained unchanged. The adjacent#440comment was rewritten to describe a walk rather than a single leaf-anchored step. No other conditional in the file was altered; in particularTryRightTreeTransitionis untouched.Tests
UtilitiesCS.Test/OutlookObjects/Folder/BreadcrumbStateModelSequenceTests.cs— addedLeftArrow_RepeatedOnThreeSegmentChain_WalksToRootThenReportsUnhandled, which asserts the active segment index after every press (2 to 1 to 0, then unhandled at 0), andLeftArrow_WalkFromAnOpenLeafExpansion_ClearsTheExpansionAndStillReachesTheRoot, which covers the open-leaf-expansion edge case. CorrectedArrows_RightExpandsThenLeftCollapses_UnhandledWhenNothingChangesto the walk contract by extending the sequence to the root.UtilitiesCS.Test/OutlookObjects/Folder/FolderBreadcrumbBridgeRouterTests.cs— correctedRoute_LeftArrow_NothingToCollapse_ReportsUnhandledLeftin place so it drives the chain to the root before asserting the unhandled Left, and replaced the superseded one-step-limit comment. Net line-negative.Docs
Architecture / How It Fits Together
Arrow keys reach the breadcrumb state machine through two surfaces. The Qfc surface routes through
FolderBreadcrumbBridgeRouterintoBreadcrumbStateModel, which owns the selection and expansion state. The Efc surface routes throughQuickFiler/Controllers/BreadcrumbBridgeRouter.Arrows.cs.LeftArrow()attempts a tree transition first and falls through to the pre-existing collapse behavior when no parent-select is available. The root boundary is enforced one level down, insideBreadcrumbStateRow.ActivateSegment(int), which refuses a plain row, a negative index, an index at or beyondChain.Count - 1, and a no-change index. Removing the leaf-anchored conjunct therefore changes only which presses reachActivateSegment; it does not widen whatActivateSegmentwill accept.Only the second and subsequent Left presses change behavior.
ActiveSegmentIndexdefaults toChain.Count - 1, so a freshly selected row is leaf-anchored and the first press behaves identically before and after.Verification
Completed
dotnet tool run csharpier formaton the three owned paths, thendotnet tool run csharpier check .— exit 0,Checked 1560 files, equal to the pre-change baseline.msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true— exit 0, 0 errors, 5 warnings (unchanged from baseline).msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:TreatWarningsAsErrors=true— exit 0, 0 errors, 5 warnings.Skipping target "CoreCompile"and 40 occurrences of(Rebuild target(s))in each file-logger output.LeftArrow()span are covered.The five analyzer and nullable warnings are the pre-existing System.Reactive 7.0.0 packages-config advisory, one from each of QuickFiler, TaskMaster, ToDoModel, UtilitiesCS, and UtilitiesCS.Test. They are unchanged from the baseline measured before this work began.
Recommended
Backward Compatibility / Migration Notes
No public API change, no renamed path, no removal. The change is a relaxation of one internal guard condition. Behavior at the root boundary is unchanged: Left at the root still returns
falseand still emits an unhandled Left arrow, so the legacy fall-through that closes the folder drop-down is retained.Risks and Mitigations
ActivateSegmentindependently rejects a negative index; a dedicated test asserts the third press returnsfalsewith the index still 0.Review Guide
UtilitiesCS/OutlookObjects/Folder/BreadcrumbStateModel.cs— the whole functional change is one deleted line plus a comment rewrite.BreadcrumbStateModelSequenceTests.cs— the two new tests and the corrected sequence test.FolderBreadcrumbBridgeRouterTests.cs— a mechanical replacement of two inline four-line calls with the existing single-line helper, plus the extra Arrange press.Follow-ups
Analyzeritems name 3.0.156 and 4.16.0. A fresh worktree fails every msbuild invocation with CS0006 until the missing package directories are provisioned. The durable realignment belongs to its own issue.Route_LeftArrow_NothingToCollapse_ReportsUnhandledLeftis defect-neutral rather than defect-detecting: its two Arrange presses discard their results, so it passes both before and after the fix. The walk contract is pinned at state-machine level by the two new tests, which do carry fail-before evidence. Worth tightening separately.GitHub Auto-close