This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow-steward.git


The following commit(s) were added to refs/heads/main by this push:
     new 3f42f8e  fix(post-checkout): drop unrunnable /setup-steward slash 
command (#200)
3f42f8e is described below

commit 3f42f8e18867af7f1545c3d40a062b75dfdad3bf
Author: Jarek Potiuk <[email protected]>
AuthorDate: Sun May 17 21:55:15 2026 +0200

    fix(post-checkout): drop unrunnable /setup-steward slash command (#200)
    
    The post-checkout hook templates shipped in #184 (per-repo,
    installed by /setup-steward adopt) and #199 (global, installed
    under whole-user scope) both contained:
    
        /setup-steward verify --auto-fix-symlinks || true
    
    `/setup-steward verify` is a Claude Code slash command, not a
    shell command. The hook fires in the operator's shell, where
    there is no slash-command dispatcher. The shell tries to execute
    the literal path /setup-steward, fails with "No such file or
    directory", and || true swallows the exit code — but the stderr
    line still prints on every git checkout. The global hook in #199
    had a `command -v /setup-steward` guard so it was silent; the
    per-repo template did not.
    
    Fix: drop the steward-verify chunk from both templates entirely.
    Symlink-drift reconciliation cannot be done from a shell hook;
    it now happens lazily — the next time the operator opens Claude
    Code in the worktree, the framework skills' pre-flight drift
    check surfaces missing symlinks and prompts for the fix.
    
    - adopt.md Step 10: hook template rewritten without the broken
      line. Added a "Why no symlink reconciliation here" note
      explaining the slash-command-from-shell issue and the lazy-
      reconciliation alternative. Instructs adopters with the old
      broken line in their installed hook to replace it.
    
    - tools/agent-isolation/git-global-post-checkout.sh: same drop.
      The previous `command -v /setup-steward` guard masked the bug
      but encoded a wrong design. Updated header comment to explain
      why the apache-steward reconciliation chunk is intentionally
      absent.
    
    - unadopt.md: two stale references updated. The inventory table
      row and the removal-procedure description for the post-checkout
      hook both now describe the current (post-fix) hook content.
      The removal procedure explicitly handles the obsolete-line case.
    
    Generated-by: Claude Code (Opus 4.7)
---
 .claude/skills/setup-steward/adopt.md             | 42 +++++++++++++-------
 .claude/skills/setup-steward/unadopt.md           | 17 +++++---
 tools/agent-isolation/git-global-post-checkout.sh | 48 ++++++++++-------------
 3 files changed, 60 insertions(+), 47 deletions(-)

