Skip to content

chore(agents): harden worktree-first guard + surface Directive #11 via CLAUDE.md - #2517

Merged
os-zhuang merged 1 commit into
mainfrom
fix/worktree-guard-hardening
Jul 2, 2026
Merged

chore(agents): harden worktree-first guard + surface Directive #11 via CLAUDE.md#2517
os-zhuang merged 1 commit into
mainfrom
fix/worktree-guard-hardening

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Why

Prime Directive #11 (worktree-first) is well written in AGENTS.md, yet agents (this one included) still edited on shared checkouts. Root cause wasn't the prose — it was enforcement + reach:

  1. The guard checked the wrong condition.guard-main-checkout.sh blocked only when branch == main. Creating a feature branch on the shared primary checkout passed the guard while the tree could still be switched/reset under you — the exact loophole that got hit (feat/studio-* on the shared objectui checkout; wip/session-off-main on framework).
  2. The guard only watched this repo. It inspected $CLAUDE_PROJECT_DIR, so editing a sibling repo (objectui/cloud) on its shared checkout from a framework session was silently unguarded.
  3. The directive never reached the agent's context. There's no CLAUDE.md (which is auto-loaded); AGENTS.md isn't. So the agent started blind to Migrate documentation site to Fumadocs with monorepo structure and shared content #11 and only learned it when the guard fired — where loophole Add metamodel interfaces for ObjectQL/ObjectUI contract #1 let it be bypassed.

What

  • Hook now enforces "in a linked worktree" (git rev-parse --git-dir under .git/worktrees/…), not branch != main. A branch on the shared checkout is blocked.
  • Hook now checks the edited file's own repo (parses tool_input.file_path from the PreToolUse stdin), so sibling repos are covered too — not just $CLAUDE_PROJECT_DIR.
  • New CLAUDE.md (auto-loaded): inlines the worktree-first rule + command, extends it to sibling repos, and points to AGENTS.md for the full playbook. (Inlining the critical rule beats a bare "go read AGENTS.md" — same weak indirection that failed.)
  • AGENTS.md Migrate documentation site to Fumadocs with monorepo structure and shared content #11 updated to match the hardened hook.

Verified (hook unit tests)

caseexpectresult
file on framework primary (main)block✅ exit 2
file in a framework worktreeallow✅ exit 0
file on objectui primary (main), from this sessionblock✅ exit 2 (cross-repo)
non-repo pathallow✅ exit 0
OS_ALLOW_MAIN_EDITS=1allow✅ exit 0

Authored from a worktree (framework-guardfix), per #11.

🤖 Generated with Claude Code

…a CLAUDE.md
The guard-main-checkout PreToolUse hook had two holes agents fell through:
1. It checked `branch != main`, so creating a feature branch on the SHARED
primary checkout passed the guard while the tree could still be switched/reset
under you. It now checks "is the edited file in a linked worktree" — a branch
on the primary checkout is blocked. Enforces the directive's intent, not a proxy.
2. It only inspected $CLAUDE_PROJECT_DIR, so editing a sibling repo (objectui /
cloud) on its shared checkout from this session was silently unguarded. It now
parses the edited file's path and checks THAT repo's checkout — cross-repo safe.
Also:
- Add CLAUDE.md (auto-loaded into agent context, unlike AGENTS.md) that inlines the
worktree-first rule + the command and points to AGENTS.md for the full playbook.
The prior gap: AGENTS.md #11 was clear but never reached the agent's context.
- Update AGENTS.md #11 to describe the hardened hook behaviour.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 2, 2026 12:47pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation size/m labels Jul 2, 2026
@os-zhuang
os-zhuang merged commit d1fc9fa into mainJul 2, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the fix/worktree-guard-hardening branch July 2, 2026 12:54
os-zhuang added a commit that referenced this pull request Jul 2, 2026
…fail-open) (#2519)
Follow-up to #2517. The guard ran `git -C "$(dirname file)"`, which fails when the
edited file's parent directory doesn't exist yet (a Write creating a new nested dir)
— and `|| exit 0` then let the edit through on the shared checkout. Now it walks up to
the nearest existing ancestor before resolving the repo, so new-file-in-new-dir writes
are guarded too. (Also applied to objectui#2160 / cloud#721.)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/m

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang