Skip to content

Commit c8e948a

Browse files
committed
Qualify complete analyzer coverage independently in Linux CI
Reuse the frozen native Aspire collector,54-source inventory and unchanged80/70/90 thresholds. Require the original complete passing TRX and retain its source/counters/hash receipt alongside raw coverage and source manifest. Governance, YAML/actionlint workflow validation, native Prepare and the real original388-test receipt check passed; full actionlint retains its unrelated existing SC2129 style warning. Actual new-source Linux coverage and complete runtime gates remain open.
1 parent a1309f6 commit c8e948a

4 files changed

Lines changed: 131 additions & 3 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,53 @@ jobs:
4141
run: |
4242
dotnet build src/KeyLoad.AppHost --no-restore --configuration Release
4343
dotnet build tests/KeyLoad.Analyzers.Tests --no-restore --configuration Release
44+
- name: Prepare source-bound analyzer coverage
45+
shell: pwsh
46+
run: |
47+
$root = $env:GITHUB_WORKSPACE
48+
$evidence = Join-Path $root 'artifacts/code-quality/analyzer-coverage'
49+
New-Item -ItemType Directory -Path $evidence -Force | Out-Null
50+
Copy-Item scripts/Features/CodeQuality/site-analyzer-coverage.settings.xml (Join-Path $evidence 'coverage.config.xml')
51+
& pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/site-analyzer-coverage.ps1 `
52+
-Mode Prepare -Repository $root `
53+
-Contract (Join-Path $root 'scripts/Features/CodeQuality/site-analyzer-coverage.contract.json') `
54+
-EvidenceRoot $evidence
55+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
4456
- name: Run analyzer tests
45-
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=analyzers --KeyLoadTests:ReportTrx=true
57+
id: analyzers
58+
run: |
59+
dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=analyzers --KeyLoadTests:ResultsDirectory=TestResults/analyzers --KeyLoadTests:ReportTrx=true "--KeyLoadTests:CoverageSettings=$GITHUB_WORKSPACE/artifacts/code-quality/analyzer-coverage/coverage.config.xml" "--KeyLoadTests:CoverageOutput=$GITHUB_WORKSPACE/artifacts/code-quality/analyzer-coverage/coverage.cobertura.xml"
60+
- name: Verify every analyzer test passed
61+
if: ${{ !cancelled() && steps.analyzers.outcome != 'skipped' }}
62+
shell: pwsh
63+
run: |
64+
$root = $env:GITHUB_WORKSPACE
65+
$files = @(Get-ChildItem -LiteralPath (Join-Path $root 'TestResults/analyzers') -Filter '*.trx' -File)
66+
if ($files.Count -ne 1) { throw 'Expected exactly one analyzer TRX receipt' }
67+
[xml]$document = Get-Content -LiteralPath $files[0].FullName -Raw
68+
$counts = $document.TestRun.ResultSummary.Counters
69+
if ([int]$counts.total -le 0 -or [int]$counts.executed -ne [int]$counts.total -or
70+
[int]$counts.passed -ne [int]$counts.total) {
71+
throw 'Incomplete or failing analyzer qualification; skipped tests cannot pass'
72+
}
73+
[ordered]@{
74+
sourceRevision = $env:GITHUB_SHA
75+
total = [int]$counts.total
76+
executed = [int]$counts.executed
77+
passed = [int]$counts.passed
78+
sha256 = (Get-FileHash -LiteralPath $files[0].FullName -Algorithm SHA256).Hash.ToLowerInvariant()
79+
} | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $root 'artifacts/code-quality/analyzer-coverage/test-receipt.json') -Encoding utf8NoBOM
80+
- name: Verify source-bound analyzer coverage
81+
if: ${{ !cancelled() && steps.analyzers.outcome != 'skipped' }}
82+
shell: pwsh
83+
run: |
84+
$root = $env:GITHUB_WORKSPACE
85+
$evidence = Join-Path $root 'artifacts/code-quality/analyzer-coverage'
86+
& pwsh -NoLogo -NoProfile -File scripts/Features/CodeQuality/site-analyzer-coverage.ps1 `
87+
-Mode Verify -Repository $root `
88+
-Contract (Join-Path $root 'scripts/Features/CodeQuality/site-analyzer-coverage.contract.json') `
89+
-EvidenceRoot $evidence -CoverageReport (Join-Path $evidence 'coverage.cobertura.xml')
90+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
4691
- name: Save analyzer test results
4792
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
4893
if: always()

