Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fca5396
docs(743): inherit prepared feature folder and mid-authoring plan fro…
drmoisan Sep 13, 2026
42e547d
chore(743): preserve inherited task-researcher findings on the pump t…
drmoisan Sep 13, 2026
2d1c0fe
chore(743): record dead-worktree recovery technique and the C4 model-…
drmoisan Sep 13, 2026
31849cd
docs(743): add planner handoff records and repair four unsatisfiable …
drmoisan Sep 13, 2026
30dc6dd
docs(743): apply preflight round 1 delta, twelve findings including a…
drmoisan Sep 13, 2026
0f5ec13
chore(743): record planner and preflight findings from the two-round …
drmoisan Sep 13, 2026
d046693
docs(743): add explicit LogFileName= to all eight /Logger:trx spans i…
drmoisan Sep 13, 2026
b10dad7
wip(743): quota-hold sweep, Phase 0 baseline evidence and plan progress
drmoisan Sep 13, 2026
08e2942
wip: commit before quota exhaustion
drmoisan Sep 13, 2026
c358b2d
Merge origin/main (39ce2892b, sibling item 583) into bug/quickfiler-i…
drmoisan Sep 13, 2026
5149565
docs(743): record the diff-base re-anchor to the origin/main merge co…
drmoisan Sep 13, 2026
e362cc6
issue 743 phase 0: baselines and AC1 observable declaration
drmoisan Sep 13, 2026
063edf7
issue 743 phase 0-1: baselines, gate instrumentation and AC1 mechanis…
drmoisan Sep 13, 2026
bce8104
issue 743 phase 2: additive viewer seam, defect-preserving intermedia…
drmoisan Sep 13, 2026
cc236c8
issue 743 phase 3: additive members in use, injected-seam marshal wit…
drmoisan Sep 13, 2026
0a845c2
issue 743 phase 4: branch COST selected, retained instrumentation con…
drmoisan Sep 13, 2026
2a94810
issue 743 phases 2-5: additive viewer seam, dispatcher marshal conver…
drmoisan Sep 13, 2026
58dd456
issue 743: record the P5-T3 check-off in the plan
drmoisan Sep 13, 2026
151241e
issue 743 phase 6 interim: final QA toolchain gates, coverage compari…
drmoisan Sep 13, 2026
5f6893d
issue 743: final QA loop, coverage comparison and acceptance check-off
drmoisan Sep 13, 2026
0677334
issue 743: record P6-T17 and P6-T18 check-off
drmoisan Sep 13, 2026
1d00eed
docs(743): add policy-audit, code-review and feature-audit artifacts …
drmoisan Sep 13, 2026
b8fc8d5
docs(743): author remediation cycle 1 inputs (R-1 host path, R-2 AC1 …
drmoisan Sep 13, 2026
56301e3
chore(743): record orchestrator memory on the spec-clause-versus-plan…
drmoisan Sep 13, 2026
9170499
fix(743): resolve review finding R-1 and correct the AC1 checkbox state
drmoisan Sep 13, 2026
5dd7bb5
docs(743): apply review finding R-2 wording amendment to the AC1 mech…
drmoisan Sep 13, 2026
5f50655
docs(743): record the maintainer AC1 ratification and correct the ver…
drmoisan Sep 13, 2026
f8f4a15
Merge commit 'e6d86049e31096914eaf6dcbc7222e5b9f435258' into bug/quic…
drmoisan Sep 13, 2026
841fba7
docs(743): corrected AC1 verdict, post-merge toolchain and evidence-f…
drmoisan Sep 13, 2026
9fc422c
Merge branch 'main' into bug/quickfiler-itemviewer-ui-marshalling-sea…
drmoisan Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
289 changes: 86 additions & 203 deletions .claude/agent-memory/atomic-executor/MEMORY.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
name: 743-seam-conversion-breaks-untouchable-test-and-r4-designed-contention
description: Issue #743 preflight (2026-09-12) - converting ViewerSetup.cs line 371 to _uiDispatcher without null tolerance NREs an existing 498-line test off the Write Set; the fixture's R4 test deliberately contends the TransactionGate so a serial "contended count 0" rule is non-discriminating; the coverage runner throws at line 236 before post-processing on ANY failing test
metadata:
type: project
---

Three plan-shape facts found while preflighting the #743 plan (`plan.2026-09-12T13-23.md`).

1. **`_uiDispatcher` is null under the parameterless `HarnessController`.** `QfcItemController.TestSupport.cs` 162-165 records it; the field is assigned only at Initialization.cs 59 / 391. The existing test `AssignControlsAsync_DispatchesAssignThroughViewerDispatcher` (ViewerSetupTests.cs 309-344, file at 498 lines, NOT in the Write Set) injects only `_itemViewer` + `_globals`. Any conversion of `_itemViewer.UiDispatcher.InvokeAsync` (ViewerSetup.cs 371) to `_uiDispatcher.InvokeAsync` with no null tolerance makes that test NRE and the whole-assembly `failed=0` gate unsatisfiable. Spec 6.2's second risk bullet REQUIRES "the same null tolerance the existing sites have"; the reference shape is `NotifyMoveFailure` at MailActions.cs 35-46 (local copy, direct call when null).

2. **R4 (`Transaction_SecondCallerCannotInstallUntilTheFirstRestores`, FixtureTests.cs 204-262) starts a second transaction while the first is held.** In the SERIAL regime it contributes 0 or 1 "contended acquisition" per run nondeterministically, so any decision rule of the form "serial contended count > 0 => leak" is polluted by design. Exclude it by `FullyQualifiedName!~` from the measurement run and say why. R4 is also the #823 known-intermittent (1 failure in 4 parallel-regime runs per the flake-watch log), so 62-run streaks over its class will not stay clean.

3. **`Invoke-MSTestWithCoverage.ps1` throws `MSTest with coverage failed with exit code` at line 236 on ANY non-zero vstest exit**, which is BEFORE `ConvertTo-KoverageCoberturaXml` at 342. A single flaky test leaves the raw document with absolute filenames, and a per-file XPath on workspace-relative backslash filenames returns zero class nodes. The 80%-threshold throw at 344 is the only non-zero path that leaves the document post-processed. Recovery: dot-source `scripts\vscode\Invoke-MSTestWithCoverage.Helpers.ps1` (function at line 406) and post-process manually. The runner has no exclusion parameter, so `-SearchRoot QuickFiler.Test` is the way to dodge the UtilitiesCS shell-icon hang.

**How to apply:** when a plan converts a viewer-owned marshal to the injected seam, grep the test project for existing tests of that member that build the controller through the harness and check whether they inject `_uiDispatcher`; when a plan builds a gate observable from `TransactionGate` counters, read every `BeginTransactionAsync` caller for nested/concurrent acquisitions first.
266 changes: 73 additions & 193 deletions .claude/agent-memory/atomic-planner/MEMORY.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: project_743_itemviewer_marshalling_seam_plan_seams
description: Issue #743 (QuickFiler ItemViewer UI-marshalling seam) completion-pass seams — a wildcard test-name comment makes a full-name grep false-before; a commented-out duplicate of a converted literal makes a zero-count gate unsatisfiable; AssignControls needs _globals injected; the SubagentStop hook path check bit two multi-line tasks
metadata:
type: project
---

Found on 2026-09-12 while completing an orphaned #743 plan (predecessor session died mid-pass, plan body done, no handoff record).

**Seams, each confirmed against the tree:**

1. **ViewerSetup.cs line 275 names the retained pump test only as `ResolveControlGroupsAsync_ThroughThePumpHost_*` (wildcard).** A grep for the full name `..._PopulatesTipsAndControlGroups` in the production file is 0 pre-edit, so a comment-update gate on it IS false-before. The orchestrator assumed it was already 1. Still add a clause on the TEST file (which the plan never writes) so the gate proves the named test exists.
2. **Line 365 is a commented-out copy of the line-371 marshal** (`// await _itemViewer.UiDispatcher.InvokeAsync(...)`). A "prints 0" gate on `_itemViewer.UiDispatcher.InvokeAsync` after converting 371 is unsatisfiable; the correct post-edit count is 1 (pre-edit 2). Same class as the #442 commented-out-code trap; always grep the whole file for the literal, including comments, before writing a zero-count.
3. **`AssignControls` reads `_globals.QfSettings` (lines 401-410).** `HarnessController` supplies nothing for `_globals`; every existing AssignControls test injects `BuildGlobals(...)` (private static at ViewerSetupTests.cs 36-51, NOT reachable from a new file). A seam test of `AssignControlsAsync` with a mock viewer must build its own `Mock<IApplicationGlobals>` → `Mock<IAppQuickFilerSettings>` and a parameterless `MailItemHelper`.
4. **`validate-planner-output.ps1` path check hit P4-T1 and P6-T14**: both had the path only in bullets/body lines, not on the `- [ ] [P#-T#]` opening line. Grep `^- \[ \] \[P\d+-T\d+\] [^/\\]*$` before handoff; expect 0 hits.
5. **`Panel`-parented labels are accepted by `QfcTipsDetails.CreateAsync`** (ResolveParentType allows exact `TableLayoutPanel` or `Panel`; precedent at UtilitiesCS.Test/HelperClasses/QfcTipsDetails_Tests.cs 660-711).
6. `CITATION:` path regex in the hook requires at least one `/` — cite root files as `./.gitignore`, `./TaskMaster.runsettings`.

**Preflight round 1 seams (2026-09-12, 12 deltas, all confirmed against the tree):**

7. **Converting `_itemViewer.UiDispatcher.InvokeAsync` to `_uiDispatcher` MUST carry null tolerance** (spec 6.2 second risk bullet; shape = `NotifyMoveFailure`, MailActions partial 35-46). `HarnessController` calls the protected parameterless ctor (Initialization 27), which assigns nothing; the field is only set at Initialization 59/391/438/480. Existing test `AssignControlsAsync_DispatchesAssignThroughViewerDispatcher` (ViewerSetupTests 308-344, file at 498 lines so untouchable) never injects `_uiDispatcher` and would NRE. "No null guard because it hides a bug" was the wrong call — check every existing test that reaches the site through the harness.
8. **`Transaction_SecondCallerCannotInstallUntilTheFirstRestores` (FixtureTests 204-262) starts a second `BeginTransactionAsync` while the first is held** — it contributes 0-or-1 contended acquisition by race and pollutes any "serial contended count == 0" observable. Exclude with `&FullyQualifiedName!~...` in the filter. It is also the #823 known-intermittent; never put it in an N-run streak.
9. **Exactly six `ThroughThePumpHost` tests exist** (Part3 40/83/131/175/245 + ViewerSetupTests 426). An "at least eight" floor was unsatisfiable; count the token before writing any duration-table floor.
10. **`Invoke-MSTestWithCoverage.ps1` accepts a single-assembly `-SearchRoot`** (line 296 wraps discovery in `@(...)`) — unlike `Invoke-MSTest.ps1`. Use `-SearchRoot QuickFiler.Test` to dodge the four UtilitiesCS shell-icon stalls. Its two non-zero paths differ: a vstest failure throws at line 236 BEFORE post-processing (line 342), leaving absolute filenames; the 80% assert (line 344, message from Threshold.ps1 54) runs after. Plan the manual `ConvertTo-KoverageCoberturaXml` fallback (Helpers.ps1 406) for the first case.
11. **A plan-status gate that greps the plan for `Status: Executed` matches its own task line**; the header form is `- **Status:** X`, so anchor `^- \*\*Status:\*\* Executed`.
12. **`acceptance-criteria-tracking` forbids appending pointers to criterion text** — check-off tasks change only the checkbox; PARTIAL figures and evidence pointers go in the status-summary artifact rows.
13. **Blast-radius extractor harvests backticked forward-slash tokens with a recognised extension even inside command spans**; write script paths in commands with backslashes (`scripts\vscode\Foo.ps1`) and name out-of-set files in plain prose. `.runsettings` switch tokens were not harvested.

**How to apply:** For any QfcItemController seam test plan, check `_globals` consumption in the member under test; for any "convert marshal" task, count the literal in comments too; run the opening-line path grep before ending the turn.
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ metadata:

**Why it matters for planning:** a plan task that cites `-SearchRoot <SingleProject>.Test` is unexecutable. Cite `-SearchRoot .` instead — the repo-wide form is proven (nine assemblies, 6112 tests) and has the side benefit of proving no regression across the other test assemblies. The one-line remedy is `@($testAssemblies).Count`, but fixing it drags the PowerShell/PoshQC toolchain plus a `artifacts/pester/powershell-coverage.xml` artifact into an otherwise C#-only feature's review gate, which is usually disproportionate — prefer filing it as a separate entry and noting it out of scope.

The sibling coverage runner [reference_invoke_mstest_with_coverage_script](reference_invoke_mstest_with_coverage_script.md) is the right citation when numeric coverage evidence is required.
The sibling coverage runner [reference_invoke_mstest_with_coverage_script](reference_invoke_mstest_with_coverage_script.md) is the right citation when numeric coverage evidence is required. **The coverage runner does NOT share this defect** (verified 2026-09-12, #743 R1): `Invoke-MSTestWithCoverage.ps1` line 296 wraps discovery in `@(Get-ChildItem ...)`, so `-SearchRoot QuickFiler.Test` (single assembly) is accepted; `-SearchRoot` is joined to the repo root at line 272. Use the single-assembly form when the nine-assembly run would hit the local UtilitiesCS shell-icon stalls.
5 changes: 5 additions & 0 deletions .claude/agent-memory/orchestrator/MEMORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Orchestrator Memory Index

## Resuming a dead run
- [Recover a dead agent worktree via shared git](recovering-a-dead-agent-worktree-via-shared-git.md) — its committed work is already in your object store; `git -C` into it is refused but `hash-object` reads its uncommitted files
- [Blast-radius audit must cover the PLAN too](blast-radius-audit-must-cover-the-plan-too.md) — spec-only audit missed 5 stray paths; a BACKSLASH path is dropped by the extractor

## Lifecycle, promotion, checkpoint
- [Evidence + lifecycle for every change](evidence-and-lifecycle-for-every-change.md) · [Small-path = minor-audit](small-path-minor-audit-selection.md) — 1-3 prod files = small path
- [potential_to_issue creates the issue](potential-to-issue-creates-github-issue.md) · [needs an absolute path](potential-to-issue-needs-absolute-path.md) · [maps sections by heading](potential-to-issue-keeps-only-summary-section.md)
Expand All @@ -15,6 +19,7 @@
- [Shared checkpoint: never read-modify-write](shared-checkpoint-read-modify-write-corrupts.md) · [Resumed child shares your worktree](resumed-child-orchestrator-shares-worktree.md)
- [MCP tools available to orchestrator](mcp-tools-available-to-orchestrator.md) — run them yourself if a worker can't
- [Run the real hook, not MCP](run-orchestration-hook-gates-locally.md) — the MCP validator disagrees on the bug route
- [Preflight-cleared plan can still contradict a spec AC clause](preflight-cleared-plan-can-still-conflict-with-a-spec-acceptance-clause.md) — read each AC's "not a pass" sentence against the claiming task's decision rule before execution (#743 AC1 no-expiry)

## PR authoring and CI gate
- [pr-author is a skill, not an agent](pr-author-hook-blocks-gh-in-this-repo.md) · [exact checkpoint schema](pr-author-hook-exact-checkpoint-schema.md) — agents must be a LIST; `relativeFile` required
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: blast-radius-audit-must-cover-the-plan-too
description: "Auditing only spec.md for stray backticked paths is incomplete — the blast-radius extractor reads the plan task bodies too; and a BACKSLASH path is dropped by it, which is the escape hatch for command spans"
metadata:
type: reference
---

The blast-radius extractor harvests backticked paths from **both** `spec.md` **and the plan task
bodies**. Auditing only the spec passes a clean bill on a plan that still over-schedules.

**Why:** on 2026-09-12 (issue #743) I audited every backticked forward-slash token in `spec.md`,
confirmed it resolved to exactly the declared seven-path Write Set, and recorded the radius as clean.
Preflight then found five out-of-Write-Set paths backticked in the **plan's** prose — the UtilitiesCS
threading and extension files and the test-support file — each of which would have serialized the item
against siblings that had no real conflict with it.

**How to apply:**

- Audit both files. Extract with the extractor's own rule rather than by eye: a backtick span, a
whitespace-free token inside it, containing `/`, ending in a recognised extension. Intersect the
result with tracked paths and diff against the declared Write Set.
- **A backslash path is DROPPED.** `.claude/lib/blast-radius/BlastRadiusExtraction.psm1` tests for `/`
only, so `scripts\vscode\Invoke-MSTestWithCoverage.ps1` is not harvested while
`scripts/vscode/Invoke-MSTestWithCoverage.ps1` is. That is the fix for a path that must stay inside a
backticked **command span**, where plain prose is not an option: write it with backslashes, which
pwsh accepts anyway. For ordinary prose, name the file in words with no backticks at all.
- The extractor has no notion of polarity, so a path in a sentence promising *not* to touch the file is
scheduled exactly like one you will edit. See [[spec-backticks-widen-blast-radius]].
- A plan that carries its own "excluded files are named in plain prose" rule can still violate it in
the Decisions Record and the citation table, which is where the #743 violations were. Check those
two regions specifically; they are prose-heavy and easy to skip.

Related: [[get-blastradius-overincludes-citations-omits-gitignored-writes]]
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,20 @@ four floor signals — `classifier_or_model_logic`, `auth_or_token_handling`,
`concurrency_or_ordering`, `cross_module_contract_change` — each contributing C3, and anything
else contributes nothing and leaves the floor at C1.

**At band C4 the overlay is irrelevant and every agent gets fable.** The overlay rewrites only the
C3 cell, and the base table already maps `C4` to `fable`, so under `preferred` *and* under
`available` a C4 delegation resolves to `table_model=fable, clamped_from=null, model=fable` for
**every** agent — including `atomic-executor` and `pr-author`, which are the two that stay opus at
C3. C4 yields opus only under `disabled`, and then as a clamp (`clamped_from=fable`,
`clamp_reason=fable_disabled`). Verified 2026-09-12 by reading the module for issue #743, where an
inherited checkpoint recorded the `disabled` clamp and the new session ran `preferred`; the receipts
had to be recomputed rather than carried over.

**You may not be able to run the module.** `pwsh` is refused under Agent worktree isolation, in the
`-Command` form too, so in an isolated worktree resolve the model by READING
`.claude/lib/model-routing/ModelRouting.psm1` — the two functions are pure and the tables are
module-scope constants, so reading them is exact, not an approximation. See
[[worktree-isolation-blocks-pwsh-per-agent-type]].

Related: [[model-routing-scripts-absent-on-epic-integration-base]],
[[model-routing-hook-reads-canonical-path-only]]
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@ Do not respond to this error by running the promotion or prd-feature step again:
would duplicate work already committed. Verify the folder on disk first
(see [[small-path-minor-audit-selection]] for the mode-to-document mapping).

## In a parallel item, this hook makes atomic-planner UNREACHABLE (verified 2026-09-13, items 839 and 743)

`Find-PrdFeatureFolderFromPrompt` truncates any `docs/features/active/...` token in the prompt to the
four-segment folder (absolute or relative spelling alike), and `Get-PrdFeatureIssueContent` (line
107) then does `Test-Path "$FeatureFolder/issue.md"` with no cwd override, so the read resolves
against the hook process cwd, the session root. A parallel item's feature folder exists only on its
branch in its own worktree, so the marker reads as "unreadable" and the delegation is denied while
`- Work Mode:` sits correct at line 12 of the item worktree's `issue.md`. With ZERO prompt candidates
the line-369 fallback reads the SESSION-ROOT checkpoint's `feature-folder`, a sibling's, and would
admit the delegation on the sibling's documents: an engineered false green, refuse it. Shimming the
folder into the session root and `isolation: "worktree"` are both out (the hook fires in the parent
process; the directive forbids session-root writes).

Consequence confirmed on 743: a parallel item cannot run its REMEDIATION loop at all, because cycle
N's `remediation-plan.md` must come from `atomic-planner`, so any review with `blocking_count > 0`
ends the item blocked however small the fix (743's were a one-token path substitution and an
evidence-wording amendment). Author `remediation-inputs.md` fully anyway, commit and push it, record
`blocked_reason: delegation_launch_failed` with the mechanism, and hand the planner step to the
coordinator. Fix upstream in drm-copilot; `.claude` files here are push-down-owned.

Related: [[agent-worktree-hooks-resolve-to-agent-cwd]],
[[model-routing-hook-reads-canonical-path-only]] — both are cases of a hook resolving a
[[model-routing-hook-reads-canonical-path-only]],
[[preimplementation-gate-reads-sibling-checkpoint]] — all cases of a hook resolving a
path differently from how the calling agent meant it.
Loading
Loading