Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
47e539c
fix(breadcrumb): restore folder selector drop-down behavior
drmoisan Jul 21, 2026
78113a9
fix(quickfiler): checkpoint folder selector remediation
drmoisan Jul 22, 2026
a3bb0c1
test(breadcrumb): expand coverage for dropdown open coordination and …
drmoisan Jul 22, 2026
d677cce
test(breadcrumb): checkpoint P5-T153 scope inventory and CSharpier bl…
drmoisan Jul 22, 2026
2596336
docs(breadcrumb): revise remediation plan for CSharpier partial-class…
drmoisan Jul 22, 2026
3b8b371
test(breadcrumb): split oversized P5 test classes and apply real CSha…
drmoisan Jul 22, 2026
c8b507f
test(breadcrumb): record P5-T172 instrumented-run determinism finding
drmoisan Jul 22, 2026
92ea234
docs(breadcrumb): plan diagnosis-first fix for UI-dispatch determinis…
drmoisan Jul 22, 2026
84cf011
fix(breadcrumb): require ambient context match to prove UI dispatch b…
drmoisan Jul 22, 2026
3b48982
docs(breadcrumb): plan test-only coverage correction for nine sub-90%…
drmoisan Jul 22, 2026
4467078
test(breadcrumb): cover coordinator and popup-host branch shortfalls
drmoisan Jul 22, 2026
3c8f6f8
test(breadcrumb): close eight of nine sub-90% coverage units (P5-T185…
drmoisan Jul 22, 2026
49cea16
docs(breadcrumb): plan removal of unreachable recovery catch to close…
drmoisan Jul 22, 2026
8e62b23
fix(breadcrumb): remove unreachable recovery catch to complete Phase 5
drmoisan Jul 22, 2026
e0438c3
(fix): SpamBayes.Actions.cs when Junk Folder is null
drmoisan Jul 22, 2026
785c828
fix(breadcrumb): implement subfolder activation with identity-based r…
drmoisan Jul 23, 2026
a5dcf8c
docs(breadcrumb): record Phase 9 formatter stabilization and remediat…
drmoisan Jul 23, 2026
29cd83a
fix(coverage): derive test-assembly exclusion without mutating covera…
drmoisan Jul 24, 2026
214ca3a
docs(quickfiler): record coverage wrapper QA completion
drmoisan Jul 25, 2026
b732737
refactor(breadcrumb): extract host-neutral ItemViewer lifecycle seams
drmoisan Jul 27, 2026
294132b
test(quickfiler): cover breadcrumb adapter boundary paths
drmoisan Jul 27, 2026
1dc2c4b
docs(quickfiler): reconcile remediation evidence through P10-T3
drmoisan Jul 27, 2026
62c4eb1
(docs): audit trio
drmoisan Aug 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .claude/agent-memory/atomic-executor/MEMORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Atomic Executor Memory Index

- [#400 CompleteOpenAsync unreachable recovery catch](project_400_completeopenasync_unreachable_recovery_catch.md) — P5-T185..204: CompleteOpenAsync d__16 153-156 is dead code (dispatcher.Report swallows sink exceptions), can't reach >=90% test-only; blocks T202-T204, escalated; 17-class gate deadlocks PopupControlDispatch testhost, retry after clearing runners (passed 5th try)
- [csharpier pipe-files is a non-enforcing gate](project_csharpier_pipefiles_nonenforcing_gate.md) — `csharpier pipe-files`+re-hash-unmodified-file enforces nothing; use `csharpier check`/`format`; #400 P5 tests balloon past 500 lines under genuine format (size new files AFTER format, not hand-written count)

- [#398 test-split gate gotchas](project_398_test_split_gate_gotchas.md) — pre-existing CS2002 duplicate PercentageFormatterTests Compile (latent til recompile, out of scope, don't Rebuild-to-verify); /EnableCodeCoverage has no branch% + .coverage merges to empty cobertura → use Cobertura-runsettings variant + single report-level JaCoCo counter; cobertura run needs MSTest Workers=4 or TryAddValuesAsync times out ~22s
- [#376 capstone scope-expansion layers](project_376_capstone_scope_expansion_layers.md) — 5 escalated layers past P2-T17 resolved via the 3 authorized patterns; stop-condition never triggered
- [BOM breaks grep ^ anchor](project_bom_grep_anchor_false_negative.md) — bash grep `^#nullable` misses BOM-prefixed files; always use the Grep tool for opt-in/candidate classification, never bash grep
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: 400-completeopenasync-unreachable-recovery-catch
description: "#400 P5-T185..204: CompleteOpenAsync d__16 inner recovery-failure catch (lines 153-156) is unreachable dead code; can't hit >=90% test-only because dispatcher.Report swallows sink exceptions"
metadata:
type: project
---

In QuickFiler `BreadcrumbDropDownOpenLifetime.CompleteOpenAsync` (`<CompleteOpenAsync>d__16`), the inner
recovery-failure catch is unreachable dead-defensive code and cannot be covered by any test-only change.

**Why:** For that inner `catch (recoveryFailure)` to run, `HandleOpenFailureAsync` must throw. Its entire body is
`try { await _uiOperations.RunAsync(..., reportFailure:false); } catch (rollbackFailure) { _uiOperations.Report(rollbackFailure); }`.
The only statement that can throw out is the `Report` call, which resolves to `BreadcrumbUiDispatcher.Report` — and
that method swallows every error-sink exception (rethrows only when its argument is null, which cannot happen for a
caught non-null exception). So `HandleOpenFailureAsync` never faults; the inner catch is dead. Confirmed both
analytically and by a focused instrumented probe with a throwing error sink (still 24/28, lines 153-156 uncovered),
which was reverted.

**How to apply:** The #400 remediation plan (`remediation-plan.2026-07-21T21-37.md`) P5-T185/P5-T195 wrongly claim
these lines are a "reachable late-callback branch" coverable test-only to reach >=90%. They are not. The plan's
zero-production-file rule plus the flat >=90%-per-unit rule are jointly unsatisfiable for this state machine
(max reachable = 24/28 = 85.71%). Batch N1 (`BreadcrumbDropDownOpenCoordinatorTests.Part2.cs`) and 4 of 5 N2 cases
(`BreadcrumbPopupBoundaryCoverageTests.Part2.cs`) close their 8 units cleanly (7 at 100%, EnsureSurfaceAsync 97.67%);
only CompleteOpenAsync blocks P5-T202/T203/T204. Escalated for replanning: either authorize a minimal production
change to make the recovery propagate / remove the dead catch, or revise the ninth-unit acceptance to its reachable
maximum. See [[project_400_csharpier_pipefiles_nonenforcing_gate]] for the same feature's P5 gate mechanics.

Also: the 17-class instrumented gate (`Workers=0`/24 ClassLevel + dotnet-coverage) intermittently deadlocks a
`BreadcrumbPopupControlDispatchTests` testhost during concurrent WinForms host-handle creation — same documented
stall the 16-22 baseline hit. Clear residual dotnet-coverage/testhost/vstest, confirm 0 with no respawn, re-run the
exact command; it passed 170/170 natural-exit-0 on the 5th attempt. Never cite a stalled attempt as a result.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: csharpier-pipefiles-nonenforcing-gate
description: csharpier pipe-files + re-hash-unmodified-file is a fake format gate; use `csharpier check`/`format`; #400 P5 tests balloon past 500 lines when genuinely formatted
metadata:
type: project
---

`csharpier pipe-files` (fed an absolute-path stdin list) writes formatted output to STDOUT and never modifies the file on disk. A gate that then re-hashes the (unmodified) file and reports "stable/PASS" is trivially satisfied and enforces nothing.

**Why:** In issue #400 (QuickFiler folder-selector drop-down), ~20 prior P5 CSharpier evidence artifacts used exactly this pattern, so the committed P5 production/test files were never actually CSharpier-clean. When P5-T154 ran genuine `csharpier format` (CSharpier 1.3.0, no `.csharpierrc`, default width 100), 8 of 10 files changed and two coverage test files blew past the hard 500-line limit: `BreadcrumbDropDownOpenCoordinatorTests.cs` 395->514 and `BreadcrumbPopupBoundaryCoverageTests.cs` 479->562. The prior batches sized those files to <=480 using their UNFORMATTED line counts. This created an unsatisfiable conflict (CSharpier-clean AND <=500) that only a plan revision (split into partial-class pairs + new includes) can resolve — P5-T154..T160 were left blocked.

**How to apply:** For any TaskMaster CSharpier gate, verify with `csharpier check <files>` (exit 1 == not formatted) or `csharpier format <files>` (writes in place), never `pipe-files`+re-hash. When sizing new/edited .cs files against the 500-line limit, measure the count AFTER `csharpier format`, not the hand-written count. Reformatting can both expand (arg lists broken across lines) and shrink (blank-line removal) files. See also [[vs18-build-toolchain-paths]].
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ Signature of the problem:
Get-CimInstance Win32_Process -Filter "Name='pwsh.exe'" | ? { $_.CommandLine -match 'Invoke-MSTest' } | % { Stop-Process -Id $_.ProcessId -Force }
Get-Process vstest.console,testhost,testhost.x86,dotnet-coverage -EA SilentlyContinue | Stop-Process -Force
```
**Residual state can look like a DETERMINISTIC hang, not a flake.** Observed on #400 P5: after an externally terminated out-of-filter `vstest.console` probe, the next two 17-class `dotnet-coverage` runs both stalled at exactly 148/160 with 0 failures, and a `/Settings` uninstrumented control stalled at 150/160 — the identical stall point twice reads as a real deadlock caused by whatever you just edited. It was not. Each class passed alone, the stalling pair passed alone, and after clearing every `vstest.console`/`testhost` process the same commands passed 160/160 twice (uninstrumented and instrumented). Before concluding "my production change deadlocked the suite", clear the process table and re-run the exact same command once.

Then re-check `Get-Process vstest.console,testhost,dotnet-coverage` == 0 AND the `Invoke-MSTest` pwsh count == 0 before running. A plain `Stop-Process` on the binaries alone is NOT enough — the surviving pwsh runner respawns testhosts. Give the clean run a generous timeout (>= 8 min) so it never times out and re-stacks. Note: leftover idle `MSBuild.exe` `nodemode` reuse-pool workers are harmless (near-zero CPU) and are NOT the cause — do not confuse them with a concurrent build. See [[project_concurrent_executor_same_worktree]].
4 changes: 4 additions & 0 deletions .claude/agent-memory/atomic-planner/MEMORY.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Atomic Planner Memory Index

- [Dead-code removal vs coverage exclusion](project_deadcode_removal_vs_coverage_exclusion.md) — coverage gate blocked by unreachable dead prod code → plan removal (shrink denominator), never exclusion/carve-out/forced-rethrow

- [Coverage Evidence Path Normalization](evidence-path-normalization.md) — specs sometimes name evidence/coverage/; normalize to canonical baseline/ + qa-gates/
- [CSharpier gate: format not pipe-files](csharpier-format-not-pipe-files-gate.md) — formatting tasks must use `csharpier format` + scoped `csharpier check` exit 0; `pipe-files` is stdout-only/non-enforcing and masked a 500-line overflow in #400
- [#400 partial-class headroom placement](project_400_partial_class_headroom_placement.md) — put new coverage cases in existing `.Part2.cs` `[TestClass] partial` files to keep the 17-class filter/count assertions stable
- [Manager AsyncLazy shared seam](project_manager_asynclazy_shared_seam.md) — Globals.AF.Manager is shared across all classifier subsystems; use a key-specific accessor, never retype the dictionary value for one key
- [Folder predictor AF holder seam](project_folder_predictor_af_holder_seam.md) — #177 F1: route flag-on LCPPN predictor through a Folder-only holder on IAppAutoFileObjects (globals.AF), not per-instance OlFolderClassifierGroup state
- [Plan validator phase-heading constraint](plan-validator-phase-heading-constraint.md) — MCP plan validator requires exact `### Phase N — <Title>`; no tokens between Phase N and em-dash; H1 title line is exempt
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: csharpier-format-not-pipe-files-gate
description: C# formatting-gate plan tasks must use `csharpier format` + scoped `csharpier check` exit 0, never `csharpier pipe-files`, which writes to stdout only and is non-enforcing
metadata:
type: feedback
---

When planning any C# CSharpier formatting gate task, require `csharpier format` (mutates files on disk) followed by a scoped `csharpier check` returning `EXIT_CODE: 0`. Never let a formatting/verification gate rely on `csharpier pipe-files`.

**Why:** In #400 P5, prior formatting gates invoked `csharpier pipe-files`, which writes formatted output to stdout only and never modifies files on disk. The evidence recorded a false "stable/no change" result. When authoritative `csharpier check`/`format` was finally run, exit code was 1 and two committed test files expanded past the 500-line hard limit once genuinely formatted (395->514 and 479->562 lines), forcing partial-class splits. A gate that never mutates and never asserts exit 0 cannot enforce formatting or line-limit policy.

**How to apply:** In plan task text for every remaining formatting task (all phases), spell out `csharpier format` then scoped `csharpier check` exit 0, and explicitly prohibit `pipe-files` as a gate. A single "Fixed execution rules" bullet can bind all remaining formatting tasks at once; still tighten any task whose wording is the ambiguous "Run CSharpier on ...". Note that `csharpier format` can expand line counts, so line-limit assertions must be evaluated post-format, not on committed source. Related: [[legacy-csproj-explicit-compile-include]] (partial-class split files each need one adjacent Compile include), [[plan-validator-task-id-sequential-constraint]] (inserting split-correction tasks mid-phase forces renumbering the unchecked tail + cross-refs).
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: project-400-partial-class-headroom-placement
description: "#400 breadcrumb plans: add new coverage cases to existing [TestClass] partial .Part2.cs files, not topically-correct near-limit files, to keep the 17-class filter intact"
metadata:
type: project
---

When a QuickFiler breadcrumb remediation plan needs new test cases to close a coverage
shortfall, allocate them to an existing `*.Part2.cs` `[TestClass] partial` continuation
that still has headroom to the 480-line bound — even when a different file is the
topically correct home.

**Why:** the downstream instrumented gate pins an exact 17-class filter and per-class case
counts. A `.Part2.cs` partial shares its original `[TestClass]` name, so class count and
filter string stay byte-identical and only the per-class case total changes. Creating a new
test file would require a new `QuickFiler.Test.csproj` Compile include, an 18th class, and a
rewrite of the filter and every downstream count assertion. In the 2026-07-22 revision,
`BreadcrumbDropDownLifecycleCoverageTests.cs` (468 lines) and
`BreadcrumbDropDownCoverageThresholdTests.cs` (479 lines) had effectively zero headroom, so
Host-lambda coverage was placed in `BreadcrumbPopupBoundaryCoverageTests.Part2.cs` instead.

**How to apply:** before allocating cases, capture current physical line counts for every
candidate test file, exclude any above roughly 460 lines, and prefer `.Part2.cs` partials.
State the case arithmetic explicitly (old total + added = new total) so the executor has an
exact expected count rather than a stale one. If a post-format count would exceed 480, stop
for replanning rather than silently adding a file.

Related: [[plan-validator-task-id-sequential-constraint]], [[project_351_quickfiler_breadcrumb_plan_seams]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: deadcode-removal-vs-coverage-exclusion
description: when a coverage gate is blocked by provably-unreachable dead production code, plan removal (shrink the denominator), never an exclusion/carve-out/forced-rethrow
metadata:
type: project
---

When a below-threshold coverage unit is blocked by provably-unreachable dead production code (e.g. #400 `BreadcrumbDropDownOpenLifetime.<CompleteOpenAsync>d__16` at 24/28, whose inner recovery `catch` at lines 153-156 can never execute because `HandleOpenFailureAsync` routes every failure to `BreadcrumbUiDispatcher.Report`, which cannot throw for a non-null exception), the repo-policy-favored resolution is to REMOVE the dead code so the denominator shrinks to 24/24.

**Why:** `.claude/rules/general-unit-test.md` forbids excluding any production file from coverage and requires untestable lines be refactored out; the simplicity-first design principle favors removing dead defensive code. Adding a coverage exclusion, documenting a `24/28` acceptance carve-out, or making a collaborator rethrow to force the catch reachable are all rejected.

**How to apply:** Plan a bounded one-production-file batch (authorization/unreachability-proof inventory → delegate edit → csharpier/analyzer/nullable/focused-vstest gates → behavior-preservation+scope+anti-masking ledger → re-run the coverage gate). State in the plan text that dead-code removal is expressly NOT a masking action and distinguish it from the [[plan-validator-task-id-sequential-constraint]] anti-masking prohibitions (no weakened/deleted assertions, sleeps, retries, [DoNotParallelize]/[Ignore], filter narrowing, coverage/threshold changes) with a one-line unreachability justification. Removal is production-only, so the instrumented case total is unchanged unless an optional comment-only test touch is authorized; verify a test that appears to target the dead lines actually asserts behavior on the reachable path (its report may come from an inner catch elsewhere) so its assertions stay byte-identical.
Loading
Loading