Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6a95dc3
Fix Pester command invocation in CI workflow
johnmbaughman Oct 2, 2025
57fc9b7
Add script to create a sample ZIP file for tests
johnmbaughman Oct 2, 2025
f34680f
Add step to list tests directory contents
johnmbaughman Oct 2, 2025
699ea65
Fix path in Pester test command in CI workflow
johnmbaughman Oct 2, 2025
9cd74dc
Simplify PowerShell command syntax in CI workflow
johnmbaughman Oct 2, 2025
7e3a337
Update Pester module import to use MinimumVersion
johnmbaughman Oct 2, 2025
61d9996
Update Pester module version requirement in CI
johnmbaughman Oct 2, 2025
451b4f8
add missing zip create script
johnmbaughman Oct 2, 2025
8885caf
Clarify Spec Kit templates source in README
johnmbaughman Oct 2, 2025
b102ce5
Convert Install-SpecKitTemplate.ps1 into a PowerShell module (#5)
Copilot Oct 2, 2025
f3dfd24
Fix workflow for testing module files (#9)
Copilot Oct 2, 2025
954e57d
Fix PSScriptAnalyzer warnings following PowerShell best practices (#7)
Copilot Oct 2, 2025
c9fd2fd
Chore/constitution 1.0.1 (#10)
johnmbaughman Oct 3, 2025
48d8b20
chore(specs): add parameter-sets spec and feature artifacts
johnmbaughman Oct 3, 2025
ef4e146
chore(pr): add PR body for feat/paramsets-install-speckit
johnmbaughman Oct 3, 2025
9c93997
feat: scaffold Install-SpecKitTemplate parameter-set workflow
johnmbaughman Oct 3, 2025
04ec6bc
fix branches parameter
johnmbaughman Oct 3, 2025
5bcb518
Add PowerShell feature with Pester and PSScriptAnalyzer
johnmbaughman Oct 3, 2025
3009271
Task 001 complete
johnmbaughman Oct 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"features": {
"ghcr.io/devcontainers/features/powershell:1": {
"version": "latest",
"modules": "Pester,PSScriptAnalyzer"
}
}
}
24 changes: 24 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# PSSpecKit Development Guidelines

Auto-generated from all feature plans. Last updated: 2025-10-02

## Active Technologies
- PowerShell 7.x (Core-compatible) + PSSpecKit module (`PSSpecKit.psm1`), Pester v5, PSScriptAnalyzer baseline rules (feat/paramsets-install-speckit)

## Project Structure
```
src/
tests/
```

## Commands
# Add commands for PowerShell 7.x (Core-compatible)

## Code Style
PowerShell 7.x (Core-compatible): Follow standard conventions

## Recent Changes
- feat/paramsets-install-speckit: Added PowerShell 7.x (Core-compatible) + PSSpecKit module (`PSSpecKit.psm1`), Pester v5, PSScriptAnalyzer baseline rules

<!-- MANUAL ADDITIONS START -->
<!-- MANUAL ADDITIONS END -->
25 changes: 16 additions & 9 deletions .github/workflows/powershell-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ on:
push:
branches:
- 'v1_specsdev'
- '001-create-a-powershell'
- 'feature/**'
- 'feat/**'
pull_request:
branches:
- 'v1_specsdev'
Expand All @@ -14,26 +14,33 @@ on:
jobs:
lint-and-test:
runs-on: windows-latest
steps:
steps:
- uses: actions/checkout@v4

- name: List tests directory contents
run: |
ls -l tests

- name: Install PSScriptAnalyzer and Pester
run: |
pwsh -Command "Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser -AcceptLicense"
pwsh -Command "Install-Module -Name Pester -MinimumVersion 5.0.0 -Force -Scope CurrentUser -AcceptLicense"
Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser -AcceptLicense
Install-Module -Name Pester -MinimumVersion 5.0.0 -Force -Scope CurrentUser -AcceptLicense

- name: Enforce no absolute paths in scripts
run: |
pwsh -NoProfile -Command "Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass; ./scripts/check-absolute-paths.ps1 -Path ."

- name: Run PSScriptAnalyzer
- name: Run PSScriptAnalyzer on module
run: |
pwsh -NoProfile -Command "Invoke-ScriptAnalyzer -Path ./PSSpecKit -Recurse -Settings .psscriptanalyzer.psd1"

- name: Verify module can be imported
run: |
pwsh -NoProfile -Command "Invoke-ScriptAnalyzer -Path . -Recurse -Settings .psscriptanalyzer.psd1"
pwsh -NoProfile -Command "Import-Module ./PSSpecKit/PSSpecKit.psd1 -Force; Write-Host 'Module imported successfully'; Get-Command -Module PSSpecKit | Format-Table -AutoSize"

- name: Run Pester tests
run: |
pwsh -NoProfile -Command 'Import-Module Pester -RequiredVersion 5.0.0 -Force; $r = Invoke-Pester -Path ./tests -PassThru; if ($r.FailedCount -gt 0) { exit 1 }'
# pwsh -NoProfile -Command "Import-Module Pester -RequiredVersion 5.0.0 -Force; $r = Pester\Invoke-Pester -Path .\tests -PassThru; if ($r.FailedCount -gt 0) { exit 1 }"
pwsh -NoProfile -Command 'Import-Module Pester -MinimumVersion 5.0.0 -Force; $r = Pester\Invoke-Pester -Path .\tests -PassThru; if ($r.FailedCount -gt 0) { exit 1 }'

integration-tests:
runs-on: windows-latest
Expand All @@ -49,4 +56,4 @@ jobs:

- name: Run integration tests only
run: |
pwsh -NoProfile -Command "Import-Module Pester -RequiredVersion 5.0.0 -Force; $r = Pester\Invoke-Pester -Path .\tests\integration -PassThru; if ($r.FailedCount -gt 0) { exit 1 }"
pwsh -NoProfile -Command "Import-Module Pester -MinimumVersion 5.0.0 -Force; $r = Pester\Invoke-Pester -Path .\tests\integration -PassThru; if ($r.FailedCount -gt 0) { exit 1 }"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

# PowerShell temporary files
*.ps1xml
# Don't ignore module files
!PSSpecKit/**/*.psm1
!PSSpecKit/**/*.psd1
*.psm1
*.psd1
*.psd1.updated
Expand Down
3 changes: 3 additions & 0 deletions .psscriptanalyzer.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
@{
# Basic PSScriptAnalyzer settings tuned for this project
# Rules must be provided as a hashtable mapping rule names to settings
# NOTE: When running PSScriptAnalyzer, exclude the .specify directory as it contains
# internal tooling scripts that are not part of the application:
# Invoke-ScriptAnalyzer -Path . -Settings .psscriptanalyzer.psd1 -Recurse -ExcludePath .specify
Rules = @{
PSUseApprovedVerbs = @{ Enable = $true }
PSAvoidUsingPlainTextForPassword = @{ Enable = $true }
Expand Down
29 changes: 15 additions & 14 deletions .specify/memory/constitution.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
<!--
Sync Impact Report
Version change: none → 1.0.0
Version change: 1.0.0 → 1.0.1
Modified principles:
- NEW: Code Quality & Style (PowerShell-centric)
- NEW: Testing Standards (Pester & CI gates)
- UPDATED: Code Quality & Style (explicit PSScriptAnalyzer enforcement & Microsoft PowerShell scripting best practices)
- NEW/CLARIFY: Testing Standards (Pester & CI gates clarified to include static analysis gating)
- NEW: User Experience Consistency (cmdlet UX, help, output contracts)
- NEW: Performance Requirements (benchmarks, memory/latency goals)
Added sections:
Added/clarified sections:
- Development Constraints (PowerShell module rules, compatibility targets)
- Development Workflow (TDD, PR review checklist, PSScriptAnalyzer gating)
- Development Workflow (TDD, PR review checklist, explicit PSScriptAnalyzer gating)
Removed sections: none
Templates requiring updates:
- .specify/templates/plan-template.md ✅ inspected (Constitution Check placeholder present; aligns with new principles)
Templates requiring updates / inspection:
- .specify/templates/plan-template.md ✅ inspected (Constitution Check placeholder present; aligns with updated principles)
- .specify/templates/spec-template.md ✅ inspected (requirements gating aligns)
- .specify/templates/tasks-template.md ✅ inspected (task rules align)
Follow-up TODOs:
- TODO(RATIFICATION_DATE): Confirm historical ratification date if this is not the first adoption (left as ratified today)
- None deferred. RATIFICATION_DATE retained as original adoption date.
-->

# PSSpecKit Constitution

## Core Principles

### I. Code Quality & Style (PowerShell-centric)
All authored PowerShell code MUST follow Microsoft PowerShell best practices. This includes:
- Consistent, discoverable names following Verb-Noun cmdlet conventions (approved verbs from Microsoft). Module, function, and parameter names MUST be clear and purpose-driven.
- Script and module layout MUST follow common PowerShell module structure (ExportedFunctions, Public/Private separation, module manifest when applicable).
- Static analysis using PSScriptAnalyzer with a project baseline is REQUIRED; rules MAY be tightened per-module. Violations MUST be addressed before merging.
- Code MUST be idempotent where applicable and avoid implicit global state; side-effects MUST be explicit and documented.
All authored PowerShell code MUST meet Microsoft PowerShell scripting best practices and pass the project's PSScriptAnalyzer quality checks. This is a mandatory, CI-enforced gate. Specifically:
- All code MUST adhere to Microsoft-approved naming conventions (Verb-Noun) and use discoverable, purpose-driven names for modules, functions and parameters.
- Script and module layouts MUST follow common PowerShell module structure (ExportedFunctions, Public/Private separation, and a module manifest when applicable).
- Static analysis using PSScriptAnalyzer against a project baseline configuration is REQUIRED; module-level rules MAY be tightened. CI MUST fail if PSScriptAnalyzer violations are present and violations MUST be addressed before merging.
- All scripts and modules MUST document any accepted deviations from the baseline (with rationale) in the PR; exceptions are time-limited and require maintainer approval.
- Code MUST be idempotent where applicable, avoid implicit global state, and make side-effects explicit and documented.

Path usage policy: NO absolute filesystem paths are permitted inside committed scripts or modules. All filesystem paths referenced by scripts MUST be relative to the script/module root and must be resolved at runtime using the script's location (for example, $PSScriptRoot) or a small, documented repository-root resolution helper called from the script root. Hard-coded absolute paths will fail review and MUST be removed before merge.

Expand Down Expand Up @@ -73,4 +74,4 @@ The Constitution defines mandatory practices for development and review. Amendme
- Versioning Policy: The Constitution uses semantic versioning: MAJOR for breaking governance changes (removals or redefinitions), MINOR for new principles or material expansions, PATCH for wording/clarity fixes. The author of the PR MUST indicate the expected bump and rationale.
- Compliance: The `Constitution Check` step in `.specify/templates/plan-template.md` and related templates MUST be evaluated during planning. CI tooling and reviewers are responsible for enforcing gates.

**Version**: 1.0.0 | **Ratified**: 2025-10-01 | **Last Amended**: 2025-10-01
**Version**: 1.0.1 | **Ratified**: 2025-10-01 | **Last Amended**: 2025-10-02
2 changes: 1 addition & 1 deletion .specify/templates/plan-template.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ directories captured above]
- Quickstart test = story validation steps

5. **Update agent file incrementally** (O(1) operation):
- Run `.specify/scripts/powershell/update-agent-context.ps1 -AgentType windsurf`
- Run `.specify/scripts/powershell/update-agent-context.ps1 -AgentType copilot`
**IMPORTANT**: Execute it exactly as specified above. Do not add or remove any arguments.
- If exists: Add only NEW tech from current plan
- Preserve manual additions between markers
Expand Down
21 changes: 21 additions & 0 deletions PR_BODY_chore-constitution-1.0.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Title: docs: constitution v1.0.1 — require PSScriptAnalyzer & clarify PowerShell best practices

Body:
Clarify Code Quality & Style to explicitly require PSScriptAnalyzer checks and adherence to Microsoft
PowerShell scripting best practices.

- Bump constitution version 1.0.0 → 1.0.1 (patch: clarifications).
- Update Sync Impact Report and Last Amended date (2025-10-02).
- Confirmed related specify templates align with the new gating rules.

Suggested follow-ups:
- Ensure CI installs and runs PSScriptAnalyzer (add to `.github/workflows/powershell-ci.yml` if missing).
- Optionally add a PSScriptAnalyzer baseline ruleset and wire into CI.

Files changed:
- .specify/memory/constitution.md

PR checklist:
- [ ] CI passes (Pester + PSScriptAnalyzer)
- [ ] Reviewers: at least two maintainers for non-breaking updates
- [ ] If adding PSScriptAnalyzer baseline, include ruleset path in PR
40 changes: 40 additions & 0 deletions PR_BODY_feat-paramsets-install-speckit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
Title: feat(paramsets): add Interactive and Noninteractive ParameterSets to Install-SpecKitTemplate

Summary

This PR implements the design and planning artifacts for adding two ParameterSets to `tools/Install-SpecKitTemplate.ps1`:
- `Interactive` parameter set: prompts for Agent, Shell, Version, Path, and Force when run in a TTY.
- `Noninteractive` parameter set: accepts all parameters explicitly for CI usage.

What changed (files added/updated)

- Added feature spec and artifacts under `specs/002-parameter-sets/`:
- `spec.md`, `plan.md`, `research.md`, `data-model.md`, `quickstart.md`, `tasks.md`
- Added feature copies under `specs/feat/paramsets-install-speckit/` for plan integration.
- Updated `tools/Install-SpecKitTemplate.ps1` (parameter-set plumbing and local edits present in branch).

Behavior & Acceptance

- Interactive runs will prompt only when targets exist or parameters are missing; SaveZip/Retry use defaults unless supplied.
- Running `-Interactive` in a non-TTY environment fails with exit code 2.
- Parameter-set validation is strict; incompatible parameter combinations fail with exit code 3.
- Overwrite confirmation uses a single prompt offering Yes/YesToAll/No/NoToAll; No aborts with exit code 3.

Testing

- This PR includes tasks and test plans under `specs/*` but does not yet add the final Pester test files. The next steps in tasks.md cover adding Pester tests and implementing code to satisfy them.

Notes

- The `gh` CLI is not available in the execution environment; opening the PR via the GitHub web UI is recommended. Use the auto-generated URL below or paste this body into the PR form.

Open PR URL

https://github.com/johnmbaughman/PSSpecKit/pull/new/feat/paramsets-install-speckit

Reviewer checklist

- [ ] Confirm spec and research artifacts align with implementation direction
- [ ] Review `tools/Install-SpecKitTemplate.ps1` parameter-set changes and validate no regressions
- [ ] Run the Pester tests once T002/T003 are implemented

133 changes: 133 additions & 0 deletions PSSpecKit/PSSpecKit.psd1
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#
# Module manifest for module 'PSSpecKit'
#
# Generated by: PSSpecKit Contributors
#
# Generated on: 10/02/2025
#

@{

# Script module or binary module file associated with this manifest.
RootModule = 'PSSpecKit.psm1'

# Version number of this module.
ModuleVersion = '1.0.0'

# Supported PSEditions
# CompatiblePSEditions = @()

# ID used to uniquely identify this module
GUID = 'e99b9261-d8cf-4f06-9a6d-983a8f298378'

# Author of this module
Author = 'PSSpecKit Contributors'

# Company or vendor of this module
CompanyName = 'Unknown'

# Copyright statement for this module
Copyright = '(c) PSSpecKit Contributors. All rights reserved.'

# Description of the functionality provided by this module
Description = 'Tools for downloading and installing GitHub Spec Kit templates'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '7.0'

# Name of the PowerShell host required by this module
# PowerShellHostName = ''

# Minimum version of the PowerShell host required by this module
# PowerShellHostVersion = ''

# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# DotNetFrameworkVersion = ''

# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
# ClrVersion = ''

# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''

# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()

# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()

# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()

# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()

# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()

# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = 'Install-SpecKitTemplate', 'Test-ZipArchive', 'Expand-SafeArchive',
'Find-ReleaseAsset', 'Get-LatestRelease', 'Save-ReleaseAsset'

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()

# Variables to export from this module
# VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @()

# DSC resources to export from this module
# DscResourcesToExport = @()

# List of all modules packaged with this module
# ModuleList = @()

# List of all files packaged with this module
# FileList = @()

# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{

PSData = @{

# Tags applied to this module. These help with module discovery in online galleries.
Tags = 'spec-kit', 'templates', 'github'

# A URL to the license for this module.
LicenseUri = 'https://github.com/johnmbaughman/PSSpecKit/blob/main/LICENSE'

# A URL to the main website for this project.
ProjectUri = 'https://github.com/johnmbaughman/PSSpecKit'

# A URL to an icon representing this module.
# IconUri = ''

# ReleaseNotes of this module
# ReleaseNotes = ''

# Prerelease string of this module
# Prerelease = ''

# Flag to indicate whether the module requires explicit user acceptance for install/update/save
# RequireLicenseAcceptance = $false

# External dependent modules of this module
# ExternalModuleDependencies = @()

} # End of PSData hashtable

} # End of PrivateData hashtable

# HelpInfo URI of this module
# HelpInfoURI = ''

# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''

}

Loading