Skip to content

install-git-hooks --check calls a correctly hand-wired core.hooksPath clone ungated #1509

Description

@bmethod

Summary

install-git-hooks --check exits 1 for a core.hooksPath clone even when that
directory has been wired exactly the way the installer itself prescribes,
and the verdict line then states something false: "commits are NOT gated".

The check never looks at the redirected directory. check_shims only ever reads
$HOOKS_DIR ($(git rev-parse --git-path hooks)), and the HOOKS_PATH_SET
branch converts a clean result into "dormant … exit 1" without probing
$CUSTOM_HOOKS.

Why it matters

The installer stands down under core.hooksPath on purpose and prints the
hand-wiring instructions. A consumer that follows those instructions is fully
gated — and --check still calls them ungated. Any consumer that puts
--check into a canonical validation command (drovr now has it first in
pnpm verify, DRO-258) makes that command permanently red for a configuration
the installer's own output told the user to adopt.

Reproduction

mkdir -p /tmp/hp/customhooks && cd /tmp/hp && git init -q .
install-git-hooks --repo /tmp/hp                       # normal install
# wire the redirected directory exactly as the installer prescribes
S=<growth-guards>/scripts
printf '#!/bin/sh\nexec %s/pre-commit "$@"\n'  "$S" > customhooks/pre-commit
printf '#!/bin/sh\nexec %s/commit-msg "$1"\n'  "$S" > customhooks/commit-msg
chmod +x customhooks/pre-commit customhooks/commit-msg
git config core.hooksPath customhooks

install-git-hooks --repo /tmp/hp --check

Observed:

growth-guards git hooks: dormant — core.hooksPath ('customhooks') redirects git
away from /tmp/hp/.git/hooks, so commits are NOT gated; wire that directory's
hooks to <…>/scripts, or unset core.hooksPath
exit 1

Commits in that clone ARE gated. Exit 1 with that wording is wrong on both counts.

Suggested fix

When core.hooksPath is set, resolve it (relative to the work tree, as git
does) and run the same check_hook predicate against $CUSTOM_HOOKS/pre-commit
and $CUSTOM_HOOKS/commit-msg — the wiring the installer prints is a shim that
execs the chain, so the predicate needs a second accepted shape ("delegates to
this skill's pre-commit/commit-msg") beside the line-2 sentinel it matches
today. Three outcomes rather than one:

  • redirected directory wired to this skill → armed (exit 0), stating that
    the gating is via core.hooksPath;
  • redirected directory present but not wired → dormant / NOT armed (exit 1),
    which is today's message and is then accurate;
  • redirected directory unreadable → could not determine (exit 2), matching
    the fail-to-measure rule the rest of --check already follows.

Keeping the conservative exit 1 for the unwired case is right; it is the wired
case that has no way to report the truth today.

Notes

Found while adopting vstack#1482 in drovr (vanillagreencom/drovr#598). drovr is
keeping --check first in pnpm verify regardless, because the un-hand-wired
case really is ungated and that is the safe failure direction — the bound is
recorded there rather than worked around.

Metadata

Metadata

Assignees

No one assigned

    Labels

    skillsskills/, agents/, skill-templates/, and base agent instructions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions