Skip to content

feat(skills): mandate unit testing and document language support#636

Merged
WilliamBerryiii merged 5 commits intomainfrom
feat/634-skills-unit-testing
Feb 17, 2026
Merged

feat(skills): mandate unit testing and document language support#636
WilliamBerryiii merged 5 commits intomainfrom
feat/634-skills-unit-testing

Conversation

@WilliamBerryiii
Copy link
Copy Markdown
Member

@WilliamBerryiii WilliamBerryiii commented Feb 17, 2026

Description

Added unit testing requirements with an 80% code coverage minimum for skill contributions and documented supported programming languages. Tests use a co-located tests/ directory pattern inside each skill, keeping skills self-contained. Updated Pester coverage configuration and extension packaging to support the new test structure.

  • feat(skills): added "Untested Skills" rejection criterion requiring unit tests with 80% code coverage
  • feat(skills): added Unit Testing Requirements section with test file layout, PowerShell and Python conventions, and packaging exclusion notes
  • feat(skills): added Supported Languages table documenting PowerShell (full CI) and Python (planned CI) with tooling expectations
  • feat(skills): added Testing checklist to the pre-submission verification section and npm run test:ps to automated validation
  • feat(skills): updated file structure diagram to include tests/ subdirectory
  • feat(extension): added co-located tests/ directory exclusion from VSIX packaging in Package-Extension.ps1
  • feat(scripts): extended Pester coverage configuration to discover and report on skill scripts from .github/skills/
  • docs(architecture): added Skills Testing section to docs/architecture/testing.md covering co-located test pattern, coverage integration, and packaging exclusion
  • docs(contributing): added paragraph in CONTRIBUTING.md explaining skill test co-location pattern with link to Skills Guide
  • feat(skills): added Programming Language dropdown (PowerShell, Python, Other) to skill request issue template with clarified cross-platform description
  • fix(skills): added pyproject to cspell word list
  • fix(skills): fixed table alignment in Supported Languages table
  • fix(templates): added "Other" option to skill request language dropdown to match documentation reference

Related Issue(s)

Closes #634

Type of Change

Select all that apply:

Code & Documentation:

  • Bug fix (non-breaking change fixing an issue)
  • New feature (non-breaking change adding functionality)
  • Breaking change (fix or feature causing existing functionality to change)
  • Documentation update

Infrastructure & Configuration:

  • GitHub Actions workflow
  • Linting configuration (markdown, PowerShell, etc.)
  • Security configuration
  • DevContainer configuration
  • Dependency update

AI Artifacts:

  • Reviewed contribution with prompt-builder agent and addressed all feedback
  • Copilot instructions (.github/instructions/*.instructions.md)
  • Copilot prompt (.github/prompts/*.prompt.md)
  • Copilot agent (.github/agents/*.agent.md)
  • Copilot skill (.github/skills/*/SKILL.md)

Note for AI Artifact Contributors:

  • Agents: Research, indexing/referencing other project (using standard VS Code GitHub Copilot/MCP tools), planning, and general implementation agents likely already exist. Review .github/agents/ before creating new ones.
  • Skills: Must include PowerShell scripts for cross-platform support. See Skills.
  • Model Versions: Only contributions targeting the latest Anthropic and OpenAI models will be accepted. Older model versions (e.g., GPT-3.5, Claude 3) will be rejected.
  • See Agents Not Accepted and Model Version Requirements.

Other:

  • Script/automation (.ps1, .sh, .py)
  • Other (please describe):

Sample Prompts (for AI Artifact Contributions)

Testing

  • All four linters pass clean: lint:md, lint:yaml, lint:frontmatter, lint:ps
  • All 228 Pester tests pass (pre-existing LASTEXITCODE: -1 leak from subprocess invocations is unrelated)
  • No new skill scripts exist yet, so skill coverage path resolution executes the Test-Path guard without error

Checklist

Required Checks

  • Documentation is updated (if applicable)
  • Files follow existing naming conventions
  • Changes are backwards compatible (if applicable)
  • Tests added for new functionality (if applicable)

AI Artifact Contributions

  • Used /prompt-analyze to review contribution
  • Addressed all feedback from prompt-builder review
  • Verified contribution follows common standards and type-specific requirements

Required Automated Checks

The following validation commands must pass before merging:

  • Markdown linting: npm run lint:md
  • Spell checking: npm run spell-check
  • Frontmatter validation: npm run lint:frontmatter
  • Link validation: npm run lint:md-links
  • PowerShell analysis: npm run lint:ps

