| name | powershell |
| paths | ["**/*.ps1","**/*.psm1","**/*.psd1"] |
| description | PowerShell-specific toolchain and coding standards. |
PowerShell Code Standards
This rule file summarizes the PowerShell-specific policies for this repository.
Toolchain
- Formatting — Invoke-Formatter: Format all PowerShell files via PoshQC. MCP command:
mcp__drm-copilot__run_poshqc_format
- Linting — PSScriptAnalyzer: Run PoshQC analyzer with repo settings. MCP command:
mcp__drm-copilot__run_poshqc_analyze. Optional autofix: mcp__drm-copilot__run_poshqc_analyze_autofix
- Type checking: Not applicable for PowerShell; skip to testing.
- Testing — Pester (v5.x): Run tests via MCP. MCP command:
mcp__drm-copilot__run_poshqc_test. Use repo config at scripts/powershell/PoshQC/settings/pester.runsettings.psd1.
Run the toolchain in order: format → analyze → test. Restart from step 1 if any step fails or changes files. Use the MCP server functions; do not substitute VS Code task wrappers.
Compatibility
- All scripts must be compatible with PowerShell 7+ (enforced via PSScriptAnalyzer settings).
Coding Standards
- Prefer advanced functions with
CmdletBinding() and named parameters.
- Add
[Parameter(Mandatory = $true)] and validation attributes where appropriate.
- Implement ShouldProcess/SupportsShouldProcess for state-changing actions.
- Avoid global state and mutable script-scoped variables; pass data explicitly.
- Avoid
Invoke-Expression, plaintext secrets, and hard-coded credentials/paths.
- Use
Write-Error/throw for failures; avoid silent catch-alls.
- Use approved verbs and descriptive nouns for function names (PSScriptAnalyzer enforces this).
- Keep scripts cohesive and under 500 lines.
Change Budget
- Direct-mode overall scope: up to 2 production PowerShell files (plus corresponding tests). Requests exceeding this must be routed to
powershell-orchestrator per powershell-change-budget-router.
- Per-batch cap in all modes: at most 3 production files and 3 test files unless an explicit override has been approved.
- If a batch would exceed the cap, split the work into smaller batches.
Design Seams (Minimal DI)
Introduce the smallest seam that enables reliable mocking. Apply these options in order:
- Wrapper function seam (preferred) — extract external executable calls into a wrapper function:
- Signature:
Invoke-<Tool>Exe -<Tool>Args <string[]> (for example Invoke-GitExe -GitArgs <string[]>).
- The wrapper accepts a single array parameter and splats into the executable:
git @GitArgs 2>&1.
- Parameter names must not be
Args (automatic variable collision). Use GitArgs, ToolArgs, or Arguments.
- Injectable delegate / ScriptBlock seam — only when a wrapper is insufficient, add a narrowly-scoped optional delegate or
ScriptBlock parameter with a safe default. Do not introduce generic runner frameworks.
- Adapter seams for non-executable boundaries — for filesystem, environment, or clock dependencies, introduce tiny helpers or narrow injectable parameters rather than threading raw I/O through domain logic.
Testing Standards
- Use Pester (v5.x) as the test framework.
- Organize tests to mirror code structure (e.g.,
tests/scripts/dev-tools/ScriptName.Tests.ps1).
- Name test files
*.Tests.ps1.
- Use
Describe/Context/It blocks; one behavior per It.
- Write focused tests exercising a single function or behavior.
- Mock sparingly; prefer real code paths.
- No external dependencies in unit tests.
- Repository-wide line coverage must remain >= 80%.
- Any new module, class, or method must reach >= 90% coverage.
- Coverage regression on changed lines is a blocking finding.
Deterministic Test Requirements
Tests must not depend on:
- network access,
- mutable machine PATH or profile state,
- implicit working-directory assumptions,
- external services or live executables.
Tests must produce identical results in Terminal and the VS Code Test Explorer. Assume a different PATH, current working directory, profile, and host when tests are run from Test Explorer; do not rely on ambient environment resolution.
Mocking Rules
- External executable mocking — never mock
git, gh, actionlint, or other executables directly. Mock the wrapper function (for example Invoke-GitExe) instead.
- Mock signature parity — mock signatures must match production named parameters exactly. Example:
- production:
Invoke-GitExe -GitArgs $gitArgs
- test mock:
param([string[]]$GitArgs)
- Mock registration order — register mocks before the code under test can resolve commands, so Test Explorer parity is preserved.
- AST/ScriptBlock import order — when importing script functions via AST or
ScriptBlock patterns:
- dot-source the returned
ScriptBlock in the test scope,
- import dependencies in the correct order,
- import wrapper seams before mocking them when executable calls exist.
Prohibited Behaviors
- Broad refactors across unrelated scripts or modules.
- Introducing generic process-runner frameworks to replace the wrapper seam pattern.
- Creating PSScriptAnalyzer debt and deferring cleanup.
- Weakening assertions merely to make tests pass.
- Adding sleeps, retries, or timing hacks to stabilize flaky tests.
- Claiming success without running the required toolchain.