Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2c9965a
feat: delta closure for truthful routing and portability
Prekzursil Mar 1, 2026
d7cde91
M3 closure: helper bridge ingress, launch+attach, strict tactical modes
Prekzursil Mar 1, 2026
584901a
feat: advance M4 chain intelligence and deep live evidence
Prekzursil Mar 3, 2026
0885670
Refactor runtime and native hotspots for Sonar/Codacy recovery
Prekzursil Mar 3, 2026
e8f8a34
Fix chain resolution classification for unresolved parent dependencies
Prekzursil Mar 3, 2026
4082aa2
Add strict Codecov 100/100 coverage gate infrastructure
Prekzursil Mar 3, 2026
f795cfd
Add strict zero-backlog provider gate scripts and workflows
Prekzursil Mar 3, 2026
739626b
Fix remaining Sonar findings on PR #97
Prekzursil Mar 3, 2026
a8bfcb4
Clear remaining PR #97 Sonar/Codacy findings
Prekzursil Mar 3, 2026
7f16d1b
Split workshop chain logic to satisfy Codacy NLOC
Prekzursil Mar 3, 2026
3cf8961
Align strict-zero workflow job names with required contexts
Prekzursil Mar 3, 2026
a9cf06c
Fix remaining Codacy warning in helper backend tests
Prekzursil Mar 3, 2026
b3833e8
Replace partial split with dedicated chain resolver helper
Prekzursil Mar 3, 2026
65022b0
Stabilize coverage dotnet resolution in mixed shell environments
Prekzursil Mar 3, 2026
43d812f
Harden deep-chain run stability and coverage staging paths
Prekzursil Mar 3, 2026
450b134
Improve live TRX fallback and deep-run artifact stability
Prekzursil Mar 3, 2026
fed0eb8
Trigger strict-zero workflows on branch pushes
Prekzursil Mar 3, 2026
2d47a38
Handle unresolved parent chains as non-execution skips
Prekzursil Mar 3, 2026
e4aff3b
Harden provider gate parsing and DeepScan backlog source
Prekzursil Mar 3, 2026
ebaf5b7
Adjust Applitools provider auth to API query contract
Prekzursil Mar 3, 2026
263e20e
Merge origin/main into PR #97 branch and resolve checker/runtime conf…
Prekzursil Mar 3, 2026
5dc6cf7
Stabilize coverage gate tooling and add helper service tests
Prekzursil Mar 3, 2026
4d52120
Add App and runtime coverage tests for helper and workshop paths
Prekzursil Mar 3, 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
16 changes: 14 additions & 2 deletions .github/workflows/codecov-analytics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,23 @@ jobs:
with:
dotnet-version: '8.0.x'
- name: Run tests with coverage
continue-on-error: true
run: |
mkdir -p coverage
dotnet restore
dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release /p:CollectCoverage=true /p:CoverletOutput=./TestResults/coverage.cobertura.xml /p:CoverletOutputFormat=cobertura
dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release \
--filter "FullyQualifiedName!~SwfocTrainer.Tests.Profiles.Live&FullyQualifiedName!~RuntimeAttachSmokeTests" \
-p:CollectCoverage=true \
-p:CoverletOutput=./TestResults/coverage.cobertura.xml \
-p:CoverletOutputFormat=cobertura \
-p:ExcludeByFile=**/obj/**%2c**/*.g.cs%2c**/*.g.i.cs

- name: Enforce 100% line+branch coverage
run: |
python3 scripts/quality/assert_coverage_100.py \
--xml "dotnet=tests/SwfocTrainer.Tests/TestResults/coverage.cobertura.xml" \
--out-json "codecov-analytics/coverage.json" \
--out-md "codecov-analytics/coverage.md"

- name: Upload coverage to Codecov
if: ${{ always() }}
uses: codecov/codecov-action@v5
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/coverage-100.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ jobs:
run: |
mkdir -p coverage
dotnet restore
dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release /p:CollectCoverage=true /p:CoverletOutput=./TestResults/coverage.cobertura.xml /p:CoverletOutputFormat=cobertura
dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release \
--filter "FullyQualifiedName!~SwfocTrainer.Tests.Profiles.Live&FullyQualifiedName!~RuntimeAttachSmokeTests" \
-p:CollectCoverage=true \
-p:CoverletOutput=./TestResults/coverage.cobertura.xml \
-p:CoverletOutputFormat=cobertura \
-p:ExcludeByFile=**/obj/**%2c**/*.g.cs%2c**/*.g.i.cs

- name: Enforce 100% coverage
run: |
Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/provider-zero-backlog.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Provider Zero Backlog

on:
push:
branches:
- "**"
pull_request:
branches:
- main

permissions:
contents: read

jobs:
provider-zero-backlog:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Sonar zero backlog
shell: pwsh
run: pwsh ./tools/quality/assert-sonar-zero-backlog.ps1 -Strict
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_PROJECT_KEY: Prekzursil_SWFOC-Mod-Menu

- name: Codacy zero backlog
shell: pwsh
run: pwsh ./tools/quality/assert-codacy-zero-backlog.ps1 -Strict
env:
CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }}
CODACY_ORG: ${{ vars.CODACY_ORG }}
CODACY_PROVIDER: gh
CODACY_REPO: Prekzursil/SWFOC-Mod-Menu

- name: DeepScan zero backlog
shell: pwsh
run: pwsh ./tools/quality/assert-deepscan-zero-backlog.ps1 -Strict
env:
DEEPSCAN_API_TOKEN: ${{ secrets.DEEPSCAN_API_TOKEN }}
DEEPSCAN_ZERO_BACKLOG_URL: ${{ vars.DEEPSCAN_ZERO_BACKLOG_URL }}

- name: Applitools zero backlog
shell: pwsh
run: pwsh ./tools/quality/assert-applitools-zero-backlog.ps1 -Strict
env:
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
APPLITOOLS_ZERO_BACKLOG_URL: ${{ vars.APPLITOOLS_ZERO_BACKLOG_URL }}
42 changes: 29 additions & 13 deletions .github/workflows/visual-audit.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
name: visual-audit
name: Applitools Visual Zero

on:
push:
branches:
- "**"
pull_request:
branches:
- main
workflow_dispatch:
inputs:
run_id:
description: Run ID to audit (maps to TestResults/runs/<run_id>/visual-pack)
required: true
required: false
type: string
baseline_dir:
description: Baseline directory
Expand All @@ -18,12 +24,28 @@ on:
default: ""
type: string

permissions:
contents: read

jobs:
applitools-visual-zero:
name: Applitools Visual Zero
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Applitools zero backlog
shell: pwsh
run: pwsh ./tools/quality/assert-applitools-zero-backlog.ps1 -Strict
env:
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
APPLITOOLS_ZERO_BACKLOG_URL: ${{ vars.APPLITOOLS_ZERO_BACKLOG_URL }}

compare-visual-pack:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.run_id != '' }}
runs-on: windows-latest
permissions:
contents: read
env:
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
steps:
Expand All @@ -44,7 +66,7 @@ jobs:
}

$candidateOverride = $env:CANDIDATE_DIR_INPUT
if (-not [string]::IsNullOrWhiteSpace($candidateOverride) -and $candidateOverride -notmatch '^[A-Za-z0-9._:\\/\\-]+$') {
if (-not [string]::IsNullOrWhiteSpace($candidateOverride) -and $candidateOverride -notmatch '^[A-Za-z0-9._:\\/\-]+$') {
throw "Invalid candidate_dir input."
}

Expand All @@ -56,7 +78,7 @@ jobs:
}

$baseline = $env:BASELINE_DIR_INPUT
if ([string]::IsNullOrWhiteSpace($baseline) -or $baseline -notmatch '^[A-Za-z0-9._:\\/\\-]+$') {
if ([string]::IsNullOrWhiteSpace($baseline) -or $baseline -notmatch '^[A-Za-z0-9._:\\/\-]+$') {
throw "Invalid baseline_dir input."
}

Expand All @@ -74,12 +96,6 @@ jobs:
-CandidateDir "${{ steps.paths.outputs.candidate }}" `
-OutputPath "${{ steps.paths.outputs.output }}"

- name: Applitools availability note
if: ${{ env.APPLITOOLS_API_KEY != '' }}
shell: pwsh
run: |
Write-Output "APPLITOOLS_API_KEY is configured. Visual pack can be uploaded for external review."

- name: Upload visual compare report
if: always()
uses: actions/upload-artifact@v4
Expand Down
7 changes: 7 additions & 0 deletions SwfocTrainer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwfocTrainer.DataIndex", "s
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwfocTrainer.Meg", "src\SwfocTrainer.Meg\SwfocTrainer.Meg.csproj", "{770853A3-EF6C-45B9-AC59-059E5AABA6EF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwfocTrainer.Transplant", "src\SwfocTrainer.Transplant\SwfocTrainer.Transplant.csproj", "{77A1A535-D5BA-4962-96D5-C3F37B6FB035}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -76,6 +78,10 @@ Global
{770853A3-EF6C-45B9-AC59-059E5AABA6EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{770853A3-EF6C-45B9-AC59-059E5AABA6EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{770853A3-EF6C-45B9-AC59-059E5AABA6EF}.Release|Any CPU.Build.0 = Release|Any CPU
{77A1A535-D5BA-4962-96D5-C3F37B6FB035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77A1A535-D5BA-4962-96D5-C3F37B6FB035}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77A1A535-D5BA-4962-96D5-C3F37B6FB035}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77A1A535-D5BA-4962-96D5-C3F37B6FB035}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -84,5 +90,6 @@ Global
{78844A28-7F80-42CC-81A4-071689DD1FE1} = {A0EC6126-B74A-4E20-A25C-06EB590EA0A9}
{C0B64C4D-4095-417F-A2D0-AE5E42D28262} = {A0EC6126-B74A-4E20-A25C-06EB590EA0A9}
{770853A3-EF6C-45B9-AC59-059E5AABA6EF} = {A0EC6126-B74A-4E20-A25C-06EB590EA0A9}
{77A1A535-D5BA-4962-96D5-C3F37B6FB035} = {A0EC6126-B74A-4E20-A25C-06EB590EA0A9}
EndGlobalSection
EndGlobal
41 changes: 41 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,47 @@ Reliability rule for runtime/mod tasks:
evidence: manual `2026-03-01` `dotnet restore SwfocTrainer.sln` + `dotnet build SwfocTrainer.sln -c Release --no-restore` + `dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release --no-build --filter "FullyQualifiedName!~SwfocTrainer.Tests.Profiles.Live&FullyQualifiedName!~RuntimeAttachSmokeTests"` => `Passed: 233`
evidence: bundle `TestResults/runs/20260301-004145/repro-bundle.json` (`classification=blocked_environment`, tactical default routing run; no swfoc process detected)
evidence: bundle `TestResults/runs/20260301-004232/repro-bundle.json` (`classification=blocked_environment`, tactical forced-override run; no swfoc process detected)
- [x] M3 closure wave: helper bridge fail-closed runtime path, `Launch + Attach` automation, strict tactical mode split (`TacticalLand`/`TacticalSpace`/`AnyTactical`), and codex-owned live process matrix rerun with schema-validated bundles.
evidence: test `tests/SwfocTrainer.Tests/Runtime/NamedPipeHelperBridgeBackendTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Runtime/NamedPipeExtenderBackendTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Profiles/LivePromotedActionMatrixTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Profiles/LiveRoeRuntimeHealthTests.cs`
evidence: manual `2026-03-01` `dotnet restore SwfocTrainer.sln` + `dotnet build SwfocTrainer.sln -c Release --no-restore` + `dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release --no-build --filter "FullyQualifiedName!~SwfocTrainer.Tests.Profiles.Live&FullyQualifiedName!~RuntimeAttachSmokeTests"` => `Passed: 237`
evidence: manual `2026-03-01` `powershell.exe -File tools/validate-workshop-topmods.ps1 -Path tools/fixtures/workshop_topmods_sample.json -Strict` => `validation passed`
evidence: manual `2026-03-01` `powershell.exe -File tools/validate-generated-profile-seed.ps1 -Path tools/fixtures/generated_profile_seeds_sample.json -Strict` => `validation passed`
evidence: manual `2026-03-01` Session A EAW snapshot `TestResults/runs/LIVE-EAW-20260301-191639/eaw-process-snapshot.json`
evidence: bundle `TestResults/runs/20260301-164213/repro-bundle.json` (`classification=passed`, scope `TACTICAL`)
evidence: bundle `TestResults/runs/20260301-165502/repro-bundle.json` (`classification=passed`, scope `AOTR`)
evidence: bundle `TestResults/runs/20260301-171325/repro-bundle.json` (`classification=skipped`, scope `ROE`, reason `set_credits precondition unmet: hook sync tick not observed`)
- [x] M4 execution wave: installed workshop/submod intelligence, chain-aware auto-launch, per-action mechanic gating, universal context faction routing, and expanded live evidence matrix (baseline + installed submod smokes).
evidence: test `tests/SwfocTrainer.Tests/Runtime/GameLaunchServiceTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Runtime/WorkshopInventoryServiceTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Runtime/ModMechanicDetectionServiceTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Runtime/RuntimeAdapterContextFactionRoutingTests.cs`
evidence: test `tests/SwfocTrainer.Tests/Core/ActionReliabilityServiceTests.cs`
evidence: manual `2026-03-02` `dotnet restore SwfocTrainer.sln` + `dotnet build SwfocTrainer.sln -c Release --no-restore` + `dotnet test tests/SwfocTrainer.Tests/SwfocTrainer.Tests.csproj -c Release --no-build --filter "FullyQualifiedName!~SwfocTrainer.Tests.Profiles.Live&FullyQualifiedName!~RuntimeAttachSmokeTests"` => `Passed: 254`
evidence: manual `2026-03-02` `powershell.exe -File tools/validate-workshop-topmods.ps1 -Path tools/fixtures/workshop_topmods_sample.json -Strict` => `validation passed`
evidence: manual `2026-03-02` `powershell.exe -File tools/validate-generated-profile-seed.ps1 -Path tools/fixtures/generated_profile_seeds_sample.json -Strict` => `validation passed`
evidence: manual `2026-03-02` installed graph `TestResults/mod-discovery/20260302-170047/installed-mod-graph.json` (`installedCount=23`, submod parent chains inferred)
evidence: bundle `TestResults/runs/20260302-164220/repro-bundle.json` (`classification=passed`, scope `TACTICAL`)
evidence: bundle `TestResults/runs/20260302-164500/repro-bundle.json` (`classification=passed`, scope `AOTR`, `launchContext.source=forced`)
evidence: bundle `TestResults/runs/20260302-164838/repro-bundle.json` (`classification=skipped`, scope `ROE`, reason `set_credits precondition unmet: hook sync tick not observed`)
evidence: bundle `TestResults/runs/M4-SUBMOD-3447786229-20260302-190617/repro-bundle.json` (`classification=passed`, chain `1397421866,3447786229`)
evidence: bundle `TestResults/runs/M4-SUBMOD-3287776766-20260302-190708/repro-bundle.json` (`classification=blocked_environment`, transient no-process attach)
evidence: bundle `TestResults/runs/M4-SUBMOD-3287776766-RERUN-20260302-191443/repro-bundle.json` (`classification=passed`, rerun confirmation chain `1397421866,3287776766`)
evidence: bundle `TestResults/runs/M4-SUBMOD-2361851963-20260302-190742/repro-bundle.json` (`classification=passed`, chain `1125571106,2361851963`)
evidence: bundle `TestResults/runs/M4-SUBMOD-2083545253-20260302-190826/repro-bundle.json` (`classification=passed`, chain `1125571106,2083545253`)
evidence: bundle `TestResults/runs/M4-SUBMOD-2083545253-20260302-190934/repro-bundle.json` (`classification=passed`, chain `1976399102,2083545253`)
evidence: bundle `TestResults/runs/M4-SUBMOD-2794270450-20260302-191050/repro-bundle.json` (`classification=passed`, chain `1770851727,2794270450`)
evidence: bundle `TestResults/runs/M4-SUBMOD-3661482670-20260302-191139/repro-bundle.json` (`classification=passed`, chain `1125571106,3661482670`)
evidence: manual `2026-03-03` installed graph delta `TestResults/mod-discovery/LIVE-NEWMOD-2361944372-20260303/installed-mod-graph.json` (`installedCount=25`, added `1780988753`, `2361944372`)
evidence: bundle `TestResults/runs/LIVE-NEWMOD-1780988753-20260303/repro-bundle.json` (`classification=skipped`, chain `1780988753`)
evidence: bundle `TestResults/runs/LIVE-NEWMOD-2361944372-20260303/repro-bundle.json` (`classification=skipped`, chain `2361944372`)
evidence: manual `2026-03-03` full deep-chain matrix `TestResults/runs/LIVE-M4-DEEP-20260302/chain-matrix-summary.json` (`entries=28`, `skipped=26`, `blocked_environment=2`, failed chains `2313576303` and `1976399102>3661482670`)
evidence: bundle `TestResults/runs/LIVE-M4-DEEP-20260302-chain16/repro-bundle.json` (`classification=blocked_environment`, reason `ATTACH_NO_PROCESS` / process drop)
evidence: bundle `TestResults/runs/LIVE-M4-DEEP-20260302-chain27/repro-bundle.json` (`classification=blocked_environment`, process dropped during promoted matrix attach)
evidence: bundle `TestResults/runs/LIVE-M4-RERUN-CHAIN16-20260303/repro-bundle.json` (`classification=blocked_environment`, persistent chain16 blocker)
evidence: bundle `TestResults/runs/LIVE-M4-RERUN-CHAIN27-20260303/repro-bundle.json` (`classification=skipped`, transient chain27 blocker cleared on rerun)

## Later (M2 + M3 + M4)

Expand Down
50 changes: 49 additions & 1 deletion docs/LIVE_VALIDATION_RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Use this runbook to gather real-machine evidence for runtime/mod issues and mile

## 1. Preconditions

- Launch the target game session first (`swfoc.exe` / `StarWarsG.exe`).
- Preferred: let Codex/tooling launch target sessions (`-AutoLaunch`) so run artifacts include deterministic launch wiring.
- Manual prelaunch remains supported when `-AutoLaunch` is not used.
- `tools/run-live-validation.ps1` preflights native host build and wires:
- `native/runtime/SwfocExtender.Host.exe`
- `SWFOC_EXTENDER_HOST_PATH` for every `dotnet test` subprocess.
Expand All @@ -20,6 +21,11 @@ Use this runbook to gather real-machine evidence for runtime/mod issues and mile
- For telemetry-first runtime mode detection, install/drop the telemetry mod template:
- `mods/SwfocTrainerTelemetry/Data/Scripts/TelemetryModeEmitter.lua`
- expected log marker: `SWFOC_TRAINER_TELEMETRY timestamp=<utc> mode=<mode>`
- Runtime mode contract is strict:
- `TacticalLand`
- `TacticalSpace`
- `AnyTactical`
- legacy `Tactical` should not be used in profile/runtime contracts.

## 2. Run Pack Command

Expand All @@ -28,6 +34,7 @@ pwsh ./tools/run-live-validation.ps1 `
-Configuration Release `
-NoBuild `
-Scope FULL `
-AutoLaunch `
-EmitReproBundle $true `
-FailOnMissingArtifacts `
-Strict
Expand All @@ -40,6 +47,7 @@ pwsh ./tools/run-live-validation.ps1 `
-Configuration Release `
-NoBuild `
-Scope ROE `
-AutoLaunch `
-EmitReproBundle $true `
-Strict `
-RequireNonBlockedClassification
Expand All @@ -51,9 +59,28 @@ Optional scope-specific runs:
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope AOTR -EmitReproBundle $true
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope ROE -EmitReproBundle $true
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope TACTICAL -EmitReproBundle $true
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope AOTR -AutoLaunch -EmitReproBundle $true
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope ROE -AutoLaunch -EmitReproBundle $true -ForceWorkshopIds 1397421866,3447786229 -ForceProfileId roe_3447786229_swfoc
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope TACTICAL -AutoLaunch -EmitReproBundle $true -ForceWorkshopIds 1397421866,2531671014
pwsh ./tools/run-live-validation.ps1 -NoBuild -Scope ROE -EmitReproBundle $true -TopModsPath TestResults/mod-discovery/<runId>/top-mods.json
```

Notes for ROE auto-launch:

- When `-ForceWorkshopIds` includes multiple IDs (for example `1397421866,3447786229`), the launcher emits chained args (`STEAMMOD=1397421866 STEAMMOD=3447786229`) to preserve mod dependency ordering.
- Runtime-health `set_credits` may be skipped with explicit precondition reason when no galactic/campaign sync tick is observed.

Installed submod smoke matrix (parent-first launch chain):

- `1397421866,2531671014`
- `1397421866,3447786229`
- `1397421866,3287776766`
- `1125571106,2361851963`
- `1125571106,2083545253`
- `1976399102,2083545253`
- `1770851727,2794270450`
- `1125571106,3661482670`

Forced-context closure run (for hosts that expose only `StarWarsG.exe NOARTPROCESS IGNOREASSERTS`):

```powershell
Expand All @@ -79,6 +106,7 @@ Expected in bundle diagnostics for forced-context runs:
Per run, artifacts are emitted under:

- `TestResults/runs/<runId>/`
- `TestResults/mod-discovery/<runId>/` (installed workshop graph)

Expected outputs:

Expand All @@ -95,6 +123,7 @@ Expected outputs:
- `repro-bundle.md`
- `issue-34-evidence-template.md`
- `issue-19-evidence-template.md`
- `installed-mod-graph.json` (under `TestResults/mod-discovery/<runId>/`)

`repro-bundle.json` classification values:

Expand All @@ -112,6 +141,14 @@ vNext bundle sections (required for runtime-affecting changes):
- `hookInstallReport`
- `overlayState`
- `actionStatusDiagnostics` (promoted action matrix diagnostics from `live-promoted-action-matrix.json`)
- `installedModContext`
- `resolvedSubmodChain`
- `mechanicGatingSummary`
- helper ingress diagnostics in `repro-bundle.json` diagnostics:
- `helperBridgeState`
- `helperEntryPoint`
- `helperInvocationSource`
- `helperVerifyState`

## 3a. Universal Compatibility Boundary

Expand All @@ -138,6 +175,10 @@ vNext bundle sections (required for runtime-affecting changes):
- `runtimeModeTelemetryReasonCode`
- `runtimeModeTelemetrySource=telemetry`
- When telemetry is stale or unavailable, expect explicit diagnostics reason codes (for example `telemetry_stale`).
- Mode mapping expectations:
- `LAND` -> `TacticalLand`
- `SPACE` -> `TacticalSpace`
- ambiguous tactical probes should resolve to `AnyTactical`, not legacy `Tactical`.

## 4. Promoted Action Matrix Evidence (Issue #7)

Expand Down Expand Up @@ -175,6 +216,13 @@ Expected evidence behavior for promoted actions:
- `hybridExecution=false`
- `hasFallbackMarker=false`
- fail-closed outcomes use explicit route diagnostics (`SAFETY_FAIL_CLOSED`) and block issue `#7` closure.
- capability-gated unavailability is recorded as explicit skip (`skipReasonCode=promoted_capability_unavailable`) instead of synthetic pass/fail.

Reset the override after matrix runs:

```powershell
Remove-Item Env:SWFOC_FORCE_PROMOTED_EXTENDER -ErrorAction SilentlyContinue
```

Reset the override after matrix runs:

Expand Down
Loading
Loading