‎docs/ADR/ADR-113-centralized-runtime-options.md‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,31 @@ dependency replacement is introduced. The focused native118/118 runtime run,
595595
full Release build are retained as local development evidence. Full native
596596
unit/scalar/recovery/RF3, source-bound functional coverage and delivered Linux
597597
acceptance remain mandatory and open.
598+
599+
### Independent delivered-source analyzer coverage join
600+
601+
TASK-CQ-GENERAL-CI-001 maps REQ-CQ-006/012/013 and AC-CQ-009/033..038 to the
602+
existing Linux `analyzer-rules` job in `.github/workflows/ci.yml`. Prepare the
603+
unchanged 54-source analyzer inventory and exact settings copy after the native
604+
Release build, run the complete analyzer suite through the existing Aspire
605+
entry with the native Cobertura collector, then verify the original report
606+
against its prepared source hashes. Preserve the existing 80 percent module
607+
line, 70 percent module branch and 90 percent critical pipeline thresholds.
608+
609+
The ordered implementation is this contract, the workflow preparation/collection/
610+
verification join, static governance review, exact-source Linux execution and
611+
original artifact review. Root owns workflow/docs/status integration; a read-only
612+
reviewer checks native caller arguments, source identity and failure paths.
613+
Collection failure remains a failed test step; verification also runs after that
614+
failure and writes its original failure evidence. Always retain reports, settings,
615+
manifest, raw coverage and derived gate evidence in the existing analyzer artifact.
616+
Require exactly one original analyzer TRX with a positive total, all tests
617+
executed and all tests passed; retain its counters, source SHA and original file
618+
hash in a derived receipt. Skipped tests cannot qualify this full-suite gate.
619+
620+
This executes the same gate independently of benchmark producer selection while
621+
retaining the existing website coverage gate. No dependency, product contract,
622+
storage migration, threshold, source inventory or required runtime suite changes.
623+
Rollback restores this workflow join together with its documentation. Only a
624+
completed successful original collector report and source-bound verification
625+
qualify coverage; unit/scalar/recovery/RF3 acceptance remains separately required.

‎docs/Features/CodeQuality.md‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,3 +1353,21 @@ RF3, recovery and every existing no-decrease/80/70/90 gate remain mandatory.
13531353
## Controlled time ownership, 2026-10-06
13541354

13551355
[ResourceExecution TimeProvider](ResourceExecution/TimeProvider.md) and [ADR-115](../ADR/ADR-115-time-provider.md) extend KLD0022 to native Stopwatch timing and Environment.TickCount/TickCount64, with exact-span real-compiler positive/negative/generated fixtures. Explicit provider/default composition boundaries remain allowed. Native provider timers and real clock-controlled engine/replica workflows are required; source migration alone is not qualification.
1356+
1357+
### Independent Linux analyzer coverage
1358+
1359+
TASK-CQ-GENERAL-CI-001 under [ADR-113](../ADR/ADR-113-centralized-runtime-options.md)
1360+
maps REQ-CQ-006/012/013 and AC-CQ-009/033..038 to the existing Linux analyzer job.
1361+
After its Release build, prepare the frozen source/settings manifest, collect the
1362+
complete native Aspire analyzer suite and verify the original Cobertura integers
1363+
against the captured source SHA. Retain all 54 sources, 45 executable files,
1364+
9 declarations and unchanged 80/70/90 module/critical thresholds. Missing, stale,
1365+
empty, malformed or insufficient native evidence fails; diagnostic suite failures
1366+
remain failures even if coverage thresholds pass. Verification runs after a failed
1367+
collection to preserve failure evidence, and the existing artifact upload retains
1368+
original reports, settings, manifest, raw coverage and gate report. This additional
1369+
CI join executes independently of benchmark producer selection and preserves the
1370+
website gate and every unit/scalar/recovery/RF3 qualification requirement.
1371+
Require exactly one original analyzer TRX, a positive total, executed equal to
1372+
total and passed equal to total. Preserve those counters, source SHA and original
1373+
TRX hash in the retained receipt; missing, skipped or failed tests fail the job.

