Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 5 additions & 2 deletions .github/agents/powershell-developer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ Implement PowerShell command and helper changes in the NovaModuleTools style.
- Preserve existing command names, warning semantics, and output shape.
- Keep new or heavily changed source functions aligned with `.github/instructions/code-quality-matrix.instructions.md`: short, single-purpose, low-duplication, and split by clear responsibility unless the scope explicitly justifies otherwise.
- Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` and `./run.ps1` for normal analyzer loops; use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repository-approved settings.
- Validate Nova-managed project tests through `Test-NovaBuild`; do not call `Invoke-Pester` directly.
- Validate Nova-managed project tests through `Invoke-NovaTest` for unit validation and `Test-NovaBuild` for build-validation integration validation; do not call `Invoke-Pester` directly.
- For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and keep per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior itself needs validation.
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output behavior.
- When help files change, keep `docs/NovaModuleTools/en-US/*.md` valid for `Import-MarkdownCommandHelp`: build and import the dist module first (`Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force`), then use `New-MarkdownCommandHelp` for new files, `Update-MarkdownCommandHelp` after command-surface changes, and `Test-MarkdownCommandHelp` before handoff. Generating help without the module imported causes `external help file` to default to the command name instead of the module name, producing per-command XML files that the manifest cannot find. A new public `src/public/*.ps1` file is not done until its matching help file exists.

## Definition of done
Expand All @@ -56,7 +58,8 @@ Implement PowerShell command and helper changes in the NovaModuleTools style.
- Build output still comes from Nova-generated `dist/` files, not hand-authored module files in `src/`.
- Public/private file ownership still follows the one externally called function per file rule, with private helpers kept as sibling top-level functions instead of nested function declarations.
- Every new public entry point has its matching help file.
- Project test validation ran through `Test-NovaBuild`.
- Project test validation ran through `Invoke-NovaTest` for unit coverage and `Test-NovaBuild` for build-validation integration coverage.
- Public-command integration coverage stays owned by `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior needs validation.
- Any ScriptAnalyzer findings reported by `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` are resolved.
- Every changed or generated text file has been checked and ends with exactly one trailing newline and no extra blank lines at the bottom.
- Docs/changelog review is complete.
Expand Down
4 changes: 3 additions & 1 deletion .github/agents/reviewer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ Review changes for correctness, maintainability, test coverage, workflow safety,
- Review changed `src/**/*.ps1` against `.github/instructions/code-quality-matrix.instructions.md` and `tests/**/*.ps1` against `.github/instructions/testing-policy.instructions.md`; flag new or heavily changed code that ignores those maintainability rules without a clear, explicit reason.
- Flag public files that do not keep exactly one top-level function, and flag private files that group multiple externally called functions instead of limiting extra functions to related same-file top-level support helpers. Also flag file/function name mismatches for public commands or externally called private helpers, and flag nested function declarations inside PowerShell functions.
- Flag broad catch-all test files when focused source-mirrored tests would make ownership clearer.
- Flag Nova-managed validation that bypasses `Test-NovaBuild` with direct `Invoke-Pester`.
- Flag public-command changes that skip `tests/public/<Command>.Tests.ps1` or the owning `tests/public/<Command>.Integration.Tests.ps1` without a clear cross-cutting justification.
- Flag destructive or environment-coupled public-command integrations that should have used safe `-WhatIf` coverage but did not.
- Flag Nova-managed validation that bypasses `Invoke-NovaTest` or `Test-NovaBuild` with direct `Invoke-Pester`.
- Flag any PSScriptAnalyzer rule excludes or suppressions; the code should be fixed instead.
- Flag unresolved ScriptAnalyzer findings from `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1`; they should be fixed instead of deferred.
- Flag every changed or generated text file if they do not exactly have one trailing newline with no extra blank lines at the bottom.
Expand Down
8 changes: 5 additions & 3 deletions .github/agents/test-engineer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,24 @@ Improve or maintain the repository's Pester coverage, coverage-gate behavior, an

## Constraints

- Prefer the smallest `Test-NovaBuild` scope the project already supports, then the full repo quality loop.
- Prefer the smallest `Invoke-NovaTest` scope for unit behavior, then `Test-NovaBuild` for build-validation integration coverage, then the full repo quality loop.
- Keep test files maintainable; passing tests are not enough if Code Health degrades.
- Reuse existing fixture and support patterns before adding new ones.
- Do not group unrelated source files into one broad test file when mirrored `tests/public`, `tests/private`, or `tests/classes` ownership is possible.
- For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when built-module behavior needs coverage.
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves the command wiring and `ShouldProcess` behavior.
- Do not introduce PowerShell 7.x-only test syntax or APIs into a project that targets `5.1` unless compatibility coverage is explicitly part of the scope.
- If CodeScene flags a regression, refactor the tests or helpers instead of suppressing the finding.
- Keep new or heavily changed tests focused, isolated, and easy to scan; split setup or assertion helpers when a test stops being readable.
- Use `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` as the normal analyzer entrypoint for changed test/helpers, and only fall back to direct `Invoke-ScriptAnalyzer` for focused local investigation with the repository-approved settings.
- Use `Test-NovaBuild` as the test entrypoint for Nova-managed projects; do not validate with direct `Invoke-Pester`.
- Use `Invoke-NovaTest` as the unit-test entrypoint and `Test-NovaBuild` as the build-validation integration-test entrypoint for Nova-managed projects; do not validate with direct `Invoke-Pester`.

## Definition of done

- The changed behavior is covered.
- Each new or changed `src/**/*.ps1` file has a matching source-mirrored test, or the cross-cutting owner test is named explicitly.
- The touched tests are readable and low-duplication.
- Validation uses `Test-NovaBuild` for project test execution.
- Validation uses `Invoke-NovaTest` for unit execution and `Test-NovaBuild` for build-validation integration execution.
- Validation and CodeScene implications are addressed.
- The pre-commit CodeScene safeguard is clean before the work is treated as commit-ready when local CodeScene tooling is available.

Expand Down
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/

- `src/public/` — public PowerShell commands; one top-level function per file, file name matches function name
- `src/private/` — domain-grouped helpers (`build/`, `cli/`, `package/`, `quality/`, `release/`, `scaffold/`, `shared/`, `update/`); one externally called helper per file
- `tests/` — Pester tests and shared test-support scripts
- `tests/` — Pester tests and shared test-support scripts; public command unit tests live under `tests/public/<Command>.Tests.ps1` and per-command build-validation integration tests live under `tests/public/<Command>.Integration.Tests.ps1`
- `scripts/build/` — local analyzer and build helpers
- `scripts/build/ci/` — CI coverage, CodeScene, and artifact helpers
- `.github/workflows/` — GitHub Actions CI, analyzer, dependency review, publish automation
Expand Down
2 changes: 1 addition & 1 deletion .github/instructions/code-quality-matrix.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp
- How to apply in PowerShell:
- Add or update a source-mirrored `tests/<area>/<Name>.Tests.ps1` file for every changed `src/**/*.ps1` file.
- Cover both the happy path and the meaningful unhappy, invalid, and boundary cases that the change introduces.
- Use `Test-NovaBuild` as the authoritative test entrypoint in Nova-managed projects. Do not call `Invoke-Pester` directly.
- Use `Invoke-NovaTest` as the unit-test entrypoint and `Test-NovaBuild` as the build-validation integration-test entrypoint in Nova-managed projects. Do not call `Invoke-Pester` directly.
- Isolate collaborators with mocks/stubs when verifying side effects or branching. Keep tests order-independent.
- See `.github/instructions/testing-policy.instructions.md` and the `pester-testing` skill for the full testing rules.
- Common objection: "It is too small to test." If it is too small to test, it is too small to be a change worth landing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Use this file when changing `src/public/`, `src/private/`, or PowerShell build/r
- Follow `.github/instructions/psscriptanalyzer.instructions.md` as the ScriptAnalyzer workflow source of truth. Use the repository analyzer wrapper for normal runs and reuse repository-approved settings when invoking `Invoke-ScriptAnalyzer` directly on a focused path.
- When public command help changes, follow `.github/instructions/platyps-help.instructions.md` and use `New-MarkdownCommandHelp`, `Update-MarkdownCommandHelp`, and `Test-MarkdownCommandHelp` instead of hand-authoring the help structure.
- Do not add PSScriptAnalyzer `ExcludeRule`, `ExcludeRules`, suppression attributes, or generated settings that hide analyzer findings. Fix the rule violation instead.
- Keep local quality wrappers ordered as ScriptAnalyzer first, then `Invoke-NovaBuild`, then `Test-NovaBuild`.
- Keep local quality wrappers ordered as ScriptAnalyzer first, then `Invoke-NovaBuild`, then `Invoke-NovaTest`, then `Test-NovaBuild`.
- If `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before treating the change as complete.

