live: heartbeat sync 2026-10-19T14:21:41-07:00 (Refs #11)

This commit is contained in:
Frank committed 2026-10-19 14:21:41 -07:00
1 parent 36ff3742b4
commit 6e3e5594eb
24 files changed
+657 -102

No files matched your search

@@ -1,68 +1,34 @@
---
name: parallel-worktree-path-hazard
description: "\"Use when several agents edit the same repo in different git worktrees at once, or when an edit/read may have landed in the wrong checkout: which path forms bind where, how to detect with git -C status, and the repair protocol (cp + git show HEAD blob write-back) because git checkout/restore is policy-blocked in a shared workspace.\""
description: "Use when several agents edit the same repo in different git worktrees at once, or when an edit lands in the wrong checkout: relative tool paths resolve to the session cwd, not the shell cwd."
---
# Concurrent-worktree path hazard (shared repo, many agents)
Use when several agents (or you across two checkouts) edit the same repo in different git worktrees at once, or when an edit/query lands in the wrong checkout.
Measured 2026-10-18 on `serverAppConfigs` with two agents live at once. The
failure is **silent**: the tool reports success, the diff looks right, and the
change lives in a *different* worktree.
## The silent failure: relative tool paths resolve to the SESSION cwd
## Which path form binds where
- **Parent/top-level session**: a **relative** `path` resolves against the
session CWD — its own worktree — never against the worktree named in the
prompt. This is how a change meant for `wt-tts-trial-docs` landed in
`wt-20261017-…`.
- **Subagent**: an **absolute** path to its own assigned worktree can resolve
into the parent's worktree when the same *relative* path exists there
(`edit` twice onto `dankclaw/.env.example`). Its `write` with the same
absolute path was fine — the bug is `edit`/`read` path resolution, not `write`.
`read` / `edit` / `write` / `grep` resolve a **relative** `path` against the **session working directory** — never against the `cd` inside a neighboring `bash` call, and not against a `../other-worktree/...` prefix either (that gets normalized back into the session tree). So after `cd ../wt-B && grep …` you can `read path="docs/page.md"` and get **wt-A's** copy.
Rules that hold:
1. A subagent passes paths as `../<its-worktree>/<rel>` (relative to the parent
worktree) for `read` **and** `edit`; the parent passes **absolute** paths to
any worktree that is not its own CWD.
2. After every edit batch, prove the landing site, do not trust the tool's echo:
`git -C <intended-worktree> status --short` must list the file. A file you
edited that is missing from that list went somewhere else.
3. Keep each work item on its own branch/worktree, and keep ONE integration
owner (the parent) for shared files — `scripts/deploy-remote.sh`,
`scripts/deploy-plan.py`, `tests/`, `serverAppConfigs-docs/index.md`,
`AGENTS.md` are the collision hot spots in this repo. Never rebase a
sibling's branch.
Why it survives "I just read it to check": the returned path is printed workspace-relative and the file name is identical in every checkout, so the output looks like a correct read of the tree you meant. Only content that differs between the checkouts betrays it.
## Repair protocol (no `git checkout`, no `git restore`)
`git checkout -- <path>` and `git restore <path>` are **policy-blocked** in a
shared workspace ("overwriting working-tree files … discards changes other
concurrent agents rely on"). Unstaging (`git reset [<path>]`,
`git restore --staged <path>`) is allowed but does not undo content. So:
Rules:
- **Absolute paths for every tool call that targets a worktree other than the session's.** No exceptions for quick reads.
- Confirm the checkout from content you know differs (a heading, a status line), not from the echoed path.
- A `read` error like "Did you mean .AGENTTRASH/<name>" is a signal the relative path resolved into the session tree — re-issue absolute.
- Same trap for `bash`: it starts each call in the session cwd, so `cd` twice per call or use absolute paths there too.
```bash
F="path/with spaces if any"
# 1. move the change to the worktree that should own it (both at the same base commit)
cp "<wrong-wt>/$F" "<right-wt>/$F"
# 2. undo in the wrong worktree by writing the committed blob back
git -C "<wrong-wt>" show "HEAD:$F" | tee "<wrong-wt>/$F" > /dev/null
# 3. prove both sides
md5sum <(git -C "<wrong-wt>" show "HEAD:$F") "<wrong-wt>/$F" "<right-wt>/$F"
git -C "<wrong-wt>" status --short # must be empty for that file
git -C "<right-wt>" diff --stat # must show the intended delta
```
## Landing a change when the session worktree is stale
Never fix it blind: if the wrong worktree had its own uncommitted edits to that
file, `cp`/blob-write-back would destroy them — check
`git -C <wrong-wt> status --short` FIRST and reconcile content, don't overwrite.
`git diff --name-only HEAD origin/main` first. If main moved a file you are editing, your edit's base is wrong even though the file "looks fine" — do not commit on the stale base.
## Tidy after a cancelled sibling
A killed subagent can leave a worktree plus an empty branch. Removing them is
safe only when verified empty: `git -C <main> log --oneline -3 <branch>` (no
unique commits) and `git -C <wt> status --short` (clean), then
`git worktree remove <wt>` + `git branch -D <branch>`. An orphan worktree at a
stale commit is the same class of trap as a leftover bench drop-in: the next
agent reads it as unfinished work.
1. `git worktree add ../wt-clean -b <type>/<slug> origin/main`; copy the new files in.
2. Re-apply the edit against the clean tree's version **with absolute paths**, then read it back absolutely to prove which tree changed.
3. Run the suite inside the clean worktree; commit there.
4. Remove your own duplicate edit from the session worktree by editing it away (`CUT`/`PUT`). `git checkout -- <path>` and branch switches are policy-blocked in shared workspaces and should stay blocked — they discard edits other agents rely on.
5. Never carry the same uncommitted edit in two worktrees at once; if you must keep both trees, keep a task that reconciles them.
## Report it
File the misresolution to `xd://report_issue` (false positives are fine) and
record the incident in the repo worklog — a repair nobody wrote down looks like
a hijack later.
## Multi-agent hazards in one shared worktree
- Another agent can stage, commit, or check out files under you; re-read a file immediately before editing it if any tool result hinted at intervening change.
- Untracked scratch you drop in a shared tree (reports, notes, `.AGENTTRASH/` entries) is visible to everyone and can be committed by them. Put throwaway artifacts outside the checkout.
- Never `git clean -f`, `rm -rf`, or branch switching to "get a clean state" in a tree another agent is using.