Repository navigation
Description
Context and request
Module maintainers rely on the shipped Test-PSModule Module suite to detect missing public class and enum accelerators. The suite can return a passing result without checking those contracts after a comment-only change to generated module text.
This was reproduced while auditing #550 and #551. The Module validator and compiler are unchanged from default-branch source 64ffb1d87f86bd5d487891fdb140b78385a00531.
Observed behavior
The real PSModuleTest2 artifact from workflow run 41824863677, source dbd162f0001b73cfa03207dd18f0ce607adc6114, passes all 26 expanded Module cases. Removing the generated type-accelerator Add calls from an isolated copy causes 21 expected registration failures. Renaming only the Class exporter comment produces 4 passed cases and 1 skipped case; the data-driven type checks disappear. Combining the missing-registration fault with that comment rename also returns 4 passed, 1 skipped, and no failures. Direct inspection of the actual TypeAccelerators API confirms that Book and Genre are then absent.
Expected behavior
A harmless generated-comment change must not remove validation of a known public-type contract. A module expected to expose public types must fail when their registration is missing. Modules with no expected public types must remain valid.
Reproduction
Use PowerShell with Pester 6.1.0 and the real fixture module dependencies. Download the named run's module artifact while it is retained, or build the default fixture through the ordinary framework route from the pinned source. Keep all mutations in a temporary copy. Lay out the copy as <root>\PSModuleTest2\8.0.7\ so the installed version-folder contract is satisfied.
Run the existing suite without a replacement validator:
$configuration = New-PesterConfiguration
$configuration.Run.Container = New-PesterContainer `
-Path '.github\actions\Test-PSModule\src\tests\Module\PSModule\PSModule.Tests.ps1' `
-Data @{ Path = $installedFixturePath }
$configuration.Run.PassThru = $true
Invoke-Pester -Configuration $configurationIn the temporary PSModuleTest2.psm1, replace $TypeAcceleratorsClass::Add($Type.FullName, $Type) with a harmless no-op and rerun: 21 registration failures. Restore the original copy, replace Class exporter in comments with Type registration, and rerun: 4 passed, 1 skipped. Finally combine both mutations: the missing public accelerators are no longer detected. Remove the fixture module between runs so its real OnRemove cleanup clears the prior registrations.
Environment, regression, and workaround
Reproduced on Windows with PowerShell 7.6.9, Pester 6.1.0, and a real Ubuntu-built fixture artifact. The missing ThreadJob 1.x fixture dependency was first detected by the validator and then saved to isolated scratch storage; no global module installation was changed. The last known working discovery behavior is unknown. Keeping the current exporter marker unchanged avoids this particular omission, but it does not provide an independent oracle for expected public types.
Acceptance criteria
- A behavior-preserving exporter comment/variable refactor does not reduce the public-type cases examined.
- A fixture with known public classes and enums fails when registration is removed, with or without the current exporter comment.
- Expected types come from an independent supported contract, not the same generated registration list whose correctness is being tested.
- Importability, manifest/version checks, accelerator cleanup, and valid modules with no public types remain covered.
- Zero expected types is handled only as a documented legitimate case; missing discovery evidence is not silently treated as success.
Technical decisions
The verified boundary is .github/actions/Test-PSModule/src/tests/Module/PSModule/PSModule.Tests.ps1: discovery and run setup identify the exporter through a region-comment regex and read expected names from its private variable text. An unrecognized marker skips the type contexts. This issue concerns discovery/oracle reliability, not a production class-export rewrite.
Refine the independent public-type input through the existing Test-PSModule container/action contract before implementation. Preserve compatibility for consumers and do not invent a separate validator, copy the compiler as the expected-value oracle, or remove the shipped quality suite. This repair is separate from the test-only cleanup PR because it changes how the shipped validation product obtains its expected contract.
Implementation plan
- Add a regression using a real compiled public class/enum fixture, a harmless exporter-comment variation, and the missing-registration fault; demonstrate the false green first.
- Establish the independent supported expected-type input and compatibility behavior for modules without public types.
- Correct discovery through the existing suite/container/action route, with explicit missing-evidence diagnostics.
- Verify import, manifest/version, registration, and OnRemove behavior on the default and manifest fixture layouts across supported platforms.
- Verify the framework test-ID/module-validation documentation and retain honest examined/skipped counts in the PR evidence.
Activity