From 396a3792c8cbed79887338c17d0808f028bf6df7 Mon Sep 17 00:00:00 2001 From: Alessandro Giorgetti Date: Wed, 25 Feb 2026 11:15:10 +0100 Subject: [PATCH] Add GitHub Copilot and ai agents support - Introduced `cleanup-worktree.sh` for removing completed or abandoned Git worktrees, with options to delete branches and remote branches. - Added `quick-worktree.sh` for setting up new worktrees with automatic guardrails configuration. - Created `verify-guardrails.sh` to ensure proper guardrail configurations in current worktrees. - Added `ArchitectReviewer` agent for validating architectural patterns and multi-framework compatibility. - Introduced `PackagePrepper` agent for managing the release pipeline, including versioning and changelog management. - Created `TestWrangler` agent for test creation, execution, and coverage analysis in MSTest projects. - Added comprehensive instructions in `copilot-instructions.md` for project setup and development guidelines. - Established a `CONTRIBUTING.md` file to guide contributors on project structure, code conventions, and testing procedures. --- .agents/skills/git-worktree-ops/SKILL.md | 1199 +++++++++++++++++ .../git-worktree-ops/cleanup-worktree.sh | 112 ++ .../skills/git-worktree-ops/quick-worktree.sh | 74 + .../git-worktree-ops/verify-guardrails.sh | 113 ++ .github/agents/architectreviewer.agent.md | 165 +++ .github/agents/packageprepper.agent.md | 189 +++ .github/agents/testwrangler.agent.md | 129 ++ .github/copilot-instructions.md | 207 +++ CONTRIBUTING.md | 103 ++ .../.copilot-codeGeneration-instructions.md | 1 - src/.vscode/settings.json | 9 - 11 files changed, 2291 insertions(+), 10 deletions(-) create mode 100644 .agents/skills/git-worktree-ops/SKILL.md create mode 100644 .agents/skills/git-worktree-ops/cleanup-worktree.sh create mode 100644 .agents/skills/git-worktree-ops/quick-worktree.sh create mode 100644 .agents/skills/git-worktree-ops/verify-guardrails.sh create mode 100644 .github/agents/architectreviewer.agent.md create mode 100644 .github/agents/packageprepper.agent.md create mode 100644 .github/agents/testwrangler.agent.md create mode 100644 .github/copilot-instructions.md create mode 100644 CONTRIBUTING.md delete mode 100644 src/.vscode/.copilot-codeGeneration-instructions.md delete mode 100644 src/.vscode/settings.json diff --git a/.agents/skills/git-worktree-ops/SKILL.md b/.agents/skills/git-worktree-ops/SKILL.md new file mode 100644 index 0000000..1f36b7c --- /dev/null +++ b/.agents/skills/git-worktree-ops/SKILL.md @@ -0,0 +1,1199 @@ +--- +name: git-worktree-ops +description: Expert guidance for Git worktree operations, safe branching, and multi-agent workflow management. Use for creating/removing worktrees, managing branches, troubleshooting conflicts, and ensuring guardrails compliance. Also covers standard Git operations like committing, merging, rebasing, stashing, and conflict resolution. +--- + +# Git Worktree Operations + +Expert skill for safe Git operations in multi-agent worktree environments and standard Git workflows. + +## When to Use This Skill + +**Worktree Operations**: +- Creating or removing Git worktrees +- Managing branches across multiple worktrees +- Troubleshooting worktree-related issues +- Verifying guardrails are properly configured +- Cleaning up stale worktrees +- Understanding git worktree metadata + +**Standard Git Operations**: +- Creating, switching, and managing branches +- Committing and staging changes +- Merging and rebasing branches +- Resolving conflicts +- Working with remote repositories +- Viewing history and diffs +- Undoing changes safely + +## Core Worktree Commands + +### Create Worktree + +**Basic pattern**: +```bash +git worktree add -b +``` + +**Examples**: +```bash +# Create worktree for Codex task +git worktree add -b feat/codex-fix-auth ../myapp-worktrees/codex-fix-auth develop + +# Create worktree from current branch +git worktree add -b feat/new-feature ../myapp-worktrees/new-feature HEAD + +# Create worktree without new branch (checkout existing) +git worktree add ../myapp-worktrees/existing-work feat/existing-branch +``` + +**Naming conventions** (for this project): +- Branch: `feat/-` (e.g., `feat/codex-fix-auth`) +- Worktree path: `-` (matches branch without `feat/`) + +### List Worktrees + +```bash +# Show all worktrees +git worktree list + +# Verbose output with branch and commit info +git worktree list --verbose + +# Porcelain format for scripting +git worktree list --porcelain +``` + +### Remove Worktree + +```bash +# Safe removal (must be clean) +git worktree remove + +# Force removal (even if dirty) +git worktree remove --force + +# Remove worktree and delete branch +git worktree remove +git branch -D +``` + +### Prune Stale Metadata + +```bash +# Clean up metadata for deleted worktree directories +git worktree prune + +# Dry run to see what would be pruned +git worktree prune --dry-run + +# Verbose output +git worktree prune --verbose +``` + +## Guardrails Configuration + +### Set Up Branch/Worktree Binding + +**Required before starting any agent** in a worktree: + +```bash +# Navigate to worktree +cd ../myapp-worktrees/codex-fix-auth + +# Verify current branch and location +git branch --show-current +git rev-parse --show-toplevel + +# Set metadata for hooks +GIT_DIR="$(git rev-parse --git-dir)" +BRANCH="feat/codex-fix-auth" +WORKTREE="$(pwd -P)" + +printf '%s\n' "$BRANCH" > "$GIT_DIR/agent-expected-branch" +printf '%s\n' "$WORKTREE" > "$GIT_DIR/agent-expected-worktree" + +# Verify metadata was written +cat "$GIT_DIR/agent-expected-branch" +cat "$GIT_DIR/agent-expected-worktree" +``` + +### Verify Guardrails Active + +```bash +# Check if pre-commit hook exists and is executable +test -x "$(git rev-parse --git-path hooks/pre-commit)" && echo "pre-commit: ✓" || echo "pre-commit: ✗" + +# Check if pre-push hook exists and is executable +test -x "$(git rev-parse --git-path hooks/pre-push)" && echo "pre-push: ✓" || echo "pre-push: ✗" + +# Check metadata files exist +test -f "$(git rev-parse --git-dir)/agent-expected-branch" && echo "branch binding: ✓" || echo "branch binding: ✗" +test -f "$(git rev-parse --git-dir)/agent-expected-worktree" && echo "worktree binding: ✓" || echo "worktree binding: ✗" + +# View hook dispatcher (if installed) +cat "$(git rev-parse --git-path hooks/pre-commit)" +``` + +## Safe Branch Operations + +### Allowed Operations + +```bash +# Safe: Rebase current branch onto base +git fetch origin +git rebase origin/develop + +# Safe: Merge base into current branch +git fetch origin +git merge origin/develop + +# Safe: Push to assigned branch (fast-forward) +git push origin feat/codex-fix-auth + +# Safe: Pull with fast-forward only +git pull --ff-only + +# Safe: Create commits on assigned branch +git add . +git commit -m "feat: implement authentication retry logic" +``` + +### Forbidden Operations + +```bash +# FORBIDDEN: Rebase another agent's branch +git rebase feat/claude-add-metrics # ✗ Never do this + +# FORBIDDEN: Force push +git push --force origin feat/codex-fix-auth # ✗ Blocked by hooks +git push --force-with-lease origin feat/codex-fix-auth # ✗ Only with explicit approval + +# FORBIDDEN: Push to different branch +git push origin feat/codex-fix-auth:develop # ✗ Blocked by hooks + +# FORBIDDEN: Delete branch via push +git push origin :feat/codex-fix-auth # ✗ Blocked by hooks +git push origin --delete feat/codex-fix-auth # ✗ Blocked by hooks + +# FORBIDDEN: Commit on wrong branch +# Hooks will block if current branch != agent-expected-branch +``` + +## Conflict Resolution + +### When Two Agents Touch Same Files + +**Strategy**: Merge one branch first, then rebase the second. + +```bash +# Step 1: Human reviews and merges first agent branch +cd ~/src/myapp +git checkout develop +git pull --ff-only +git merge --no-ff feat/codex-fix-auth +git push origin develop + +# Step 2: Update second agent branch +cd ../myapp-worktrees/claude-add-metrics +git fetch origin +git rebase origin/develop + +# Step 3: Resolve conflicts manually +# (Edit conflicted files) +git add . +git rebase --continue + +# Step 4: Re-run validation +npm test # or appropriate test command + +# Step 5: Human reviews and merges second branch +cd ~/src/myapp +git checkout develop +git pull --ff-only +git merge --no-ff feat/claude-add-metrics +git push origin develop +``` + +**Important**: Never ask agents to auto-resolve conflicts between agent branches without human oversight. + +### Abort Rebase if Needed + +```bash +# Cancel rebase and return to pre-rebase state +git rebase --abort + +# Check what caused the issue +git status +git log --oneline --graph --all --decorate -10 +``` + +## Standard Git Branch Operations + +For teams not using worktrees or for single-developer scenarios, these standard Git operations provide safe workflows. + +### Branch Management + +**Create and switch to new branch**: +```bash +# Create branch from current HEAD +git checkout -b feat/new-feature + +# Create branch from specific base +git checkout -b feat/new-feature develop + +# Modern syntax (Git 2.23+) +git switch -c feat/new-feature +git switch -c feat/new-feature develop +``` + +**Switch between branches**: +```bash +# Switch to existing branch +git checkout develop +git switch develop # Modern syntax + +# Switch to previous branch +git checkout - +git switch - + +# Switch and discard local changes (dangerous!) +git checkout -f develop +``` + +**List branches**: +```bash +# List local branches +git branch +git branch -v # With last commit info +git branch -vv # With upstream tracking info + +# List all branches (local + remote) +git branch -a +git branch -avv + +# List remote branches only +git branch -r + +# List merged branches +git branch --merged +git branch --no-merged + +# Search for branches +git branch --list '*fix*' +git branch -a --list '*feature*' +``` + +**Delete branches**: +```bash +# Delete merged branch (safe) +git branch -d feat/completed-feature + +# Force delete unmerged branch +git branch -D feat/abandoned-feature + +# Delete remote branch +git push origin --delete feat/old-feature +git push origin :feat/old-feature # Older syntax + +# Prune deleted remote branches from local +git fetch --prune +``` + +**Rename branch**: +```bash +# Rename current branch +git branch -m new-name + +# Rename specific branch +git branch -m old-name new-name + +# Update remote after rename +git push origin :old-name new-name +git push origin -u new-name +``` + +### Staging and Committing + +**Stage changes**: +```bash +# Stage specific files +git add file1.js file2.js + +# Stage all changes in directory +git add src/ + +# Stage all changes (tracked and untracked) +git add . +git add --all + +# Stage only tracked files +git add -u + +# Interactive staging +git add -p # Patch mode - stage hunks interactively +git add -i # Interactive mode + +# Stage parts of a file +git add -p file.js +``` + +**Unstage changes**: +```bash +# Unstage file (keep changes) +git restore --staged file.js # Modern +git reset HEAD file.js # Classic + +# Unstage all +git restore --staged . +git reset HEAD +``` + +**Commit changes**: +```bash +# Basic commit +git commit -m "feat: add user authentication" + +# Commit with detailed message +git commit # Opens editor + +# Stage all tracked files and commit +git commit -am "fix: resolve login timeout" + +# Amend last commit (add changes or fix message) +git commit --amend +git commit --amend -m "Updated commit message" + +# Commit with specific author +git commit --author="Name " -m "Message" + +# Empty commit (for triggering CI) +git commit --allow-empty -m "Trigger CI" +``` + +**Conventional commit format**: +```bash +git commit -m "feat: add new feature" # New feature +git commit -m "fix: resolve bug" # Bug fix +git commit -m "docs: update README" # Documentation +git commit -m "style: format code" # Formatting +git commit -m "refactor: restructure" # Code restructure +git commit -m "test: add tests" # Add tests +git commit -m "chore: update deps" # Maintenance +``` + +### Viewing Changes and History + +**Status and diffs**: +```bash +# Show working directory status +git status +git status -s # Short format +git status -sb # Short with branch info + +# Show unstaged changes +git diff + +# Show staged changes +git diff --staged +git diff --cached + +# Show changes in specific file +git diff file.js +git diff --staged file.js + +# Compare branches +git diff develop..feat/new-feature +git diff develop...feat/new-feature # Since common ancestor + +# Word-level diff +git diff --word-diff + +# Statistics only +git diff --stat +git diff --shortstat +``` + +**View history**: +```bash +# Show commit history +git log +git log --oneline +git log --oneline --graph --all --decorate + +# Show last N commits +git log -5 +git log --oneline -10 + +# Show commits by author +git log --author="John" + +# Show commits in date range +git log --since="2 weeks ago" +git log --after="2024-01-01" --before="2024-02-01" + +# Show commits affecting specific file +git log -- file.js +git log -p -- file.js # With diffs + +# Search commit messages +git log --grep="fix" +git log --grep="auth" --grep="login" --all-match + +# Show commits with specific changes +git log -S "function name" # Pickaxe search +git log -G "regex pattern" + +# Pretty formats +git log --pretty=format:"%h - %an, %ar : %s" +git log --graph --pretty=format:"%C(yellow)%h%Creset %C(blue)%an%Creset %s" +``` + +**Show specific commit**: +```bash +# Show commit details +git show +git show HEAD +git show HEAD~1 # Previous commit +git show HEAD~3 # 3 commits ago + +# Show file at specific commit +git show :path/to/file.js + +# Show commit stats only +git show --stat +``` + +### Merging + +**Fast-forward merge**: +```bash +# Merge feature into current branch (fast-forward if possible) +git merge feat/new-feature + +# Force fast-forward only (fail if not possible) +git merge --ff-only feat/new-feature +``` + +**No fast-forward merge** (creates merge commit): +```bash +# Always create merge commit +git merge --no-ff feat/new-feature + +# With custom message +git merge --no-ff -m "Merge feature X" feat/new-feature +``` + +**Squash merge** (combine all commits): +```bash +# Squash all commits into one +git merge --squash feat/new-feature +git commit -m "Add feature X" +``` + +**Abort merge**: +```bash +# Cancel merge in progress +git merge --abort + +# Reset to before merge +git reset --hard HEAD +``` + +### Rebasing + +**Interactive rebase**: +```bash +# Rebase last 3 commits +git rebase -i HEAD~3 + +# Rebase onto another branch +git rebase develop +git rebase -i develop + +# In the editor, you can: +# - pick: use commit as-is +# - reword: change commit message +# - edit: stop to amend commit +# - squash: combine with previous commit +# - fixup: like squash but discard message +# - drop: remove commit +``` + +**Continue/abort rebase**: +```bash +# After resolving conflicts +git add . +git rebase --continue + +# Skip current commit +git rebase --skip + +# Abort rebase +git rebase --abort +``` + +**Rebase vs Merge**: +```bash +# Rebase: linear history, no merge commits +git rebase develop + +# Merge: preserves history, creates merge commit +git merge develop +``` + +### Conflict Resolution + +**When conflicts occur**: +```bash +# 1. See conflicted files +git status + +# 2. View conflict in file +cat file.js +# <<<<<<< HEAD +# Your changes +# ======= +# Their changes +# >>>>>>> branch-name + +# 3. Edit file to resolve +vim file.js + +# 4. Mark as resolved +git add file.js + +# 5. Complete merge/rebase +git commit # For merge +git rebase --continue # For rebase +``` + +**Conflict resolution tools**: +```bash +# Use mergetool +git mergetool + +# Accept theirs for all conflicts +git checkout --theirs . +git add . + +# Accept ours for all conflicts +git checkout --ours . +git add . + +# Accept theirs for specific file +git checkout --theirs path/to/file.js +git add path/to/file.js +``` + +**View conflict diff**: +```bash +# Show both sides of conflict +git diff + +# Show only conflicted files +git diff --name-only --diff-filter=U + +# Show detailed conflict info +git log --merge -p +``` + +### Undoing Changes + +**Discard uncommitted changes**: +```bash +# Discard changes in specific file +git restore file.js # Modern +git checkout -- file.js # Classic + +# Discard all unstaged changes +git restore . +git checkout -- . + +# Discard staged and unstaged changes +git restore --staged --worktree . +git reset --hard HEAD +``` + +**Undo commits**: +```bash +# Undo last commit, keep changes staged +git reset --soft HEAD~1 + +# Undo last commit, keep changes unstaged +git reset HEAD~1 +git reset --mixed HEAD~1 # Default + +# Undo last commit, discard changes +git reset --hard HEAD~1 + +# Undo multiple commits +git reset --hard HEAD~3 + +# Undo to specific commit +git reset --hard +``` + +**Revert commits** (safe for shared branches): +```bash +# Create new commit that undoes changes +git revert + +# Revert last commit +git revert HEAD + +# Revert multiple commits +git revert HEAD~3..HEAD + +# Revert without committing +git revert -n +git revert --no-commit +``` + +**Recovery**: +```bash +# View reflog (history of HEAD) +git reflog + +# Recover lost commit +git reflog +git reset --hard + +# Recover deleted branch +git reflog +git checkout -b recovered-branch + +# Find dangling commits +git fsck --lost-found +``` + +### Remote Operations + +**Fetch updates**: +```bash +# Fetch all remotes +git fetch --all + +# Fetch specific remote +git fetch origin + +# Fetch and prune deleted branches +git fetch --all --prune + +# Fetch specific branch +git fetch origin develop +``` + +**Pull changes**: +```bash +# Pull with default strategy +git pull + +# Pull with fast-forward only (safe) +git pull --ff-only + +# Pull with rebase +git pull --rebase + +# Pull specific branch +git pull origin develop +``` + +**Push changes**: +```bash +# Push current branch to upstream +git push + +# Push and set upstream +git push -u origin feat/new-feature +git push --set-upstream origin feat/new-feature + +# Push specific branch +git push origin feat/new-feature + +# Push all branches +git push --all origin + +# Push tags +git push --tags + +# Force push (dangerous!) +git push --force origin feat/new-feature + +# Force push with lease (safer) +git push --force-with-lease origin feat/new-feature +``` + +**Remote management**: +```bash +# List remotes +git remote +git remote -v + +# Add remote +git remote add origin https://github.com/user/repo.git + +# Change remote URL +git remote set-url origin https://github.com/user/new-repo.git + +# Remove remote +git remote remove origin + +# Rename remote +git remote rename origin upstream + +# Show remote info +git remote show origin +``` + +### Stashing + +**Save work temporarily**: +```bash +# Stash current changes +git stash +git stash save "Work in progress on feature X" + +# Stash including untracked files +git stash -u +git stash --include-untracked + +# Stash including untracked and ignored files +git stash -a +git stash --all + +# Stash only unstaged changes +git stash --keep-index +``` + +**Apply stashed changes**: +```bash +# List stashes +git stash list + +# Apply most recent stash (keep in stash list) +git stash apply + +# Apply specific stash +git stash apply stash@{2} + +# Apply and remove from stash list +git stash pop + +# Apply to different branch +git stash branch new-branch stash@{0} +``` + +**Manage stashes**: +```bash +# Show stash contents +git stash show +git stash show -p # With diff + +# Show specific stash +git stash show stash@{1} + +# Drop specific stash +git stash drop stash@{0} + +# Clear all stashes +git stash clear +``` + +### Tagging + +**Create tags**: +```bash +# Lightweight tag +git tag v1.0.0 + +# Annotated tag (recommended) +git tag -a v1.0.0 -m "Release version 1.0.0" + +# Tag specific commit +git tag -a v1.0.0 -m "Message" +``` + +**List and show tags**: +```bash +# List all tags +git tag +git tag -l +git tag --list + +# Search tags +git tag -l "v1.*" + +# Show tag details +git show v1.0.0 +``` + +**Push and delete tags**: +```bash +# Push specific tag +git push origin v1.0.0 + +# Push all tags +git push --tags + +# Delete local tag +git tag -d v1.0.0 + +# Delete remote tag +git push origin --delete v1.0.0 +git push origin :refs/tags/v1.0.0 +``` + +### Common Workflows Without Worktrees + +**Feature branch workflow**: +```bash +# 1. Update main branch +git checkout main +git pull --ff-only + +# 2. Create feature branch +git checkout -b feat/new-feature + +# 3. Work on feature +git add . +git commit -m "feat: implement X" + +# 4. Keep feature branch updated +git fetch origin +git rebase origin/main + +# 5. Push feature branch +git push -u origin feat/new-feature + +# 6. After code review - merge +git checkout main +git pull --ff-only +git merge --no-ff feat/new-feature +git push origin main + +# 7. Cleanup +git branch -d feat/new-feature +git push origin --delete feat/new-feature +``` + +**Hotfix workflow**: +```bash +# 1. Create hotfix from main +git checkout main +git pull --ff-only +git checkout -b hotfix/critical-bug + +# 2. Fix and commit +git add . +git commit -m "fix: resolve critical bug" + +# 3. Merge to main +git checkout main +git merge --no-ff hotfix/critical-bug +git tag -a v1.0.1 -m "Hotfix release" +git push origin main --tags + +# 4. Merge to develop (if exists) +git checkout develop +git merge --no-ff hotfix/critical-bug +git push origin develop + +# 5. Cleanup +git branch -d hotfix/critical-bug +``` + +**Bisect for debugging**: +```bash +# Find commit that introduced bug +git bisect start +git bisect bad # Current commit is bad +git bisect good v1.0.0 # This commit was good + +# Git checks out commit to test +# Test the code, then: +git bisect good # or git bisect bad + +# Repeat until Git finds the culprit +# When done: +git bisect reset +``` + +## Troubleshooting + +### Worktree Path Issues + +**Problem**: "fatal: '' already exists" + +```bash +# Check if worktree is registered +git worktree list + +# If stale, prune and retry +git worktree prune +rm -rf # if directory still exists +git worktree add -b +``` + +**Problem**: "fatal: '' is not a working tree" + +```bash +# Remove stale registration +git worktree prune + +# Manually remove if needed +rm -rf +``` + +### Branch Already Exists + +**Problem**: "fatal: A branch named 'feat/task' already exists" + +```bash +# Check if branch exists and where +git branch -a | grep feat/task + +# If you want to reuse existing branch +git worktree add feat/task + +# If you want to delete old branch and start fresh +git branch -D feat/task +git worktree add -b feat/task +``` + +### Lock Files + +**Problem**: "fatal: 'worktrees/' is locked" + +```bash +# Check lock status +cat .git/worktrees//locked + +# Remove lock (if safe) +rm .git/worktrees//locked + +# Or use prune to clean +git worktree prune +``` + +### Hook Not Blocking Wrong Branch + +**Problem**: Able to commit on wrong branch despite hooks + +```bash +# Verify hooks are executable +HOOK_PATH="$(git rev-parse --git-path hooks/pre-commit)" +ls -la "$HOOK_PATH" +chmod +x "$HOOK_PATH" + +# Check metadata files exist +GIT_DIR="$(git rev-parse --git-dir)" +cat "$GIT_DIR/agent-expected-branch" # Should show expected branch +cat "$GIT_DIR/agent-expected-worktree" # Should show current worktree path + +# Reinstall guardrails if needed +cd /path/to/AgentStackGuide +./scripts/setup-agent-guardrails.sh --target /path/to/your-repo --guardrails on --force +``` + +## Common Workflows + +### Full Multi-Agent Setup + +```bash +# 1. Fetch latest +git fetch --all --prune + +# 2. Create worktrees directory +mkdir -p ../myapp-worktrees + +# 3. Create worktrees for three agents +git worktree add -b feat/codex-fix-auth ../myapp-worktrees/codex-fix-auth develop +git worktree add -b feat/claude-add-metrics ../myapp-worktrees/claude-add-metrics develop +git worktree add -b feat/copilot-docs ../myapp-worktrees/copilot-docs develop + +# 4. Configure each worktree (repeat for each) +cd ../myapp-worktrees/codex-fix-auth +GIT_DIR="$(git rev-parse --git-dir)" +printf '%s\n' "feat/codex-fix-auth" > "$GIT_DIR/agent-expected-branch" +printf '%s\n' "$(pwd -P)" > "$GIT_DIR/agent-expected-worktree" + +# 5. Verify setup +git worktree list +``` + +### Clean Merge and Cleanup + +```bash +# 1. Review changes +git log --oneline develop..feat/codex-fix-auth +git diff --stat develop..feat/codex-fix-auth + +# 2. Merge to develop +cd ~/src/myapp +git checkout develop +git pull --ff-only +git merge --no-ff feat/codex-fix-auth +git push origin develop + +# 3. Clean up worktree +git worktree remove ../myapp-worktrees/codex-fix-auth +git branch -d feat/codex-fix-auth # -d ensures branch was merged + +# 4. Prune metadata +git worktree prune +``` + +### Discard Failed Branch + +```bash +# 1. Remove worktree +cd ~/src/myapp +git worktree remove ../myapp-worktrees/claude-add-metrics +# or force if needed: +git worktree remove --force ../myapp-worktrees/claude-add-metrics + +# 2. Delete branch (use -D to force) +git branch -D feat/claude-add-metrics + +# 3. Delete remote branch if pushed +git push origin --delete feat/claude-add-metrics + +# 4. Clean up metadata +git worktree prune +``` + +## Git Configuration for Safety + +### Per-Worktree Settings + +```bash +# In each worktree, configure safe defaults +cd + +# Only push current branch (not all matching branches) +git config --local push.default current + +# Require fast-forward for pulls +git config --local pull.ff only + +# Prevent accidental push of all branches +git config --local remote.pushDefault origin +``` + +### Useful Aliases + +```bash +# Global aliases for worktree operations +git config --global alias.wt "worktree" +git config --global alias.wtl "worktree list" +git config --global alias.wta "worktree add" +git config --global alias.wtr "worktree remove" +git config --global alias.wtp "worktree prune" + +# Branch visualization +git config --global alias.br "branch -vv" +git config --global alias.bra "branch -avv" + +# Safer operations +git config --global alias.pullff "pull --ff-only" +``` + +## Advanced Operations + +### Move Worktree + +```bash +# Option 1: Remove and recreate +git worktree remove +git worktree add + +# Option 2: Move directory and update metadata +mv +git worktree list # Will show "(error)" for old path +git worktree prune +git worktree repair +``` + +### Repair Worktree + +```bash +# Fix broken worktree metadata +git worktree repair + +# Repair specific worktree +git worktree repair +``` + +### Lock Worktree + +```bash +# Prevent accidental removal +git worktree lock + +# Lock with reason +git worktree lock --reason "Agent currently working" + +# Unlock +git worktree unlock +``` + +## Quick Reference + +### Worktree Operations + +| Task | Command | +|------|---------| +| Create worktree | `git worktree add -b ` | +| List worktrees | `git worktree list` | +| Remove worktree | `git worktree remove ` | +| Clean metadata | `git worktree prune` | +| Set branch binding | `printf '%s\n' "" > "$(git rev-parse --git-dir)/agent-expected-branch"` | +| Set worktree binding | `printf '%s\n' "$(pwd -P)" > "$(git rev-parse --git-dir)/agent-expected-worktree"` | + +### Standard Git Operations + +| Task | Command | +|------|---------| +| Create branch | `git checkout -b feat/name` or `git switch -c feat/name` | +| Switch branch | `git checkout main` or `git switch main` | +| List branches | `git branch -vv` (local) or `git branch -avv` (all) | +| Delete branch | `git branch -d name` (safe) or `git branch -D name` (force) | +| Stage changes | `git add .` or `git add file.js` | +| Commit changes | `git commit -m "message"` | +| Amend commit | `git commit --amend` | +| View status | `git status` or `git status -sb` | +| View diff | `git diff` (unstaged) or `git diff --staged` (staged) | +| View history | `git log --oneline --graph --all` | +| Merge branch | `git merge --no-ff feat/name` | +| Rebase branch | `git rebase main` | +| Abort merge/rebase | `git merge --abort` or `git rebase --abort` | +| Undo last commit | `git reset HEAD~1` (keep changes) | +| Discard changes | `git restore file.js` or `git checkout -- file.js` | +| Stash changes | `git stash` or `git stash -u` | +| Apply stash | `git stash pop` or `git stash apply` | +| Fetch updates | `git fetch --all --prune` | +| Pull changes | `git pull --ff-only` (safe) | +| Push changes | `git push -u origin feat/name` | +| View reflog | `git reflog` | + +### Safety Commands + +| Task | Command | +|------|---------| +| Verify branch | `git branch --show-current` | +| Verify path | `git rev-parse --show-toplevel` | +| Safe rebase | `git rebase origin/develop` | +| Safe push | `git push origin ` | +| Safe pull | `git pull --ff-only` | + +## Error Prevention Checklist + +Before starting agent work in a worktree: +- [ ] Worktree created with correct branch name +- [ ] Branch follows naming convention `feat/-` +- [ ] Metadata files written to `.git/agent-expected-branch` and `.git/agent-expected-worktree` +- [ ] Hooks are executable (`chmod +x "$(git rev-parse --git-path hooks)"/pre-*`) +- [ ] Current branch verified with `git branch --show-current` +- [ ] Worktree path verified with `git rev-parse --show-toplevel` +- [ ] Base branch is up to date (`git fetch origin`) diff --git a/.agents/skills/git-worktree-ops/cleanup-worktree.sh b/.agents/skills/git-worktree-ops/cleanup-worktree.sh new file mode 100644 index 0000000..b1deac1 --- /dev/null +++ b/.agents/skills/git-worktree-ops/cleanup-worktree.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# Clean up completed or abandoned worktrees +# Usage: cleanup-worktree.sh [--delete-branch] [--force] + +set -euo pipefail + +usage() { + cat < [options] + +Options: + --delete-branch Delete the branch after removing worktree + --force Force removal even if worktree has uncommitted changes + --remote Also delete remote branch (requires --delete-branch) + +Examples: + cleanup-worktree.sh ../myapp-worktrees/codex-fix-auth + cleanup-worktree.sh ../myapp-worktrees/codex-fix-auth --delete-branch + cleanup-worktree.sh ../myapp-worktrees/codex-fix-auth --delete-branch --remote --force +EOF +} + +if [[ $# -lt 1 ]]; then + usage + exit 1 +fi + +WORKTREE_PATH="$1" +shift + +DELETE_BRANCH=0 +FORCE=0 +DELETE_REMOTE=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --delete-branch) + DELETE_BRANCH=1 + shift + ;; + --force) + FORCE=1 + shift + ;; + --remote) + DELETE_REMOTE=1 + shift + ;; + *) + echo "Unknown option: $1" >&2 + usage + exit 1 + ;; + esac +done + +if [[ ! -d "$WORKTREE_PATH" ]]; then + echo "Error: Worktree path not found: $WORKTREE_PATH" >&2 + exit 1 +fi + +# Get branch name from worktree +cd "$WORKTREE_PATH" +BRANCH="$(git branch --show-current)" +cd - >/dev/null + +echo "Cleaning up worktree:" +echo " Path: $WORKTREE_PATH" +echo " Branch: $BRANCH" +echo "" + +# Remove worktree +echo "Removing worktree..." +if [[ $FORCE -eq 1 ]]; then + git worktree remove --force "$WORKTREE_PATH" +else + git worktree remove "$WORKTREE_PATH" +fi +echo " ✓ Worktree removed" + +# Delete branch if requested +if [[ $DELETE_BRANCH -eq 1 ]]; then + echo "Deleting local branch..." + if git show-ref --verify --quiet "refs/heads/$BRANCH"; then + git branch -D "$BRANCH" + echo " ✓ Local branch deleted: $BRANCH" + else + echo " ⚠️ Branch not found: $BRANCH" + fi + + # Delete remote branch if requested + if [[ $DELETE_REMOTE -eq 1 ]]; then + echo "Deleting remote branch..." + if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then + git push origin --delete "$BRANCH" + echo " ✓ Remote branch deleted: origin/$BRANCH" + else + echo " ⚠️ Remote branch not found: origin/$BRANCH" + fi + fi +fi + +# Prune worktree metadata +echo "Pruning worktree metadata..." +git worktree prune +echo " ✓ Metadata pruned" + +echo "" +echo "✓ Cleanup complete!" +echo "" +echo "Remaining worktrees:" +git worktree list diff --git a/.agents/skills/git-worktree-ops/quick-worktree.sh b/.agents/skills/git-worktree-ops/quick-worktree.sh new file mode 100644 index 0000000..82bb6df --- /dev/null +++ b/.agents/skills/git-worktree-ops/quick-worktree.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# Quick worktree setup with automatic guardrails configuration +# Usage: quick-worktree.sh [base-branch] + +set -euo pipefail + +usage() { + cat < [base-branch] + +Examples: + quick-worktree.sh codex fix-auth + quick-worktree.sh claude add-metrics develop + quick-worktree.sh copilot docs main + +Arguments: + agent Agent name (codex, claude, copilot) + task Task description (kebab-case) + base-branch Base branch to branch from (default: develop) +EOF +} + +if [[ $# -lt 2 ]]; then + usage + exit 1 +fi + +AGENT="$1" +TASK="$2" +BASE="${3:-develop}" + +BRANCH="feat/${AGENT}-${TASK}" +WORKTREE_ROOT="../$(basename "$(pwd)")-worktrees" +WORKTREE_PATH="${WORKTREE_ROOT}/${AGENT}-${TASK}" + +echo "Creating worktree setup:" +echo " Agent: $AGENT" +echo " Task: $TASK" +echo " Branch: $BRANCH" +echo " Path: $WORKTREE_PATH" +echo " Base: $BASE" +echo "" + +# Create worktrees directory if needed +mkdir -p "$WORKTREE_ROOT" + +# Create worktree +echo "Creating worktree..." +git worktree add -b "$BRANCH" "$WORKTREE_PATH" "$BASE" + +# Configure guardrails +echo "Configuring guardrails..." +cd "$WORKTREE_PATH" + +GIT_DIR="$(git rev-parse --git-dir)" +printf '%s\n' "$BRANCH" > "$GIT_DIR/agent-expected-branch" +printf '%s\n' "$(pwd -P)" > "$GIT_DIR/agent-expected-worktree" + +# Set safe defaults +git config --local push.default current +git config --local pull.ff only + +echo "" +echo "✓ Worktree created and configured!" +echo "" +echo "Verification:" +echo " Current branch: $(git branch --show-current)" +echo " Worktree path: $(git rev-parse --show-toplevel)" +echo " Expected branch: $(cat "$GIT_DIR/agent-expected-branch")" +echo " Expected worktree: $(cat "$GIT_DIR/agent-expected-worktree")" +echo "" +echo "Next steps:" +echo " cd $WORKTREE_PATH" +echo " # Start your agent and begin work" diff --git a/.agents/skills/git-worktree-ops/verify-guardrails.sh b/.agents/skills/git-worktree-ops/verify-guardrails.sh new file mode 100644 index 0000000..0b45a9e --- /dev/null +++ b/.agents/skills/git-worktree-ops/verify-guardrails.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash +# Verify guardrails are properly configured in current worktree +# Usage: verify-guardrails.sh [worktree-path] + +set -euo pipefail + +WORKTREE="${1:-.}" + +cd "$WORKTREE" + +echo "Verifying guardrails for: $(pwd)" +echo "" + +ERRORS=0 +WARNINGS=0 + +# Check if in a git repository +if ! git rev-parse --git-dir >/dev/null 2>&1; then + echo "✗ Not a Git repository" + exit 1 +fi + +GIT_DIR="$(git rev-parse --git-dir)" +CURRENT_BRANCH="$(git branch --show-current)" +CURRENT_PATH="$(git rev-parse --show-toplevel)" + +# Check hooks +echo "Hooks:" +for hook in pre-commit pre-push; do + HOOK_PATH="$(git rev-parse --git-path hooks/$hook)" + if [[ -x "$HOOK_PATH" ]]; then + echo " ✓ $hook is executable" + else + echo " ✗ $hook is missing or not executable" + ((ERRORS++)) + fi +done +echo "" + +# Check metadata files +echo "Metadata files:" +if [[ -f "$GIT_DIR/agent-expected-branch" ]]; then + EXPECTED_BRANCH="$(cat "$GIT_DIR/agent-expected-branch")" + echo " ✓ agent-expected-branch exists: $EXPECTED_BRANCH" + + if [[ "$CURRENT_BRANCH" != "$EXPECTED_BRANCH" ]]; then + echo " ⚠️ WARNING: Current branch ($CURRENT_BRANCH) != expected ($EXPECTED_BRANCH)" + ((WARNINGS++)) + fi +else + echo " ✗ agent-expected-branch is missing" + ((ERRORS++)) +fi + +if [[ -f "$GIT_DIR/agent-expected-worktree" ]]; then + EXPECTED_PATH="$(cat "$GIT_DIR/agent-expected-worktree")" + echo " ✓ agent-expected-worktree exists: $EXPECTED_PATH" + + if [[ "$CURRENT_PATH" != "$EXPECTED_PATH" ]]; then + echo " ⚠️ WARNING: Current path ($CURRENT_PATH) != expected ($EXPECTED_PATH)" + ((WARNINGS++)) + fi +else + echo " ✗ agent-expected-worktree is missing" + ((ERRORS++)) +fi +echo "" + +# Check git config +echo "Git configuration:" +PUSH_DEFAULT="$(git config --local --get push.default 2>/dev/null || echo "not set")" +PULL_FF="$(git config --local --get pull.ff 2>/dev/null || echo "not set")" + +if [[ "$PUSH_DEFAULT" == "current" ]]; then + echo " ✓ push.default = current" +else + echo " ⚠️ push.default = $PUSH_DEFAULT (recommended: current)" + ((WARNINGS++)) +fi + +if [[ "$PULL_FF" == "only" ]]; then + echo " ✓ pull.ff = only" +else + echo " ⚠️ pull.ff = $PULL_FF (recommended: only)" + ((WARNINGS++)) +fi +echo "" + +# Summary +echo "Summary:" +echo " Current branch: $CURRENT_BRANCH" +echo " Current worktree: $CURRENT_PATH" + +if [[ $ERRORS -eq 0 && $WARNINGS -eq 0 ]]; then + echo "" + echo "✓ All guardrails properly configured!" + exit 0 +elif [[ $ERRORS -eq 0 ]]; then + echo "" + echo "⚠️ $WARNINGS warning(s) found" + exit 0 +else + echo "" + echo "✗ $ERRORS error(s) and $WARNINGS warning(s) found" + echo "" + echo "To fix, run:" + echo " GIT_DIR=\"\$(git rev-parse --git-dir)\"" + echo " printf '%s\\n' \"$CURRENT_BRANCH\" > \"\$GIT_DIR/agent-expected-branch\"" + echo " printf '%s\\n' \"$CURRENT_PATH\" > \"\$GIT_DIR/agent-expected-worktree\"" + echo " git config --local push.default current" + echo " git config --local pull.ff only" + exit 1 +fi diff --git a/.github/agents/architectreviewer.agent.md b/.github/agents/architectreviewer.agent.md new file mode 100644 index 0000000..04bee23 --- /dev/null +++ b/.github/agents/architectreviewer.agent.md @@ -0,0 +1,165 @@ +--- +name: ArchitectReviewer +description: Multi-framework compatibility and architectural pattern validation specialist +--- + +# ArchitectReviewer Agent + +Specialized agent for validating architectural patterns, multi-framework compatibility, and design consistency in Mammoth.Extensions.DependencyInjection. + +## Primary Role + +ArchitectReviewer is your architecture guardian. It ensures: +- **Multi-framework compatibility** across `netstandard2.0`, `net8.0`, `net9.0`, `net10.0` +- **Design pattern consistency** (decorators, keyed services, partial classes, fluent APIs) +- **Type safety** (generics, constraints, nullability) +- **Circular dependency prevention** in decoration chains +- **Feature parity** across target frameworks (`.Disabled.cs` patterns) +- **Breaking change detection** before they cause issues + +## When to Use + +Invoke ArchitectReviewer when you need to: +- Validate a new extension method or decorator before committing +- Review multi-framework compatibility of a refactor (`@ArchitectReviewer: Check this change across all net versions`) +- Audit circular dependencies in decoration chains +- Verify keyed service lifetime management correctness +- Identify potential transient disposables issues +- Ensure deprecations and breaking changes are properly flagged +- Refactor core types (`ServiceIdentifier`, `ServiceDescriptor` handling) + +## Core Capabilities + +### Multi-Framework Validation +- Verifies code runs correctly on all targets: `netstandard2.0`, `net8.0`, `net9.0`, `net10.0` +- Checks `.Disabled.cs` conditional compilation patterns +- Validates `Directory.Build.props` constraints are respected +- Flags reflection-only features that don't work on limited frameworks +- Tests compatibility with different .NET API surfaces + +### Design Pattern Audits +- **Decorators**: Validates implementation follows pipe pattern (no cycles, correct lifetime handling) +- **Keyed Services**: Ensures `ServiceIdentifier` uniqueness and proper key types +- **Partial Classes**: Verifies organization aligns with functionality grouping +- **Fluent APIs**: Checks extension methods return appropriate types for chaining +- **Factory Registration**: Audits factory delegates for proper service lifetime + +### Type Safety & Generics +- Reviews generic constraints (`where TService : class`, etc.) for correctness +- Validates nullability annotations across all parameters and returns +- Ensures implicit usings don't create ambiguity +- Checks for proper use of `struct` vs `class` patterns + +### Dependency & Lifetime Analysis +- Detects circular decoration patterns +- Validates that transient services aren't decorated as singletons +- Checks keyed service dependencies are properly tracked +- Analyzes resolution chains for correctness + +### Breaking Change Detection +- Flags API surface changes (removed methods, signature changes) +- Detects behavioral breaking changes +- Checks if changes require `Changelog.md` entries +- Alerts when `ServiceIdentifier`, `ServiceDescriptor` handling changes + +## Typical Workflow + +1. **Receive code for review**: Examine the proposed change or refactor +2. **Analyze architecture**: Check patterns, generics, nullability, and design consistency +3. **Test frameworks**: Verify on each target framework (or flag compatibility issues) +4. **Audit safety**: Check for circular deps, lifetime issues, transient disposables +5. **Identify breaking changes**: Flag any API or behavioral changes +6. **Suggest or fix**: + - Auto-fix safe, obvious issues (naming, pattern alignment) + - Suggest improvements for design issues + - Flag breaking changes for manual review +7. **Report**: Provide clear feedback with severity levels + +## Example Prompts + +### Validating New Code +``` +@ArchitectReviewer: Review this new Decorate overload for multi-framework +compatibility and potential circular dependency issues. +``` + +### Refactoring Core Types +``` +@ArchitectReviewer: I'm refactoring ServiceIdentifier to support custom equality. +Check if the change is compatible across all frameworks and highlight any breaking changes. +``` + +### Framework-Specific Features +``` +@ArchitectReviewer: This reflection-based optimization only works on net8.0+. +Set up the .Disabled.cs pattern correctly and validate compatibility. +``` + +### Dependency Chain Audits +``` +@ArchitectReviewer: Audit the entire decoration chain for potential circular +dependencies and lifetime correctness. +``` + +## Key Patterns (from copilot-instructions.md) + +ArchitectReviewer enforces these project patterns: + +- **Target Frameworks**: `netstandard2.0`, `net8.0`, `net9.0`, `net10.0` (from `Directory.Build.props`) +- **C# 14.0**: Latest language features with nullable reference types enabled +- **Partial Classes**: Organization by feature area +- **Fluent Extension Methods**: Return `IServiceCollection` for chaining +- **Decorator Pattern**: Composition of wrappers without modifying originals +- **Keyed Services**: Built on .NET 8.0+ infrastructure with `ServiceIdentifier` tracking +- **Diagnostic Utilities**: `DetectIncorrectUsageOfTransientDisposables` patterns +- **Framework Conditionality**: `.Disabled.cs` for unsupported features on limited frameworks + +## Code Fixes ArchitectReviewer Makes + +### Auto-Fix (Safe) +- ✅ Incorrect generic constraint syntax +- ✅ Missing XML documentation tags +- ✅ Naming inconsistencies (Decorate* prefix, Keyed suffix) +- ✅ Nullability annotation issues + +### Suggest (Requires Review) +- ⚠️ Potential circular dependencies +- ⚠️ Generic constraint overly restrictive or loose +- ⚠️ Factory lifetime mismatch with decorator lifetime +- ⚠️ Missing `.Disabled.cs` pattern for framework-specific code + +### Flag (Breaking Changes) +- 🚩 Public API signature changes +- 🚩 Behavioral changes to ServiceIdentifier or keyed service resolution +- 🚩 Framework compatibility breaking (netstandard2.0 vs net8.0+) +- 🚩 Decorator pipe reordering or removal + +## Tool Access + +ArchitectReviewer has full access to: +- File creation/editing (source and `.Disabled.cs` patterns) +- Code analysis (grep, semantic search, symbol lookup) +- Test execution (validate changes don't break tests) +- Git operations (check breaking changes) +- Changelog updates (flag when needed) + +## Integration Points + +- **With TestWrangler**: Suggests tests for new architectural patterns +- **With PackagePrepper**: Flags breaking changes for changelog documentation +- **With copilot-instructions.md**: Enforces all project conventions and patterns + +## Quality Standards + +Every change reviewed by ArchitectReviewer should: +- ✅ Work on all target frameworks (tested or verified logically) +- ✅ Follow generic constraint and nullability patterns +- ✅ Maintain decorator/keyed service consistency +- ✅ Include no circular dependencies +- ✅ Pass architecture checks +- ✅ Clearly document framework-specific behavior +- ✅ Flag breaking changes explicitly + +--- + +**Integration**: Works seamlessly with TestWrangler and PackagePrepper for end-to-end development. diff --git a/.github/agents/packageprepper.agent.md b/.github/agents/packageprepper.agent.md new file mode 100644 index 0000000..5137614 --- /dev/null +++ b/.github/agents/packageprepper.agent.md @@ -0,0 +1,189 @@ +--- +name: PackagePrepper +description: Release pipeline, versioning, and NuGet package management specialist +--- + +# PackagePrepper Agent + +Specialized agent for managing the complete release pipeline, including versioning, changelog management, and NuGet package validation in Mammoth.Extensions.DependencyInjection. + +## Primary Role + +PackagePrepper orchestrates the entire release lifecycle. It handles: +- **Changelog management** (vNext → version sections, entry formatting) +- **Versioning** (GitVersion-based semver, git tag coordination) +- **Package metadata** (validation, source link, symbol packages) +- **Release validation** (breaking changes, documentation, build checks) +- **Publishing coordination** (pack generation, artifact management) + +## When to Use + +Invoke PackagePrepper when you need to: +- Prepare a release (`@PackagePrepper: Prepare version 0.7.0 for release`) +- Update changelog (`@PackagePrepper: Add this feature to the changelog`) +- Validate package metadata before packaging +- Manage breaking change documentation +- Run a full pack with production settings and verification +- Audit the release pipeline for completeness + +## Core Capabilities + +### Changelog Management +- **Creates entries** in the `vNext` section with GitHub issue links +- **Promotes versions** from `vNext` → release numbered sections +- **Validates structure**: Ensures breaking changes have dedicated section +- **Formats entries**: Consistent bullet point style with issue references +- **Cross-references**: Links to GitHub issues and PRs + +### Versioning Operations +- **Reads current version** from `GitVersion.yml` and git tags +- **Suggests version bumps** based on breaking changes vs features/fixes +- **Validates semver** structure against GitVersion patterns +- **Coordinates git tags** for release commits +- **Updates files** that embed version information + +### Package Metadata Validation +- **Validates `.csproj` metadata**: + - `PackageDescription`, `PackageTags`, `Authors` + - `RepositoryUrl`, `PackageProjectUrl`, `LicenseExpression` + - `GenerateDocumentationFile`, `PackageReadmeFile`, `PackageIcon` +- **Checks source link**: `SourceLink.GitHub` is configured for symbol packages +- **Verifies symbols**: `.snupkg` generation enabled +- **Tests output**: Runs `dotnet pack` and validates artifact structure + +### Release Validation +- **Breaking changes check**: Ensures breaking changes are documented +- **Completeness audit**: + - Build succeeds (`dotnet build --configuration Release`) + - Tests pass (`dotnet test`) + - Coverage maintained + - Changelog entries exist + - Version is bumped +- **Artifact verification**: Checks `.nupkg` and `.snupkg` files are created +- **NuGet readiness**: Validates package can be published + +### Release Preparation +- **Full pipeline execution**: + 1. Validate changelog structure + 2. Promote `vNext` → version + 3. Update version in `GitVersion.yml` + 4. Run build and tests + 5. Generate package + 6. Verify artifacts + 7. Create release summary +- **Pre-flight checks**: Confirm all steps are ready before promotion + +## Typical Workflow + +1. **Receive release request**: "Prepare 0.7.0" or "Add feature to vNext" +2. **Validate current state**: Check changelog, version, and build status +3. **Perform operations**: + - Update `Changelog.md` structure + - Bump version in `GitVersion.yml` if needed + - Run `dotnet build` and `dotnet test` + - Execute `dotnet pack --configuration Release` +4. **Verify artifacts**: Check `.nupkg` and `.snupkg` in `./artifacts` +5. **Report**: Provide release summary with next steps +6. **Coordinate**: Flag any manual steps (git tag, GitHub release) + +## Example Prompts + +### Adding to Changelog (vNext) +``` +@PackagePrepper: Add this to the changelog vNext section: +"Removed Reflection.Emit-based proxy generation; class-based decoration is now +supported natively. #11" +``` + +### Preparing a Release +``` +@PackagePrepper: Prepare version 0.7.0 for release. Promote vNext to 0.7.0 +in Changelog.md, update GitVersion.yml, and run a full pack validation. +``` + +### Release Validation +``` +@PackagePrepper: Run a full release validation. Check changelog, version, +build, tests, and package generation for 0.7.0. +``` + +### Breaking Changes Documentation +``` +@PackagePrepper: Document these breaking changes in the changelog: +- ServiceProviderFactory constructor signature changed +- Removed deprecated Decorate(Type, Type) method +``` + +## Key Patterns (from copilot-instructions.md) + +PackagePrepper coordinates around these project patterns: + +- **Changelog Format**: + - `## vNext` at top (unreleased) + - `## X.Y.Z` dated sections below + - `### Breaking Changes` subsection when applicable +- **Version Management**: GitVersion-based semver with git tags +- **Target Frameworks**: Multi-framework packaging (`netstandard2.0`, `net8.0`, `net9.0`, `net10.0`) +- **Package Metadata**: All fields in `.csproj` must be complete +- **Symbol Packages**: `.snupkg` generation for source link +- **CI Integration**: GitHub Actions workflow support + +## Release Checklist + +PackagePrepper verifies before finalizing a release: + +- ✅ Changelog structure is valid and `vNext` → version promoted +- ✅ Version is bumped in `GitVersion.yml` if needed +- ✅ Build succeeds: `dotnet build --configuration Release` +- ✅ All tests pass: `dotnet test` +- ✅ Code coverage is adequate (no regression) +- ✅ Package metadata is complete in `.csproj` +- ✅ Breaking changes are documented in changelog +- ✅ `dotnet pack` succeeds and creates `.nupkg` + `.snupkg` +- ✅ Source link is configured correctly +- ✅ README and icon files are included +- ✅ Release notes are ready for GitHub release page + +## Tool Access + +PackagePrepper has full access to: +- File editing (Changelog.md, GitVersion.yml, `.csproj`) +- Git operations (tags, commit info) +- Build and test execution +- `dotnet pack` and artifact validation +- Terminal commands for release coordination + +## Release Workflow Integration + +PackagePrepper coordinates with: + +1. **Development Phase**: Maintains `## vNext` section in Changelog.md +2. **ArchitectReviewer Phase**: Flags breaking changes for documentation +3. **TestWrangler Phase**: Validates test completion before packaging +4. **Release Phase**: + - Promotes vNext → version in changelog + - Bumps version number + - Runs full validation + - Generates artifacts + - Creates release summary + +## Integration Points + +- **With ArchitectReviewer**: Gets flagged breaking changes to document +- **With TestWrangler**: Verifies test coverage before release +- **With copilot-instructions.md**: Knows all project conventions and version targets + +## Quality Standards + +Every release managed by PackagePrepper must: +- ✅ Have complete, formatted changelog entries +- ✅ Use valid semantic versioning +- ✅ Include all required NuGet metadata +- ✅ Pass build, tests, and coverage checks +- ✅ Document all breaking changes explicitly +- ✅ Generate both `.nupkg` and `.snupkg` artifacts +- ✅ Include source link and documentation + +--- + +**Release Coordination**: Prepares releases for confident, documented publishing to NuGet. diff --git a/.github/agents/testwrangler.agent.md b/.github/agents/testwrangler.agent.md new file mode 100644 index 0000000..f7e2a88 --- /dev/null +++ b/.github/agents/testwrangler.agent.md @@ -0,0 +1,129 @@ +--- +name: TestWrangler +description: Test creation, execution, and coverage analysis specialist for MSTest projects +--- + +# TestWrangler Agent + +Specialized agent for comprehensive test development, execution, and coverage analysis in Mammoth.Extensions.DependencyInjection. + +## Primary Role + +TestWrangler is your dedicated testing specialist. It focuses on: +- **Creating** test files following MSTest patterns and project 1:1 naming conventions +- **Executing** unit, integration, and edge-case tests with detailed feedback +- **Analyzing** code coverage and identifying gaps +- **Debugging** test failures and flaky tests +- **Improving** test quality and comprehensiveness + +## When to Use + +Invoke TestWrangler when you need to: +- Write new test files or test methods (`@TestWrangler: Create tests for...`) +- Debug failing or flaky tests (`@TestWrangler: Why are these tests failing?`) +- Analyze coverage gaps (`@TestWrangler: Suggest test scenarios for...`) +- Refactor existing tests for clarity or maintainability +- Run tests with coverage reporting and recommendations +- Create fixtures and mocks following `TestServices.cs` patterns + +## Core Capabilities + +### Test Creation +- Creates test files matching source file names (`ServiceCollectionExtensions.Decorators.cs` → `ServiceCollectionExtensions.Decorators.Tests.cs`) +- Uses `[TestClass]` and `[TestMethod]` attributes correctly +- Leverages `TestServices.cs` for common fixtures, mocks, and service registration patterns +- Includes Arrange-Act-Assert structure with clear test naming +- Covers unit cases, integration scenarios, and edge cases + +### Test Execution & Analysis +- Runs `dotnet test` with targeted scope (single class, specific test, or full suite) +- Collects and interprets code coverage reports (`--collect:"XPlat Code Coverage"`) +- Identifies covered vs. uncovered code paths +- Suggests additional test scenarios for untested branches +- Diagnoses test failures and proposes fixes + +### Code Coverage +- **Actively analyzes** coverage gaps after test runs +- Recommends test cases for low-coverage areas +- Highlights critical paths that lack test coverage +- Validates that new features have adequate test protection +- Suggests behavioral edge cases to test + +## Typical Workflow + +1. **Understand the requirement**: Examine the code to be tested or the failing test +2. **Review existing patterns**: Check `TestServices.cs` and related test files for fixture/mock patterns +3. **Create or modify tests**: Write test methods with descriptive names and clear structure +4. **Run tests**: Execute with `dotnet test` and collect coverage +5. **Analyze results**: + - Flag failures with root cause analysis + - Identify coverage gaps + - Suggest additional scenarios +6. **Iterate**: Refine tests based on results and recommendations + +## Example Prompts + +### Writing New Tests +``` +@TestWrangler: Write comprehensive MSTest unit tests for the new Decorate overload +that handles async service factories. Include edge cases for singleton decorators. +``` + +### Analyzing Coverage Gaps +``` +@TestWrangler: Check code coverage for ServiceProviderExtensions.Registration.cs +and suggest missing test scenarios for the factory-based registration paths. +``` + +### Debugging Failures +``` +@TestWrangler: The ServiceCollectionExtensions.KeyedService.Tests are randomly +failing. Debug the issue and fix the flaky tests. +``` + +### Improving Test Quality +``` +@TestWrangler: Review the InjectAnArrayOfDependenciesTests.cs file for clarity, +maintainability, and suggest any missing edge cases. +``` + +## Key Patterns (from copilot-instructions.md) + +TestWrangler operates within these project patterns: + +- **Partial Classes**: Tests match partial source files (e.g., `Decorators.Tests.cs`) +- **Fluent APIs**: Service registration returns `IServiceCollection` for chaining +- **Generic Constraints**: Many methods use `where TService : class` constraints +- **Keyed Services**: Testing keyed service lifetime and resolution +- **Framework Targets**: Library builds target `netstandard2.0`; tests run on `net472`, `net8.0`, `net9.0`, `net10.0` +- **Diagnostic Validation**: Tests check for transient disposables and circular dependencies + +## Tool Access + +TestWrangler has full access to: +- File creation/editing (test files and fixtures) +- Running tests via `runTests` tool and terminal +- Code search and analysis (grep, semantic search) +- Reading source files to understand patterns +- Coverage collection and reporting + +## Integration Points + +- **With ArchitectReviewer**: For validating test assumptions align with architectural patterns +- **With PackagePrepper**: Ensures breaking changes in tests are noted in changelog +- **With copilot-instructions.md**: Inherits all project conventions and multi-framework knowledge + +## Quality Standards + +Every test created or modified by TestWrangler should: +- ✅ Follow `[TestClass]` / `[TestMethod]` naming and structure +- ✅ Use descriptive test names (e.g., `WhenDecoratingFactoryService_ThenDecoratorIsApplied`) +- ✅ Leverage `TestServices.cs` fixtures where applicable +- ✅ Include comments for non-obvious test setup or assertions +- ✅ Cover both success and failure paths +- ✅ Pass across all target frameworks (verify with `dotnet test`) +- ✅ Achieve >80% coverage for new code paths + +--- + +**Integration**: Works seamlessly with ArchitectReviewer and PackagePrepper for end-to-end development. \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..0fca72b --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,207 @@ +# Copilot Workspace Instructions + +## Project Overview + +**Mammoth.Extensions.DependencyInjection** is a utility library providing advanced extensions for `Microsoft.Extensions.DependencyInjection` (v9.0.0+). + +### Purpose + +Extend the standard DI container with: +- **Decorator pattern** support for wrapping services (interface-based and class-based) +- **DependsOn** extensions to register services with explicit keyed dependencies +- **Keyed services** management utilities +- **Service provider factory** with advanced registration tracking and resolution diagnostics + +### Key Technologies + +- **Language**: C# 14.0 with nullable reference types and implicit usings enabled +- **Target Frameworks**: `netstandard2.0`, `net8.0`, `net9.0`, `net10.0` +- **Testing**: MSTest with coverlet code coverage +- **Versioning**: GitVersion (based on Git tags) +- **Packaging**: NuGet with source link support + +--- + +## Build & Development + +### Essential Commands + +```powershell +# Restore and build +dotnet restore ./src/Mammoth.Extensions.DependencyInjection.sln +dotnet build ./src/Mammoth.Extensions.DependencyInjection.sln --configuration Release + +# Run tests +dotnet test ./src/Mammoth.Extensions.DependencyInjection.sln + +# Create NuGet package +dotnet pack ./src/Mammoth.Extensions.DependencyInjection.sln --configuration Release --output ./artifacts +``` + +### Build Script + +Use `build.ps1` for full CI pipeline (restore tools, versioning, build, test, pack). + +### Development Workflow + +1. Work in `src/` directory +2. Solution file: `src/Mammoth.Extensions.DependencyInjection.sln` +3. Main project: `src/Mammoth.Extensions.DependencyInjection/` +4. Tests: `src/Mammoth.Extensions.DependencyInjection.Tests/` +5. Common settings: `src/Directory.Build.props` + +--- + +## Code Organization + +### Main Library Structure + +The library uses **partial classes** to organize extension methods by functionality: + +| File | Purpose | +|------|---------| +| `ServiceCollectionExtensions.cs` | Base installer pattern | +| `ServiceCollectionExtensions.Decorators.cs` | Decorator registration methods | +| `ServiceCollectionExtensions.KeyedService.cs` | Keyed service helpers | +| `ServiceCollectionExtensions.Registration.cs` | Advanced registration utilities | +| `ServiceProviderExtensions.cs` | Service provider query methods | +| `ServiceProviderExtensions.Registration.cs` | Factory and registration tracking | +| `ServiceProviderExtensions.Reflection.cs` | Reflection-based utilities | + +### Supporting Classes + +- **`ServiceIdentifier`**: Uniquely identifies registered services +- **`ServiceDescriptorExtensions`**: Utilities for analyzing service descriptors +- **`TypeExtensions`**: Type inspection and filtering helpers +- **`ServiceProviderFactory`**: Advanced provider configuration +- **`DetectIncorrectUsageOfTransientDisposables`**: Diagnostic checks +- **`ResolutionContext`**: Tracks service resolution graph +- **`Configuration/` subfolder**: Configuration and diagnostic utilities +- **`Inspector/` subfolder**: Assembly inspection for type discovery + +### Test Organization + +Tests follow a 1:1 naming pattern with source files: + +- `ServiceCollectionExtensions.Decorators.Tests.cs` → Tests for decorators +- `ServiceProviderExtensions.Resolution.Tests.cs` → Tests for resolution +- `ServiceProviderExtensions.Registration.Tests.cs` → Tests for registration +- `InjectAnArrayOfDependenciesTests.cs` → Feature-specific tests +- `TestServices.cs` → Shared test fixtures and utilities + +--- + +## Code Conventions + +### Style & Standards + +- **XML Documentation**: All public types/methods must have `///` documentation +- **Nullability**: Strict null checking enabled (`enable`) +- **Implicit Usings**: Enabled to reduce boilerplate +- **Analysis**: Latest recommended .NET analyzers enabled with code style enforcement +- **Code Style**: Enforced during build (`True`) + +### Naming Patterns + +- Extension methods use `ServiceCollectionExtensions` and `ServiceProviderExtensions` partial classes +- Service identifiers use `ServiceIdentifier` struct for uniqueness +- Decorator factories prefix with `Decorate` +- Keyed service methods include `Keyed` in the name + +### Common Patterns + +1. **Fluent Extension Methods**: All service registration methods return the collection for chaining +2. **Generic Methods with Constraints**: Extensive use of generic constraints for type safety +3. **Factory Pattern**: Services often registered via factory delegates +4. **Descriptor Inspection**: Extension methods analyze `ServiceDescriptor` to apply transformations + +--- + +## Testing Guidelines + +### Test Framework + +- **Framework**: MSTest (v4.0.2) +- **Coverage**: coverlet (v6.0.4) +- **Diagnostics**: Microsoft.Extensions.Diagnostics.Testing + +### Test File Conventions + +- Test files match source file names with `.Tests.cs` suffix +- Use `[TestMethod]` attribute +- Group related tests in `[TestClass]` classes +- Leverage `TestServices.cs` for common fixtures + +### Running Tests + +```powershell +# All tests +dotnet test ./src/Mammoth.Extensions.DependencyInjection.sln + +# Specific test class +dotnet test --filter ClassName=ServiceCollectionExtensions.Decorators.Tests + +# With coverage +dotnet test --collect:"XPlat Code Coverage" +``` + +--- + +## Architecture & Design Patterns + +### Core Concepts + +1. **Service Decoration**: Wraps existing service registrations with decorators without modifying the original + - Works with transient, scoped, singleton, and keyed services + - Supports interface-based and class-based decoration + - Handles factory-registered services + +2. **Keyed Services**: Built on .NET 8.0+ keyed service infrastructure + - `DependsOn` extensions enable explicit keyed dependency registration + - Service identifiers include both type and key information + +3. **Reflection-Based Resolution**: Optional advanced diagnostics + - `ServiceProviderExtensions.Reflection.cs` provides introspection capabilities + - `ResolutionContextTrackingServiceProviderDecorator` tracks resolution chains (disabled by default) + +### Common Pitfalls + +- **Transient Disposables**: Use `DetectIncorrectUsageOfTransientDisposables` to catch services that shouldn't be transient +- **Circular Dependencies**: Decoration chains must not create cycles +- **Frame-level Compatibility**: Some reflection features require specific .NET versions (see `.Disabled.cs` files) + +--- + +## Related Files & Resources + +- **GitHub**: [PrimordialCode/Mammoth.Extensions.DependencyInjection](https://github.com/PrimordialCode/Mammoth.Extensions.DependencyInjection) +- **License**: MIT +- **Changelog**: `Changelog.md` - tracks features, breaking changes, and bug fixes +- **GitVersion Config**: `GitVersion.yml` - semantic versioning rules + +--- + +## Tips for AI Assistants + +### Before Making Changes + +1. Check `Changelog.md` for recent breaking changes and version constraints +2. Verify target framework support in `Directory.Build.props` +3. Understand whether changes affect single or multiple target frameworks +4. Check if the feature is platform-specific (see `.Disabled.cs` files) + +### When Adding Features + +1. Update the appropriate partial class file based on functionality +2. Add XML documentation with examples +3. Create corresponding test file or add tests to existing one +4. Update `Changelog.md` under vNext section +5. Ensure changes work across all supported target frameworks + +### Common Tasks + +- **Add new extension method**: Add to the appropriate `ServiceCollectionExtensions.*.cs` or `ServiceProviderExtensions.*.cs` partial class +- **Add diagnostics**: Extend `DetectIncorrectUsageOfTransientDisposables` or configuration utilities +- **Enable reflection features**: Modify condition checks in `ServiceProviderExtensions.Reflection.cs` +- **Update supported versions**: Modify `Directory.Build.props` and adjust compatibility checks + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4196d81 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,103 @@ +# Contributing to Mammoth.Extensions.DependencyInjection + +Thank you for your interest in contributing! This guide provides a quick overview. For detailed technical conventions and project context, see [`.github/copilot-instructions.md`](.github/copilot-instructions.md). + +## Quick Start + +1. **Fork and clone** the repository +2. **Read the instructions**: [`.github/copilot-instructions.md`](.github/copilot-instructions.md) covers code organization, conventions, and build commands +3. **Build locally**: + ```powershell + dotnet restore ./src/Mammoth.Extensions.DependencyInjection.sln + dotnet build ./src/Mammoth.Extensions.DependencyInjection.sln + dotnet test ./src/Mammoth.Extensions.DependencyInjection.sln + ``` +4. **Create a branch** for your feature or fix +5. **Make your changes** (see sections below) +6. **Run tests** and ensure all pass +7. **Open a Pull Request** + +## Project Structure + +- **`src/Mammoth.Extensions.DependencyInjection/`** — Main library (extension methods, decorators, keyed services) +- **`src/Mammoth.Extensions.DependencyInjection.Tests/`** — Unit tests (MSTest + coverlet) +- **`src/Directory.Build.props`** — Shared build configuration (frameworks, C# version, analyzers) +- **`Changelog.md`** — Release notes and breaking changes +- **`.github/copilot-instructions.md`** — Full technical context for development + +## Making Changes + +### Adding Extension Methods + +1. Add to the appropriate partial class: + - `ServiceCollectionExtensions.*.cs` for service registration + - `ServiceProviderExtensions.*.cs` for provider queries/operations +2. Include XML documentation (`///`) with examples for all public methods +3. Follow fluent API pattern (return `IServiceCollection` for chaining where applicable) +4. Add corresponding tests in `*.Tests.cs` matching your source file name + +### Adding Decorators or Keyed Service Features + +- Refer to `ServiceCollectionExtensions.Decorators.cs` and `ServiceCollectionExtensions.KeyedService.cs` +- Ensure compatibility with transient, scoped, singleton, and factory registrations +- Target the library for `netstandard2.0`; run tests on `net472`, `net8.0`, `net9.0`, `net10.0` +- Use `ServiceIdentifier` to track keyed services uniquely + +### Targeting Specific Frameworks + +- Some features may not work on all frameworks (e.g., reflection features on `netstandard2.0`) +- Use `.Disabled.cs` file pattern for conditional compilation (see `ServiceProviderExtensions.Reflection.Disabled.cs`) +- Verify `Directory.Build.props` target framework constraints + +## Code Conventions + +- **C# 14.0** with nullable reference types enabled +- **Named parameters**: Use explicit parameter names in calls +- **Nullability**: Strict checking; mark nullable types with `?` +- **Analyzers**: Latest recommended rules enforced at build time +- **Tests**: Use `[TestMethod]` / `[TestClass]` (MSTest); leverage `TestServices.cs` for fixtures + +## Testing + +- **Run all tests**: `dotnet test ./src/Mammoth.Extensions.DependencyInjection.sln` +- **Run specific test class**: `dotnet test --filter ClassName=MyTestsClass` +- **With coverage**: `dotnet test --collect:"XPlat Code Coverage"` +- **Test files follow naming**: `ServiceCollectionExtensions.Decorators.Tests.cs` matches `ServiceCollectionExtensions.Decorators.cs` + +## Documentation & Changelog + +Every feature or fix should update **`Changelog.md`**: + +1. Find the **`## vNext`** section at the top +2. Add a bullet point describing your change: + ```markdown + ## vNext + + - Added support for wrapping async factory registrations [#XX](https://github.com/PrimordialCode/Mammoth.Extensions.DependencyInjection/issues/XX). + ``` +3. Reference the issue number if applicable +4. If a **breaking change**, prefix with "### Breaking Changes" section + +## Pull Request Checklist + +- [ ] Code builds without warnings (`dotnet build --configuration Release`) +- [ ] All tests pass (`dotnet test`) +- [ ] New public APIs have XML documentation +- [ ] Changelog updated in `vNext` section +- [ ] Changes verified across target frameworks (at least build the library for `netstandard2.0` and run tests on `net472`/`net8.0+`) +- [ ] No transient disposables in new code (use `DetectIncorrectUsageOfTransientDisposables` diagnostic) + +## Asking for Help + +If you need guidance on architecture, decorators, keyed services, or multi-framework compatibility: +- Check [`.github/copilot-instructions.md`](.github/copilot-instructions.md) for detailed patterns +- Review existing code in similar feature areas +- Open a discussion issue if you have design questions + +## License + +By contributing, you agree your work will be licensed under the **MIT License** (see `LICENSE` file). + +--- + +**Questions?** See the [GitHub repository](https://github.com/PrimordialCode/Mammoth.Extensions.DependencyInjection) or open an issue. diff --git a/src/.vscode/.copilot-codeGeneration-instructions.md b/src/.vscode/.copilot-codeGeneration-instructions.md deleted file mode 100644 index 4655a34..0000000 --- a/src/.vscode/.copilot-codeGeneration-instructions.md +++ /dev/null @@ -1 +0,0 @@ -Use MSTest for C# tests. Private field names should start with an underscore. Use CamelCase in TypeScript and JavaScript, use PascalCase in C#. Do not use underscores in variable and parameter names. Avoid using magic numbers in code and prefer using constants for clarity. \ No newline at end of file diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json deleted file mode 100644 index d7ab35f..0000000 --- a/src/.vscode/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "powershell.codeFormatting.addWhitespaceAroundPipe": true, - "workbench.externalBrowser": "chrome", - "github.copilot.chat.codeGeneration.instructions": [ - { - "file": ".copilot-codeGeneration-instructions.md", - } - ], -} \ No newline at end of file