diff --git a/.claude/skills/setup-steward/adopt.md 
b/.claude/skills/setup-steward/adopt.md
index 05e1067..1a56ce8 100644
--- a/.claude/skills/setup-steward/adopt.md
+++ b/.claude/skills/setup-steward/adopt.md
@@ -541,10 +541,9 @@ collected values substituted in (leaving any unanswered 
field as
 
 ## Step 10 — Worktree-aware post-checkout hook (FRESH only)
 
-Install `<repo-root>/.git/hooks/post-checkout` that re-creates
-the gitignored symlinks if a fresh worktree is checked out
-**and** chains into the sandbox-allowlist helper installed by
-`setup-isolated-setup-install` so the new worktree's working
+Install `<repo-root>/.git/hooks/post-checkout` that chains into
+the sandbox-allowlist helper installed by
+`setup-isolated-setup-install`, so the new worktree's working
 directory is added to the worktree's own
 `.claude/settings.local.json`'s `sandbox.filesystem.allowRead` /
 `allowWrite` (defensive against
@@ -552,28 +551,24 @@ directory is added to the worktree's own
 — see
 [`setup-isolated-setup-install/SKILL.md` → Step 
P](../setup-isolated-setup-install/SKILL.md#step-p--project-root-coverage-in-the-sandbox-allowlists)).
 
-The hook is a small shell script, not a one-liner. Surface the
-exact content to the user before writing:
+The hook is a small shell script. Surface the exact content to
+the user before writing:
 
 ```bash
 #!/usr/bin/env bash
 # apache-steward post-checkout hook (installed by /setup-steward adopt).
-# Two responsibilities, each idempotent:
-#   1. Reconcile gitignored framework-skill symlinks for the
-#      current worktree.
-#   2. Add the current worktree's working dir to the worktree's
-#      own .claude/settings.local.json's sandbox allowlists
-#      (per issue #197) — chains into the helper if installed by
-#      /setup-isolated-setup-install, no-op when absent.
+# Add the current worktree's working dir to the worktree's own
+# .claude/settings.local.json sandbox allowlists (per issue #197).
+# Chains into the helper if installed by /setup-isolated-setup-install;
+# no-op when the helper is absent.
 set -u
-/setup-steward verify --auto-fix-symlinks || true
 if [ -x "$HOME/.claude/scripts/sandbox-add-project-root.sh" ]; then
   "$HOME/.claude/scripts/sandbox-add-project-root.sh" || true
 fi
 exit 0
 ```
 
-The `|| true` guards keep the hook from failing the surrounding
+The `|| true` guard keeps the hook from failing the surrounding
 git operation (`git checkout`, `git worktree add`) — the hook is
 best-effort reconciliation, not a gate.
 
@@ -582,6 +577,23 @@ the helper-script line is a no-op (the `-x` test fails). 
When
 they later install the secure setup, no hook re-write is needed:
 the next `post-checkout` fires the helper automatically.
 
+**Why no framework-skill symlink reconciliation here.** Earlier
+template versions of this hook also called
+`/setup-steward verify --auto-fix-symlinks` to recreate
+gitignored symlinks after a checkout. That line printed a spurious
+`No such file or directory` error on every `git checkout` because
+`/setup-steward` is a **Claude Code slash command**, not a shell
+command, and the hook fires in the operator's shell where there is
+no slash-command dispatcher. The line has been removed.
+Symlink-drift reconciliation now happens **lazily** — the next
+time the operator opens Claude Code in the worktree, the framework
+skills' pre-flight drift check surfaces any missing symlinks and
+`/setup-steward verify` (or any skill that needs the symlink)
+prompts for the fix. Adopters whose existing hooks still contain
+the broken line should remove it; the
+[`setup-isolated-setup-update`](../setup-isolated-setup-update/SKILL.md)
+drift check surfaces stale hook content on a routine sweep.
+
 ## Step 11 — Project doc updates (FRESH only)
 
 Update two adopter-facing docs so contributors discover the
diff --git a/.claude/skills/setup-steward/unadopt.md 
b/.claude/skills/setup-steward/unadopt.md
index cd8cbf1..e04005a 100644
--- a/.claude/skills/setup-steward/unadopt.md
+++ b/.claude/skills/setup-steward/unadopt.md
@@ -89,7 +89,7 @@ every artefact).
 | Committed lock | `<committed-lock>` | exists |
 | `.gitignore` entries | `<repo-root>/.gitignore` | which of the entries from 
[`adopt.md` Step 7](adopt.md) are present |
 | Framework-skill symlinks | `<adopter-skills-dir>/` (and `.github/skills/` if 
double-symlinked) | each symlink whose target resolves into 
`<snapshot-dir>/.claude/skills/` |
-| Post-checkout hook | `<repo-root>/.git/hooks/post-checkout` | exists + 
contains `/setup-steward verify --auto-fix-symlinks` |
+| Post-checkout hook | `<repo-root>/.git/hooks/post-checkout` | exists + 
invokes `~/.claude/scripts/sandbox-add-project-root.sh` |
 | Doc section: `README.md` | `<repo-root>/README.md` | contains the `## 
Agent-assisted contribution (apache-steward)` heading |
 | Doc section: `AGENTS.md` | `<repo-root>/AGENTS.md` | contains the `## 
apache-steward framework` heading |
 | Doc section: `CONTRIBUTING.md` | `<repo-root>/CONTRIBUTING.md` | contains 
the adoption section (fallback layout) |
@@ -193,10 +193,17 @@ pointing at a deleted snapshot.
    touch a non-symlink at the same path.
 2. **Post-checkout hook.** Remove only if its content matches
    the steward recipe verbatim (i.e. the hook the adopt flow
-   wrote — a single `/setup-steward verify --auto-fix-symlinks`
-   invocation). If the hook contains additional adopter logic,
-   surface that, leave the hook in place, and tell the user
-   which line to delete by hand.
+   wrote — a single
+   `~/.claude/scripts/sandbox-add-project-root.sh` invocation
+   guarded by the `-x` test; see
+   [`adopt.md` Step 
10](adopt.md#step-10--worktree-aware-post-checkout-hook-fresh-only)
+   for the exact text). If the hook contains additional adopter
+   logic, surface that, leave the hook in place, and tell the
+   user which line to delete by hand. Hooks that still contain
+   the obsolete `/setup-steward verify --auto-fix-symlinks` line
+   (a Claude Code slash command that does not work from a shell
+   hook — removed in a later framework release) should be
+   replaced with the current Step 10 template.
 3. **Snapshot directory.** `rm -rf <snapshot-dir>/`.
 4. **Local lock.** `rm <local-lock>`.
 5. **`.gitignore` entries.** Read `<repo-root>/.gitignore`,
diff --git a/tools/agent-isolation/git-global-post-checkout.sh 
b/tools/agent-isolation/git-global-post-checkout.sh
index ba2990f..f3b4b67 100755
--- a/tools/agent-isolation/git-global-post-checkout.sh
+++ b/tools/agent-isolation/git-global-post-checkout.sh
@@ -29,28 +29,28 @@
 # across the operator's host invokes this script — for any repo,
 # not just apache-steward adopters.
 #
-# Two responsibilities, both best-effort + idempotent + `|| true`
-# so the hook never breaks the surrounding git operation:
+# One responsibility, best-effort + idempotent + `|| true` so the
+# hook never breaks the surrounding git operation:
 #
-#   1. **apache-steward symlink reconciliation.** If the working
-#      tree carries `.apache-steward.lock`, this is a steward-
-#      adopted repo and its gitignored framework-skill symlinks
-#      may need re-creating after a checkout (the symlinks point
-#      into `.apache-steward/`, which is itself gitignored). The
-#      hook calls `/setup-steward verify --auto-fix-symlinks` if
-#      that command is on PATH; if not, it falls through silently
-#      (the operator may not be in a Claude Code session, or may
-#      not have the framework installed beyond this hook).
+#   **Sandbox-allowlist for the current worktree.** If the working
+#   tree has a `.claude/` directory (i.e. it is Claude-Code-aware)
+#   and the framework's `sandbox-add-project-root.sh` helper is
+#   installed at `~/.claude/scripts/`, the hook calls the helper
+#   to populate `<worktree>/.claude/settings.local.json` with the
+#   worktree's absolute path. Defensive against the harness
+#   behaviour documented at
+#   https://github.com/apache/airflow-steward/issues/197 .
 #
-#   2. **Sandbox-allowlist for the current worktree.** If the
-#      working tree has a `.claude/` directory (i.e. it is
-#      Claude-Code-aware) and the framework's
-#      `sandbox-add-project-root.sh` helper is installed at
-#      `~/.claude/scripts/`, the hook calls the helper to populate
-#      `<worktree>/.claude/settings.local.json` with the
-#      worktree's absolute path. Defensive against the harness
-#      behaviour documented at
-#      https://github.com/apache/airflow-steward/issues/197 .
+# **Not** in this hook: apache-steward symlink reconciliation.
+# `/setup-steward verify --auto-fix-symlinks` is a Claude Code
+# slash command, not a shell command, so it cannot be invoked from
+# a `git checkout` hook running in the operator's shell — the
+# previous template version of this hook spelled out the line
+# anyway and printed a spurious "No such file or directory" error
+# on every checkout. Symlink-drift in steward-adopted repos is now
+# reconciled **lazily** — the next time the operator opens Claude
+# Code in the worktree, `/setup-steward verify` detects any drift
+# and offers to fix it.
 #
 # IMPORTANT — `core.hooksPath` shadowing. When `core.hooksPath` is
 # set globally, git looks ONLY in that directory for hooks. Every
@@ -78,13 +78,7 @@ if [ -z "$worktree" ]; then
   exit 0
 fi
 
-# 1. apache-steward symlink reconciliation
-if [ -f "$worktree/.apache-steward.lock" ] \
-    && command -v /setup-steward >/dev/null 2>&1; then
-  /setup-steward verify --auto-fix-symlinks 2>/dev/null || true
-fi
-
-# 2. Sandbox-allowlist helper
+# Sandbox-allowlist helper
 if [ -x "$HOME/.claude/scripts/sandbox-add-project-root.sh" ] \
     && [ -d "$worktree/.claude" ]; then
   "$HOME/.claude/scripts/sandbox-add-project-root.sh" 2>/dev/null || true

Reply via email to