Skip to content

Fall back to PATH binary when local-dev build is broken#1274

Merged
pjbgf merged 1 commit into
mainfrom
hook-dev
May 28, 2026
Merged

Fall back to PATH binary when local-dev build is broken#1274
pjbgf merged 1 commit into
mainfrom
hook-dev

Conversation

@pjbgf
Copy link
Copy Markdown
Member

@pjbgf pjbgf commented May 27, 2026

https://entire.io/gh/entireio/cli/trails/433

In local-dev mode every Entire hook runs the CLI straight from source via go run .../cmd/entire/main.go, recompiling on demand. That coupling makes hooks only as reliable as the current tree: the moment the project stops compiling — most commonly while an agent is resolving a merge conflict — the go run build fails and the hook silently does nothing. The session is not checkpointed, the commit trailer is not added, and there is no signal that anything went wrong. The one situation where checkpointing matters most is the one where it quietly stops working.

The fallback cannot live in main.go: when the tree is broken, main.go never compiles, so it never runs. The decision "run fresh code vs. run the installed binary" has to be made by something outside that build.

Introduce scripts/entire-dev, a single committed launcher that all local-dev hooks delegate to. It probes the build with go build; on success it execs go run (fresh code, warmed by the probe's build cache), and on failure it falls back to an entire binary on PATH, logging the reason to stderr. When neither is available it exits 0 so it never blocks the surrounding git or agent operation. Centralising the logic in one script keeps shell branching out of the generated hook commands (it was previously a sprawl of sh -c 'if ... elif ... fi' strings), gives one place to test, and logs clearly which path it took.

Wiring, every local-dev hook path now routes through the launcher:

  • git hooks (strategy): local-dev prefix points at ./scripts/entire-dev
  • all eight agents: claude-code via ${CLAUDE_PROJECT_DIR}/scripts/entire-dev, the git-rev-parse agents (codex, cursor, gemini-cli, copilot-cli, factoryai-droid, opencode, pi) via the shared agent.LocalDevHookScript const
  • this repo's own .claude/settings.json dev hooks, so the fix applies here

Each agent keeps the old go run .../cmd/entire/main.go prefix in its detection list so hooks installed by older versions are still recognised for clean upgrade and uninstall.

Tests run the real script against a non-building tree (build probe fails) and assert it falls back to a fake entire on PATH, logs the fallback, forwards args verbatim, and exits 0 when nothing is available; agent and integration suites assert hooks delegate to scripts/entire-dev rather than embedding go run.


Note

Medium Risk
Changes how every local-dev git and agent hook invokes the CLI; mitigated by PATH fallback, exit-0 when unavailable, and broad test coverage, but still touches critical checkpoint/commit hook paths.

Overview
Local-dev Entire hooks no longer invoke go run …/cmd/entire/main.go directly. They now call a committed scripts/entire-dev launcher that probes whether the tree builds, runs fresh code via go run when it does, and otherwise falls back to an entire binary on PATH (logging to stderr). If neither works, it exits 0 so git/agent workflows are not blocked—addressing silent hook failures when the repo does not compile (e.g. during merge conflicts).

Wiring: git hooks use ./scripts/entire-dev; Claude Code uses ${CLAUDE_PROJECT_DIR}/scripts/entire-dev; other agents share agent.LocalDevHookScript (git rev-parse + scripts/entire-dev). This repo’s .claude/settings.json is updated accordingly. Older go run hook prefixes remain in detection lists for clean upgrade/uninstall.

Tests and docs/architecture/agent-guide.md assert delegation to the script (no embedded build/fallback shell in generated hook commands) and exercise the launcher’s fallback and no-op paths.

Reviewed by Cursor Bugbot for commit 0ef509d. Configure here.

In local-dev mode every Entire hook runs the CLI straight from source via
`go run .../cmd/entire/main.go`, recompiling on demand. That coupling makes
hooks only as reliable as the current tree: the moment the project stops
compiling — most commonly while an agent is resolving a merge conflict — the
`go run` build fails and the hook silently does nothing. The session is not
checkpointed, the commit trailer is not added, and there is no signal that
anything went wrong. The one situation where checkpointing matters most is the
one where it quietly stops working.

The fallback cannot live in main.go: when the tree is broken, main.go never
compiles, so it never runs. The decision "run fresh code vs. run the installed
binary" has to be made by something outside that build.

Introduce scripts/entire-dev, a single committed launcher that all local-dev
hooks delegate to. It probes the build with `go build`; on success it execs
`go run` (fresh code, warmed by the probe's build cache), and on failure it
falls back to an `entire` binary on PATH, logging the reason to stderr. When
neither is available it exits 0 so it never blocks the surrounding git or agent
operation. Centralising the logic in one script keeps shell branching out of
the generated hook commands (it was previously a sprawl of `sh -c 'if ... elif
... fi'` strings), gives one place to test, and logs clearly which path it took.

Wiring, every local-dev hook path now routes through the launcher:
- git hooks (strategy): local-dev prefix points at ./scripts/entire-dev
- all eight agents: claude-code via ${CLAUDE_PROJECT_DIR}/scripts/entire-dev,
  the git-rev-parse agents (codex, cursor, gemini-cli, copilot-cli,
  factoryai-droid, opencode, pi) via the shared agent.LocalDevHookScript const
- this repo's own .claude/settings.json dev hooks, so the fix applies here

Each agent keeps the old `go run .../cmd/entire/main.go` prefix in its
detection list so hooks installed by older versions are still recognised for
clean upgrade and uninstall.

Tests run the real script against a non-building tree (build probe fails) and
assert it falls back to a fake `entire` on PATH, logs the fallback, forwards
args verbatim, and exits 0 when nothing is available; agent and integration
suites assert hooks delegate to scripts/entire-dev rather than embedding go run.

Assisted-by: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: Paulo Gomes <paulo@entire.io>
Entire-Checkpoint: 9063f5a3926c
Copilot AI review requested due to automatic review settings May 27, 2026 11:26
@pjbgf pjbgf requested a review from a team as a code owner May 27, 2026 11:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes local-dev hook execution resilient when the working tree doesn’t compile by routing all local-dev git/agent hooks through a committed launcher script (scripts/entire-dev) that probes buildability and falls back to an entire binary on PATH when needed.

Changes:

  • Added scripts/entire-dev launcher: go build probe → go run when buildable, otherwise exec entire, otherwise log + exit 0.
  • Updated git hook generation (strategy) and all agent hook installers to delegate to scripts/entire-dev (while retaining legacy go run ...main.go prefixes for detection/upgrade/uninstall).
  • Added/updated unit and integration tests to assert delegation to the launcher and to exercise the fallback/no-op paths; updated agent architecture docs and this repo’s .claude/settings.json accordingly.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated no comments.

Show a summary per file
File Description
scripts/entire-dev New local-dev launcher that probes compilation and falls back to entire on PATH (or exits 0).
docs/architecture/agent-guide.md Documentation updated to reflect agent.LocalDevHookScript / scripts/entire-dev delegation.
cmd/entire/cli/strategy/hooks.go Git hook local-dev prefix changed to ./scripts/entire-dev.
cmd/entire/cli/strategy/hooks_test.go New tests validating delegation and launcher fallback/no-op behavior.
cmd/entire/cli/strategy/hook_managers.go Updated comments/examples to match new local-dev prefix.
cmd/entire/cli/strategy/hook_managers_test.go Updated assertions for new local-dev hook prefix in warnings.
cmd/entire/cli/integration_test/agent_test.go Integration assertions updated to require scripts/entire-dev delegation.
cmd/entire/cli/agent/hook_command.go Added LocalDevHookScript constant for shared agent local-dev prefix.
cmd/entire/cli/agent/*/hooks.go Agents updated to use agent.LocalDevHookScript (or Claude’s ${CLAUDE_PROJECT_DIR} variant).
cmd/entire/cli/agent/*/hooks_test.go Tests updated to assert scripts/entire-dev delegation strings.
.claude/settings.json Repo’s Claude Code dev hooks updated to call scripts/entire-dev.

@pjbgf pjbgf enabled auto-merge May 27, 2026 13:35
@pjbgf pjbgf changed the title Fall back to PATH binary when local-dev build is broken Fall back to PATH binary when local-dev build is broken May 28, 2026
@pjbgf pjbgf merged commit 35c9bdd into main May 28, 2026
11 checks passed
@pjbgf pjbgf deleted the hook-dev branch May 28, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants