chore(agent): commit the machine tier and the doctrine text the checkout was already running
Landing blocker for #61 and #63: the deployment checkout is 12 commits behind and `merge --ff-only` refuses while tracked paths are dirty. Discard is not available here (workspace policy: no `checkout`/`stash` on shared state), so the dirt is committed. - `agent/APPEND_SYSTEM.md`: the point-of-use / one-work-log / PR-link doctrine, already byte-identical to `origin/main` (`cmp` against the trunk blob: no difference). No new prose — the commit exists so the trunk merge can proceed. - `agent/config.yml` and `agent/managed-skills/**`: the machine-live tier the heartbeat owns (AGENTS.md § Live-sync tiers). `ALLOW_SECRETS=1` was used, deliberately and after auditing the staged diff by hand: the only credential-shaped strings in it are two copies of `AKIA0000000000000EXAMPLE` — the inert all-zero AWS example id — and they appear inside the two skill pages that teach that exact placeholder shape. This checkout is still running the pre-#61 hook; the merged gate (value-scoped placeholder filter, `71601f7`) exempts this value, so the refusal dies with this landing. No `--no-verify` was used: the gate ran and its verdict is recorded here. Refs #61
This commit is contained in:
1 parent
004962ffce
commit
8af40c402b
79 files changed
+2771
-332
No files matched your search
@@ -1,49 +1,22 @@
|
||||
---
|
||||
name: omp-worktree-path-gotchas
|
||||
description: "Use in ~/.omp (or any multi-worktree repo) when an edit lands in the wrong checkout, git checkout is policy-refused, or an omp session id is needed — relative-path tool resolution, shared-worktree branch law, session-id lookup, edit auto-prefix trap."
|
||||
description: "Multi-worktree edits/tests land in the wrong checkout: bash persistent-cwd drift, phantom file reverts, which tree a tool really touched"
|
||||
---
|
||||
|
||||
# Multi-worktree gotchas in ~/.omp-style repos
|
||||
## Purpose
|
||||
Answer "why did my file/tests revert or behave differently than what I just wrote?" in repos with several worktrees (e.g. `~/.omp`, `~/Projects/wt-*`, `~/.omp/wt/*`).
|
||||
|
||||
Measured 2026-10-18 building PR #12/#14 in `dank/command-center` worktrees.
|
||||
## Failure modes and fixes
|
||||
|
||||
## 1. Relative paths resolve to the SESSION worktree — always edit by absolute path
|
||||
`edit`/`read`/`write` with a relative `path` resolve against the session CWD
|
||||
(the harness worktree you were spawned in), NEVER the worktree you `cd`'d into
|
||||
via bash. Identical file content in sibling worktrees yields identical
|
||||
`[path#tag]` hashes, so an edit can "succeed" against the WRONG checkout with
|
||||
no warning; only a rejected stale-hash edit reveals it.
|
||||
1. **Bash tool persistent-cwd drift** (the expensive one): the persistent shell keeps its cwd across calls; a call *without* an explicit `cwd` runs in whatever the *previous* call left, which after interleaved work may be a DIFFERENT worktree. Result: reads/greps/appends hit tree A while `git`/`bats` hit tree B — symptoms are "file keeps reverting to HEAD", duplicate test names at shifting line numbers, scenario `CALLS 0` for scenarios that exist, mismatched `grep -n` vs tool-reported line numbers.
|
||||
- **Diagnose:** `pwd` in the same call as the failing command; `wc -l <file>` in BOTH candidate worktrees; compare md5s. The file is not flapping — two files exist and commands alternate between them.
|
||||
- **Fix/prevent:** pass an explicit `cwd` on EVERY bash call once two or more checkouts are in play; never trust a read taken without one as evidence about "the" file.
|
||||
|
||||
- When working in a second worktree, ALL file-tool paths: absolute.
|
||||
- Symptom seen: edit rejected "hash #X is not from this session" while the
|
||||
bash-side `git status` showed the file clean — two different files, two
|
||||
worktrees. Recovery: revert the stray edit (CUT the inserted lines) in the
|
||||
wrong tree, re-read the right tree, redo with absolute header.
|
||||
2. **Symlinked or stale `git` state**: `git status` in a worktree shows a clean tree while the disk file differs from what you intended — the corruption is already committed. Audit committed blobs (`git log --oneline -- <file>`; per-commit `git show <c>:<path> | grep -c <sentinel>`) instead of re-reading the disk copy repeatedly.
|
||||
|
||||
## 2. Branching: shared worktrees refuse git checkout
|
||||
Workspace policy blocks `git checkout` (branch switches AND `--` discards) in
|
||||
harness-managed worktrees — concurrent agents depend on them. To start a
|
||||
branch off fresh trunk:
|
||||
3. **Same-name files across worktrees** (`tests/behavior.bats` exists in each): a `find`/`grep` rooted above the worktrees mixes copies; anchor the search path to one worktree root.
|
||||
|
||||
```bash
|
||||
git -C ~/.omp worktree add -q -b <type>/<issue#>-<slug> ~/.omp/wt/<name> origin/main
|
||||
```
|
||||
|
||||
Never force past the refusal; the new-worktree route is strictly safer.
|
||||
Custom worktrees not matching `wt/wt-*` are invisible to the live-sync reaper —
|
||||
prune them by hand after merge (`git worktree remove`, `git branch -d`).
|
||||
|
||||
## 3. omp session id for attribution footers
|
||||
Fleet law requires `session:` in issue/PR bodies. Authoritative source:
|
||||
`~/.omp/agent/sessions/<cwd-slug>/<timestamp>_<UUID>.jsonl` — the `<UUID>` is
|
||||
the session id. Pick the newest file whose first `{"type":"title"}` line names
|
||||
this conversation to prove the id is yours. The `wt/<ts>-<hash>` dir suffix is
|
||||
NOT the session id (it persists across sessions per cwd).
|
||||
|
||||
## 4. edit-tool auto-prefix trap (recurring)
|
||||
A body row written bare (intending it as the "original line" anchor or as
|
||||
context) is AUTO-PREFIXED with `+` and INSERTED — leaving the old line plus a
|
||||
duplicate. `PUT n.=n:` therefore behaves like insert, not replace, whenever
|
||||
the anchor row lacks an explicit marker. After any `PUT` where the response
|
||||
warns "Auto-prefixed bare body row(s)", immediately `CUT` the stale line number
|
||||
shown in the response (descending order for multiple CUTs).
|
||||
## Repair recipe for a corrupted-but-committed test file
|
||||
- Inventory both versions: `grep -o '@test "[^"]*"' | sort` and `grep -o 'case "[a-z]*":' | sort -u`; `comm` the sets to find lost scenarios and duplicate tests.
|
||||
- Rebuild from the committed copy (`git show HEAD:<path> > <path>`, no checkout), then re-apply only the true deltas: restore missing scenario blocks from the last clean base, dedupe imports, rename scratch-dir mkdtemp prefixes that collide with a test's own orphan-census glob (e.g. `dankvoice-stage-` matching `dankvoice-*`).
|
||||
- Re-run the targeted tests, then the full suite single-process.
|
||||
Reference in new issue
Block a user