Skip to content

fix(quickfiler): EFC recursive subfolder selection, trash selection, and QFC nested indentation (#1002) - #1003

Merged
drmoisan merged 16 commits into
mainfrom
bug/efc-qfc-folder-tree-selection-and-nesting-1002
Oct 22, 2026
Merged

drmoisan merged 16 commits into
mainfrom
bug/efc-qfc-folder-tree-selection-and-nesting-1002

Conversation

@drmoisan

Copy link
Copy Markdown
Owner

Suggested title

fix(quickfiler): EFC recursive subfolder selection, trash selection, and QFC nested indentation (#1002)

Summary

  • EFC viewer now expands and selects subfolders below the first revealed level, matching the recursive selection the QFC viewer gained in issue Bug: QuickFiler descendant selection and recursive expansion #997 (PR Fix QuickFiler descendant selection and recursive folder expansion #998). The activated descendant is filed through the existing SelectHierarchyPath.
  • EFC trash button now selects the "Trash to Delete" row in the same bind that prepends it, so the row is highlighted when the document is delivered.
  • QFC nested rows now render the +/- after the folder name at every depth, and each nested level is indented one 16-pixel step further than its visible parent.
  • Adds a keyed descendant tree to BreadcrumbRow, two inbound message types (descendantToggle, descendantActivate), recursive rendering, and stale-completion guards for descendant and first-level expansion.
  • Five EfcFormController members carry a member-level [ExcludeFromCodeCoverage], ratified by the maintainer (see Risks).
  • The manual Outlook check (AC26) is pending for the maintainer.

Why

Per the feature spec, three defects affected the QuickFiler folder-selection surfaces:

  1. The EFC viewer could not expand and select a subfolder below the first revealed level.
  2. Pressing the EFC trash button prepended the "Trash to Delete" row but selected no row.
  3. In the QFC selector, a descendant row with its own subfolders showed its +/- before the folder name, and every nested level shared the same indent.

What Changed

Core feature (C#, QuickFiler and UtilitiesCS):

  • Defect 1: keyed descendant tree on BreadcrumbRow (new partial file) reusing the existing BreadcrumbDescendantNode; BreadcrumbMessages and BreadcrumbMessageCodec accept descendantToggle and descendantActivate with a non-empty string nodeId (exposed as BreadcrumbInboundMessage.NodeId); BreadcrumbHtmlRenderer renders children recursively with the node affordance after the name; the EFC router routes both messages with stale-completion guards; BreadcrumbDocumentAssets bridge script and base CSS updated.
  • Defect 2: BreadcrumbBridgeRouter.BindRowsAsync accepts an optional preferred row so the trash row is selected before document delivery; the preferred-row computation is shared with SelectRow; the delete gesture path in EfcFormController awaits the bind.
  • Defect 3: QuickFiler/Resources/FolderBreadcrumb.js makeSubfolders appends the name before the toggle, takes a depth argument, and sets a data-depth attribute and inline left padding (24 px plus 16 px per level).

Tests:

  • New MSTest/Moq/FluentAssertions suites under UtilitiesCS.Test (codec, row descendants, HTML renderer) and QuickFiler.Test (router, stale completion, trash, controller, QFC nesting text contract).
  • New node suite under tests/quickfiler-breadcrumb/ for the real page script.

Docs:

  • Feature folder docs/features/active/2026-10-22-efc-qfc-folder-tree-selection-and-nesting-1002 with spec, plan, research, audits, and Markdown evidence projections.

Architecture / How It Fits Together

  • EFC: the bridge script posts descendantToggle or descendantActivate with row and node identity. The router validates identity, calls GetImmediateSubfoldersAsync for a toggle, attaches children to the row only if the node is still expanded and its request generation is current, and posts one row render. An activation calls SelectHierarchyPath, which raises SelectedFolderPathChanged once.
  • Trash: ActionDeleteAsync binds rows with the trash row as the preferred row, so SelectedFolderPath equals "Trash to Delete" before DeliverDocument.
  • QFC: only the page script changes; the router, selection session, and FolderBreadcrumb.html are not modified.

Verification

Completed (from the committed evidence projections):

  • Full MSTest with coverage run (scripts/vscode/Invoke-MSTestWithCoverage.ps1): 7599 total, 7599 passed, 0 failed.
  • Repository first-party coverage: lines 57546/66677 (86.31%), branches 14038/17419 (80.59%); baseline was 86.30% line and 80.59% branch, so neither figure is lowered.
  • EfcFormController.Actions.cs: 26/28 lines (92.86%), 13/16 branches (81.25%), unchanged from baseline.
  • Fail-before and pass-after evidence is recorded for each of the three defects; the format, analyzer, and warnings-as-errors steps are recorded as passing in the cycle 2 projections.
  • Feature audit: PASS (cycle 2 re-audit, feature-audit.2026-10-22T14-10.md). Spec acceptance criteria AC1 to AC26 are all checked.
  • CI visibility: TaskMaster CI does not run the node .mjs suites. C# text-contract tests (for example MakeSubfolders_AppendsNameBeforeToggle and the bridge-script ordering tests) cover the JavaScript behavior in CI; the node suites were run locally and recorded in evidence/regression-testing/node-suites-run.2026-10-22T10-14.md.

Pending (AC26, non-blocking):

  • The manual Outlook check has not been performed. evidence/other/manual-outlook-check.2026-10-22T10-17.md records the steps for the maintainer: EFC grandchild selection and OK, EFC trash highlight and OK, QFC +/- placement after the name, and QFC one-step indentation per level.

Recommended:

  • dotnet tool run csharpier check .
  • msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true
  • msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:TreatWarningsAsErrors=true
  • The test: MSTest with Coverage (Koverage) task
  • Perform the manual Outlook check above.

Backward Compatibility / Migration Notes

  • No public API removal. BreadcrumbInboundMessage gains an optional trailing nodeId parameter, and BindRowsAsync gains an optional preferred-row parameter; existing callers compile unchanged.
  • Previously accepted inbound message types deserialize as before; key-less children render as before.

Risks and Mitigations

  • Coverage exclusion: five EfcFormController members (ActionOkAsync, ActionCancelAsync, CreateFolderAsync, RefreshSuggestionsAsync, ConfigureBreadcrumbControl) carry member-level [ExcludeFromCodeCoverage]. This exclusion was ratified by the maintainer under CLAUDE.md UT2. No coverage.config entry and no class-level exclusion was added.
  • WebView2 layout and message delivery cannot be observed from unit tests; mitigated by the text-contract tests and the pending manual check.
  • Rollback: revert this PR; no data migration is involved.

Review Guide

  1. docs/features/active/2026-10-22-efc-qfc-folder-tree-selection-and-nesting-1002/spec.md for acceptance criteria.
  2. UtilitiesCS/OutlookObjects/Folder/ (messages, codec, row state, renderer, assets).
  3. QuickFiler/Controllers/ (router partials, EfcFormController).
  4. QuickFiler/Resources/FolderBreadcrumb.js.
  5. Tests, then evidence projections (large, mechanical Markdown).

Follow-ups

  • Maintainer to perform and record the manual Outlook check (AC26).

GitHub Auto-close

🤖 Generated with Claude Code

https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P

drmoisan and others added 15 commits October 22, 2026 05:09
Co-Authored-By: Claude Opus 5.5 (noreply@anthropic.com)

Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
- Add recursive subfolder expansion and selection to the EFC breadcrumb
  tree through a keyed descendant tree on BreadcrumbRow, new
  descendantToggle and descendantActivate messages, and recursive
  rendering
- Guard against stale expansion completions, including the first-level
  ExpandLeafAsync path
- Select the trash entry created by the EFC trash button through a
  preferred-row bind
- Place the +/- toggle after the name on nested QFC subfolder rows and
  indent each level by 16px
- Add regression tests and feature-folder evidence for the router,
  codec, renderer, and nesting behavior

Refs: #1002

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
- Add tests for BindFolderRows and BindSourceFolderRows
- Add null-argument tests for the breadcrumb message constructors
- Add a null-viewer delete-gesture test
- Apply maintainer-ratified member-level ExcludeFromCodeCoverage to the
  MessageBox-bound EFC action handlers, RefreshSuggestionsAsync and
  ConfigureBreadcrumbControl
- Add a selected-descendant highlight rule to both EFC themes
- Restore ellipsis truncation on .child .name
- Add remediation evidence for cycle 1

Refs: #1002

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
Co-Authored-By: Claude Opus 5.5 (noreply@anthropic.com)

Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
Co-Authored-By: Claude Opus 5.5 (noreply@anthropic.com)

Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
Co-Authored-By: Claude Opus 5.5 (noreply@anthropic.com)

Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
Co-Authored-By: Claude Opus 5.5 (noreply@anthropic.com)

Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
- Amend AC23 to name the five maintainer-ratified ExcludeFromCodeCoverage
  members and add a dated amendment entry to spec.md
- Name the EfcViewer dependency in the ActionCancelAsync exemption comment
- Fault the delivered-task waits in the EFC tests on a bind fault instead
  of hanging, and add a test for that path
- Wrap child names in a name span in the bridge subfolderResult handler so
  truncation applies, with a text-contract test
- Add cycle 2 evidence for the baseline, QA gates, coverage, and child-name
  dispositions

Refs: #1002

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
Co-Authored-By: Claude Opus 5.5 (noreply@anthropic.com)

Claude-Session: https://claude.ai/code/session_014ASyXWyEc23fGahFNciw3P
@drmoisan
drmoisan merged commit 3466512 into main Oct 22, 2026
7 checks passed
@drmoisan drmoisan mentioned this pull request Oct 22, 2026
1 of 5 tasks
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: efc-qfc-folder-tree-selection-and-nesting

1 participant