From ba058c6c97bafb4412d9a720ec754442e524b25a Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 19 Sep 2026 09:13:41 +0700 Subject: [PATCH 1/5] fix(ci): allow R10 post-merge convergence authority --- scripts/verify-source-clean.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/verify-source-clean.ps1 b/scripts/verify-source-clean.ps1 index 46a1e406a..f55b84a92 100644 --- a/scripts/verify-source-clean.ps1 +++ b/scripts/verify-source-clean.ps1 @@ -62,6 +62,7 @@ $ApprovedConvergenceIdentifierPaths = [System.Collections.Generic.HashSet[string @( ".github/workflows/iedscout-convergence-guard.yml", ".github/workflows/scl-interoperability-r7.yml", + ".github/workflows/smart-discovery-post-merge-production.yml", "docs/IEDSCOUT_CONVERGENCE.md", "evidence/iedscout-convergence-target.json", "tests/ARSAS.Tests/CanonicalLiveSclExportRegressionTests.cs" From 01bb03531dbdce97070f48c192012c635d6a046c Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 19 Sep 2026 09:13:43 +0700 Subject: [PATCH 2/5] fix(ci): place R10 engine beside ARSAS workspace --- .../smart-discovery-post-merge-production.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/smart-discovery-post-merge-production.yml b/.github/workflows/smart-discovery-post-merge-production.yml index c95ddfa1f..b74229e10 100644 --- a/.github/workflows/smart-discovery-post-merge-production.yml +++ b/.github/workflows/smart-discovery-post-merge-production.yml @@ -52,10 +52,10 @@ jobs: - name: Checkout exact merged ARIEC61850 authority shell: powershell run: | - git clone --quiet --filter=blob:none --no-checkout "https://github.com/$env:ENGINE_REPOSITORY.git" ARIEC61850 - git -C .\ARIEC61850 fetch --quiet --depth 1 origin $env:ENGINE_COMMIT - git -C .\ARIEC61850 checkout --quiet --detach $env:ENGINE_COMMIT - $actual = (git -C .\ARIEC61850 rev-parse HEAD).Trim().ToLowerInvariant() + git clone --quiet --filter=blob:none --no-checkout "https://github.com/$env:ENGINE_REPOSITORY.git" ..\ARIEC61850 + git -C ..\ARIEC61850 fetch --quiet --depth 1 origin $env:ENGINE_COMMIT + git -C ..\ARIEC61850 checkout --quiet --detach $env:ENGINE_COMMIT + $actual = (git -C ..\ARIEC61850 rev-parse HEAD).Trim().ToLowerInvariant() if ($actual -ne $env:ENGINE_COMMIT) { throw "R10 engine authority mismatch. Expected $env:ENGINE_COMMIT, got $actual." } @@ -70,9 +70,9 @@ jobs: run: | # Keep the exact R10 physical-tested engine commit. Post-merge acceptance # validates the immutable commit identity plus full restore/build/test. - dotnet restore .\ARIEC61850\ARIEC61850.sln - dotnet build .\ARIEC61850\ARIEC61850.sln -c Release --no-restore - dotnet test .\ARIEC61850\tests\AR.Iec61850.Tests\AR.Iec61850.Tests.csproj -c Release --no-build --no-restore + dotnet restore ..\ARIEC61850\ARIEC61850.sln + dotnet build ..\ARIEC61850\ARIEC61850.sln -c Release --no-restore + dotnet test ..\ARIEC61850\tests\AR.Iec61850.Tests\AR.Iec61850.Tests.csproj -c Release --no-build --no-restore - name: Build and test ARSAS main shell: powershell From daa3d575293a9eb7eb664491304e0465216b7e55 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 19 Sep 2026 09:19:07 +0700 Subject: [PATCH 3/5] fix(ci): recognize R10 mainline readiness authority --- scripts/verify-source-clean.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/verify-source-clean.ps1 b/scripts/verify-source-clean.ps1 index f55b84a92..5e367ab17 100644 --- a/scripts/verify-source-clean.ps1 +++ b/scripts/verify-source-clean.ps1 @@ -63,6 +63,7 @@ $ApprovedConvergenceIdentifierPaths = [System.Collections.Generic.HashSet[string ".github/workflows/iedscout-convergence-guard.yml", ".github/workflows/scl-interoperability-r7.yml", ".github/workflows/smart-discovery-post-merge-production.yml", + ".github/workflows/smart-discovery-mainline-readiness.yml", "docs/IEDSCOUT_CONVERGENCE.md", "evidence/iedscout-convergence-target.json", "tests/ARSAS.Tests/CanonicalLiveSclExportRegressionTests.cs" From 050ef298e170c2ed0bbfe0580e89a9ca948e213c Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 19 Sep 2026 09:19:10 +0700 Subject: [PATCH 4/5] fix(ci): move mainline readiness authority to R10 --- .../smart-discovery-mainline-readiness.yml | 114 +++++++++++------- 1 file changed, 69 insertions(+), 45 deletions(-) diff --git a/.github/workflows/smart-discovery-mainline-readiness.yml b/.github/workflows/smart-discovery-mainline-readiness.yml index 79bdc79bb..610306e28 100644 --- a/.github/workflows/smart-discovery-mainline-readiness.yml +++ b/.github/workflows/smart-discovery-mainline-readiness.yml @@ -6,7 +6,7 @@ on: jobs: mainline-readiness: - name: Require physical promotion before mainline review + name: Require R10 physical authority before mainline review runs-on: windows-latest steps: - name: Checkout ARSAS full history @@ -16,22 +16,59 @@ jobs: git clone --quiet --branch $ref "https://github.com/$env:GITHUB_REPOSITORY.git" ArIED61850Tester $arsasHead = (git -C .\ArIED61850Tester rev-parse HEAD).Trim().ToLowerInvariant() "ARSAS_HEAD=$arsasHead" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - Write-Host "P0-5g mainline ARSAS head: $arsasHead" + Write-Host "R10 mainline ARSAS head: $arsasHead" - - name: Checkout ARIEC61850 PR 134 head + - name: Verify R10 physical convergence authority shell: powershell run: | - git clone --quiet --branch perf/smart-ied-discovery https://github.com/masarray/ARIEC61850.git ARIEC61850 - $engineHead = (git -C .\ARIEC61850 rev-parse HEAD).Trim().ToLowerInvariant() - "ENGINE_HEAD=$engineHead" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append - Write-Host "P0-5g mainline engine head: $engineHead" + $root = '.\ArIED61850Tester' + $target = Get-Content "$root\evidence\iedscout-convergence-target.json" -Raw | ConvertFrom-Json + $lock = Get-Content "$root\engines\ARIEC61850.lock.json" -Raw | ConvertFrom-Json + + if ($target.status -ne 'physical-retest-passed-merge-ready' -or + -not [bool]$target.promotion.physicalRetestPassed -or + [bool]$target.promotion.physicalRetestRequired -or + -not [bool]$target.promotion.mergeAllowedAfterPhysicalRetest) { + throw 'R10 physical convergence authority is not in the accepted mainline state.' + } + + $r10 = $target.physicalEvidence.arsasR10 + foreach ($edition in @($r10.reuseEdition2, $r10.reuseEdition1)) { + if ([int]$edition.failedReads -ne 0 -or + [int]$edition.projectionErrors -ne 0 -or + [int]$edition.cacheLoss -ne 0 -or + [int]$edition.reportBackedRuntimePoints -ne 58 -or + [int]$edition.unresolvedRuntimePoints -ne 0 -or + -not [bool]$edition.actualInformationReportObserved) { + throw 'R10 trusted-SCL reuse proof regressed.' + } + } + + if ($lock.commit -ne $target.activeStack.engineModelAndScl.mainMerge -or + $lock.commit -ne $r10.testedArtifact.engineMergedMain) { + throw 'ARSAS engine lock no longer matches the R10 merged engine authority.' + } + + "ENGINE_REPOSITORY=$($lock.repository)" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + "ENGINE_COMMIT=$($lock.commit)" | Out-File $env:GITHUB_ENV -Encoding utf8 -Append + + - name: Checkout exact merged ARIEC61850 authority + shell: powershell + run: | + git clone --quiet --filter=blob:none --no-checkout "https://github.com/$env:ENGINE_REPOSITORY.git" ARIEC61850 + git -C .\ARIEC61850 fetch --quiet --depth 1 origin $env:ENGINE_COMMIT + git -C .\ARIEC61850 checkout --quiet --detach $env:ENGINE_COMMIT + $actual = (git -C .\ARIEC61850 rev-parse HEAD).Trim().ToLowerInvariant() + if ($actual -ne $env:ENGINE_COMMIT) { + throw "R10 engine authority mismatch. Expected $env:ENGINE_COMMIT, got $actual." + } - name: Setup .NET 8 uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - - name: Validate exact engine head + - name: Validate exact merged engine authority shell: powershell run: | .\ARIEC61850\scripts\verify-source-clean.ps1 @@ -39,51 +76,38 @@ jobs: dotnet build .\ARIEC61850\ARIEC61850.sln -c Release --no-restore dotnet test .\ARIEC61850\tests\AR.Iec61850.Tests\AR.Iec61850.Tests.csproj -c Release --no-build --no-restore - - name: Require READY_FOR_REVIEW promotion state - shell: powershell - run: | - $root = '.\ArIED61850Tester' - $physical = "$root\evidence\smart-discovery-repeat-run.authority.json" - $promotion = "$root\evidence\smart-discovery-production-promotion-authority.json" - $physicalArg = if (Test-Path $physical -PathType Leaf) { $physical } else { '' } - $promotionArg = if (Test-Path $promotion -PathType Leaf) { $promotion } else { '' } - $output = "$root\TestResults\P0-5G-mainline-readiness.json" - New-Item -ItemType Directory -Force "$root\TestResults" | Out-Null - - & "$root\scripts\verify-smart-discovery-production-readiness.ps1" ` - -TargetPath "$root\evidence\smart-discovery-production-promotion-target.json" ` - -EngineLockPath "$root\engines\ARIEC61850.lock.json" ` - -PromotionPropsPath "$root\evidence\SmartDiscoveryPromotion.props" ` - -ArsasRepositoryPath $root ` - -EngineRepositoryPath '.\ARIEC61850' ` - -ArsasHeadCommit $env:ARSAS_HEAD ` - -EngineHeadCommit $env:ENGINE_HEAD ` - -EngineHeadCiConclusion success ` - -PhysicalAuthorityPath $physicalArg ` - -PromotionAuthorityPath $promotionArg ` - -OutputJson $output ` - -NoFailExit - - $result = Get-Content $output -Raw | ConvertFrom-Json - if ($result.Verdict -ne 'READY_FOR_REVIEW') { - throw "MAINLINE BLOCKED: readiness verdict is '$($result.Verdict)': $(@($result.Blockers) -join '; ')" - } - if (-not [bool]$result.ProductionSwitchEnabled) { - throw 'MAINLINE BLOCKED: production smart-discovery switch is not enabled.' - } - - - name: Build and test promoted ARSAS path + - name: Build and test R10 ARSAS path shell: powershell run: | dotnet restore .\ArIED61850Tester\ArIED61850Tester.sln dotnet build .\ArIED61850Tester\ArIED61850Tester.sln -c Release --no-restore dotnet test .\ArIED61850Tester\tests\ARSAS.Tests\ARSAS.Tests.csproj -c Release --no-build --no-restore - - name: Upload P0-5g mainline evidence + - name: Write R10 mainline evidence + if: always() + shell: powershell + run: | + $root = '.\ArIED61850Tester' + New-Item -ItemType Directory -Force "$root\TestResults" | Out-Null + $target = Get-Content "$root\evidence\iedscout-convergence-target.json" -Raw | ConvertFrom-Json + [ordered]@{ + schemaVersion = 1 + sourceCommit = $env:ARSAS_HEAD + engineCommit = $env:ENGINE_COMMIT + convergenceStatus = $target.status + physicalRetestPassed = [bool]$target.promotion.physicalRetestPassed + ed2ProjectionErrors = [int]$target.physicalEvidence.arsasR10.reuseEdition2.projectionErrors + ed2CacheLoss = [int]$target.physicalEvidence.arsasR10.reuseEdition2.cacheLoss + ed1ProjectionErrors = [int]$target.physicalEvidence.arsasR10.reuseEdition1.projectionErrors + ed1CacheLoss = [int]$target.physicalEvidence.arsasR10.reuseEdition1.cacheLoss + reportBackedRuntimePoints = 58 + } | ConvertTo-Json -Depth 5 | Set-Content "$root\TestResults\R10-mainline-readiness.json" + + - name: Upload R10 mainline evidence if: always() uses: actions/upload-artifact@v4 with: - name: ARSAS-p0-5g-mainline-readiness - path: ArIED61850Tester\TestResults\P0-5G-mainline-readiness.json + name: ARSAS-r10-mainline-readiness + path: ArIED61850Tester\TestResults\R10-mainline-readiness.json if-no-files-found: error retention-days: 14 From 19d86cb5506a1b6c0553c20855b9a7a2b7b3f476 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Sat, 19 Sep 2026 09:21:49 +0700 Subject: [PATCH 5/5] test(ci): lock R10 mainline readiness contract --- ...coveryProductionPromotionRegressionTests.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/ARSAS.Tests/SmartDiscoveryProductionPromotionRegressionTests.cs b/tests/ARSAS.Tests/SmartDiscoveryProductionPromotionRegressionTests.cs index 9f75a51a3..afc8d4c9a 100644 --- a/tests/ARSAS.Tests/SmartDiscoveryProductionPromotionRegressionTests.cs +++ b/tests/ARSAS.Tests/SmartDiscoveryProductionPromotionRegressionTests.cs @@ -64,16 +64,22 @@ public void P05g_ReadinessAllowsMissingPromotionBindingsWhileFailClosed() } [Fact] - public void P05g_DedicatedMainlineGateRequiresReadyForReviewAndRealAuthorities() + public void R10_DedicatedMainlineGateRequiresPhysicalAuthorityAndExactMergedEngine() { var workflow = File.ReadAllText(FindRepoFile(".github/workflows/smart-discovery-mainline-readiness.yml")); Assert.Contains("Smart Discovery Mainline Readiness", workflow, StringComparison.Ordinal); - Assert.Contains("smart-discovery-repeat-run.authority.json", workflow, StringComparison.Ordinal); - Assert.Contains("smart-discovery-production-promotion-authority.json", workflow, StringComparison.Ordinal); - Assert.Contains("READY_FOR_REVIEW", workflow, StringComparison.Ordinal); - Assert.Contains("ProductionSwitchEnabled", workflow, StringComparison.Ordinal); - Assert.Contains("-NoFailExit", workflow, StringComparison.Ordinal); + Assert.Contains("Verify R10 physical convergence authority", workflow, StringComparison.Ordinal); + Assert.Contains("physical-retest-passed-merge-ready", workflow, StringComparison.Ordinal); + Assert.Contains("projectionErrors", workflow, StringComparison.Ordinal); + Assert.Contains("cacheLoss", workflow, StringComparison.Ordinal); + Assert.Contains("reportBackedRuntimePoints", workflow, StringComparison.Ordinal); + Assert.Contains("actualInformationReportObserved", workflow, StringComparison.Ordinal); + Assert.Contains("engineMergedMain", workflow, StringComparison.Ordinal); + Assert.Contains("Validate exact merged engine authority", workflow, StringComparison.Ordinal); + Assert.Contains("Build and test R10 ARSAS path", workflow, StringComparison.Ordinal); + Assert.DoesNotContain("smart-discovery-repeat-run.authority.json", workflow, StringComparison.Ordinal); + Assert.DoesNotContain("READY_FOR_REVIEW", workflow, StringComparison.Ordinal); Assert.Contains("if-no-files-found: error", workflow, StringComparison.Ordinal); }