Security Considerations

  • This PR does not contain any sensitive or NDA information
  • Any new dependencies have been reviewed for security issues
  • Security-related scripts follow the principle of least privilege

Additional Notes

  • Bash was intentionally excluded from the Supported Languages table; it may be added in a future iteration
  • The 80% code coverage threshold applies to skill scripts only; the repository-wide informational baseline remains at 18%
  • No GHCP artifacts (instructions, prompts, agents, skills) were modified in this PR

🧪 - Generated by Copilot

- Add unit testing requirements with 80% code coverage minimum
- Add supported languages table (PowerShell, Python)
- Extend Pester coverage config to discover skill scripts
- Add tests/ exclusion to extension packaging
- Add programming language dropdown to skill request template

Closes #634

✨ - Generated by Copilot
Copilot AI review requested due to automatic review settings February 17, 2026 00:41
@WilliamBerryiii WilliamBerryiii requested a review from a team as a code owner February 17, 2026 00:41
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 17, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Feb 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.47%. Comparing base (bd7d512) to head (3e73c83).
⚠️ Report is 157 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #636      +/-   ##
==========================================
- Coverage   85.48%   85.47%   -0.02%     
==========================================
  Files          23       23              
  Lines        4541     4543       +2     
==========================================
+ Hits         3882     3883       +1     
- Misses        659      660       +1     
Flag Coverage Δ
pester 85.47% <100.00%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
scripts/extension/Package-Extension.ps1 94.83% <100.00%> (+0.03%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR establishes unit testing requirements for GitHub Copilot skills, mandating 80% code coverage with co-located test directories to keep skills self-contained. It documents supported programming languages (PowerShell with full CI, Python with planned CI), extends Pester coverage to include skill scripts, and ensures test directories are excluded from extension packaging.

Changes:

  • Added "Untested Skills" rejection criterion requiring unit tests with 80% code coverage minimum
  • Extended Pester configuration to discover and report on skill scripts from .github/skills/ for code coverage
  • Updated extension packaging to exclude co-located tests/ directories from VSIX packages
  • Added comprehensive Unit Testing Requirements and Supported Languages sections to skills documentation
  • Added Testing checklist items and npm run test:ps to pre-submission validation workflow

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
scripts/tests/pester.config.ps1 Extends coverage path resolution to include .github/skills/ directory with proper guards and array concatenation
scripts/extension/Package-Extension.ps1 Adds removal of co-located tests/ directories after copying skill artifacts to extension package
docs/contributing/skills.md Adds Unit Testing Requirements, Supported Languages table, Python test conventions, and Testing checklist section
docs/architecture/testing.md Documents Skills Testing section covering co-located test pattern, coverage integration, and packaging exclusion
CONTRIBUTING.md Adds paragraph explaining skill test co-location pattern with reference to Skills Guide
.github/ISSUE_TEMPLATE/skill-request.yml Adds Programming Language dropdown field with PowerShell and Python options

WilliamBerryiii and others added 2 commits February 16, 2026 17:06
- add pyproject to cspell word list

- fix table alignment in Supported Languages table

- add Other option to skill-request language dropdown

- clarify cross-platform requirement in dropdown description

🔧 - Generated by Copilot
Copilot AI review requested due to automatic review settings February 17, 2026 10:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 7 comments.

WilliamBerryiii and others added 2 commits February 17, 2026 14:45
- correct file structure diagrams to show scripts/ subdirectory
- clarify test discovery requires explicit path inclusion
- add Bash row to Supported Languages table
- update skill-request template to mention Bash and PowerShell
- narrow pester coverage scan to per-skill script collection

📝 - Generated by Copilot
Copilot AI review requested due to automatic review settings February 17, 2026 22:50
@WilliamBerryiii WilliamBerryiii merged commit 9263617 into main Feb 17, 2026
22 checks passed
@WilliamBerryiii WilliamBerryiii deleted the feat/634-skills-unit-testing branch February 17, 2026 22:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

$skillScripts = Join-Path $skillRoot 'scripts'
$paths = @()

$paths += Get-ChildItem -Path $skillRoot -Include '*.ps1', '*.psm1' -File -ErrorAction SilentlyContinue
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -Include parameter on this line requires a -Recurse or -Filter parameter to work correctly with Get-ChildItem. Without -Recurse, -Include is ignored when enumerating files in a single directory.

Since this line is enumerating files directly in $skillRoot (not recursively), the -Include parameter will have no effect. Scripts at the skill root level (e.g., .github/skills/video-to-gif/convert.ps1) will not be discovered.

Either:

  1. Remove the -Include parameter and use -Filter '*.ps1' | Where-Object { $_.Extension -in '.ps1', '.psm1' }
  2. Add the -Recurse parameter (though this would also include scripts in subdirectories, which may not be intended)
  3. Use two separate Get-ChildItem calls with -Filter '*.ps1' and -Filter '*.psm1'

Note that line 73 correctly uses -Include with -Recurse for the scripts subdirectory.

Suggested change
$paths += Get-ChildItem -Path $skillRoot -Include '*.ps1', '*.psm1' -File -ErrorAction SilentlyContinue
$paths += Get-ChildItem -Path $skillRoot -File -ErrorAction SilentlyContinue |
Where-Object { $_.Extension -in '.ps1', '.psm1' }

Copilot uses AI. Check for mistakes.
Comment on lines +191 to +198
Coverage path resolution for skills uses the repository root rather than `$scriptRoot` (which points to `scripts/`):

```powershell
$repoRoot = Split-Path $scriptRoot -Parent
$skillScripts = Get-ChildItem -Path (Join-Path $repoRoot '.github/skills') `
-Include '*.ps1', '*.psm1' -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\.Tests\.ps1$' }
```
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code example shown here is a simplified version that doesn't accurately represent the actual implementation in scripts/tests/pester.config.ps1. The actual implementation:

  1. Iterates through skill directories and checks both the skill root and the scripts/ subdirectory separately
  2. Uses a $paths array to accumulate results before filtering
  3. Applies the test file filter (-notmatch '\.Tests\.ps1$') after collecting all paths

The example implies a single recursive search with inline filtering, which doesn't match the actual logic. Consider either:

  1. Showing the actual code block from pester.config.ps1 (lines 65-78)
  2. Adding a note that this is a conceptual example, not the literal implementation
  3. Simplifying the example further to just explain the concept without showing misleading code
Suggested change
Coverage path resolution for skills uses the repository root rather than `$scriptRoot` (which points to `scripts/`):
```powershell
$repoRoot = Split-Path $scriptRoot -Parent
$skillScripts = Get-ChildItem -Path (Join-Path $repoRoot '.github/skills') `
-Include '*.ps1', '*.psm1' -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\.Tests\.ps1$' }
```
Conceptually, coverage path resolution for skills uses the repository root rather than `$scriptRoot` (which points to `scripts/`):
```powershell
# Conceptual example only; see scripts/tests/pester.config.ps1 for the full implementation.
$repoRoot = Split-Path $scriptRoot -Parent
$skillScripts = Get-ChildItem -Path (Join-Path $repoRoot '.github/skills') `
-Include '*.ps1', '*.psm1' -Recurse -File -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\.Tests\.ps1$' }

Copilot uses AI. Check for mistakes.
Comment on lines +567 to +569
# Remove co-located test directories from packaged skills
Get-ChildItem -Path $destPath -Directory -Filter 'tests' -Recurse -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test directory removal happens after copying the skill to $destPath, but the logic assumes $destPath is a directory. Looking at line 565, Copy-Item with -Recurse copies the skill directory structure, so $destPath should indeed be a directory.

However, the Get-ChildItem -Path $destPath -Directory -Filter 'tests' -Recurse will find ALL tests directories within the skill, including nested ones. If a skill contains example projects or nested structures with their own tests directories, those would also be removed.

Consider either:

  1. Limiting the search to the immediate child level: Get-ChildItem -Path $destPath -Directory -Filter 'tests' -Depth 1 (requires PS 5.0+)
  2. Adding a more specific filter based on the documented structure (e.g., only remove tests directories that are direct children of the skill root)
  3. Documenting in the Skills Guide that nested tests directories in examples or subprojects will also be excluded from packaging
Suggested change
# Remove co-located test directories from packaged skills
Get-ChildItem -Path $destPath -Directory -Filter 'tests' -Recurse -ErrorAction SilentlyContinue |
Remove-Item -Recurse -Force
# Remove co-located root-level test directory from packaged skills
$testsRoot = Join-Path -Path $destPath -ChildPath 'tests'
if (Test-Path -LiteralPath $testsRoot -PathType Container) {
Remove-Item -LiteralPath $testsRoot -Recurse -Force
}

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +316
| Bash | `.sh` | N/A | shellcheck | Lint only |
| PowerShell | `.ps1` | Pester 5.x | PSScriptAnalyzer | Full (lint + test) |
| Python | `.py` | pytest | ruff (line-length=88, target-version=py311) | Planned |
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an inconsistency regarding Bash script testing requirements:

  1. Line 46 states that "Untested Skills" (lacking unit tests or failing to achieve 80% code coverage) will be rejected
  2. Line 266 states "All skill scripts MUST include unit tests that achieve a minimum of 80% code coverage"
  3. However, the Supported Languages table (line 314) lists Bash with "N/A" for Test Framework and "Lint only" for CI Coverage
  4. The Unit Testing Requirements section includes subsections for PowerShell Tests and Python Tests, but not for Bash Tests
  5. The issue template description (line 24 in skill-request.yml) states "All skills require Bash (macOS/Linux) and PowerShell (Windows) scripts"

This creates ambiguity: are Bash scripts exempt from the testing requirement, or is testing infrastructure simply not yet available? If Bash scripts are exempt, the wording at lines 46 and 266 should be clarified to specify "PowerShell and Python scripts" rather than "all skill scripts". If Bash scripts do require tests, the table should indicate the expected test framework (e.g., BATS, shunit2) and the Unit Testing Requirements section should include a Bash Tests subsection.

Copilot uses AI. Check for mistakes.
WilliamBerryiii pushed a commit that referenced this pull request Feb 20, 2026
🤖 I have created a release *beep* *boop*
---


##
[3.0.0](hve-core-v2.3.10...hve-core-v3.0.0)
(2026-02-20)


### ⚠ BREAKING CHANGES

* **skills:** migrate PR reference generation to self-contained skill
([#669](#669))
* restructure RPI collection to HVE Core naming convention
([#668](#668))

### ✨ Features

* **agents:** add agile-coach agent
([#562](#562))
([de8d86c](de8d86c))
* **agents:** add DT coach agent with tiered instruction loading
([#656](#656))
([206d3a7](206d3a7))
* **agents:** add product manager advisor and UX/UI designer agents
([#627](#627))
([539eb8a](539eb8a))
* **agents:** add system architecture reviewer for design trade-offs and
ADR creation ([#626](#626))
([de5cfd6](de5cfd6))
* **build:** pin devcontainer image and align tool parity
([#704](#704))
([6258b1c](6258b1c))
* **design-thinking:** add manufacturing industry context template
([#682](#682))
([ce864bf](ce864bf))
* **instructions:** add DT coaching state protocol for session
persistence ([#654](#654))
([5a5be4e](5a5be4e))
* **instructions:** add dt-coaching-identity ambient instruction
([#642](#642))
([6209a0d](6209a0d))
* **instructions:** add dt-method-01-deep for advanced scope
conversation techniques
([#673](#673))
([cc92ef9](cc92ef9))
* **instructions:** add dt-method-03-deep for advanced input synthesis
techniques ([#676](#676))
([0079a4f](0079a4f))
* **instructions:** add dt-method-09-deep instructions for Method 9
advanced coaching
([#703](#703))
([150b2a6](150b2a6))
* **instructions:** add dt-method-sequencing ambient instruction
([#650](#650))
([e465b2f](e465b2f))
* **instructions:** add dt-quality-constraints and design-thinking
collection ([#645](#645))
([17002bd](17002bd))
* **instructions:** add DT-to-RPI handoff contract specification
([#679](#679))
([87f9962](87f9962))
* **instructions:** add energy industry context template
([#687](#687))
([41088d8](41088d8))
* **instructions:** add healthcare industry context template
([#686](#686))
([b2d5281](b2d5281))
* **instructions:** add Method 1 Scope Conversations coaching knowledge
([#651](#651))
([93e2d48](93e2d48))
* **instructions:** add Method 2 Design Research coaching knowledge
([#652](#652))
([30f7f3b](30f7f3b))
* **instructions:** add Method 3 Input Synthesis coaching knowledge
([#653](#653))
([1efdb7d](1efdb7d))
* **instructions:** add Method 7 High-Fidelity Prototypes coaching
instruction ([#666](#666))
([9233eab](9233eab))
* **instructions:** add pull request instructions for PR generation
workflow ([#706](#706))
([73d23eb](73d23eb))
* **instructions:** create DT curriculum content (9 modules)
([#690](#690))
([9f7378f](9f7378f)),
closes [#617](#617)
* **instructions:** create dt-method-02-deep.instructions.md
([#700](#700))
([4d4d0ca](4d4d0ca))
* **instructions:** create dt-method-06-lofi-prototypes.instructions.md
([#684](#684))
([4d5f757](4d5f757))
* **instructions:** create dt-method-07-deep.instructions.md
([#678](#678))
([d3ec70d](d3ec70d))
* **instructions:** Create dt-method-08-deep.instructions.md
([#683](#683))
([d9e1115](d9e1115))
* **instructions:** create dt-method-08-testing.instructions.md
([#681](#681))
([3008ad8](3008ad8))
* **instructions:** create dt-method-09-iteration.instructions.md
([#685](#685))
([9d7f4f5](9d7f4f5))
* **instructions:** create dt-rpi-research-context.instructions.md
([#689](#689))
([34c7b89](34c7b89))
* **instructions:** create manufacturing reference learning scenario
([#692](#692))
([1bd3994](1bd3994))
* **instructions:** Design Thinking Method 4 brainstorming instruction
file ([#664](#664))
([06f90b0](06f90b0))
* **prompts:** add DT start-project prompt for coaching initialization
([#657](#657))
([ce583d5](ce583d5))
* **prompts:** add dt-resume-coaching prompt for session recovery
([#665](#665))
([11b93cb](11b93cb))
* **prompts:** create dt-handoff-problem-space.prompt.md
([#688](#688))
([277963d](277963d))
* **scripts:** add collection-level maturity field with validation,
gating, and notices
([#697](#697))
([7b1c8e8](7b1c8e8))
* **scripts:** add per-violation CI annotations and colorized console
output ([#637](#637))
([bd7d512](bd7d512))
* **skills:** edit SKILL frontmatter schema, add CI validation, and
documentation ([#625](#625))
([0138a78](0138a78))
* **skills:** mandate unit testing and document language support
([#636](#636))
([9263617](9263617))
* **skills:** migrate PR reference generation to self-contained skill
([#669](#669))
([cf8805f](cf8805f))


### 🐛 Bug Fixes

* **collections:** migrate artifacts into collection-based
subdirectories
([#658](#658))
([dfa5261](dfa5261))
* **instructions:** optimize Phase 1 DT token budgets and close
[#564](https://github.com/microsoft/hve-core/issues/564)/[#565](https://github.com/microsoft/hve-core/issues/565)
gaps ([#675](#675))
([4f42f00](4f42f00))
* **scripts:** add CI annotations and step summary to copyright header
check ([#638](#638))
([5fa6328](5fa6328))
* **scripts:** add grouped link-lang console diagnostics and failure
summary ([#661](#661))
([4d6871f](4d6871f))
* **scripts:** add per-violation Write-Host and Write-CIAnnotation
output to Test-DependencyPinning
([#640](#640))
([9d3b71d](9d3b71d))
* **scripts:** align agent frontmatter schema with VS Code spec
([#469](#469))
([254d445](254d445))
* **scripts:** optimize PSScriptAnalyzer linting performance in WSL2
([#667](#667))
([f120b93](f120b93))
* **scripts:** stabilize YAML display key ordering in collection
manifest ([#701](#701))
([73c0d2c](73c0d2c))
* **scripts:** use text stubs for plugin links when symlinks unavailable
([#695](#695))
([d7650a3](d7650a3))
* **skills:** fix powershell test coverage in pr-reference skill
([#699](#699))
([408e6b7](408e6b7))


### 📚 Documentation

* **dt:** add Method 5 Concepts and Method 6 Lo-Fi Prototypes
instructions ([#693](#693))
([cfdcf11](cfdcf11))
* **hve-guide:** add role-based guides and project lifecycle
documentation ([#663](#663))
([17a85da](17a85da))


### ♻️ Refactoring

* restructure RPI collection to HVE Core naming convention
([#668](#668))
([120dde0](120dde0))
* **scripts:** consolidate duplicate logging into shared SecurityHelpers
module ([#655](#655))
([627a877](627a877))
* **scripts:** use shared SecurityHelpers and CIHelpers modules in
security scripts
([#705](#705))
([3a0baa7](3a0baa7))


### 🔧 Maintenance

* **deps-dev:** bump markdownlint-cli2 from 0.20.0 to 0.21.0 in the
npm-dependencies group
([#609](#609))
([1486dd7](1486dd7))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: hve-core-release-please[bot] <254602402+hve-core-release-please[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(skills): Mandate unit testing, extend CI coverage, and document language support process

5 participants