Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/entire/cli/hooks_git_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package cli
import (
"context"
"log/slog"
"time"

"github.com/entireio/cli/cmd/entire/cli/agent/external"
"github.com/entireio/cli/cmd/entire/cli/logging"
"github.com/entireio/cli/cmd/entire/cli/settings"
"github.com/entireio/cli/cmd/entire/cli/strategy"
Expand Down Expand Up @@ -97,6 +99,13 @@ func newHooksGitCmd() *cobra.Command {
gitHooksDisabled = true
return nil
}
// Discover external agent plugins so GetByAgentType works correctly
// during condensation (e.g. post-commit). Without this, external agents
// registered in the hook phase cannot be resolved here, causing token
// usage and other agent-specific data to be missing from metadata.json.
discoveryCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
external.DiscoverAndRegister(discoveryCtx)
hookLogCleanup = initHookLogging(ctx)
return nil
},
Expand Down
78 changes: 78 additions & 0 deletions cmd/entire/cli/hooks_git_cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"testing"
"time"

"github.com/entireio/cli/cmd/entire/cli/agent"
"github.com/entireio/cli/cmd/entire/cli/agent/types"
"github.com/entireio/cli/cmd/entire/cli/paths"
"github.com/entireio/cli/cmd/entire/cli/session"
)
Expand Down Expand Up @@ -167,3 +169,79 @@ func TestInitHookLogging_SkipsWhenDisabled(t *testing.T) {
t.Errorf("expected .entire/logs to NOT be created when Entire is disabled, but it exists")
}
}

// TestHooksGitCmd_DiscoverExternalAgents_WhenEnabled verifies that when Entire is set up
// and enabled, PersistentPreRunE calls external.DiscoverAndRegister so that external
// agents are available during hook execution (e.g. post-commit condensation).
func TestHooksGitCmd_DiscoverExternalAgents_WhenEnabled(t *testing.T) {
if _, err := exec.LookPath("sh"); err != nil {
t.Skip("sh not available")
}

tmpDir := t.TempDir()

// Initialize git repo first, then chdir so paths cache is correct
gitInit := exec.CommandContext(context.Background(), "git", "init")
gitInit.Dir = tmpDir
if err := gitInit.Run(); err != nil {
t.Fatalf("failed to init git repo: %v", err)
}

t.Chdir(tmpDir)
paths.ClearWorktreeRootCache()
session.ClearGitCommonDirCache()

// Reset global state before the test
gitHooksDisabled = false

// Create .entire/settings.json with enabled: true and external_agents: true
entireDir := filepath.Join(tmpDir, paths.EntireDir)
if err := os.MkdirAll(entireDir, 0o755); err != nil {
t.Fatalf("failed to create .entire directory: %v", err)
}
settingsFile := filepath.Join(entireDir, "settings.json")
if err := os.WriteFile(settingsFile, []byte(`{"enabled":true,"external_agents":true}`), 0o644); err != nil {
t.Fatalf("failed to write settings file: %v", err)
}

// Create a mock external agent binary in a temp PATH directory.
// Use a unique name to avoid conflicts with agents registered by other tests.
agentName := types.AgentName("hooktest-discovery-agent")
binDir := t.TempDir()
binPath := filepath.Join(binDir, "entire-agent-"+string(agentName))
infoJSON := `{
"protocol_version": 1,
"name": "` + string(agentName) + `",
"type": "Hook Test Agent",
"description": "Agent for hook discovery test",
"is_preview": false,
"protected_dirs": [],
"hook_names": [],
"capabilities": {}
}`
script := "#!/bin/sh\nif [ \"$1\" = \"info\" ]; then\n echo '" + infoJSON + "'\nfi\n"
if err := os.WriteFile(binPath, []byte(script), 0o755); err != nil {
t.Fatalf("failed to write mock agent binary: %v", err)
}
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))

// Execute the git hook command (post-commit) so PersistentPreRunE runs
cmd := newHooksGitCmd()
cmd.SetArgs([]string{"post-commit"})
ctx := context.Background()
cmd.SetContext(ctx)
if err := cmd.Execute(); err != nil {
t.Fatalf("git hook command failed: %v", err)
}

// PersistentPreRunE should not have disabled hooks
if gitHooksDisabled {
t.Fatal("gitHooksDisabled should be false when Entire is enabled")
}

// The external agent should have been discovered and registered in the agent registry,
// confirming that DiscoverAndRegister was called during PersistentPreRunE.
if _, err := agent.Get(agentName); err != nil {
t.Errorf("expected external agent %q to be registered after hook pre-run, got: %v", agentName, err)
}
}
Loading