gate hooks on checkpoint policy · Entire
gate hooks on checkpoint policy
Make agent hooks surface unsupported checkpoint policy loudly while Git hooks skip checkpoint work without blocking Git.
Sessions
Changes
9
cmd/entire/cli
Mhook_registry.go+76/-1
- Mhook_registry_test.go+93
- Mhooks_git_cmd.go+44
- Mhooks_git_cmd_test.go+45
- strategy
- Mcheckpoint_policy.go+24/-10
- Mcheckpoint_policy_test.go+9/-13
- Mmanual_commit_condensation.go+4/-1
- Mmanual_commit_hooks.go+6/-1
- Mmanual_commit_push.go+3
3 unmodified lines
package cli
import (
"context"
"errors"
"fmt"
"io"
"log/slog"
"strings"
"github.com/entireio/cli/cmd/entire/cli/agent"
"github.com/entireio/cli/cmd/entire/cli/agent/claudecode"
"github.com/entireio/cli/cmd/entire/cli/agent/geminicli"
"github.com/entireio/cli/cmd/entire/cli/agent/types"
"github.com/entireio/cli/cmd/entire/cli/checkpointpolicy"
"github.com/entireio/cli/cmd/entire/cli/gitrepo"
"github.com/entireio/cli/cmd/entire/cli/logging"
"github.com/entireio/cli/cmd/entire/cli/paths"
"github.com/entireio/cli/cmd/entire/cli/strategy"
"github.com/entireio/cli/cmd/entire/cli/versioncheck"
"github.com/entireio/cli/cmd/entire/cli/versioninfo"
"github.com/entireio/cli/perf"
"github.com/spf13/cobra"
)
// their parent command's PersistentPreRunE already handles logging.
func executeAgentHook(cmd *cobra.Command, agentName types.AgentName, hookName string, initLogging bool) error {
// Skip silently if not in a git repository - hooks shouldn't prevent the agent from working
if _, err := paths.WorktreeRoot(cmd.Context()); err != nil {
worktreeRoot, err := paths.WorktreeRoot(cmd.Context())
if err != nil {
return nil
}
}
// remaining function implementation omitted for brevity
}
func shouldSkipAgentHookForPolicy(ctx context.Context, worktreeRoot string, errW io.Writer, ag agent.Agent, eventType agent.EventType) (skipHook bool, err error) {
repo, err := gitrepo.OpenPath(worktreeRoot)
if err != nil {
logging.Warn(ctx, "checkpoint policy read skipped for agent hook",
slog.String("error", err.Error()))
return false, nil
}
defer repo.Close()
policy := localCheckpointPolicyForNewCheckpoint(ctx, repo)
if checkpointpolicy.CanSatisfyPolicy(policy) {
return false, nil
}
if eventType == agent.SessionStart {
return true, writeUnsupportedPolicySessionStartWarning(errW, ag, sessionStartPolicyWarning(policy))
}
fmt.Fprint(errW, agentCheckpointCaptureDisabledMessage(policy))
return false, NewSilentError(errUnsupportedCheckpointPolicy)
}
func sessionStartPolicyWarning(policy checkpointpolicy.Policy) string {
message := "Entire CLI is enabled, but this repository's checkpoint policy requires a newer Entire CLI. No Entire checkpoints will be created for this session until you upgrade."
details := strings.TrimSpace(checkpointpolicy.UnsupportedPolicyMessage(policy, versioncheck.UpdateCommandForCurrentBinary(versioninfo.Version)))
if details == "" {
return message
}
return message + "\n\n" + details
}
func agentCheckpointCaptureDisabledMessage(policy checkpointpolicy.Policy) string {
var b strings.Builder
b.WriteString("[entire] Checkpoint capture is disabled for this repository.\n")
b.WriteString("[entire] No Entire checkpoints will be created until the CLI is upgraded.\n")
if details := strings.TrimSpace(checkpointpolicy.UnsupportedPolicyMessage(policy, versioncheck.UpdateCommandForCurrentBinary(versioninfo.Version))); details != "" {
b.WriteString(details)
b.WriteByte('\n')
}
return b.String()
}
func writeUnsupportedPolicySessionStartWarning(errW io.Writer, ag agent.Agent, message string) error {
if writer, ok := agent.AsHookResponseWriter(ag); ok {
if err := writer.WriteHookResponse(message); err != nil {
return fmt.Errorf("failed to write hook response: %w", err)
}
return nil
}
fmt.Fprintln(errW, message)
return nil
}
// Test functions and additional implementations omitted for brevity.