‎docs/implementation/status.json‎

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4909,7 +4909,7 @@
49094909
"feature": "docs/Features/CodeQuality.md",
49104910
"decision": "docs/ADR/ADR-113-centralized-runtime-options.md",
49114911
"sourceStage": "runtime_options_literals_locks_phase_health_semantics_native_test_admission_and_manifest_input_fix_complete_runtime_gates_in_progress",
4912-
"canonicalBuildPassed": false,
4912+
"canonicalBuildPassed": true,
49134913
"runtimeQualified": false,
49144914
"fullTaskComplete": false,
49154915
"remaining": [
@@ -5359,8 +5359,45 @@
53595359
"compiledReceipt": "keyload-general-options-compiled-inventory-audit-v38.log:19projects_3190inputs_mismatches_empty",
53605360
"nativeRegression": "unit_v34_AcScale016CancellationStopsAndJoinsTheOwnedNativeProbe_passed_5296.189ms_in_original_4133test_report",
53615361
"qualification": "prior successful local full-build snapshot and genuine child cancellation case; complete suite originally failed72other_tests; unrelated subsequent CLI_telemetry_coverage_source_changes_require_fresh_build_and_reports"
5362+
},
5363+
"deliveredLinuxA130": {
5364+
"headSha": "a1309f6b6115790d012977aff3eb7db26ab22146",
5365+
"run": "https://github.com/managedcode/KeyLoad/actions/runs/37449460526",
5366+
"canonicalBuild": "passed_in_main_verify_and_RF3_jobs",
5367+
"repositoryRules": "passed",
5368+
"analyzerJob": "passed_original_report_review_pending",
5369+
"rf3Prerequisite": "failed_native_Release_DLL_PDB_source_binding_KeyLoad_Abstractions_missingSourceCount120_before_topology_and_tests",
5370+
"rf3Job": "https://github.com/managedcode/KeyLoad/actions/runs/37449460526/job/112222193881",
5371+
"mainVerify": "format_step_in_progress_at_observation",
5372+
"qualification": "immutable Linux source; successful builds are not complete runtime or source-bound coverage qualification"
5373+
},
5374+
"independentAnalyzerCoverageCiJoin": {
5375+
"task": "TASK-CQ-GENERAL-CI-001",
5376+
"scope": ".github/workflows/ci.yml:analyzer-rules",
5377+
"nativeCaller": "existing_full_Aspire_analyzers_with_original_TRX_and_Cobertura",
5378+
"inventory": {
5379+
"sources": 54,
5380+
"executable": 45,
5381+
"declarationOnly": 9,
5382+
"configuration": 8
5383+
},
5384+
"thresholds": {
5385+
"moduleLinePercent": 80,
5386+
"moduleBranchPercent": 70,
5387+
"criticalPipelineLinePercent": 90
5388+
},
5389+
"staticChecks": {
5390+
"governance": "passed",
5391+
"yamlParse": "passed",
5392+
"actionlintWorkflowValidation": "passed",
5393+
"fullActionlint": "one_preexisting_SC2129_shellcheck_style_finding_in_unchanged_RF3_environment_export_block_confirmed_same_on_HEAD"
5394+
},
5395+
"nativePrepare": "passed_original_54source_8configuration_manifest_with_frozen_settings_hash",
5396+
"originalTrxReceiptCheck": "passed_against_retained_original_Linux702_receipt_total388_executed388_passed388_SHA256b464ebaedff25a6e59c2bb3db74864afa01ecee858a450422339811b67261800",
5397+
"review": "read_only_reviewer_verified_native_settings_source_SHA_binding_failure_paths_original_upload_and_no_skip_receipt_join",
5398+
"qualification": "new_workflow_requires_actual_exact_source_Linux_collection_and_80_70_90_verification_no_coverage_pass_claim"
53625399
}
53635400
},
5364-
"verificationStage": "Linux702_repository_rules_and388analyzers_pass_build_blocked_by_seven_native_cancellation_helper_diagnostics_reviewed_exact_byte_repairs_joined_remaining_full_runtime_coverage_gates_open"
5401+
"verificationStage": "Linuxa130_full_Release_builds_pass_RF3_stopped_at_native_PDB_source_binding_independent_complete_analyzer_CI_coverage_join_reviewed_and_static_checked_remaining_exact_source_full_runtime_and_numeric_coverage_gates_open"
53655402
}
53665403
}

0 commit comments

Comments
 (0)