Skip to content

Extend guard_master.py's worktree gate to Edit/Write/NotebookEdit - #444

Merged
WilfordGrimley merged 1 commit into
masterfrom
worktree-agent-a3bc38f546739b394
Jul 24, 2026
Merged

Extend guard_master.py's worktree gate to Edit/Write/NotebookEdit#444
WilfordGrimley merged 1 commit into
masterfrom
worktree-agent-a3bc38f546739b394

Conversation

@WilfordGrimley

Copy link
Copy Markdown

Description

guard_master.py's PreToolUse hook only ever matched Bash commands. Four
independent sessions on 2026-07-23 and 2026-07-24 accidentally edited the
shared main checkout via absolute-path Read/Edit/Write calls run from
a worker worktree — the failure mode docs/lessons.md's "Absolute paths to
the repo root silently target the wrong checkout in a worktree session"
entry already documents, but via a file tool instead of git/gh in
Bash, so the existing rules never saw it. All four were self-caught
before landing anything, but the near-misses stacked up fast enough to
close the gap at the tool layer instead of relying on every session to
catch its own mistake.

This PR:

  • Extends .claude/settings.json's PreToolUse matcher to also fire on
    Edit, Write, and NotebookEdit (was Bash only).
  • Adds check_worktree_write_guard() to guard_master.py: when the
    session's cwd is under a worker worktree (.claude/worktrees/<name>/...)
    and the tool's target path (file_path for Edit/Write, notebook_path
    for NotebookEdit) resolves inside the main checkout root but outside
    .claude/worktrees/, the call is blocked with a message mirroring the
    existing Bash-rule wording.
  • Preserves the documented WORKERS.md/journal/ exception (per
    docs/lessons.md and CLAUDE.local.md's multi-worker protocol) —
    those are gitignored files that intentionally live in the main
    checkout, so writes there from a worktree session stay allowed.
  • Leaves Read entirely ungated — blocking reads would break legitimate
    cross-referencing against the main checkout's on-disk state, and a read
    can't silently land content on the wrong branch the way a write can.
  • Does NOT block: paths inside the session's own worktree, paths inside
    any other worktree, or paths outside the repo entirely (/tmp, the
    orchestration repo, the memory dir).

Checklist

  • I have installed pre-commit and installed the hooks with pre-commit install before creating any commits.
  • I have updated any related tests for code I modified or added new tests where appropriate — extended the existing .claude/hooks/test_guard_master.py suite (there was already a test precedent for this hook) with 13 new end-to-end cases and 9 new unit cases against the new helper functions; no new --self-test mode was needed since the precedent already existed. This suite has no CI wiring (same as before this change) — it's a local-only dev-loop check, run manually.
  • I have manually tested my changes as follows:
    • python3 .claude/hooks/test_guard_master.py — all 58 cases pass (36 pre-existing + 22 new).
    • python3 -m py_compile .claude/hooks/guard_master.py .claude/hooks/test_guard_master.py
    • black --check and the repo's pre-commit hooks (ruff, isort, black, mypy, prettier) all pass.
    • python3 .github/scripts/docs_lint.py — clean.
  • I have updated any relevant documentation or created new documentation where appropriate — extended the existing .claude/hooks/guard_master.py guard_master.py entry in docs/troubleshooting.md, and added a "closed at the tool layer" note to the existing worktree-path-trap entry in docs/lessons.md.

…trap

Four sessions on 2026-07-23/24 accidentally edited the main checkout via
absolute-path file-tool calls; PreToolUse now blocks writes that resolve
outside .claude/worktrees/ from a worker worktree session (WORKERS.md and
journal/ still exempt; Read stays ungated).
@WilfordGrimley
WilfordGrimley merged commit f29729a into master Jul 24, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant