Analyze only changed files

July 8, 2026 · View on GitHub

This directory contains PowerShell scripts for validating code quality and documentation standards in the hve-core repository.

Architecture

The linting scripts follow a modular architecture with shared helper functions:

ComponentDescription
Wrapper Scripts (Invoke-*.ps1)Entry points that orchestrate validation logic
Core ScriptsExisting validation logic (e.g., Link-Lang-Check.ps1, Validate-MarkdownFrontmatter.ps1)
Shared Module (Modules/LintingHelpers.psm1)Common functions for file discovery and git operations
Shared Module (Modules/AdrBodyParser.psm1)Parse ADR body sections, headings, bullets, table rows, and path-shaped tokens for downstream consistency checks
Shared Module (Modules/AdrConsistency.psm1)Implement the ADR consistency rule registry and validation logic for Govern-phase ADR checks
CI Helpers (scripts/lib/Modules/CIHelpers.psm1)CI annotations, outputs, env flags, and step summaries
Configuration FilesTool-specific settings (e.g., PSScriptAnalyzer.psd1, markdown-link-check.config.json)

Scripts

PowerShell Linting

Invoke-PSScriptAnalyzer.ps1

Static analysis for PowerShell scripts using PSScriptAnalyzer.

Purpose: Enforce PowerShell best practices and detect common issues.

Features
  • Detects changed PowerShell files via Git
  • Supports analyzing all files or changed files only
  • Creates CI annotations for violations
  • Exports JSON results and markdown summary
  • Configurable via PSScriptAnalyzer.psd1
Parameters
  • -ChangedFilesOnly (switch) - Analyze only files changed in current branch
Usage
# Analyze all PowerShell files
./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -Verbose

# Analyze only changed files
./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -ChangedFilesOnly

# View detailed output
./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -Verbose -Debug
GitHub Actions Integration
  • Workflow: .github/workflows/ps-script-analyzer.yml
  • Artifacts: psscriptanalyzer-results (JSON + markdown)
  • Exit Code: Non-zero if violations found

PSScriptAnalyzer.psd1

Configuration file for PSScriptAnalyzer rules.

Enforced Rules
Rule CategoryDescription
SeverityError and Warning levels
Best PracticesAvoid aliases, use approved verbs, singular nouns
HelpRequire comment-based help
SecurityCheck for credentials in code
PerformanceIdentify inefficient patterns
Excluded Rules
  • PSAvoidUsingWriteHost - Allowed for script output

YAML Linting

Invoke-YamlLint.ps1

Static analysis for GitHub Actions workflow files using actionlint.

Purpose: Validate GitHub Actions workflow YAML syntax and best practices.