## Formatting rules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Canonical rule source for cross-cutting NovaModuleTools conventions that apply t
Use the smallest validation set that proves the change, then run the repository quality loop before finishing code work:

- local quality loop: `pwsh -NoLogo -NoProfile -File ./run.ps1`
- test validation: `Test-NovaBuild`
- test validation: `Invoke-NovaTest` for unit-test validation, then `Test-NovaBuild` for build-validation integration coverage
- analyzer only: `./scripts/build/Invoke-ScriptAnalyzerCI.ps1`
- CI-parity coverage flow: `./scripts/build/ci/Invoke-NovaModuleToolsCI.ps1 -OutputDirectory ./artifacts`

Expand Down
20 changes: 17 additions & 3 deletions .github/instructions/testing-policy.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ BeforeAll {

Legacy tests that still use `Import-Module $project.OutputModuleDir` + `InModuleScope` can still exist while maintainers finish migrations, but the mirrored pattern itself now supports enabled repository coverage gates. Generated project templates still ship `CodeCoverage.Enabled = false` until maintainers opt into the coverage gate for their own project.

## Integration tests may import `dist/`

- New mirrored unit tests should keep dot-sourcing `src/**/*.ps1` files directly.
- Public command integration ownership lives in `tests/public/<Command>.Integration.Tests.ps1` when the purpose is validating built-module behavior, exported command shape, command wiring, or build-validation smoke coverage.
- Cross-cutting `*.Integration.Tests.ps1` files may `Import-Module ./dist/<ModuleName>/<ModuleName>.psd1` when the behavior genuinely spans multiple source files.
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output behavior.
- Keep that `dist/` import limited to integration scenarios; do not use it as the default pattern for mirrored unit tests.

## Cross-cutting tests are still allowed

Use a cross-cutting test file (not a mirrored one) when the behavior under test truly spans multiple source files:
Expand All @@ -46,6 +54,7 @@ Cross-cutting files should be **named for the behavior** they validate (e.g., `A
| Source file | Mirrored test file |
|-----------------------------------|-------------------------------------------|
| `src/public/<Name>.ps1` | `tests/public/<Name>.Tests.ps1` |
| `src/public/<Name>.ps1` | `tests/public/<Name>.Integration.Tests.ps1` for built-module/public-command integration ownership |
| `src/private/<domain>/<Name>.ps1` | `tests/private/<domain>/<Name>.Tests.ps1` |
| `src/classes/<Name>.ps1` | `tests/classes/<Name>.Tests.ps1` |

Expand All @@ -54,8 +63,10 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
## Test expectations

- Behavior changes require Pester coverage.
- Use `Test-NovaBuild` as the authoritative test entrypoint in Nova-managed projects. Do not validate with direct `Invoke-Pester`, because it can bypass Nova's build/import/StrictMode flow and disagree with what users see later.
- Prefer the smallest `Test-NovaBuild` scope the project already supports before running the full quality loop.
- `Invoke-NovaTest` is the unit-test entrypoint and `Test-NovaBuild` is the build-validation integration-test entrypoint in Nova-managed projects. Do not validate with direct `Invoke-Pester`, because it can bypass Nova's build/import/StrictMode flow and disagree with what users see later.
- Prefer the smallest supported test scope first: `Invoke-NovaTest` for unit behavior, then `Test-NovaBuild` when the change needs built-module or integration validation, before running the full quality loop.
- For public commands, keep unit coverage in `tests/public/<Command>.Tests.ps1` and keep per-command integration ownership in `tests/public/<Command>.Integration.Tests.ps1` when the built command behavior itself needs validation.
- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output semantics.
- Keep test names explicit about the behavior being proven.
- Reuse `*.TestSupport.ps1` helpers where possible.
- For every new or changed `src/**/*.ps1` file, add or update the matching source-mirrored `.Tests.ps1` file.
Expand All @@ -71,6 +82,7 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
## Repository test structure

- `tests/public/<Name>.Tests.ps1`, `tests/private/<domain>/<Name>.Tests.ps1`, `tests/classes/<Name>.Tests.ps1` - mirrored unit tests (preferred for new and migrated tests)
- `tests/public/<Name>.Integration.Tests.ps1` - per-command build-validation integration tests for public commands
- `tests/ArchitectureGuardrails.Tests.ps1` - layering and adapter boundaries
- `tests/NovaCommandModel*.Tests.ps1` - public command, CLI, and workflow behavior (legacy bucket, being migrated)
- `tests/*TestSupport.ps1`, `tests/TestHelpers/` - shared helpers, reusable fixtures, dot-source helpers
Expand All @@ -79,7 +91,8 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro
## Coverage and CodeScene

- CI coverage is generated by `./scripts/build/ci/Invoke-NovaModuleToolsCI.ps1`.
- `Test-NovaBuild` runs once and produces a JaCoCo coverage report at `artifacts/coverage.xml`.
- `Invoke-NovaTest` produces the repository JaCoCo coverage report at `artifacts/coverage.xml`.
- `Test-NovaBuild` focuses on build-validation integration coverage and produces NUnit results without source coverage enforcement.
- The JaCoCo artifact is reused by the CodeScene PR coverage gate and by the develop/manual CodeScene analysis flow.
- The CodeScene analysis upload sends coverage twice: once for `line-coverage` and once for `branch-coverage`.
- Coverage paths in `project.json` must point at `src/**/*.ps1`, not at the built `dist` psm1. Nova does not override `CodeCoverage.Path`.
Expand All @@ -99,6 +112,7 @@ A non-blocking mirror status helper is available at `scripts/build/Get-TestMirro

## Verification

- `Invoke-NovaTest`
- `Test-NovaBuild`
- `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` when PowerShell code changed
- `pwsh -NoLogo -NoProfile -File ./run.ps1` before completion
Loading
Loading