diff --git a/.agents/skills/worktrees-pnpm/SKILL.md b/.agents/skills/worktrees-pnpm/SKILL.md index 41a98b05..f0931b05 100644 --- a/.agents/skills/worktrees-pnpm/SKILL.md +++ b/.agents/skills/worktrees-pnpm/SKILL.md @@ -14,12 +14,22 @@ problem in this repo. **`git worktree add` is not finished until `pnpm install` has run inside the new worktree.** ```bash -git fetch origin main +git fetch origin +refs/heads/main:refs/remotes/origin/main # explicit refspec; see the hook for why git worktree add -b .agents/.worktrees/ origin/main # or an existing , without -b cd .agents/.worktrees/ -pnpm install # ← not optional +git rev-list --count HEAD..origin/main # anything above 0: git rebase origin/main +pnpm install # ← not optional, and after the rebase, which can change the lockfile ``` +**The base check applies whoever made the worktree.** The `WorktreeCreate` hook fetches before +branching, but a worktree made by hand or by another tool is cut from whatever its maker had +locally. Stepping into one you did not create, run the fetch and the `rev-list` check above first, +before reading code or installing. + +Branch from `origin/main`, never the local `main`, which is only as fresh as the main checkout's +last pull. A stale tree also carries stale conventions, including this one, so the check cannot +wait until you have read the docs it would correct. + Worktrees go in **`.agents/.worktrees/`**, gitignored except for a tracked `.gitkeep`, so the directory exists in every clone. This is the location every agent harness shares, not a Claude Code one, so a worktree made by hand, by Claude Code, or by another tool lands in the same place. In Claude Code, the `WorktreeCreate` / `WorktreeRemove` hooks configured in `.claude/settings.json` (scripts in this skill's `scripts/` directory) do the placement, which would otherwise nest worktrees at `.claude/worktrees/`. A harness without those hooks follows the manual steps above, and the result is identical. `ls .agents/.worktrees/` answers "what worktrees do I have?" at a glance. **Two older locations are still ignored, and new worktrees never go there.** `worktrees/` at the repo root was the previous standard, and `.claude/worktrees/` is Claude Code's default. Both keep their ignore entries so that worktrees already living there do not surface as untracked files or get linted, until their work is done. diff --git a/AGENTS.md b/AGENTS.md index dec62000..eb048c42 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -91,14 +91,16 @@ Both flags can be passed in one call. See also **Stacked PRs → Other gotchas** **Use the hooks and skills that are available, and do not depend on them.** In Claude Code, the `WorktreeCreate`/`WorktreeRemove` hooks in `.claude/settings.json` do the placement, and `.agents/skills/` (which `.claude/skills` links to) holds the skills, `worktrees-pnpm` among them. Another harness may have neither. If no hook places the worktree for you, do it by hand. The result must be the same: a fresh branch cut from `origin`'s default branch as just fetched, never from the main checkout's `HEAD`: ```bash -git fetch origin main +git fetch origin +refs/heads/main:refs/remotes/origin/main git worktree add -b .agents/.worktrees/ origin/main cd .agents/.worktrees/ && pnpm install ``` +The refspec is spelled out because a bare `git fetch origin main` only updates `origin/main` when `remote.origin.fetch` covers it, which a single-branch clone of another branch does not. Branch from `origin/main`, never the local `main`: the local branch is whatever the main checkout was last pulled to. + The three rules that cause the most damage when missed: -- **A worktree starts from the latest `origin/main`, checked before any work begins.** Run `git fetch origin`, then `git rev-list --count HEAD..origin/main`. Anything above `0` means the worktree is behind: rebase onto `origin/main` (`git rebase origin/main`) before reading code, making changes, or running `pnpm install` (a rebase can change the lockfile), unless the work was explicitly asked to start from another branch or commit. The `WorktreeCreate` hook already branches from a freshly fetched `origin/main`, but a worktree made any other way (by hand, by another tool, or by a session board) is cut from whatever the main checkout was last pulled to. One started 68 commits behind `main`, and nothing flagged it: stale code reads exactly like current code. +- **A worktree starts from the latest `origin/main`, checked before any work begins.** Run `git fetch origin +refs/heads/main:refs/remotes/origin/main` (the explicit refspec, for the reason above), then `git rev-list --count HEAD..origin/main`. Anything above `0` means the worktree is behind: rebase onto `origin/main` (`git rebase origin/main`) before reading code, making changes, or running `pnpm install` (a rebase can change the lockfile), unless the work was explicitly asked to start from another branch or commit. The `WorktreeCreate` hook already branches from a freshly fetched `origin/main`, but a worktree made any other way (by hand, by another tool, or by a session board) is cut from whatever the main checkout was last pulled to. One started 68 commits behind `main`, and nothing flagged it: stale code reads exactly like current code. Another started 156 behind and never saw this rule at all, because the rule landed after its base: **a stale tree carries stale conventions**, so nothing in the repo can warn a checkout that is already behind. That is why the fix belongs in whatever creates the worktree (the hook, a session board, your own hands), and why this check comes before reading anything else here. - **A worktree gets its own empty `node_modules`.** `git worktree add` is not finished until `pnpm install` has run inside it. Without that, `git commit` fails in `lint-staged` (no `prettier`/`eslint`), and every `pnpm` script fails. A missing `prettier` here once cost an agent an hour of dead-end workarounds. There is no `pnpm worktree` command; `git worktree` is the tool. - **NEVER point an agent at the main repo path** (e.g. `/Users//code/taskless/skills`). It will `cd` there and run git commands and edits in the **main** checkout, defeating isolation. It can create and check out a branch in your working tree, silently switching your session off its own branch. Tell the agent to work in **its assigned worktree** (`$PWD`) and pass only relative paths plus GitHub identifiers (`owner/repo`).