Commit test-evidence projections instead of raw documents, and remove identity leaks from the vscode MSTest tooling - #881
Merged
drmoisan merged 15 commits intoSep 13, 2026
Conversation
…ion and identity leak tooling
…jection-convention-and-identity-leak-tooling-873
…spec footprint Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…file Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nd conditional discard Phase 3 of the atomic plan. Get-DotnetCoverageArgumentList and Invoke-DotnetCoverageCollection gain a mandatory results directory and log file name; the builder appends the results-directory switch and the trx logger switch to the inner test-console segment, after the argument separator, leaving the existing /Settings:, /InIsolation and /TestCaseFilter: elements unchanged in content and relative order. Invoke-MSTestWithCoverageMain dot-sources the summary part file explicitly, builds the JaCoCo projection from the post-processed content, writes it beside the coverage output, runs the reconciliation assertion, writes the test-result summary beside the test-result document, and only then applies the conditional discard. A missing, unreadable or unparseable test-result document is a non-fatal warning that suppresses both the summary write and the discard. The two test files the signature change breaks are repaired in this same phase so no gate runs a test path this change broke. The shared call-site file converts ten coverage-family call sites to splatting from four argument sets, so it absorbs two extra arguments per site and measures 491 lines against the 500-line ceiling with all 28 of its tests intact. Toolchain: PoshQC format ok, analyzer diagnostic set unchanged at 16 with no entry for any file this phase touched, whole-folder Pester 128 passed 0 failed 0 skipped. AC4, AC5 and AC14 checked off. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d trx summary (#873 Phase 4) Get-VsTestArgumentList gains two mandatory parameters, ResultsDirectory and LogFileName, and appends a results-directory switch and a trx logger switch carrying the explicit log file name, so the test-result document lands at a path a later step can predict and read. Invoke-MSTestMain defaults the results directory to coverage\test-results and the log file name to mstest-run.trx, resolves both against the repository root, dot-sources the summary part file, and after the existing exit-code check writes the run summary beside the document and discards the raw document. A missing, unreadable, unparseable or result-summary-free document is reported as a non-fatal warning that suppresses both the write and the discard. The four plain-builder call sites in the shared argument-builder test file are converted to splatting from two hashtables, which reclaims the lines the two added arguments would otherwise have cost and keeps the file under the 500-line ceiling. The main test file's exact-array assertion is widened to six elements. Toolchain: poshqc format, analyze and test, all over scripts/vscode and tests/scripts/vscode. The loop restarted once: the first analyze pass reported a third PSAvoidUsingWriteHost on the entry point, introduced by this phase, which was changed to Write-Output. Final pass: format ok, analyzer 16 diagnostics matching the Phase 0 baseline set tuple for tuple, Pester 131 passed 0 failed 0 skipped over the whole test folder. Acceptance criteria checked off: AC12, AC13. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…er leaks (#873 Phase 5) The project file's publish destination now carries the repository-relative value the sibling project file already uses, replacing an absolute user-profile path. The Power Query additional-symbols setting now resolves through the editor workspace-folder variable instead of an absolute path into another checkout. Both edits are paired with a parse check, because an absence count alone would report success for an edit that broke the markup. CLAUDE.md gains a Committed Test Evidence Format section naming the three permitted projections and prohibiting the two raw documents, and both test-console toolchain steps now name the explicit results-directory switch and the explicit log-file-name form. Both steps were amended, because amending one would leave the sibling contradicting it. The rule lives here rather than in the push-down-owned conventions documents, which are reverted on the next push-down. Five agent-memory files had a leaked account or host token substituted for an angle-bracket placeholder. The sixth was rewritten rather than substituted: its sentence used the token twice on one line to contrast a case-sensitive search against a case-insensitive one, and one placeholder in both positions would have destroyed the contrast. The shared hygiene rule file gains two numbered obligations that its prior text recorded only as incidents. Every after-state observation is recorded as counts only, with no token value in any artifact, which is the rule this delivery exists to enforce. All five memory files, the project file and the settings file return zero for both run-time derived tokens. No PowerShell file changed, so no toolchain gate applies. Acceptance criteria checked off: AC16, AC17, AC18, AC19. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n on a pre-existing defect (#873 Phase 6, partial) P6-T1 passes. The coverage entry point run in discovery-only mode reports nine built Debug test assemblies, and an independent re-derivation of the same discovery predicate enumerates the same nine repository-relative. The bare integer is greater than zero, so the Phase 0 rebuild contingency did not apply. P6-T2 is BLOCKED and its checkbox stays unchecked. The run executed 7221 tests in 42.89 seconds; 7218 passed and three failed. All three belong to QuickFiler.Controllers.Tests.QfcInitEmailQueueZeroBatchTests in the QuickFiler.Test assembly, and each throws a TypeInitializationException for Deedle.Reflection whose innermost cause is a FileNotFoundException for netstandard 2.1.0.0. The throw site is the test class helper calling Deedle.Reflection.convertRecordSequence, and the sub-millisecond elapsed times identify it as an assembly-load failure at static-initialiser time rather than an assertion failure. The entry point throws on a nonzero test-console exit code before it reaches the post-processing, the projection write and the summary write, so the run left the raw Cobertura document and the TRX in the ignored coverage tree but produced neither the projection nor the test-result summary this task observes. The reconciliation integers are therefore not derivable. The console banner records class-level parallelisation with 24 workers for the QuickFiler.Test assembly, which is supplied by the off-root CLI runsettings the argument builder appends as the inner /Settings: switch. The continuous integration workflow passes no settings file, so the defect is invisible there. Neither the runsettings file nor the /Settings: switch was altered: both sit outside this delivery Write Set, and the plan Phase 6 flakiness attribution rule requires recording and reporting a pre-existing failure rather than suppressing it by editing a test outside the Write Set. No file outside this feature folder changed. No raw coverage or test-result document was added to version control. P6-T3 through P6-T5 stay unchecked, AC23 stays unchecked, and Phase 7 was not begun. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…check-off (#873 Phase 7) Runs the full toolchain in order over the delivery. PowerShell format rewrote nothing; the analyzer reports the same 16 diagnostics as the Phase 0 baseline with none absent from it; Pester reports 133 passed, 0 failed, 0 skipped over the test folder against a baseline of 103 passed. The C# format check exits 0 over 1626 files, and the analyzer and nullable rebuilds each exit 0 with 0 warnings and 0 errors, matching their Phase 0 baselines. New-code coverage is 92.86 percent line for Invoke-MSTest.TrxSummary.ps1 and 92.50 percent for Invoke-MSTestWithCoverage.Projection.ps1, both above the 90 floor. The first measurement failed at 82.50 percent for the projection part file; two tests were added to its test file, which is inside the declared Write Set, covering the valid-total reconciliation throw and the no-parent guard clause, and the toolchain loop was restarted from the format step with every preceding gate re-run and passing. Both the failing measurement and the remediation are recorded rather than replaced. Every PowerShell file is at most 500 lines, the largest being 498, and the helpers file grew by exactly one line against its post-format baseline. The changed-file inventory records 100 paths, one project file, and an empty executor agent-memory carve-out. Checks off AC15, AC20, AC21 and AC22, taking the total to 22 of 23. AC23 stays unchecked and is recorded as OUTSTANDING in the acceptance status summary, because Phase 6 tasks P6-T2 through P6-T5 have not run. A disclosure artifact records that this Phase 7 pass was taken with those tasks outstanding, names the tracked paths Phase 6 would modify, and records that none of them is a file any Phase 7 gate measures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Phase 7) Appends the delivery commit identifier, the eighteen-file summary, the empty POST_COMMIT_PORCELAIN record with EXIT_CODE 0, and the executor agent-memory disposition, which is empty so neither of that step's two commands was run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This task's own check-off is a modification of a tracked file, so it is committed separately and the clean-tree observation is taken after it rather than before it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ion-and-identity-leak-tooling-873 for Phase 6 Brings in item 880 (issue 877) QuickFiler.Test AssemblyResolve self-sufficiency and item 839 QfcHomeController.Init ordering fix. The 877 change is the remediation for the pre-existing netstandard 2.1 Deedle assembly-load failure that aborted the first P6-T2 attempt. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e 6) Runs P6-T2 through P6-T5 after merging origin/main a5622ab, which carried the issue 877 AssemblyResolve fix that repaired the netstandard 2.1.0.0 bind failure halting the first P6-T2 attempt. No file in this delivery's Write Set was changed to make the run pass. P6-T2 default-output run: 7222 tests, 7222 passed, 0 failed. Raw document retained, projection written beside it, reconciliation exact at 56066 covered and 65416 valid lines, test-result summary present. P6-T3 external-output run: 7222 tests, 7222 passed, 0 failed. Raw document discarded, projection and summary retained, which is invariant 4's discard branch. P6-T4 default-name scan: zero matches over both results-directory listings and zero over the 195-path changed-path union. The artifact carries the full post-merge provenance and reconciles the union against the pre-merge P7-T9 inventory of 100: plus 91 inherited from the merge, plus 4 own artifacts authored after P7-T9 ran. Also re-runs the three C# gates against the merged tree, since the merge altered compilation inputs that the pre-merge Phase 7 gates measured. Format, analyzers and nullable all return results identical to their Phase 0 baselines. AC23 is checked off, taking the item to 23 of 23. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Delegated to Agent(feature-review) after the coordinator identified the missing review as a gap in its definition of done rather than in this run's execution. The prior step7_status was the invalid literal not-run, recorded with a rationale rather than a passing value. Verdict PASS on all three artifacts, 0 Blocking and 11 Non-blocking findings, 23 of 23 acceptance criteria independently evaluated and satisfied. Coverage rows: C# 85.71 line / 79.87 branch against the CLAUDE.md floors of 80/75; PowerShell new code 92.86 and 92.50 against the 90 floor. No coverage.xml was created under any artifacts/ path, so the 85 percent hook floor was not activated. Three non-blocking residuals are recorded in the checkpoint for follow-up promotion. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Suggested title
Commit test-evidence projections instead of raw documents, and remove identity leaks from the vscode MSTest tooling
Summary
Assert-JacocoProjectionReconciliationthrows unless the summed packageLINEcounters equal the source document's root covered-lines and valid-lines attributes.CLAUDE.mdgains a section stating the permitted committed test-evidence formats.Why
The maintainer recorded a committed test-evidence convention on #671 on 2026-09-11. Before this change the two entry points committed raw evidence: a raw test-result document carrying the operator account name, the host name and the absolute checkout path across six attributes, and a raw Cobertura document measured in tens of megabytes.
This item implements that convention and removes the identity leaks that sit in configuration. The tooling half of #602 and the configuration leaks tracked under #728 are in scope. The historical sweep of evidence already committed from earlier features is deliberately not in scope, and is discussed under Follow-ups.
CLAUDE.mdis the home for the convention text because the evidence-and-timestamp conventions document and the atomic-plan contract are both push-down owned, so an edit to either would be reverted on the next push-down. The repository-root instruction file is owned here and is loaded into every agent session.What Changed
Core logic
scripts/vscode/Invoke-MSTestWithCoverage.Projection.ps1— new. HoldsConvertTo-JacocoPackageProjection(pure writer),Assert-JacocoProjectionReconciliation(pure assertion) andTest-RawCoverageDocumentRetained(pure predicate). It is a new part file rather than an addition to the helpers file because the helpers file had 29 lines of headroom against the repository's 500-line ceiling.scripts/vscode/Invoke-MSTest.TrxSummary.ps1— new. HoldsGet-TrxRunSummary(pure reader over a test-result document string) andFormat-TrxRunSummary(pure formatter). Dot-sourced by both entry points.scripts/vscode/Invoke-MSTestWithCoverage.ps1— the argument builder gains the results-directory and trx-logger switches on the test-console segment; the main function writes the projection, runs the reconciliation assertion, applies the conditional discard and writes the test-result summary.scripts/vscode/Invoke-MSTest.ps1— the same two switches on the plain path, plus summary write and raw-document discard.scripts/vscode/Invoke-MSTestWithCoverage.Helpers.ps1— one added dot-source line.Tests
Four new Pester files and three existing files repaired. The three repairs are forced by the signature changes rather than chosen: adding two mandatory parameters breaks parameter binding at every existing call site, and array assertions change because the returned arrays gain two elements.
Invoke-MSTest.RunSettings.Tests.ps1was already 496 lines against the 500-line ceiling, so its call sites were converted to splatting, which is net line-reducing.Configuration and documentation
TaskMaster/TaskMaster.csproj— the publish-destination element now carries the repository-relative value the other project file already uses for the same property..vscode/settings.json— the Power Query additional-symbols array element now begins with the editor workspace-folder variable and contains no drive letter.CLAUDE.md— a new## Committed Test Evidence Formatsection, and both test-console toolchain steps now name the explicit results-directory switch and log-file-name form.Architecture / How It Fits Together
The design keeps the new logic pure and testable and leaves the entry points as thin wiring.
The coverage entry point resolves its output path and results directory by joining the supplied parameters against the repository root, runs the collector, post-processes the raw Cobertura document, then calls the projection writer on the post-processed content. The reconciliation assertion runs against the same post-processed source, so a projection that disagrees with its source fails the run rather than being written silently. The summary reader parses the test-result document and the formatter renders it. Only then does the retention predicate decide whether the raw document survives.
The ordering matters and is asserted in-process by a call-order test, because an end-to-end run emits no ordered progress output from which an order could be read.
Verification
Completed
PowerShell gates, recorded in this feature folder's evidence tree:
C# gates, re-run after this branch merged
origin/main:dotnet tool run csharpier check .— exit 0, 1627 files checked.All three match their Phase 0 baselines exactly. The merge altered C# compilation inputs, so these were re-run rather than carried forward from the pre-merge measurement.
End-to-end observation, two full runs of the coverage entry point over every discovered Debug test assembly:
Repository coverage measured during the first run, against the
CLAUDE.mdfloors of 80 percent line and 75 percent branch: first-party line coverage 85.71 percent and branch coverage 79.87 percent. Both clear.Recommended
pwsh -NoProfile -File scripts/vscode/Invoke-MSTestWithCoverage.ps1to reproduce the retention path.Invoke-MSTestWithCoverageMainwith-CoverageOutputand-ResultsDirectorypointed at a directory other than the repository coverage directory, to reproduce the discard path.Backward Compatibility / Migration Notes
ResultsDirectoryparameter is exposed on the main function rather than on the script's top-level parameter block. A caller needing to override it dot-sources the script, which suppresses auto-invocation, and callsInvoke-MSTestWithCoverageMaindirectly.Risks and Mitigations
Review Guide
Suggested order:
scripts/vscode/Invoke-MSTestWithCoverage.Projection.ps1andscripts/vscode/Invoke-MSTest.TrxSummary.ps1— the new pure logic, and the place where correctness is decided.scripts/vscode/Invoke-MSTestWithCoverage.ps1andscripts/vscode/Invoke-MSTest.ps1, particularly the ordering around the discard.Invoke-MSTest.RunSettings.Tests.ps1carries a splatting conversion across many call sites and is the noisiest diff in the change; it is mechanical.Largely mechanical and safe to skim: the feature folder's evidence tree, which is the bulk of the changed-file count.
Note on the diff size: this branch merged
origin/main, so the changed-path union against the original base anchor spans 195 paths, of which 91 are inherited from two items that merged tomainafter the anchor and are not authored here. The P6-T4 evidence artifact reconciles that figure against the earlier 100-path inventory in full.Follow-ups
GitHub Auto-close
The context bundle reports GitHub validation unavailable and lists no verified autoclose issue, so no auto-close bullet is emitted. This work implements issue #873. The issue numbers #602, #646, #662, #671, #718 and #728 appear in the feature documents as background references and as scope boundaries; they are not auto-close targets for this pull request and should remain open.