
Ia Git Worktree
- 3 installs
- 28 repo stars
- Updated August 5, 2026
- iliaal/whetstone
Manages Git worktrees for isolated parallel development via a manager script that copies env files, gitignores worktrees, and installs dependencies.
About
A skill for creating, listing, switching, and cleaning up Git worktrees through a worktree-manager.sh script rather than raw git commands. A developer uses it when needing isolated branches for concurrent reviews or feature work.
- Always use the manager script, which copies env files and installs deps
- Fresh-remote-base branching logic that avoids carrying unrelated commits
Ia Git Worktree by the numbers
- 3 all-time installs (skills.sh)
- Ranked #492 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/iliaal/whetstone --skill ia-git-worktreeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 28 |
| Last updated | August 5, 2026 |
| Repository | iliaal/whetstone ↗ |
What it does
Manages Git worktrees for isolated parallel development via a manager script that copies env files, gitignores worktrees, and installs dependencies.
Files
Git worktree manager
Always use the manager script
Never call git worktree add directly -- always use the worktree-manager.sh script.
The script handles critical setup that raw git commands don't: 1. Copies .env, .env.local, .env.test, etc. from main repo 2. Ensures .worktrees is in .gitignore 3. Creates consistent directory structure 4. After creation, install dependencies if detected: package.json → npm install, composer.json → composer install, pyproject.toml → pip install -e ., go.mod → go mod download
Safety Verification
Before creating a worktree, verify the worktree directory is gitignored:
# Verify .worktrees is ignored (should output ".worktrees")
git check-ignore .worktrees || echo "WARNING: .worktrees not in .gitignore"If not ignored, add it to .gitignore before proceeding. The manager script handles this, but verify when troubleshooting.
Branch from a fresh remote base (manager-script behavior)
This subsection documents the safety logic worktree-manager.sh create implements when branching from the default branch — it is not a manual sequence to run. The script handles the steps; the rationale lives here so users can reason about the behavior.
When creating a worktree's branch from the default branch (main/master), the local base may be ahead of origin/<base> due to another session, worktree, or background task. Branching from local HEAD silently carries those unrelated commits into the new feature branch and the eventual PR — and an unconditional git reset --hard origin/<base> would silently drop the user's intentional unpushed work.
The script's safe sequence:
git fetch --no-tags origin <base>
unpushed=$(git log "origin/$base..$base" --oneline)
if [ -n "$unpushed" ]; then
# Surface the commit list and prompt: carry forward (base_ref=$base) or leave on local <base> (base_ref=origin/$base)
...
fi
git worktree add .worktrees/<name> -b <branch> "$base_ref"Two failure modes the prompt distinguishes:
- Stale-base contamination — another session advanced local
<base>pastorigin/<base>with unrelated commits. The user wantsorigin/<base>as the new branch's base; the unpushed commits stay on local<base>for separate handling. - Forgot-to-branch — the user authored real commits on local
<base>intending them for a feature branch. The user wants HEAD as the new branch's base so the commits carry forward.
Local git state alone cannot distinguish these (author email is unreliable in multi-session setups), so the script surfaces the choice rather than guessing. Default fallback when the user can't be reached: branch from origin/<base> and report the unpushed commits in the change summary so the user resolves them deliberately. If the script does not implement this yet, that is a known gap — open an issue rather than working around with raw git worktree add.
After creating a worktree, run the project's test suite to establish a clean baseline. Pre-existing failures in the worktree should be caught before starting new work -- not discovered mid-implementation.
# CORRECT - Always use the script
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh create feature-name
# WRONG - Never do this directly
git worktree add .worktrees/feature-name -b feature-name mainCommands
| Command | Description | Example |
|---|---|---|
create <branch> [from] | Create worktree + branch (default: from main) | ...worktree-manager.sh create feature-login |
list / ls | List all worktrees with status | ...worktree-manager.sh list |
switch <name> / go | Switch to existing worktree | ...worktree-manager.sh switch feature-login |
copy-env <name> | Copy .env files to existing worktree | ...worktree-manager.sh copy-env feature-login |
cleanup / clean | Interactively remove inactive worktrees | ...worktree-manager.sh cleanup |
After cleanup, run git worktree prune to remove any orphaned worktree metadata from manually deleted directories.
All commands use: bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh <command>
Environment Detection
Before creating worktrees, detect the execution context:
1. Already in a worktree? Check git rev-parse --show-toplevel against git worktree list. If the current directory is already a linked worktree, skip creation -- work directly in the existing worktree. 2. Codex/sandbox environment? If $CODEX_SANDBOX is set or the repo is at a non-standard path (e.g., /tmp/, /workspace/), worktrees may not be supported. Fall back to regular branch switching. 3. Bare repo? If git rev-parse --is-bare-repository returns true, worktrees are the only way to have a working directory. Adjust paths accordingly.
Adapt the workflow to the detected context rather than failing with a generic error.
Integration with Workflows
/ia-review
1. Check current branch 2. If ALREADY on target branch -> stay there, no worktree needed 3. If DIFFERENT branch -> offer worktree: "Use worktree for isolated review? (y/n)"
/ia-work
Always offer choice: 1. New branch on current worktree (live work) 2. Worktree (parallel work)
Branch Completion
When work in a worktree is done, verify tests pass, then present exactly 4 options:
1. Merge locally -- merge into base branch, delete worktree branch, clean up worktree 2. Push + PR -- push branch, create PR with gh pr create, keep worktree until merged 3. Keep as-is -- leave branch and worktree for later 4. Discard -- requires typing "discard" to confirm. Deletes branch and worktree. No silent discards.
Clean up the worktree directory only for options 1 and 4. For option 2, the worktree stays until the PR merges.
Change Summary
When completing work in a worktree (before merge or PR), output a structured summary:
CHANGES MADE:
- src/routes/tasks.ts: Added validation middleware
THINGS I DIDN'T TOUCH (intentionally):
- src/routes/auth.ts: Has similar validation gap but out of scope
POTENTIAL CONCERNS:
- The Zod schema is strict -- rejects extra fields. Confirm this is desired.The "DIDN'T TOUCH" section prevents reviewers from wondering whether adjacent issues were missed or intentionally deferred.
Hook Safety Under Husky
Installing hooks into .git/hooks/ silently fails on any repo that uses Husky. Husky sets core.hooksPath (typically to .husky/_) and git ignores .git/hooks/ entirely when that config is non-empty. The hook file lands on disk, is executable, is correct, and is dead. Invisible failure until someone asks why the post-merge behavior isn't running.
Detection rule before writing any hook
hooks_path=$(git -C "$repo" config --get core.hooksPath)- Empty output: write to
$(git rev-parse --git-common-dir)/hooks/<name>as usual. .husky/_(or any path containinghusky.sh/htrampoline): Husky v9 setup. Write to.husky/<name>; do NOT include the v8-era. "$(dirname "$0")/_/husky.sh"line (v9 prints a deprecation warning if you do).- Unrecognized non-empty value: refuse to write the hook and surface the path to the user. Silent writes to the wrong location waste debug cycles later.
Worktree-safe hook body
.git/hooks/ lives in the common git dir and runs for every worktree of the clone. A hook installed once fires across all trees. Two rules to stay safe:
1. Resolve the invoking worktree's root inside the hook body with git rev-parse --show-toplevel, not a hardcoded path. Hardcoding means the last install-hooks invocation wins for every worktree. 2. Guard the tool invocation with an existence check on the tool's per-tree state dir. Siblings without your tool's setup must no-op, not spawn a failing background process per git op.
#!/bin/sh
root="$(git rev-parse --show-toplevel 2>/dev/null)" || exit 0
[ -d "$root/.my-tool" ] || exit 0
( cd "$root" && my-tool index ) >>"$root/.my-tool/hook.log" 2>&1 &
exit 0Redirect to a log file inside the tool's state dir, not /dev/null — silent failures produce stale state you only notice hours later.
Local Excludes: .git/info/exclude vs .gitignore
Tooling artifacts (local index dirs, hook helpers, per-developer scratch files) belong in .git/info/exclude, NOT in the tracked .gitignore.
.gitignoreis content — tracked, shared with the team, reviewed in PRs. Adding a personal tooling rule there pollutes a shared file. On foreign repos (upstream projects, third-party clones) the rule either rides into a PR by accident or sits as a dirty working tree forever..git/info/excludeis local — untracked, lives in the common git dir, shared across every worktree of the clone. Same syntax and semantics as.gitignorewithout the leakage.
Resolving the path correctly under worktrees
Don't hardcode $repo/.git/info/exclude. In a worktree, .git is a file (gitlink), not a directory. Use git itself:
exclude=$(git -C "$repo" rev-parse --git-path info/exclude)Idempotent append
line="/.my-tool/"
mkdir -p "$(dirname "$exclude")"
grep -qxF "$line" "$exclude" 2>/dev/null || printf '\n# my-tool\n%s\n' "$line" >> "$exclude"grep -qxF matches the exact line with no regex surprises.
When to break the rule
Only when the artifact is genuinely team-shared and belongs in the repo (build outputs used in CI, generated files, vendored dependencies). If in doubt, ask: "would another contributor benefit from this rule?" If no, exclude locally.
Verify
git worktree listshows the new entry.worktreesdirectory confirmed in.gitignore- Dependencies installed in the worktree
- Baseline test suite passes in the worktree
References
- workflow-examples.md - Code review and parallel development workflows
- troubleshooting.md - Common issues, directory structure, how it works
- worktree-manager.sh - The manager script
Troubleshooting & Technical Details
Troubleshooting
"Worktree already exists"
If you see this, the script will ask if you want to switch to it instead.
"Cannot remove worktree: it is the current worktree"
Switch out of the worktree first (to main repo), then cleanup:
cd $(git rev-parse --show-toplevel)
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh cleanupLost in a worktree?
See where you are:
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh list.env files missing in worktree?
If a worktree was created without .env files (e.g., via raw git worktree add), copy them:
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh copy-env feature-nameNavigate back to main:
cd $(git rev-parse --show-toplevel)---
Technical Details
Directory Structure
.worktrees/
├── feature-login/ # Worktree 1
│ ├── .git
│ ├── app/
│ └── ...
├── feature-notifications/ # Worktree 2
│ ├── .git
│ ├── app/
│ └── ...
└── ...
.gitignore (updated to include .worktrees)How It Works
- Uses
git worktree addfor isolated environments - Each worktree has its own branch
- Changes in one worktree don't affect others
- Share git history with main repo
- Can push from any worktree
Performance
- Worktrees are lightweight (just file system links)
- No repository duplication
- Shared git objects for efficiency
- Much faster than cloning or stashing/switching
Workflow Examples
Code Review with Worktree
# Claude Code recognizes you're not on the PR branch
# Offers: "Use worktree for isolated review? (y/n)"
# You respond: yes
# Script runs (copies .env files automatically):
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh create pr-123-feature-name
# You're now in isolated worktree for review with all env vars
cd .worktrees/pr-123-feature-name
# After review, return to main:
cd ../..
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh cleanupParallel Feature Development
# For first feature (copies .env files):
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh create feature-login
# Later, start second feature (also copies .env files):
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh create feature-notifications
# List what you have:
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh list
# Switch between them as needed:
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh switch feature-login
# Return to main and cleanup when done:
cd .
bash ${CLAUDE_PLUGIN_ROOT}/skills/ia-git-worktree/scripts/worktree-manager.sh cleanup#!/bin/bash
# Git Worktree Manager
# Handles creating, listing, switching, and cleaning up Git worktrees
# KISS principle: Simple, interactive, opinionated
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Get repo root
GIT_ROOT=$(git rev-parse --show-toplevel)
WORKTREE_DIR="$GIT_ROOT/.worktrees"
# Ensure .worktrees is in .gitignore
ensure_gitignore() {
if ! grep -q "^\.worktrees$" "$GIT_ROOT/.gitignore" 2>/dev/null; then
echo ".worktrees" >> "$GIT_ROOT/.gitignore"
fi
}
# Copy .env files from main repo to worktree
copy_env_files() {
local worktree_path="$1"
echo -e "${BLUE}Copying environment files...${NC}"
# Find all .env* files in root (excluding .env.example which should be in git)
local env_files=()
for f in "$GIT_ROOT"/.env*; do
if [[ -f "$f" ]]; then
local basename=$(basename "$f")
# Skip .env.example (that's typically committed to git)
if [[ "$basename" != ".env.example" ]]; then
env_files+=("$basename")
fi
fi
done
if [[ ${#env_files[@]} -eq 0 ]]; then
echo -e " ${YELLOW}ℹ️ No .env files found in main repository${NC}"
return
fi
local copied=0
for env_file in "${env_files[@]}"; do
local source="$GIT_ROOT/$env_file"
local dest="$worktree_path/$env_file"
if [[ -f "$dest" ]]; then
echo -e " ${YELLOW}⚠️ $env_file already exists, backing up to ${env_file}.backup${NC}"
cp "$dest" "${dest}.backup"
fi
cp "$source" "$dest"
echo -e " ${GREEN}✓ Copied $env_file${NC}"
copied=$((copied + 1))
done
echo -e " ${GREEN}✓ Copied $copied environment file(s)${NC}"
}
# Create a new worktree
create_worktree() {
local branch_name="$1"
local from_branch="${2:-main}"
if [[ -z "$branch_name" ]]; then
echo -e "${RED}Error: Branch name required${NC}"
exit 1
fi
local worktree_path="$WORKTREE_DIR/$branch_name"
# Check if worktree already exists
if [[ -d "$worktree_path" ]]; then
echo -e "${YELLOW}Worktree already exists at: $worktree_path${NC}"
echo -e "Switch to it instead? (y/n)"
read -r response
if [[ "$response" == "y" ]]; then
switch_worktree "$branch_name"
fi
return
fi
echo -e "${BLUE}Creating worktree: $branch_name${NC}"
echo " From: $from_branch"
echo " Path: $worktree_path"
# Update main branch
echo -e "${BLUE}Updating $from_branch...${NC}"
git checkout "$from_branch"
git pull origin "$from_branch" || true
# Create worktree
mkdir -p "$WORKTREE_DIR"
ensure_gitignore
echo -e "${BLUE}Creating worktree...${NC}"
git worktree add -b "$branch_name" "$worktree_path" "$from_branch"
# Copy environment files
copy_env_files "$worktree_path"
echo -e "${GREEN}✓ Worktree created successfully!${NC}"
echo ""
echo "To switch to this worktree:"
echo -e "${BLUE}cd $worktree_path${NC}"
echo ""
}
# List all worktrees
list_worktrees() {
echo -e "${BLUE}Available worktrees:${NC}"
echo ""
if [[ ! -d "$WORKTREE_DIR" ]]; then
echo -e "${YELLOW}No worktrees found${NC}"
return
fi
local count=0
for worktree_path in "$WORKTREE_DIR"/*; do
if [[ -d "$worktree_path" && -e "$worktree_path/.git" ]]; then
count=$((count + 1))
local worktree_name=$(basename "$worktree_path")
local branch=$(git -C "$worktree_path" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
if [[ "$PWD" == "$worktree_path" ]]; then
echo -e "${GREEN}✓ $worktree_name${NC} (current) → branch: $branch"
else
echo -e " $worktree_name → branch: $branch"
fi
fi
done
if [[ $count -eq 0 ]]; then
echo -e "${YELLOW}No worktrees found${NC}"
else
echo ""
echo -e "${BLUE}Total: $count worktree(s)${NC}"
fi
echo ""
echo -e "${BLUE}Main repository:${NC}"
local main_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
echo " Branch: $main_branch"
echo " Path: $GIT_ROOT"
}
# Switch to a worktree
switch_worktree() {
local worktree_name="$1"
if [[ -z "$worktree_name" ]]; then
list_worktrees
echo -e "${BLUE}Switch to which worktree? (enter name)${NC}"
read -r worktree_name
fi
local worktree_path="$WORKTREE_DIR/$worktree_name"
if [[ ! -d "$worktree_path" ]]; then
echo -e "${RED}Error: Worktree not found: $worktree_name${NC}"
echo ""
list_worktrees
exit 1
fi
echo -e "${GREEN}Switching to worktree: $worktree_name${NC}"
cd "$worktree_path"
echo -e "${BLUE}Now in: $(pwd)${NC}"
}
# Copy env files to an existing worktree (or current directory if in a worktree)
copy_env_to_worktree() {
local worktree_name="$1"
local worktree_path
if [[ -z "$worktree_name" ]]; then
# Check if we're currently in a worktree
local current_dir=$(pwd)
if [[ "$current_dir" == "$WORKTREE_DIR"/* ]]; then
worktree_path="$current_dir"
worktree_name=$(basename "$worktree_path")
echo -e "${BLUE}Detected current worktree: $worktree_name${NC}"
else
echo -e "${YELLOW}Usage: worktree-manager.sh copy-env [worktree-name]${NC}"
echo "Or run from within a worktree to copy to current directory"
list_worktrees
return 1
fi
else
worktree_path="$WORKTREE_DIR/$worktree_name"
if [[ ! -d "$worktree_path" ]]; then
echo -e "${RED}Error: Worktree not found: $worktree_name${NC}"
list_worktrees
return 1
fi
fi
copy_env_files "$worktree_path"
echo ""
}
# Clean up completed worktrees
cleanup_worktrees() {
if [[ ! -d "$WORKTREE_DIR" ]]; then
echo -e "${YELLOW}No worktrees to clean up${NC}"
return
fi
echo -e "${BLUE}Checking for completed worktrees...${NC}"
echo ""
local found=0
local to_remove=()
for worktree_path in "$WORKTREE_DIR"/*; do
if [[ -d "$worktree_path" && -e "$worktree_path/.git" ]]; then
local worktree_name=$(basename "$worktree_path")
# Skip if current worktree
if [[ "$PWD" == "$worktree_path" ]]; then
echo -e "${YELLOW}(skip) $worktree_name - currently active${NC}"
continue
fi
found=$((found + 1))
to_remove+=("$worktree_path")
echo -e "${YELLOW}• $worktree_name${NC}"
fi
done
if [[ $found -eq 0 ]]; then
echo -e "${GREEN}No inactive worktrees to clean up${NC}"
return
fi
echo ""
echo -e "Remove $found worktree(s)? (y/n)"
read -r response
if [[ "$response" != "y" ]]; then
echo -e "${YELLOW}Cleanup cancelled${NC}"
return
fi
echo -e "${BLUE}Cleaning up worktrees...${NC}"
for worktree_path in "${to_remove[@]}"; do
local worktree_name=$(basename "$worktree_path")
git worktree remove "$worktree_path" --force 2>/dev/null || true
echo -e "${GREEN}✓ Removed: $worktree_name${NC}"
done
# Clean up empty directory if nothing left
if [[ -z "$(ls -A "$WORKTREE_DIR" 2>/dev/null)" ]]; then
rmdir "$WORKTREE_DIR" 2>/dev/null || true
fi
echo -e "${GREEN}Cleanup complete!${NC}"
}
# Main command handler
main() {
local command="${1:-list}"
case "$command" in
create)
create_worktree "$2" "$3"
;;
list|ls)
list_worktrees
;;
switch|go)
switch_worktree "$2"
;;
copy-env|env)
copy_env_to_worktree "$2"
;;
cleanup|clean)
cleanup_worktrees
;;
help)
show_help
;;
*)
echo -e "${RED}Unknown command: $command${NC}"
echo ""
show_help
exit 1
;;
esac
}
show_help() {
cat << EOF
Git Worktree Manager
Usage: worktree-manager.sh <command> [options]
Commands:
create <branch-name> [from-branch] Create new worktree (copies .env files automatically)
(from-branch defaults to main)
list | ls List all worktrees
switch | go [name] Switch to worktree
copy-env | env [name] Copy .env files from main repo to worktree
(if name omitted, uses current worktree)
cleanup | clean Clean up inactive worktrees
help Show this help message
Environment Files:
- Automatically copies .env, .env.local, .env.test, etc. on create
- Skips .env.example (should be in git)
- Creates .backup files if destination already exists
- Use 'copy-env' to refresh env files after main repo changes
Examples:
worktree-manager.sh create feature-login
worktree-manager.sh create feature-auth develop
worktree-manager.sh switch feature-login
worktree-manager.sh copy-env feature-login
worktree-manager.sh copy-env # copies to current worktree
worktree-manager.sh cleanup
worktree-manager.sh list
EOF
}
# Run
main "$@"
ia-git-worktree Specification
Intent
ia-git-worktree is a tool-class skill (a narrow utility scoped to a single capability). Manage Git worktrees for isolated parallel development. Use when creating, listing, switching, or cleaning up git worktrees, or when needing isolated branches for concurrent reviews or feature work.
Scope
In scope:
- Behaviors described in
SKILL.mdand routed via the should_trigger phrasings indistillery/tests/fixtures/triggers/ia-git-worktree.jsonl. - Updates to runtime behavior, structure, trigger precision, references, and validation.
Out of scope:
- Acting as the runtime instructions themselves (those live in
SKILL.md). - Trigger phrasings already covered by adjacent
ia-*skills (validate-pluginflags >70% description overlap as DUPLICATE_TRIGGER). - <!-- to fill in: domain-specific exclusions when the skill drifts -->
Trigger Context
- Class:
tool - Hook regex:
plugins/whetstone/hooks/skill-patterns.sh->SKILL_PATTERNS[ia-git-worktree] - Common requests (from fixture should_trigger):
- "create a worktree for the feature branch so I can review in parallel"
- "set up parallel development branches using worktrees"
- "set up an isolated worktree to review this PR"
- Should not trigger for (from fixture should_not_trigger):
- "write an Eloquent model for the invoices table"
- "add rate limiting to the public API"
- "merge the PR into main"
Source And Evidence Model
Authoritative sources:
SKILL.md-- runtime instructions and reference routing.references/*.md-- bundled supplementary content (2 file(s)).distillery/tests/fixtures/triggers/ia-git-worktree.jsonl-- positive and negative trigger phrasings under regression test.plugins/whetstone/hooks/skill-patterns.sh-- regex pattern that fires this skill.distillery/.eval-data/ia-git-worktree/-- harvested session examples (when present).
Data that must not be stored in this skill or its references:
- Secrets, credentials, tokens.
- Machine-specific filesystem paths (
/home/...,/Users/...,~/ai/...). The validator (MACHINE_PATH_LEAK) flags these as HIGH. - Private URLs, customer data, or unredacted personal information.
Coverage matrix
| Dimension | Status | Evidence |
|---|---|---|
| Trigger fixtures | complete | distillery/tests/fixtures/triggers/ia-git-worktree.jsonl (>=5 should_trigger, >=5 should_not_trigger) |
| Hook regex pattern | complete | plugins/whetstone/hooks/skill-patterns.sh (SKILL_PATTERNS[ia-git-worktree]) |
| Reference architecture | complete | 2 file(s) under references/ |
| Real-usage signal | <!-- populated by harvest-sessions when sessions exist --> | distillery/.eval-data/ia-git-worktree/ (created by harvest-sessions) |
Evaluation
Lightweight (run on every change):
python3 distillery/scripts/distiller.py validate-plugin --component ia-git-worktree
python3 distillery/scripts/distiller.py test-triggers --skill ia-git-worktreeDeeper (when behavior risk warrants):
python3 distillery/scripts/distiller.py dspy-eval ia-git-worktree
python3 distillery/scripts/distiller.py diagnose-negatives ia-git-worktreeAcceptance gates:
validate-plugin --component ia-git-worktreereturns 0 HIGH findings.test-triggers --skill ia-git-worktreereturns F1 = 1.0 with floors of 5 should_trigger and 5 should_not_trigger.- For dspy-eval, the composite score does not regress against the most recent saved baseline (see
distillery/.eval-data/ia-git-worktree/history.json).
Known Limitations
<!-- to fill in over time as drift surfaces. Default rule: any time diagnose-negatives surfaces a recurring failure pattern, document it here so future maintainers understand the trade-off the current implementation accepts. -->
Maintenance Notes
- Update
SKILL.mdwhen the runtime workflow, branch conditions, or output contract changes. - Update this
SPEC.mdwhen intent, scope, evidence model, evaluation gates, or maintenance expectations change. - Update the trigger fixture when adding new positive phrasings, removing stale ones, or expanding scope (the 5/5 floor is a hard validator gate).
- Update the hook regex in
skill-patterns.shwhenever fixture positives expose a missed phrasing; verify F1 = 1.0 witheval-triggersbefore committing. - Run the full release pipeline via
/release-- never bump versions or update CHANGELOG.md from a per-skill edit.