Skip to content

fix(quickfiler): make folder-suggestion fallback selection bounds-safe (#392)#393

Merged
drmoisan merged 3 commits into
mainfrom
bug/folder-combobox-fallback-index-out-of-range-392
Jul 20, 2026
Merged

fix(quickfiler): make folder-suggestion fallback selection bounds-safe (#392)#393
drmoisan merged 3 commits into
mainfrom
bug/folder-combobox-fallback-index-out-of-range-392

Conversation

@drmoisan

Copy link
Copy Markdown
Owner

Suggested title

fix(quickfiler): make folder-suggestion fallback selection bounds-safe (#392)

Summary

  • Fixes a System.ArgumentOutOfRangeException thrown from BreadcrumbStateModel.SelectRow that aborted the entire QuickFiler high-confidence load pipeline whenever a loaded item had exactly one folder suggestion and no predetermined folder match.
  • QfcItemController.AssignFolderComboBox() no longer hardcodes fallback selection index 1; it selects index 0 when FolderArray has exactly one entry (QuickFiler/Controllers/QfcItemController.FolderHandling.cs).
  • The retained static helper PopulateAndSelectFolder applies the same bounds-safe fallback for the single-item ComboBox path.
  • Two regression tests reproduce the defect (verified failing before the fix, passing after), plus one targeted branch-coverage test added during remediation; suite is 542/542 passing.
  • Touched-class coverage rose from 91.89% line / 73.81% branch to 95.95% line / 76.19% branch; new/changed-code coverage is 100%.
  • Feature-review re-audit (2026-07-20T19-30 artifacts) records zero blocking findings with a PASS verdict.

Why

AssignFolderComboBox assumed the folder-suggestion list always contained at least two entries (index 0 placeholder semantics plus an index-1 top suggestion). When FolderPredictor returned exactly one suggestion, the unconditional SetFolderSelectedIndex(1) flowed through BreadcrumbBridgeCoordinator.SelectRow into BreadcrumbStateModel.SelectRow, whose bounds validation (correct defensive behavior, unchanged by this PR) threw ArgumentOutOfRangeException: "Row selection requires -1 or an index in [0, 0]". The exception propagated up QfcCollectionController.LoadSecondaryAsyncQfcFormController.LoadItemsAsyncQfcHomeController.LaunchAsync and aborted the ribbon-initiated QuickFiler load. Root-cause analysis: evidence/other/root-cause-392.2026-07-20T13-50.md.

What Changed

Core fix (C#, 2 files):

  • QuickFiler/Controllers/QfcItemController.FolderHandling.cs — fallback selection is now FolderArray.Length == 1 ? 0 : 1 in AssignFolderComboBox(), and predeterminedIndex >= 0 ? predeterminedIndex : (folderArray.Length == 1 ? 0 : 1) in PopulateAndSelectFolder. No other production change.
  • QuickFiler.Test/Controllers/QfcItemController.FolderHandlingTests.cs — adds AssignFolderComboBox_WhenSingleSuggestionNoPredeterminedMatch_SelectsIndexZero, PopulateAndSelectFolder_SingleItemNoPredeterminedMatch_SelectsIndexZeroWithoutThrowing, and PopulateFolderComboBox_WhenInvokeRequired_MarshalsAssignFolderComboBoxViaInvoke (branch-coverage remediation); comment-only trims keep the file at 498 lines (under the 500-line limit).

Docs / audit trail:

  • Active feature folder docs/features/active/2026-07-20-folder-combobox-fallback-index-out-of-range-392/ with issue.md (all five acceptance criteria checked), atomic plan, remediation plan, policy-audit / code-review / feature-audit artifacts for both review cycles, and full baseline/QA/regression evidence.
  • Feature-review agent memory notes under .claude/agent-memory/feature-review/.

Architecture / How It Fits Together

The selection path is unchanged: QfcItemController.AssignFolderComboBox()IItemViewer.SetFolderSelectedIndex(int)BreadcrumbBridgeCoordinator.SelectRow(int)BreadcrumbStateModel.SelectRow(int). The fix constrains the caller to the model's documented invariant (index in [-1, rowCount-1]); the model's validation and the coordinator remain untouched.

Verification

Completed (evidence under the feature folder's evidence/ tree):

  • Regression tests failed before the fix (fail-before-392.2026-07-20T14-05.md, exit 1) and passed after (pass-after-392.2026-07-20T14-10.md).
  • CSharpier format: PASS on touched files (final + remediation runs).
  • .NET analyzer build: PASS, exit 0 (analyzer-final-392.2026-07-20T14-24.md, remediation-analyzer-final.2026-07-20T18-32.md).
  • Nullable /t:Rebuild build: 34 errors, all pre-existing in vendored SVGControl.csproj, byte-identical to the Phase 0 baseline; zero new errors, zero first-party errors (nullable-final-392.2026-07-20T15-10.md, remediation-nullable-final.2026-07-20T18-35.md; tracked separately in docs/features/potential/2026-07-07-ci-nullable-check-skipped-vendored-projects.md).
  • vstest with coverage: 542/542 pass; name-level no-regression set-difference checks empty (remediation-regression-check.2026-07-20T18-46.md).
  • Touched-class coverage 95.95% line / 76.19% branch (>= 85%/75% floor); new/changed-code 100% (remediation-coverage-delta.2026-07-20T18-44.md).

Recommended:

  • CI full-suite run on this PR (measures the true all-first-party repo-wide coverage figure; the local canonical artifact instruments only QuickFiler.Test).
  • Manual smoke: ribbon "QuickFiler High Confidence" against an item with a single folder suggestion.

Backward Compatibility / Migration Notes

No public API changes, no signature changes, no behavior change for multi-suggestion or predetermined-folder cases (re-verified by the pre-existing test set). No migration required.

Risks and Mitigations

  • Risk: single-suggestion items now select index 0 instead of throwing; if any consumer relied on the exception path (none found), behavior differs. Mitigation: regression tests pin the new behavior; rollback is reverting the two-line conditional.
  • Risk: pre-existing QuickFiler package-wide coverage (73.72% line / 64.69% branch) remains below the repository floor. Mitigation: ratified as a pre-existing, separately-tracked exception (open issue Feature: quickfiler-80-per-file-coverage #136, disposition record evidence/qa-gates/coverage-disposition-decision.2026-07-20T18-17.md); not regressed by this PR.

Review Guide

  1. QuickFiler/Controllers/QfcItemController.FolderHandling.cs (7-line production diff — the substantive change).
  2. QuickFiler.Test/Controllers/QfcItemController.FolderHandlingTests.cs (three new tests + disclosed comment-only trims).
  3. Audit artifacts in the feature folder (policy-audit/code-review/feature-audit, 2026-07-20T19-30 = final PASS cycle); the remaining ~50 changed files are evidence markdown.

Follow-ups

  • Issue Feature: quickfiler-80-per-file-coverage #136 (quickfiler-80-per-file-coverage): package-wide coverage uplift, deliberately out of scope here.
  • docs/features/potential/2026-07-07-ci-nullable-check-skipped-vendored-projects.md: vendored-project nullable-gate scoping decision.
  • Code-review note CR-1 (non-blocking): the count == 1 ? 0 : 1 clamp is duplicated at the two fallback sites; candidate for a shared helper in a future cleanup.

GitHub Auto-close

drmoisan and others added 3 commits July 20, 2026 13:54
- Guard AssignFolderComboBox fallback selection against single-item list
- Guard PopulateAndSelectFolder fallback selection against single-item list
- Add regression tests for single-item, no-predetermined-match case

Refs: #392

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2Yht8Rg83Um38RaVyV1sA
- Covers PopulateFolderComboBox marshaling when InvokeRequired is true
- Raises QfcItemController.FolderHandlingTests branch coverage above 75% floor
- Includes feature-review audit and remediation evidence

Refs: #392

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2Yht8Rg83Um38RaVyV1sA
@drmoisan
drmoisan merged commit 83b66e5 into main Jul 20, 2026
2 checks passed
@drmoisan
drmoisan deleted the bug/folder-combobox-fallback-index-out-of-range-392 branch July 20, 2026 19:42
drmoisan added a commit that referenced this pull request Jul 20, 2026
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.

Bug: folder-combobox-fallback-index-out-of-range

1 participant