diff --git a/.claude/agent-memory/orchestrator/MEMORY.md b/.claude/agent-memory/orchestrator/MEMORY.md index 7a7f2fc8b..202dcb3fc 100644 --- a/.claude/agent-memory/orchestrator/MEMORY.md +++ b/.claude/agent-memory/orchestrator/MEMORY.md @@ -1,4 +1,5 @@ -- [CLAUDE.md nullable command != the CI gate](project_claudemd_nullable_command_diverges_from_ci.md) — ci.yml omits `/p:Nullable=enable`; CS86xx from the forced flag is a FALSE blocker +- [CLAUDE.md nullable command != CI gate — RESOLVED by #540](project_claudemd_nullable_command_diverges_from_ci.md) — docs now match ci.yml; a reappearance of `/p:Nullable=enable` or `/t:Build` is a regression. Carries the 195-error UtilitiesCS lower bound for #492 +- [PoshQC test drops coverage.xml at repo root](poshqc-test-drops-coverage-xml-at-repo-root.md) — untracked, not gitignored/csharpierignored; inflates the CSharpier file count and leaks into `git add -A` - [Agent-worktree discovery + evidence hygiene](project_agent_worktree_discovery_and_evidence_hygiene.md) — `\.claude\` test-glob filter must use the RELATIVE path; never commit raw Cobertura - [Completion-gate receipt shapes](completion-gate-receipt-shapes.md) — exact fields require_complete wants: delegation_receipts as a LIST, skill_receipts required:true - [JaCoCo not Cobertura for coverage evidence](jacoco-not-cobertura-for-evidence.md) — maintainer deletes committed Cobertura; convert to package-level JaCoCo before pushing @@ -68,7 +69,7 @@ - [C# coverage has two denominators](csharp-coverage-denominator-two-figures.md) — filtered first-party ~85.9% clears the gate, unfiltered ~70.4% doesn't; measure before trusting - [Preflight catches vacuous gates](preflight-catches-vacuous-gates.md) — MCP `ok:true` is not enough; executor preflight found 6 gates that passed while verifying nothing - [Bash tool mangles MSBuild switches](bash-tool-mangles-msbuild-switches.md) — `/m` becomes `M:/` (MSB1008); run C# tools via `pwsh -NoProfile` with absolute paths -- [Analyzer gate is vacuous without /t:Rebuild](msbuild-analyzer-gate-vacuous-without-rebuild.md) — `/t:Build` after any earlier build skips CoreCompile and compiles NOTHING at EXIT 0 +- [Analyzer gate is vacuous without /t:Rebuild](msbuild-analyzer-gate-vacuous-without-rebuild.md) — `/t:Build` after any earlier build skips CoreCompile and compiles NOTHING at EXIT 0; assert a ZERO `Skipping target "CoreCompile"` count, NOT a csc.exe count (csc is 0 even on real compiles) - [Aggregate vstest crash: isolate per assembly](vstest-aggregate-crash-isolate-per-assembly.md) — "Test host process crashed" is environmental; re-run per assembly with /InIsolation - [Direct-csproj build facts (AnyCPU; CS2002)](csharp-direct-csproj-build-facts.md) — a single project needs `AnyCPU` (no space) while the .sln needs `"Any CPU"`; TWAE doesn't promote CS2002 - [Model-routing hook reads the canonical path only](model-routing-hook-reads-canonical-path-only.md) — it hardcodes artifacts/orchestration/orchestrator-state.json; a child-scoped file alone is blocked diff --git a/.claude/agent-memory/orchestrator/poshqc-test-drops-coverage-xml-at-repo-root.md b/.claude/agent-memory/orchestrator/poshqc-test-drops-coverage-xml-at-repo-root.md new file mode 100644 index 000000000..a6eec9da5 --- /dev/null +++ b/.claude/agent-memory/orchestrator/poshqc-test-drops-coverage-xml-at-repo-root.md @@ -0,0 +1,23 @@ +--- +name: poshqc-test-drops-coverage-xml-at-repo-root +description: run_poshqc_test and direct Pester coverage runs write an untracked coverage.xml to the repo root that is neither gitignored nor in .csharpierignore, so it inflates the CSharpier file count and can leak into a diff +metadata: + type: project +--- + +`mcp__drm-copilot__run_poshqc_test`, and a direct `Invoke-Pester` run with +`$c.CodeCoverage.Enabled = $true`, both write a `coverage.xml` to the **repository root**. As of +2026-08-11 that path is in neither `.gitignore` nor `.csharpierignore`. + +**Why it matters:** CSharpier 1.2.6 processes `*.xml`, so the stray file raises the CSharpier +`Checked N files` count by one between two otherwise-identical runs, which looks like formatter +drift when you are comparing a baseline count against a final-QC count. It is also untracked, so a +`git add -A` at commit time will sweep it into the diff. + +**How to apply:** in any route that runs a PowerShell test gate before a C# format gate, delete the +root `coverage.xml` between the two and record the deletion in the format-step evidence artifact. +Re-check for it immediately before `git add`. Observed on issue #512 / PR #540; the executor removed +it before each CSharpier gate and attributed the count difference in the evidence. + +Distinct from [[jacoco-not-cobertura-for-evidence]] (which is about what coverage format to commit) +and from [[feature-review-coverage-85-floor-trap]] (about `artifacts/csharp/coverage.xml`). diff --git a/.claude/agent-memory/orchestrator/project_claudemd_nullable_command_diverges_from_ci.md b/.claude/agent-memory/orchestrator/project_claudemd_nullable_command_diverges_from_ci.md index 61addb67e..1f2fa24a8 100644 --- a/.claude/agent-memory/orchestrator/project_claudemd_nullable_command_diverges_from_ci.md +++ b/.claude/agent-memory/orchestrator/project_claudemd_nullable_command_diverges_from_ci.md @@ -1,15 +1,29 @@ --- name: claudemd-nullable-command-diverges-from-ci -description: CLAUDE.md's nullable toolchain command adds /p:Nullable=enable but ci.yml does not; forced-flag CS86xx in a file with no #nullable pragma is a false blocker, not a merge gate +description: RESOLVED 2026-08-11 by PR #540 - CLAUDE.md's C# toolchain commands now match ci.yml; the historical divergence (forced /p:Nullable=enable, vacuous /t:Build) and its false-blocker failure mode are recorded here metadata: type: project --- -`CLAUDE.md` documents the nullable stage as +**STATUS: RESOLVED on 2026-08-11 by issue #512 / PR #540** (child of epic +`build-ci-coverage-gate-fidelity`). `CLAUDE.md`, `.claude/rules/csharp.md` and +`.claude/skills/csharp-qa-gate/SKILL.md` now document `/t:Rebuild /m ... /p:TreatWarningsAsErrors=true` +with no `/p:Nullable=enable`, character-for-character `ci.yml`'s command, with in-line prohibitions +against re-adding either defect. The format command is now `dotnet tool run csharpier format .` +(v0 bare-path syntax fixed, #509). Read the sections below as the historical record of what the +divergence was and what it cost, not as a live description of the repo. + +**If you find `/p:Nullable=enable` or `/t:Build` back in a documented C# toolchain command, that is +a regression of #512/#522, not policy.** The corrected sites carry explicit "do not restore this" +prose for exactly that reason. + +--- + +Historically `CLAUDE.md` documented the nullable stage as `msbuild TaskMaster.sln /t:Build ... /p:Nullable=enable /p:TreatWarningsAsErrors=true`. The gate that actually governs merge, in `.github/workflows/ci.yml` ("Build with nullable warnings -treated as errors"), is: +treated as errors"), is (and always was): ``` msbuild TaskMaster.sln /t:Rebuild /m /p:Configuration=Debug "/p:Platform=Any CPU" /p:TreatWarningsAsErrors=true @@ -32,6 +46,13 @@ applied returned EXIT 0, zero errors, zero CS8603. The blocker was an artifact o unenforced flag. The sibling `SB` property already returns `null` from a non-nullable declared return type, so the pattern was pre-existing anyway. +**Measured figure for the follow-on burn-down (2026-08-10, #492).** Under an explicit +`/p:Nullable=enable` probe the corrected `/t:Rebuild` gate reports **195 errors, all in +`UtilitiesCS.csproj`** (CS8766 x130, CS8618 x23, CS8625 x12, CS8600 x9, CS8601 x8, CS8604 x7, +CS8602 x3, CS8603 x2, CS8714 x1). That is a **lower bound**: the build aborted after 22 of 73 +`CoreCompile` executions, so `UtilitiesCS`'s dependents never compiled. Size that epic by measuring +the solution-wide total first, not by trusting 195. + **How to apply:** when a delegated agent reports a nullable failure, do not relay it. Check whether the diagnostic is in a file carrying `#nullable enable`; if not, reproduce `ci.yml`'s command verbatim before accepting a blocker or leaving an AC unchecked. Do not "fix" a forced-flag-only