From 5fa5fa4a351c5f591701d5ecdca4fcab5916e4eb Mon Sep 17 00:00:00 2001
From: Ken Allred
Date: Sun, 31 May 2026 09:58:38 -0600
Subject: [PATCH 1/4] fix: place agent worktrees consistently under
/.worktrees/
setup-agent-worktree.sh created worktrees as repo siblings
(../-), which scattered them outside the project and
diverged from where other tooling expects them. Standardize on a single
project-local location, /.worktrees/, matching the
superpowers using-git-worktrees convention.
- setup-agent-worktree.sh: compute worktree path under .worktrees/ and
ensure .worktrees/ is gitignored before creating the worktree so a
worktree's checkout is never accidentally committed
- gitignore.ts: add .worktrees/ to the scaffold-managed block so
downstream-scaffolded projects ignore it automatically
- git-workflow.md meta-prompt: instruct downstream-generated worktree
scripts to use the .worktrees/ convention + gitignore guard
- docs/git-workflow.md, worktree-management knowledge, multi-agent guide
(md + regenerated html, cite lines re-pointed): document the new path
- tests: assert new location, no sibling dir, and .worktrees/ ignored
Co-Authored-By: Claude Opus 4.8
---
content/guides/multi-agent/index.html | 31 ++++++++++---------
content/guides/multi-agent/index.md | 31 ++++++++++---------
.../execution/worktree-management.md | 8 ++---
content/pipeline/environment/git-workflow.md | 10 ++++--
docs/git-workflow.md | 16 +++++-----
scripts/setup-agent-worktree.sh | 20 ++++++++++--
src/project/gitignore.test.ts | 1 +
src/project/gitignore.ts | 4 +++
tests/setup-agent-worktree.bats | 26 ++++++++++++----
9 files changed, 96 insertions(+), 51 deletions(-)
diff --git a/content/guides/multi-agent/index.html b/content/guides/multi-agent/index.html
index 75cbed651..250246250 100644
--- a/content/guides/multi-agent/index.html
+++ b/content/guides/multi-agent/index.html
@@ -1380,11 +1380,11 @@ Parallel Agents & Worktrees
A git worktree solves this: it is an independent working directory backed by
the same .git repository. Each agent gets its own files and its own checked-out
branch, but commits, refs and history are shared. The layout is one primary
-checkout plus one sibling directory per agent:
-~/projects/
-├── scaffold/ # primary checkout (you work here)
-├── scaffold-alpha/ # worktree for agent "alpha"
-└── scaffold-beta/ # worktree for agent "beta"
+checkout with all agent worktrees project-local under .worktrees/:
+scaffold/ # primary checkout (you work here)
+└── .worktrees/ # agent worktrees (gitignored)
+ ├── alpha/ # worktree for agent "alpha"
+ └── beta/ # worktree for agent "beta"
So worktrees give you filesystem isolation with a shared object store:
agents never overwrite each other's working files, but a PR merged from one
@@ -1398,20 +1398,21 @@
Setup — setup-agent-worktree.shalpha, it:
- Normalizes the name to a lowercase, hyphenated, alphanumeric slug (so
-
Agent_1 becomes agent-1), then derives the worktree directory as a
-sibling of the primary repo: ../<repo-name>-<slug>.
+Agent_1 becomes agent-1), then derives the worktree directory project-local
+under the primary repo: .worktrees/<slug>. It also ensures .worktrees/ is
+gitignored so the worktree's checkout is never accidentally committed.
- Creates the workspace branch
<slug>-workspace if it does not already
-exist scripts/setup-agent-worktree.sh:40, then adds the worktree on
-that branch scripts/setup-agent-worktree.sh:44. Re-running for an
+exist scripts/setup-agent-worktree.sh:57, then adds the worktree on
+that branch scripts/setup-agent-worktree.sh:60. Re-running for an
existing worktree is a safe no-op.
- Writes
.scaffold/identity.json — the stable identity that build
observability stamps onto every event this worktree records. The script
-creates .scaffold/ scripts/setup-agent-worktree.sh:52 and, only if no
+creates .scaffold/ scripts/setup-agent-worktree.sh:68 and, only if no
identity file exists yet, writes worktree_id (a UUID), worktree_label
(the agent slug), and created_at
-scripts/setup-agent-worktree.sh:71.
+scripts/setup-agent-worktree.sh:87.
- Re-syncs Beads with a fail-soft
bd doctor --fix when a .beads/
-directory is present scripts/setup-agent-worktree.sh:88, reconciling the
+directory is present scripts/setup-agent-worktree.sh:104, reconciling the
worktree's Beads git hooks and project config against the installed bd
version. (Beads DB sharing is automatic — worktrees discover the main repo's
task DB via git's common directory, so there is nothing for bd doctor to
@@ -1467,8 +1468,8 @@ Working in parallel
Each agent otherwise follows the standard PR workflow from its own worktree:
branch, commit, push, gh pr create, wait for CI, squash-merge. The shared
-object store means a merge from scaffold-alpha is on main for everyone the
-moment it lands.
+object store means a merge from agent alpha's worktree is on main for
+everyone the moment it lands.
Teardown & harvest
When an agent's work is merged, retire its worktree. The single command for this
is scripts/teardown-agent-worktree.sh <worktree-path>, and the order of
@@ -1529,7 +1530,7 @@ Resuming after a break
morning — does not mean re-running setup. The worktree and its
identity.json persist on disk. Instead:
-- Return to the agent's worktree directory (
../<repo>-<agent>).
+- Return to the agent's worktree directory (
.worktrees/<agent>).
- Run
multi-agent-resume <agent-name> (or single-agent-resume for the
non-worktree case). It verifies the worktree environment, syncs with main,
reconciles task status against any PRs merged while you were away, and
diff --git a/content/guides/multi-agent/index.md b/content/guides/multi-agent/index.md
index 623813b08..ce80d22b0 100644
--- a/content/guides/multi-agent/index.md
+++ b/content/guides/multi-agent/index.md
@@ -18,13 +18,13 @@ test run.
A **git worktree** solves this: it is an independent working directory backed by
the *same* `.git` repository. Each agent gets its own files and its own checked-out
branch, but commits, refs and history are shared. The layout is one primary
-checkout plus one sibling directory per agent:
+checkout with all agent worktrees project-local under `.worktrees/`:
```text
-~/projects/
-├── scaffold/ # primary checkout (you work here)
-├── scaffold-alpha/ # worktree for agent "alpha"
-└── scaffold-beta/ # worktree for agent "beta"
+scaffold/ # primary checkout (you work here)
+└── .worktrees/ # agent worktrees (gitignored)
+ ├── alpha/ # worktree for agent "alpha"
+ └── beta/ # worktree for agent "beta"
```
So worktrees give you **filesystem isolation with a shared object store**:
@@ -44,20 +44,21 @@ branch.
one parallel agent. Given a name like `alpha`, it:
1. **Normalizes the name** to a lowercase, hyphenated, alphanumeric slug (so
- `Agent_1` becomes `agent-1`), then derives the worktree directory as a
- *sibling* of the primary repo: `../-`.
+ `Agent_1` becomes `agent-1`), then derives the worktree directory project-local
+ under the primary repo: `.worktrees/`. It also ensures `.worktrees/` is
+ gitignored so the worktree's checkout is never accidentally committed.
2. **Creates the workspace branch** `-workspace` if it does not already
- exist :cite[scripts/setup-agent-worktree.sh:40], then adds the worktree on
- that branch :cite[scripts/setup-agent-worktree.sh:44]. Re-running for an
+ exist :cite[scripts/setup-agent-worktree.sh:57], then adds the worktree on
+ that branch :cite[scripts/setup-agent-worktree.sh:60]. Re-running for an
existing worktree is a safe no-op.
3. **Writes `.scaffold/identity.json`** — the stable identity that build
observability stamps onto every event this worktree records. The script
- creates `.scaffold/` :cite[scripts/setup-agent-worktree.sh:52] and, only if no
+ creates `.scaffold/` :cite[scripts/setup-agent-worktree.sh:68] and, only if no
identity file exists yet, writes `worktree_id` (a UUID), `worktree_label`
(the agent slug), and `created_at`
- :cite[scripts/setup-agent-worktree.sh:71].
+ :cite[scripts/setup-agent-worktree.sh:87].
4. **Re-syncs Beads** with a fail-soft `bd doctor --fix` when a `.beads/`
- directory is present :cite[scripts/setup-agent-worktree.sh:88], reconciling the
+ directory is present :cite[scripts/setup-agent-worktree.sh:104], reconciling the
worktree's Beads git hooks and project config against the installed `bd`
version. (Beads DB sharing is automatic — worktrees discover the main repo's
task DB via git's common directory, so there is nothing for `bd doctor` to
@@ -148,8 +149,8 @@ footprint small and its branches short. The conflict-prevention rules from
Each agent otherwise follows the standard PR workflow from its own worktree:
branch, commit, push, `gh pr create`, wait for CI, squash-merge. The shared
-object store means a merge from `scaffold-alpha` is on `main` for everyone the
-moment it lands.
+object store means a merge from agent `alpha`'s worktree is on `main` for
+everyone the moment it lands.
## Teardown & harvest
@@ -225,7 +226,7 @@ Coming back to parallel work — a context reset, a paused session, the next
morning — does **not** mean re-running setup. The worktree and its
`identity.json` persist on disk. Instead:
-1. Return to the agent's worktree directory (`../-`).
+1. Return to the agent's worktree directory (`.worktrees/`).
2. Run **`multi-agent-resume `** (or `single-agent-resume` for the
non-worktree case). It verifies the worktree environment, syncs with `main`,
reconciles task status against any PRs merged while you were away, and
diff --git a/content/knowledge/execution/worktree-management.md b/content/knowledge/execution/worktree-management.md
index e5bbef75e..9f3be5c58 100644
--- a/content/knowledge/execution/worktree-management.md
+++ b/content/knowledge/execution/worktree-management.md
@@ -17,7 +17,7 @@ Expert knowledge for managing git worktrees to enable parallel multi-agent execu
### Setup
-Use `scripts/setup-agent-worktree.sh ` to create a worktree at `../-/`. Each agent gets its own isolated working directory and workspace branch.
+Use `scripts/setup-agent-worktree.sh ` to create a worktree at `.worktrees//` (project-local). Each agent gets its own isolated working directory and workspace branch.
### Branching Conventions
@@ -40,12 +40,12 @@ After all agents finish, remove worktrees and prune stale references. Delete mer
scripts/setup-agent-worktree.sh agent-1
# This creates:
-# ../-agent-1/ (working directory)
+# .worktrees/agent-1/ (working directory, project-local)
# Branch: agent-1-workspace (workspace branch)
```
**What the setup script does:**
-1. Creates a new worktree directory adjacent to the main repo
+1. Creates a new worktree directory project-local under `.worktrees/`
2. Creates a workspace branch for the agent
3. Sets up the working directory with a clean state
4. Installs dependencies if a package manager is detected
@@ -154,7 +154,7 @@ git rebase origin/main
```bash
# From the main repository (not from inside the worktree)
-git worktree remove ../-agent-1
+git worktree remove .worktrees/agent-1
```
**Pruning stale worktree references:**
diff --git a/content/pipeline/environment/git-workflow.md b/content/pipeline/environment/git-workflow.md
index c81275a8c..ff74e4305 100644
--- a/content/pipeline/environment/git-workflow.md
+++ b/content/pipeline/environment/git-workflow.md
@@ -26,7 +26,11 @@ parallel agents, CI pipeline, branch protection, and conflict prevention rules.
- docs/git-workflow.md — branching strategy, commit standards, rebase strategy,
PR workflow (8 sub-steps), task closure, agent crash recovery, branch protection,
conflict prevention, and worktree documentation
-- scripts/setup-agent-worktree.sh — permanent worktree creation script
+- scripts/setup-agent-worktree.sh — permanent worktree creation script. Create
+ worktrees project-local at `/.worktrees/` (a single,
+ consistent location — never as repo siblings like `../-`). The
+ script must ensure `.worktrees/` is gitignored before creating the worktree so
+ the worktree's checkout is never accidentally committed.
- .github/workflows/ci.yml — CI workflow with lint and test jobs
- .github/pull_request_template.md — PR template with task ID format
- CLAUDE.md updated with Committing/PR Workflow, Task Closure, Parallel Sessions,
@@ -37,7 +41,9 @@ parallel agents, CI pipeline, branch protection, and conflict prevention rules.
- (mvp) Commit format is consistent (Beads: [bd-] type(scope): desc. Non-Beads: type(scope): desc)
- (deep) PR workflow includes all 8 sub-steps (commit, AI review, rebase, push, create,
auto-merge with --delete-branch, watch CI, confirm merge)
-- (deep) Worktree script creates permanent worktrees with workspace branches
+- (deep) Worktree script creates permanent worktrees with workspace branches at
+ the project-local path `/.worktrees/` and ensures
+ `.worktrees/` is gitignored
- (deep) If Beads: BEADS_ACTOR environment variable documented for agent identity
- (deep) CI workflow job name matches branch protection context
- (mvp) Branch cleanup documented for both single-agent and worktree-agent variants
diff --git a/docs/git-workflow.md b/docs/git-workflow.md
index 361b0973f..6868dcc06 100644
--- a/docs/git-workflow.md
+++ b/docs/git-workflow.md
@@ -149,13 +149,13 @@ Quality gates run both locally (`make check-all`) and in CI. The CI workflow is
## 7. Advanced: Parallel Agents (Worktrees)
-For parallel development, each agent gets a git worktree — an independent working directory sharing the same `.git` repository.
+For parallel development, each agent gets a git worktree — an independent working directory sharing the same `.git` repository. Worktrees live project-local under `.worktrees/` for a single, consistent location:
```
-~/projects/
-├── scaffold/ # Main repo
-├── scaffold-agent-1/ # Worktree for agent 1
-└── scaffold-agent-2/ # Worktree for agent 2
+scaffold/ # Main repo
+└── .worktrees/ # Agent worktrees (gitignored)
+ ├── agent-1/ # Worktree for agent 1
+ └── agent-2/ # Worktree for agent 2
```
### Creating Worktrees
@@ -164,7 +164,9 @@ For parallel development, each agent gets a git worktree — an independent work
scripts/setup-agent-worktree.sh
```
-This creates `../-` with a workspace branch.
+This creates `.worktrees/` with a workspace branch. The script
+also ensures `.worktrees/` is gitignored so worktree checkouts are never
+accidentally committed.
### Worktree Workflow
@@ -178,6 +180,6 @@ Each agent follows the same PR workflow (section 3) from its worktree. Additiona
```bash
git worktree list # List all worktrees
-git worktree remove ../scaffold- # Remove a worktree
+git worktree remove .worktrees/ # Remove a worktree
git worktree prune # Prune stale references
```
diff --git a/scripts/setup-agent-worktree.sh b/scripts/setup-agent-worktree.sh
index 8290b1d4a..9d1c84b04 100755
--- a/scripts/setup-agent-worktree.sh
+++ b/scripts/setup-agent-worktree.sh
@@ -28,11 +28,27 @@ if [ -z "$agent_suffix" ]; then
fi
# ─── Resolve paths ──────────────────────────────────────────
+# Worktrees live project-local under /.worktrees/ for a single,
+# consistent location (see docs/git-workflow.md §7). This matches the
+# superpowers `using-git-worktrees` convention and keeps every agent worktree
+# discoverable from one place rather than scattered as repo siblings.
-repo_name="$(basename "$REPO_DIR")"
-worktree_dir="$(cd "$REPO_DIR/.." && pwd)/${repo_name}-${agent_suffix}"
+worktree_dir="$REPO_DIR/.worktrees/${agent_suffix}"
branch_name="${agent_suffix}-workspace"
+# ─── Ensure .worktrees/ is gitignored ───────────────────────
+# Critical: a project-local worktree dir must be ignored or its contents (a full
+# checkout) would show as untracked and could be committed. Add the rule if the
+# repo does not already ignore it.
+if ! git -C "$REPO_DIR" check-ignore -q .worktrees 2>/dev/null; then
+ gitignore_file="$REPO_DIR/.gitignore"
+ if [ -f "$gitignore_file" ] && [ -s "$gitignore_file" ] && [ "$(tail -c1 "$gitignore_file")" != "" ]; then
+ printf '\n' >> "$gitignore_file"
+ fi
+ printf '# Git worktrees (scaffold parallel agents)\n.worktrees/\n' >> "$gitignore_file"
+ echo "Added .worktrees/ to $gitignore_file"
+fi
+
# ─── Create worktree ────────────────────────────────────────
if [ ! -d "$worktree_dir" ]; then
diff --git a/src/project/gitignore.test.ts b/src/project/gitignore.test.ts
index 266a33270..5f03f36a9 100644
--- a/src/project/gitignore.test.ts
+++ b/src/project/gitignore.test.ts
@@ -36,6 +36,7 @@ describe('ensureScaffoldGitignore', () => {
expect(content).toContain('.scaffold/lock.json')
expect(content).toContain('.scaffold/*.tmp')
expect(content).toContain('.scaffold/**/*.tmp')
+ expect(content).toContain('.worktrees/')
})
it('updates existing managed block idempotently without changing user content', () => {
diff --git a/src/project/gitignore.ts b/src/project/gitignore.ts
index 96afdb0d7..2b5e4de40 100644
--- a/src/project/gitignore.ts
+++ b/src/project/gitignore.ts
@@ -11,6 +11,10 @@ const MANAGED_LINES = [
'.scaffold/lock.json',
'.scaffold/*.tmp',
'.scaffold/**/*.tmp',
+ // Parallel-agent worktrees live at /.worktrees/; ignore so a
+ // worktree's full checkout is never accidentally committed (see
+ // scripts/setup-agent-worktree.sh and docs/git-workflow.md §7).
+ '.worktrees/',
]
const DANGEROUS_RULES = new Set([
diff --git a/tests/setup-agent-worktree.bats b/tests/setup-agent-worktree.bats
index 042660f60..828141b4b 100644
--- a/tests/setup-agent-worktree.bats
+++ b/tests/setup-agent-worktree.bats
@@ -29,9 +29,10 @@ setup() {
}
teardown() {
+ # Worktrees now live inside the repo at /.worktrees/, so removing
+ # CLONE_DIR also removes them. Prune any stale registrations first.
+ git -C "$CLONE_DIR" worktree prune 2>/dev/null || true
rm -rf "$ORIG_DIR" "$CLONE_DIR"
- # Clean up any worktrees that were created
- rm -rf "$RESOLVED_TMPDIR"/scaffold-$$-*
}
@test "exits 1 with usage message when no arguments provided" {
@@ -40,10 +41,23 @@ teardown() {
[[ "$output" == *"Usage:"* ]]
}
-@test "creates worktree at expected path" {
+@test "creates worktree under /.worktrees/" {
run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-alpha"
[ "$status" -eq 0 ]
- [ -d "$RESOLVED_TMPDIR/scaffold-$$-agent-alpha" ]
+ [ -d "$CLONE_DIR/.worktrees/agent-alpha" ]
+}
+
+@test "does not create a sibling worktree directory" {
+ run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-alpha"
+ [ "$status" -eq 0 ]
+ [ ! -d "$RESOLVED_TMPDIR/scaffold-$$-agent-alpha" ]
+}
+
+@test "ensures .worktrees/ is gitignored" {
+ run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-alpha"
+ [ "$status" -eq 0 ]
+ run git -C "$CLONE_DIR" check-ignore -q .worktrees
+ [ "$status" -eq 0 ]
}
@test "idempotent: succeeds if worktree already exists" {
@@ -60,14 +74,14 @@ teardown() {
@test "normalizes agent name to lowercase with hyphens" {
run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "Agent_Charlie"
[ "$status" -eq 0 ]
- [ -d "$RESOLVED_TMPDIR/scaffold-$$-agent-charlie" ]
+ [ -d "$CLONE_DIR/.worktrees/agent-charlie" ]
}
@test "creates workspace branch for the agent" {
run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-delta"
[ "$status" -eq 0 ]
# Check that the branch exists in the worktree
- local worktree_dir="$RESOLVED_TMPDIR/scaffold-$$-agent-delta"
+ local worktree_dir="$CLONE_DIR/.worktrees/agent-delta"
run git -C "$worktree_dir" branch --show-current
[ "$output" = "agent-delta-workspace" ]
}
From 9628346d5df46ab499432e627adec14d8776faf4 Mon Sep 17 00:00:00 2001
From: Ken Allred
Date: Sun, 31 May 2026 10:16:50 -0600
Subject: [PATCH 2/4] fix(review): use trailing-slash check-ignore; drop
redundant prune
Address multi-channel review findings on the worktree gitignore guard:
- The pre-create check `git check-ignore -q .worktrees` false-negatived
when `.worktrees/` was already ignored but the directory did not yet
exist (a directory-only pattern only matches a path git knows is a
dir). That caused a duplicate `.worktrees/` rule to be appended,
including when src/project/gitignore.ts had already added it. Use the
trailing-slash form `.worktrees/` so the check matches correctly
regardless of whether the dir exists. Adds a regression test.
- Remove the redundant `git worktree prune` from the bats teardown; the
whole clone (with its .git/worktree metadata) is rm -rf'd right after.
Co-Authored-By: Claude Opus 4.8
---
scripts/setup-agent-worktree.sh | 7 ++++++-
tests/setup-agent-worktree.bats | 14 ++++++++++++--
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/scripts/setup-agent-worktree.sh b/scripts/setup-agent-worktree.sh
index 9d1c84b04..345af7760 100755
--- a/scripts/setup-agent-worktree.sh
+++ b/scripts/setup-agent-worktree.sh
@@ -40,7 +40,12 @@ branch_name="${agent_suffix}-workspace"
# Critical: a project-local worktree dir must be ignored or its contents (a full
# checkout) would show as untracked and could be committed. Add the rule if the
# repo does not already ignore it.
-if ! git -C "$REPO_DIR" check-ignore -q .worktrees 2>/dev/null; then
+#
+# Use the trailing-slash path ('.worktrees/') in the check: a directory-only
+# pattern like '.worktrees/' only matches a path git knows to be a directory.
+# Without the slash, `git check-ignore` false-negatives here because this runs
+# *before* the worktree dir exists, which would append a duplicate ignore rule.
+if ! git -C "$REPO_DIR" check-ignore -q .worktrees/ 2>/dev/null; then
gitignore_file="$REPO_DIR/.gitignore"
if [ -f "$gitignore_file" ] && [ -s "$gitignore_file" ] && [ "$(tail -c1 "$gitignore_file")" != "" ]; then
printf '\n' >> "$gitignore_file"
diff --git a/tests/setup-agent-worktree.bats b/tests/setup-agent-worktree.bats
index 828141b4b..f232ffc18 100644
--- a/tests/setup-agent-worktree.bats
+++ b/tests/setup-agent-worktree.bats
@@ -30,8 +30,7 @@ setup() {
teardown() {
# Worktrees now live inside the repo at /.worktrees/, so removing
- # CLONE_DIR also removes them. Prune any stale registrations first.
- git -C "$CLONE_DIR" worktree prune 2>/dev/null || true
+ # CLONE_DIR (including its .git and worktree metadata) also removes them.
rm -rf "$ORIG_DIR" "$CLONE_DIR"
}
@@ -60,6 +59,17 @@ teardown() {
[ "$status" -eq 0 ]
}
+@test "does not duplicate .worktrees/ when it is already gitignored" {
+ # .worktrees/ already ignored, but the directory does not exist yet — the
+ # check must use the trailing-slash form or it false-negatives and appends
+ # a duplicate rule. Regression guard for that.
+ printf '.worktrees/\n' > "$CLONE_DIR/.gitignore"
+ run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-echo"
+ [ "$status" -eq 0 ]
+ run grep -c '^\.worktrees/$' "$CLONE_DIR/.gitignore"
+ [ "$output" = "1" ]
+}
+
@test "idempotent: succeeds if worktree already exists" {
# First run creates it
run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-beta"
From 225d2be5f0ea94ac94f87e0ddbb804611e589c7f Mon Sep 17 00:00:00 2001
From: Ken Allred
Date: Sun, 31 May 2026 10:35:12 -0600
Subject: [PATCH 3/4] docs(review): re-point multi-agent guide cites; align
test slash form
- Re-point :cite line numbers in content/guides/multi-agent to the
shifted lines in setup-agent-worktree.sh (branch add, worktree add,
mkdir .scaffold, identity printf, beads check) and rebuild index.html.
- Align the "ensures .worktrees/ is gitignored" test to use the
trailing-slash check-ignore form the script uses.
Co-Authored-By: Claude Opus 4.8
---
.claude/scheduled_tasks.lock | 1 +
content/guides/multi-agent/index.html | 10 +++++-----
content/guides/multi-agent/index.md | 10 +++++-----
tests/setup-agent-worktree.bats | 2 +-
4 files changed, 12 insertions(+), 11 deletions(-)
create mode 100644 .claude/scheduled_tasks.lock
diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock
new file mode 100644
index 000000000..f9925f73c
--- /dev/null
+++ b/.claude/scheduled_tasks.lock
@@ -0,0 +1 @@
+{"sessionId":"087c190a-bbad-41c5-b115-089dc8c0e023","pid":59988,"procStart":"Fri May 22 15:28:00 2026","acquiredAt":1779714712906}
\ No newline at end of file
diff --git a/content/guides/multi-agent/index.html b/content/guides/multi-agent/index.html
index 250246250..8f0b35ef9 100644
--- a/content/guides/multi-agent/index.html
+++ b/content/guides/multi-agent/index.html
@@ -1402,17 +1402,17 @@ Setup — setup-agent-worktree.sh.worktrees/<slug>. It also ensures .worktrees/ is
gitignored so the worktree's checkout is never accidentally committed.
- Creates the workspace branch
<slug>-workspace if it does not already
-exist scripts/setup-agent-worktree.sh:57, then adds the worktree on
-that branch scripts/setup-agent-worktree.sh:60. Re-running for an
+exist scripts/setup-agent-worktree.sh:62, then adds the worktree on
+that branch scripts/setup-agent-worktree.sh:65. Re-running for an
existing worktree is a safe no-op.
- Writes
.scaffold/identity.json — the stable identity that build
observability stamps onto every event this worktree records. The script
-creates .scaffold/ scripts/setup-agent-worktree.sh:68 and, only if no
+creates .scaffold/ scripts/setup-agent-worktree.sh:73 and, only if no
identity file exists yet, writes worktree_id (a UUID), worktree_label
(the agent slug), and created_at
-scripts/setup-agent-worktree.sh:87.
+scripts/setup-agent-worktree.sh:92.
- Re-syncs Beads with a fail-soft
bd doctor --fix when a .beads/
-directory is present scripts/setup-agent-worktree.sh:104, reconciling the
+directory is present scripts/setup-agent-worktree.sh:109, reconciling the
worktree's Beads git hooks and project config against the installed bd
version. (Beads DB sharing is automatic — worktrees discover the main repo's
task DB via git's common directory, so there is nothing for bd doctor to
diff --git a/content/guides/multi-agent/index.md b/content/guides/multi-agent/index.md
index ce80d22b0..b51d59b95 100644
--- a/content/guides/multi-agent/index.md
+++ b/content/guides/multi-agent/index.md
@@ -48,17 +48,17 @@ one parallel agent. Given a name like `alpha`, it:
under the primary repo: `.worktrees/`. It also ensures `.worktrees/` is
gitignored so the worktree's checkout is never accidentally committed.
2. **Creates the workspace branch** `-workspace` if it does not already
- exist :cite[scripts/setup-agent-worktree.sh:57], then adds the worktree on
- that branch :cite[scripts/setup-agent-worktree.sh:60]. Re-running for an
+ exist :cite[scripts/setup-agent-worktree.sh:62], then adds the worktree on
+ that branch :cite[scripts/setup-agent-worktree.sh:65]. Re-running for an
existing worktree is a safe no-op.
3. **Writes `.scaffold/identity.json`** — the stable identity that build
observability stamps onto every event this worktree records. The script
- creates `.scaffold/` :cite[scripts/setup-agent-worktree.sh:68] and, only if no
+ creates `.scaffold/` :cite[scripts/setup-agent-worktree.sh:73] and, only if no
identity file exists yet, writes `worktree_id` (a UUID), `worktree_label`
(the agent slug), and `created_at`
- :cite[scripts/setup-agent-worktree.sh:87].
+ :cite[scripts/setup-agent-worktree.sh:92].
4. **Re-syncs Beads** with a fail-soft `bd doctor --fix` when a `.beads/`
- directory is present :cite[scripts/setup-agent-worktree.sh:104], reconciling the
+ directory is present :cite[scripts/setup-agent-worktree.sh:109], reconciling the
worktree's Beads git hooks and project config against the installed `bd`
version. (Beads DB sharing is automatic — worktrees discover the main repo's
task DB via git's common directory, so there is nothing for `bd doctor` to
diff --git a/tests/setup-agent-worktree.bats b/tests/setup-agent-worktree.bats
index f232ffc18..fe3c06133 100644
--- a/tests/setup-agent-worktree.bats
+++ b/tests/setup-agent-worktree.bats
@@ -55,7 +55,7 @@ teardown() {
@test "ensures .worktrees/ is gitignored" {
run "$CLONE_DIR/scripts/setup-agent-worktree.sh" "agent-alpha"
[ "$status" -eq 0 ]
- run git -C "$CLONE_DIR" check-ignore -q .worktrees
+ run git -C "$CLONE_DIR" check-ignore -q .worktrees/
[ "$status" -eq 0 ]
}
From 03769ff7c01931b1a4573fb3db45957249ed21b1 Mon Sep 17 00:00:00 2001
From: Ken Allred
Date: Sun, 31 May 2026 10:47:44 -0600
Subject: [PATCH 4/4] fix(review): stop tracking transient
.claude/scheduled_tasks.lock
A git add -A swept the Claude Code scheduler lock file (session id, PID,
process start time) into the branch. Untrack it and add .claude/*.lock to
.gitignore so runtime locks are never committed.
Co-Authored-By: Claude Opus 4.8
---
.claude/scheduled_tasks.lock | 1 -
.gitignore | 4 ++++
2 files changed, 4 insertions(+), 1 deletion(-)
delete mode 100644 .claude/scheduled_tasks.lock
diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock
deleted file mode 100644
index f9925f73c..000000000
--- a/.claude/scheduled_tasks.lock
+++ /dev/null
@@ -1 +0,0 @@
-{"sessionId":"087c190a-bbad-41c5-b115-089dc8c0e023","pid":59988,"procStart":"Fri May 22 15:28:00 2026","acquiredAt":1779714712906}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index ff20ed00c..98b3d6d4a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,10 @@ node_modules/
# Git worktrees
.worktrees/
+# Claude Code transient runtime locks
+.claude/scheduled_tasks.lock
+.claude/*.lock
+
# Playwright MCP test artifacts
tests/screenshots/current/
tests/screenshots/diff/