Create New Worktree - pi adaptation
Create a new git worktree with:
- serial branch/bootstrap setup using the bundled package scripts
- asset wiring from
.worktree.ymlor bounded inference - shared worker-wave environment setup through
subagent - serial
direnv allow, commit, and final summary
Current shipped boundary
This pi wrapper now ships, but it stays inside the bounded IT003 contract:
- branch/bootstrap is handled directly in this skill; do not try to invoke
ac-git-branchfrom inside the skill - the shared
pi-compatworker-wave surface is used only for the environment-setup wave .worktree.ymldiscovery, asset wiring,direnv allow, final commit, and final summary stay coordinator-owned- if user input is required, only the coordinator uses
AskUserQuestion; workers stay non-interactive
Arguments
worktree_name(required): base name for the branch and worktreeassets_path(optional): explicit path to shared assets to mirror into the worktree
Required references
Read these when needed:
cookbook/setup.mdwhen no.worktree.ymlexists or the user wants setup help../../assets/scripts/spec-resolver.shfor serial branch/spec bootstrapnode_modules/@agentic-config/pi-compat/assets/orchestration/protocol/worker.mdfor every environment workernode_modules/@agentic-config/pi-compat/assets/orchestration/tools/write-result.jsnode_modules/@agentic-config/pi-compat/assets/orchestration/tools/summarize-results.js
Pre-flight checks
Verify repo root:
REPO_ROOT=$(git rev-parse --show-toplevel)Verify the main checkout is clean before branch/bootstrap work:
git -C "$REPO_ROOT" status --short- If dirty: STOP and ask the user to clean or stash changes first.
Validate
worktree_name:- required
- allow only letters, numbers,
-, and_ - reject spaces and shell-special characters
Generate the unique branch/worktree name:
UUID_PREFIX=$(uuidgen | cut -c1-6 | tr 'A-Z' 'a-z') FULL_NAME="$UUID_PREFIX-<worktree_name>" WORKTREE_PATH="$REPO_ROOT/trees/$FULL_NAME"Check for existing worktree path:
test -e "$WORKTREE_PATH"- If it already exists: STOP and report the path.
Check for existing branch:
git -C "$REPO_ROOT" show-ref --verify --quiet "refs/heads/$FULL_NAME"- If missing: continue with serial bootstrap.
- If present: use
AskUserQuestionto ask whether to reuse the existing branch or abort. - On reuse: skip the branch-creation step and assume the original bootstrap commit already exists.
Check for live
.worktree.ymlfiles in the main checkout only:find "$REPO_ROOT" \ \( -path "$REPO_ROOT/.git" -o -path "$REPO_ROOT/.git/*" \ -o -path "$REPO_ROOT/trees" -o -path "$REPO_ROOT/trees/*" \ -o -path '*/templates' -o -path '*/templates/*' \ -o -path '*/example' -o -path '*/example/*' \ -o -path '*/examples' -o -path '*/examples/*' \ -o -path '*/fixture' -o -path '*/fixture/*' \ -o -path '*/fixtures' -o -path '*/fixtures/*' \ -o -path '*/test' -o -path '*/test/*' \ -o -path '*/tests' -o -path '*/tests/*' \) -prune -o \ -name ".worktree.yml" -type f -print- Treat template/example/fixture/test copies as non-live examples, not active worktree configs.
- If at least one live config exists in the main checkout: use config-driven mode.
- If none exist: use
AskUserQuestion:- explain that
.worktree.ymlmakes asset/environment setup deterministic - offer to create one now via
cookbook/setup.md - if the user says yes, read
cookbook/setup.md, create the file, then continue in config-driven mode - if the user says no, continue in inference mode
- explain that
If
assets_pathwas provided, validate it before continuing:test -d "$ASSETS_PATH"- If the explicit path does not exist: STOP.
Execution overview
- Serial branch/bootstrap
- Create the worktree
- Apply assets from
.worktree.ymlor inference - Build ordered environment targets
- Run one bounded environment worker wave through
subagent - Run
direnv allowserially - Commit setup changes if any
- Report the final summary, including warnings
Step 1: Serial branch/bootstrap
When the branch does not already exist, inline the shipped ac-git-branch flow with the bundled helper script:
source "../../assets/scripts/spec-resolver.sh"
git -C "$REPO_ROOT" checkout -b "$FULL_NAME"
RELATIVE_PATH="$(date +%Y)/$(date +%m)/$FULL_NAME/000-backlog.md"
SPEC_FILE=$(resolve_spec_path "$RELATIVE_PATH")
SPEC_DIR="${SPEC_FILE%/*}"
: > "$SPEC_FILE"
commit_spec_changes "$SPEC_FILE" "CREATE" "000" "backlog"
Record for the final summary:
FULL_NAMESPEC_FILE- whether the branch was newly created or reused
Why this stays serial and skill-owned:
- the shipped pi branch wrapper already proves this is a bounded bash flow
- it does not require generic skill-to-skill invocation
- the commit must exist before
git worktree addso the backlog file appears in the new worktree
Step 2: Create the worktree
mkdir -p "$REPO_ROOT/trees"
git -C "$REPO_ROOT" worktree add "$WORKTREE_PATH" "$FULL_NAME"
After creation, verify:
git -C "$WORKTREE_PATH" rev-parse --show-toplevel
git -C "$WORKTREE_PATH" rev-parse --abbrev-ref HEAD
Step 3: Discover and apply assets
Keep this step in the coordinator.
Mode A: explicit assets_path
Use the provided path as the root asset source.
Mode B: .worktree.yml
When config files exist, process every live .worktree.yml inside the new worktree, excluding template/example/fixture/test directories.
For each config file:
- Determine its directory.
- Resolve
assets.sourcerelative to that config directory, not the repo root. - Apply
assets.symlinkentries as symlinks. - Apply
assets.copyentries as copies. - Apply
root_symlinksfrom the main checkout root, not fromassets.source. - Record every applied action for the final summary.
Use yq when available. Otherwise, use a short python3 snippet with yaml.safe_load. If neither yq nor Python YAML parsing is available, STOP and explain that the config cannot be applied honestly.
Representative structure:
for CONFIG_FILE in $(find "$WORKTREE_PATH" \
\( -path '*/templates' -o -path '*/templates/*' \
-o -path '*/example' -o -path '*/example/*' \
-o -path '*/examples' -o -path '*/examples/*' \
-o -path '*/fixture' -o -path '*/fixture/*' \
-o -path '*/fixtures' -o -path '*/fixtures/*' \
-o -path '*/test' -o -path '*/test/*' \
-o -path '*/tests' -o -path '*/tests/*' \) -prune -o \
-name ".worktree.yml" -type f -print); do
CONFIG_DIR=$(dirname "$CONFIG_FILE")
CONFIG_RELATIVE=$(realpath --relative-to="$WORKTREE_PATH" "$CONFIG_DIR")
# Resolve assets.source relative to CONFIG_DIR.
# Apply copy/symlink actions into CONFIG_DIR.
# Resolve root_symlinks from the main checkout root.
done
Mode C: inference
If no .worktree.yml exists and no explicit assets_path was provided, infer assets in this order:
sibling assets directories:
REPO_NAME=$(basename "$REPO_ROOT") REPO_PARENT=$(dirname "$REPO_ROOT") for candidate in \ "$REPO_PARENT/${REPO_NAME}-assets" \ "$REPO_PARENT/assets" \ "$REPO_PARENT/.${REPO_NAME}-assets"; do test -d "$candidate" && echo "$candidate" doneignored local assets:
git -C "$REPO_ROOT" ls-files --others --ignored --exclude-standard --directory
Inference rules:
- copy
.env,.env.local, andconfig*.local* - symlink large shared directories such as
data/,inputs/,fixtures/,models/,weights/, andcache/ - if an explicitly requested asset source is missing: STOP
- if an inferred asset candidate is missing: warn and continue
Step 4: Build the ordered environment target list
Create one ordered target list for the environment wave.
Preferred source of truth:
.worktree.ymlenvironmentsentries, preserving config order- otherwise infer from project markers inside the worktree
Marker-based inference:
pyproject.tomlorrequirements.txt->pythonpackage.json->nodeCargo.toml->rustgo.mod->goGemfile->ruby
For each target, capture:
worker_id(stable ordered id such as01-backend)- absolute target path
- detected environment type
- report path under
tmp/worktree/$FULL_NAME/reports/ - result path under
tmp/worktree/$FULL_NAME/results/
Create scratch directories outside the worktree so they are not committed accidentally:
RUN_ROOT="$REPO_ROOT/tmp/worktree/$FULL_NAME"
mkdir -p "$RUN_ROOT/reports" "$RUN_ROOT/results"
If no environment targets are detected, continue without a worker wave and report that no environment bootstrap was required.
Step 5: Run the shared environment worker wave
Use exactly one synchronous subagent wave for the environment setup step.
- Use
subagent.parallelwhen multiple targets are independent. - Use a single worker only when exactly one target exists.
- Prefer the
workeragent. - Workers must stay non-interactive.
- Workers must not launch nested subagents.
- Workers must write their report first, then call
write-result.js.
Worker contract
Every worker task must explicitly tell the worker to:
- read
node_modules/@agentic-config/pi-compat/assets/orchestration/protocol/worker.md - touch only its assigned target path
- write a detailed markdown report to the assigned report path
- call:
node node_modules/@agentic-config/pi-compat/assets/orchestration/tools/write-result.js \ --result-path "$RESULT_PATH" \ --worker-id "$WORKER_ID" \ --status "$STATUS" \ --summary "$SUMMARY" \ --report-path "$REPORT_PATH" \ --target "$TARGET_PATH" - return a concise completion message after the result file is written
Worker responsibilities by environment type
Python
- create
.venvif missing - create/update
.envrcwith:dotenv_if_exists .env source .venv/bin/activate - if a worktree-root
.envexists and the target is nested, symlink.envinto the target when that is appropriate for the project layout - install dependencies from
requirements.txt,requirements.dev.txt, and/orpyproject.tomlas applicable
Node
- create/update
.envrcwith:dotenv_if_exists .env PATH_add node_modules/.bin - install dependencies using the repo's package-manager signal:
pnpm-lock.yaml->pnpm installyarn.lock->yarn install- otherwise ->
npm install
Rust / Go / Ruby
- create a minimal
.envrcwhen the project needs one - run the standard bootstrap command if the toolchain is present
- if the required toolchain is missing, return
warnwith a clear summary and manual next step
Wave result policy
For worktree, warnings are allowed when setup completed but produced a non-fatal issue.
Failures and missing result files are not allowed.
After the wave finishes, summarize the ordered results:
node node_modules/@agentic-config/pi-compat/assets/orchestration/tools/summarize-results.js \
--result "$RUN_ROOT/results/01-...json" \
--result "$RUN_ROOT/results/02-...json" \
--fail-on-missing \
--fail-on-status fail \
--format json
Coordinator rules after summarization:
- if the summary command exits non-zero: STOP and surface the failing or missing workers
- if only
warnentries exist: continue, but include the warnings in the final summary - if a worker produced a warning you do not understand, read that worker's report before continuing
Step 6: Run direnv allow serially
Keep this coordinator-owned.
For each environment target path that now contains .envrc:
if DIRENV_BIN=$(command -v direnv); then
(cd "$TARGET_PATH" && "$DIRENV_BIN" allow)
else
echo "WARN: direnv not installed; skipped allow for $TARGET_PATH"
fi
Treat missing direnv as a warning, not a failure.
Step 7: Commit setup changes in the worktree
Leave the new worktree in a clean committed state whenever there are tracked changes.
cd "$WORKTREE_PATH"
git add -A
git status --short
if ! git diff --cached --quiet; then
git commit -m "chore(worktree): setup $FULL_NAME
- Configure asset links and copies
- Bootstrap development environments
- Add direnv configuration"
fi
Do not commit transient scratch state from tmp/worktree/...; that directory lives outside the worktree root.
Step 8: Final summary
Report:
FULL_NAME- worktree path
- branch name
- resolved spec path or reused-branch note
- applied asset actions
- environment targets and their statuses
- whether
direnv allowsucceeded or was skipped - whether a setup commit was created
- every warning that still needs user attention
Error handling
| Condition | Action |
|---|---|
| main checkout is dirty before bootstrap | STOP |
| worktree path already exists | STOP |
| branch already exists | Ask user whether to reuse or abort |
explicit assets_path missing |
STOP |
.worktree.yml exists but cannot be parsed honestly |
STOP |
| inferred asset candidate missing | warn and continue |
| worker result missing | STOP |
worker status fail |
STOP |
worker status warn |
continue and report explicitly |
direnv missing |
warn and continue |
Path resolution rule for .worktree.yml
This is the most important correctness rule in the asset step.
Resolve every .worktree.yml path relative to the config file's directory, not the repo root and not the current shell directory.
Correct pattern:
CONFIG_DIR=$(dirname "$CONFIG_FILE")
ASSETS_SOURCE=$(cd "$CONFIG_DIR" && realpath "$SOURCE_VALUE")
Wrong pattern:
ASSETS_SOURCE=$(realpath "$SOURCE_VALUE")
The wrong pattern breaks monorepos with nested .worktree.yml files.