Refuse agent-branch commits from a main checkout #119

Open
opened 2026-07-27 15:52:57 +01:00 by vnprc-agent · 0 comments
Contributor

Worktree isolation only holds if agents actually use it, and today nothing stops an agent from running bare git switch -c in a shared checkout — which is how the collision in allod/tools#115 happened, since neither agent invoked allod change at all. Move the rule down to the hook layer so working on an agent branch in a shared checkout is refused rather than merely discouraged.

Part of allod/tools#115. Depends on allod/tools#112.

Primary goals:

  • Refuse agent-branch work in a main checkout — a commit or push on an agent/* branch from a registry checkout is blocked, with a message naming the allod change begin invocation that produces a correct worktree.
  • Leave humans and default branches alone — commits to a repo's default branch in a shared checkout are untouched, so the memory and planning-doc flow and ordinary human work are unaffected.
  • Keep the override a human act — bypassing is standard git commit --no-verify, never a flag the tooling offers, per architecture.md principle 4.
  • Close the enforcement gap, not just the tool gap — the rule has to hold for agents that never call allod change, which is the failure mode actually observed.

Why this depends on allod/tools#112

The hook cannot currently tell where it is. git-hooks/protected-refs-policy:4 resolves the repo as git rev-parse --show-toplevel and :21 derives the lookup key as ${repo#"$HOME"/}, so inside a linked worktree the key is an absolute path that matches nothing. Both path-keyed policy files therefore go silent in a worktree: protected-branches (:21) and signing-required-branches (:35). Signing enforcement disappearing inside a worktree is the more serious half, since a repo whose default branch requires signed pushes loses that guard entirely there.

Worth noting that the same hook already keys two other policies off remote identity — active-pr-branches (:48, used at :174 and :186) and allowed-external-remotes (:62-68) — so allod/tools#112's remote-identity lookup is the established pattern in this file and the path-keyed pair is the outlier. Until that lands, adding a rule that pushes more work into worktrees widens the gap rather than closing it.

Current state

Nothing distinguishes a registry checkout from a linked worktree in the hook, and nothing keys on the agent/ branch prefix. A linked worktree can be identified by git rev-parse --git-common-dir differing from --git-dir, which is also how allod change already resolves repo identity from a worktree.

Scope

In: git-hooks/protected-refs-policy and its tests, covering the refusal, the default-branch pass-through, and the human override. Out: the identity-resolution change itself (allod/tools#112) and worktree creation policy (allod/tools#116).

Worktree isolation only holds if agents actually use it, and today nothing stops an agent from running bare `git switch -c` in a shared checkout — which is how the collision in allod/tools#115 happened, since neither agent invoked `allod change` at all. Move the rule down to the hook layer so working on an agent branch in a shared checkout is refused rather than merely discouraged. Part of allod/tools#115. Depends on allod/tools#112. Primary goals: - **Refuse agent-branch work in a main checkout** — a commit or push on an `agent/*` branch from a registry checkout is blocked, with a message naming the `allod change begin` invocation that produces a correct worktree. - **Leave humans and default branches alone** — commits to a repo's default branch in a shared checkout are untouched, so the memory and planning-doc flow and ordinary human work are unaffected. - **Keep the override a human act** — bypassing is standard `git commit --no-verify`, never a flag the tooling offers, per `architecture.md` principle 4. - **Close the enforcement gap, not just the tool gap** — the rule has to hold for agents that never call `allod change`, which is the failure mode actually observed. ### Why this depends on allod/tools#112 The hook cannot currently tell where it is. `git-hooks/protected-refs-policy:4` resolves the repo as `git rev-parse --show-toplevel` and `:21` derives the lookup key as `${repo#"$HOME"/}`, so inside a linked worktree the key is an absolute path that matches nothing. Both path-keyed policy files therefore go silent in a worktree: `protected-branches` (`:21`) and `signing-required-branches` (`:35`). Signing enforcement disappearing inside a worktree is the more serious half, since a repo whose default branch requires signed pushes loses that guard entirely there. Worth noting that the same hook already keys two other policies off remote identity — `active-pr-branches` (`:48`, used at `:174` and `:186`) and `allowed-external-remotes` (`:62-68`) — so allod/tools#112's remote-identity lookup is the established pattern in this file and the path-keyed pair is the outlier. Until that lands, adding a rule that pushes more work into worktrees widens the gap rather than closing it. ### Current state Nothing distinguishes a registry checkout from a linked worktree in the hook, and nothing keys on the `agent/` branch prefix. A linked worktree can be identified by `git rev-parse --git-common-dir` differing from `--git-dir`, which is also how `allod change` already resolves repo identity from a worktree. ### Scope In: `git-hooks/protected-refs-policy` and its tests, covering the refusal, the default-branch pass-through, and the human override. Out: the identity-resolution change itself (allod/tools#112) and worktree creation policy (allod/tools#116).
Sign in to join this conversation.
No description provided.