diff --git a/.github/agents/architect.agent.md b/.github/agents/architect.agent.md index cbb84c4..17fbc34 100644 --- a/.github/agents/architect.agent.md +++ b/.github/agents/architect.agent.md @@ -37,6 +37,7 @@ Design or reshape changes that cross public commands, private helper boundaries, ## Skills to use - `/powershell-module-development` +- `/terminal-ux-design` - `/release-and-changelog` - `/markdown-authoring` - `/building-maintainable-code` diff --git a/.github/agents/powershell-developer.agent.md b/.github/agents/powershell-developer.agent.md index 3a7dc0c..2a0090d 100644 --- a/.github/agents/powershell-developer.agent.md +++ b/.github/agents/powershell-developer.agent.md @@ -32,6 +32,7 @@ Implement PowerShell command and helper changes in the NovaModuleTools style. ## Skills to use - `/powershell-module-development` +- `/terminal-ux-design` - `/pester-testing` - `/building-maintainable-code` - `/codescene-quality` diff --git a/.github/agents/reviewer.agent.md b/.github/agents/reviewer.agent.md index aab9fde..69fcb87 100644 --- a/.github/agents/reviewer.agent.md +++ b/.github/agents/reviewer.agent.md @@ -41,6 +41,7 @@ Review changes for correctness, maintainability, test coverage, workflow safety, ## Skills to use +- `/terminal-ux-design` - `/codescene-quality` - `/safeguarding-ai-generated-code` - `/building-maintainable-code` diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index e8a83d5..55b93ee 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -37,15 +37,15 @@ For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/ The table below shows how to route work. Prompts are the task entry points; each prompt delegates to its agent, which uses the listed skills, which in turn enforce the listed instructions. -| Task | Prompt | Agent | Primary skills | Primary instructions | -| ----------------------------- | ------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | -| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `github-actions`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | -| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `pester-testing`, `building-maintainable-code`, `codescene-quality`, `safeguarding-ai-generated-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | -| Review a change | `review-change.prompt.md` | `reviewer` | `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` | +| Task | Prompt | Agent | Primary skills | Primary instructions | +|--------------------------|--------------------------------------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| +| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `terminal-ux-design`, `github-actions`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | +| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `terminal-ux-design`, `pester-testing`, `building-maintainable-code`, `codescene-quality`, `safeguarding-ai-generated-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | +| 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` | ## Notation @@ -61,5 +61,6 @@ The table below shows how to route work. Prompts are the task entry points; each - PSScriptAnalyzer workflow: `.github/instructions/psscriptanalyzer.instructions.md` - PowerShell coding standards: `.github/instructions/powershell-coding-standards.instructions.md` - PlatyPS help generation: `.github/instructions/platyps-help.instructions.md` +- Terminal UX: `.github/instructions/terminal-ux-design.instructions.md` + `terminal-ux-design` skill - Release flow: `.github/instructions/release-policy.instructions.md` + `release-and-changelog` skill - Documentation separation: `.github/instructions/documentation-separation.instructions.md` + `docs-site` skill diff --git a/.github/instructions/terminal-ux-design.instructions.md b/.github/instructions/terminal-ux-design.instructions.md new file mode 100644 index 0000000..a6312f2 --- /dev/null +++ b/.github/instructions/terminal-ux-design.instructions.md @@ -0,0 +1,21 @@ +--- +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. + +This applies to: + +- PowerShell cmdlets +- `% nova` CLI routes +- private helpers that shape user-visible terminal behavior +- 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. + +The skill is authoritative for: + +- Atlassian's 10 design principles for delightful CLIs +- Jakob Nielsen's 10 usability heuristics for user interface design diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0adae17..c327641 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -20,6 +20,7 @@ - [ ] Dependency or manifest changes (`project.json`, workflow dependencies, release tooling) - [ ] Security-sensitive change - [ ] Documentation-only change +- [ ] Agentic Copilot Workflow + scaffold mirror + scaffold-sync guardrail test. - [ ] Other ## Review guidance diff --git a/.github/skills/terminal-ux-design/SKILL.md b/.github/skills/terminal-ux-design/SKILL.md new file mode 100644 index 0000000..b83d8b5 --- /dev/null +++ b/.github/skills/terminal-ux-design/SKILL.md @@ -0,0 +1,145 @@ +--- +name: terminal-ux-design +description: Guidance for designing terminal-first PowerShell cmdlets and CLI workflows with Atlassian's CLI principles and Jakob Nielsen's usability heuristics. +--- + +# Skill: terminal UX design + +## When to use + +Use this skill when: + +- adding or changing a public PowerShell cmdlet +- adding or changing a CLI command/route or its help/output flow +- shaping prompts, progress, warnings, success messages, or error messages +- reviewing terminal-facing behavior in scaffolds, contributor docs, or command help + +This skill applies even when the surface is not named "CLI". In NovaModuleTools, PowerShell cmdlets are also terminal UX. + +## Two surfaces, two conventions + +The same underlying PowerShell code can present itself through two distinct user-facing surfaces, and each is held to its own conventions: + +- **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. + +## Relevant surfaces + +This skill is intentionally surface-based rather than path-based, so it applies the same way in this repository and in any project scaffolded by `nova init`, regardless of folder layout. Apply it to any change that touches: + +- a public PowerShell cmdlet or its parameters, help, output, or error contract +- a CLI command/route, its help text, flags, exit codes, or output +- a helper that shapes terminal-visible help, prompts, progress, warnings, or errors +- command help authored for PlatyPS or equivalent help generators +- contributor-facing agent, instruction, or skill files that describe terminal-facing behavior + +## Atlassian's 10 design principles for delightful CLIs + +1. **Align with established conventions** + Use established PowerShell and terminal conventions so users do not have to relearn basic command behavior. + PowerShell cmdlets: prefer approved verbs, common parameter semantics, and standard streams. + CLI: prefer familiar `--flag` / `-f` patterns, standard help forms, and predictable exit codes. +2. **Build help into the CLI** + Help must be discoverable from the command itself, not only from external docs. + PowerShell cmdlets: keep comment-based help complete and `Get-Help -Full` useful. + 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. + 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. + PowerShell cmdlets: success, cancellation, and failure paths should be explicit. + CLI: commands should not silently succeed, silently cancel, or fail without context. +5. **Craft human-readable error messages** + Errors should explain what happened and what to do next. + PowerShell cmdlets: surface actionable `Stop-NovaOperation` messages and preserve a stable `ErrorId`. + CLI: convert internal failures into user-readable guidance instead of raw backend output. +6. **Support your skim-readers** + Terminal output should be easy to scan under time pressure. + PowerShell cmdlets: prefer short paragraphs, focused bullets, and restrained output. + CLI: keep normal-path output minimal and make the important line easy to spot. +7. **Suggest the next best step** + After a successful action, guide the user to the most likely follow-up. + PowerShell cmdlets: mention the next cmdlet or validation step when it helps. + 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. + 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. + PowerShell cmdlets: preserve native `-WhatIf`, `-Confirm`, and cancellation semantics. + CLI: make `Ctrl+C`, cancel choices, and non-destructive previews obvious. +10. **Flags over args** + Favor named inputs over memory-heavy positional usage. + PowerShell cmdlets: prefer explicit parameter names and sensible aliases over positional-only designs. + CLI: prefer `--environment production` over unlabeled ordered arguments. + +## Jakob Nielsen's 10 usability heuristics for user interface design + +1. **Visibility of system status** + Keep users informed about current state, current step, and recent outcome within a reasonable time. +2. **Match between the system and the real world** + Use the user's language, not internal implementation jargon, and order information the way users expect. +3. **User control and freedom** + Support cancel, undo, preview, and escape paths so users do not feel trapped in a workflow. +4. **Consistency and standards** + Use one meaning per word, one shape per interaction, and familiar platform conventions across cmdlets, CLI routes, and docs. +5. **Error prevention** + Prevent common mistakes with defaults, validation, confirmations, and constraints before the user commits. +6. **Recognition rather than recall** + Show the needed options, values, examples, and names instead of forcing the user to remember them from earlier output. +7. **Flexibility and efficiency of use** + Support both newcomers and experts with clear defaults plus shortcuts, aliases, and low-friction repeated flows. +8. **Aesthetic and minimalist design** + Every line in the terminal competes for attention. Keep normal-path output focused on what matters now. +9. **Help users recognize, diagnose, and recover from errors** + State the problem plainly, show where it happened, and suggest recovery steps that a user can act on immediately. +10. **Help and documentation** + Make help searchable, contextual, concise, and task-oriented. Users should not have to leave the workflow to understand the next step. + +## Combined mapping table + +| Concern | Concrete PowerShell / CLI mechanism | Atlassian principle(s) | Nielsen heuristic(s) | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|----------------------| +| Surface routing | Decide whether the command exposes a PowerShell cmdlet surface, a unix-style CLI alias surface, or both, and apply the matching conventions per surface | 1, 10 | 2, 4 | +| Status visibility | `Write-Progress`, stage-by-stage status lines, clear completion/cancel summaries | 3, 4, 7 | 1 | +| Familiar language | Approved PowerShell verbs, user-facing terminology, surface-specific wording in docs and help | 1 | 2, 4 | +| Safe exits | `-WhatIf`, `-Confirm`, `SupportsShouldProcess`, explicit cancel choices, `Ctrl+C` support | 9 | 3, 5 | +| Error prevention | Parameter validation, pre-flight checks, sensible defaults, explicit `-OverrideWarning` / `--override-warning` gates | 8 | 5 | +| Recognition over recall | Comment-based help, CLI `--help`, examples, prompts that show available choices, discoverable defaults | 2, 8, 10 | 6, 10 | +| Expert efficiency | Parameter aliases, short CLI flags, repeatable subcommand flows, next-step hints for common sequences | 7, 10 | 7 | +| Minimal output | Short paragraphs, focused bullets, no decorative banners in normal mode, use `-Verbose` for detail | 6 | 8 | +| Recoverable errors | `Stop-NovaOperation` with stable `ErrorId`, plain language, and actionable recovery guidance | 5 | 9 | +| Help quality | Accurate `Get-Help`, accurate CLI ` --help`, related links, task-oriented examples | 2 | 10 | +| Consistent surfaces | Do not mix cmdlet `-Parameter` syntax into CLI guidance or CLI `--flag` syntax into cmdlet help | 1, 10 | 2, 4 | + +## Expected practices + +- Keep PowerShell cmdlet UX and CLI UX distinct, but hold both to the same terminal UX bar. +- Tell users what happened, especially after mutating, long-running, or risky operations. +- Prefer visible choices, examples, and defaults over forcing users to remember values from prior steps. +- 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. + +## Common pitfalls + +- leaking internal jargon, object names, or backend wording into user-facing messages +- returning success with no visible reaction +- printing raw exception text without recovery guidance +- forcing users to remember flag names, route names, IDs, or paths from earlier output +- mixing cmdlet syntax and CLI syntax in the same always-visible guidance +- using large banner-style output where one clear status line would do +- adding confirmations or prompts in a way that breaks automation + +## Definition of done + +- The user can discover how to invoke the command from the terminal surface they are using. +- Long-running, risky, and error paths expose enough state to keep the user oriented. +- 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. diff --git a/AGENTS.md b/AGENTS.md index 8801c37..015cd5f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,15 +39,15 @@ For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/ The table below shows how to route work. Prompts are the task entry points; each prompt delegates to its agent, which uses the listed skills, which in turn enforce the listed instructions. -| Task | Prompt | Agent | Primary skills | Primary instructions | -| ----------------------------- | ------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | -| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `github-actions`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | -| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `pester-testing`, `building-maintainable-code`, `codescene-quality`, `safeguarding-ai-generated-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | -| Review a change | `review-change.prompt.md` | `reviewer` | `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` | +| Task | Prompt | Agent | Primary skills | Primary instructions | +|--------------------------|--------------------------------------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| +| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `terminal-ux-design`, `github-actions`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | +| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `terminal-ux-design`, `pester-testing`, `building-maintainable-code`, `codescene-quality`, `safeguarding-ai-generated-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | +| 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` | ## Notation @@ -63,5 +63,6 @@ The table below shows how to route work. Prompts are the task entry points; each - PSScriptAnalyzer workflow: `.github/instructions/psscriptanalyzer.instructions.md` - PowerShell coding standards: `.github/instructions/powershell-coding-standards.instructions.md` - PlatyPS help generation: `.github/instructions/platyps-help.instructions.md` +- Terminal UX: `.github/instructions/terminal-ux-design.instructions.md` + `terminal-ux-design` skill - Release flow: `.github/instructions/release-policy.instructions.md` + `release-and-changelog` skill - Documentation separation: `.github/instructions/documentation-separation.instructions.md` + `docs-site` skill diff --git a/CHANGELOG.md b/CHANGELOG.md index b0e30df..7955eb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - The workflow reads `ProjectName` and `Description` from `project.json`, requires a `ShortName` on every run for token replacement, and fails clearly when the project metadata or short name is invalid. - Nova refreshes only the approved managed Agentic Copilot paths under `.github/` plus `AGENTS.md` and `CONTRIBUTING.md`, while `README.md`, `CHANGELOG.md`, and `RELEASE_NOTE.md` are created only when they are missing. - The new cmdlet and CLI route prompt before overwriting managed scaffold content by default, and support non-interactive execution only through `-OverrideWarning` / `--override-warning` / `-o`. +- Added `terminal-ux-design` to Nova's repository-local and scaffolded Agentic Copilot guidance. + - The new guidance combines Atlassian's 10 design principles for delightful CLIs with Jakob Nielsen's 10 usability heuristics for user interface design, and applies them to both the PowerShell cmdlet surface and any unix-style CLI alias surface (such as `% nova`) as terminal-first user interfaces. + - The new skill ships with a "two surfaces, two conventions" framing, a shared mapping table for concrete PowerShell cmdlet and CLI alias UX mechanisms, a universal instruction that points terminal-facing changes at the skill, and updated architect, implementation, and review agent entry points. ### Changed @@ -20,6 +23,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Fixed +- `Test-NovaBuild` now expands configured Pester coverage globs into concrete source files before invoking Pester, so nested helpers remain measurable in `artifacts/coverage.xml` while repository and scaffolded `project.json` defaults can stay on the simpler `src/private/**/*.ps1` entry. + ### Security ## [3.0.1] - 2026-05-18 diff --git a/scripts/build/Sync-AgenticCopilotScaffold.psd1 b/scripts/build/Sync-AgenticCopilotScaffold.psd1 index b0a18e7..de05cf0 100644 --- a/scripts/build/Sync-AgenticCopilotScaffold.psd1 +++ b/scripts/build/Sync-AgenticCopilotScaffold.psd1 @@ -139,35 +139,35 @@ New = '- `docs/` - project documentation' } @{ - Old = '- `.github/instructions/documentation.instructions.md`' + Old = "- ``.github/instructions/documentation.instructions.md```n" New = '' } @{ - Old = '- `/quality tooling-quality`' + Old = "- ``/quality tooling-quality```n" New = '' } @{ - Old = '- `/codescene-quality`' + Old = "- ``/codescene-quality```n" New = '' } @{ - Old = '- `/guiding-refactoring-with-maintainability`' + Old = "- ``/guiding-refactoring-with-maintainability```n" New = '' } @{ - Old = '- `/guiding-refactoring-with-code-health`' + Old = "- ``/guiding-refactoring-with-code-health```n" New = '' } @{ - Old = '- `/safeguarding-ai-generated-code`' + Old = "- ``/safeguarding-ai-generated-code```n" New = '' } @{ - Old = '- `/workflow guidance`' + Old = "- ``/workflow guidance```n" New = '' } @{ - Old = '- `/documentation-html`' + Old = "- ``/documentation-html```n" New = '' } @{ @@ -450,5 +450,9 @@ Old = ', or `nova` CLI route naming conventions.' New = '.' } + @{ + Old = 'Stop-NovaOperation' + New = 'Stop-{{ShortName}}Operation' + } ) } diff --git a/src/private/quality/GetNovaTestWorkflowContext.ps1 b/src/private/quality/GetNovaTestWorkflowContext.ps1 index 50ee1fb..fdf003d 100644 --- a/src/private/quality/GetNovaTestWorkflowContext.ps1 +++ b/src/private/quality/GetNovaTestWorkflowContext.ps1 @@ -92,6 +92,23 @@ function Get-NovaConfiguredPesterCoveragePercentTarget { return [double]$coveragePercentTarget } +function Get-NovaConfiguredPesterCoveragePath { + [CmdletBinding()] + param( + [Parameter(Mandatory)][object]$ProjectPesterSettings + ) + + $codeCoverageSettings = Get-NovaPesterSettingValue -InputObject $ProjectPesterSettings -Name 'CodeCoverage' + if ($true -ne [bool](Get-NovaPesterSettingValue -InputObject $codeCoverageSettings -Name 'Enabled')) { + return @() + } + + return @( + Get-NovaPesterSettingValue -InputObject $codeCoverageSettings -Name 'Path' | + Where-Object {-not [string]::IsNullOrWhiteSpace([string]$_)} + ) +} + function Initialize-NovaPesterCoverageConfiguration { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Mutates PesterConfiguration state, not user-facing resources. ShouldProcess is not appropriate here.')] [CmdletBinding()] @@ -109,6 +126,110 @@ function Initialize-NovaPesterCoverageConfiguration { if ($null -ne $coveragePercentTarget) { $PesterConfig.CodeCoverage.CoveragePercentTarget = $coveragePercentTarget } + + $resolvedCoveragePath = @(Get-NovaResolvedPesterCoveragePath -ProjectInfo $ProjectInfo) + if ($resolvedCoveragePath.Count -gt 0) { + $PesterConfig.CodeCoverage.Path = $resolvedCoveragePath + } +} + +function Get-NovaResolvedPesterCoveragePath { + [CmdletBinding()] + param( + [Parameter(Mandatory)][pscustomobject]$ProjectInfo + ) + + $coveragePath = @(Get-NovaConfiguredPesterCoveragePath -ProjectPesterSettings $ProjectInfo.Pester) + if ($coveragePath.Count -eq 0) { + return @() + } + + $coverageFile = @(Get-NovaPesterCoverageFile -ProjectRoot $ProjectInfo.ProjectRoot) + $resolvedPath = New-Object 'System.Collections.Generic.List[string]' + foreach ($pattern in $coveragePath) { + Add-NovaResolvedCoveragePath -ResolvedPath $resolvedPath -CoverageFile $coverageFile -Pattern $pattern + } + + return @($resolvedPath) +} + +function Get-NovaPesterCoverageFile { + [CmdletBinding()] + param( + [Parameter(Mandatory)][string]$ProjectRoot + ) + + $resolvedProjectRoot = (Resolve-Path -LiteralPath $ProjectRoot -ErrorAction Stop).Path + foreach ($file in (Get-ChildItem -LiteralPath $resolvedProjectRoot -Recurse -File | Sort-Object FullName)) { + [pscustomobject]@{ + FullPath = ConvertTo-NovaCoveragePathString -Path $file.FullName + RelativePath = ConvertTo-NovaCoveragePathString -Path ([System.IO.Path]::GetRelativePath($resolvedProjectRoot, $file.FullName)) + } + } +} + +function Add-NovaResolvedCoveragePath { + [CmdletBinding()] + param( + [Parameter(Mandatory)][AllowEmptyCollection()][System.Collections.Generic.List[string]]$ResolvedPath, + [Parameter(Mandatory)][object[]]$CoverageFile, + [Parameter(Mandatory)][string]$Pattern + ) + + $patternVariant = @(Get-NovaCoveragePathPatternVariant -Pattern $Pattern) + + foreach ($file in $CoverageFile) { + if ((Test-NovaCoveragePathMatch -CoverageFile $file -Pattern $patternVariant) -and -not $ResolvedPath.Contains($file.RelativePath)) { + $ResolvedPath.Add($file.RelativePath) + } + } +} + +function Test-NovaCoveragePathMatch { + [CmdletBinding()] + param( + [Parameter(Mandatory)][pscustomobject]$CoverageFile, + [Parameter(Mandatory)][string[]]$Pattern + ) + + foreach ($item in $Pattern) { + $wildcardPattern = [System.Management.Automation.WildcardPattern]::new($item, [System.Management.Automation.WildcardOptions]::IgnoreCase) + if ($wildcardPattern.IsMatch($CoverageFile.RelativePath) -or $wildcardPattern.IsMatch($CoverageFile.FullPath)) { + return $true + } + } + + return $false +} + +function Get-NovaCoveragePathPatternVariant { + [CmdletBinding()] + param( + [Parameter(Mandatory)][string]$Pattern + ) + + $patternVariant = New-Object 'System.Collections.Generic.List[string]' + $normalizedPattern = ConvertTo-NovaCoveragePathString -Path $Pattern + $patternVariant.Add($normalizedPattern) + + $collapsedPattern = $normalizedPattern + while ($collapsedPattern.Contains('/**/')) { + $collapsedPattern = $collapsedPattern.Replace('/**/', '/') + if (-not $patternVariant.Contains($collapsedPattern)) { + $patternVariant.Add($collapsedPattern) + } + } + + return @($patternVariant) +} + +function ConvertTo-NovaCoveragePathString { + [CmdletBinding()] + param( + [Parameter(Mandatory)][string]$Path + ) + + return $Path -replace '\\', '/' } function Get-NovaPesterSettingValue { diff --git a/src/resources/agentic-copilot/.github/agents/architect.agent.md b/src/resources/agentic-copilot/.github/agents/architect.agent.md index 79b635e..e54d15f 100644 --- a/src/resources/agentic-copilot/.github/agents/architect.agent.md +++ b/src/resources/agentic-copilot/.github/agents/architect.agent.md @@ -37,6 +37,7 @@ Design or reshape changes that cross public commands, private helper boundaries, ## Skills to use - `/powershell-module-development` +- `/terminal-ux-design` - `/release-and-changelog` - `/markdown-authoring` - `/building-maintainable-code` diff --git a/src/resources/agentic-copilot/.github/agents/powershell-developer.agent.md b/src/resources/agentic-copilot/.github/agents/powershell-developer.agent.md index 3bab967..f4ccb9d 100644 --- a/src/resources/agentic-copilot/.github/agents/powershell-developer.agent.md +++ b/src/resources/agentic-copilot/.github/agents/powershell-developer.agent.md @@ -32,6 +32,7 @@ Implement PowerShell command and helper changes in the {{ProjectName}} style. ## Skills to use - `/powershell-module-development` +- `/terminal-ux-design` - `/pester-testing` - `/building-maintainable-code` diff --git a/src/resources/agentic-copilot/.github/agents/reviewer.agent.md b/src/resources/agentic-copilot/.github/agents/reviewer.agent.md index a3c0de9..4a64d0b 100644 --- a/src/resources/agentic-copilot/.github/agents/reviewer.agent.md +++ b/src/resources/agentic-copilot/.github/agents/reviewer.agent.md @@ -41,6 +41,7 @@ Review changes for correctness, maintainability, test coverage, workflow safety, ## Skills to use +- `/terminal-ux-design` - `/building-maintainable-code` - `/documentation` - `/markdown-authoring` diff --git a/src/resources/agentic-copilot/.github/agents/test-engineer.agent.md b/src/resources/agentic-copilot/.github/agents/test-engineer.agent.md index 02fffad..5bc9e25 100644 --- a/src/resources/agentic-copilot/.github/agents/test-engineer.agent.md +++ b/src/resources/agentic-copilot/.github/agents/test-engineer.agent.md @@ -31,7 +31,6 @@ Improve or maintain the repository's Pester coverage, coverage-gate behavior, an ## Skills to use - `/pester-testing` - - `/building-maintainable-code` ## Constraints diff --git a/src/resources/agentic-copilot/.github/copilot-instructions.md b/src/resources/agentic-copilot/.github/copilot-instructions.md index a40769c..9af879b 100644 --- a/src/resources/agentic-copilot/.github/copilot-instructions.md +++ b/src/resources/agentic-copilot/.github/copilot-instructions.md @@ -37,15 +37,15 @@ For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/ The table below shows how to route work. Prompts are the task entry points; each prompt delegates to its agent, which uses the listed skills, which in turn enforce the listed instructions. -| Task | Prompt | Agent | Primary skills | Primary instructions | -| ----------------------------- | ------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | -| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `workflow guidance`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | -| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `pester-testing`, `building-maintainable-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | -| Review a change | `review-change.prompt.md` | `reviewer` | `building-maintainable-code`, `documentation`, `markdown-authoring`, `pester-testing`, `release-and-changelog`, `workflow guidance` | All `.github/instructions/*.instructions.md` | -| Improve test coverage | `improve-test-coverage.prompt.md` | `test-engineer` | `pester-testing`, `building-maintainable-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`) | `workflow guidance`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | -| Update project docs | (no dedicated prompt — invoke agent) | `documentation` | `documentation`, `markdown-authoring` | `documentation` | +| Task | Prompt | Agent | Primary skills | Primary instructions | +|--------------------------|--------------------------------------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| +| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `terminal-ux-design`, `workflow guidance`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | +| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `terminal-ux-design`, `pester-testing`, `building-maintainable-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | +| Review a change | `review-change.prompt.md` | `reviewer` | `terminal-ux-design`, `building-maintainable-code`, `documentation`, `markdown-authoring`, `pester-testing`, `release-and-changelog`, `workflow guidance` | All `.github/instructions/*.instructions.md` | +| Improve test coverage | `improve-test-coverage.prompt.md` | `test-engineer` | `pester-testing`, `building-maintainable-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`) | `workflow guidance`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | +| Update project docs | (no dedicated prompt — invoke agent) | `documentation` | `documentation`, `markdown-authoring` | `documentation` | ## Notation @@ -61,5 +61,6 @@ The table below shows how to route work. Prompts are the task entry points; each - PSScriptAnalyzer workflow: `.github/instructions/psscriptanalyzer.instructions.md` - PowerShell coding standards: `.github/instructions/powershell-coding-standards.instructions.md` - PlatyPS help generation: `.github/instructions/platyps-help.instructions.md` +- Terminal UX: `.github/instructions/terminal-ux-design.instructions.md` + `terminal-ux-design` skill - Release flow: `.github/instructions/release-policy.instructions.md` + `release-and-changelog` skill - Documentation separation: `.github/instructions/documentation.instructions.md` + `documentation` skill diff --git a/src/resources/agentic-copilot/.github/instructions/code-quality-matrix.instructions.md b/src/resources/agentic-copilot/.github/instructions/code-quality-matrix.instructions.md index 3d3c275..5dab39c 100644 --- a/src/resources/agentic-copilot/.github/instructions/code-quality-matrix.instructions.md +++ b/src/resources/agentic-copilot/.github/instructions/code-quality-matrix.instructions.md @@ -126,7 +126,7 @@ This file tells Agentic Copilot how to shape source code from the start. Test-sp - No dead code. Remove unreachable branches and unused private helpers. - No long or multi-responsibility identifiers. Use focused, intent-revealing names. - No magic literals. Lift unexplained numbers and strings into named constants, script variables, or lookup tables. - - No broad catches. Catch specific exceptions only when the layer adds context; otherwise let failures surface clearly through `Stop-NovaOperation` or a structured `ErrorRecord` instead of silent fallback. + - No broad catches. Catch specific exceptions only when the layer adds context; otherwise let failures surface clearly through `Stop-{{ShortName}}Operation` or a structured `ErrorRecord` instead of silent fallback. - Files must end with exactly one trailing newline and no extra blank lines at the bottom. - Common objection: "Style is taste." Style is repeatable. These items are not taste, they are signals reviewers and tools rely on. diff --git a/src/resources/agentic-copilot/.github/instructions/terminal-ux-design.instructions.md b/src/resources/agentic-copilot/.github/instructions/terminal-ux-design.instructions.md new file mode 100644 index 0000000..a6312f2 --- /dev/null +++ b/src/resources/agentic-copilot/.github/instructions/terminal-ux-design.instructions.md @@ -0,0 +1,21 @@ +--- +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. + +This applies to: + +- PowerShell cmdlets +- `% nova` CLI routes +- private helpers that shape user-visible terminal behavior +- 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. + +The skill is authoritative for: + +- Atlassian's 10 design principles for delightful CLIs +- Jakob Nielsen's 10 usability heuristics for user interface design diff --git a/src/resources/agentic-copilot/.github/skills/terminal-ux-design/SKILL.md b/src/resources/agentic-copilot/.github/skills/terminal-ux-design/SKILL.md new file mode 100644 index 0000000..452a3a1 --- /dev/null +++ b/src/resources/agentic-copilot/.github/skills/terminal-ux-design/SKILL.md @@ -0,0 +1,145 @@ +--- +name: terminal-ux-design +description: Guidance for designing terminal-first PowerShell cmdlets and CLI workflows with Atlassian's CLI principles and Jakob Nielsen's usability heuristics. +--- + +# Skill: terminal UX design + +## When to use + +Use this skill when: + +- adding or changing a public PowerShell cmdlet +- adding or changing a CLI command/route or its help/output flow +- shaping prompts, progress, warnings, success messages, or error messages +- reviewing terminal-facing behavior in scaffolds, contributor docs, or command help + +This skill applies even when the surface is not named "CLI". In {{ProjectName}}, PowerShell cmdlets are also terminal UX. + +## Two surfaces, two conventions + +The same underlying PowerShell code can present itself through two distinct user-facing surfaces, and each is held to its own conventions: + +- **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. + +## Relevant surfaces + +This skill is intentionally surface-based rather than path-based, so it applies the same way in this repository and in any project scaffolded by `nova init`, regardless of folder layout. Apply it to any change that touches: + +- a public PowerShell cmdlet or its parameters, help, output, or error contract +- a CLI command/route, its help text, flags, exit codes, or output +- a helper that shapes terminal-visible help, prompts, progress, warnings, or errors +- command help authored for PlatyPS or equivalent help generators +- contributor-facing agent, instruction, or skill files that describe terminal-facing behavior + +## Atlassian's 10 design principles for delightful CLIs + +1. **Align with established conventions** + Use established PowerShell and terminal conventions so users do not have to relearn basic command behavior. + PowerShell cmdlets: prefer approved verbs, common parameter semantics, and standard streams. + CLI: prefer familiar `--flag` / `-f` patterns, standard help forms, and predictable exit codes. +2. **Build help into the CLI** + Help must be discoverable from the command itself, not only from external docs. + PowerShell cmdlets: keep comment-based help complete and `Get-Help -Full` useful. + 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. + 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. + PowerShell cmdlets: success, cancellation, and failure paths should be explicit. + CLI: commands should not silently succeed, silently cancel, or fail without context. +5. **Craft human-readable error messages** + Errors should explain what happened and what to do next. + PowerShell cmdlets: surface actionable `Stop-{{ShortName}}Operation` messages and preserve a stable `ErrorId`. + CLI: convert internal failures into user-readable guidance instead of raw backend output. +6. **Support your skim-readers** + Terminal output should be easy to scan under time pressure. + PowerShell cmdlets: prefer short paragraphs, focused bullets, and restrained output. + CLI: keep normal-path output minimal and make the important line easy to spot. +7. **Suggest the next best step** + After a successful action, guide the user to the most likely follow-up. + PowerShell cmdlets: mention the next cmdlet or validation step when it helps. + 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. + 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. + PowerShell cmdlets: preserve native `-WhatIf`, `-Confirm`, and cancellation semantics. + CLI: make `Ctrl+C`, cancel choices, and non-destructive previews obvious. +10. **Flags over args** + Favor named inputs over memory-heavy positional usage. + PowerShell cmdlets: prefer explicit parameter names and sensible aliases over positional-only designs. + CLI: prefer `--environment production` over unlabeled ordered arguments. + +## Jakob Nielsen's 10 usability heuristics for user interface design + +1. **Visibility of system status** + Keep users informed about current state, current step, and recent outcome within a reasonable time. +2. **Match between the system and the real world** + Use the user's language, not internal implementation jargon, and order information the way users expect. +3. **User control and freedom** + Support cancel, undo, preview, and escape paths so users do not feel trapped in a workflow. +4. **Consistency and standards** + Use one meaning per word, one shape per interaction, and familiar platform conventions across cmdlets, CLI routes, and docs. +5. **Error prevention** + Prevent common mistakes with defaults, validation, confirmations, and constraints before the user commits. +6. **Recognition rather than recall** + Show the needed options, values, examples, and names instead of forcing the user to remember them from earlier output. +7. **Flexibility and efficiency of use** + Support both newcomers and experts with clear defaults plus shortcuts, aliases, and low-friction repeated flows. +8. **Aesthetic and minimalist design** + Every line in the terminal competes for attention. Keep normal-path output focused on what matters now. +9. **Help users recognize, diagnose, and recover from errors** + State the problem plainly, show where it happened, and suggest recovery steps that a user can act on immediately. +10. **Help and documentation** + Make help searchable, contextual, concise, and task-oriented. Users should not have to leave the workflow to understand the next step. + +## Combined mapping table + +| Concern | Concrete PowerShell / CLI mechanism | Atlassian principle(s) | Nielsen heuristic(s) | +|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|----------------------| +| Surface routing | Decide whether the command exposes a PowerShell cmdlet surface, a unix-style CLI alias surface, or both, and apply the matching conventions per surface | 1, 10 | 2, 4 | +| Status visibility | `Write-Progress`, stage-by-stage status lines, clear completion/cancel summaries | 3, 4, 7 | 1 | +| Familiar language | Approved PowerShell verbs, user-facing terminology, surface-specific wording in docs and help | 1 | 2, 4 | +| Safe exits | `-WhatIf`, `-Confirm`, `SupportsShouldProcess`, explicit cancel choices, `Ctrl+C` support | 9 | 3, 5 | +| Error prevention | Parameter validation, pre-flight checks, sensible defaults, explicit `-OverrideWarning` / `--override-warning` gates | 8 | 5 | +| Recognition over recall | Comment-based help, CLI `--help`, examples, prompts that show available choices, discoverable defaults | 2, 8, 10 | 6, 10 | +| Expert efficiency | Parameter aliases, short CLI flags, repeatable subcommand flows, next-step hints for common sequences | 7, 10 | 7 | +| Minimal output | Short paragraphs, focused bullets, no decorative banners in normal mode, use `-Verbose` for detail | 6 | 8 | +| Recoverable errors | `Stop-{{ShortName}}Operation` with stable `ErrorId`, plain language, and actionable recovery guidance | 5 | 9 | +| Help quality | Accurate `Get-Help`, accurate CLI ` --help`, related links, task-oriented examples | 2 | 10 | +| Consistent surfaces | Do not mix cmdlet `-Parameter` syntax into CLI guidance or CLI `--flag` syntax into cmdlet help | 1, 10 | 2, 4 | + +## Expected practices + +- Keep PowerShell cmdlet UX and CLI UX distinct, but hold both to the same terminal UX bar. +- Tell users what happened, especially after mutating, long-running, or risky operations. +- Prefer visible choices, examples, and defaults over forcing users to remember values from prior steps. +- 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. + +## Common pitfalls + +- leaking internal jargon, object names, or backend wording into user-facing messages +- returning success with no visible reaction +- printing raw exception text without recovery guidance +- forcing users to remember flag names, route names, IDs, or paths from earlier output +- mixing cmdlet syntax and CLI syntax in the same always-visible guidance +- using large banner-style output where one clear status line would do +- adding confirmations or prompts in a way that breaks automation + +## Definition of done + +- The user can discover how to invoke the command from the terminal surface they are using. +- Long-running, risky, and error paths expose enough state to keep the user oriented. +- 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. diff --git a/src/resources/agentic-copilot/AGENTS.md b/src/resources/agentic-copilot/AGENTS.md index 9e79b5e..0b29962 100644 --- a/src/resources/agentic-copilot/AGENTS.md +++ b/src/resources/agentic-copilot/AGENTS.md @@ -39,15 +39,15 @@ For new or not-yet-scoped work, use the `architect` agent with `.github/prompts/ The table below shows how to route work. Prompts are the task entry points; each prompt delegates to its agent, which uses the listed skills, which in turn enforce the listed instructions. -| Task | Prompt | Agent | Primary skills | Primary instructions | -| ----------------------------- | ------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------- | -| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `workflow guidance`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | -| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `pester-testing`, `building-maintainable-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | -| Review a change | `review-change.prompt.md` | `reviewer` | `building-maintainable-code`, `documentation`, `markdown-authoring`, `pester-testing`, `release-and-changelog`, `workflow guidance` | All `.github/instructions/*.instructions.md` | -| Improve test coverage | `improve-test-coverage.prompt.md` | `test-engineer` | `pester-testing`, `building-maintainable-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`) | `workflow guidance`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | -| Update project docs | (no dedicated prompt — invoke agent) | `documentation` | `documentation`, `markdown-authoring` | `documentation` | +| Task | Prompt | Agent | Primary skills | Primary instructions | +|--------------------------|--------------------------------------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------| +| Design or scope a change | `design-change.prompt.md` | `architect` | `powershell-module-development`, `terminal-ux-design`, `workflow guidance`, `release-and-changelog`, `markdown-authoring` | `repository-conventions`, `code-quality-matrix` | +| Implement an issue | `implement-issue.prompt.md` | `powershell-developer` | `powershell-module-development`, `terminal-ux-design`, `pester-testing`, `building-maintainable-code` | `repository-conventions`, `code-quality-matrix`, `psscriptanalyzer`, `powershell-coding-standards`, `platyps-help` | +| Review a change | `review-change.prompt.md` | `reviewer` | `terminal-ux-design`, `building-maintainable-code`, `documentation`, `markdown-authoring`, `pester-testing`, `release-and-changelog`, `workflow guidance` | All `.github/instructions/*.instructions.md` | +| Improve test coverage | `improve-test-coverage.prompt.md` | `test-engineer` | `pester-testing`, `building-maintainable-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`) | `workflow guidance`, `pester-testing` | `testing-policy`, `psscriptanalyzer`, `repository-conventions` | +| Update project docs | (no dedicated prompt — invoke agent) | `documentation` | `documentation`, `markdown-authoring` | `documentation` | ## Notation @@ -63,5 +63,6 @@ The table below shows how to route work. Prompts are the task entry points; each - PSScriptAnalyzer workflow: `.github/instructions/psscriptanalyzer.instructions.md` - PowerShell coding standards: `.github/instructions/powershell-coding-standards.instructions.md` - PlatyPS help generation: `.github/instructions/platyps-help.instructions.md` +- Terminal UX: `.github/instructions/terminal-ux-design.instructions.md` + `terminal-ux-design` skill - Release flow: `.github/instructions/release-policy.instructions.md` + `release-and-changelog` skill - Documentation separation: `.github/instructions/documentation.instructions.md` + `documentation` skill diff --git a/tests/AgenticCopilotScaffoldSync.Tests.ps1 b/tests/AgenticCopilotScaffoldSync.Tests.ps1 index d8cbdda..8fa13ea 100644 --- a/tests/AgenticCopilotScaffoldSync.Tests.ps1 +++ b/tests/AgenticCopilotScaffoldSync.Tests.ps1 @@ -17,14 +17,17 @@ BeforeAll { return [pscustomobject]@{ Instruction = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/copilot-instructions.md') -Raw RepositoryConventions = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/repository-conventions.instructions.md') -Raw + TerminalUxInstruction = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/terminal-ux-design.instructions.md') -Raw QualityMatrix = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/code-quality-matrix.instructions.md') -Raw PlatyPsHelp = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/platyps-help.instructions.md') -Raw ScriptAnalyzer = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/psscriptanalyzer.instructions.md') -Raw CodingStandards = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/powershell-coding-standards.instructions.md') -Raw TestingPolicy = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/instructions/testing-policy.instructions.md') -Raw + ArchitectAgent = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/agents/architect.agent.md') -Raw DeveloperAgent = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/agents/powershell-developer.agent.md') -Raw ReviewerAgent = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/agents/reviewer.agent.md') -Raw TestEngineerAgent = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/agents/test-engineer.agent.md') -Raw + TerminalUxSkill = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/skills/terminal-ux-design/SKILL.md') -Raw DeveloperSkill = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/skills/powershell-module-development/SKILL.md') -Raw PesterSkill = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/skills/pester-testing/SKILL.md') -Raw ImplementPrompt = Get-Content -LiteralPath (Join-Path $script:scaffoldRoot '.github/prompts/implement-issue.prompt.md') -Raw @@ -123,6 +126,28 @@ Describe 'Agentic Copilot scaffold sync' { $content.DeveloperSkill | Should -Match 'PowerShell 7\.x-only' } + It 'documents terminal UX guidance in mirrored instructions, skills, and agent entry points' { + $content = & $script:getAgenticScaffoldGuidanceContent + + $content.TerminalUxInstruction | Should -Match 'Use the `terminal-ux-design` skill' + $content.TerminalUxInstruction | Should -Match 'Jakob Nielsen' + $content.TerminalUxInstruction | Should -Match 'Atlassian' + + $content.TerminalUxSkill | Should -Match 'Atlassian''s 10 design principles for delightful CLIs' + $content.TerminalUxSkill | Should -Match 'Jakob Nielsen''s 10 usability heuristics for user interface design' + $content.TerminalUxSkill | Should -Match 'This skill applies even when the surface is not named "CLI"' + $content.TerminalUxSkill | Should -Match 'Combined mapping table' + $content.TerminalUxSkill | Should -Match 'Two surfaces, two conventions' + $content.TerminalUxSkill | Should -Match 'Keep PowerShell cmdlet UX and CLI UX distinct' + + $content.Instruction | Should -Match 'terminal-ux-design' + $content.Instruction | Should -Match 'Terminal UX: `\.github/instructions/terminal-ux-design\.instructions\.md` \+ `terminal-ux-design` skill' + $content.ArchitectAgent | Should -Match '/terminal-ux-design' + $content.DeveloperAgent | Should -Match '/terminal-ux-design' + $content.ReviewerAgent | Should -Match '/terminal-ux-design' + $content.Agents | Should -Match 'terminal-ux-design' + } + It 'documents valid PlatyPS help generation guidance' { $content = & $script:getAgenticScaffoldGuidanceContent diff --git a/tests/ProjectPesterCoverageConfiguration.Tests.ps1 b/tests/ProjectPesterCoverageConfiguration.Tests.ps1 index b3cde6e..6271ad4 100644 --- a/tests/ProjectPesterCoverageConfiguration.Tests.ps1 +++ b/tests/ProjectPesterCoverageConfiguration.Tests.ps1 @@ -1,13 +1,26 @@ BeforeAll { $projectRoot = Split-Path -Parent $PSScriptRoot $script:projectJson = Get-Content -LiteralPath (Join-Path $projectRoot 'project.json') -Raw | ConvertFrom-Json -AsHashtable + $script:projectTemplateJson = Get-Content -LiteralPath (Join-Path $projectRoot 'src/resources/ProjectTemplate.json') -Raw | ConvertFrom-Json -AsHashtable + $script:exampleProjectJson = Get-Content -LiteralPath (Join-Path $projectRoot 'src/resources/example/project.json') -Raw | ConvertFrom-Json -AsHashtable } Describe 'project.json Pester code coverage configuration' { - It 'uses explicit private-source globs so nested helpers stay measurable' { + It 'keeps one recursive private-source glob in the repository config' { $script:projectJson.Pester.CodeCoverage.Path | Should -Be @( 'src/public/*.ps1' 'src/private/**/*.ps1' ) } + + It 'keeps scaffolded project templates aligned with the recursive private-source glob' { + $expectedPath = @( + 'src/public/*.ps1' + 'src/private/**/*.ps1' + 'src/classes/*.ps1' + ) + + $script:projectTemplateJson.Pester.CodeCoverage.Path | Should -Be $expectedPath + $script:exampleProjectJson.Pester.CodeCoverage.Path | Should -Be $expectedPath + } } diff --git a/tests/private/quality/GetNovaTestWorkflowContext.TestSupport.ps1 b/tests/private/quality/GetNovaTestWorkflowContext.TestSupport.ps1 index a71749c..8c4277b 100644 --- a/tests/private/quality/GetNovaTestWorkflowContext.TestSupport.ps1 +++ b/tests/private/quality/GetNovaTestWorkflowContext.TestSupport.ps1 @@ -20,12 +20,16 @@ $script:getPesterConfig = { } $script:getProjectInfo = { - param([Parameter(Mandatory)][object]$PesterSettings) + param( + [Parameter(Mandatory)][object]$PesterSettings, + [string]$ProjectRoot = '/tmp/nova-project' + ) + [pscustomobject]@{ Pester = $PesterSettings BuildRecursiveFolders = $false TestsDir = 'tests' - ProjectRoot = '/tmp/nova-project' - ModuleFilePSM1 = '/tmp/nova-project/dist/TestProject/TestProject.psm1' + ProjectRoot = $ProjectRoot + ModuleFilePSM1 = (Join-Path $ProjectRoot 'dist/TestProject/TestProject.psm1') } } diff --git a/tests/private/quality/GetNovaTestWorkflowContext.Tests.ps1 b/tests/private/quality/GetNovaTestWorkflowContext.Tests.ps1 index bbe5370..abc97c4 100644 --- a/tests/private/quality/GetNovaTestWorkflowContext.Tests.ps1 +++ b/tests/private/quality/GetNovaTestWorkflowContext.Tests.ps1 @@ -55,6 +55,46 @@ Describe 'Get-NovaTestWorkflowContext' { $result = Get-NovaTestWorkflowContext -TestOption @{} -BoundParameters @{} & $AssertResult $result } + + It 'expands configured coverage paths into concrete project-relative source files' { + $projectRoot = Join-Path $TestDrive 'coverage-project' + foreach ($relativePath in @( + 'src/public/GetAlpha.ps1' + 'src/private/GetBeta.ps1' + 'src/private/quality/GetGamma.ps1' + 'src/private/quality/duplicates/GetDelta.ps1' + 'src/classes/NovaThing.ps1' + )) { + $filePath = Join-Path $projectRoot $relativePath + New-Item -ItemType Directory -Path (Split-Path -Parent $filePath) -Force | Out-Null + Set-Content -LiteralPath $filePath -Value '# test' + } + + $pesterConfig = & $script:getPesterConfig + $projectInfo = & $script:getProjectInfo -ProjectRoot $projectRoot -PesterSettings ([ordered]@{ + CodeCoverage = [ordered]@{ + Enabled = $true + Path = @( + 'src/public/*.ps1' + 'src/private/**/*.ps1' + 'src/classes/*.ps1' + ) + } + }) + + Mock Get-NovaProjectInfo {$projectInfo} + Mock New-PesterConfiguration {$pesterConfig} + + $result = Get-NovaTestWorkflowContext -TestOption @{} -BoundParameters @{} + + $result.PesterConfig.CodeCoverage.Path | Should -Be @( + 'src/public/GetAlpha.ps1' + 'src/private/GetBeta.ps1' + 'src/private/quality/duplicates/GetDelta.ps1' + 'src/private/quality/GetGamma.ps1' + 'src/classes/NovaThing.ps1' + ) + } } Describe 'Get-NovaTestWorkflowOperation' { @@ -98,6 +138,16 @@ Describe 'Get-NovaConfiguredPesterCoveragePercentTarget' { } } +Describe 'Get-NovaConfiguredPesterCoveragePath' { + It 'returns an empty array when CodeCoverage is disabled' { + @(Get-NovaConfiguredPesterCoveragePath -ProjectPesterSettings ([ordered]@{CodeCoverage = [ordered]@{Enabled = $false; Path = @('src/private/**/*.ps1')}})).Count | Should -Be 0 + } + + It 'returns configured coverage paths when coverage is enabled' { + Get-NovaConfiguredPesterCoveragePath -ProjectPesterSettings ([ordered]@{CodeCoverage = [ordered]@{Enabled = $true; Path = @('src/public/*.ps1', 'src/private/**/*.ps1')}}) | Should -Be @('src/public/*.ps1', 'src/private/**/*.ps1') + } +} + Describe 'Get-NovaPesterSettingValue' { It 'returns null for null input' { Get-NovaPesterSettingValue -InputObject $null -Name 'X' | Should -BeNullOrEmpty