diff --git a/.github/agents/architect.agent.md b/.github/agents/architect.agent.md index 17fbc342..879562d7 100644 --- a/.github/agents/architect.agent.md +++ b/.github/agents/architect.agent.md @@ -12,16 +12,16 @@ Design or reshape changes that cross public commands, private helper boundaries, ## Responsibilities - Default new work to analysis first: clarify the problem, scope, risks, affected layers, validation needs, and documentation impact before implementation starts. -- Keep new-work design conversations interactive instead of collapsing them into a complete solution in the first reply. +- Keep new-work design conversations interactive instead of collapsing them into a complete solution in the first reply. New work means any request that introduces a new command, new workflow, new documentation section, or a structural change to existing layers. Refinements to already-scoped designs, bug fixes within a single private helper, and clarifying questions from the user are not new work and do not require the discussion-first flow. - Identify the affected public surface, internal helper domains, tests, docs, and workflows. - Keep the change aligned with the repo's layering and ArchitectureGuardrails expectations. - Recommend the smallest structure that solves the problem cleanly. - Treat scope cuts, deferrals, and out-of-scope boundaries as proposals that require explicit user confirmation. - Before offering finalization when unresolved questions remain, summarize what is settled, what is still unresolved, and present the explicit next-step choices. -- Support two finalization modes when the discussion is sufficiently scoped: +- When all of the following are true: affected layers and files are identified, no unresolved design questions remain, all out-of-scope boundaries have explicit user confirmation, and the user has indicated the discussion is done or asked to finalize, support two finalization modes: - design package plus GitHub issue draft - design package only -- Once the discussion is sufficiently scoped, produce an issue-ready change design with acceptance criteria, out-of-scope boundaries, and a GitHub issue draft. +- In the selected finalization mode, produce an issue-ready change design with acceptance criteria and out-of-scope boundaries. Include a GitHub issue draft only when the user selects the design-package-plus-issue-draft mode. ## Inputs to inspect @@ -33,6 +33,7 @@ Design or reshape changes that cross public commands, private helper boundaries, - `tests/ArchitectureGuardrails.Tests.ps1` - Relevant `src/public/` and `src/private//` files - Relevant `.github/workflows/*.yml` +- If one or more of these inputs are inaccessible, note which files are missing at the start of the response, state the assumptions you are making because of those gaps, and proceed with the available context. ## Skills to use @@ -49,12 +50,16 @@ Design or reshape changes that cross public commands, private helper boundaries, - Prefer surgical changes over broad rewrites. - Default to analysis, clarifying questions, and design-option discussion for new work. +- If the user's request has no connection to NovaModuleTools architecture or its defined layers, respond with a brief note that this agent is scoped to NovaModuleTools design work and suggest a more appropriate resource or agent. +- If the user explicitly asks to skip the discussion phase and receive a full design immediately, acknowledge the request, note any layers or questions that may still be underspecified, and produce the best-effort final design package while flagging the assumptions made because of the abbreviated process. - Preserve the public/private command model and CLI vs PowerShell distinction. - Avoid introducing new abstractions unless the current structure clearly duplicates or conflicts. - Do not edit repository files unless the user explicitly asks to move from design into implementation. -- Do not finalize the full design package until the user says the discussion is done, or you explicitly ask whether you should finalize it now. -- Do not ask to finalize as if the change is fully issue-ready when unresolved questions still exist; surface those unresolved items explicitly before asking how the user wants to proceed. -- Do not finalize out-of-scope decisions unless the user has explicitly confirmed them. +- Finalization gate: + - If unresolved design questions remain, summarize the settled points, list the unresolved items, present explicit next-step choices, and do not offer finalization yet. + - If any out-of-scope boundary lacks explicit user confirmation, surface it and ask for confirmation before finalization. + - When all finalization prerequisites in Responsibilities are satisfied, ask which finalization mode the user wants unless they already requested one. + - Produce only the output for the mode the user selected. ## Definition of done @@ -62,8 +67,7 @@ Design or reshape changes that cross public commands, private helper boundaries, - The scoped implementation approach matches existing repo structure. - Validation, documentation impact, and follow-on agent ownership are called out explicitly. - If the user chooses full finalization, a GitHub issue draft is ready to paste or create from the final output. -- If the user chooses design-package-only finalization, the output is clearly resumable later from an `Open questions / - resume here` section. +- If the user chooses design-package-only finalization, the output contains an `Open questions / resume here` section with every unresolved design question, the decisions already confirmed, the affected layers identified so far, and the next suggested step for whoever resumes the work. - Finalization output is copy-ready Markdown that applies the project `markdown-authoring` skill. ## Must not do diff --git a/.github/agents/docs-site.agent.md b/.github/agents/docs-site.agent.md index fb1d0877..676689db 100644 --- a/.github/agents/docs-site.agent.md +++ b/.github/agents/docs-site.agent.md @@ -14,6 +14,7 @@ Keep the GitHub Pages documentation under `docs/*.html` accurate, user-focused, - Update `docs/*.html` when end-user workflows, examples, or website wording change. - Preserve the separation between CLI-oriented website docs and PowerShell cmdlet help. - Check whether source, tests, help docs, and website docs still agree after a change. +- If a discrepancy between `docs/*.html` and `src/public/*.ps1` can only be resolved by changing source code, do not modify the HTML to match incorrect source behavior. Leave a clearly labeled `TODO` comment in the HTML and note the disagreement in your response so a developer can resolve it. - Keep command-surface-toggle pages honest by splitting CLI-only and PowerShell-only wording into the matching `data-command-visibility` blocks instead of mixing both spellings in shared prose. ## Inputs to inspect @@ -23,8 +24,8 @@ Keep the GitHub Pages documentation under `docs/*.html` accurate, user-focused, - `README.md` - `CONTRIBUTING.md` - `CHANGELOG.md` -- Relevant `src/public/*.ps1` files -- Relevant tests for the changed command or workflow +- The `src/public/*.ps1` file(s) that implement the command(s) documented on the page being edited, plus any command whose example output appears in that page. +- All test files under `tests/` whose file name or `Describe` block name references the command or workflow being documented. ## Skills to use @@ -37,8 +38,15 @@ Keep the GitHub Pages documentation under `docs/*.html` accurate, user-focused, - Treat `docs/*.html` as end-user website docs, not cmdlet help. - Keep CLI and cmdlet surfaces clearly separated. -- Mention PowerShell-only commands in CLI-oriented docs only when there is no CLI equivalent for that scenario, such as installing NovaModuleTools with `Install-Module`. -- On pages with the surface toggle, only show `--option` spellings in command-line-visible blocks and only show `-Parameter` spellings in PowerShell-visible blocks unless the wording is fully surface-neutral. +- Mention PowerShell-only commands in CLI-oriented docs only when there is no CLI equivalent for that same end-user task, such as installing NovaModuleTools with `Install-Module`. +- A CLI equivalent exists when a `--option`-style flag or subcommand that accomplishes the same end-user task is listed in `docs/*.html` or in `src/public/*.ps1` as a CLI entry point. Undocumented or internal CLI flags do not count as equivalents. +- Handle command-surface visibility with this decision tree: + 1. If the page does not have a command-surface toggle and contains both `--option` and `-Parameter` syntax, add the toggle markup and split the content into the appropriate `data-command-visibility` blocks. + 2. If the page has no command-surface toggle and does not contain both syntax forms, leave the existing structure in place. + 3. If a sentence contains a `--option` flag, place it in the command-line-visible block. + 4. If a sentence contains a `-Parameter` name, place it in the PowerShell-visible block. + 5. If a sentence contains both syntax forms, split it into separate surface-specific blocks. + 6. If a sentence contains no command names, flag spellings, or parameter names from either surface, keep it in shared always-visible HTML copy. ## Definition of done @@ -49,7 +57,7 @@ Keep the GitHub Pages documentation under `docs/*.html` accurate, user-focused, ## Must not do -- Must not mix cmdlet syntax into CLI docs when a CLI variant exists. +- Must not mix cmdlet syntax into CLI docs when a CLI equivalent, as defined above, exists. - Must not leave shared always-visible HTML copy with both CLI flags and PowerShell parameters when the page already has the command-surface toggle. - Must not use `docs/*.html` as a duplicate of `docs/NovaModuleTools/en-US/*.md`. - Must not leave installation/documentation exceptions implicit; state them clearly. diff --git a/.github/agents/powershell-developer.agent.md b/.github/agents/powershell-developer.agent.md index 3a384a1c..fe68a6db 100644 --- a/.github/agents/powershell-developer.agent.md +++ b/.github/agents/powershell-developer.agent.md @@ -14,11 +14,11 @@ Implement PowerShell command and helper changes in the NovaModuleTools style. - Change the relevant public command and private helper flow. - Keep public files delegating and internal helpers domain-aligned. - Preserve Nova's `project.json`-driven build model; do not add hand-written source `.psm1` or module `.psd1` files. -- Read `project.json` `Manifest.PowerShellHostVersion` before implementing PowerShell changes and keep source, tests, and examples compatible with that target. -- Keep one externally called function per file and match the file name to that function. In `src/private/`, additional related functions may stay only as same-file top-level support helpers called by that file's entry function, and PowerShell functions must not declare nested functions inside their bodies. +- Read `project.json` `Manifest.PowerShellHostVersion` before implementing PowerShell changes and keep source, tests, and examples compatible with that target. If `Manifest.PowerShellHostVersion` is absent or unrecognized, stop and ask the user to confirm the target PowerShell version before writing any source changes. +- Keep one externally called function per file and match the file name to that function. `src/public/*.ps1` files keep exactly one top-level public function; when a public command needs supporting logic, extract it to `src/private/` instead of adding more top-level functions to the public file. In `src/private/`, additional related functions may stay only as same-file top-level support helpers called by that file's entry function, and PowerShell functions must not declare nested functions inside their bodies. - Use `.github/instructions/code-quality-matrix.instructions.md` as the best-effort source-code maintainability guidance while shaping `src/**/*.ps1`. - Use `.github/instructions/psscriptanalyzer.instructions.md` as the ScriptAnalyzer workflow source of truth while changing PowerShell code or analyzer helpers. -- Add or update source-mirrored tests and valid PlatyPS-compatible help docs for the changed behavior, using the Microsoft.PowerShell.PlatyPS cmdlets instead of hand-written help structure. +- Add or update tests that follow the naming convention `tests/public/.Tests.ps1` for public commands and source-mirrored paths such as `tests/private//.Tests.ps1` for private helpers, one test file per source file, and keep valid PlatyPS-compatible help docs for the changed behavior using the Microsoft.PowerShell.PlatyPS cmdlets instead of hand-written help structure. - Every new public entry point must add its matching help file in the same change. - Before handoff, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the bottom. @@ -45,12 +45,17 @@ Implement PowerShell command and helper changes in the NovaModuleTools style. - Keep `ShouldProcess` behavior where the command already supports it. - Keep raw infrastructure calls behind approved adapters. - 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. +- 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. In `src/public/*.ps1`, satisfy that split by extracting helpers to `src/private/` or to separate private files, not by adding extra top-level functions to the public command file. - 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 `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/.Tests.ps1` and keep per-command integration ownership in `tests/public/.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. +- When help files change, keep `docs/NovaModuleTools/en-US/*.md` valid for `Import-MarkdownCommandHelp` and follow this workflow: + 1. Build and import the dist module: `Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force`. + 2. For new commands, run `New-MarkdownCommandHelp`. For updated command surfaces, run `Update-MarkdownCommandHelp`. + 3. Run `Test-MarkdownCommandHelp` before handoff. + 4. If you encounter an existing help file where the `external help file` field contains a command name rather than `NovaModuleTools-Help.xml`, treat it as broken and regenerate it with this import-first workflow before handoff. + Skipping step 1 causes the `external help file` field 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 @@ -58,12 +63,12 @@ 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 `Invoke-NovaTest` for unit coverage and `Test-NovaBuild` for build-validation integration coverage. +- Project test validation ran through `Invoke-NovaTest` for unit coverage and `Test-NovaBuild` for build-validation integration coverage. If either command reports failures, resolve every failure introduced by the current change before handoff. If a pre-existing failure is outside the current change scope, document it explicitly and do not mark this item complete until the user confirms how to proceed. - Public-command integration coverage stays owned by `tests/public/.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. -- The relevant validation commands have been run. +- Docs/changelog review is complete: update `CHANGELOG.md` under `[Unreleased]` with a one-line summary for each public-facing behavioral change, and if no public-facing behavior changed, explicitly confirm that no changelog update was needed. +- The required validation commands have been run: `Invoke-NovaTest` for unit coverage, `Test-NovaBuild` for build-validation integration coverage, `./run.ps1` or `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` for analyzer checks, and `Test-MarkdownCommandHelp` whenever help files were added or changed. ## Must not do diff --git a/.github/agents/release-manager.agent.md b/.github/agents/release-manager.agent.md index a8786637..2d1e14b1 100644 --- a/.github/agents/release-manager.agent.md +++ b/.github/agents/release-manager.agent.md @@ -15,7 +15,7 @@ Handle versioning, changelog shaping, release-flow documentation, and publish au - Keep `CHANGELOG.md` accurate and release-ready. - Review workflow, docs, and versioning implications together. - Produce a release-ready summary that follows `.github/pull_request_template.md` when a release preparation summary is requested. -- When the release scope is unclear (for example whether the change targets a stable bump, a prerelease, or both), ask one clarifying question before proceeding instead of guessing. +- If the user's request does not explicitly mention `stable`, `prerelease`, or a version identifier such as a SemVer value or channel name, ask exactly one clarifying question before proceeding: `Is this change targeting a stable release, a prerelease, or both?` ## Inputs to inspect @@ -25,6 +25,7 @@ Handle versioning, changelog shaping, release-flow documentation, and publish au - `.github/workflows/Publish.yml` - Relevant package, release, and publish tests - `README.md` / `CONTRIBUTING.md` +- If any required input file (`CHANGELOG.md`, `project.json`) is missing or cannot be parsed, halt and report: `Required file not found or unreadable. Please provide it before proceeding.` Do not attempt to reconstruct or infer its contents. ## Skills to use @@ -36,12 +37,14 @@ Handle versioning, changelog shaping, release-flow documentation, and publish au ## Constraints - Treat release automation as high-risk. -- Keep Keep a Changelog structure intact. -- Use only the official Keep a Changelog section types in `CHANGELOG.md` and `RELEASE_NOTE.md`: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`. -- Do not invent extra changelog section headings such as `Documentation`; place documentation-related release notes under the official type that best matches the actual impact. -- Distinguish contributor docs from end-user docs. -- Treat `.github/pull_request_template.md` as the authoritative format for structured release summaries. -- When the release summary is returned as Markdown or copy-ready UI output, it must follow the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). +- Preserve the Keep a Changelog structure intact. +- Changelog rules: + 1. Allowed section types in `CHANGELOG.md` and `RELEASE_NOTE.md` are exactly `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`. + 2. Do not create any other changelog or release-note headings such as `Documentation`. + 3. For documentation changes, use `Fixed` when correcting an inaccuracy, `Changed` when updating existing guidance to reflect behavior changes, and `Added` when documenting a newly introduced feature. When more than one type could apply, choose the type that reflects end-user impact rather than the authoring action. + 4. Treat contributor docs such as `CONTRIBUTING.md` and workflow READMEs separately from end-user docs such as `README.md` and public API docs. Contributor-only doc changes do not require a changelog entry; end-user doc changes must use the matching official section type. +- Treat `.github/pull_request_template.md` as the authoritative format for structured release summaries. If it cannot be read, halt and respond: `The PR template at .github/pull_request_template.md is required to produce a release summary but was not found. Please provide the file or paste its contents.` +- When the release summary is returned as Markdown or copy-ready UI output, it must follow the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). If that skill file is inaccessible, halt and respond: `Required skill markdown-authoring could not be loaded. Please resolve this before continuing.` If its rules conflict with this prompt, this prompt takes precedence. ## Definition of done @@ -53,5 +56,6 @@ Handle versioning, changelog shaping, release-flow documentation, and publish au ## Must not do - Must not publish packages, create tags, or push branch mutations unless explicitly requested. +- If the user explicitly requests publishing, tagging, or branch mutation, confirm the exact action and target such as package name, tag value, or branch, and summarize the irreversible consequences before proceeding. Do not proceed without explicit user confirmation in that same turn. - Must not change `main` / `develop` release semantics casually. - Must not skip changelog review for release-facing behavior. diff --git a/.github/agents/reviewer.agent.md b/.github/agents/reviewer.agent.md index a5a3452f..f10c5e65 100644 --- a/.github/agents/reviewer.agent.md +++ b/.github/agents/reviewer.agent.md @@ -12,26 +12,46 @@ Review changes for correctness, maintainability, test coverage, workflow safety, ## Responsibilities - Start with the highest-risk workflow or public behavior surface. +- First identify which file types are present in the diff, then apply only the rules for those types. - Check for missing tests, doc drift, changelog gaps, and CI/release side effects. -- Use the PR template categories as the review frame. -- When the review scope is genuinely ambiguous (for example which subset of files to focus on, or whether a borderline behavior change is intentional), ask one clarifying question before proceeding instead of guessing. -- Treat CodeScene maintainability and changed-code coverage results as release-blocking signals unless risk is accepted explicitly. -- If local CodeScene tooling is unavailable, continue the review with normal validation and rely on PR/CI as the effective CodeScene gate. -- Check whether website docs preserve the CLI-vs-cmdlet separation when `docs/*.html` or help markdown changed. +- Use the PR template categories as the review frame. If the PR description is absent or does not use the template categories, flag this as a process issue at the top of the review and proceed using the responsibility checklist directly as the review frame. +- If, after reading the diff and PR description, you cannot determine (a) which of two or more distinct file areas is the primary risk surface, or (b) whether a public-interface change is intentional, ask exactly one clarifying question identifying the specific ambiguity before proceeding. Do not ask if a reasonable inference is available from the diff context. +- If any referenced `.github/instructions/` or `.github/skills/` file is not available in context, stop and report which file is missing before continuing. Do not proceed with the affected check using assumed content. +- Treat available CodeScene maintainability and changed-code coverage results as release-blocking signals unless risk is accepted explicitly. If local CodeScene tooling is unavailable, note that local CodeScene was not run and rely on PR/CI as the effective CodeScene gate instead of treating the missing local result as a blocker by itself. + +### PowerShell source files + - Check that Nova projects still use generated `dist/` module files instead of hand-written source `.psm1` or module `.psd1` files. - Check changed PowerShell code, tests, and examples against `project.json` `Manifest.PowerShellHostVersion`; flag PowerShell 7.x-only constructs in projects that target `5.1` unless the change explicitly adds guarded compatibility handling. -- Check that public commands/classes have matching valid PlatyPS-compatible help and that new source files have source-mirrored tests. Flag help files under `docs/NovaModuleTools/en-US/` that look like plain Markdown, break the required PlatyPS section order, or would fail `Test-MarkdownCommandHelp` / `Import-MarkdownCommandHelp`. -- Flag any new public entry point that does not add its matching help file in the same change. -- Flag help files where `external help file` contains a command name instead of the module name. The correct value is `NovaModuleTools-Help.xml`; a per-command name like `Get-Something-Help.xml` means the help was generated without the built module imported. +- Review changed `src/**/*.ps1` against `.github/instructions/code-quality-matrix.instructions.md`; flag new or heavily changed code that ignores those maintainability rules without a clear, explicit reason. - Check analyzer changes and PowerShell validation flow against `.github/instructions/psscriptanalyzer.instructions.md`. Flag direct `Invoke-ScriptAnalyzer` usage that bypasses repository-approved settings or wrapper semantics without a clear reason. -- 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 public-command changes that skip `tests/public/.Tests.ps1` or the owning `tests/public/.Integration.Tests.ps1` without a clear cross-cutting justification. +- Flag public files that do not keep exactly one top-level function. For private files, additional functions are allowed only if those functions are called exclusively by the primary function in the same file and are not called from any other file; flag any private file whose secondary functions are called from outside that file. Also flag file/function name mismatches for public commands or externally called private helpers, and flag nested function declarations inside PowerShell functions. - 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. + +### Test files + +- Review changed `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. +- Check that public commands/classes have matching source-mirrored tests. +- Flag any test file that covers functions from more than one source file (i.e., the test file name does not mirror a single source file path), unless the file is explicitly scoped to integration or cross-cutting scenarios documented in its header. +- Flag public-command changes that skip `tests/public/.Tests.ps1` or the owning `tests/public/.Integration.Tests.ps1` without a clear cross-cutting justification. + +### Documentation files + +- Check whether website docs preserve the CLI-vs-cmdlet separation when `docs/*.html` or help markdown changed. +- Check that public commands/classes have matching valid PlatyPS-compatible help. Flag help files under `docs/NovaModuleTools/en-US/` that look like plain Markdown, break the required PlatyPS section order, or would fail `Test-MarkdownCommandHelp` / `Import-MarkdownCommandHelp`. +- Flag any new public entry point that does not add its matching help file in the same change. +- Flag help files where `external help file` contains a command name instead of the module name. The correct value is `NovaModuleTools-Help.xml`; a per-command name like `Get-Something-Help.xml` means the help was generated without the built module imported. + +### CI and workflow files + +- Check for CI/release side effects and workflow-safety regressions. + +### Other changed files + +- For changed files outside `src/`, `tests/`, `docs/`, `.github/`, and `AGENTS.md`, apply only the trailing-newline rule and note the file in the review summary. Do not apply source-specific rules to files outside their defined scope. - Flag every changed or generated text file if they do not exactly have one trailing newline with no extra blank lines at the bottom. ## Inputs to inspect @@ -60,6 +80,11 @@ Review changes for correctness, maintainability, test coverage, workflow safety, - Respect the repo's preference for small, reviewable changes. - Respect the repo's documentation split between website docs, command help, and contributor docs. +## Output format + +- Structure your review as: (1) a one-paragraph risk summary naming the highest-risk area, (2) a numbered list of findings each containing the file and line range, the violated rule, and the required fix, and (3) a final pass/needs-changes verdict. +- Omit sections for which there are no findings. + ## Definition of done - The main risk area is called out first. @@ -68,7 +93,7 @@ Review changes for correctness, maintainability, test coverage, workflow safety, ## Must not do -- Must not nitpick formatting-only issues. +- Must not nitpick formatting-only issues beyond the repository's explicit trailing-newline rule. - Must not ask for broad rewrites when a focused fix is enough. - Must not ignore contributor-doc or changelog obligations for behavior changes. - Must not miss CLI/cmdlet mixing in website documentation when that drift changes user guidance. diff --git a/.github/agents/test-engineer.agent.md b/.github/agents/test-engineer.agent.md index c1f5f8eb..51417d55 100644 --- a/.github/agents/test-engineer.agent.md +++ b/.github/agents/test-engineer.agent.md @@ -18,7 +18,7 @@ Improve or maintain the repository's Pester coverage, coverage-gate behavior, an - Use `.github/instructions/testing-policy.instructions.md` as the test-design source of truth while shaping `tests/**/*.ps1`. - Use `.github/instructions/psscriptanalyzer.instructions.md` when changing tests, test helpers, or analyzer/CI helpers so the repo-standard analyzer workflow stays intact. - Keep CI coverage output compatible with the CodeScene workflow. -- Before handoff, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the bottom. +- Before handoff, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the bottom. Apply trailing-newline normalization only to files with extensions `.ps1`, `.psm1`, `.psd1`, `.yml`, `.yaml`, `.json`, and `.md`. Skip all other file types silently. ## Inputs to inspect @@ -28,6 +28,7 @@ Improve or maintain the repository's Pester coverage, coverage-gate behavior, an - `scripts/build/ci/Invoke-NovaModuleToolsCI.ps1` - `.github/workflows/Tests.yml` - CodeScene findings when available +- If CodeScene findings are unavailable, proceed with all other Definition of Done criteria and add a PR comment: `CodeScene findings were not available at review time; re-run after merge if the pipeline provides them.` ## Skills to use @@ -40,26 +41,26 @@ Improve or maintain the repository's Pester coverage, coverage-gate behavior, an ## Constraints -- 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. +- 1. Use `Invoke-NovaTest` when the change affects only in-memory logic with no module-load or file-system dependency. 2. Escalate to `Test-NovaBuild` when the change affects module manifest, exported commands, or build artifacts. 3. Run the full repo quality loop only when step 2 passes and a CodeScene regression is still open. +- Passing tests are not enough if any CodeScene hotspot score for a changed file worsens compared to the baseline on the default branch. +- If an existing fixture or support helper in `tests/*TestSupport.ps1` covers at least 80% of the setup needed, extend it rather than creating a new file. Only create a new support file when no existing helper addresses the scenario. +- Do not group unrelated source files into one broad test file when mirrored `tests/public`, `tests/private`, or `tests/classes` ownership is possible. For source files outside `public`, `private`, and `classes` subdirectories, place tests in a `tests//` folder that mirrors the source path. If no matching subdirectory exists, create it rather than placing the test in the root `tests/` folder. - For public commands, keep unit coverage in `tests/public/.Tests.ps1` and per-command integration ownership in `tests/public/.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. +- For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves the command wiring and `ShouldProcess` behavior. If a destructive command does not implement `ShouldProcess`, create an integration test that uses a temporary isolated environment (for example, a `[System.IO.Path]::GetTempPath()` subdirectory) and cleans up in `AfterAll`. - 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 `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` as the normal analyzer entrypoint for changed test/helpers, and use direct `Invoke-ScriptAnalyzer` only for focused local investigation that reuses the repository-approved settings from that wrapper. - 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. +- Each new or changed `src/**/*.ps1` file has a matching source-mirrored test, or the covering test file contains a comment header of the form `# Covers: src//.ps1` immediately below the `#Requires` block. - The touched tests are readable and low-duplication. - 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. +- The pre-commit CodeScene safeguard is clean before the work is treated as commit-ready when local CodeScene tooling is available. If local CodeScene tooling is unavailable, document the gap in a `# TODO: verify CodeScene` comment on the PR description and do not block the commit, but treat the item as open. ## Must not do diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e1842e1f..9155d476 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -6,7 +6,13 @@ Index of repository-wide Copilot guidance for NovaModuleTools. This file is inte ## Start here -For non-trivial changes, read in this order: +Start here: + +1. If the work is new or not yet scoped, use the `architect` agent with `.github/prompts/design-change.prompt.md` first. The architect flow is discussion-first: clarify the request, explore options, and only finalize a scoped solution or issue draft after the discussion is done. +2. Otherwise, identify your task type in the Task map below and follow only the prompt, agent, and instructions listed for that row. +3. Use the reading order below only when no Task map row matches the work. + +For any change that adds, removes, or modifies public commands, helper functions, tests, CI workflows, or documentation, read in this order: 1. `README.md` 2. `CONTRIBUTING.md` @@ -15,8 +21,6 @@ For non-trivial changes, read in this order: 5. The topic-scoped instruction file(s) that match the paths you are touching 6. The skill listed under that topic in the task map below -For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/design-change.prompt.md`. The architect flow is discussion-first: clarify the request, explore options, and only finalize a scoped solution or issue draft after the discussion is done. - ## Repository map - `src/public/` — public PowerShell commands; one top-level function per file, file name matches function name @@ -44,14 +48,17 @@ The table below shows how to route work. Prompts are the task entry points; each | Review a change | `review-change.prompt.md` | `reviewer` | `terminal-ux-design`, `codescene-quality`, `safeguarding-ai-generated-code`, `building-maintainable-code`, `docs-site`, `markdown-authoring`, `pester-testing`, `release-and-changelog`, `github-actions` | All `.github/instructions/*.instructions.md` | | Improve test coverage | `improve-test-coverage.prompt.md` | `test-engineer` | `pester-testing`, `building-maintainable-code`, `codescene-quality`, `github-actions`, `guiding-refactoring-with-code-health`, `safeguarding-ai-generated-code` | `testing-policy`, `psscriptanalyzer` | | Prepare a release | `prepare-release.prompt.md` | `release-manager` | `release-and-changelog`, `markdown-authoring` | `release-policy`, `repository-conventions` | -| Fix a CI failure | `fix-ci-failure.prompt.md` | `powershell-developer` (or `test-engineer`) | `github-actions`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | -| Update website docs | (no dedicated prompt — invoke agent) | `docs-site` | `docs-site`, `markdown-authoring` | `documentation-separation` | +| Fix a CI failure | `fix-ci-failure.prompt.md` | `powershell-developer` when the failure is in source code or build scripts; `test-engineer` when the failure is in a Pester test file under `tests/` | `github-actions`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | +| Update website docs | Invoke `@docs-site` directly and pass the target file path. No prompt file is required. | `docs-site` | `docs-site`, `markdown-authoring` | `documentation-separation` | + +If a change spans multiple task types, run each relevant flow sequentially in this order: design (if needed) → implement → test coverage → docs → release. Do not attempt to merge prompts. ## Notation - Skills referenced as `/skill-name` in agent files map 1-to-1 to the `name:` field in `.github/skills//SKILL.md`. The runtime invokes them through the `skill` tool with the bare name. - Prompts are referenced by path. Custom prompts are not auto-loaded by the Copilot CLI; invoke them explicitly with `@.github/prompts/.prompt.md`. - Instructions auto-load when their `applyTo:` glob matches a file in the change set. +- If an expected instruction file does not auto-load because no file in the change set matches its `applyTo:` glob, explicitly load it with `@.github/instructions/.instructions.md` before proceeding. ## Related guidance diff --git a/.github/instructions/code-quality-matrix.instructions.md b/.github/instructions/code-quality-matrix.instructions.md index 725f1e91..98c1fc3a 100644 --- a/.github/instructions/code-quality-matrix.instructions.md +++ b/.github/instructions/code-quality-matrix.instructions.md @@ -15,26 +15,30 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp ## How to apply this guidance - Use these rules when writing or reviewing `src/**/*.ps1`, `scripts/**/*.ps1`, `run.ps1`, and `reload.ps1`. +- For script files that contain top-level imperative code without wrapping functions (`run.ps1`, `reload.ps1`, and similar entry scripts), treat each logically distinct top-level block as a unit. If any such block exceeds 15 lines, extract it into a named private helper function and call it from the script. - Prefer these patterns in new or heavily changed code instead of leaving cleanup for later. +- When reviewing a file that was not authored in this session, limit findings to: (a) all violations introduced or worsened by the current change, and (b) up to three pre-existing violations ranked by the G1-G10 priority order. Do not enumerate every pre-existing violation in a legacy file; instead note the total count and recommend a dedicated refactoring task. - Treat the thresholds as default goals, not as opinions. Use them to decide whether a function or file should be split. - If a change must violate one of these rules, keep the exception narrow and explain the trade-off clearly in the handoff. - Favor small refactors that remove the smell at the source over comments, suppressions, or wrappers that only hide it. - Apply lower-level (unit) guidelines before higher-level (component) guidelines. Fix size, complexity, duplication, and interface width first; balance and component coupling become much easier afterward. - Every commit counts. Leave each touched file at least as healthy as you found it; that is how the codebase trends upward over time. +When multiple smells are present, raise findings in this order: (1) size - G1, (2) complexity - G2, (3) duplication - G3, (4) interface width - G4, (5) separation of concerns - G5, (6) coupling - G6, (7) balance - G7, (8) codebase size - G8, (9) test coverage - G9, (10) cleanliness - G10. Do not raise a component-level finding (G5-G8) until all unit-level findings (G1-G4) in the same file have been identified. + ## Guideline 1 — Write short units of code -- Threshold: keep each PowerShell function body at most 15 lines, excluding the `function` line, the closing `}`, the `param(...)` block, and blank lines. +- Threshold: count only the executable statement lines inside the function body. Exclude: the `function` declaration line, the closing `}` of the function, the entire `param(...)` block (from `param` through its closing `)`), `[CmdletBinding()]`, `begin {` / `process {` / `end {` block-delimiter lines and their closing `}` lines, and blank lines. Every other line counts as one toward the 15-line limit. - Why: short units are easier to read, test, reuse, and review, and they fit inside human and agent working memory. - How to apply in PowerShell: - - Extract named helper functions; in `src/private/` they may stay as sibling top-level functions in the same file when they belong together. + - Extract named helper functions; in `src/private/` they may stay as sibling top-level functions in the same file when they belong to that entry function. - Replace inline transformation chains with a helper named after its intent. - Move repeated setup or formatting into helpers, not into comments that mark sections. - Common objection: "It is one logical step." If the function still ends up over 15 lines, the step has substeps. Name them. ## Guideline 2 — Write simple units of code -- Threshold: keep cyclomatic complexity at most 5, which is 4 branch points. Count `if`, `elseif`, `switch` case bodies, `-and`, `-or`, ternary `? :`, `while`, `for`, `foreach`, and `catch`. +- Threshold: keep the condition complexity score at most 5. Score 1 point for each: `if`, `elseif`, `switch` case body, ternary `? :`, `while`, `for`, `foreach`, `catch`, `-and`, and `-or`. This is stricter than standard cyclomatic complexity; it penalizes dense boolean guards as well as branching structure. - Why: complex units have too many paths to test thoroughly and are the most common source of regressions. - How to apply in PowerShell: - Replace long `switch` blocks or `if`/`elseif` chains with a dispatch hashtable keyed by mode, provider, state, or kind. @@ -44,7 +48,7 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp ## Guideline 3 — Write code once -- Rule: no Type 1 clones. Any identical block of 6 or more functional lines that appears twice is a finding. +- Rule: no Type 1 clones. Any block of 6 or more consecutive executable statement lines that is textually identical in two or more locations is a Type 1 clone finding. Exclude blank lines, comment-only lines, and `#region` / `#endregion` markers when counting. - Why: duplicated code drifts. Bugs fixed in one copy keep living in the other. - How to apply in PowerShell: - Extract the shared block into a helper under the correct `src/private//` folder and call it from both sites. @@ -54,7 +58,7 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp ## Guideline 4 — Keep unit interfaces small -- Threshold: at most 4 parameters per function. `[CmdletBinding()]` common parameters do not count. +- Threshold: at most 4 explicitly declared parameters in the `param()` block, regardless of whether they are mandatory, optional, or pipeline-bound. `[CmdletBinding()]` implicit common parameters (`Verbose`, `Debug`, `ErrorAction`, and similar) do not count. Pipeline-bound parameters declared in `param()` do count. - Why: long parameter lists are hard to read at the call site, hard to extend safely, and usually a sign that two or more concepts have been bundled into one function. - How to apply in PowerShell: - Group related parameters into a single `[pscustomobject]`, ordered hashtable, or small class such as a workflow context, an options object, or a request. @@ -80,7 +84,7 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp - How to apply in PowerShell: - Route environment access, Git execution, REST calls, uploads, and self-update behavior through their approved private helpers. `tests/ArchitectureGuardrails.Tests.ps1` is authoritative. - Hide provider-specific or platform-specific branching behind a small adapter surface so callers depend on a stable contract, not on the provider's quirks. - - Avoid pass-through helpers that only forward parameters to another function. Either add policy, validation, translation, or abstraction, or call the underlying function directly. + - A helper that exists solely to rename or re-export another function with no added policy, validation, error translation, or mock surface is a pass-through and should be removed. A helper that wraps an infrastructure call (environment, Git, HTTP, file system, and similar) to provide a stable internal contract is an adapter and is exempt from this rule even if it currently forwards parameters directly, provided it lives under the appropriate `src/private//` adapter folder. - Common objection: "The adapter feels redundant." It pays off the moment the underlying call changes, gains an error mode, or needs mocking. ## Guideline 7 — Keep architecture components balanced @@ -133,6 +137,5 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp ## Review expectations - Flag long mixed-responsibility functions, deep nesting, duplicated blocks, long parameter lists, pass-through helpers, provider-specific branching spread across callers, dead or commented-out code, magic values, and broad or hidden exception handling. -- When a finding is unit-level (Guidelines 1–4), prefer raising it before component-level findings (Guidelines 5–8). The unit fix usually makes the component fix smaller. -- When the code smell is test-specific, route that feedback through `.github/instructions/testing-policy.instructions.md` and the `pester-testing` skill instead of stretching this file to cover test-only patterns. +- Guidelines 3 and 9 apply to test files to the extent that they address duplication and coverage requirements. For smells that are specific to Pester syntax, mock hygiene, or test-file structure beyond duplication and coverage, route feedback to `.github/instructions/testing-policy.instructions.md` and the `pester-testing` skill instead of stretching this file to cover test-only patterns. - For step-by-step refactoring of unhealthy files, use the `building-maintainable-code` and `guiding-refactoring-with-code-health` skills together: the first picks the right guideline, the second runs measured Code Health checks between steps. diff --git a/.github/instructions/documentation-separation.instructions.md b/.github/instructions/documentation-separation.instructions.md index e8ff6450..4a64b077 100644 --- a/.github/instructions/documentation-separation.instructions.md +++ b/.github/instructions/documentation-separation.instructions.md @@ -4,6 +4,10 @@ applyTo: "docs/**/*.html,docs/assets/**/*.js,docs/NovaModuleTools/en-US/**/*.md, # NovaModuleTools documentation separation +## Files outside the applyTo scope + +For any documentation file not covered by the `applyTo` glob, apply the same audience-separation principles on a best-effort basis. If uncertain which audience a file targets, default to contributor/maintainer framing and flag it for review. + ## Purpose NovaModuleTools has multiple documentation surfaces with different audiences. Keep them clearly separated. @@ -13,6 +17,7 @@ NovaModuleTools has multiple documentation surfaces with different audiences. Ke - `docs/*.html` - GitHub Pages end-user documentation - `docs/NovaModuleTools/en-US/*.md` - PowerShell command help source - `README.md` / `CONTRIBUTING.md` - contributor and maintainer documentation +- `RELEASE_NOTE.md` - end-user-facing release announcements; use CLI syntax when a CLI variant exists, cmdlet syntax otherwise ## Separation rules @@ -23,11 +28,13 @@ NovaModuleTools has multiple documentation surfaces with different audiences. Ke - On website pages that support the command-surface toggle, keep surface-specific wording behind the matching visibility gate. - CLI-only flags, labels, and guidance belong in elements marked with `data-command-visibility="command-line"`. - PowerShell-only parameters, labels, and guidance belong in elements marked with `data-command-visibility="powershell"`. - - Shared prose should stay surface-neutral instead of mixing `--option` and `-Parameter` spellings in the same always-visible paragraph. + - Shared, always-visible prose must be surface-neutral: never use `--option` (CLI) or `-Parameter` (PowerShell) syntax in any always-visible element. Surface-specific syntax belongs exclusively inside the matching `data-command-visibility` gate. + - When a PowerShell-only cmdlet appears in CLI-oriented website docs under the allowed exception, do not place it inside a `data-command-visibility="powershell"` gate; keep it in always-visible prose and note that no `nova` CLI alternative exists. +- When a `nova` command and a PowerShell cmdlet both exist for the same task but behave differently, document the behavioral difference inside the respective `data-command-visibility` gate for each surface. Do not silently substitute one for the other. ## Allowed exception -- A PowerShell-only command may appear in CLI-oriented website docs when there is no CLI alternative for that task. +- A PowerShell-only cmdlet may appear in CLI-oriented website docs only when the specific operation it performs has no equivalent `nova` CLI command at all (not merely when the CLI command is less convenient or less documented). - The clearest current example is installation: - `Install-Module -Name NovaModuleTools` is a valid website-doc example - `nova` installation/setup docs may mention it because installation is still PowerShell-driven @@ -43,4 +50,5 @@ NovaModuleTools has multiple documentation surfaces with different audiences. Ke ## Follow-up expectations - Review `CHANGELOG.md` when a docs separation fix changes how users are guided. +- Review `RELEASE_NOTE.md` when a change affects user-visible CLI or cmdlet behavior. - Review `README.md` / `CONTRIBUTING.md` if contributor expectations or documentation ownership changed. diff --git a/.github/instructions/platyps-help.instructions.md b/.github/instructions/platyps-help.instructions.md index b2714daf..6ada3c85 100644 --- a/.github/instructions/platyps-help.instructions.md +++ b/.github/instructions/platyps-help.instructions.md @@ -17,6 +17,8 @@ Use this file when creating or updating command help under `docs/NovaModuleTools 1. Build and import the dist module before generating or updating help files. This ensures PlatyPS picks up the correct module name for both the `Module Name` and `external help file` metadata fields. + If `Invoke-NovaBuild` or `Import-Module` fails, stop and resolve the build error before proceeding. Do not run `New-MarkdownCommandHelp` or `Update-MarkdownCommandHelp` without a successfully imported dist module, as the resulting help files will have incorrect `external help file` values that break the Nova build. + ```powershell Invoke-NovaBuild Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force @@ -26,17 +28,18 @@ Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force ```powershell $newMarkdownHelp = @{ - CommandInfo = Get-Command -Module 'NovaModuleTools' - OutputFolder = './docs' - WithModulePage = $true - Force = $true + CommandInfo = Get-Command -Module 'NovaModuleTools' + OutputFolder = './docs' + WithModulePage = $false + Force = $true } New-MarkdownCommandHelp @newMarkdownHelp ``` 3. Every new public entry point must add its matching command-help file in the same change. A new `src/public/.ps1` file is not done until `docs/NovaModuleTools/en-US/.md` exists. -4. Keep the resulting command-help files under `docs/NovaModuleTools/en-US/` before handoff. If you generate files in a staging folder first, move the command-help markdown files into the repository's locale folder before you finish. -5. For existing command help, refresh syntax and parameter metadata with `Update-MarkdownCommandHelp` instead of editing the generated YAML structure by hand. +4. When a public entry point is removed, delete its matching command-help file in the same change. A removed `src/public/.ps1` is not done until `docs/NovaModuleTools/en-US/.md` is also deleted and any `RELATED LINKS` pointing to it in other help files are updated or removed. +5. Keep the resulting command-help files under `docs/NovaModuleTools/en-US/` before handoff. If you generate files in a staging folder first, move all generated command-help markdown files (per-command files and the module page, if generated) into `docs/NovaModuleTools/en-US/` before you finish. +6. For existing command help, refresh syntax and parameter metadata with `Update-MarkdownCommandHelp` instead of editing the generated YAML structure by hand. ```powershell Measure-PlatyPSMarkdown -Path ./docs/NovaModuleTools/en-US/*.md | @@ -44,7 +47,7 @@ Measure-PlatyPSMarkdown -Path ./docs/NovaModuleTools/en-US/*.md | Update-MarkdownCommandHelp -Path {$_.FilePath} ``` -6. Validate the final help with `Test-MarkdownCommandHelp -DetailView`, and inspect `Import-MarkdownCommandHelp` diagnostics when the structure or build result is unclear. +7. Validate the final help with `Test-MarkdownCommandHelp -DetailView`, and inspect `Import-MarkdownCommandHelp` diagnostics when the structure or build result is unclear. ```powershell Test-MarkdownCommandHelp -Path ./docs/NovaModuleTools/en-US/*.md -DetailView @@ -53,27 +56,37 @@ Import-MarkdownCommandHelp -Path ./docs/NovaModuleTools/en-US/.md | Select-Object -ExpandProperty Diagnostics ``` -7. Remember the build path: Nova effectively runs `Measure-PlatyPSMarkdown | Import-MarkdownCommandHelp | Export-MamlCommandHelp`. If your help files fail that path, the help is not done yet. -8. `-WithModulePage` is optional. Nova build consumes the command-help markdown files; a module page can exist, but it does not replace per-command help. +8. If `Test-MarkdownCommandHelp` reports any failures, or if `Import-MarkdownCommandHelp` returns non-empty Diagnostics with severity Error or Warning, fix the reported issues and re-run both validation commands before considering the help file done. Do not hand off a file that fails either check. +9. Remember the build path: Nova effectively runs `Measure-PlatyPSMarkdown | Import-MarkdownCommandHelp | Export-MamlCommandHelp`. If your help files fail that path, the help is not done yet. +10. `-WithModulePage` is optional. Nova build consumes the command-help markdown files; a module page can exist, but it does not replace per-command help. ## Required format - Files under `docs/NovaModuleTools/en-US/` must be valid PlatyPS command-help markdown, not plain project prose. - Start new help files from a PlatyPS-generated skeleton or from an existing valid help file that already matches the repository's help shape. - Keep one command-help file per public entry point, and match the markdown file name to the command name. + +### YAML metadata rules + +- Build-breaking constraint: the `external help file` field must always use the module name, not the command name: `NovaModuleTools-Help.xml`. The `Module Name` field must match the project name. When both fields use the module name, Nova build produces a single `-Help.xml` under `dist//en-US/`. If either field contains a command name instead, the build produces per-command XML files and the module manifest cannot find its help. - Keep the YAML metadata block at the top of every help file, delimited by `---`. - Keep the metadata aligned with the command being documented. At minimum, preserve the same metadata keys used by the repository's existing valid help files, including `document type`, `external help file`, `HelpUri`, `Locale`, `Module Name`, `ms.date`, `PlatyPS schema version`, and `title`. -- The `external help file` field must always use the module name, not the command name: `NovaModuleTools-Help.xml`. The `Module Name` field must match the project name. When both fields use the module name, Nova build produces a single `-Help.xml` under `dist//en-US/`. If either field contains a command name instead, the build produces per-command XML files and the module manifest cannot find its help. - Keep the H1 title equal to the exact command name. -- Preserve the standard PlatyPS section order with uppercase H2 headers: `SYNOPSIS`, `SYNTAX`, optional `ALIASES`, `DESCRIPTION`, `EXAMPLES`, `PARAMETERS`, `INPUTS`, `OUTPUTS`, `NOTES`, and `RELATED LINKS`. -- In `## RELATED LINKS`, use only a bulleted list of Markdown links. Do not use bare URLs or backticked command names as list items. -- Prefer relative links to sibling command-help files when the related topic has a matching file in `docs/NovaModuleTools/en-US/`, for example `[Invoke-NovaBuild](./Invoke-NovaBuild.md)`. -- Do not use GitHub blob URLs in shipped command help. If a relative command-help link is not suitable after PlatyPS validation, use the related topic's `novamoduletools.com` `HelpUri` instead. + +### Section structure rules + +- Preserve the standard PlatyPS section order with uppercase H2 headers: `SYNOPSIS`, `SYNTAX`, optional `ALIASES`, `DESCRIPTION`, `EXAMPLES`, `PARAMETERS`, `INPUTS`, `OUTPUTS`, required `NOTES`, and required `RELATED LINKS`. +- `## NOTES` and `## RELATED LINKS` headers are required even when the sections are empty. - Keep at least one example under `## EXAMPLES`. - Keep parameter sections as `### -ParameterName` blocks with the PlatyPS-generated YAML metadata code block. -- Only hand-edit parameter metadata when PlatyPS cannot infer it correctly, especially `DefaultValue` and `SupportsWildcards`. -- `## NOTES` and `## RELATED LINKS` headers are required even when the sections are empty. - Do not add ad hoc sections or reorder the required sections. + +### Links and examples rules + +- In `## RELATED LINKS`, use only a bulleted list of Markdown links. Do not use bare URLs or backticked command names as list items. +- Prefer relative links to sibling command-help files when the related topic has a matching file in `docs/NovaModuleTools/en-US/`, for example `[Invoke-NovaBuild](./Invoke-NovaBuild.md)`. +- Do not use GitHub blob URLs in shipped command help. If a relative command-help link is not suitable after PlatyPS validation, use the `HelpUri` value from the YAML metadata block of the related topic's command-help file instead, for example `https://novamoduletools.com/docs/en-US/Get-Something`. +- Only hand-edit parameter metadata when the PlatyPS-generated value is factually wrong, for example when `DefaultValue` is blank or `none` but the command has a documented default, or when `SupportsWildcards` is `false` but the parameter does accept wildcards. - If content is still incomplete, keep placeholder text inside a valid PlatyPS skeleton rather than collapsing the file into generic Markdown. ## Authoring guidance @@ -96,3 +109,4 @@ Import-MarkdownCommandHelp -Path ./docs/NovaModuleTools/en-US/.md | - Reviewers should flag any new public entry point that does not add its matching command-help file in the same change. - Reviewers should flag `RELATED LINKS` entries that use GitHub blob URLs, plain URLs, or bare/backticked command names instead of Markdown links. - Treat build errors from `Import-MarkdownCommandHelp` as a sign that the file is not valid PlatyPS help yet. +- If `Test-MarkdownCommandHelp` reports failures, or if `Import-MarkdownCommandHelp` returns Diagnostics with severity Error or Warning, reviewers should require those issues to be fixed and both validation commands to be re-run before handoff. diff --git a/.github/instructions/powershell-coding-standards.instructions.md b/.github/instructions/powershell-coding-standards.instructions.md index c7da2220..0cfdecb2 100644 --- a/.github/instructions/powershell-coding-standards.instructions.md +++ b/.github/instructions/powershell-coding-standards.instructions.md @@ -13,6 +13,7 @@ Use this file when changing `src/public/`, `src/private/`, or PowerShell build/r - Keep public command files small and delegating. - Keep exactly one top-level public function per file in `src/public/`. - Match the file name to that top-level public function name. +- If you encounter an existing `src/public/` file that violates the one-function or file-name-match rule, do not silently leave it. Note the violation in your response and, if fixing it is within the stated scope of the change, split or rename the file. If it is out of scope, flag it explicitly for a follow-up task. - Public mutating commands should support PowerShell `ShouldProcess` semantics. - Preserve existing naming and command model conventions for public commands/functions such as `Invoke-Nova*`, `Get-Nova*`, `Update-Nova*`, and the `nova` CLI routing model. - Do not create or maintain hand-written module `.psm1` or module `.psd1` files in source. Nova generates the built module root and manifest under `dist/NovaModuleTools/` from `project.json` and `src/**/*.ps1`. @@ -21,25 +22,32 @@ Use this file when changing `src/public/`, `src/private/`, or PowerShell build/r - Put internal helpers in the correct domain folder under `src/private/`. - In `src/private/`, keep at most one externally called function per file and match the file name to that entry function. -- Additional functions in a private file are allowed only as related top-level support helpers called from that same file. +- Additional functions in a private file are allowed only if they are never called from outside that file and exist solely to support the file's single entry-point function. - If two private functions are both called from outside their file, split them into separate same-named files. +- If any secondary function is called from a second file, move it to its own same-named file immediately. +- If splitting a private function would create a file name that already exists under `src/private/`, report the collision explicitly and do not overwrite the existing file. Propose a resolution such as renaming one function, merging responsibilities, or flagging the case for human decision before proceeding. - Do not declare functions inside other functions. Keep private support helpers as sibling top-level functions in the file instead of nested function declarations. - Private helper names should not use the public `Invoke-Nova*`, `Get-Nova*`, `Update-Nova*`, or `nova` CLI route naming conventions. Give private helpers clear implementation-focused names that describe what the helper does. -- Reuse existing adapters and shared helpers before adding new infrastructure calls. +- Before adding a new function that calls the filesystem, Git, network, or environment, check whether an approved wrapper already exists in the locations listed in `tests/ArchitectureGuardrails.Tests.ps1`. Use that wrapper instead of writing a new one. If `tests/ArchitectureGuardrails.Tests.ps1` is not accessible, stop and ask the user to provide it before making the related infrastructure change. - Keep direct environment access, Git execution, upload requests, and self-update execution in their approved helper locations. `tests/ArchitectureGuardrails.Tests.ps1` is authoritative. - Prefer explicit workflow-context objects (`[pscustomobject]` / ordered hashtables) for multi-step flows. ## Error and behavior rules -- Prefer clear, structured Nova errors over silent fallback behavior. -- Preserve existing warning semantics; do not rename warning opt-ins to a generic `-Force` pattern. -- Keep CLI spellings and PowerShell spellings distinct in messages and docs. -- Read `project.json` `Manifest.PowerShellHostVersion` before changing PowerShell source, scripts, or tests, and keep new usage compatible with that target. A `5.1` project must not receive PowerShell 7.x-only syntax, cmdlets, parameters, or APIs unless compatibility is explicitly guarded and within scope. -- 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 `Invoke-NovaTest`, then `Test-NovaBuild`. -- If `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before treating the change as complete. +### Before writing code + +1. Read `project.json` `Manifest.PowerShellHostVersion` before changing PowerShell source, scripts, or tests, and keep new usage compatible with that target. A `5.1` project must not receive PowerShell 7.x-only syntax, cmdlets, parameters, or APIs unless compatibility is explicitly guarded and within scope. If `Manifest.PowerShellHostVersion` is missing or cannot be parsed from `project.json`, default to targeting PowerShell 5.1 compatibility and note the assumption in your response. +2. 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. If `.github/instructions/psscriptanalyzer.instructions.md` is not accessible, stop and ask the user to provide it before proceeding with ScriptAnalyzer-related changes. +3. 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. If `.github/instructions/platyps-help.instructions.md` is not accessible, stop and ask the user to provide it before editing any help content. Do not fall back to hand-authoring the help structure. + +### While writing code + +1. Prefer clear, structured Nova errors over silent fallback behavior. +2. Preserve existing warning semantics; do not rename warning opt-ins to a generic `-Force` pattern. +3. Keep CLI spellings and PowerShell spellings distinct in messages and docs. +4. Do not add PSScriptAnalyzer `ExcludeRule`, `ExcludeRules`, suppression attributes, or generated settings that hide analyzer findings. Fix the rule violation instead. +5. In `run.ps1` and any task script that runs the full quality pipeline, invoke the tools in this order: (1) ScriptAnalyzer via the repository wrapper, (2) `Invoke-NovaBuild`, (3) `Invoke-NovaTest`, (4) `Test-NovaBuild`. Do not reorder them in other contexts. +6. If `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before treating the change as complete. ## Formatting rules @@ -79,7 +87,7 @@ Use this file when changing `src/public/`, `src/private/`, or PowerShell build/r ## Maintainability rules -- Use `.github/instructions/code-quality-matrix.instructions.md` as the best-effort source-code maintainability guidance for `src/**/*.ps1`; keep new or heavily changed code short, single-purpose, low-duplication, and split by clear responsibility. +- Treat `.github/instructions/code-quality-matrix.instructions.md` as mandatory maintainability guidance for new or heavily changed code in `src/**/*.ps1`; keep that code short, single-purpose, low-duplication, and split by clear responsibility. If `.github/instructions/code-quality-matrix.instructions.md` is not accessible, stop and ask the user to provide it before proceeding with the related refactoring or maintainability-sensitive change. - Favor short functions and extracted helpers over large nested logic. - Replace long `switch` or `if`/`elseif` chains with lookup tables, dispatch helpers, or focused strategy functions when behavior varies by mode, provider, or state. - Avoid copy/paste across source or test files. @@ -93,6 +101,6 @@ Use this file when changing `src/public/`, `src/private/`, or PowerShell build/r - Update or add Pester coverage for behavior changes. - Recheck `tests/ArchitectureGuardrails.Tests.ps1` when changing layering or helper placement. -- Run `./run.ps1` before considering a code change complete. +- Run `./run.ps1` before considering a code change complete. If `./run.ps1` cannot be executed because dependencies are missing or the environment is not configured, document the blocker explicitly in your response and list which verification steps were skipped. Do not treat the change as complete until a human confirms the run result. - Resolve any ScriptAnalyzer findings that `./run.ps1` reports before handoff. - Before handoff, review the changed/generated text files and normalize any file endings that violate the single-trailing-newline rule. diff --git a/.github/instructions/psscriptanalyzer.instructions.md b/.github/instructions/psscriptanalyzer.instructions.md index 82cf78a7..e0fc8987 100644 --- a/.github/instructions/psscriptanalyzer.instructions.md +++ b/.github/instructions/psscriptanalyzer.instructions.md @@ -18,16 +18,23 @@ Use this file when changing PowerShell code, tests, build helpers, or analyzer w 1. Use the repository wrappers as the authoritative entrypoints: - analyzer only: `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` - full local loop: `./run.ps1` -2. Use raw `Invoke-ScriptAnalyzer` only for focused local investigation or when you are deliberately changing analyzer tooling. -3. When you call `Invoke-ScriptAnalyzer` directly, point it at real `.ps1`, `.psm1`, or `.psd1` paths, use `-Recurse` when analyzing a directory, and reuse the repository-approved analyzer settings through `-Settings` instead of inventing a new rule selection. -4. Treat `Error`, `Warning`, and `ParseError` diagnostics as findings to fix before handoff. Parser errors are analyzer diagnostics too and are not something to suppress away. -5. Do not add ad hoc `ExcludeRule`, `ExcludeRules`, `SuppressMessageAttribute`, or custom settings changes just to make the analyzer pass. Only keep analyzer exceptions that the repository already approves and can justify narrowly. -6. `Invoke-ScriptAnalyzer -Fix` is optional and only applies to selected rules. Review every change it would make, prefer `-WhatIf` first, and inspect the diff afterwards. -7. `Invoke-ScriptAnalyzer -EnableExit` is useful for CI shells, but if the repository already has a wrapper with established failure semantics, do not replace that wrapper with an ad hoc direct invocation. +2. If the repository wrapper is missing or non-functional, do not silently fall back to a direct invocation. Instead, flag the broken wrapper as a blocking issue before proceeding. +3. Use raw `Invoke-ScriptAnalyzer` only for focused local investigation, including one focused run on changed files while iterating, or when you are deliberately changing analyzer tooling. +4. If invoking `Invoke-ScriptAnalyzer` directly, all of the following must hold: + - the run is justified as focused local investigation or analyzer-tooling work + - the target is a real `.ps1`, `.psm1`, or `.psd1` path + - use `-Recurse` when analyzing a directory + - use `-Settings` with the repository-approved settings source, which in this repository is the wrapper-owned `$settingsPath` configuration in `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` + - if using `-Fix`, run `-WhatIf` first and inspect the diff afterwards + - do not use `-EnableExit` when the repository wrapper already defines failure semantics +5. Treat `Error`, `Warning`, and `ParseError` diagnostics as findings to fix before opening a pull request or passing the change to a reviewer. Parser errors are analyzer diagnostics too and are not something to suppress away. +6. Do not add ad hoc `ExcludeRule`, `ExcludeRules`, `SuppressMessageAttribute`, or custom settings changes just to make the analyzer pass. Only keep analyzer exceptions explicitly present in the wrapper-owned `$settingsPath` configuration in `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` and justified narrowly. +7. `Invoke-ScriptAnalyzer -Fix` is optional and only applies to selected rules. Review every change it would make, prefer `-WhatIf` first, and inspect the diff afterwards. +8. `Invoke-ScriptAnalyzer -EnableExit` is useful for CI shells, but if the repository already has a wrapper with established failure semantics, do not replace that wrapper with an ad hoc direct invocation. ## Authoring guidance -- Prefer one focused analyzer run on the changed files while iterating, then rerun `./scripts/build/Invoke-ScriptAnalyzerCI.ps1`, then `./run.ps1` before handoff. +- Prefer one focused analyzer run on the changed files while iterating, then rerun `./scripts/build/Invoke-ScriptAnalyzerCI.ps1`, then `./run.ps1` before opening a pull request or passing the change to a reviewer. During iterative focused runs, apply the same severity threshold as the full CI run: fix all `Error`, `Warning`, and `ParseError` diagnostics; `Information` diagnostics may be deferred unless the repository settings elevate them. - Keep analyzer wrappers focused on source files and helper scripts, not generated output such as `dist/` or `artifacts/`. - If the repository has a `PSScriptAnalyzerSettings.psd1` file or a wrapper-owned settings hashtable, treat that configuration as authoritative for direct `Invoke-ScriptAnalyzer` runs. - Built-in presets such as `PSGallery` or `CodeFormatting` exist, but do not switch to them unless the repository explicitly adopts them. diff --git a/.github/instructions/release-policy.instructions.md b/.github/instructions/release-policy.instructions.md index 528ffd6b..4f68ee3c 100644 --- a/.github/instructions/release-policy.instructions.md +++ b/.github/instructions/release-policy.instructions.md @@ -13,13 +13,12 @@ Use this file when changing versioning, changelog handling, package metadata, pu - Follow Semantic Versioning intent. - Treat `CHANGELOG.md` as the exhaustive release history. - Treat `RELEASE_NOTE.md` as the interface-focused summary for public cmdlet, CLI, configuration, and migration changes. +- When a change qualifies for both files, write the `CHANGELOG.md` entry with full technical detail and write the `RELEASE_NOTE.md` entry as a concise consumer-facing summary; do not copy the `CHANGELOG.md` text verbatim into `RELEASE_NOTE.md`. - Keep `## [Unreleased]` valid and readable. - Use only the official Keep a Changelog section types in both files: `Added`, `Changed`, `Deprecated`, `Removed`, - `Fixed`, and `Security`. + `Fixed`, and `Security`. Under `## [Unreleased]`, `Changed` is valid for changes relative to the last released version, but not for internal iteration history of an unreleased feature that is already listed under `Added`. - Do not add custom section headings such as `Documentation`; place documentation-related release notes under the official type that best matches the real change. -- If `RELEASE_NOTE.md` has no public API or workflow changes under `## [Unreleased]`, keep the exact placeholder under - `### Added`: `No public API or workflow changes in this release. Internal maintenance only.` -- If `RELEASE_NOTE.md` has real release-note entries, do not keep that placeholder. +- Under `## [Unreleased]` > `### Added` in `RELEASE_NOTE.md`: if there are no public API or workflow changes, the section must contain exactly the line `No public API or workflow changes in this release. Internal maintenance only.` and nothing else. If there is at least one real entry, remove that placeholder line entirely before adding entries. - Do not add compare-link footer URLs to `RELEASE_NOTE.md`. - For unreleased feature iterations, update the existing `Added` entry instead of adding an internal-history `Changed` entry. @@ -33,14 +32,15 @@ Use this file when changing versioning, changelog handling, package metadata, pu ## Documentation rules -- Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, and `RELEASE_NOTE.md` for workflow or release changes. +- Read `README.md` and `CONTRIBUTING.md` to check for content that must be kept consistent with the current change; update them if they describe behavior that has changed. Always update `CHANGELOG.md` and `RELEASE_NOTE.md` as specified in the versioning rules. - Update command help in `docs/NovaModuleTools/en-US/` when public command behavior changes. -- Update `docs/*.html` only when end-user behavior or examples changed. +- Update `docs/*.html` only when a public cmdlet's output, parameters, default values, or documented examples change in a way visible to module consumers. - Use `.github/pull_request_template.md` as the authoritative structure when preparing a release summary for review. ## Agent safety rules - Do not publish, create tags, or push release commits unless the task explicitly requires it. +- If it is unclear whether a task requires publishing, tagging, or pushing, ask for explicit confirmation before proceeding. Never infer publishing intent from context alone. - Do not assume a preview flow should move `latest`; check the current package and release tests first. - Do not change release defaults without corresponding tests and changelog entries. @@ -48,4 +48,5 @@ Use this file when changing versioning, changelog handling, package metadata, pu - Validate the touched release or versioning path with targeted tests. - Run `./run.ps1` after code changes. +- If `./run.ps1` is not found or exits with a non-zero code, stop and report the failure with the full error output before proceeding with any further steps. - Re-read `.github/pull_request_template.md` before preparing release-related summaries. diff --git a/.github/instructions/repository-conventions.instructions.md b/.github/instructions/repository-conventions.instructions.md index 0ec4c41c..710262fe 100644 --- a/.github/instructions/repository-conventions.instructions.md +++ b/.github/instructions/repository-conventions.instructions.md @@ -19,7 +19,7 @@ Canonical rule source for cross-cutting NovaModuleTools conventions that apply t ## File ownership - `src/public/` files own exactly one top-level function each. The file name matches the function name. -- `src/private/` files expose at most one externally called function per file. Additional helpers may stay as sibling top-level functions in the same file when they belong to that entry function. The file name matches the externally called function. +- `src/private/` files expose at most one externally called function per file. Additional helpers may stay as sibling top-level functions in the same file only when they are called exclusively by that entry function and have no callers outside the file. The file name matches the externally called function. - PowerShell functions must not declare nested functions inside their bodies. - Prefer existing helpers and support files over ad hoc duplication. - Do not add raw infrastructure calls in public commands when an adapter/helper layer already exists. @@ -40,26 +40,28 @@ When CodeScene tooling is available: - run the pre-commit safeguard on AI-touched changes before suggesting a commit - run a branch/change-set analysis before suggesting a PR or declaring a larger change ready - if CodeScene reports a regression, refactor instead of treating the work as done +- If a CodeScene regression cannot be resolved by refactoring, for example because it appears in generated, vendored, or third-party code, document the exception in the PR description and proceed; do not block the change indefinitely. If CodeScene tooling is unavailable locally, continue with the normal repository validation flow; pull requests and CI remain the effective gate. -For documentation-only changes, executable validation may be skipped if no code path or workflow behavior changed. +If the only files changed are `.md` files and none of those files contain embedded code blocks that are executed as part of a test or build step, executable validation may be skipped. ## Documentation review -- Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, and `RELEASE_NOTE.md` after every meaningful change. +- Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, and `RELEASE_NOTE.md` after any change that adds, removes, or alters public-facing behavior, commands, parameters, or documented workflows. - Update tests when behavior changes. ## File formatting rule - Before handoff, review every changed or created text file and ensure it ends with exactly one trailing newline and no extra blank lines at the bottom. +- This rule applies to human-authored source files (`.ps1`, `.psm1`, `.psd1`, `.md`, `.json`, `.yml`, `.txt`). Do not apply it to binary files, lock files, or files under `dist/` that are generated by the build. - Do not leave any edited file with extra blank lines at the end, even if the functional code change is already complete. - Do not alter internal whitespace just to enforce the trailing newline rule. ## Safety constraints - Do not publish packages, create tags, or push changes unless explicitly requested. -- Do not modify GitHub Actions release automation casually; `Publish.yml` mutates `main` and `develop`. +- Do not modify `Publish.yml` unless the change is explicitly requested and the requester has acknowledged that `Publish.yml` mutates `main` and `develop`. - Do not bypass warnings or guards silently; Nova uses explicit `-OverrideWarning` / `--override-warning`. ## Commit message guidance @@ -67,16 +69,19 @@ For documentation-only changes, executable validation may be skipped if no code - When you are asked to suggest or prepare a commit message, answer in English. - Use Conventional Commit format. - Extract the ticket number from `$GIT_BRANCH_NAME` and render it as `(#)` immediately after the type when one is available. -- If `$GIT_BRANCH_NAME` starts with `hotfix/` or `bug/`, use `fix` as the type even when the implementation looks more like a feature. Use `fix!` if that branch change is also breaking. -- Otherwise estimate the type from the actual change: - - `feat` for feature work - - `fix` for bug fixes - - `feat!` for breaking feature work - - `fix!` for breaking fixes +- If `$GIT_BRANCH_NAME` is not set or is empty, omit the ticket number entirely and do not add a placeholder. +- Branch prefix takes precedence over change content when selecting the commit type. +- Select the commit type in this order: + 1. If `$GIT_BRANCH_NAME` starts with `hotfix/` or `bug/`, use `fix` as the type. Use `fix!` if that branch change is also breaking. Stop. + 2. Otherwise estimate the type from the actual change: + - `feat` for feature work + - `fix` for bug fixes + - `feat!` for breaking feature work + - `fix!` for breaking fixes - Keep the subject short, specific, and free of unnecessary detail. - If you provide multiple commit message suggestions or summarize multiple change options, use bullet points. - Do not invent a ticket number when `$GIT_BRANCH_NAME` does not contain one. ## Markdown output -When the output is intended to be copied as Markdown from the UI or written to a Markdown file, follow the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). Apply that rule especially to release summaries, review summaries, contributor-facing Markdown docs, prompt output, and PR-template-shaped text. +When the output is intended to be copied as Markdown from the UI or written to a Markdown file, follow the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). Apply that rule especially to release summaries, review summaries, contributor-facing Markdown docs, prompt output, and PR-template-shaped text. If `.github/skills/markdown-authoring/SKILL.md` is not accessible, apply standard CommonMark formatting: use ATX headings, fenced code blocks with language identifiers, and no trailing whitespace. diff --git a/.github/instructions/terminal-ux-design.instructions.md b/.github/instructions/terminal-ux-design.instructions.md index a6312f2d..4a184fc7 100644 --- a/.github/instructions/terminal-ux-design.instructions.md +++ b/.github/instructions/terminal-ux-design.instructions.md @@ -4,18 +4,20 @@ applyTo: "**" # Terminal UX design -Use the `terminal-ux-design` skill when a change touches any user-facing command, terminal output, prompt, help surface, progress indicator, warning, error message, or scaffold guidance for those surfaces. +Use the `terminal-ux-design` skill when a change touches any user-facing command, terminal output, prompt, help surface, progress indicator, warning, error message, or scaffold guidance for those surfaces. If a change touches both terminal-facing and non-terminal surfaces, apply the skill only to the terminal-facing portions of that change; leave non-terminal surfaces out of scope. This applies to: - PowerShell cmdlets - `% nova` CLI routes -- private helpers that shape user-visible terminal behavior +- internal functions or modules whose return values or side-effects are directly rendered as terminal output by a public command or route - contributor docs, command help, and scaffold content that teach those workflows -Keep PowerShell cmdlet UX and `% nova` CLI UX distinct, but hold both to the same terminal UX bar. +Keep PowerShell cmdlet UX and `% nova` CLI UX distinct, but apply both Atlassian's 10 CLI design principles and Nielsen's 10 usability heuristics equally to PowerShell cmdlet UX and `% nova` CLI UX; when the two frameworks conflict, prefer the Atlassian CLI principle as the more domain-specific guidance. The skill is authoritative for: - Atlassian's 10 design principles for delightful CLIs - Jakob Nielsen's 10 usability heuristics for user interface design + +When invoked, review the change against each of Atlassian's 10 CLI design principles and each of Nielsen's 10 usability heuristics. For every principle or heuristic that is violated or at risk, cite it by name, explain the specific violation in the change, and propose a concrete corrective rewrite. diff --git a/.github/instructions/testing-policy.instructions.md b/.github/instructions/testing-policy.instructions.md index fa9adb04..715e4bd7 100644 --- a/.github/instructions/testing-policy.instructions.md +++ b/.github/instructions/testing-policy.instructions.md @@ -13,9 +13,11 @@ Use this file when changing production code, tests, coverage behavior, or CI tes NovaModuleTools is migrating tests to a 1:1 source-to-test layout per issue #208. New and migrated tests follow this loading pattern: - The test file's `BeforeAll` dot-sources **only** the `src/**/*.ps1` files it needs (the source under test plus its private collaborators that are not being mocked). +- Dot-source a private collaborator when its real behavior is required to exercise the scenario under test. Mock a private collaborator when isolating the function under test from that collaborator's side effects or when controlling its return value is necessary for the test. - Tests do **not** `Import-Module $project.OutputModuleDir`. - Tests do **not** use `InModuleScope { ... }`. Mocked functions live in the same scope as the test because they were dot-sourced into it. - Shared fixtures and dot-source helpers live in `tests/TestHelpers/`. +- Changes to `tests/TestHelpers/` or `*.TestSupport.ps1` files do not require a separate mirrored test, but must be validated by running `Invoke-NovaTest` to confirm no existing tests regress. If a helper encapsulates reusable assertion logic, add inline Pester examples in a `*.Tests.ps1` file in `tests/TestHelpers/` only when the logic is non-trivial. - This makes `project.json` `Pester.CodeCoverage.Path = ["src/public/*.ps1", "src/private/*.ps1", "src/private/*/*.ps1", "src/private/*/*/*.ps1"]` produce real source-file coverage, including nested helper folders such as `src/private/build/manifest/` and `src/private/quality/duplicates/`, and means `Test-NovaBuild` does not require a `dist/` folder. Example: @@ -28,13 +30,13 @@ 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. +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. If a changed source file has no mirrored test yet, create the mirrored test file as part of the same change. Do not add new coverage to legacy bucket files (`CoverageGaps*.Tests.ps1`, `Remaining*Coverage*.Tests.ps1`, or `NovaCommandModel*.Tests.ps1`) for code that belongs in a mirrored test. Generated project templates still ship `CodeCoverage.Enabled = false` with a `90` percent target 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/.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//.psd1` when the behavior genuinely spans multiple source files. +- Public command integration ownership lives in `tests/public/.Integration.Tests.ps1` when the purpose is validating the built public command's shape, exports, wiring, or build-validation smoke coverage. +- Per-command and cross-cutting `*.Integration.Tests.ps1` files may `Import-Module ./dist//.psd1` only when the scenario genuinely requires the built module because the behavior spans multiple source files or depends on the exported command surface. - 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. @@ -57,27 +59,42 @@ Cross-cutting files should be **named for the behavior** they validate (e.g., `A | `src/public/.ps1` | `tests/public/.Integration.Tests.ps1` for built-module/public-command integration ownership | | `src/private//.ps1` | `tests/private//.Tests.ps1` | | `src/classes/.ps1` | `tests/classes/.Tests.ps1` | +| Any other `src/**/.ps1` | `tests//.Tests.ps1` mirroring the directory structure | A non-blocking mirror status helper is available at `scripts/build/Get-TestMirrorStatus.ps1` to show which source files still lack a mirrored test. +If the path does not fit an existing category, mirror the directory structure under `tests/` and flag it for maintainer review. If `Get-TestMirrorStatus.ps1` is unavailable or errors, manually verify that every modified `src/**/*.ps1` file has a corresponding `tests/**/*.Tests.ps1` file before marking the change complete. ## Test expectations +**Scope and entrypoint** + - Behavior changes require Pester coverage. - `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/.Tests.ps1` and keep per-command integration ownership in `tests/public/.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. +- Use broad guardrail, architecture, command-model, or integration tests only for behavior that genuinely spans multiple source files; do not use them as the default place for unit coverage of unrelated source files. + +**Isolation and helpers** + - Reuse `*.TestSupport.ps1` helpers where possible. - For every new or changed `src/**/*.ps1` file, add or update the matching source-mirrored `.Tests.ps1` file. - Keep test files and helpers compatible with `project.json` `Manifest.PowerShellHostVersion`; if a project targets `5.1`, do not rely on PowerShell 7.x-only syntax, cmdlets, parameters, or APIs in the tests. -- Cover both the normal path and the meaningful unhappy, invalid, or boundary cases that the changed behavior introduces. -- Use mocks or stubs for collaborators when the test needs to isolate behavior or verify side effects. +- Cover both the normal path and every distinct failure mode and boundary condition visible in the changed code's branching logic (for example null input, empty collections, out-of-range values, and each explicit error throw or early return). +- Use mocks or stubs for any function from a different source file, or for any function that performs I/O, state mutation, or external side effects, when the test needs to isolate the behavior of the file under test. - Keep tests isolated and order-independent; do not rely on shared mutable state between tests. + +**Maintenance and readability** + +- Keep test names explicit about the behavior being proven. - Update tests when production signatures or behavior change instead of leaving stale expectations behind. - Keep test flows linear and easy to scan; extract setup or assertion helpers when one test starts carrying too many responsibilities. - Follow `.github/instructions/psscriptanalyzer.instructions.md` when PowerShell tests, test helpers, or build helpers change. Use `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` for the repo-standard analyzer run, and use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repo-approved settings. -- Use broad guardrail, architecture, command-model, or integration tests only for behavior that genuinely spans multiple source files; do not use them as the default place for unit coverage of unrelated source files. + +Test placement decision tree: + +1. Does the test cover a single source file's logic? Use the mirrored `.Tests.ps1` file and dot-source `src/`. +2. Does the test validate the built public command's shape, exports, or wiring? Use `tests/public/.Integration.Tests.ps1`; do not `Import-Module dist/` unless step 3 also applies. +3. Does the test require the built module because the behavior genuinely spans multiple source files or depends on the exported command surface? Use an `.Integration.Tests.ps1` file and `Import-Module ./dist//.psd1`. ## Repository test structure diff --git a/.github/prompts/design-change.prompt.md b/.github/prompts/design-change.prompt.md index d438b5a8..fc2fc77b 100644 --- a/.github/prompts/design-change.prompt.md +++ b/.github/prompts/design-change.prompt.md @@ -2,11 +2,11 @@ > Invoke with `@.github/prompts/design-change.prompt.md`. Delegates to the `architect` agent. -Use this prompt with `architect.agent.md` when a change still needs analysis, scoping, and issue drafting before anyone starts editing files. +Use this prompt with `architect.agent.md` when a change still needs analysis, scoping, and issue drafting before anyone starts editing files. Do not treat invoking this prompt by itself as a request for the full final design package in the first response. -This is a discussion-first prompt. The default behavior is to hold a short design conversation with the user before producing a final scoped solution, implementation handoff, or GitHub issue draft. +This is a discussion-first prompt. The default behavior is to hold a short design conversation with the user before producing a final scoped solution, implementation handoff, or GitHub issue draft. If the user's first message already confirms the scope and leaves no open questions, you may skip the discussion phase and proceed directly to the readiness summary and finalization choices. -Scope is not final until the user confirms it. That includes anything you think should be treated as out of scope, deferred, split into follow-up work, or excluded from the first implementation pass. +Scope is not final until the user confirms it. That includes anything you think should be treated as out of scope, deferred, split into follow-up work, or excluded from the first implementation pass. For this prompt, the user selecting a finalization option after the readiness summary counts as confirming the current scope. ## Required inputs @@ -16,24 +16,28 @@ Scope is not final until the user confirms it. That includes anything you think ## Required process -1. Clarify the real problem first. Ask focused follow-up questions when scope, public-surface impact, ownership, or rollout direction is unclear. -2. Read `README.md`, `CONTRIBUTING.md`, `.github/copilot-instructions.md`, the relevant - `.github/instructions/*.instructions.md` files, and the most relevant skill definitions under - `.github/skills/*/SKILL.md`. -3. Inspect the affected public command, private helper domain, tests, docs, workflows, or release files without editing them. -4. Decide whether the request affects public cmdlets, `% nova` CLI behavior, `project.json`, CI/workflows, command help, website docs, `CHANGELOG.md`, or `RELEASE_NOTE.md`. -5. Present the user with the clearest trade-offs, options, or design directions when more than one reasonable path exists. -6. When you believe part of the request should be out of scope, present that as a proposal and ask the user to confirm or reject it. Do not silently narrow the task. -7. If unresolved questions still remain but the discussion is far enough along to consider finalization, pause for a short readiness check before asking to finalize: - - list what is already settled - - list what is still unresolved - - offer three explicit choices: - - finalize with design package and GitHub issue draft - - finalize with design package only - - keep discussing -8. Keep the conversation interactive until the user explicitly confirms the scope is correct and says the task is clear enough to finalize, or until you explicitly ask whether you should now draft the final output and the user chooses one of those options. -9. Only after that discussion is complete, produce the final scoped solution and implementation handoff, and include the GitHub issue draft only when the user chose the full-finalization option. -10. Do not edit repository files unless the user explicitly switches from design to implementation. +### Before first response + +1. Clarify the real problem first. Ask at most 2 focused follow-up questions per turn, prioritizing the question most likely to change the scope or approach. +2. Read only the minimum repository context needed to ask informed questions. Start with the most relevant of `README.md`, `CONTRIBUTING.md`, `.github/copilot-instructions.md`, the relevant `.github/instructions/*.instructions.md` files, and the most relevant skill definitions under `.github/skills/*/SKILL.md`. + If any of these files are missing or inaccessible, note which ones could not be read, proceed with the information available, and flag the missing context to the user in your first response. +3. Inspect only the most directly affected public command, private helper domain, test, doc, workflow, or release surface without editing files. + +### Before finalization + +4. Before producing final output, read the remaining relevant repository guidance from `README.md`, `CONTRIBUTING.md`, `.github/copilot-instructions.md`, the relevant `.github/instructions/*.instructions.md` files, and the most relevant `.github/skills/*/SKILL.md` definitions. +5. Inspect the affected public command, private helper domain, tests, docs, workflows, or release files without editing them. +6. Decide whether the request affects public cmdlets, `% nova` CLI behavior, `project.json`, CI/workflows, command help, website docs, `CHANGELOG.md`, or `RELEASE_NOTE.md`. Preserve the distinction between public PowerShell cmdlets and `% nova` CLI behavior, and keep contributor docs, command help, website docs, changelog entries, and release notes separated by audience. +7. Present the user with the clearest trade-offs, options, or design directions when more than one reasonable path exists. +8. When choices exist, present 2-3 concrete solution directions when the approaches differ in public API surface, implementation complexity, or rollout risk. +9. When you believe part of the request should be out of scope, present that as a proposal and ask the user to confirm or reject it. Do not silently narrow the task. +10. After each response, if the user has not yet confirmed scope, end your turn with either the next most important design question or, if you have no remaining questions and at least the core scope and problem statement are settled, even if secondary questions remain open, a readiness summary followed by these three finalization choices: + - finalize with design package and GitHub issue draft + - finalize with design package only + - keep discussing +11. Do not produce final output until the user selects a finalization option from those choices. If the user has declined finalization or continued the discussion for more than three turns after the readiness summary was first offered, restate the readiness summary and say: "We can keep refining, but I want to flag that we have already covered the core design decisions. Would you like to finalize now, or is there a specific blocker preventing finalization?" +12. Only after that discussion is complete, produce the final scoped solution and implementation handoff, and include the GitHub issue draft only when the user chose the full-finalization option. +13. Do not edit repository files unless the user explicitly switches from design to implementation. If the user requests a switch to implementation before scope is finalized, produce the design package only, without a GitHub issue draft, as the handoff record, then defer to the implementation agent. Do not begin editing files until the design package has been produced. ## Discussion-phase output @@ -41,18 +45,20 @@ Use the first response and follow-up design turns to drive a conversation, not t - a short restatement of the problem - the most important design questions -- 2-3 concrete solution directions when choices exist +- 2-3 concrete solution directions when the approaches differ in public API surface, implementation complexity, or rollout risk - clear trade-offs - a recommendation when one option is strongest - proposed scope and out-of-scope boundaries clearly marked as proposals until the user confirms them - when unresolved items remain, a readiness summary before any finalization question so the user knows what is still open -Do not produce the full final design package in the first response unless the user explicitly asks for it. Do not convert your own proposed scope boundaries into final decisions without the user's confirmation. +Do not produce the full final design package in the first response unless the user explicitly asks for it or their first message already confirms scope and requests finalization. Do not convert your own proposed scope boundaries into final decisions without the user's confirmation. ## Finalization output All finalization output is copy-ready Markdown. Apply the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`) for copy-safe UI output, including any required wrapping, and do not add prose outside the final output. +Draft issue text in English unless the user explicitly asks for another language. + If the user chooses **design package and GitHub issue draft**, return: - a short usage note that explains: @@ -89,14 +95,3 @@ In design-package-only mode: - preserve the settled decisions clearly enough that the user can resume later - end with the next unresolved design decision or a short resume prompt the user can reuse later - still apply the `markdown-authoring` skill to the final response - -## Repository-specific reminders - -- Preserve the distinction between public PowerShell cmdlets and `% nova` CLI behavior. -- Keep contributor docs, command help, website docs, changelog entries, and release notes separated by audience. -- Final design summaries and GitHub issue drafts are always copy-ready Markdown output; apply the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). -- Draft issue text in English unless the user explicitly asks for another language. -- If the task still has unresolved choices, end the turn with the next best question or the next design decision the user should make. -- If unresolved choices remain and you offer finalization anyway, explain what is settled, what is unresolved, and what each finalization option will produce. -- If you return both design notes and a GitHub issue draft, explicitly tell the user how to use each part. -- If you think some requested work should be deferred or excluded, ask for confirmation before turning that judgment into the final scope or issue draft. diff --git a/.github/prompts/fix-ci-failure.prompt.md b/.github/prompts/fix-ci-failure.prompt.md index a7c667d3..b3985041 100644 --- a/.github/prompts/fix-ci-failure.prompt.md +++ b/.github/prompts/fix-ci-failure.prompt.md @@ -1,6 +1,6 @@ # Fix NovaModuleTools CI failure -> Invoke with `@.github/prompts/fix-ci-failure.prompt.md`. Delegates to the `powershell-developer` or `test-engineer` agent depending on the failing area. +> Invoke with `@.github/prompts/fix-ci-failure.prompt.md`. Delegate to `powershell-developer` when the failing step invokes a PowerShell script or custom action. Delegate to `test-engineer` when the failing step runs tests, generates coverage reports, or uploads test artifacts. Investigate and fix a failing NovaModuleTools CI or workflow issue. @@ -8,17 +8,20 @@ Investigate and fix a failing NovaModuleTools CI or workflow issue. - Failing workflow name, job, and error output +If any required input is missing, stop and ask the user to supply it before proceeding. Do not attempt to guess the failing workflow, job, or error output. + ## Required process 1. Read the failing workflow in `.github/workflows/`. 2. Inspect the script or custom action that owns the failing step. -3. Reproduce locally with the closest existing command or helper script. -4. Fix the root cause with the smallest safe change. -5. Update tests or docs if the workflow behavior changed. +3. Reproduce locally by running the exact command from the failing workflow step. If that command is not directly runnable locally, document the closest approximation and note the difference. If the failure cannot be reproduced locally due to missing secrets, environment, or runner dependencies, document that fact explicitly and proceed to root-cause analysis using the error output and workflow definition alone. +4. Fix the root cause by changing only the files directly involved in the failure. Do not refactor unrelated code, rename public interfaces, or alter behavior outside the failing step. +5. If the fix changes what the workflow does, what it produces, or how it is invoked, update the corresponding tests and documentation to match the new behavior. 6. Summarize the failure mode, the fix, and the validation. ## Repository-specific reminders - `Tests.yml` owns test/coverage artifacts and CodeScene coverage gates. - `Publish.yml` is high-risk because it handles publish, release commits, tags, and branch updates. +- If the failing step is in `Publish.yml`, do not apply any fix without first presenting a detailed description of the change and its blast radius to the user for explicit approval before editing the file. - `powershell.yml` is analyzer-focused and should stay narrow. diff --git a/.github/prompts/implement-issue.prompt.md b/.github/prompts/implement-issue.prompt.md index 13327fdd..38ae64fc 100644 --- a/.github/prompts/implement-issue.prompt.md +++ b/.github/prompts/implement-issue.prompt.md @@ -7,34 +7,37 @@ Implement the issue in the NovaModuleTools repository using the repository-local ## Required inputs - Issue number or issue text +- If the issue number cannot be resolved, the issue text is insufficient to determine scope, or the issue appears already implemented, stop and ask the user to clarify before proceeding. Do not attempt to infer intent from a missing or unresolvable issue. - Relevant files or failing behavior - `$GIT_BRANCH_NAME` when a commit message suggestion is needed +- If a commit message is requested but `$GIT_BRANCH_NAME` was not provided, generate the commit message without a ticket number suffix and note that the branch name was not available. Do not omit the commit message or halt. ## Required process -1. **Before any other action:** invoke the `skill` tool for `markdown-authoring` when the final handoff summary will be returned as copy-ready Markdown. This is a blocking requirement — load the skill before reading files or producing output. -2. If scope, acceptance criteria, or ownership are still unclear, start with `.github/prompts/design-change.prompt.md` and `architect.agent.md` before implementing. -2. Read `README.md`, `CONTRIBUTING.md`, `.github/copilot-instructions.md`, and `.github/pull_request_template.md`. -3. Inspect the relevant public command, matching private helper domain, tests, and docs. +1. Read `README.md`, `CONTRIBUTING.md`, `.github/copilot-instructions.md`, and `.github/pull_request_template.md`. +2. If scope, acceptance criteria, or ownership are still unclear after that initial read, start with `.github/prompts/design-change.prompt.md` and `architect.agent.md` before implementing. +3. Identify which public command(s) are directly implicated by the issue. Inspect those commands, their private helper files in the matching subdirectory under `src/private/`, their Pester test files, and their help docs. If no single command is implicated, inspect all files referenced in the issue body. 4. If the issue is release-, workflow-, or coverage-related, also inspect the matching `.github/workflows/*.yml` and `scripts/build/ci/*.ps1` files. 5. Preserve the Nova build model: use `project.json` and Nova commands for build/test/package/release behavior, and do not create hand-written source `.psm1` or module `.psd1` files. 6. Inspect `project.json` `Manifest.PowerShellHostVersion` before changing PowerShell code, tests, or examples, and keep the implementation compatible with that target. 7. Implement the smallest maintainable fix. -8. Use `.github/instructions/code-quality-matrix.instructions.md` for changed source/helper scripts and `.github/instructions/testing-policy.instructions.md` for changed tests; keep new or heavily changed code short, single-purpose, low-duplication, and easy to scan unless the scope explicitly justifies otherwise. -9. Follow `.github/instructions/psscriptanalyzer.instructions.md` as the ScriptAnalyzer workflow source of truth. Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` and `./run.ps1`, and use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repository-approved settings. -10. Do not add PSScriptAnalyzer excluded rules, suppressions, or ad hoc analyzer settings that hide findings; fix analyzer findings in the code. -11. If `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before handoff instead of only reporting the failure. -12. Keep file/function ownership explicit: one externally called function per file, with private-file extras limited to related same-file top-level support helpers, keep the file name aligned to the entry function, and do not declare functions inside functions. -13. Before handoff, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the bottom. -14. Add or update the matching source-mirrored Pester file for every changed `src/**/*.ps1` file; if the behavior is genuinely cross-cutting, document which integration/guardrail test owns it and why a mirrored unit test is not practical. -15. 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 because it can bypass Nova's build/import/StrictMode flow. -16. For public commands, keep unit coverage in `tests/public/.Tests.ps1` and keep per-command integration ownership in `tests/public/.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. -17. Add or update valid PlatyPS-compatible help under `docs/NovaModuleTools/en-US/` when public commands or public classes change. Use `New-MarkdownCommandHelp` for new help, `Update-MarkdownCommandHelp` after command-surface changes, and `Test-MarkdownCommandHelp` before handoff; do not replace command help with plain Markdown prose. -18. For every new public entry point, create its matching help file immediately in the same change. -19. Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, `RELEASE_NOTE.md`, help docs, and `docs/*.html` as applicable. -20. If a commit message is requested, derive it from `$GIT_BRANCH_NAME` and the implemented change using the repository's Conventional Commit rules. -21. Run the relevant validation, then summarize what changed, why, and how it was verified. -22. If that summary is returned as Markdown or copy-ready UI output, format it according to the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). +8. Implementation phase: use `.github/instructions/code-quality-matrix.instructions.md` for changed source/helper scripts and `.github/instructions/testing-policy.instructions.md` for changed tests. Apply the short, single-purpose, low-duplication, easy-to-scan quality rules to any file where more than about 20% of lines are added or modified. The scope justifies an exception only when the issue text or an accepted design document explicitly states that a larger or more complex implementation is required. +9. During implementation, follow `.github/instructions/psscriptanalyzer.instructions.md` as the ScriptAnalyzer workflow source of truth. Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` and `./run.ps1`, and use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repository-approved settings. +10. During implementation, do not add PSScriptAnalyzer excluded rules, suppressions, or ad hoc analyzer settings that hide findings; fix analyzer findings in the code. +11. During implementation, keep file/function ownership explicit: one externally called function per file, with private-file extras limited to related same-file top-level support helpers, keep the file name aligned to the entry function, and do not declare functions inside functions. +12. During implementation, add or update the matching source-mirrored Pester file for every changed `src/**/*.ps1` file. If the behavior under test requires a fully built and imported module, depends on the interaction of three or more distinct source files, or cannot be isolated with mocks without rewriting the implementation, it qualifies as cross-cutting. In that case, document in the test file which integration or guardrail test covers it and why unit isolation is impractical. +13. During implementation, for public commands, keep unit coverage in `tests/public/.Tests.ps1` and keep per-command integration ownership in `tests/public/.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. +14. During implementation, add or update valid PlatyPS-compatible help under `docs/NovaModuleTools/en-US/` when public commands or public classes change. Use `New-MarkdownCommandHelp` for new help, `Update-MarkdownCommandHelp` after command-surface changes, and `Test-MarkdownCommandHelp` before handoff; do not replace command help with plain Markdown prose. +15. During implementation, for every new public entry point, create its matching help file immediately in the same change. +16. Pre-handoff verification phase: after completing all implementation steps, run the pre-handoff verification pass over every file touched during implementation, including files added in earlier steps. +17. In that verification phase, if `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before handoff instead of only reporting the failure. +18. In that verification phase, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the bottom. +19. In that verification phase, 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 because it can bypass Nova's build/import/StrictMode flow. +20. If `Invoke-NovaTest` or `Test-NovaBuild` reports test failures, fix the failures before handoff. Do not summarize or hand off with known failing tests. If a failure is pre-existing and unrelated to the current change, document it explicitly in the handoff summary with the test name and a brief explanation of why it is out of scope. +21. Review `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, `RELEASE_NOTE.md`, help docs, and `docs/*.html` as applicable. +22. If a commit message is requested, derive it from `$GIT_BRANCH_NAME` and the implemented change using the repository's Conventional Commit rules. +23. If the summary will be returned as Markdown or copy-ready UI output, invoke the `markdown-authoring` skill before producing that final summary and format the handoff accordingly. +24. Run the relevant validation, then summarize what changed, why, and how it was verified. ## Repository-specific reminders diff --git a/.github/prompts/improve-test-coverage.prompt.md b/.github/prompts/improve-test-coverage.prompt.md index 7208c858..855b3993 100644 --- a/.github/prompts/improve-test-coverage.prompt.md +++ b/.github/prompts/improve-test-coverage.prompt.md @@ -7,21 +7,28 @@ Improve changed-code coverage in NovaModuleTools without lowering maintainabilit ## Required process 1. Identify the exact uncovered file and line or branch. -2. Read the nearby production code and the most relevant existing test/support files. -3. Place new tests in the source-mirrored path under `tests/` by default: one focused `.Tests.ps1` file per covered `src/**/*.ps1` file. -4. Use an existing guardrail or integration test only when it intentionally owns genuinely cross-cutting behavior, and document that ownership in the handoff. -5. Use `.github/instructions/testing-policy.instructions.md` as the test-design source of truth; keep new or heavily changed tests focused, isolated, and easy to scan. -6. Follow `.github/instructions/psscriptanalyzer.instructions.md` when test code or test helpers change. Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` for repo-standard analyzer runs, and use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repo-approved settings. -7. Add the smallest test that proves the missing behavior. -8. If setup is duplicated, refactor the tests before adding more assertions. -9. Re-run `Invoke-NovaTest` for unit coverage, then `Test-NovaBuild` when build-validation integration ownership changed, then the repository quality loop if code changed. Do not validate a Nova-managed project with direct `Invoke-Pester`. -10. Recheck CodeScene coverage or Code Health if that was the original failure. +2. If no uncovered lines or branches are found, report that coverage is already complete and halt. If `artifacts/coverage.xml` is missing or stale, regenerate it by running `Invoke-NovaTest` before proceeding. +3. Read the nearby production code and the most relevant existing test/support files. +4. Place new tests in the source-mirrored path under `tests/` by default: one focused `.Tests.ps1` file per covered `src/**/*.ps1` file. If no corresponding `.Tests.ps1` file exists yet, create it with the standard file header and an empty `Describe` block before adding the first test. Do not add tests to an unrelated existing file. +5. Use an existing guardrail or integration test only when it intentionally owns genuinely cross-cutting behavior. When built-module behavior of a single public command needs validation, use `tests/public/.Integration.Tests.ps1` instead. For cross-cutting ownership, add a comment at the top of the integration test file in the format `# Cross-cutting owner: `. +6. Use `.github/instructions/testing-policy.instructions.md` as the test-design source of truth; keep new or heavily changed tests focused, isolated, and easy to scan. +7. Follow `.github/instructions/psscriptanalyzer.instructions.md` when test code or test helpers change. Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` for repo-standard analyzer runs, and use direct `Invoke-ScriptAnalyzer` only for focused local checks that reuse the repo-approved settings. +8. Add the smallest test that proves the missing behavior. +9. If setup is duplicated, refactor the tests before adding more assertions. +10. Validate in this order: + - Always run `Invoke-NovaTest`. + - If `Invoke-NovaTest` exits with an error or test failures, stop immediately, report the failure output verbatim, and do not proceed. + - Run `Test-NovaBuild` only if any `*.Integration.Tests.ps1` file was added, removed, or had its `# Cross-cutting owner: ` comment added or removed. + - If `Test-NovaBuild` exits with an error or test failures, stop immediately, report the failure output verbatim, and do not proceed. + - Run the repository quality loop only if any `src/**/*.ps1` production file was modified. + - Never use `Invoke-Pester` directly for Nova-managed validation. +11. Recheck CodeScene coverage or Code Health if that was the original failure. If the original failure type is not stated in the conversation, recheck CodeScene as the default final step. ## Repository-specific reminders - Many tests expect a built `dist/NovaModuleTools` module. - The CI coverage flow writes `artifacts/coverage.xml`. - Use `Invoke-NovaTest` for unit coverage validation and `Test-NovaBuild` for build-validation integration coverage; direct `Invoke-Pester` can miss Nova-specific strict-mode behavior. -- Keep public command unit coverage in `tests/public/.Tests.ps1` and per-command integration ownership in `tests/public/.Integration.Tests.ps1` when built-module behavior itself needs validation. +- Keep public command unit coverage in `tests/public/.Tests.ps1`. Use `tests/public/.Integration.Tests.ps1` when built-module behavior of that public command needs validation, and reserve existing cross-cutting guardrail or integration tests for behavior that intentionally spans multiple commands or workflows. - For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves `ShouldProcess`, routing, and output behavior. - Do not "fix" coverage by weakening assertions or suppressing CodeScene warnings. diff --git a/.github/prompts/prepare-release.prompt.md b/.github/prompts/prepare-release.prompt.md index 7879a164..38028a35 100644 --- a/.github/prompts/prepare-release.prompt.md +++ b/.github/prompts/prepare-release.prompt.md @@ -6,20 +6,20 @@ Prepare release-related changes in NovaModuleTools without publishing or tagging ## Required process -1. **Before any other action:** invoke the `skill` tool for both `markdown-authoring` and `release-and-changelog`. This is a blocking requirement — do not read files or produce output until both skills are loaded. -2. Read `CHANGELOG.md`, `RELEASE_NOTE.md`, `project.json`, `README.md`, `CONTRIBUTING.md`, `.github/pull_request_template.md`, and `.github/workflows/Publish.yml`. -2. Inspect the touched versioning, package, publish, or release tests. -3. Confirm whether the change affects stable releases, prereleases, or both. -4. Update changelog, release notes, and contributor docs as needed. -5. Use only the official Keep a Changelog section types in `CHANGELOG.md` and `RELEASE_NOTE.md`: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`. +1. **Before any other action:** invoke the `skill` tool for both `markdown-authoring` and `release-and-changelog`. This is a blocking requirement — do not read files or produce output until both skills are loaded. If either skill tool invocation fails or returns an error, stop immediately and report: `Required skill [name] could not be loaded. Please resolve this before continuing.` Do not proceed with any subsequent steps. +2. Read `CHANGELOG.md`, `RELEASE_NOTE.md`, `project.json`, `README.md`, `CONTRIBUTING.md`, `.github/pull_request_template.md`, and `.github/workflows/Publish.yml`. If any required file is not found, stop and report which files are missing before proceeding. Do not create files that do not already exist unless explicitly instructed. +3. Identify any test files in the repository whose names or content relate to versioning, packaging, publishing, or release logic, and review them to understand the intended behavior being validated. +4. Confirm whether the change affects stable releases, prereleases, or both. Based on the nature of the changes, propose the new version string using semantic versioning: breaking changes = major, new public API = minor, fixes or internal changes = patch. Use this version string consistently in all subsequent file updates. +5. Update `CHANGELOG.md` to reflect the changes identified in the prior steps. Update `RELEASE_NOTE.md` only for public interface, configuration, or migration changes. Update `CONTRIBUTING.md` only if the release process, versioning scheme, or contribution workflow has changed. +6. Use only the official Keep a Changelog section types in `CHANGELOG.md` and `RELEASE_NOTE.md`: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`. - Do not create custom headings such as `Documentation`; place documentation-related release notes under the official type that best matches the actual impact. -6. Check whether `RELEASE_NOTE.md` needs the placeholder rule under `## [Unreleased]`: - - If there are no real public API or workflow changes, ensure `### Added` contains exactly `No public API or workflow changes in this release. Internal maintenance only.` - - If there are real release-note entries, remove that placeholder. -7. Keep `RELEASE_NOTE.md` free of compare-link footer URLs. -8. Validate the relevant release or versioning path. -9. Summarize the result using the exact structure from `.github/pull_request_template.md`. -10. Make the summary concise, reviewer-focused, directly reusable, and compliant with the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`) when the output is returned as Markdown. + - If `CHANGELOG.md` already contains non-standard section headings in existing versioned entries, do not modify those historical entries. Only enforce the official section type rule for the `[Unreleased]` section. +7. Check whether `RELEASE_NOTE.md` needs the placeholder rule under `## [Unreleased]`. This placeholder is already formatted under the official `### Added` heading and is exempt from step 6 content-type guidance — do not reclassify it. + - 7a. If there are no real public API or workflow changes, ensure `### Added` contains exactly `No public API or workflow changes in this release. Internal maintenance only.` + - 7b. If there are real release-note entries, remove that placeholder. +8. Keep `RELEASE_NOTE.md` free of compare-link footer URLs. +9. Verify that the version string in `project.json` matches the latest versioned heading in `CHANGELOG.md`, and confirm that `.github/workflows/Publish.yml` references the correct version source. +10. Summarize the result using the exact structure from `.github/pull_request_template.md`. For sections in the pull request template that are not applicable to this release preparation, write `N/A` rather than omitting the section or leaving it blank. Make the summary concise, reviewer-focused, directly reusable, and compliant with the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`) when the output is returned as Markdown. ## Repository-specific reminders diff --git a/.github/prompts/review-change.prompt.md b/.github/prompts/review-change.prompt.md index 619a692f..9041e4a8 100644 --- a/.github/prompts/review-change.prompt.md +++ b/.github/prompts/review-change.prompt.md @@ -2,20 +2,23 @@ > Invoke with `@.github/prompts/review-change.prompt.md`. Delegates to the `reviewer` agent. -Review a NovaModuleTools change set with emphasis on correctness, maintainability, validation, and workflow safety. +Review a NovaModuleTools change set with emphasis on correctness, maintainability, validation, and workflow safety. If the diff contains no files matching any checked pattern (no `src/**/*.ps1`, test, or docs files), state explicitly which checks were not applicable and confirm that the remaining checks (changelog, PR template, release automation) were still performed. ## Required process -1. **Before any other action:** invoke the `skill` tool for `markdown-authoring` when the review output will be returned as copy-ready Markdown. This is a blocking requirement — load the skill before reading files or producing output. -2. Start with the highest-risk public command, workflow, or release path in the diff. +1. **Before any other action:** always invoke the `skill` tool for `markdown-authoring` before producing output unless the user explicitly requests plain text. This is a blocking requirement. If the `skill` tool for `markdown-authoring` returns an error or is unavailable, stop and report: "Could not load markdown-authoring skill. Review cannot proceed until the skill is available." Do not produce review output without it. 2. Compare the changed files against the relevant repository instructions and skills. -3. Check changed `src/**/*.ps1` against `.github/instructions/code-quality-matrix.instructions.md` and `tests/**/*.ps1` against `.github/instructions/testing-policy.instructions.md`. -4. Check changed PowerShell validation flow against `.github/instructions/psscriptanalyzer.instructions.md`; flag direct analyzer usage that bypasses the repository wrapper or repo-approved settings without a clear reason. -5. Check changed `docs/NovaModuleTools/en-US/*.md` against `.github/instructions/platyps-help.instructions.md` when command help was added or updated; flag files that do not follow the `New-MarkdownCommandHelp` / `Update-MarkdownCommandHelp` / `Test-MarkdownCommandHelp` workflow, miss a new public entry point's matching help file, or break the required PlatyPS section structure. -6. Check whether tests, docs, and changelog updates match the change, and flag Nova-managed validation that bypasses `Invoke-NovaTest` or `Test-NovaBuild` with direct `Invoke-Pester`. -7. Call out the smallest set of meaningful issues first. -8. Note any missing validation or follow-up work. -9. If the review is returned as Markdown or copy-ready UI text, format it according to the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`). +3. If a referenced instructions or skills file cannot be read, stop and report which file is missing before continuing. Do not proceed with the affected check using assumed content. +4. Start with the highest-risk public command, workflow, or release path in the diff. +5. Check changed `src/**/*.ps1` against `.github/instructions/code-quality-matrix.instructions.md` and `tests/**/*.ps1` against `.github/instructions/testing-policy.instructions.md`. +6. Check changed PowerShell validation flow against `.github/instructions/psscriptanalyzer.instructions.md`; flag direct analyzer usage that bypasses the repository wrapper or repo-approved settings without a clear reason. +7. When command help was added or updated in changed `docs/NovaModuleTools/en-US/*.md`, check those files against `.github/instructions/platyps-help.instructions.md`. +8. Verify changed help files follow the `New-MarkdownCommandHelp` / `Update-MarkdownCommandHelp` / `Test-MarkdownCommandHelp` workflow. +9. Confirm every new public entry point has a matching help file. +10. Confirm required PlatyPS section structure is intact. +11. Check whether tests, docs, and changelog updates match the change, and flag Nova-managed validation that bypasses `Invoke-NovaTest` or `Test-NovaBuild` with direct `Invoke-Pester`. +12. List the top 3-5 highest-severity issues first, each with a one-sentence rationale for its priority ranking. +13. Note any missing validation or follow-up work. ## Repository-specific reminders @@ -23,4 +26,3 @@ Review a NovaModuleTools change set with emphasis on correctness, maintainabilit - Watch for CLI vs PowerShell wording drift. - Watch for CodeScene maintainability regressions in tests. - Treat publish/release automation edits as high-risk even when the diff is small. -- Follow the `markdown-authoring` skill (`.github/skills/markdown-authoring/SKILL.md`) when the review output is intended to be pasted as Markdown. diff --git a/.github/skills/building-maintainable-code/SKILL.md b/.github/skills/building-maintainable-code/SKILL.md index 76089abb..50ffa8fd 100644 --- a/.github/skills/building-maintainable-code/SKILL.md +++ b/.github/skills/building-maintainable-code/SKILL.md @@ -34,6 +34,7 @@ The companion instruction file is `.github/instructions/code-quality-matrix.inst ## Guideline order and precedence Apply lower-level guidelines first. Unit-level structure fixes (Guidelines 1–4) usually make the component-level work (5–8) smaller and safer. +When satisfying a lower-numbered guideline would force a violation of a higher-numbered one, resolve the higher-numbered violation immediately in the same step before moving on. If both violations cannot be resolved simultaneously, prefer the lower-numbered guideline and document the remaining finding as a follow-up task. 1. Write short units of code 2. Write simple units of code @@ -54,7 +55,7 @@ Apply lower-level guidelines first. Unit-level structure fixes (Guidelines 1–4 | 2 Simple units | ≤ 4 branch points per function (cyclomatic complexity ≤ 5) | | 3 Write once | no identical block ≥ 6 functional lines repeated anywhere | | 4 Small interfaces | ≤ 4 parameters per function (`[CmdletBinding()]` common parameters not counted) | -| 5 Separate concerns | one externally called function per file, matching the file name | +| 5 Separate concerns | one externally called function per file, matching the file name; file-local sibling helpers are allowed | | 6 Loose coupling | infrastructure only via approved private adapters | | 7 Balanced components | no `src/private//` absorbing unrelated responsibilities | | 8 Small codebase | no dead/commented-out code; reuse over custom utilities | @@ -64,11 +65,12 @@ Apply lower-level guidelines first. Unit-level structure fixes (Guidelines 1–4 ## Implementation playbook Follow these steps for any non-trivial PowerShell change. +If a step produces no findings, record it as "✓ No action required" and proceed to the next step. After all steps pass cleanly, confirm that the file is compliant and proceed directly to the Verification section. -1. Read the changed function and surrounding file. Note where it sits in `src/public/`, `src/private//`, or `scripts/`. +1. Read the changed function and surrounding file. Note where it sits in `src/public/`, `src/private//`, or `scripts/`. Files under `scripts/` follow the same 10 guidelines and thresholds as `src/` files unless a script is a thin entry-point wrapper of ≤ 10 lines, in which case only Guidelines 3, 8, and 10 are enforced. 2. For each new or heavily changed function, walk the checklist below in order. -3. If a step requires a refactor, make it the smallest structural step that fixes the specific finding. Do not bundle unrelated cleanup. -4. After meaningful steps, run `./run.ps1` (analyzer → build → `Invoke-NovaTest` → `Test-NovaBuild`). For risk-bearing files, also run `code_health_review` from the `safeguarding-ai-generated-code` skill. +3. If a step requires a refactor, make it the smallest structural step that fixes the specific finding. Do not fix issues belonging to a different guideline number than the one currently being addressed. Each commit or change should reference exactly one guideline finding. +4. After meaningful steps, run `./run.ps1` (analyzer → build → `Invoke-NovaTest` → `Test-NovaBuild`). If `./run.ps1` exits with a non-zero code or any test fails, stop all further guideline steps, diagnose and fix the failure before continuing, and do not proceed to the next guideline step until the full pipeline is green. For any file that calls external infrastructure (`git`, web requests, file IO), modifies public API surface, or has a function body exceeding 20 lines before refactoring, also run `code_health_review` from the `safeguarding-ai-generated-code` skill. 5. Before handoff, normalize every changed text file to exactly one trailing newline. ### Step 1 — Short units (≤ 15 lines) @@ -77,7 +79,7 @@ Counting rule: only the body lines count. Exclude `function`, opening `{`, closi Refactor options in PowerShell: -- Extract the most distinct top-of-function block into a named helper. Place it as a sibling top-level function in the same private file if it belongs to the entry function. +- Extract the most distinct top-of-function block into a named helper. Place it as a sibling top-level function in the same private file only when it has no callers outside that file and belongs to the entry function. - Replace inline preparation with `Resolve-*`, `Get-*Context`, or `Build-*Request` helpers that return the prepared object. - Move repeated formatting into `Format-*` helpers. @@ -175,10 +177,11 @@ function Invoke-NovaTestWorkflow { ``` Use parameter sets only for genuinely different calling shapes, not to hide 8 parameters in one signature. +After completing Steps 1–4, re-read the changed files from scratch before proceeding to Steps 5–8. Component-level findings identified before unit fixes may no longer apply or may have shifted scope. ### Step 5 — Separate concerns in modules -- One externally called function per file, matching the file name. +- One externally called function per file, matching the file name. Additional top-level functions in that file must be file-local helpers with no callers outside the file. - Helpers used only inside the file stay as sibling top-level functions in the same file. Never nest functions. - When a private file mixes lookup, mutation, formatting, validation, and transport, split it by concern. @@ -202,7 +205,7 @@ Use parameter sets only for genuinely different calling shapes, not to hide 8 pa ### Step 9 — Automate tests - Add or update one source-mirrored `tests//.Tests.ps1` for every changed `src/**/*.ps1` file. -- Cover happy path plus the meaningful unhappy/invalid/boundary cases that the change introduces. +- Cover (1) the happy path, (2) every branch that returns early or throws, and (3) any input boundary explicitly referenced in the function's parameter validation or documentation comments. - Validate with `Invoke-NovaTest` for unit behavior and `Test-NovaBuild` for build-validation integration behavior. Do not call `Invoke-Pester` directly. - For full rules, follow the `pester-testing` skill and `.github/instructions/testing-policy.instructions.md`. diff --git a/.github/skills/codescene-quality/SKILL.md b/.github/skills/codescene-quality/SKILL.md index 76c4a17f..d059b7ee 100644 --- a/.github/skills/codescene-quality/SKILL.md +++ b/.github/skills/codescene-quality/SKILL.md @@ -25,12 +25,14 @@ Use the narrower sibling skills when the task is more specific: ## Expected practices - Treat Code Health as the repository's authoritative maintainability signal. -- Aim for Code Health `10.0` on touched files, not merely "good enough." +- Aim to improve touched files toward Code Health `10.0` in their post-change state, not merely "good enough." +- The `10.0` target applies to any file you touch; if a file already starts below `10.0`, improve it as far as safe incremental refactoring allows and document the before/after score delta. +- If incremental refactoring cannot reach `10.0` without a large structural rewrite, document the achieved score, cite the remaining CodeScene finding, and recommend the rewrite as follow-up work instead of doing it immediately. - Treat CodeScene findings as actionable maintainability signals. -- If CodeScene tooling is unavailable locally, continue with the normal repository validation flow and continue silently; pull requests and CI remain the effective CodeScene gate. +- If CodeScene tooling is unavailable locally, continue with the normal repository validation flow without blocking progress or surfacing an error, but note once that CI and PR gates remain the effective CodeScene check. - Fix duplicated test structure by extracting or parameterizing setup. -- Add the smallest test that covers the missing changed-code branch. -- Prefer incremental refactors over large rewrites. +- Add the minimal test, ideally a single focused test function with no shared setup beyond what already exists, that executes the uncovered changed-code branch and asserts its observable outcome. +- Prefer incremental refactors over large rewrites unless the current task explicitly calls for a larger structural change. ## Common pitfalls @@ -40,8 +42,12 @@ Use the narrower sibling skills when the task is more specific: ## Verification +Always: - Re-run the affected test file(s) +- Run `./run.ps1` after code changes + +When local CodeScene tooling is available: - Re-run the CodeScene file review after the refactor when local CodeScene tooling is available - Run the pre-commit safeguard before suggesting a commit when local CodeScene tooling is available - Run a change-set analysis before suggesting a PR for larger branch work when local CodeScene tooling is available -- Run `./run.ps1` after code changes +- If any verification command fails with an error unrelated to the code change itself, such as a missing dependency or permission error, surface the exact error output to the user and pause before suggesting further steps. diff --git a/.github/skills/docs-site/SKILL.md b/.github/skills/docs-site/SKILL.md index ec145ea2..7c113e40 100644 --- a/.github/skills/docs-site/SKILL.md +++ b/.github/skills/docs-site/SKILL.md @@ -22,10 +22,13 @@ Use this skill when changing `docs/*.html`, end-user examples, installation guid - Write `docs/*.html` for end users, not for contributors. - Use CLI-oriented examples when the workflow has a `nova` variant. -- Mention PowerShell cmdlets only when no CLI equivalent exists for that scenario. +- Mention PowerShell cmdlets only when the scenario has no direct one-to-one `nova` CLI command that achieves the same result in a single step. +- If the `nova` CLI command and its PowerShell cmdlet equivalent behave differently in a way end users would observe (for example different defaults, output format, or supported platforms), document both surfaces and note the difference explicitly within the appropriate `data-command-visibility` blocks. - Keep installation guidance explicit about PowerShell-only steps such as `Install-Module`. -- On pages with the command-surface toggle, keep option/parameter wording aligned with the active surface by using `data-command-visibility="command-line"` and `data-command-visibility="powershell"` blocks instead of one shared paragraph that mixes CLI flags with PowerShell parameters. +- On pages with the command-surface toggle, wrap any text containing CLI flags in `data-command-visibility="command-line"` blocks and any text containing PowerShell parameters in `data-command-visibility="powershell"` blocks. +- Do not write shared paragraphs that mention both CLI flags and PowerShell parameters outside of these visibility blocks. - Recheck the matching command-help markdown when public behavior changes. +- If the matching command-help markdown in `docs/NovaModuleTools/en-US/*.md` is found to be out of sync with the current public behavior, update it in the same PR and note the change in `CHANGELOG.md`. ## Common pitfalls @@ -40,4 +43,4 @@ Use this skill when changing `docs/*.html`, end-user examples, installation guid - Read the touched HTML page as an end-user flow - Toggle the page mentally between PowerShell and command-line surfaces and confirm the visible option/parameter names still match that surface - Check whether the same behavior is documented consistently in help markdown or contributor docs -- Use docs-only validation when no executable behavior changed +- When no executable behavior changed, limit verification to the three HTML/markdown review steps above and skip any code-execution or changelog review steps diff --git a/.github/skills/github-actions/SKILL.md b/.github/skills/github-actions/SKILL.md index addb10bf..f256d301 100644 --- a/.github/skills/github-actions/SKILL.md +++ b/.github/skills/github-actions/SKILL.md @@ -23,7 +23,8 @@ Use this skill when changing CI workflows, artifact handling, CodeScene coverage - Read the whole affected workflow before editing a single step. - Keep artifact names and paths aligned with the scripts that produce them. - Treat `main` and `develop` release behavior in `Publish.yml` as deliberate and branch-specific. -- Keep CI output human-readable in the step summary when relevant. +- If a change must alter release behavior for both `main` and `develop` at once, explicitly justify the change for each branch independently in comments or the PR description before editing `Publish.yml`. +- Always emit a step summary (`$GITHUB_STEP_SUMMARY`) for steps that produce test results, coverage reports, or publish outcomes. Omit summaries for purely mechanical setup steps such as checkout or dependency restore. ## Common pitfalls @@ -37,3 +38,4 @@ Use this skill when changing CI workflows, artifact handling, CodeScene coverage - Re-run relevant local scripts when possible - Re-read the touched workflow and script pair together - Run `./run.ps1` if repo code or workflow helper scripts changed +- If local execution of `./run.ps1` is not possible, document the untested assumption explicitly in the PR description and flag it for reviewer verification. diff --git a/.github/skills/guiding-refactoring-with-code-health/SKILL.md b/.github/skills/guiding-refactoring-with-code-health/SKILL.md index 4c6b5d50..f6234089 100644 --- a/.github/skills/guiding-refactoring-with-code-health/SKILL.md +++ b/.github/skills/guiding-refactoring-with-code-health/SKILL.md @@ -25,12 +25,15 @@ Do not use this skill when the task is to rank project-wide priorities. Use Code ## Implementation 1. Run `code_health_review` on the target file. +If `code_health_review` returns no significant structural findings, report this to the user and do not proceed with refactoring unless the user provides a specific goal beyond the measured findings. 2. Record the current `code_health_score` so the refactoring starts from a measurable baseline. +If `code_health_review` or `code_health_score` returns an error or no data, inform the user immediately and do not proceed with any refactoring steps until a valid baseline can be established. 3. Identify the highest-leverage structural problems, such as excessive responsibilities, deep nesting, low cohesion, or hard-to-follow control flow. 4. Propose 3 to 5 small structural refactor steps, not a single rewrite. -5. After each meaningful step, re-run `code_health_review` to see whether the targeted structural problems were reduced. +5. After each of the proposed refactor steps is implemented, re-run `code_health_review` to see whether the targeted structural problems were reduced. +If `code_health_review` shows new structural issues introduced by the step, or if `code_health_score` has not improved, pause and explain the regression to the user before proceeding. Do not continue to the next step until the user confirms how to proceed. 6. Use `code_health_score` as the compact checkpoint to confirm directional improvement across iterations. -7. Stop only when the targeted structural issues are substantially reduced and the score has measurably improved, or when the user explicitly accepts a partial uplift. +7. Stop only when the targeted structural issues are reduced by at least half as measured by the number of flagged structural issues in `code_health_review` and the score has improved by at least 0.5 points on the `code_health_score`, or when the user explicitly accepts a partial uplift. ## Common mistakes diff --git a/.github/skills/markdown-authoring/SKILL.md b/.github/skills/markdown-authoring/SKILL.md index 1a6e8f0d..96e5fb8e 100644 --- a/.github/skills/markdown-authoring/SKILL.md +++ b/.github/skills/markdown-authoring/SKILL.md @@ -25,18 +25,21 @@ Use this skill when producing Markdown files in the repository or Markdown outpu ## Expected practices - Write valid Markdown that is easy to paste without cleanup. -- Use `~~~` as the outer wrapper when the whole response must be one copy-ready Markdown block. +- Use `~~~` as the outer wrapper when the task is producing one copy-ready Markdown block for release summaries, PR-template-shaped text, contributor docs, or reusable prompt output. - Use triple backticks inside that wrapper for code examples. - Keep headings, lists, and code fences balanced and readable. - Prefer concise Markdown that fits the required template or document structure. ## Copy-safe fence rules -- When the entire response must be wrapped, start with a line containing exactly `~~~` and end with a line containing exactly `~~~`. -- **Any text outside the `~~~` block is a rule violation.** This includes greetings, preambles, "here is the summary" lead-ins, observations appended after the block, and any other prose. The response must be the `~~~` block and nothing else. +- Apply the `~~~` wrapper whenever the task is a release summary, PR-template-shaped text, contributor doc, or reusable prompt output. Do not apply it for conversational answers or inline file edits. +- When the `~~~` wrapper is required, start with a line containing exactly `~~~` and end with a line containing exactly `~~~`. +- **When the `~~~` wrapper is required, any text outside the `~~~` block is a rule violation.** This includes greetings, preambles, "here is the summary" lead-ins, observations appended after the block, and any other prose. In all other cases, normal prose responses are allowed. - Inside the wrapped block, use normal Markdown. -- For inner code examples, use triple backticks and include a language when helpful. +- If contextual explanation is necessary alongside a copy-ready block, place it inside the `~~~` wrapper as a Markdown blockquote or comment rather than outside the block. Never emit prose outside the `~~~` block when the wrapper is required. +- For inner code examples, use triple backticks and always include a language identifier unless the content is plain text or has no established language identifier. - Never use triple backticks as the outer wrapper when the content itself may already contain fenced code blocks. +- If the content to be wrapped itself contains a `~~~` fence, escape or represent it as a code span or indented block, and add a comment `` so the author can restore it manually. ## Copy-safe wrapper example @@ -70,3 +73,4 @@ Or from the CLI: - Re-read the output as raw Markdown before finalizing it - Check that every opening fence has a matching closing fence - If a template is authoritative, verify the generated Markdown follows it exactly +- If the available information is insufficient to populate a required template field, insert a clearly marked placeholder such as `` rather than omitting the field or inventing content, and note the missing fields inside the `~~~` block as a Markdown comment when the wrapper is required diff --git a/.github/skills/pester-testing/SKILL.md b/.github/skills/pester-testing/SKILL.md index 2f15aa27..617666c3 100644 --- a/.github/skills/pester-testing/SKILL.md +++ b/.github/skills/pester-testing/SKILL.md @@ -20,18 +20,41 @@ Use this skill when adding tests, closing coverage gaps, fixing regressions, or ## Expected practices +Use `.github/instructions/testing-policy.instructions.md` for the general test-design rules. Apply the repository-specific conventions below for file layout, import strategy, validation entrypoints, and exceptions. + +### General style + - Match existing `Describe` / `It` naming style. - Prefer support helpers for repeated setup. -- For new and migrated tests, dot-source `src/**/*.ps1` files directly in `BeforeAll`. Do not `Import-Module $project.OutputModuleDir` in mirrored unit tests, and do not use `InModuleScope NovaModuleTools { ... }` - the function under test is already in scope after dot-sourcing. -- Use `Invoke-NovaTest` as the unit-test entrypoint and `Test-NovaBuild` as the build-validation integration-test entrypoint in Nova-managed projects. Do not validate with direct `Invoke-Pester`, because it can miss the Nova build/import/StrictMode flow. +- Cover normal, boundary, and unhappy paths; isolate collaborators with mocks/stubs where needed; and extract setup or assertion helpers when a test stops being easy to scan. - Add coverage for both happy paths and explicit warnings/errors when behavior changed. + +### File layout + - For every new or changed `src/**/*.ps1` file, add or update one focused test file that mirrors the source path under `tests/`. -- Keep test files and helpers compatible with `project.json` `Manifest.PowerShellHostVersion`; if a project targets `5.1`, do not introduce PowerShell 7.x-only syntax, cmdlets, parameters, or APIs in the tests. -- Use `.github/instructions/testing-policy.instructions.md` as the test-design source of truth. Cover normal, boundary, and unhappy paths; isolate collaborators with mocks/stubs where needed; and extract setup or assertion helpers when a test stops being easy to scan. -- Keep shared setup in `tests/TestHelpers/` or `*TestSupport.ps1`; do not hide unrelated source-file coverage in broad catch-all test files. - Public command unit tests belong in `tests/public/.Tests.ps1`; public command integration ownership belongs in `tests/public/.Integration.Tests.ps1` when the built-module behavior itself needs coverage. +- Private function tests belong in `tests/private/.Tests.ps1`, mirroring the source path under `src/private/`. For example, a test for `src/private/quality/Initialize-NovaPesterCoverageConfiguration.ps1` belongs in `tests/private/quality/Initialize-NovaPesterCoverageConfiguration.Tests.ps1`. +- Keep shared setup in `tests/TestHelpers/` or `*TestSupport.ps1`; do not hide unrelated source-file coverage in broad catch-all test files. + +### Import strategy + +- For new and migrated tests, dot-source `src/**/*.ps1` files directly in `BeforeAll`. Do not `Import-Module $project.OutputModuleDir` in mirrored unit tests, and do not use `InModuleScope NovaModuleTools { ... }` - the function under test is already in scope after dot-sourcing. +- If you encounter an existing test file that uses `Import-Module $project.OutputModuleDir` or `InModuleScope NovaModuleTools`, migrate it to the dot-source pattern as part of the same change. If migration is out of scope for the current task, add a TODO comment in that test file and note it in your final handoff. + +### Validation entrypoints + +- Use `Invoke-NovaTest` as the unit-test entrypoint and `Test-NovaBuild` as the build-validation integration-test entrypoint in Nova-managed projects. Do not validate with direct `Invoke-Pester`, because it can miss the Nova build/import/StrictMode flow. + +### Version compatibility + +- Keep test files and helpers compatible with `project.json` `Manifest.PowerShellHostVersion`. +- If a project targets `5.1`, do not introduce PowerShell 7.x-only syntax, cmdlets, parameters, or APIs in the tests. +- If a project targets PowerShell 7.x or later, 7.x syntax and APIs are permitted. Always match the minimum version declared in `Manifest.PowerShellHostVersion` and avoid syntax requiring a higher version than declared. + +### Coverage exceptions + - For destructive or environment-coupled public commands, prefer safe `-WhatIf` integration coverage when that still proves command wiring, `ShouldProcess`, and output semantics. -- If a mirrored test is not practical because the behavior is genuinely cross-cutting, document the reason in the handoff and point to the owning integration or guardrail test. +- If a mirrored test is not practical because the behavior is genuinely cross-cutting, add a brief comment at the top of the owning test file that explains why a mirrored test is not practical and which integration or guardrail test provides coverage instead. ## Mirrored layout example diff --git a/.github/skills/powershell-module-development/SKILL.md b/.github/skills/powershell-module-development/SKILL.md index 1778cf93..fcb24aaf 100644 --- a/.github/skills/powershell-module-development/SKILL.md +++ b/.github/skills/powershell-module-development/SKILL.md @@ -29,18 +29,23 @@ Use this skill when changing public commands, private helpers, CLI routing suppo - Read `project.json` `Manifest.PowerShellHostVersion` before changing PowerShell code, tests, or examples, and keep new work compatible with that target. A `5.1` project must not receive PowerShell 7.x-only syntax, cmdlets, parameters, or APIs unless the change explicitly adds guarded compatibility handling. - Do not create or maintain hand-written module `.psm1` or module `.psd1` files in source; Nova generates those files under `dist/NovaModuleTools/`. - Preserve native PowerShell semantics. Keep Nova naming patterns on public commands, and give private helpers clear implementation-focused names instead of public-style `Invoke-Nova*`, `Get-Nova*`, or `Update-Nova*` naming. -- Keep one externally called function per file and match the file name to that function. In `src/private/`, additional related functions may stay only as same-file top-level support helpers called by that file's entry function; do not declare functions inside functions. -- Use `.github/instructions/code-quality-matrix.instructions.md` as the best-effort source-code maintainability guidance. Keep new or heavily changed code short, single-purpose, low-duplication, lightly nested, and split by clear responsibility; group related inputs instead of growing long parameter lists. +- Keep one externally called function per file and match the file name to that function. In `src/private/`, a file may contain additional top-level functions only when those functions are called exclusively by the file's primary entry function and are not referenced from any other file. If a helper is called from more than one file, extract it into its own same-named file. Do not declare functions inside functions. +- Use `.github/instructions/code-quality-matrix.instructions.md` as the authoritative source-code maintainability guidance. Apply all of its rules to new or heavily changed code. Keep that code short, single-purpose, low-duplication, lightly nested, and split by clear responsibility; group related inputs instead of growing long parameter lists. - Reuse existing workflow-context helpers and shared adapters. - Follow the repository's PowerShell style rules: 4-space indentation, same-line opening braces, restrained blank lines, full cmdlet names, and readable operator spacing. - Follow `.github/instructions/psscriptanalyzer.instructions.md` as the ScriptAnalyzer workflow source of truth. Prefer `./scripts/build/Invoke-ScriptAnalyzerCI.ps1` and `./run.ps1`, and use direct `Invoke-ScriptAnalyzer` only for focused local checks or deliberate analyzer-tooling work. - Keep ScriptAnalyzer strict: do not add excluded rules, suppression attributes, or settings that hide analyzer findings. - Keep `run.ps1`-style local checks 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 handoff instead of just reporting the failure. -- Before handoff, review every changed or generated text file and normalize it to exactly one trailing newline with no extra blank lines at the end. -- Add or update valid PlatyPS-compatible help under `docs/NovaModuleTools/en-US/` when public commands or public classes change. Always build and import the dist module first (`Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force`) before running `New-MarkdownCommandHelp` or `Update-MarkdownCommandHelp`, so PlatyPS writes the module name — not the command name — into `external help file` and `Module Name`. Use `Test-MarkdownCommandHelp` to validate structure before handoff instead of writing plain Markdown from scratch. +- If `run.ps1` or `Invoke-ScriptAnalyzerCI.ps1` reports ScriptAnalyzer findings, fix them before handoff instead of just reporting the failure. If a finding appears to be a false positive or conflicts with a rule explicitly required by this prompt, document the conflict in a code comment and escalate to the human reviewer instead of adding a suppression attribute or excluding the rule. +- Before handoff, review every source text file you created or modified under `src/`, `tests/`, `docs/`, and `scripts/` and normalize it to exactly one trailing newline with no extra blank lines at the end. Do not modify files under `dist/` or any file you did not directly change. +- Add or update valid PlatyPS-compatible help under `docs/NovaModuleTools/en-US/` when public commands or public classes change. Use this order: + 1. Build the module with `Invoke-NovaBuild`. + 2. Import the built module with `Import-Module ./dist/NovaModuleTools/NovaModuleTools.psd1 -Force`. + 3. Run `New-MarkdownCommandHelp` for new commands or `Update-MarkdownCommandHelp` for existing ones. + 4. Verify that `external help file` and `Module Name` reference the module name, not the command name. + 5. Run `Test-MarkdownCommandHelp` on all affected help files and fix any reported issues before handoff. - For every new public `src/public/*.ps1` file, create the matching help file immediately in the same change. -- Add or update the source-mirrored Pester test file for every changed `src/**/*.ps1` file. +- Add or update the source-mirrored Pester test file for every changed `src/**/*.ps1` file. Source-mirrored test files for private helpers live under `tests/private//.Tests.ps1`, mirroring the `src/private//` folder structure. Use the same `Describe` block name as the function under test. If no existing test file exists for a private helper you are changing, create it with at least one `Context` block covering the primary success path. - For public commands, keep unit coverage in `tests/public/.Tests.ps1` and keep per-command integration ownership in `tests/public/.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. @@ -51,7 +56,7 @@ Use this skill when changing public commands, private helpers, CLI routing suppo - Calling `git`, `Invoke-WebRequest`, `Update-Module`, or `$env:` from the wrong layer - Replacing explicit warning opt-ins with generic force semantics - Creating a root module `.psm1` or module manifest `.psd1` by hand instead of letting Nova generate them from `project.json` -- Grouping two externally called private helpers in one file instead of splitting them into separate same-named files +- Grouping two private helpers in one file when both are referenced from outside that file instead of splitting them into separate same-named files - Declaring helper functions inside another function instead of keeping related private helpers as sibling top-level functions in the file - Ignoring the source-code guidance and letting new or heavily changed functions grow long, deeply nested, duplicated, or multi-purpose without justification - Writing plain Markdown under `docs/NovaModuleTools/en-US/` that lacks YAML metadata or the PlatyPS structure expected by `Import-MarkdownCommandHelp` @@ -64,7 +69,7 @@ Use this skill when changing public commands, private helpers, CLI routing suppo ## Verification -- `Invoke-NovaTest` for unit-level behavior changes -- `Test-NovaBuild` when the change needs built-module or integration validation -- `tests/ArchitectureGuardrails.Tests.ps1` implications checked -- `pwsh -NoLogo -NoProfile -File ./run.ps1` +- Run `Invoke-NovaTest` for any change under `src/` or `tests/`. +- Run `Test-NovaBuild` additionally when a public command signature changed, packaging or manifest metadata changed, or integration tests were added or modified. +- Run `tests/ArchitectureGuardrails.Tests.ps1` for any structural change, including new files, renamed files, or changed function names. +- Always run `pwsh -NoLogo -NoProfile -File ./run.ps1` as the final gate before handoff. diff --git a/.github/skills/release-and-changelog/SKILL.md b/.github/skills/release-and-changelog/SKILL.md index 266bd5d9..5717c12a 100644 --- a/.github/skills/release-and-changelog/SKILL.md +++ b/.github/skills/release-and-changelog/SKILL.md @@ -25,15 +25,19 @@ Use this skill when working on semantic versioning, release automation, package - Keep unreleased entries readable and outcome-focused. - Keep `CHANGELOG.md` exhaustive and keep `RELEASE_NOTE.md` limited to interface-facing change summaries. -- Use only the official Keep a Changelog section types: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`. -- Do not create custom changelog headings such as `Documentation`; place documentation-related release notes under the official type that best matches the actual release impact. -- If `RELEASE_NOTE.md` has no public API or workflow changes under `## [Unreleased]`, keep the exact placeholder under `### Added`: `No public API or workflow changes in this release. Internal maintenance only.` -- If `RELEASE_NOTE.md` has real release-note entries, remove that placeholder. +- Use only the official Keep a Changelog section types: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security`, and choose the one that best matches the actual release impact. +- When the appropriate section type differs between `CHANGELOG.md` and `RELEASE_NOTE.md` for the same change, use the type that best describes the internal implementation in `CHANGELOG.md` and the type that best describes the public interface impact in `RELEASE_NOTE.md`. Document both choices in the PR description if they differ. +- If a single release change spans multiple section types, create separate entries under each relevant section type rather than combining them into one entry. +- Do not create custom changelog headings such as `Documentation`; place documentation-related release notes under the official type that best matches the actual release impact. For documentation-only changes with no behavior change, use `Fixed` if the docs corrected an error, `Changed` if existing doc content was revised, or `Added` if new documentation was introduced. If the documentation change accompanies a code change, include it in the same entry as that code change rather than creating a separate entry. +- `RELEASE_NOTE.md` placeholder rule: + 1. Check whether `## [Unreleased]` contains any entries describing public API or workflow changes. + 2. If no such entries exist, ensure the `### Added` section contains exactly this line: `No public API or workflow changes in this release. Internal maintenance only.` + 3. If real release-note entries exist, remove that placeholder line entirely. - Keep `RELEASE_NOTE.md` free of compare-link footer URLs. -- Use `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed`, and `Security` intentionally. -- Update an existing unreleased `Added` entry when a feature is still evolving before release. -- Verify whether stable and preview behavior differ. -- Shape release-preparation summaries so they fit the PR template directly. +- If a feature is still evolving before release, update its existing `Added` entry in `[Unreleased]` rather than adding a new entry. If no entry exists yet for that feature, create one and update it as the feature evolves. +- If stable and preview behavior differ, document both behaviors explicitly in `CHANGELOG.md` under separate notes or a clearly labeled sub-description so readers can distinguish them. +- Branch versioning roles: `main` is the stable release branch, so version bumps and changelog entries there reflect published stable releases. `develop` is the prerelease branch, so version bumps there use prerelease suffixes and changelog entries remain under `[Unreleased]` until merged to `main`. Never apply stable versioning actions to `develop` or prerelease actions to `main`. +- When writing release-preparation summaries, structure the text to match the sections in `.github/pull_request_template.md` so it can be pasted without reformatting. Specifically, align entries to the changelog and validation sections of that template. ## Common pitfalls diff --git a/.github/skills/safeguarding-ai-generated-code/SKILL.md b/.github/skills/safeguarding-ai-generated-code/SKILL.md index 0d7d9ecd..3b1bdf2e 100644 --- a/.github/skills/safeguarding-ai-generated-code/SKILL.md +++ b/.github/skills/safeguarding-ai-generated-code/SKILL.md @@ -26,11 +26,12 @@ Do not use this skill for broad refactoring discovery or project-level prioritiz ## Implementation 1. After each AI modification to a file, run `code_health_review` on that file. -2. If the review reports maintainability problems or regression risk, refactor the file in small steps and review it again. -3. When local CodeScene tooling is available, run `pre_commit_code_health_safeguard` before commit-oriented recommendations as a broader gate across staged or modified files. -4. When local CodeScene tooling is available, run `analyze_change_set` before PR-oriented recommendations as a final branch-level gate. -5. If local CodeScene tooling is unavailable, continue with the normal repository validation flow and continue silently; pull requests and CI remain the effective CodeScene gate. -6. If either later gate reports a regression, inspect the affected files with `code_health_review` and keep iterating until the issue is removed or the user explicitly accepts the risk. +2. Treat any CodeScene score degradation, any new code smell flagged as high-severity, or any function exceeding the configured complexity ceiling as a regression requiring remediation before proceeding. If the review reports maintainability problems or regression risk, refactor the file in small steps and review it again. If `code_health_review` returns an error or cannot analyse the file, such as an unsupported language or tool failure, notify the user, skip that file's automated gate, and flag it for manual review before commit. +3. If local CodeScene tooling is available, use this decision flow: + - For commit-oriented recommendations, run `pre_commit_code_health_safeguard`. If it reports a regression, enter the regression loop below. + - For PR-oriented recommendations, run `analyze_change_set`. If it reports a regression, enter the regression loop below. +4. If local CodeScene tooling is unavailable, do not warn the user or alter the recommendation flow; proceed as if the CodeScene step does not exist. If the user asks whether CodeScene was run, state that local tooling was unavailable and the check was skipped. +5. Regression loop: run `code_health_review` on each flagged file, refactor in small steps, and re-run the triggering gate. Repeat until the issue is removed or the user responds with a clear acknowledgement such as "I accept this risk" or "proceed despite the regression" after you have named the specific file and regression type. If the same regression persists after three consecutive refactor-and-review cycles without improvement, stop iterating, summarize the unresolved issue to the user, and ask whether to accept the risk or escalate. ## Common mistakes diff --git a/.github/skills/terminal-ux-design/SKILL.md b/.github/skills/terminal-ux-design/SKILL.md index b83d8b56..733823a0 100644 --- a/.github/skills/terminal-ux-design/SKILL.md +++ b/.github/skills/terminal-ux-design/SKILL.md @@ -23,7 +23,15 @@ The same underlying PowerShell code can present itself through two distinct user - **PowerShell cmdlet surface** — anything invoked as `Verb-Noun -Parameter` in a PowerShell session. Follow PowerShell conventions: approved verbs, `-Parameter` naming, `Write-*` streams, `Get-Help`, `-WhatIf` / `-Confirm`, pipeline-friendly output. - **CLI alias surface** — anything invoked as a unix-style command, including PowerShell aliases or wrapper functions that emulate a CLI (for example `nova --flag`). Follow CLI conventions: `--flag` / `-f`, subcommands, `--help`, predictable exit codes, `Ctrl+C` cancellation, text-stream output. -Decide which surface a command exposes before applying the per-principle guidance below. A single command may be reachable through both surfaces; in that case, evaluate each surface against its own conventions instead of blending them. +Use this evaluation protocol before applying the per-principle guidance below: + +1. Identify which surface the change touches: PowerShell cmdlet, CLI alias, or both. +2. For each identified surface, work through principles 1-10 using only the guidance for that surface. +3. Record any conflicts with Common Pitfalls and keep cmdlet and CLI evaluations as separate checklists; never merge their outputs. + +If the surface cannot be determined from the available context, ask the requester to clarify before applying per-surface guidance. Do not default to either surface silently. + +A single command may be reachable through both surfaces; in that case, evaluate each surface against its own conventions instead of blending them. ## Relevant surfaces @@ -47,7 +55,7 @@ This skill is intentionally surface-based rather than path-based, so it applies CLI: keep `--help` and ` --help` accurate and task-focused. 3. **Show progress visually** Long-running work should expose state, phases, and forward motion. - PowerShell cmdlets: use `Write-Progress` when work is meaningful enough to justify it. + PowerShell cmdlets: use `Write-Progress` when an operation runs longer than approximately 3 seconds or has two or more discrete, nameable phases. CLI: show clear step transitions and status lines instead of silent waiting. 4. **Create a reaction for every action** Every meaningful user action should receive clear feedback. @@ -67,7 +75,7 @@ This skill is intentionally surface-based rather than path-based, so it applies CLI: suggest the next subcommand instead of forcing the user back to docs. 8. **Consider your options** Make common cases easy with prompts, defaults, and clear required inputs. - PowerShell cmdlets: use sensible defaults, parameter validation, and prompts only when the flow is intentionally interactive. + PowerShell cmdlets: use sensible defaults, parameter validation, and prompts only when the cmdlet is explicitly designed for interactive use and exposes a `-Interactive` switch or equivalent; never prompt when input can arrive from the pipeline or when no TTY is detected. CLI: accept explicit flags for automation, but guide the user when required context is missing. 9. **Provide an easy way out** Users need a clear cancellation and escape path. @@ -125,6 +133,7 @@ This skill is intentionally surface-based rather than path-based, so it applies - Prevent high-cost mistakes before execution; recover clearly when prevention is not enough. - Keep normal-path output concise, with optional detail on demand through the appropriate verbose/help surface. - When a next step is common and useful, suggest it explicitly. +- When the host is non-interactive (no TTY, CI environment variable set, or `-NonInteractive` / `--no-interactive` flag present), suppress all prompts, suppress `Write-Progress` output, and ensure the command can complete using only supplied parameters or fail with a non-zero exit code and a machine-readable error message. ## Common pitfalls @@ -143,3 +152,4 @@ This skill is intentionally surface-based rather than path-based, so it applies - The command uses user language, not internal implementation language. - The normal path is concise and scannable. - The user has a clear recovery path after errors and a clear exit path during risky or interactive flows. +- For commands exposed through both surfaces, the review or generated output contains two clearly labeled sections: one for the PowerShell cmdlet surface and one for the CLI alias surface, each evaluated independently against its own conventions. diff --git a/AGENTS.md b/AGENTS.md index b280973f..bb90df7c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,7 +8,13 @@ Index of repository-wide Copilot guidance for NovaModuleTools. This file is inte ## Start here -For non-trivial changes, read in this order: +Start here: + +1. If the work is new or not yet scoped, use the `architect` agent with `.github/prompts/design-change.prompt.md` first. The architect flow is discussion-first: clarify the request, explore options, and only finalize a scoped solution or issue draft after the discussion is done. +2. Otherwise, identify your task type in the Task map below and follow only the prompt, agent, and instructions listed for that row. +3. Use the reading order below only when no Task map row matches the work. + +For any change that adds, removes, or modifies public commands, helper functions, tests, CI workflows, or documentation, read in this order: 1. `README.md` 2. `CONTRIBUTING.md` @@ -17,8 +23,6 @@ For non-trivial changes, read in this order: 5. The topic-scoped instruction file(s) that match the paths you are touching 6. The skill listed under that topic in the task map below -For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/design-change.prompt.md`. The architect flow is discussion-first: clarify the request, explore options, and only finalize a scoped solution or issue draft after the discussion is done. - ## Repository map - `src/public/` — public PowerShell commands; one top-level function per file, file name matches function name @@ -46,14 +50,17 @@ The table below shows how to route work. Prompts are the task entry points; each | Review a change | `review-change.prompt.md` | `reviewer` | `terminal-ux-design`, `codescene-quality`, `safeguarding-ai-generated-code`, `building-maintainable-code`, `docs-site`, `markdown-authoring`, `pester-testing`, `release-and-changelog`, `github-actions` | All `.github/instructions/*.instructions.md` | | Improve test coverage | `improve-test-coverage.prompt.md` | `test-engineer` | `pester-testing`, `building-maintainable-code`, `codescene-quality`, `github-actions`, `guiding-refactoring-with-code-health`, `safeguarding-ai-generated-code` | `testing-policy`, `psscriptanalyzer` | | Prepare a release | `prepare-release.prompt.md` | `release-manager` | `release-and-changelog`, `markdown-authoring` | `release-policy`, `repository-conventions` | -| Fix a CI failure | `fix-ci-failure.prompt.md` | `powershell-developer` (or `test-engineer`) | `github-actions`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | -| Update website docs | (no dedicated prompt — invoke agent) | `docs-site` | `docs-site`, `markdown-authoring` | `documentation-separation` | +| Fix a CI failure | `fix-ci-failure.prompt.md` | `powershell-developer` when the failure is in source code or build scripts; `test-engineer` when the failure is in a Pester test file under `tests/` | `github-actions`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | +| Update website docs | Invoke `@docs-site` directly and pass the target file path. No prompt file is required. | `docs-site` | `docs-site`, `markdown-authoring` | `documentation-separation` | + +If a change spans multiple task types, run each relevant flow sequentially in this order: design (if needed) → implement → test coverage → docs → release. Do not attempt to merge prompts. ## Notation - Skills referenced as `/skill-name` in agent files map 1-to-1 to the `name:` field in `.github/skills//SKILL.md`. The runtime invokes them through the `skill` tool with the bare name. - Prompts are referenced by path. Custom prompts are not auto-loaded by the Copilot CLI; invoke them explicitly with `@.github/prompts/.prompt.md`. - Instructions auto-load when their `applyTo:` glob matches a file in the change set. +- If an expected instruction file does not auto-load because no file in the change set matches its `applyTo:` glob, explicitly load it with `@.github/instructions/.instructions.md` before proceeding. ## Related guidance diff --git a/CHANGELOG.md b/CHANGELOG.md index 806e4e85..5ed45d54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changed +- The maintained Agentic Copilot guidance shipped by Nova now uses stricter release, review, testing, and analyzer rules across prompts, skills, agents, and scaffold mirrors. + - The repository and scaffolded guidance now stop earlier when required guidance files or required skills are missing, keep private-helper test ownership aligned with mirrored `tests/private//.Tests.ps1` paths, and require analyzer fallback guidance to reuse the repository wrapper settings. + - The scaffold-sync guardrail test now verifies those release/review/test guidance expectations so future scaffold updates stay aligned with the maintained source files. + ### Deprecated ### Removed ### Fixed +- `Test-NovaBuild` and `% nova test -b` now complete with a visible warning when a project has no `*.Integration.Tests.ps1` files, instead of failing the build-validation flow. + - The guidance explains where build-validation tests belong, tells users to add at least one `*.Integration.Tests.ps1` file before rerunning `Test-NovaBuild`, and reminds users to keep unit tests in `Invoke-NovaTest`. +- The packaged example scaffold now includes a minimal `*.Integration.Tests.ps1` file that resolves the generated `ProjectName`, imports the built module, and validates `Get-ExampleGreeting`, so `nova init -e` projects can pass `Test-NovaBuild` even after the scaffold rewrites `project.json`. + ### Security ## [3.2.0] - 2026-05-31 @@ -510,4 +518,3 @@ This release was yanked because it removed the implicit `Pester` dependency, bef [0.0.6]: https://github.com/stiwicourage/NovaModuleTools/compare/Version_0.0.5...Version_0.0.6 [0.0.5]: https://github.com/stiwicourage/NovaModuleTools/compare/Version_0.0.4...Version_0.0.5 [0.0.4]: https://github.com/stiwicourage/NovaModuleTools/compare/Version_0.0.3...Version_0.0.4 - diff --git a/RELEASE_NOTE.md b/RELEASE_NOTE.md index 41d4dfe0..cb06e750 100644 --- a/RELEASE_NOTE.md +++ b/RELEASE_NOTE.md @@ -8,12 +8,17 @@ This file summarizes the release notes for NovaModuleTools. **UNRELEASED** chang ### Changed +- The shipped Agentic Copilot scaffold now includes tighter review, release, testing, and analyzer guidance so generated projects inherit the latest workflow guardrails and validation expectations. + ### Deprecated ### Removed ### Fixed +- `Test-NovaBuild` and `% nova test -b` now complete with a visible warning when a project has no `*.Integration.Tests.ps1` files, and the guidance now explains where build-validation tests belong plus when to use `Invoke-NovaTest` instead. +- The packaged example scaffold now includes a minimal build-validation integration test that resolves the generated project name before importing the built module and checking `Get-ExampleGreeting`, so `nova init -e` projects can pass `Test-NovaBuild`. + ### Security ## [3.2.0] - 2026-05-31 @@ -259,4 +264,3 @@ This release was yanked because it removed the implicit `Pester` dependency befo ## [0.0.4] - 2024-06-25 ### Added - First PowerShell Gallery release of NovaModuleTools with the initial module workflow support. - diff --git a/docs/NovaModuleTools/en-US/Test-NovaBuild.md b/docs/NovaModuleTools/en-US/Test-NovaBuild.md index aff590a9..338c8ced 100644 --- a/docs/NovaModuleTools/en-US/Test-NovaBuild.md +++ b/docs/NovaModuleTools/en-US/Test-NovaBuild.md @@ -35,6 +35,8 @@ This build-validation flow writes NUnit XML to `artifacts/TestResults.xml`. Unlike `Invoke-NovaTest`, this command does not enforce source-coverage targets. Use `Invoke-NovaTest` for the unit-test and code-coverage workflow, and use `Test-NovaBuild` when you need build-validation integration coverage that reflects the built module path. +If the current project does not contain any `*.Integration.Tests.ps1` files, `Test-NovaBuild` stops with a Nova-native error that explains the expected naming and reminds you to use `Invoke-NovaTest` for unit tests. + `-OverrideWarning` lets the nested build-validation flow continue even if the `src/public` layout guard reports zero or multiple top-level functions in a public file. With the default `BuildRecursiveFolders=true`, integration test files in nested folders under `tests` are discovered and run. Set `BuildRecursiveFolders=false` to limit discovery to top-level matching test files. diff --git a/docs/core-workflows.html b/docs/core-workflows.html index 0b9d86da..833e9cc1 100644 --- a/docs/core-workflows.html +++ b/docs/core-workflows.html @@ -246,10 +246,10 @@

Run the tests

PS> Test-NovaBuild PS> Invoke-NovaTest -TagFilter unit,fast PS> Test-NovaBuild -ExcludeTagFilter slow - PS> Invoke-NovaTest -OutputVerbosity Detailed -OutputRenderMode Ansi - PS> $credential = Get-Credential - PS> $container = New-PesterContainer -Path 'tests/public/PublishNovaModule.Tests.ps1' -Data @{ Credential = $credential } - PS> Invoke-NovaTest -PesterConfigurationOverride @{ Run = @{ Container = @($container) } } +PS> Invoke-NovaTest -OutputVerbosity Detailed -OutputRenderMode Ansi +PS> $credential = Get-Credential +PS> $container = New-PesterContainer -Path 'tests/public/PublishNovaModule.Tests.ps1' -Data @{ Credential = $credential } +PS> Invoke-NovaTest -PesterConfigurationOverride @{ Run = @{ Container = @($container) } }