Summary
The lrc-managed git hooks fail to locate an existing attestation when committing inside a linked git worktree (git worktree add). Even after a successful lrc review / lrc review --vouch / lrc review --skip, the commit is rejected with:
LiveReview: review attestation missing for staged changes. Run 'lrc review --staged' (or --skip/--vouch) and retry commit.
lrc_version: v0.3.9 (from the managed hook section header).
Root cause
The hooks locate the attestation using a hardcoded relative path .git/lrc/.... In a linked worktree, .git is not a directory — it is a pointer file whose contents are gitdir: /path/to/main/.git/worktrees/<name>. So .git/lrc/attestations/<tree>.json never resolves, and the [ -f "$ATTEST_FILE" ] test always fails.
Meanwhile lrc review writes the attestation to the per-worktree git dir, i.e. <main>/.git/worktrees/<name>/lrc/attestations/<tree>.json — which is exactly where git rev-parse --git-dir points from inside the worktree. So the file is written to one location and looked up in another.
Notably, the hooks already compute the correct dir but don't use it. In lrc/prepare-commit-msg and lrc/commit-msg:
LRC_DIR=".git/lrc" # <-- hardcoded, breaks in worktrees
ATTEST_DIR="$LRC_DIR/attestations"
...
GIT_DIR="$(git rev-parse --git-dir 2>/dev/null || echo .git)" # computed but never used for ATTEST_DIR
...
TREE_HASH="$(git write-tree 2>/dev/null || true)"
ATTEST_FILE="$ATTEST_DIR/$TREE_HASH.json"
And in lrc/pre-commit:
TREE_HASH="$(git write-tree 2>/dev/null || true)"
ATTEST_FILE=".git/lrc/attestations/$TREE_HASH.json" # <-- same hardcoded .git
All three hooks (pre-commit, prepare-commit-msg, commit-msg) share this bug.
Reproduction
# main repo
git init main && cd main
echo a > a.txt && git add a.txt
lrc review --skip # writes attestation, commit works here
git commit -m "init"
# linked worktree on a new branch
git worktree add ../wt -b feature
cd ../wt
echo b > b.txt && git add b.txt
lrc review --skip # reports success; attestation written to
# <main>/.git/worktrees/wt/lrc/attestations/<tree>.json
git commit -m "change" # FAILS: "review attestation missing for staged changes"
You can confirm the attestation exists and matches the staged tree:
git write-tree
# -> <tree-hash> (matches the .json filename under the per-worktree git dir)
cat "$(git rev-parse --git-dir)/lrc/attestations/<tree-hash>.json"
# -> {"action":"vouched",...} (present and correct)
Expected
Inside a linked worktree, a valid attestation produced by lrc review for the current staged tree should let the commit proceed, exactly as in a normal (non-worktree) checkout.
Actual
The commit is rejected because the hooks look under the literal .git/lrc/... relative path, which is invalid in a worktree (.git is a file, not a directory).
Suggested fix
Derive the lrc dir from git instead of hardcoding .git. The hooks already compute GIT_DIR; just use it:
GIT_DIR="$(git rev-parse --git-dir 2>/dev/null || echo .git)"
LRC_DIR="$GIT_DIR/lrc"
ATTEST_DIR="$LRC_DIR/attestations"
(git rev-parse --git-dir returns the per-worktree git dir, matching where the CLI writes the attestation. If attestations are intended to be shared across worktrees, --git-common-dir would be the alternative — but the CLI currently writes to the per-worktree dir, so --git-dir keeps hook and CLI consistent.) The same substitution is needed in pre-commit (which inlines the literal .git/lrc/attestations/...).
The .git/lrc/disabled check at the top of the hooks has the same hardcoded-path issue and should use $GIT_DIR/lrc/disabled too — otherwise the hook cannot be disabled from within a worktree either.
Workaround note
git commit --no-verify does not help, because the attestation check also runs in prepare-commit-msg, which git does not skip with --no-verify (it only skips pre-commit and commit-msg). A one-shot git -c core.hooksPath=<empty-dir> commit ... after a genuine lrc review/--vouch is the only clean bypass until this is fixed.
Environment
- OS: macOS
- git: 2.50.1
- git-lrc: v0.3.9
Summary
The lrc-managed git hooks fail to locate an existing attestation when committing inside a linked git worktree (
git worktree add). Even after a successfullrc review/lrc review --vouch/lrc review --skip, the commit is rejected with:lrc_version: v0.3.9(from the managed hook section header).Root cause
The hooks locate the attestation using a hardcoded relative path
.git/lrc/.... In a linked worktree,.gitis not a directory — it is a pointer file whose contents aregitdir: /path/to/main/.git/worktrees/<name>. So.git/lrc/attestations/<tree>.jsonnever resolves, and the[ -f "$ATTEST_FILE" ]test always fails.Meanwhile
lrc reviewwrites the attestation to the per-worktree git dir, i.e.<main>/.git/worktrees/<name>/lrc/attestations/<tree>.json— which is exactly wheregit rev-parse --git-dirpoints from inside the worktree. So the file is written to one location and looked up in another.Notably, the hooks already compute the correct dir but don't use it. In
lrc/prepare-commit-msgandlrc/commit-msg:And in
lrc/pre-commit:All three hooks (
pre-commit,prepare-commit-msg,commit-msg) share this bug.Reproduction
You can confirm the attestation exists and matches the staged tree:
Expected
Inside a linked worktree, a valid attestation produced by
lrc reviewfor the current staged tree should let the commit proceed, exactly as in a normal (non-worktree) checkout.Actual
The commit is rejected because the hooks look under the literal
.git/lrc/...relative path, which is invalid in a worktree (.gitis a file, not a directory).Suggested fix
Derive the lrc dir from git instead of hardcoding
.git. The hooks already computeGIT_DIR; just use it:(
git rev-parse --git-dirreturns the per-worktree git dir, matching where the CLI writes the attestation. If attestations are intended to be shared across worktrees,--git-common-dirwould be the alternative — but the CLI currently writes to the per-worktree dir, so--git-dirkeeps hook and CLI consistent.) The same substitution is needed inpre-commit(which inlines the literal.git/lrc/attestations/...).The
.git/lrc/disabledcheck at the top of the hooks has the same hardcoded-path issue and should use$GIT_DIR/lrc/disabledtoo — otherwise the hook cannot be disabled from within a worktree either.Workaround note
git commit --no-verifydoes not help, because the attestation check also runs inprepare-commit-msg, which git does not skip with--no-verify(it only skipspre-commitandcommit-msg). A one-shotgit -c core.hooksPath=<empty-dir> commit ...after a genuinelrc review/--vouchis the only clean bypass until this is fixed.Environment