Features
  • Validates .github/workflows/*.yml and .yaml files
  • Detects changed workflow files via Git
  • Supports analyzing all files or changed files only
  • Creates CI annotations for violations
  • Exports JSON results and markdown summary
  • Configurable via .github/actionlint.yaml
Parameters
  • -ChangedFilesOnly (switch) - Analyze only files changed in current branch
  • -BaseBranch (string) - Base branch for comparison (default: origin/main)
  • -OutputPath (string) - Output path for JSON results (default: logs/yaml-lint-results.json)
Usage
# Analyze all workflow files
./scripts/linting/Invoke-YamlLint.ps1 -Verbose

# Analyze only changed files
./scripts/linting/Invoke-YamlLint.ps1 -ChangedFilesOnly

# View detailed output
./scripts/linting/Invoke-YamlLint.ps1 -Verbose -Debug
GitHub Actions Integration
  • Workflow: .github/workflows/yaml-lint.yml
  • Configuration: .github/actionlint.yaml
  • Artifacts: yaml-lint-results (JSON)
  • Exit Code: Non-zero if violations found

Markdown Validation

Validate-MarkdownFrontmatter.ps1

Validates YAML frontmatter and footer format in markdown files.

Purpose: Ensure consistent metadata across documentation.

Features
  • Validates required frontmatter fields
  • Checks footer format and copyright notice
  • Supports changed files only mode
  • Configurable warnings-as-errors
  • Creates CI annotations for all issues
  • Exports JSON results with detailed statistics
  • Generates comprehensive step summary
Parameters
  • -ChangedFilesOnly (switch) - Validate only changed markdown files
  • -SkipFooterValidation (switch) - Skip footer checks
  • -WarningsAsErrors (switch) - Treat warnings as errors
  • -EnableSchemaValidation (switch) - Enable JSON Schema validation (advisory only)
Artifacts Generated
  • logs/frontmatter-validation-results.json - Complete validation results including:
    • Timestamp and script name
    • Summary statistics (total files, error/warning counts)
    • Lists of all errors and warnings
Usage
# Validate all markdown files
./scripts/linting/Validate-MarkdownFrontmatter.ps1

# Validate only changed files
./scripts/linting/Validate-MarkdownFrontmatter.ps1 -ChangedFilesOnly

# Skip footer validation
./scripts/linting/Validate-MarkdownFrontmatter.ps1 -SkipFooterValidation
GitHub Actions Integration
  • Workflow: .github/workflows/frontmatter-validation.yml
  • Artifacts: frontmatter-validation-results (JSON)
  • Annotations: Errors and warnings with file paths
  • Exit Code: Non-zero if validation fails

Invoke-LinkLanguageCheck.ps1

Detects URLs with language paths (e.g., /en-us/) that should be removed.

Purpose: Ensure language-agnostic URLs for better internationalization.

Features
  • Scans all markdown files recursively
  • Calls Link-Lang-Check.ps1 for detection logic
  • Creates CI warning annotations
  • Provides fix instructions in summary
Parameters
  • -ExcludePaths (string array) - Paths to exclude from the check (default: @())
  • -OutputPath (string) - Path where the JSON result file is written; the parent directory is created automatically if it does not exist (default: logs/link-lang-check-results.json)
Usage
# Check all markdown files
./scripts/linting/Invoke-LinkLanguageCheck.ps1 -Verbose

# View detection details
./scripts/linting/Invoke-LinkLanguageCheck.ps1 -Debug

# Write results to a custom location
./scripts/linting/Invoke-LinkLanguageCheck.ps1 -OutputPath "custom/results.json"
GitHub Actions Integration
  • Workflow: .github/workflows/link-lang-check.yml
  • Annotations: Warnings on files with language paths
  • Artifacts: link-lang-check-results (JSON + markdown)

Core logic for detecting language paths in URLs.

Detection Pattern: Matches /[a-z]{2}-[a-z]{2}/ patterns in Microsoft domain URLs.

Validates all links in markdown files using markdown-link-check npm package.

Purpose: Detect broken links before deployment.

Features
  • Checks internal and external links
  • Configurable via markdown-link-check.config.json
  • Retries failed links
  • Respects robots.txt
  • Creates CI annotations for broken links
  • Exports JSON results with link statistics
  • Generates detailed step summary
Artifacts Generated
  • logs/markdown-link-check-results.json - Complete validation results including:
    • Timestamp and script name
    • Summary statistics (total files, broken links count)
    • List of all broken links with file paths
GitHub Actions Integration
  • Workflow: .github/workflows/markdown-link-check.yml
  • Configuration: markdown-link-check.config.json
  • Artifacts: markdown-link-check-results (JSON)
  • Annotations: Error for each broken link
  • Exit Code: Non-zero if broken links found

ADR Consistency Validation

Validate-AdrConsistency.ps1

Validates ADR markdown files for Govern-phase consistency rules.

Purpose: Enforce ADR structure and content rules for architecture decision records under the ADR planning tree.

Features
  • Discovers ADR markdown files under the supplied paths
  • Applies the ADR consistency rule registry from scripts/linting/rules/adr-consistency-rules.json
  • Emits JSON results, optional SARIF output, and CI annotations
  • Supports changed-files-only mode and warning-as-error behavior
Parameters
  • -Paths (string[]) - Repository-relative or absolute directories to scan recursively for ADR markdown files
  • -Files (string[]) - Explicit markdown files to validate
  • -ExcludePaths (string[]) - Wildcard patterns to exclude from the scan
  • -WarningsAsErrors (switch) - Treat warn-severity violations as failures
  • -ChangedFilesOnly (switch) - Validate only ADR files changed relative to -BaseBranch
  • -BaseBranch (string) - Git reference used by changed-files detection (default: origin/main)
  • -OutputPath (string) - Path for the JSON report (default: logs/adr-consistency-results.json)
  • -SarifOutputPath (string) - Optional path for SARIF 2.1.0 output
Usage
# Validate the default ADR tree
./scripts/linting/Validate-AdrConsistency.ps1

# Validate only changed ADR files
./scripts/linting/Validate-AdrConsistency.ps1 -ChangedFilesOnly -BaseBranch origin/main
GitHub Actions Integration
  • npm script: npm run lint:adr-consistency
  • Default scan path: docs/planning/adrs

Skill Structure Validation

Validate-SkillStructure.ps1

Validates the structural integrity of skill directories under .github/skills/.

Purpose: Ensure all skill packages comply with the agentskills.io specification and hve-core conventions.

Features
  • Validates SKILL.md presence in each skill directory
  • Checks frontmatter for required name and description fields
  • Verifies name matches directory name
  • When scripts/ subdirectory exists, requires both .ps1 and .sh files for cross-platform support
  • Validates Python skills with tests/ include tests/fuzz_harness.py for Scorecard compliance
  • Warns when a Python skill has pyproject.toml without a committed uv.lock (required for Dependabot uv ecosystem coverage)
  • Warns on unrecognized directories
  • Supports changed-files-only mode via Git
  • Creates CI annotations for violations
  • Exports JSON results to logs/skill-validation-results.json
Parameters
  • -SkillsPath (string) - Root path containing skill directories (default: .github/skills)
  • -WarningsAsErrors (switch) - Treat warnings as errors
  • -ChangedFilesOnly (switch) - Validate only skills with changed files
  • -BaseBranch (string) - Git reference for changed file detection (default: origin/main)
Usage
# Validate all skills
./scripts/linting/Validate-SkillStructure.ps1

# Validate with warnings as errors
./scripts/linting/Validate-SkillStructure.ps1 -WarningsAsErrors

# Validate only changed skills
./scripts/linting/Validate-SkillStructure.ps1 -ChangedFilesOnly
GitHub Actions Integration
  • Workflow: .github/workflows/skill-validation.yml
  • Artifacts: skill-validation-results (JSON)
  • Exit Code: Non-zero if validation fails

Test-CopyrightHeaders.ps1

Validates copyright and SPDX license headers in source files.

Purpose: Ensure all PowerShell, shell, and Python scripts include the required Microsoft copyright notice and MIT SPDX license identifier in their first 15 lines.

Features
  • Scans .ps1, .psm1, .psd1, .sh, and .py files recursively
  • Checks for Copyright (c) 2026 Microsoft Corporation. All rights reserved. header
  • Checks for SPDX-License-Identifier: MIT identifier
  • Configurable file extensions and exclude paths
  • Exports JSON results with per-file compliance details
  • Calculates compliance percentage across all scanned files
Parameters
  • -Path (string) - Root path to scan (default: repository root via git rev-parse --show-toplevel)
  • -FileExtensions (string[]) - File extensions to check (default: @('*.ps1', '*.psm1', '*.psd1', '*.sh', '*.py'))
  • -OutputPath (string) - Path for JSON results (default: logs/copyright-header-results.json)
  • -FailOnMissing (switch) - Exit with code 1 if any files lack required headers
  • -ExcludePaths (string[]) - Directories to exclude (default: @('node_modules', '.git', 'vendor', 'logs'))
  • -Fix (switch) - Rewrite non-canonical headers and insert missing ones in place using the comment prefix appropriate to each file. Idempotent. Default is validation-only.
Usage
# Check all source files (report only)
./scripts/linting/Test-CopyrightHeaders.ps1

# Check and fail on missing headers
./scripts/linting/Test-CopyrightHeaders.ps1 -FailOnMissing

# Check specific path with verbose output
./scripts/linting/Test-CopyrightHeaders.ps1 -Path ./scripts -FailOnMissing -Verbose

# Normalize headers in place (rewrite non-canonical, insert missing)
./scripts/linting/Test-CopyrightHeaders.ps1 -Fix
GitHub Actions Integration
  • Workflow: .github/workflows/copyright-headers.yml
  • Artifacts: copyright-header-results (JSON)
  • Exit Code: Non-zero if validation fails (with -FailOnMissing)

ms.date Freshness Check

Invoke-MsDateFreshnessCheck.ps1

Checks ms.date frontmatter freshness across markdown files.

Purpose: Flag documentation files whose ms.date exceeds a configurable staleness threshold, helping teams identify content that may need review or updates.

Features
  • Scans all markdown files or only changed files via Git
  • Configurable staleness threshold in days
  • Generates JSON report and markdown step summary
  • Creates CI annotations for each stale file
  • Excludes CHANGELOG.md and .copilot-tracking/ by default
Parameters
  • -ThresholdDays (int) - Days before ms.date is considered stale (default: 90)
  • -Paths (string[]) - Directories to scan (default: repository root)
  • -ChangedFilesOnly (switch) - Only check files changed relative to BaseBranch
  • -BaseBranch (string) - Base branch for changed-file detection (default: origin/main)
Artifacts Generated
  • logs/msdate-freshness-results.json - Structured results with stale file details
  • logs/msdate-summary.md - Markdown step summary with stale files table
Usage
# Check all markdown files with default 90-day threshold
./scripts/linting/Invoke-MsDateFreshnessCheck.ps1

# Use a stricter 60-day threshold
./scripts/linting/Invoke-MsDateFreshnessCheck.ps1 -ThresholdDays 60

# Check only changed files
./scripts/linting/Invoke-MsDateFreshnessCheck.ps1 -ChangedFilesOnly
GitHub Actions Integration
  • Workflow: .github/workflows/msdate-freshness-check.yml
  • Artifacts: msdate-freshness-results (JSON + markdown)
  • npm script: npm run lint:frontmatter (frontmatter check also includes freshness)

Python Tooling

Invoke-PythonLint.ps1

Lints Python skills using ruff.

Purpose: Enforce Python code quality standards across all Python skills in the repository by dynamically discovering and linting each skill.

Features
  • Discovers Python skills via pyproject.toml file search
  • Verifies ruff availability before running
  • Lints each skill directory independently
  • Reports per-skill pass/fail results
  • Supports optional JSON output
  • -Fix mode applies ruff check --fix followed by ruff format; writes results to python-lint-fix-results.json instead of python-lint-results.json
Parameters
  • -RepoRoot (string) - Repository root path (default: current directory)
  • -OutputPath (string) - Optional path for JSON results
  • -Fix (switch) - Applies ruff check --fix + ruff format to each skill directory; intended for local developer use, not CI gating
Usage
# Lint all Python skills
./scripts/linting/Invoke-PythonLint.ps1

# Lint from a specific repository root
./scripts/linting/Invoke-PythonLint.ps1 -RepoRoot /path/to/repo

# Apply ruff autofixes and format (local use only)
./scripts/linting/Invoke-PythonLint.ps1 -Fix
GitHub Actions Integration
  • Workflow: .github/workflows/python-lint.yml
  • npm script: npm run lint:py

Invoke-PythonTests.ps1

Runs tests across Python skills using uv run pytest when uv is available, with a fallback to venv or global pytest.

Purpose: Execute Python test suites for all Python skills that include a tests/ directory, reporting aggregate pass/fail results.

Features
  • Discovers Python skills via pyproject.toml file search
  • Skips skills without a tests/ directory
  • Prefers uv run pytest when uv is available; syncs dev dependencies with uv sync --dev (or --locked when uv.lock exists) before running
  • Falls back to venv or global pytest when uv is not found
  • Reports per-skill test results with pass/fail counts
  • Configurable verbosity level
Parameters
  • -RepoRoot (string) - Repository root path (default: current directory)
  • -OutputPath (string) - Optional path for JSON results
  • -Verbosity (string) - pytest verbosity flag (default: -v)
Usage
# Run all Python tests
./scripts/linting/Invoke-PythonTests.ps1

# Run with quiet output
./scripts/linting/Invoke-PythonTests.ps1 -Verbosity '-q'
GitHub Actions Integration
  • Workflow: .github/workflows/pytest-tests.yml
  • npm script: npm run test:py

Additional Validation Scripts

The linting directory also contains these scripts that are not yet covered in the earlier sections:

ScriptPurpose
Invoke-JsonLint.ps1Validate strict JSON syntax using System.Text.Json
Validate-HookManifests.ps1Validate collection-scoped hook manifests under .github/hooks/
Validate-PlannerArtifacts.ps1Validate AI artifact footer and disclaimer presence in instruction templates
Test-ModelReferences.ps1Validate model references in agent and prompt files against the model catalog
Test-ExtensionArtifactNaming.ps1Validate extension-vsix artifact producer and consumer naming across the extension release workflows
Update-ModelCatalog.ps1Refresh the model catalog from GitHub docs data
Format-MarkdownTables.ps1Normalize markdown tables to the repository formatting convention

npm Scripts

npm ScriptDescription
lint:extension-artifact-namingRun pwsh -NoProfile -File scripts/linting/Test-ExtensionArtifactNaming.ps1 to validate extension VSIX artifact names

Shared Module

Modules/FrontmatterValidation.psm1

Frontmatter validation functions and types used by Validate-MarkdownFrontmatter.ps1 and its test suite.

Imported via using module syntax in test files.

Exported Classes

ClassPurpose
ValidationIssueRepresents a single validation finding with type, field, message, and file
FileTypeInfoClassifies a markdown file by type (docs, prompt, instruction, agent, etc.)
FileValidationResultAggregates all validation issues and frontmatter for a single file

Usage

using module ./scripts/linting/Modules/FrontmatterValidation.psm1

$issue = [ValidationIssue]::new('Error', 'ms.date', 'Missing required field', 'README.md')

Modules/LintingHelpers.psm1

Common helper functions for file discovery and git operations.

Exported Functions

Get-ChangedFilesFromGit

Detects files changed in current branch compared to main.

Parameters
  • -BaseBranch (string) - Base branch to compare against (default: origin/main)
  • -FileExtensions (string[]) - Array of file patterns to filter (e.g., @('*.ps1', '*.md'))

Returns: Array of changed file paths

Fallbacks
  1. git merge-base with specified base branch
  2. git diff HEAD~1 when merge-base fails
  3. git diff HEAD for staged/unstaged files

Get-FilesRecursive

Finds files matching patterns using git ls-files with a Get-ChildItem fallback.

Parameters
  • -Path (string, required) - Root directory to search from
  • -Include (string[], required) - File patterns to include (e.g., @('*.ps1', '*.psm1'))
  • -GitIgnorePath (string) - Path to .gitignore file for exclusion patterns (fallback path only)

Returns: Array of FileInfo objects

Behavior
  • Inside a git repository, uses git ls-files --cached --others --exclude-standard scoped to the given path. Git natively handles .gitignore exclusions.
  • Outside a git repository (or when git is unavailable), falls back to Get-ChildItem -Recurse with optional -GitIgnorePath filtering.

Get-GitIgnorePatterns

Parses .gitignore into PowerShell wildcard patterns.

Parameters
  • -GitIgnorePath (string, required) - Path to .gitignore file

Returns: Array of wildcard patterns using platform-appropriate separators

scripts/lib/Modules/CIHelpers.psm1

CI helper functions for annotations, outputs, environment flags, and summaries.

Exported Functions

Write-CIAnnotation

Creates a CI annotation.

Parameters
  • -Level ('Error'|'Warning'|'Notice') - Annotation severity
  • -Message (string) - Annotation text
  • -File (string, optional) - File path
  • -Line (int, optional) - Line number
  • -Column (int, optional) - Column number

Output: CI annotation command

Write-CIAnnotations

Writes CI annotations from a validation summary.

Parameters
  • -Summary (ValidationSummary) - Validation results to annotate

Set-CIOutput

Sets a CI output variable.

Parameters
  • -Name (string) - Variable name
  • -Value (string) - Variable value

Set-CIEnv

Sets a CI environment variable.

Parameters
  • -Name (string) - Variable name
  • -Value (string) - Variable value

Write-CIStepSummary

Appends content to the CI step summary.

Parameters
  • -Content (string) - Markdown content

Usage Example

Import-Module ./Modules/LintingHelpers.psm1

# Get changed PowerShell files
$files = Get-ChangedFilesFromGit -FileExtension '.ps1'

# Create error annotation
Write-CIAnnotation -Level 'Error' -Message 'Syntax error' -File 'script.ps1' -Line 42

# Set output variable
Set-CIOutput -Name 'files-analyzed' -Value $files.Count

# Add to step summary
Write-CIStepSummary -Content "## Results`n`nAnalyzed $($files.Count) files"

Configuration Files

Configuration: PSScriptAnalyzer.psd1

PSScriptAnalyzer rule configuration.

Key Settings

  • Severity: Error, Warning
  • IncludeRules: Best practices, security, performance
  • ExcludeRules: PSAvoidUsingWriteHost

Markdown link checker configuration.

Key Settings

  • Retry attempts: 3
  • Timeout: 10 seconds
  • Ignore patterns: Localhost, example.com

Schemas Directory

The schemas/ directory contains JSON schema files used for frontmatter validation. These schemas ensure that the metadata in various markdown and configuration files adheres to the expected structure.

Schema Files

The directory includes the following 20 JSON schema files:

  • accessibility-state.schema.json
  • adr-config.schema.json
  • adr-consistency-rules.schema.json
  • adr-frontmatter.schema.json
  • agent-frontmatter.schema.json
  • ai-artifact-config.schema.json
  • base-frontmatter.schema.json
  • chatmode-frontmatter.schema.json
  • collection-manifest.schema.json
  • docs-frontmatter.schema.json
  • hook-manifest.schema.json
  • instruction-frontmatter.schema.json
  • marketplace-manifest.schema.json
  • model-catalog.schema.json
  • prompt-frontmatter.schema.json
  • rai-state.schema.json
  • root-community-frontmatter.schema.json
  • security-state.schema.json
  • skill-frontmatter.schema.json
  • sssc-state.schema.json

Schema Mapping

  • schema-mapping.json: Maps glob patterns to their corresponding JSON schemas for targeted validation.

Testing

All scripts support local testing before running in GitHub Actions:

# Test PSScriptAnalyzer
./scripts/linting/Invoke-PSScriptAnalyzer.ps1 -Verbose

# Test frontmatter validation
./scripts/linting/Validate-MarkdownFrontmatter.ps1 -ChangedFilesOnly

# Test link language check
./scripts/linting/Invoke-LinkLanguageCheck.ps1

# Test markdown links
./scripts/linting/Markdown-Link-Check.ps1

# Test shared module
Import-Module ./scripts/linting/Modules/LintingHelpers.psm1
Get-Command -Module LintingHelpers

GitHub Actions Workflows

All linting scripts are integrated into GitHub Actions workflows:

ScriptWorkflow
PSScriptAnalyzer.github/workflows/ps-script-analyzer.yml
YAML Lint.github/workflows/yaml-lint.yml
Frontmatter Validation.github/workflows/frontmatter-validation.yml
Link Language Check.github/workflows/link-lang-check.yml
Markdown Link Check.github/workflows/markdown-link-check.yml
ms.date Freshness.github/workflows/msdate-freshness-check.yml
Python Lint.github/workflows/python-lint.yml
Python Tests.github/workflows/pytest-tests.yml
Copyright Headers.github/workflows/copyright-headers.yml
Skill Validation.github/workflows/skill-validation.yml
ADR Consistency.github/workflows/adr-consistency-validation.yml

See GitHub Workflows Documentation for details.

Adding New Linting Scripts

To add a new linting script:

  1. Create wrapper script following Invoke-*.ps1 naming convention
  2. Import LintingHelpers and CIHelpers modules for file discovery and CI integration
  3. Implement core validation logic with clear error reporting
  4. Support common parameters: -Verbose, -Debug, -ChangedFilesOnly (if applicable)
  5. Create GitHub Actions workflow in .github/workflows/
  6. Add to PR validation in .github/workflows/pr-validation.yml
  7. Document in this README and workflows README
  8. Test locally before creating PR

Template

#!/usr/bin/env pwsh
<#
.SYNOPSIS
    Brief description of validation.

.DESCRIPTION
    Detailed description.

.PARAMETER ChangedFilesOnly
    Validate only changed files.

.EXAMPLE
    ./scripts/linting/Invoke-MyValidator.ps1 -Verbose
#>

[CmdletBinding()]
param(
    [switch]$ChangedFilesOnly
)

$ErrorActionPreference = 'Stop'
Import-Module (Join-Path $PSScriptRoot 'Modules/LintingHelpers.psm1') -Force
Import-Module (Join-Path $PSScriptRoot '../lib/Modules/CIHelpers.psm1') -Force

#region Functions

function Invoke-MyValidatorCore {
    [CmdletBinding()]
    [OutputType([void])]
    param(
        [switch]$ChangedFilesOnly
    )

    Write-Host "🔍 Running MyValidator..."

    if ($ChangedFilesOnly) {
        $files = Get-ChangedFilesFromGit -FileExtension '.ext'
    }
    else {
        $files = Get-FilesRecursive -Path (Get-Location) -Pattern '*.ext'
    }

    if ($files.Count -eq 0) {
        Write-Host "✅ No files to validate"
        return
    }

    # Perform validation
    $issues = @()
    foreach ($file in $files) {
        # Validation logic here
        if ($issue) {
            $issues += $issue
            Write-CIAnnotation -Level 'Error' -Message 'Issue found' -File $file
        }
    }

    Write-CIStepSummary -Content "## Validation Results`n`nFound $($issues.Count) issues"

    if ($issues.Count -gt 0) {
        throw "Found $($issues.Count) issues"
    }

    Write-Host "✅ All files validated successfully"
}

#endregion Functions

#region Main Execution
if ($MyInvocation.InvocationName -ne '.') {
    try {
        Invoke-MyValidatorCore @PSBoundParameters
        exit 0
    }
    catch {
        Write-Error -ErrorAction Continue "Invoke-MyValidator failed: $($_.Exception.Message)"
        Write-CIAnnotation -Message $_.Exception.Message -Level Error
        exit 1
    }
}
#endregion Main Execution

Contributing

When modifying linting scripts:

  1. Follow PowerShell best practices (PSScriptAnalyzer compliant)
  2. Maintain CI integration patterns
  3. Keep scripts testable locally without GitHub Actions
  4. Update documentation in README files
  5. Test thoroughly before creating PR
  6. Get CODEOWNERS approval

🤖 Crafted with precision by ✨Copilot following brilliant human instruction, then carefully refined by our team of discerning human reviewers.