From 000f2ca759180a335cc8ce05601aa452859fb4e5 Mon Sep 17 00:00:00 2001 From: Gilbert Sanchez Date: Fri, 3 Apr 2026 11:08:53 -0700 Subject: [PATCH 1/3] Potential fix for code scanning alert no. 3: Workflow does not contain permissions (#118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Potential fix for [https://github.com/psake/PowerShellBuild/security/code-scanning/3](https://github.com/psake/PowerShellBuild/security/code-scanning/3) In general, this should be fixed by explicitly defining GITHUB_TOKEN permissions in the workflow, either at the root level (applying to all jobs) or per job, and restricting them to the least privilege required (for a simple test workflow usually `contents: read` is enough). This documents the workflow’s needs and prevents it from gaining broader access if repository or organization defaults change. For this specific workflow in `.github/workflows/test.yml`, the safest, least intrusive fix that preserves existing behavior is to add a root-level `permissions:` block granting only `contents: read`. The existing steps perform a checkout and run a PowerShell script; there is no explicit indication they need to write to the repo, issues, or pull requests. Adding the block directly under the workflow `name:` (before `on:`) is conventional and applies to all jobs unless overridden. No imports or additional methods are required; this is purely a YAML configuration change within the workflow file. _Suggested fixes powered by Copilot Autofix. Review carefully before merging._ Signed-off-by: Gilbert Sanchez Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4dd83b..8b30baf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,6 @@ name: Test +permissions: + contents: read on: push: branches: [ $default-branch ] From 1b1680597429441591a313ade09b80f4f197d5a0 Mon Sep 17 00:00:00 2001 From: Gilbert Sanchez Date: Fri, 3 Apr 2026 11:14:11 -0700 Subject: [PATCH 2/3] Potential fix for code scanning alert no. 1: Workflow does not contain permissions (#119) Potential fix for [https://github.com/psake/PowerShellBuild/security/code-scanning/1](https://github.com/psake/PowerShellBuild/security/code-scanning/1) In general, the fix is to explicitly define a `permissions:` block for the workflow or individual jobs, granting only the scopes actually needed. For most build/publish workflows that only need to read the repository contents, `contents: read` is an appropriate minimal default. If later steps need more permissions (e.g., to create releases or write issues), those can be added explicitly. For this specific file, the simplest and safest fix without altering functionality is to add a workflow-level `permissions:` block with `contents: read`. This will apply to the `publish` job because it currently has no `permissions` of its own. Concretely, in `.github/workflows/publish.yaml`, insert: ```yaml permissions: contents: read ``` between the `on:` block and the `jobs:` block. No additional imports or dependencies are needed, and no other lines in the workflow need to change. _Suggested fixes powered by Copilot Autofix. Review carefully before merging._ Signed-off-by: Gilbert Sanchez Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/publish.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 904dd4a..10c7f7a 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -4,6 +4,9 @@ on: release: types: [published] +permissions: + contents: read + jobs: publish: name: Publish From 08b191acd41edb1db296f865f67b463ebbffbc27 Mon Sep 17 00:00:00 2001 From: Trent Blackburn <45049539+tablackburn@users.noreply.github.com> Date: Sun, 17 May 2026 20:10:04 -0400 Subject: [PATCH 3/3] feat: deploy AIM (AI Agent Instruction Modules) (#122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 0 of #120 — deploy [AIM (AI Agent Instruction Modules)](https://github.com/tablackburn/ai-agent-instruction-modules) as the first PR of the v1.0.0 cycle. ## What's included - `AGENTS.md` (root) — agent-facing entry point with instruction matrix; Last sync: 2026-05-17 (AIM 0.8.14) - `aim.config.json` — module configuration; external sources enabled (awesome-copilot fallback) - `instructions/` — 12 instruction modules: - Core: `agent-workflow`, `shorthand`, `git-workflow`, `testing`, `update` - Language/tools: `powershell`, `markdown`, `readme`, `github-cli` - Repository management: `releases`, `contributing` - Repo-specific: `repository-specific.instructions.md` (migrated from CLAUDE.md) - `CLAUDE.md` — one-line `@AGENTS.md` import so Claude Code auto-loads AIM context (see "CLAUDE.md handling" below) ## CLAUDE.md migration CLAUDE.md content was migrated to `instructions/repository-specific.instructions.md`, keeping only repo-specific content (project layout, `$PSBPreference` internals, task dependency variables, naming conventions, build workflows, BuildHelpers env vars). Generic content covered by standard AIM modules (PowerShell style, git workflow, generic testing patterns) was dropped to avoid duplication. Stale references corrected during migration: - Version: 0.7.3 → 0.8.0 - Public function count: 9 → 12 (signing functions added in 0.8.0) ## CLAUDE.md handling The original CLAUDE.md was deleted, then re-added as a one-line file containing only `@AGENTS.md`. Reason: Claude Code auto-loads `CLAUDE.md` from the project root but does not auto-load `AGENTS.md` ([memory docs](https://code.claude.com/docs/en/memory.md)). Using the official `@`-import syntax means fresh Claude Code sessions in this repo automatically pick up AIM context (AGENTS.md → instruction matrix → applicable modules) without needing a manual pointer in every prompt. This matches the AIM source repo, which ships both `AGENTS.md` and `CLAUDE.md`. ## AIM 0.8.14 sync Bumped from 0.8.13 → 0.8.14 (released 2026-05-16). Pulls three instruction-file fixes from [tablackburn/ai-agent-instruction-modules#24](https://github.com/tablackburn/ai-agent-instruction-modules/pull/24): - **`contributing.instructions.md`** — "Make Changes" pointed contributors at `instructions/` instead of `instruction-templates/`. Surfaced during Copilot review of this PR and filed upstream as [tablackburn/ai-agent-instruction-modules#23](https://github.com/tablackburn/ai-agent-instruction-modules/issues/23). - **`github-cli.instructions.md`** — "Creating Releases" example used `gh release create --notes`, contradicting `releases.instructions.md` which mandates `--notes-file` to avoid escaping issues. Replaced with a temp-file pattern and added a precedence note. Also surfaced during this PR's review; same upstream issue. - **`shorthand.instructions.md`** — backfilled the missing `Dir → Directory` row (pre-existing sync drift in the upstream template; fixed in the same upstream PR). `AGENTS.md` Template Version 0.8.13 → 0.8.14 and Last sync 2026-05-15 → 2026-05-17. ## Scope Docs/config-only — no module code changes. Verified locally: - `git diff --stat origin/main`: 16 files changed, 0 under `PowerShellBuild/`, `requirements.psd1`, `CHANGELOG.md`, or `.github/` - `./build.ps1 -Task Test -Bootstrap` passes (314 passed, 0 failed, 2 skipped — the skips are git-tagging tests that expectedly skip on feature branches) - Module version, dependencies, and CI workflows untouched ## Note on module count vs #120 checklist #120's Phase 0 checklist lists 8 modules. This PR deploys 12 — the additional `readme`, `contributing`, `update`, and `repository-specific` modules were included per the Phase 0 deployment scope I worked from. Happy to drop any of them if the tracking issue's narrower list was intentional. ## Phase 0 checklist (#120) - [x] Add `AGENTS.md`, `aim.config.json`, `instructions/` - [x] Migrate `CLAUDE.md` content → `instructions/repository-specific.instructions.md` - [x] Modules included: `agent-workflow`, `shorthand`, `git-workflow`, `testing`, `powershell`, `markdown`, `releases`, `github-cli` (plus `readme`, `contributing`, `update`, `repository-specific` — see note above) - [x] Fix stale version reference (CLAUDE.md said 0.7.3; actual is 0.8.0) ## Commits 1. `feat: deploy AIM (AI Agent Instruction Modules)` — main deployment + CLAUDE.md content migration + CLAUDE.md deletion 2. `docs: add CLAUDE.md as @AGENTS.md import for Claude Code auto-loading` — restore CLAUDE.md as a 1-line pointer 3. `docs: address Copilot review feedback on repository-specific instructions` — Sign/Catalog rows, IB alias examples, `-FromModule` psake pattern, signing task dependency + task rows 4. `docs: sync AIM 0.8.14 fixes (contributing folder, gh release notes, Dir row)` — pull the three instruction-file fixes from AIM 0.8.14 and bump template version + sync date 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- AGENTS.md | 72 +++ CLAUDE.md | 411 +------------- aim.config.json | 31 ++ instructions/agent-workflow.instructions.md | 96 ++++ instructions/contributing.instructions.md | 157 ++++++ instructions/git-workflow.instructions.md | 280 ++++++++++ instructions/github-cli.instructions.md | 252 +++++++++ instructions/markdown.instructions.md | 123 +++++ instructions/powershell.instructions.md | 515 ++++++++++++++++++ instructions/readme.instructions.md | 31 ++ instructions/releases.instructions.md | 85 +++ .../repository-specific.instructions.md | 388 +++++++++++++ instructions/shorthand.instructions.md | 66 +++ instructions/testing.instructions.md | 339 ++++++++++++ instructions/update.instructions.md | 193 +++++++ 15 files changed, 2629 insertions(+), 410 deletions(-) create mode 100644 AGENTS.md create mode 100644 aim.config.json create mode 100644 instructions/agent-workflow.instructions.md create mode 100644 instructions/contributing.instructions.md create mode 100644 instructions/git-workflow.instructions.md create mode 100644 instructions/github-cli.instructions.md create mode 100644 instructions/markdown.instructions.md create mode 100644 instructions/powershell.instructions.md create mode 100644 instructions/readme.instructions.md create mode 100644 instructions/releases.instructions.md create mode 100644 instructions/repository-specific.instructions.md create mode 100644 instructions/shorthand.instructions.md create mode 100644 instructions/testing.instructions.md create mode 100644 instructions/update.instructions.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..177aaf5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,72 @@ +# AI Agent Instructions + +AI agents working in this repository must follow these instructions. + +Template Version: 0.8.14 + +Last sync: 2026-05-17 (Update this date when syncing from the centralized repository) + +## Instructions for AI Agents + +AI agents **must**: + +1. **When deploying or updating this template, follow `instructions/update.instructions.md` and + update the Last sync date above.** + +2. **Read `instructions/agent-workflow.instructions.md` FIRST to determine which other instruction + files apply to your task.** Follow all applicable instructions before proceeding with work. + +3. **Check `aim.config.json`** for module configuration and external source settings. + +## Instruction Applicability Matrix + +Use this matrix to determine which instruction files to read based on your task: + +| Task Type | Required Instructions | +| ---------------------------- | -------------------------------------- | +| Any task | `agent-workflow.instructions.md` | +| Any code or documentation | `shorthand.instructions.md` | +| Git operations | `git-workflow.instructions.md` | +| Writing tests | `testing.instructions.md` | +| PowerShell code | `powershell.instructions.md` | +| Documentation | `markdown.instructions.md` | +| README files | `readme.instructions.md` | +| GitHub CLI usage | `github-cli.instructions.md` | +| Creating releases | `releases.instructions.md` | +| Repository-specific work | `repository-specific.instructions.md` | +| Updating instructions | `update.instructions.md` | +| Contributing to upstream | `contributing.instructions.md` | + +## Available Instruction Files + +- `agent-workflow.instructions.md` - Pre-flight protocol and task workflow +- `shorthand.instructions.md` - Avoid shorthand and abbreviations +- `git-workflow.instructions.md` - Git branching, commits, and PR conventions +- `testing.instructions.md` - Test writing best practices +- `powershell.instructions.md` - PowerShell coding standards +- `markdown.instructions.md` - Markdown formatting standards +- `readme.instructions.md` - README maintenance guidelines +- `github-cli.instructions.md` - GitHub CLI usage guidelines +- `releases.instructions.md` - Release management guidelines +- `repository-specific.instructions.md` - Repository-specific customizations +- `update.instructions.md` - Procedures for updating instructions +- `contributing.instructions.md` - Contributing improvements to upstream + +## Quick Reference + +### Before Starting Any Task + +1. Identify the task type from the matrix above +2. Read all applicable instruction files +3. Follow the guidelines when implementing + +### Best Practices + +- Follow existing patterns in the codebase +- Keep solutions simple and focused +- Only make changes that are directly requested +- Follow language-specific guidelines + +## Repository-Specific Instructions + +See `instructions/repository-specific.instructions.md` for customizations specific to this repository. diff --git a/CLAUDE.md b/CLAUDE.md index a11fa07..43c994c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,410 +1 @@ -# CLAUDE.md — AI Assistant Guide for PowerShellBuild - -## Project Overview - -**PowerShellBuild** is a PowerShell module that provides a standardized set of build, test, and publish tasks for PowerShell module projects. It supports two popular PowerShell task-runner frameworks: - -- **psake** (4.9.0+) — task-based build system -- **Invoke-Build** (5.8.1+) — alternative task runner - -The module version is **0.7.3** and targets PowerShell 3.0+. It is cross-platform and tested on Windows, Linux, and macOS. - ---- - -## Repository Layout - -``` -PowerShellBuild/ -├── .devcontainer/ # Dev container (Docker) configuration -│ ├── Dockerfile -│ └── devcontainer.json -├── .github/ -│ └── workflows/ -│ ├── test.yml # CI: runs tests on push/PR across 3 OSes -│ └── publish.yaml # CI: publishes to PSGallery on release -├── .vscode/ # VS Code editor settings and tasks -├── Build/ -│ └── Convert-PSAke.ps1 # Utility: converts psake tasks to Invoke-Build -├── PowerShellBuild/ # THE MODULE SOURCE (System Under Test) -│ ├── Public/ # Exported (public) functions — 9 functions -│ ├── Private/ # Internal functions — 1 function -│ ├── en-US/ -│ │ └── Messages.psd1 # Localized string resources -│ ├── PowerShellBuild.psd1 # Module manifest (version, deps, exports) -│ ├── PowerShellBuild.psm1 # Module entry point (dot-sources all functions) -│ ├── ScriptAnalyzerSettings.psd1 # PSScriptAnalyzer rule config -│ ├── build.properties.ps1 # $PSBPreference config hashtable (canonical config) -│ └── psakeFile.ps1 # psake/Invoke-Build task definitions for consumers -├── tests/ # Pester test suite -│ ├── build.tests.ps1 -│ ├── Help.tests.ps1 -│ ├── IBTasks.tests.ps1 -│ ├── Manifest.tests.ps1 -│ ├── Meta.tests.ps1 -│ ├── MetaFixers.psm1 -│ ├── ScriptAnalyzerSettings.psd1 -│ └── TestModule/ # A complete example module used in tests -├── build.ps1 # Main build entry point (run this to build/test) -├── build.settings.ps1 # Build settings for the repo's own psake build -├── psakeFile.ps1 # psake tasks for building THIS repo -├── requirements.psd1 # PSDepend dependencies manifest -├── cspell.json # Spell checker config -├── .markdownlint.json # Markdown lint config -├── README.md -└── CHANGELOG.md -``` - ---- - -## Key Concepts - -### $PSBPreference — The Central Configuration Object - -All build behavior is controlled through a single ordered hashtable `$PSBPreference`, defined in `PowerShellBuild/build.properties.ps1`. This is set as a **read-only script-scoped variable** when `psakeFile.ps1` is loaded. - -The hashtable is organized into sections: - -| Section | Purpose | -|---------|---------| -| `General` | ProjectRoot, SrcRootDir, ModuleName, ModuleVersion, ModuleManifestPath | -| `Build` | OutDir, ModuleOutDir, CompileModule, CompileDirectories, CopyDirectories, Exclude | -| `Test` | Enabled, RootDir, OutputFile, OutputFormat, ScriptAnalysis, CodeCoverage, ImportModule, SkipRemainingOnFailure, OutputVerbosity | -| `Help` | UpdatableHelpOutDir, DefaultLocale, ConvertReadMeToAboutHelp | -| `Docs` | RootDir, Overwrite, AlphabeticParamsOrder, ExcludeDontShow, UseFullTypeName | -| `Publish` | PSRepository, PSRepositoryApiKey, PSRepositoryCredential | - -Consumers override settings by modifying `$PSBPreference` in their own `build.ps1` **before** importing the tasks file. - -### Module Compilation Modes - -The `Build.CompileModule` setting controls how the module is staged to the output directory: - -- `$false` (default): Files are copied as-is, preserving the `Public/`/`Private/` directory structure. -- `$true`: All `.ps1` files from `CompileDirectories` (default: `Enum`, `Classes`, `Private`, `Public`) are concatenated into a single `.psm1` file. Optional `CompileHeader`, `CompileFooter`, `CompileScriptHeader`, and `CompileScriptFooter` strings can be injected. - -### Task Dependency Variables - -Task dependencies in `PowerShellBuild/psakeFile.ps1` are defined via variables checked with `if ($null -eq ...)`. This allows consumers to **override dependencies before importing the tasks file**: - -```powershell -# Example: add a custom task before Pester runs -$PSBPesterDependency = @('Build', 'MyCustomTask') -``` - -Available dependency variables: - -| Variable | Default | -|----------|---------| -| `$PSBCleanDependency` | `@('Init')` | -| `$PSBStageFilesDependency` | `@('Clean')` | -| `$PSBBuildDependency` | `@('StageFiles', 'BuildHelp')` | -| `$PSBAnalyzeDependency` | `@('Build')` | -| `$PSBPesterDependency` | `@('Build')` | -| `$PSBTestDependency` | `@('Pester', 'Analyze')` | -| `$PSBBuildHelpDependency` | `@('GenerateMarkdown', 'GenerateMAML')` | -| `$PSBGenerateMarkdownDependency` | `@('StageFiles')` | -| `$PSBGenerateMAMLDependency` | `@('GenerateMarkdown')` | -| `$PSBGenerateUpdatableHelpDependency` | `@('BuildHelp')` | -| `$PSBPublishDependency` | `@('Test')` | - ---- - -## Public API (Exported Functions) - -All functions reside in `PowerShellBuild/Public/`. - -| Function | Description | -|----------|-------------| -| `Initialize-PSBuild` | Sets up BuildHelpers environment variables, displays build info | -| `Build-PSBuildModule` | Copies/compiles module source to output directory | -| `Clear-PSBuildOutputFolder` | Safely removes the build output directory | -| `Build-PSBuildMarkdown` | Generates PlatyPS Markdown docs from module help | -| `Build-PSBuildMAMLHelp` | Converts PlatyPS Markdown to MAML XML help files | -| `Build-PSBuildUpdatableHelp` | Creates a `.cab` file for updatable help | -| `Test-PSBuildPester` | Runs Pester tests with configurable output and coverage | -| `Test-PSBuildScriptAnalysis` | Runs PSScriptAnalyzer with configurable severity threshold | -| `Publish-PSBuildModule` | Publishes the built module to a PowerShell repository | - -Private helper: `Remove-ExcludedItem` — filters file system items by regex patterns during builds. - -### Invoke-Build Alias - -The module exports an alias `PowerShellBuild.IB.Tasks` that points to `IB.tasks.ps1`, enabling the Invoke-Build dot-source pattern: - -```powershell -# In your .build.ps1 for Invoke-Build -. ([IO.Path]::Combine((Split-Path (Get-Module PowerShellBuild).Path), 'PowerShellBuild.IB.Tasks')) -``` - ---- - -## Build Workflows - -### Building This Repository (the module itself) - -The repo uses its own psake build system. The main entry point is `build.ps1`. - -**Run with PowerShell 7+** (`pwsh`). - -```powershell -# Install dependencies and run the default task (Test) -./build.ps1 -Bootstrap - -# Run a specific task -./build.ps1 -Task Build -./build.ps1 -Task Test -./build.ps1 -Task Analyze -./build.ps1 -Task Pester - -# List available tasks -./build.ps1 -Help - -# Publish to PSGallery (requires API key credential) -./build.ps1 -Task Publish -PSGalleryApiKey $cred -``` - -### Available psake Tasks (repo-level `psakeFile.ps1`) - -| Task | Depends On | Description | -|------|-----------|-------------| -| `default` | Test | Default task | -| `Init` | — | Initialize build environment (shows BH* env vars) | -| `Clean` | Init | Remove output directory | -| `Build` | Init, Clean | Copy module source to output directory | -| `Analyze` | Build | Run PSScriptAnalyzer | -| `Pester` | Build | Run Pester tests | -| `Test` | Init, Analyze, Pester | Run all tests | -| `Publish` | Test | Publish to PSGallery | - -### Module-Level Tasks (`PowerShellBuild/psakeFile.ps1`) - -These are the tasks that consumer modules get when they reference PowerShellBuild: - -| Task | Description | -|------|-------------| -| `Init` | Initialize build environment variables | -| `Clean` | Clear module output directory | -| `StageFiles` | Copy/compile source to output | -| `Build` | StageFiles + BuildHelp | -| `Analyze` | PSScriptAnalyzer | -| `Pester` | Pester tests | -| `Test` | Pester + Analyze | -| `GenerateMarkdown` | PlatyPS Markdown from help | -| `GenerateMAML` | MAML XML from Markdown | -| `BuildHelp` | GenerateMarkdown + GenerateMAML | -| `GenerateUpdatableHelp` | CAB file for updatable help | -| `Publish` | Publish to repository | - -Tasks with prerequisites (`Analyze`, `Pester`, `GenerateMarkdown`, `GenerateMAML`, `GenerateUpdatableHelp`) check that required modules are installed before running; they skip gracefully with a warning if the module is missing. - ---- - -## Dependencies - -Defined in `requirements.psd1`, installed via **PSDepend**: - -| Module | Version | -|--------|---------| -| BuildHelpers | 2.0.16 | -| Pester | ≥ 5.6.1 | -| psake | 4.9.0 | -| PSScriptAnalyzer | 1.24.0 | -| InvokeBuild | 5.8.1 | -| platyPS | 0.14.2 | - ---- - -## Testing - -Tests are in the `tests/` directory and use **Pester 5+** syntax. - -```powershell -# Run tests via build script (recommended) -./build.ps1 -Task Test -Bootstrap - -# Run Pester directly (after building) -Invoke-Pester ./tests -``` - -### Test Files - -| File | Tests | -|------|-------| -| `build.tests.ps1` | Module compilation, file staging, exclusion, header/footer injection | -| `Help.tests.ps1` | Help documentation completeness | -| `IBTasks.tests.ps1` | Invoke-Build task definitions | -| `Manifest.tests.ps1` | Module manifest validity | -| `Meta.tests.ps1` | Script analysis, best practices across module source | - -### TestModule - -`tests/TestModule/` is a complete example module used to exercise PowerShellBuild's tasks. It has its own `build.ps1`, `psakeFile.ps1`, `.build.ps1` (Invoke-Build), and Pester tests. - ---- - -## CI/CD (GitHub Actions) - -### Test Workflow (`.github/workflows/test.yml`) - -- **Triggers**: Push to default branch, pull requests, manual dispatch -- **Matrix**: `ubuntu-latest`, `windows-latest`, `macOS-latest` -- **Command**: `./build.ps1 -Task Test -Bootstrap` -- Supports `DEBUG` runner flag for verbose output - -### Publish Workflow (`.github/workflows/publish.yaml`) - -- **Triggers**: Manual dispatch, GitHub release published -- **Runs on**: `ubuntu-latest` -- Reads `PSGALLERY_API_KEY` secret, converts to `PSCredential`, then runs: - `./build.ps1 -Task Publish -PSGalleryApiKey $cred -Bootstrap` - ---- - -## Code Style & Conventions - -### PowerShell Formatting (from `.vscode/settings.json`) - -- **Indentation**: Spaces (not tabs) -- **Formatting preset**: OTBS (One True Brace Style) -- **Whitespace**: Spaces around pipe operators (`|`) -- **Casing**: Correct/consistent casing enforced -- **Property alignment**: Values aligned in hashtables - -### Naming Conventions - -- **Functions**: `Verb-PSBuildNoun` pattern for all public functions (e.g., `Build-PSBuildModule`, `Test-PSBuildPester`) -- **Config variable**: Always `$PSBPreference` — never rename or recreate -- **Task dependency vars**: `$PSB{TaskName}Dependency` pattern (e.g., `$PSBPesterDependency`) - -### Script Analysis - -PSScriptAnalyzer is configured via `PowerShellBuild/ScriptAnalyzerSettings.psd1`. The default severity threshold for build failure is `Error`. Warnings are reported but do not fail the build. - -Inline suppressions use the standard attribute: -```powershell -[System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreThanAssigments', '')] -``` - -Spell-checker ignores use inline comments: -```powershell -# spell-checker:ignore MAML PSGALLERY -``` - -### Localization - -User-facing strings are stored in `PowerShellBuild/en-US/Messages.psd1` and loaded via `Import-LocalizedData`. Add new strings there rather than hardcoding messages in function bodies. - ---- - -## How Consumers Use This Module - -### With psake - -```powershell -# In consumer's psakeFile.ps1 -properties { - # Override defaults BEFORE including the tasks - $PSBPreference.Build.CompileModule = $true - $PSBPreference.Test.CodeCoverage.Enabled = $true -} - -# Include PowerShellBuild tasks -Include "$PSScriptRoot/node_modules/PowerShellBuild/psakeFile.ps1" -``` - -### With Invoke-Build - -```powershell -# In consumer's .build.ps1 -. ([IO.Path]::Combine((Split-Path (Get-Module PowerShellBuild -ListAvailable).Path), 'PowerShellBuild.IB.Tasks')) - -# Override configuration after dot-sourcing -$PSBPreference.Build.CompileModule = $false -``` - ---- - -## Common Development Tasks - -### Adding a New Public Function - -1. Create the file in `PowerShellBuild/Public/NewFunction.ps1` -2. Follow the `Verb-PSBuildNoun` naming convention -3. Add any user-facing strings to `en-US/Messages.psd1` -4. Export the function by adding it to the `FunctionsToExport` array in `PowerShellBuild.psd1` -5. No need to edit `PowerShellBuild.psm1` — it dot-sources all files in `Public/` automatically - -### Adding a New Build Task - -1. Add the task to `PowerShellBuild/psakeFile.ps1` -2. Define a corresponding `$PSB{TaskName}Dependency` variable with a `if ($null -eq ...)` guard -3. Expose the dependency variable so consumers can override it -4. Update `PowerShellBuild.psd1` if any new modules are required - -### Updating Module Version - -1. Edit the `ModuleVersion` field in `PowerShellBuild/PowerShellBuild.psd1` -2. Add a changelog entry in `CHANGELOG.md` - -### Running Script Analysis Only - -```powershell -./build.ps1 -Task Analyze -``` - -### Debugging the Build - -```powershell -# Enable debug output -$DebugPreference = 'Continue' -./build.ps1 -Task Test -Bootstrap -``` - ---- - -## Environment Variables (Set by BuildHelpers) - -`Initialize-PSBuild` calls `BuildHelpers\Set-BuildEnvironment`, which populates: - -| Variable | Value | -|----------|-------| -| `$env:BHProjectPath` | Repository root directory | -| `$env:BHProjectName` | Module name (from directory structure) | -| `$env:BHPSModulePath` | Path to module source directory | -| `$env:BHPSModuleManifest` | Path to `.psd1` manifest | -| `$env:BHModulePath` | Same as `BHPSModulePath` | -| `$env:BHBuildSystem` | Detected CI system (e.g., `GitHubActions`, `Unknown`) | -| `$env:BHBranchName` | Current git branch | -| `$env:BHCommitMessage` | Latest git commit message | - ---- - -## Output Directory Structure - -After a successful build, output is in `Output/PowerShellBuild//`: - -``` -Output/ -└── PowerShellBuild/ - └── 0.7.3/ - ├── Public/ # (when CompileModule = $false) - ├── Private/ - ├── en-US/ - ├── PowerShellBuild.psd1 - ├── PowerShellBuild.psm1 - └── ScriptAnalyzerSettings.psd1 -``` - -When `CompileModule = $true`, all `.ps1` files are merged into the single `.psm1` file and the `Public/`/`Private/` directories are not copied. - ---- - -## Notes for AI Assistants - -- **Always run `./build.ps1 -Bootstrap` first** in a fresh environment to install all dependencies via PSDepend. -- The `$PSBPreference` variable is **read-only at the script scope** once `psakeFile.ps1` is loaded. To modify it, set values before loading the task file, or use `-Force` on `Set-Variable`. -- Tests require the module to be **built first** — running Pester directly against source (not output) may produce incorrect results. Use `./build.ps1 -Task Test` rather than calling `Invoke-Pester` directly unless the module is already built and imported. -- The `Output/` directory is **excluded from VS Code search** (per `.vscode/settings.json`) and should not be committed to git (it is in `.gitignore`). -- The `Build/Convert-PSAke.ps1` utility is a developer convenience tool; it is not part of the published module. -- When editing `en-US/Messages.psd1`, ensure it uses UTF-8 encoding with BOM (standard for PowerShell data files). -- The repo's own `psakeFile.ps1` (at the root) is simpler than the one inside the module (`PowerShellBuild/psakeFile.ps1`). The root one is for building the module itself; the inner one is what consumers import. +@AGENTS.md diff --git a/aim.config.json b/aim.config.json new file mode 100644 index 0000000..620e754 --- /dev/null +++ b/aim.config.json @@ -0,0 +1,31 @@ +{ + "version": "latest", + "modules": { + "include": [ + "agent-workflow", + "shorthand", + "git-workflow", + "testing", + "powershell", + "markdown", + "readme", + "github-cli", + "releases", + "contributing", + "update", + "repository-specific" + ], + "exclude": [] + }, + "externalSources": { + "enabled": true, + "repositories": [ + { + "name": "awesome-copilot", + "url": "https://github.com/github/awesome-copilot", + "path": "instructions", + "description": "Community-contributed instructions from GitHub's awesome-copilot repository" + } + ] + } +} diff --git a/instructions/agent-workflow.instructions.md b/instructions/agent-workflow.instructions.md new file mode 100644 index 0000000..efc3f66 --- /dev/null +++ b/instructions/agent-workflow.instructions.md @@ -0,0 +1,96 @@ +--- +applyTo: '**/*' +description: 'Mandatory pre-flight protocol for AI agents' +--- + +# Agent Workflow Instructions + +## Purpose + +This file defines the recommended workflow that AI agents should follow when working in +repositories using AIM. It ensures agents understand the context and guidelines before +starting work. + +## Pre-Flight Protocol + +**Before starting any task, AI agents should:** + +### 1. Identify Task Type + +Analyze the user's request and identify all areas it touches. Common patterns: + +- Code development (specific languages or frameworks) +- Documentation (Markdown files, README files) +- Git operations (commits, branches, PRs) +- Testing and quality assurance +- Security considerations +- Repository-specific customizations + +### 2. Consider Applicable Instructions + +Review the instruction files listed in the repository's `AGENTS.md` to understand: + +- Language-specific coding standards +- Framework conventions +- Documentation requirements +- Git workflow expectations +- Security best practices + +### 3. Implement with Compliance + +Execute your task following the guidelines from the applicable instruction sections. + +## Best Practices + +### Read Before Writing + +- Always read existing code before modifying it +- Understand the project's patterns and conventions +- Check for existing implementations before creating new ones + +### Confirm Understanding + +When starting complex tasks, briefly confirm your understanding: + +> "Based on the instructions, I'll follow [specific guidelines]. Here's my approach..." + +This builds trust and catches misunderstandings early. + +### Avoid Over-Engineering + +- Only make changes that are directly requested +- Keep solutions simple and focused +- Don't add features, refactoring, or improvements beyond what was asked + +### Security First + +- Never introduce security vulnerabilities +- Be careful with user input validation +- Avoid hardcoding secrets or credentials +- Follow the security guidelines in this document + +## When in Doubt + +1. **Ask for clarification** - Better to ask than implement incorrectly +2. **Check existing code** - Follow established patterns in the codebase +3. **Keep it simple** - The simplest solution that works is usually best + +## Post-Task Protocol + +### Before Committing + +1. **Run tests** - Ensure all tests pass before committing +2. **Check repository-specific requirements** - Review `repository-specific.instructions.md` for + any post-task requirements such as: + - Release processes (version bumps, changelogs, tags) + - Commit message conventions beyond standard guidelines + - Required reviewers or approval workflows + - Documentation updates + +Following repository-specific requirements ensures consistency with the project's established +workflows and prevents incomplete changes from being committed. + +## Custom Instructions + +If this repository has a custom instructions section, those guidelines take precedence for +repository-specific conventions and may override or supplement the general instructions above. diff --git a/instructions/contributing.instructions.md b/instructions/contributing.instructions.md new file mode 100644 index 0000000..3c03a57 --- /dev/null +++ b/instructions/contributing.instructions.md @@ -0,0 +1,157 @@ +--- +applyTo: '**/*' +description: 'Guidelines for contributing improvements back to the upstream AIM repository' +--- + +# Contributing Instructions for AI Agents + +When users want to improve, fix, or extend the AI agent instructions, this guide helps agents +facilitate contributions back to the upstream AIM repository. + +## When to Contribute Upstream vs. Modify Locally + +### Contribute Upstream (Submit a PR) + +- Fixing errors or typos in instruction files +- Clarifying confusing or ambiguous instructions +- Adding missing best practices that benefit all users +- Creating new instruction modules for languages, frameworks, or tools +- Improving examples or adding helpful code snippets + +### Modify Locally Only + +- Organization-specific conventions or standards +- Project-specific customizations +- Internal tooling or proprietary workflows +- Content that references internal systems or URLs + +**Local changes belong in `repository-specific.instructions.md`** - this file is never synced from upstream. + +## Agent-Assisted Contribution Workflow + +When a user wants to contribute to upstream, guide them through these steps: + +### 1. Fork the Repository + +```bash +gh repo fork tablackburn/ai-agent-instruction-modules --clone +cd ai-agent-instruction-modules +``` + +### 2. Create a Feature Branch + +```bash +git checkout -b feature/descriptive-branch-name +``` + +Use descriptive branch names: + +- `feature/add-python-module` - New module +- `fix/powershell-typo` - Bug fix +- `docs/clarify-update-procedure` - Documentation improvement + +### 3. Make Changes + +Follow existing patterns in the repository: + +**For new instruction files:** + +- Place in `instruction-templates/` folder +- Use `.instructions.md` extension +- Include required YAML frontmatter + +**For existing files:** + +- Preserve the file's structure and style +- Make minimal, focused changes +- Don't introduce unrelated modifications + +### 4. Validate Changes + +```powershell +Invoke-Pester -Path .\tests\ +``` + +Ensure all tests pass before committing. + +### 5. Commit with Conventional Commits + +```bash +git commit -m "feat: Add Python type hints module" +``` + +Prefixes: + +- `feat:` - New feature or module +- `fix:` - Bug fix or correction +- `docs:` - Documentation only +- `refactor:` - Code restructuring without behavior change + +### 6. Push and Create Pull Request + +```bash +git push origin feature/descriptive-branch-name +gh pr create --title "feat: Add Python type hints module" --body "Description of changes" +``` + +## Module Requirements + +All instruction files must include YAML frontmatter: + +```yaml +--- +applyTo: '**/*.py' +description: 'Brief description of what this module covers' +--- +``` + +**Frontmatter fields:** + +- `applyTo` - Glob pattern for applicable files (e.g., `'**/*'`, `'**/*.py'`, `'**/README.md'`) +- `description` - One-line description of the module's purpose + +**Content guidelines:** + +- Keep instructions generic and universally applicable +- Use placeholder examples (``, ``, `example.com`) +- Avoid organization-specific references +- Include practical code examples where helpful +- Follow markdown conventions from `markdown.instructions.md` + +## Pull Request Guidelines + +**Title:** Use conventional commit format (e.g., `feat: Add Python module`) + +**Description should include:** + +- Summary of changes (1-3 bullet points) +- Motivation or problem being solved +- Any breaking changes or migration notes + +**Example PR body:** + +```markdown +## Summary + +- Add Python type hints and docstring guidelines +- Include examples for common patterns +- Reference PEP 484 and PEP 257 standards + +## Motivation + +Python developers need consistent guidance on type annotations and documentation strings. +``` + +## After Submission + +- Respond to review feedback promptly +- Make requested changes in additional commits +- Once merged, downstream repositories can sync using `update.instructions.md` + +## Questions or Discussion + +For questions about contributing, open an issue on the upstream repository: + +```bash +gh issue create --repo tablackburn/ai-agent-instruction-modules --title "Question: Your topic" --body "Your question here" +``` diff --git a/instructions/git-workflow.instructions.md b/instructions/git-workflow.instructions.md new file mode 100644 index 0000000..9c3d96c --- /dev/null +++ b/instructions/git-workflow.instructions.md @@ -0,0 +1,280 @@ +--- +applyTo: '**/*' +description: 'Git workflow conventions including branching, commits, and pull requests' +--- + +# Git Workflow Instructions + +Guidelines for consistent Git usage across repositories. + +## Working on Branches + +**Agents must always work on branches, never directly on main.** + +Before starting any work: + +1. Create a branch from `main` using the naming conventions below +2. Make changes in small, logical commits +3. Push the branch and create a pull request +4. Wait for CI checks and address any review feedback +5. Report status and wait for instructions before merging + +This ensures all changes go through review and CI validation before reaching the main branch. + +## Branch Naming + +Use descriptive, lowercase branch names with hyphens. + +### Basic Format + +```text +/ +``` + +### Format with Ticket Numbers + +When using project management tools, include the ticket identifier: + +```text +/- +``` + +### Branch Types + +| Prefix | Purpose | Example | +| ----------- | ------------------------------------ | ------------------------------------ | +| `feature/` | New functionality | `feature/user-authentication` | +| `bugfix/` | Bug fixes | `bugfix/login-validation-error` | +| `hotfix/` | Urgent production patches | `hotfix/security-vulnerability` | +| `release/` | Release preparation | `release/v1.2.0` | +| `docs/` | Documentation only | `docs/api-documentation` | +| `refactor/` | Code restructuring | `refactor/database-queries` | +| `test/` | Adding or updating tests | `test/payment-integration` | +| `chore/` | Maintenance tasks | `chore/update-dependencies` | + +### Examples with Ticket Numbers + +```text +feature/PROJ-123-add-user-authentication +bugfix/PROJ-456-fix-login-validation +hotfix/PROJ-789-patch-security-issue +``` + +### Best Practices + +- **Be descriptive**: Names should reflect the branch's purpose or task +- **Be concise**: Keep names brief but meaningful +- **Be consistent**: Follow the same conventions across the team +- **Use lowercase**: Avoid mixed case for cross-platform compatibility +- **Use hyphens**: Separate words with hyphens, not underscores or spaces + +### Technical Constraints + +Avoid the following in branch names: + +- Dots at the start of the name +- Trailing slashes +- Reserved Git names (`HEAD`, `FETCH_HEAD`) +- Spaces or special characters (except hyphens and forward slashes) + +### Avoid + +- Overly long names +- Generic names like `fix`, `update`, `changes` +- Names without context or purpose + +## Commit Messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/) format: + +```text +: + +[optional body] + +[optional footer] +``` + +**Types:** + +- `feat:` - New feature +- `fix:` - Bug fix +- `docs:` - Documentation changes +- `style:` - Formatting (no code change) +- `refactor:` - Code restructuring +- `test:` - Adding/updating tests +- `chore:` - Maintenance tasks + +**Guidelines:** + +- Use imperative mood ("Add feature" not "Added feature") +- Keep first line under 72 characters +- Capitalize first letter after type +- No period at end of subject line +- Separate subject from body with blank line + +**Good examples:** + +```text +feat: Add user authentication flow +fix: Resolve null reference in payment processing +docs: Update API endpoint documentation +refactor: Extract validation logic to separate module +``` + +**Avoid:** + +```text +Fixed stuff +WIP +updates +asdfasdf +``` + +## Pull Request Guidelines + +### Before Creating a PR + +1. Ensure your branch is up to date with the base branch +2. Run tests locally and verify they pass +3. Review your own changes first +4. Remove debugging code and console logs + +### PR Title + +Use the same format as commit messages: + +```text +feat: Add user authentication flow +``` + +### PR Description + +Include: + +- **Summary** - What changed and why (1-3 bullet points) +- **Test plan** - How to verify the changes work +- **Breaking changes** - Note any breaking changes + +**Template:** + +```markdown +## Summary + +- Added user login and logout functionality +- Integrated with OAuth2 provider +- Added session management + +## Test Plan + +- [ ] Login with valid credentials succeeds +- [ ] Login with invalid credentials shows error +- [ ] Logout clears session + +## Breaking Changes + +None +``` + +### PR Size + +- Keep PRs focused and small when possible +- Large changes should be split into logical commits +- If a PR is too large, consider breaking it into smaller PRs + +### After Creating a PR + +1. **Monitor CI**: Wait for CI checks to complete and verify they pass +2. **Check for comments**: Review the PR for any feedback or requested changes +3. **Address feedback**: Make additional commits to address review comments +4. **Report status**: Report the PR status to the user and wait for instructions before merging + +## Branching Strategy + +### Default Branch + +- Use `main` as the default branch name for new repositories +- `main` is the industry standard and preferred for inclusive terminology +- When working with existing repositories using `master`, follow the repository's convention +- Consider migrating legacy repositories from `master` to `main` when practical + +### Main Branch + +- `main` is the production-ready branch +- Should always be in a deployable state +- Direct commits to main should be avoided + +### Feature Branches + +1. Create feature branch from `main` +2. Make changes in small, logical commits +3. Push branch and create PR +4. After review and approval, merge to `main` +5. Delete feature branch after merge + +### Keeping Branches Updated + +```bash +# Update your feature branch with latest main +git fetch origin +git rebase origin/main +``` + +Prefer rebase for feature branches to maintain clean history. + +## Merge Strategy + +### Squash and Merge (Recommended for feature branches) + +- Combines all commits into one clean commit +- Keeps main branch history clean +- Use when feature branch has many small/WIP commits + +### Merge Commit + +- Preserves full commit history +- Use for significant features where history is valuable +- Use for release branches + +### Rebase and Merge + +- Applies commits linearly without merge commit +- Use when commits are already clean and logical + +## Git Safety + +### Before Force Pushing + +- Never force push to `main` or shared branches +- Only force push to your own feature branches +- Always communicate with team before force pushing shared branches + +### Avoiding Common Issues + +- Pull before pushing to avoid conflicts +- Don't commit sensitive data (secrets, credentials, API keys) +- Use `.gitignore` for build artifacts and dependencies +- Review staged changes before committing + +## Useful Commands + +```bash +# View branch status +git status + +# View commit history +git log --oneline -10 + +# Amend last commit (before pushing) +git commit --amend + +# Stash changes temporarily +git stash +git stash pop + +# Undo last commit (keep changes) +git reset --soft HEAD~1 + +# View changes before committing +git diff --staged +``` diff --git a/instructions/github-cli.instructions.md b/instructions/github-cli.instructions.md new file mode 100644 index 0000000..347a024 --- /dev/null +++ b/instructions/github-cli.instructions.md @@ -0,0 +1,252 @@ +--- +applyTo: '**/*' +description: 'GitHub CLI usage guidelines and best practices (operational instructions for running gh commands, not file-specific)' +--- + +# GitHub CLI Guidelines + +Instructions for using GitHub CLI (`gh`) for repository operations. + +## Authentication + +Verify authentication before performing operations: + +```bash +# Check current authentication status +gh auth status + +# If not authenticated +gh auth login +``` + +## Repository Operations + +### Repository Discovery + +```bash +# List repositories in an organization +gh repo list --limit 100 + +# Get repository default branch (don't assume main) +gh api repos// --jq '.default_branch' + +# View repository details +gh repo view / +``` + +### Cloning and Forking + +```bash +# Clone a repository +gh repo clone / + +# Fork a repository +gh repo fork / --clone +``` + +## Issue Management + +### Creating Issues + +```bash +# Create a new issue +gh issue create --title "Issue Title" --body "Issue description" + +# Create with labels and assignee +gh issue create --title "Bug: Login fails" --body "Description" --label "bug" --assignee "@me" + +# Create interactively +gh issue create +``` + +### Viewing and Searching Issues + +```bash +# List open issues +gh issue list + +# View specific issue +gh issue view + +# Search issues +gh issue list --search "bug in:title" +``` + +### Issue Labels + +Common labels to use: + +- `bug` - Something isn't working +- `enhancement` - New feature or request +- `documentation` - Documentation improvements +- `question` - Further information requested +- `good first issue` - Good for newcomers + +## Pull Request Workflows + +### Creating Pull Requests + +```bash +# Create PR from current branch +gh pr create --title "PR Title" --body "Description" + +# Create draft PR +gh pr create --title "WIP: Feature" --body "Work in progress" --draft + +# Create PR with specific base branch +gh pr create --base develop --title "Feature" --body "Description" +``` + +### PR Review + +```bash +# List PRs awaiting review +gh pr list --search "review-requested:@me" + +# View PR details +gh pr view + +# Checkout PR locally +gh pr checkout + +# Approve PR +gh pr review --approve + +# Request changes +gh pr review --request-changes --body "Please fix..." +``` + +### Merging PRs + +```bash +# Merge PR +gh pr merge + +# Merge with squash +gh pr merge --squash + +# Merge with rebase +gh pr merge --rebase + +# Delete branch after merge +gh pr merge --delete-branch +``` + +## GitHub Actions + +### Workflow Management + +```bash +# List workflow runs +gh run list + +# View specific run +gh run view + +# Watch a running workflow +gh run watch + +# Re-run failed jobs +gh run rerun --failed +``` + +### Viewing Logs + +```bash +# View run logs +gh run view --log + +# View failed step logs +gh run view --log-failed +``` + +## Releases + +### Creating Releases + +Use `--notes-file` (write notes to a temporary file first) rather than `--notes` to avoid +escaping issues with backticks, backslashes, and quotes. For project releases, the rules in +`releases.instructions.md` take precedence over these examples. + +```bash +# Create release from tag (write notes to a file first to avoid escaping issues) +printf '## Highlights\n\n- Your release notes here\n' > release-notes.md +gh release create v1.0.0 --title "Version 1.0.0" --notes-file release-notes.md +rm release-notes.md + +# Create release with auto-generated notes +gh release create v1.0.0 --generate-notes + +# Create draft release +gh release create v1.0.0 --draft --title "Version 1.0.0" + +# Upload assets +gh release create v1.0.0 ./dist/*.zip --title "Version 1.0.0" +``` + +### Viewing Releases + +```bash +# List releases +gh release list + +# View latest release +gh release view --latest +``` + +## API Access + +### Direct API Calls + +```bash +# GET request +gh api repos// + +# POST request +gh api repos///issues --method POST -f title="Title" -f body="Body" + +# Use jq for filtering +gh api repos///pulls --jq '.[].title' +``` + +## Best Practices + +### Pre-Operation Validation + +```bash +# Verify you're in a git repository +gh repo view --json nameWithOwner --jq '.nameWithOwner' + +# Verify authentication +gh auth status +``` + +### Issue-to-Branch Workflow + +```bash +# Create issue and capture the issue number +ISSUE_NUM=$(gh issue create --title "Feature: New functionality" --body "Description" --json number --jq '.number') + +# Create feature branch using the captured issue number +git checkout -b "feature/issue-${ISSUE_NUM}-new-functionality" + +# Push and create PR +git push -u origin "feature/issue-${ISSUE_NUM}-new-functionality" +gh pr create --title "Feature: New functionality" --body "Closes #${ISSUE_NUM}" +``` + +### Common Flags + +- `--json` - Output as JSON +- `--jq` - Filter JSON output +- `--web` - Open in browser +- `--help` - Show help for any command + +## Environment Variables + +Useful environment variables: + +- `GH_TOKEN` - Authentication token +- `GH_HOST` - GitHub hostname (for enterprise) +- `GH_REPO` - Default repository +- `GH_EDITOR` - Editor for composing text diff --git a/instructions/markdown.instructions.md b/instructions/markdown.instructions.md new file mode 100644 index 0000000..430da58 --- /dev/null +++ b/instructions/markdown.instructions.md @@ -0,0 +1,123 @@ +--- +applyTo: '**/*.md' +description: 'Markdown formatting standards' +--- + +# Markdown Style Guidelines + +Consistent Markdown formatting for documentation files. + +## Blank Lines + +- Use single blank lines between sections and elements +- Never use multiple consecutive blank lines +- Headings, lists, and code blocks must have a blank line above and below + +## Headings + +- Use ATX style (`#`) not setext (underlines) +- Use consistent heading levels (don't skip levels) +- Start with a single H1 (`#`) for the document title +- Use sentence case for headings +- Include a space after `#` characters +- No trailing punctuation (colons, periods, etc.) +- Avoid duplicate heading text within the same document + +## Lists + +- Use `-` for unordered lists +- Use sequential numbering for ordered lists (`1.`, `2.`, `3.`, etc.) +- Use 2 spaces for nested list indentation + +```markdown +Text before list. + +- First item +- Second item + - Nested item + - Another nested item +- Third item + +Text after list. +``` + +## Code Blocks + +- Use backticks (`` ` ``) not tildes (`~`) for code fences +- Always specify language for fenced code blocks +- Ensure closing triple backticks are on their own line +- No trailing whitespace after closing backticks +- Code inside fenced blocks should follow the conventions of the relevant language's instruction + file (e.g., PowerShell snippets follow `powershell.instructions.md`) + +```javascript +// JavaScript code here +``` + +```python +# Python code here +``` + +```bash +# Shell code here +``` + +## Inline Formatting + +- Use `**bold**` for strong emphasis +- Use `*italic*` for light emphasis +- Use backticks for `code`, `filenames`, and `commands` +- Use backticks for keyboard shortcuts like `Ctrl+C` +- No spaces inside emphasis markers (`**text**` not `** text **`) +- No spaces inside backticks (`` `code` `` not `` ` code ` ``) +- Don't use bold/emphasis as a substitute for headings + +## Links + +- Use descriptive link text (not "click here") +- Use reference-style links for long URLs +- Use reference-style links when the same URL appears multiple times +- Links must have valid destinations (no empty hrefs) + +```markdown +See the [official documentation][docs] for more details. +The [documentation][docs] covers advanced topics. + +[docs]: https://example.com/documentation +``` + +## Images + +- Always include alt text for accessibility +- Use descriptive alt text that conveys the image content + +```markdown +![Diagram showing data flow between components](./images/data-flow.png) +``` + +## Line Length + +- Wrap prose at 80-100 characters when practical +- Don't wrap tables - maintain table formatting +- Don't wrap URLs or code blocks + +## File Structure + +- End all files with exactly one newline character +- No trailing whitespace on any lines +- Use spaces, not hard tabs +- Use UTF-8 encoding +- Avoid inline HTML when markdown alternatives exist + +## Tables + +- Align columns for readability in source +- Use header row separators +- Keep tables simple when possible + +```markdown +| Column 1 | Column 2 | Column 3 | +|----------|----------|----------| +| Value 1 | Value 2 | Value 3 | +| Value 4 | Value 5 | Value 6 | +``` diff --git a/instructions/powershell.instructions.md b/instructions/powershell.instructions.md new file mode 100644 index 0000000..8493861 --- /dev/null +++ b/instructions/powershell.instructions.md @@ -0,0 +1,515 @@ +--- +applyTo: '**/*.ps1,**/*.psm1,**/*.psd1' +description: 'PowerShell coding standards and best practices' +--- + +# PowerShell Style Guidelines + +Style rules for PowerShell code based on Microsoft guidelines and community standards. + +## Common Mistakes to Avoid + +**IMPORTANT**: These are frequent violations that MUST be avoided: + +1. **Plural nouns in function names** - ALWAYS use singular nouns regardless of how many items the + function returns. Use `Get-User` not `Get-Users`, `Get-Item` not `Get-Items`. + +## Function Structure + +1. Always start functions with `[CmdletBinding()]` attribute +2. Always include explicit `param()` block +3. Use `process {}` block when accepting pipeline input +4. For system-modifying cmdlets, use `[CmdletBinding(SupportsShouldProcess)]` +5. Document output types with `[OutputType([TypeName])]` attribute +6. Include comment-based help for all functions +7. Do not define nested functions inside other functions; define helper functions at module or + script scope + +```powershell +# Bad - nested function +function Get-Data { + [CmdletBinding()] + param() + + function Format-Result { + param($Value) + # Helper logic + } + + $result = Get-RawData + Format-Result -Value $result +} + +# Good - separate functions at module/script scope +function Format-Result { + [CmdletBinding()] + [OutputType([psobject])] + param( + [Parameter(Mandatory)] + [ValidateNotNull()] + [psobject] + $Value + ) + # Helper logic +} + + +function Get-Data { + [CmdletBinding()] + [OutputType([hashtable])] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] + $Name + ) + + # Implementation +} + +# Function with pipeline input +function Get-PipelineInput { + [CmdletBinding()] + [OutputType([PSCustomObject])] + param( + [Parameter(ValueFromPipeline)] + [ValidateNotNull()] + [string] + $InputData + ) + + process { + # Process each pipeline item + } +} +``` + +## Type Accelerators + +Prefer type accelerators over full .NET type names: + +- `[string]`, `[int]`, `[bool]`, `[array]`, `[hashtable]` +- `[PSCustomObject]`, `[PSCredential]`, `[datetime]`, `[regex]` + +```powershell +# Good - type accelerators in parameter declarations +function Get-Setting { + [CmdletBinding()] + [OutputType([PSCustomObject])] + param( + [Parameter(Mandatory)] + [ValidateNotNull()] + [hashtable] + $Configuration + ) +} + +# Avoid - full .NET type names +function Get-Setting { + [CmdletBinding()] + [OutputType([System.Management.Automation.PSCustomObject])] + param( + [Parameter(Mandatory)] + [System.Collections.Hashtable] + $Configuration + ) +} +``` + +## Naming Conventions + +1. Use approved PowerShell verbs only (verify with `Get-Verb`) +2. Use singular nouns for function names (`Get-Item` not `Get-Items`) +3. Use PascalCase for function names and parameters +4. Use camelCase for local variables (`$userName`, `$itemCount`) +5. Use descriptive variable names that indicate purpose +6. Use full cmdlet names, never aliases (`Get-Process` not `gps`) + +```powershell +# Good - descriptive variable names +$backupPath = 'C:\Backups' +$backupFiles = Get-ChildItem -Path $backupPath -Filter '*.bak' +$activeUsers = Get-ADUser -Filter { Enabled -eq $true } + +# Bad - generic variable names +$files = Get-ChildItem -Path $backupPath -Filter '*.bak' +$users = Get-ADUser -Filter { Enabled -eq $true } +``` + +### Path vs Directory Naming + +Use the appropriate suffix to indicate what the variable holds: + +- Use `Path` for any path string (file or folder) +- Reserve `Directory` for directory objects (e.g., `[System.IO.DirectoryInfo]`) or bare folder names + +```powershell +# Good - Path suffix for path strings +$configurationPath = Join-Path -Path $PSScriptRoot -ChildPath 'config.json' +$outputPath = Join-Path -Path $PSScriptRoot -ChildPath 'results' +$backupPath = 'C:\Backups' + +# Good - Directory suffix for a directory object +$logDirectory = [System.IO.DirectoryInfo]::new('C:\Logs') + +# Bad - Directory suffix on a path string +$outputDirectory = 'C:\App\results' +``` + +## Parameters + +1. Use full parameter names in scripts and functions +2. Always use quotes around string parameter values +3. Include validation on every parameter +4. Place each component on its own line + +```powershell +# Good - string parameter values are quoted +Get-Process -Name 'powershell' +Get-ChildItem -Path 'C:\Program Files' -Filter '*.txt' + +# Bad - bare string parameter values +Get-Process -Name powershell +Get-ChildItem -Path C:\Program Files -Filter *.txt +``` + +```powershell +function Get-UserData { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] + $UserName, + + [Parameter()] + [ValidateRange(1, 100)] + [int] + $MaxResults = 10, + + [Parameter(ValueFromPipeline)] + [ValidateNotNull()] + [string[]] + $ComputerName + ) +} +``` + +## Formatting + +1. Opening brace `{` at end of line, closing brace `}` on new line +2. Use 4 spaces per indentation level +3. Maximum line length: 115 characters +4. Use splatting for long parameter lists +5. Two blank lines before function definitions +6. One blank line at end of file + +```powershell +function Test-Code { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [ValidateRange(1, 100)] + [int] + $Value + ) + + if ($Value -gt 10) { + Write-Output 'Greater' + } + elseif ($Value -eq 10) { + Write-Output 'Equal' + } + else { + Write-Output 'Lesser' + } +} + +# Good - splatting for readability +$invokeRestMethodParameters = @{ + Uri = 'https://api.example.com/endpoint' + Method = 'Post' + Headers = $headers + Body = $body +} +Invoke-RestMethod @invokeRestMethodParameters +``` + +## Line Continuation + +1. Do not use backtick (`` ` ``) line continuation +2. Do not use semicolons (`;`) to chain multiple statements on one line +3. Prefer splatting (`@copyItemParameters`) for long parameter lists +4. Use natural continuation inside `()`, `@{}`, or `@()` when grouping expressions or collections +5. Place each hashtable element on its own line in multi-line hashtables +6. Pipelines continue without backticks when the line ends with `|` + +```powershell +# Good - splatting for long parameter lists +$copyItemParameters = @{ + Path = $sourcePath + Destination = $destinationPath + Recurse = $true + Force = $true +} +Copy-Item @copyItemParameters + +# Good - pipeline continues across lines +Get-ChildItem -Path $sourceDirectory -Recurse | + Where-Object { $_.Length -gt 1MB } | + Sort-Object -Property 'Length' -Descending + +# Good - natural continuation inside parentheses +$summaryMessage = ( + "Processed $successCount of $totalCount records. " + + "Skipped $skipCount records. " + + "Encountered $errorCount errors." +) + +# Good - for-loop semicolons are syntactic, not statement chaining +for ($i = 0; $i -lt 10; $i++) { + Write-Output -InputObject $i +} + +# Good - hashtable with each element on its own line +$webRequestOptions = @{ + Name = 'Value' + Size = 100 +} + +# Bad - backtick line continuation +Copy-Item -Path $sourcePath ` + -Destination $destinationPath ` + -Recurse ` + -Force + +# Bad - semicolons chaining statements +Import-Module -Name 'PSReadLine'; Set-PSReadLineOption -EditMode 'Emacs' + +# Bad - hashtable elements chained with semicolons on one line +$webRequestOptions = @{ Name = 'Value'; Size = 100 } +``` + +## Paths and File System + +1. Use `$PSScriptRoot` for script-relative paths +2. Use `$Env:UserProfile` or `$HOME` instead of `~` +3. Use `Join-Path` to construct paths + +```powershell +# Good +$configurationPath = Join-Path -Path $PSScriptRoot -ChildPath 'config.json' +$documentsPath = Join-Path -Path $Env:UserProfile -ChildPath 'Documents' + +# Bad +$configurationPath = '.\config.json' +$documentsPath = '~\Documents' +``` + +## Error Handling + +1. Use `-ErrorAction 'Stop'` for cmdlets within try/catch +2. Immediately copy `$_` in catch blocks before other commands + +```powershell +$filePath = 'C:\Data\settings.json' +try { + Get-Item -Path $filePath -ErrorAction 'Stop' +} +catch { + $errorRecord = $_ # Capture immediately + Write-Error "Failed: $($errorRecord.Exception.Message)" +} +``` + +## Credential Handling + +1. Use `[PSCredential]` for credential parameters, never `[string]` for passwords +2. Make credentials optional when the function can run without them +3. Use `[System.Management.Automation.Credential()]` attribute for flexibility + +```powershell +function Connect-Service { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string] + $Server, + + [Parameter()] + [ValidateNotNull()] + [System.Management.Automation.PSCredential] + [System.Management.Automation.Credential()] + $Credential = [System.Management.Automation.PSCredential]::Empty + ) + + # Check if credentials were provided + if ($Credential -eq [System.Management.Automation.PSCredential]::Empty) { + # Use current user context + } + else { + # Use provided credentials + } +} +``` + +## Output + +1. Write objects to pipeline immediately, don't batch into arrays +2. Use `Write-Verbose` for detailed operation information +3. Use `Write-Warning` for potential issues + +```powershell +# Good - immediate output +foreach ($item in $collection) { + $result = Format-Item -InputObject $item + $result # Output immediately +} + +# Bad - batching +$results = @() +foreach ($item in $collection) { + $results += Format-Item -InputObject $item +} +$results +``` + +## Documentation + +All functions must include comment-based help: + +```powershell +function Get-UserData { + <# + .SYNOPSIS + Brief one-line description. + + .DESCRIPTION + Detailed description of behavior. + + .PARAMETER UserName + Description of the parameter. + + .EXAMPLE + Get-UserData -UserName 'jsmith' + + Retrieves data for user jsmith. + + .OUTPUTS + System.Management.Automation.PSCustomObject + #> + [CmdletBinding()] + [OutputType([PSCustomObject])] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] + $UserName + ) + + # Implementation +} +``` + +## Quotes + +1. Use single quotes for string literals +2. Use double quotes only when variable expansion is needed +3. Quote hashtable keys only when necessary (hyphens, spaces) + +```powershell +# Good +$headers = @{ + Authorization = "Bearer $token" # Needs expansion + 'User-Agent' = 'PowerShell' # Key has hyphen +} + +$branchName = "feature/issue-$issueNumber" +$title = 'Static string' +``` + +## Spacing + +1. Spaces around all operators: `$x = 1 + 2` +2. Spaces around comparison operators: `$value -eq 10` +3. Space after commas and semicolons +4. No trailing spaces + +## Build Systems + +When a repository uses a build system (psake, Invoke-Build, etc.), use the build system's tasks for +operations like testing, building, publishing, and deployment rather than running commands directly +or creating separate scripts. Check for common build files: + +- `psakefile.ps1` or `psake.ps1` (psake) +- `*.build.ps1` (Invoke-Build) +- `build.ps1` (general build script) + +```powershell +# Good - use the build system +Invoke-psake -taskList Test +Invoke-Build -Task Test + +# Avoid - bypassing the build system +Invoke-Pester -Path .\tests\ +``` + +## Static Analysis + +PSScriptAnalyzer warnings indicate real issues. Fix the underlying problem rather than suppressing warnings. + +### Warnings to Always Fix + +These warnings represent naming and style violations that should be corrected: + +- **PSUseSingularNouns** - Rename function to use singular noun (`Get-Item` not `Get-Items`) +- **PSUseApprovedVerbs** - Use an approved verb from `Get-Verb` +- **PSAvoidUsingCmdletAliases** - Replace alias with full cmdlet name +- **PSAvoidUsingWriteHost** - Use `Write-Output`, `Write-Verbose`, or `Write-Information` + +```powershell +# Bad - suppressing instead of fixing +function Get-Items { # PSUseSingularNouns warning + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] + [CmdletBinding()] + param() + # Returns multiple items +} + +# Good - fix the naming +function Get-Item { + [CmdletBinding()] + param() + # Returns zero, one, or more items (singular noun is correct regardless) +} +``` + +### Suppression Requirements + +When suppression is genuinely necessary (rare), include a justification: + +1. Use `SuppressMessageAttribute` with the `Justification` parameter +2. Explain why the warning cannot be resolved +3. Reference external constraints if applicable + +```powershell +# Acceptable - justified suppression for API compatibility +function Get-AWSItems { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseSingularNouns', + '', + Justification = 'Matches AWS SDK naming convention for consistency with existing tooling' + )] + [CmdletBinding()] + param() +} +``` + +### Never Suppress Without Justification + +Suppressions without justification are not acceptable: + +```powershell +# Never do this +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')] +``` diff --git a/instructions/readme.instructions.md b/instructions/readme.instructions.md new file mode 100644 index 0000000..5b9ea49 --- /dev/null +++ b/instructions/readme.instructions.md @@ -0,0 +1,31 @@ +--- +applyTo: '**/README.md' +description: 'README maintenance guidelines' +--- + +# README Instructions + +## Purpose + +Guidelines and requirements for maintaining `README.md` files in repositories using these instructions. + +## Requirements + +- The `README.md` must always reflect the current repository structure, naming conventions, and + setup instructions. +- Whenever you make changes to files, instructions, or workflows, review and update the + `README.md` to ensure: + - All file and directory names are accurate and up to date + - All setup and usage instructions match the latest practices and workflows + - The repository structure diagram is correct + - Any new or deprecated features are documented +- Use clear, concise language and follow Markdown best practices (see `markdown.instructions.md`). +- Place repository-specific or maintainer-only notes in clearly marked sections. +- Reference the CHANGELOG.md file for a summary of recent changes. + +## Best Practices + +- When making changes to instructions, templates, or workflows, update the `README.md` as part of + your change process. +- Include a checklist item for README review in pull requests and release notes. +- Ensure consistency between the `README.md`, instruction files, and actual repository contents. diff --git a/instructions/releases.instructions.md b/instructions/releases.instructions.md new file mode 100644 index 0000000..17aa7c7 --- /dev/null +++ b/instructions/releases.instructions.md @@ -0,0 +1,85 @@ +--- +applyTo: '**/*' +description: 'Release management guidelines for AI agents' +--- + +# Release Instructions for AI Agents + +When creating releases, AI agents must follow these guidelines to ensure proper release +management and avoid formatting issues. + +These instructions are self-contained for release processes but reference +repository-specific.instructions.md for additional requirements. + +## Creating Releases + +Always use `--notes-file` instead of `--notes` when creating GitHub releases to avoid escaping +issues with special characters (backticks, backslashes, quotes, etc.): + +```powershell +# Create a temporary file with release notes +$releaseNotes = @" +## Added + +- Your changes here + +## Changed + +- Your changes here + +## Fixed + +- Your changes here +"@ + +$releaseNotes | Out-File -FilePath "release-notes.md" -Encoding utf8 +gh release create v0.x.y --title "v0.x.y - Release Title" --notes-file release-notes.md +Remove-Item "release-notes.md" +``` + +## Release Notes Format + +Release notes should follow the [Keep a Changelog](https://keepachangelog.com/) format: + +- Use standard sections: Added, Changed, Deprecated, Removed, Fixed, Security +- Write clear, user-focused descriptions +- Reference issue numbers or PRs where relevant +- Use present tense for changes ("Add feature" not "Added feature" in the section items) +- Keep descriptions concise but informative + +## Version Numbering + +Follow [Semantic Versioning](https://semver.org/): + +- **MAJOR** version (x.0.0): Breaking changes or incompatible API changes +- **MINOR** version (0.x.0): New features in a backward-compatible manner +- **PATCH** version (0.0.x): Backward-compatible bug fixes + +## Pre-Release Checklist + +Follow `git-workflow.instructions.md` for branching and PR workflow. The steps below are +release-specific: + +1. **Verify current release state**: Run `gh release list --limit 5` to check the most recent + releases. Compare the latest released version against the version in CHANGELOG.md. If they + match, the changelog version needs to be incremented. If the changelog is already ahead, use + that version. NEVER release a version that already exists. +2. **Check repository-specific instructions**: Review `repository-specific.instructions.md` for + any additional release requirements specific to this repository +3. **Update CHANGELOG.md**: Add new version section with all changes +4. **Update version numbers**: Bump version in relevant files as needed +5. **Update changelog links**: Add comparison link for the new version at the bottom of + CHANGELOG.md (e.g., `[0.2.0]: https://github.com/owner/repo/compare/v0.1.0...v0.2.0`) +6. **Run tests**: Ensure all tests pass +7. **Commit changes**: Commit all version updates +8. **Create PR and wait for merge**: Follow the PR workflow in `git-workflow.instructions.md` +9. **Create release**: After PR is merged, use `gh release create` with `--notes-file` + +## Post-Release + +After creating a release: + +1. Verify the release appears correctly on GitHub +2. Check that release notes display properly (no formatting issues) +3. Confirm download links work if applicable +4. Notify team members if this is a significant release diff --git a/instructions/repository-specific.instructions.md b/instructions/repository-specific.instructions.md new file mode 100644 index 0000000..f390059 --- /dev/null +++ b/instructions/repository-specific.instructions.md @@ -0,0 +1,388 @@ +--- +applyTo: '**/*' +description: 'Repository-specific instructions for the PowerShellBuild module' +--- + +# Repository-Specific Instructions + +These instructions cover the parts of PowerShellBuild that an agent cannot infer from the +standard AIM modules (`powershell`, `git-workflow`, `testing`, etc.). Read those first; this +file only adds repo-specific concepts. + +## Repository Context + +**PowerShellBuild** is a PowerShell module that provides standardized build, test, and publish +tasks for other PowerShell module projects. It supports two task-runner frameworks: + +- **psake** (4.9.0+) +- **Invoke-Build** (5.8.1+) + +- Current version: **0.8.0** (see `PowerShellBuild/PowerShellBuild.psd1`) +- `PowerShellVersion` in the manifest is currently `'3.0'` — almost certainly wrong; under + review in the v1.0.0 roadmap (psake/PowerShellBuild#120) +- Cross-platform: Windows, Linux, macOS (CI matrix in `.github/workflows/test.yml`) +- The module is **psake/PowerShellBuild** on PSGallery and GitHub; maintained by the psake org + +## Repository Layout + +```text +PowerShellBuild/ +├── Build/Convert-PSAke.ps1 # Dev utility: converts psake tasks to Invoke-Build (not shipped) +├── PowerShellBuild/ # THE MODULE SOURCE (system under test) +│ ├── Public/ # 12 exported functions +│ ├── Private/ # Internal helpers +│ ├── en-US/Messages.psd1 # Localized strings (Import-LocalizedData) +│ ├── PowerShellBuild.psd1 # Manifest +│ ├── PowerShellBuild.psm1 # Dot-sources Public/ and Private/ +│ ├── ScriptAnalyzerSettings.psd1 +│ ├── build.properties.ps1 # $PSBPreference (canonical config hashtable) +│ ├── psakeFile.ps1 # Tasks consumers import +│ └── IB.tasks.ps1 # Invoke-Build entry (aliased as PowerShellBuild.IB.Tasks) +├── tests/ # Pester 5+ tests +│ └── TestModule/ # Sample module exercised by the test suite +├── build.ps1 # Main build entry point for THIS repo +├── build.settings.ps1 # Build settings for THIS repo's own psake build +├── psakeFile.ps1 # psake tasks for building THIS repo (simpler than the inner one) +└── requirements.psd1 # PSDepend manifest +``` + +**The two `psakeFile.ps1` files serve different purposes:** + +- Root `psakeFile.ps1` → builds *this* repo +- `PowerShellBuild/psakeFile.ps1` → what consumers import to build *their* repo + +## Key Concepts + +### `$PSBPreference` — the central configuration object + +All build behavior is controlled through a single ordered hashtable named `$PSBPreference`, +defined in `PowerShellBuild/build.properties.ps1`. The variable name is fixed — never rename +it or recreate it under a different name. + +It is set as a **read-only script-scoped variable** when `psakeFile.ps1` is loaded. To modify +it, set values *before* loading the task file, or use `Set-Variable -Force`. + +Sections: + +| Section | Purpose | +| -------------- | ------------------------------------------------------------------------------------------------------------------ | +| `General` | ProjectRoot, SrcRootDir, ModuleName, ModuleVersion, ModuleManifestPath | +| `Build` | OutDir, ModuleOutDir, CompileModule, CompileDirectories, CopyDirectories, Exclude | +| `Test` | Enabled, RootDir, OutputFile/Format, ScriptAnalysis, CodeCoverage, ImportModule, etc. | +| `Help` | UpdatableHelpOutDir, DefaultLocale, ConvertReadMeToAboutHelp | +| `Docs` | RootDir, Overwrite, AlphabeticParamsOrder, ExcludeDontShow, UseFullTypeName | +| `Publish` | PSRepository, PSRepositoryApiKey, PSRepositoryCredential | +| `Sign` | Enabled, CertificateSource, CertStoreLocation, Thumbprint, EnvVar/PfxFile sources, TimestampServer, HashAlgorithm, FilesToSign, Catalog | +| `Sign.Catalog` | Enabled, Version, FileName | + +### Module compilation modes + +`$PSBPreference.Build.CompileModule` controls how the module is staged to the output directory: + +- `$false` (default) — files copied as-is, preserving the `Public/`/`Private/` structure +- `$true` — all `.ps1` files from `CompileDirectories` (default: `Enum`, `Classes`, `Private`, + `Public`) are concatenated into a single `.psm1`. Optional `CompileHeader`, `CompileFooter`, + `CompileScriptHeader`, and `CompileScriptFooter` strings can be injected. + +### Task dependency variables + +Task dependencies in `PowerShellBuild/psakeFile.ps1` are defined via variables checked with +`if ($null -eq ...)`. This lets consumers override dependencies *before* importing the tasks +file: + +```powershell +# Example: insert a custom task before Pester runs +$PSBPesterDependency = @('Build', 'MyCustomTask') +``` + +Variables (pattern: `$PSB{TaskName}Dependency`): + +| Variable | Default | +| ------------------------------------- | -------------------------------- | +| `$PSBCleanDependency` | `@('Init')` | +| `$PSBStageFilesDependency` | `@('Clean')` | +| `$PSBBuildDependency` | `@('StageFiles', 'BuildHelp')` | +| `$PSBAnalyzeDependency` | `@('Build')` | +| `$PSBPesterDependency` | `@('Build')` | +| `$PSBTestDependency` | `@('Pester', 'Analyze')` | +| `$PSBBuildHelpDependency` | `@('GenerateMarkdown', 'GenerateMAML')` | +| `$PSBGenerateMarkdownDependency` | `@('StageFiles')` | +| `$PSBGenerateMAMLDependency` | `@('GenerateMarkdown')` | +| `$PSBGenerateUpdatableHelpDependency` | `@('BuildHelp')` | +| `$PSBPublishDependency` | `@('Test')` | +| `$PSBSignModuleDependency` | `@('Build')` | +| `$PSBBuildCatalogDependency` | `@('SignModule')` | +| `$PSBSignCatalogDependency` | `@('BuildCatalog')` | +| `$PSBSignDependency` | `@('SignCatalog')` | + +## Public API (Exported Functions) + +12 exported functions in `PowerShellBuild/Public/` (all follow the `Verb-PSBuildNoun` naming +pattern — keep new public functions consistent with this): + +| Function | Description | +| ------------------------------ | ---------------------------------------------------------------------- | +| `Initialize-PSBuild` | Sets up BuildHelpers env vars, displays build info | +| `Build-PSBuildModule` | Copies/compiles module source to output directory | +| `Clear-PSBuildOutputFolder` | Safely removes the build output directory | +| `Build-PSBuildMarkdown` | Generates PlatyPS Markdown docs from module help | +| `Build-PSBuildMAMLHelp` | Converts PlatyPS Markdown to MAML XML help files | +| `Build-PSBuildUpdatableHelp` | Creates a `.cab` file for updatable help | +| `Test-PSBuildPester` | Runs Pester tests with configurable output and coverage | +| `Test-PSBuildScriptAnalysis` | Runs PSScriptAnalyzer with a configurable severity threshold | +| `Publish-PSBuildModule` | Publishes the built module to a PowerShell repository | +| `Get-PSBuildCertificate` | Resolves an Authenticode signing certificate | +| `Invoke-PSBuildModuleSigning` | Signs module files with an Authenticode certificate | +| `New-PSBuildFileCatalog` | Generates a `.cat` file catalog for the module | + +Private helper: `Remove-ExcludedItem` — filters file system items by regex patterns during builds. + +### Invoke-Build alias + +The module exports an alias `PowerShellBuild.IB.Tasks` that points to `IB.tasks.ps1`, enabling +the Invoke-Build dot-source pattern: + +```powershell +# In a consumer's .build.ps1 for Invoke-Build +Import-Module PowerShellBuild +. PowerShellBuild.IB.Tasks +``` + +## Build Workflows + +### Building this repo + +The repo uses its own psake build. Main entry point is `./build.ps1`. **Run with PowerShell 7+ +(`pwsh`).** + +```powershell +# First time in a fresh env — installs deps via PSDepend +./build.ps1 -Bootstrap + +# Specific tasks +./build.ps1 -Task Build +./build.ps1 -Task Test +./build.ps1 -Task Analyze +./build.ps1 -Task Pester + +# List available tasks +./build.ps1 -Help + +# Publish to PSGallery (requires API-key credential) +./build.ps1 -Task Publish -PSGalleryApiKey $cred +``` + +### Repo-level tasks (root `psakeFile.ps1`) + +| Task | Depends On | Description | +| --------- | ---------------------- | ------------------------------------------ | +| `default` | Test | Default task | +| `Init` | — | Initialize build env (shows `BH*` env vars)| +| `Clean` | Init | Remove output directory | +| `Build` | Init, Clean | Copy module source to output | +| `Analyze` | Build | Run PSScriptAnalyzer | +| `Pester` | Build | Run Pester tests | +| `Test` | Init, Analyze, Pester | Run all tests | +| `Publish` | Test | Publish to PSGallery | + +### Module-level tasks (consumer-facing `PowerShellBuild/psakeFile.ps1`) + +These are the tasks consumer modules get when they import PowerShellBuild: + +| Task | Description | +| ----------------------- | -------------------------------------------- | +| `Init` | Initialize build env variables | +| `Clean` | Clear module output directory | +| `StageFiles` | Copy/compile source to output | +| `Build` | StageFiles + BuildHelp | +| `Analyze` | PSScriptAnalyzer | +| `Pester` | Pester tests | +| `Test` | Pester + Analyze | +| `GenerateMarkdown` | PlatyPS Markdown from help | +| `GenerateMAML` | MAML XML from Markdown | +| `BuildHelp` | GenerateMarkdown + GenerateMAML | +| `GenerateUpdatableHelp` | CAB file for updatable help | +| `Publish` | Publish to repository | +| `SignModule` | Authenticode-sign module files (`*.psd1`, `*.psm1`, `*.ps1`) | +| `BuildCatalog` | Create Windows catalog (`.cat`) for the built module | +| `SignCatalog` | Authenticode-sign the module catalog file | +| `Sign` | Meta task — runs the full signing chain | + +Tasks with prerequisite modules (`Analyze`, `Pester`, `GenerateMarkdown`, `GenerateMAML`, +`GenerateUpdatableHelp`) check that required modules are installed; they skip gracefully +with a warning if the module is missing. + +The signing tasks (`SignModule`, `BuildCatalog`, `SignCatalog`) have similar preconditions: +they skip when `$PSBPreference.Sign.Enabled` is `$false` (catalog tasks also require +`$PSBPreference.Sign.Catalog.Enabled = $true`) or when the required Windows-only cmdlets +(`Set-AuthenticodeSignature`, `New-FileCatalog`) are not available — so signing safely +no-ops on non-Windows. + +## Dependencies + +Defined in `requirements.psd1`, installed via **PSDepend** when `./build.ps1 -Bootstrap` runs: + +| Module | Version | +| ---------------- | -------- | +| BuildHelpers | 2.0.16 | +| Pester | ≥ 5.6.1 | +| psake | 4.9.0 | +| PSScriptAnalyzer | 1.24.0 | +| InvokeBuild | 5.8.1 | +| platyPS | 0.14.2 | + +## Testing + +Tests live in `tests/` and use **Pester 5+** syntax. + +- Always build the module before running Pester directly — running against source can produce + incorrect results. Prefer `./build.ps1 -Task Test` over a raw `Invoke-Pester` call. +- `tests/TestModule/` is a complete example module used to exercise PowerShellBuild's tasks. + It has its own `build.ps1`, `psakeFile.ps1`, `.build.ps1` (Invoke-Build), and Pester tests. + +| Test file | Tests | +| ---------------------- | ----------------------------------------------------------------------- | +| `build.tests.ps1` | Module compilation, file staging, exclusion, header/footer injection | +| `Help.tests.ps1` | Help documentation completeness | +| `IBTasks.tests.ps1` | Invoke-Build task definitions | +| `Manifest.tests.ps1` | Module manifest validity | +| `Meta.tests.ps1` | Script analysis, best practices across module source | + +## CI / CD (GitHub Actions) + +### Test workflow (`.github/workflows/test.yml`) + +- Triggers: push to default branch, pull requests, manual dispatch +- Matrix: `ubuntu-latest`, `windows-latest`, `macOS-latest` +- Command: `./build.ps1 -Task Test -Bootstrap` +- Supports a `DEBUG` runner flag for verbose output + +### Publish workflow (`.github/workflows/publish.yaml`) + +- Triggers: manual dispatch, GitHub release published +- Runs on: `ubuntu-latest` +- Reads `PSGALLERY_API_KEY` secret, converts to `PSCredential`, runs + `./build.ps1 -Task Publish -PSGalleryApiKey $cred -Bootstrap` + +## Repo-Specific Conventions + +These supplement `powershell.instructions.md` and `git-workflow.instructions.md` — they +don't replace them. + +- **Function naming**: public functions follow `Verb-PSBuildNoun` (e.g., `Build-PSBuildModule`, + `Test-PSBuildPester`). Always use an approved verb. +- **Config variable**: always `$PSBPreference`. Never rename or recreate it. +- **Task dependency vars**: `$PSB{TaskName}Dependency` (e.g., `$PSBPesterDependency`). +- **Localization**: user-facing strings live in `PowerShellBuild/en-US/Messages.psd1` and load + via `Import-LocalizedData`. Add new strings there rather than hardcoding messages in + function bodies. Use UTF-8 with BOM (standard for PowerShell data files). +- **Script analysis**: PSScriptAnalyzer config is `PowerShellBuild/ScriptAnalyzerSettings.psd1`. + Default severity threshold for build failure is `Error`. Warnings are reported but don't + fail the build. +- **Spell-checker ignores**: inline comments — `# spell-checker:ignore MAML PSGALLERY`. + +## How Consumers Use This Module + +### With psake + +```powershell +# In consumer's psakeFile.ps1 +properties { + # These settings overwrite values supplied from the PowerShellBuild + # module and govern how those tasks are executed + $PSBPreference.Test.ScriptAnalysisEnabled = $false + $PSBPreference.Test.CodeCoverage.Enabled = $true +} + +task default -depends Build + +task Build -FromModule PowerShellBuild -Version '0.1.0' +``` + +### With Invoke-Build + +```powershell +# In consumer's .build.ps1 +Import-Module PowerShellBuild +. PowerShellBuild.IB.Tasks + +# Override configuration after dot-sourcing +$PSBPreference.Build.CompileModule = $false +``` + +## Common Development Tasks + +### Adding a new public function + +1. Create the file under `PowerShellBuild/Public/NewFunction.ps1` +2. Use the `Verb-PSBuildNoun` naming pattern +3. Add any user-facing strings to `PowerShellBuild/en-US/Messages.psd1` +4. Add the function name to `FunctionsToExport` in `PowerShellBuild.psd1` +5. No edit to `PowerShellBuild.psm1` needed — it dot-sources all files in `Public/` automatically + +### Adding a new build task + +1. Add the task to `PowerShellBuild/psakeFile.ps1` +2. Define a corresponding `$PSB{TaskName}Dependency` variable with an `if ($null -eq ...)` guard +3. If the task requires a new module, update `PowerShellBuild.psd1` and `requirements.psd1` + +### Updating module version + +1. Edit `ModuleVersion` in `PowerShellBuild/PowerShellBuild.psd1` +2. Add a `CHANGELOG.md` entry (see `releases.instructions.md` for format) + +## Environment Variables (set by BuildHelpers) + +`Initialize-PSBuild` calls `BuildHelpers\Set-BuildEnvironment`, which populates: + +| Variable | Value | +| ------------------------- | ---------------------------------------------------- | +| `$env:BHProjectPath` | Repository root directory | +| `$env:BHProjectName` | Module name (from directory structure) | +| `$env:BHPSModulePath` | Path to module source directory | +| `$env:BHPSModuleManifest` | Path to `.psd1` manifest | +| `$env:BHModulePath` | Same as `BHPSModulePath` | +| `$env:BHBuildSystem` | Detected CI system (e.g., `GitHubActions`, `Unknown`)| +| `$env:BHBranchName` | Current git branch | +| `$env:BHCommitMessage` | Latest git commit message | + +## Output Directory Structure + +After a successful build: + +```text +Output/ +└── PowerShellBuild/ + └── 0.8.0/ + ├── Public/ # (when CompileModule = $false) + ├── Private/ + ├── en-US/ + ├── PowerShellBuild.psd1 + ├── PowerShellBuild.psm1 + └── ScriptAnalyzerSettings.psd1 +``` + +When `CompileModule = $true`, all `.ps1` files are merged into the single `.psm1` and the +`Public/`/`Private/` directories are not copied to output. + +`Output/` is in `.gitignore` and excluded from VS Code search (`.vscode/settings.json`). + +## v1.0.0 Roadmap + +The v1.0.0 release is actively being planned in **psake/PowerShellBuild#120**. Locked-in +decisions include: PRs directly to `main`, `1.0.0-preview.N` prereleases after each phase, +hard cut + migration guide (no deprecation cycle), psake 5.x in scope. Phase-by-phase +breakdown lives in the tracking issue. + +Migration guide path (created in Phase 1): `docs/migration/v0.8-to-v1.0.md`. + +## Notes for AI Agents + +- **First-time setup**: always run `./build.ps1 -Bootstrap` in a fresh environment to install + dependencies via PSDepend. +- **`$PSBPreference` is read-only at script scope** once `psakeFile.ps1` is loaded. To modify + it, set values before loading the task file, or use `Set-Variable -Force`. +- **Tests need the module built first** — running Pester directly against source can produce + incorrect results. Use `./build.ps1 -Task Test` rather than raw `Invoke-Pester` unless the + module is already built and imported. +- `Build/Convert-PSAke.ps1` is a developer convenience tool, not part of the published module. diff --git a/instructions/shorthand.instructions.md b/instructions/shorthand.instructions.md new file mode 100644 index 0000000..de68961 --- /dev/null +++ b/instructions/shorthand.instructions.md @@ -0,0 +1,66 @@ +--- +applyTo: '**/*' +description: 'Guidelines for avoiding shorthand and abbreviations in all code and documentation.' +--- + +# Shorthand Guidelines + +## Avoid Shorthand and Abbreviations + +To maximize clarity, maintainability, and consistency across all code and documentation, always +use full, descriptive words instead of shorthand or abbreviations. + +- **Do not use**: `Params`, `Props`, `Config`, `Info`, `Temp`, `Env`, `Obj`, `Val`, `Ref`, + `Err`, `Msg`, etc. +- **Do use**: `Parameters`, `Properties`, `Configuration`, `Information`, `Temporary`, + `Environment`, `Object`, `Value`, `Reference`, `Error`, `Message`, etc. + +### Rationale + +- Shorthand and abbreviations can be ambiguous and reduce code readability. +- Full words make intent clear for all contributors and AI agents. +- Consistent naming improves searchability and onboarding for new team members. + +### Examples + +| Avoid | Prefer | +| ------ | ---------------------------- | +| Params | Parameters | +| Props | Properties | +| Config | Configuration | +| Info | Information | +| Temp | Temporary | +| Env | Environment | +| Obj | Object | +| Val | Value | +| Ref | Reference | +| Err | Error | +| Msg | Message | +| Conn | Connection / Connections | +| Dir | Directory | +| Cmd | Command | +| Svc | Service | +| Cfg | Configuration | +| Tmp | Temporary | +| Usr | User | +| Grp | Group | +| Ctx | Context | +| Auth | Authentication / Authorize | +| Util | Utility / Utilities | +| Init | Initialize / Initialization | +| Req | Request / Requirement | +| Resp | Response | +| ObjRef | Object Reference | +| Num | Number | + +### Additional Guidance + +- Never use abbreviations in parameter, property, or variable names unless they are + industry-standard and unambiguous (e.g., `ID`, `URL`). +- Use the singular or plural form of a word as appropriate for the context (e.g., use + `Connection` for a single item, `Connections` for collections or lists). +- If a project already uses a specific abbreviation as a standard, document it clearly in the + relevant instruction file. +- If new abbreviations are introduced in the future, document them here and avoid their use + unless absolutely necessary and unambiguous. +- This rule applies to all code, documentation, commit messages, and user-facing text. diff --git a/instructions/testing.instructions.md b/instructions/testing.instructions.md new file mode 100644 index 0000000..4753984 --- /dev/null +++ b/instructions/testing.instructions.md @@ -0,0 +1,339 @@ +--- +applyTo: '**/*' +description: 'Test writing best practices and conventions' +--- + +# Testing Instructions + +Language-agnostic guidelines for writing effective tests. + +## Discovering Existing Test Tooling + +Before creating scripts for test-related tasks (running tests, gathering coverage, generating reports): + +1. **Check for build systems** - Look for `Makefile`, `build.ps1`, `package.json` scripts, `tox.ini`, + `pyproject.toml`, or similar build configuration files +2. **Search README and CI configs** - Existing commands are often documented or visible in CI workflows +3. **Ask the user** - If unsure whether tooling exists, ask before creating anything new + +**Never create new scripts when existing build tooling already handles the task.** + +## Test Structure + +### Arrange-Act-Assert (AAA) + +Structure each test in three clear sections: + +```javascript +// Arrange - Set up test data and preconditions +// Act - Execute the code being tested +// Assert - Verify the expected outcome +``` + +**Example:** + +```javascript +// Arrange +user = createTestUser(name: "Alice", role: "admin") + +// Act +result = user.hasPermission("delete") + +// Assert +expect(result).toBe(true) +``` + +### Given-When-Then (BDD Style) + +Alternative structure for behavior-focused tests: + +```javascript +// Given - Initial context +// When - Action occurs +// Then - Expected outcome +``` + +## Naming Conventions + +### Test Names Should Describe Behavior + +**Pattern:** `__` + +**Good examples:** + +```text +calculateTotal_withEmptyCart_returnsZero +userLogin_withInvalidPassword_throwsAuthError +emailValidator_withValidEmail_returnsTrue +``` + +**Avoid:** + +```text +test1 +testCalculate +itWorks +``` + +### Test File Naming + +Place test files alongside source files or in a dedicated test directory: + +```text +src/ + calculator.js + calculator.test.js # Adjacent to source + +tests/ + calculator.test.js # Or in test directory +``` + +Common extensions: + +- `.test.js`, `.test.ts` +- `.spec.js`, `.spec.ts` +- `_test.go` +- `Test.cs` +- `.Tests.ps1` + +## Test Types + +### Unit Tests + +- Test individual functions or methods in isolation +- Mock external dependencies +- Fast execution (milliseconds) +- High coverage of edge cases + +### Integration Tests + +- Test interaction between components +- May use real databases or services +- Slower than unit tests +- Focus on component boundaries + +### End-to-End Tests + +- Test complete user workflows +- Use real browser/UI automation +- Slowest to execute +- Cover critical user paths + +## Best Practices + +### One Assertion Per Concept + +Each test should verify one logical concept: + +**Good:** + +```text +test_addItem_increasesCartCount +test_addItem_updatesCartTotal +``` + +**Avoid:** + +```text +test_addItem_doesEverything // Tests multiple things +``` + +### Test Independence + +- Each test should run independently +- Don't rely on test execution order +- Clean up test data after each test +- Use fresh fixtures for each test + +### Avoid Test Interdependence + +**Bad:** + +```javascript +test1_createUser() // Creates user +test2_loginUser() // Assumes user exists from test1 +``` + +**Good:** + +```javascript +test_loginUser() { + user = createTestUser() // Each test creates its own data + // ... test logic +} +``` + +### Use Descriptive Assertions + +**Good:** + +```javascript +expect(user.isActive).toBe(true) +expect(result).toContain("success") +expect(list).toHaveLength(3) +``` + +**Avoid:** + +```javascript +expect(x).toBe(true) // What is x? +assert(result) // What should result be? +``` + +## Test Data + +### Use Meaningful Test Data + +**Good:** + +```javascript +email = "valid.user@example.com" +invalidEmail = "not-an-email" +``` + +**Avoid:** + +```javascript +email = "test" +x = "asdf" +``` + +### Use Factories or Builders + +Create helper functions for test data: + +```javascript +function createTestUser(overrides = {}) { + return { + id: generateId(), + name: "Test User", + email: "test@example.com", + role: "user", + ...overrides + } +} + +// Usage +adminUser = createTestUser({ role: "admin" }) +``` + +### Edge Cases to Consider + +- Empty inputs (null, undefined, empty string, empty array) +- Boundary values (0, -1, max int, min int) +- Invalid inputs (wrong type, malformed data) +- Large inputs (performance edge cases) +- Special characters and unicode +- Concurrent access (race conditions) + +## Mocking and Stubbing + +### When to Mock + +- External services (APIs, databases) +- Time-dependent operations +- Random number generation +- File system operations +- Network requests + +### When Not to Mock + +- Simple value objects +- Pure functions with no side effects +- The code you're actually testing + +### Mock Guidelines + +- Only mock what you need +- Verify mock interactions when behavior matters +- Reset mocks between tests +- Prefer dependency injection for easier mocking + +## Test Coverage + +### Focus on Critical Paths + +Prioritize testing: + +1. Business-critical functionality +2. Error handling and edge cases +3. Security-sensitive code +4. Complex algorithms + +### Coverage Goals + +- Aim for meaningful coverage, not 100% +- High coverage doesn't guarantee quality +- Focus on testing behavior, not implementation details + +## Bug Fix Testing + +### Test-First Bug Fixing + +When fixing a bug, always follow this workflow: + +1. **Write a failing test first** - Create at least one test that reproduces the bug +2. **Verify the test fails** - Confirm the test fails for the expected reason +3. **Fix the bug** - Implement the minimal fix to make the test pass +4. **Verify all tests pass** - Ensure both the new test and existing tests pass + +**Example workflow:** + +```text +# 1. Create test that exposes the bug +test_calculateDiscount_withZeroQuantity_returnsZero() + # This test fails because of the bug + +# 2. Run tests - confirm failure +> npm test +FAIL: calculateDiscount returns NaN instead of 0 + +# 3. Fix the bug in the source code + +# 4. Run tests - confirm fix +> npm test +PASS: All tests passing +``` + +### Why Test-First Matters + +- **Proves the bug exists** - The failing test documents the exact issue +- **Prevents regressions** - The test ensures the bug won't return +- **Validates the fix** - You know the fix works when the test passes +- **Documents behavior** - Future developers understand the expected behavior + +### Bug Test Naming + +Name bug-related tests to indicate the scenario being fixed: + +```text +calculateTotal_withNullItems_returnsZeroInsteadOfCrashing +parseDate_withLeapYear_handlesFebruary29Correctly +userAuth_withExpiredToken_returnsUnauthorizedNotServerError +``` + +## Running Tests + +### Before Committing + +- Run related tests locally +- Ensure all tests pass +- Add tests for new functionality +- Update tests for changed behavior + +### Continuous Integration + +- Tests should run on every PR +- Failed tests should block merging +- Keep test suite fast (parallelize when possible) + +## Anti-Patterns to Avoid + +| Anti-Pattern | Problem | Solution | +| ----------------------- | ------------------ | ----------------------------- | +| Testing implementation | Brittle tests | Test behavior/outcomes | +| Flaky tests | Unreliable CI | Fix timing/ordering issues | +| Slow tests | Developer friction | Optimize or parallelize | +| No assertions | False confidence | Always verify outcomes | +| Commented-out tests | Hidden failures | Delete or fix tests | +| Test data in production | Security risk | Use separate test environment | diff --git a/instructions/update.instructions.md b/instructions/update.instructions.md new file mode 100644 index 0000000..623ed3c --- /dev/null +++ b/instructions/update.instructions.md @@ -0,0 +1,193 @@ +--- +applyTo: '**/*' +description: 'Procedures for updating AI agent instructions from the centralized repository' +--- + +# Update Instructions for AI Agents + +These instructions are self-contained for update procedures but assume familiarity with Git. +For general workflow guidance, see agent-workflow.instructions.md. + +## Configuration Schema + +Repositories control AIM behavior through `aim.config.json` in the repository root: + +```json +{ + "version": "latest", + "modules": { + "include": ["agent-workflow", "powershell", "markdown"], + "exclude": [] + }, + "externalSources": { + "enabled": true, + "repositories": [ + { + "name": "awesome-copilot", + "url": "https://github.com/github/awesome-copilot", + "path": "instructions", + "description": "Community-contributed instructions from GitHub" + } + ] + } +} +``` + +**Configuration fields:** + +- `version` - Target AIM version: `"latest"` or specific version (e.g., `"0.8.0"`) +- `modules.include` - List of modules to include (without `.instructions.md` extension) +- `modules.exclude` - List of modules to exclude (takes precedence over include) +- `externalSources.enabled` - Enable fetching from external repositories +- `externalSources.repositories` - List of external instruction sources + +## Update Procedure + +When updating AI agent instructions in a repository that uses AIM, AI agents should: + +### 1. Read Configuration + +- Check if `aim.config.json` exists in the repository root +- If it exists, read all configuration fields +- If it doesn't exist, use defaults: version=latest, all modules, externalSources disabled + +### 2. Clone the Centralized Repository + +- Clone: `git clone https://github.com/tablackburn/ai-agent-instruction-modules.git` +- If targeting a specific version (not "latest"), checkout that tag: `git checkout v0.8.0` +- Use `AGENTS.template.md` from the cloned repository, NOT `AGENTS.md` +- The file `AGENTS.md` in the centralized repository is that repository's own implementation +- The file `AGENTS.template.md` is the template for downstream repositories + +### 3. Summarize Changes + +- Read the current version from the downstream repository's `AGENTS.md` header + (e.g., "Template Version: 0.7.0") +- Read `CHANGELOG.md` from the cloned upstream repository +- Extract all version sections between the current version and the target version +- Provide the user with a brief summary of what has changed, noting any breaking changes +- If the current version equals the target version, inform the user they are already up to date + +### 4. Determine Modules to Sync + +Based on `aim.config.json`: + +- If `modules.include` is specified, only sync those modules +- If `modules.exclude` is specified, exclude those from the sync +- Core modules (`agent-workflow`, `update`) should always be included unless explicitly excluded +- `repository-specific.instructions.md` is NEVER copied from upstream + +### 5. Sync Instruction Files + +For each instruction file in the upstream `instruction-templates/` folder: + +1. Check if the module should be synced based on configuration +2. Check if the file already exists in the downstream `instructions/` folder +3. **If the file exists, ask the user:** + - "File X already exists. Overwrite with upstream version? (yes/no/diff)" + - If "diff", show the differences between local and upstream versions + - Only overwrite if the user confirms +4. **If the file is new**, copy it without prompting + +### 6. Handle External Sources + +If `externalSources.enabled` is true and a needed language/framework instruction is not found in +AIM: + +1. Check each configured external repository in order +2. For awesome-copilot, look in the `instructions/` path for matching `.instructions.md` files +3. Download the instruction file and copy to the downstream `instructions/` folder +4. Inform the user which files were fetched from external sources + +**Example external fetch:** + +```text +Fetching python.instructions.md from github/awesome-copilot... +Fetching react.instructions.md from github/awesome-copilot... +``` + +### 7. Update AGENTS.md + +- Replace the HTML comment block at the top (the comment starting with `