From 425f2a31739884924a8dc53b009351164ac8d2ab Mon Sep 17 00:00:00 2001 From: Peyton Montei Date: Thu, 2 Apr 2026 15:03:44 -0700 Subject: [PATCH 1/3] fix: allow checkpoint trailers on agent-initiated sequence operations When an agent runs git revert or cherry-pick as part of its work, the commit should be checkpointed. Previously prepare-commit-msg unconditionally skipped during sequence operations, making the agent's work invisible to Entire. Now checks for active sessions: if an agent session is ACTIVE, the operation is agent-initiated and gets a trailer. If no active session, it's user-initiated and is skipped as before. Part of fix for #834. Co-Authored-By: Claude Opus 4.6 (1M context) Entire-Checkpoint: 85df9ac94bc7 --- .../cli/strategy/manual_commit_hooks.go | 16 +++- .../cli/strategy/manual_commit_session.go | 21 +++++ cmd/entire/cli/strategy/manual_commit_test.go | 93 +++++++++++++++++++ 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/cmd/entire/cli/strategy/manual_commit_hooks.go b/cmd/entire/cli/strategy/manual_commit_hooks.go index f4986daa9..60042e246 100644 --- a/cmd/entire/cli/strategy/manual_commit_hooks.go +++ b/cmd/entire/cli/strategy/manual_commit_hooks.go @@ -309,14 +309,22 @@ func isGitSequenceOperation(ctx context.Context) bool { func (s *ManualCommitStrategy) PrepareCommitMsg(ctx context.Context, commitMsgFile string, source string) error { logCtx := logging.WithComponent(ctx, "checkpoint") - // Skip during rebase, cherry-pick, or revert operations - // These are replaying existing commits and should not be linked to agent sessions + // Skip during rebase, cherry-pick, or revert operations — UNLESS an agent + // session is ACTIVE. When an agent runs git revert/cherry-pick as part of + // its work, the commit should be checkpointed. When the user does it + // manually (no active session), skip as before. if isGitSequenceOperation(ctx) { - logging.Debug(logCtx, "prepare-commit-msg: skipped during git sequence operation", + if !s.hasActiveSessionInWorktree(ctx) { + logging.Debug(logCtx, "prepare-commit-msg: skipped during git sequence operation (no active session)", + slog.String("strategy", "manual-commit"), + slog.String("source", source), + ) + return nil + } + logging.Debug(logCtx, "prepare-commit-msg: sequence operation with active session, proceeding", slog.String("strategy", "manual-commit"), slog.String("source", source), ) - return nil } // Skip for merge and squash sources diff --git a/cmd/entire/cli/strategy/manual_commit_session.go b/cmd/entire/cli/strategy/manual_commit_session.go index ad4d852fd..bb7bc9f7b 100644 --- a/cmd/entire/cli/strategy/manual_commit_session.go +++ b/cmd/entire/cli/strategy/manual_commit_session.go @@ -148,6 +148,27 @@ func (s *ManualCommitStrategy) findSessionsForWorktree(ctx context.Context, work return matching, nil } +// hasActiveSessionInWorktree returns true if any session in the current worktree +// is in ACTIVE phase. Used to distinguish agent-initiated git operations (revert, +// cherry-pick) from user-initiated ones. Agent-initiated operations should be +// checkpointed; user-initiated ones should be skipped. +func (s *ManualCommitStrategy) hasActiveSessionInWorktree(ctx context.Context) bool { + worktreePath, err := paths.WorktreeRoot(ctx) + if err != nil { + return false + } + sessions, err := s.findSessionsForWorktree(ctx, worktreePath) + if err != nil { + return false + } + for _, state := range sessions { + if state.Phase.IsActive() { + return true + } + } + return false +} + // findSessionsForCommit finds all sessions where base_commit matches the given SHA. func (s *ManualCommitStrategy) findSessionsForCommit(ctx context.Context, baseCommitSHA string) ([]*SessionState, error) { allStates, err := s.listAllSessionStates(ctx) diff --git a/cmd/entire/cli/strategy/manual_commit_test.go b/cmd/entire/cli/strategy/manual_commit_test.go index a256dd64b..1deb075bd 100644 --- a/cmd/entire/cli/strategy/manual_commit_test.go +++ b/cmd/entire/cli/strategy/manual_commit_test.go @@ -15,10 +15,12 @@ import ( "github.com/entireio/cli/cmd/entire/cli/checkpoint" "github.com/entireio/cli/cmd/entire/cli/checkpoint/id" "github.com/entireio/cli/cmd/entire/cli/paths" + "github.com/entireio/cli/cmd/entire/cli/session" "github.com/entireio/cli/cmd/entire/cli/trailers" "github.com/go-git/go-git/v6" "github.com/go-git/go-git/v6/plumbing" "github.com/go-git/go-git/v6/plumbing/object" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -824,6 +826,97 @@ func TestShadowStrategy_PrepareCommitMsg_SkipSources(t *testing.T) { } } +// TestShadowStrategy_PrepareCommitMsg_AgentRevertGetsTrailer verifies that when an +// agent runs git revert (REVERT_HEAD exists) and the session is ACTIVE, the commit +// gets a checkpoint trailer. The agent's work should be checkpointed. +func TestShadowStrategy_PrepareCommitMsg_AgentRevertGetsTrailer(t *testing.T) { + dir := setupGitRepo(t) + t.Chdir(dir) + t.Setenv("ENTIRE_TEST_TTY", "1") + + s := &ManualCommitStrategy{} + + // Create an ACTIVE session (agent is running) + err := s.InitializeSession(context.Background(), "agent-revert-session", agent.AgentTypeClaudeCode, "", "revert the change", "") + require.NoError(t, err) + + // Save a checkpoint so there's content + metaDir := filepath.Join(".entire", "metadata", "agent-revert-session") + require.NoError(t, os.MkdirAll(filepath.Join(dir, metaDir), 0o755)) + transcript := `{"type":"human","message":{"content":"revert the change"}}` + "\n" + + `{"type":"assistant","message":{"content":"I'll revert that"}}` + "\n" + require.NoError(t, os.WriteFile(filepath.Join(dir, metaDir, "full.jsonl"), []byte(transcript), 0o644)) + + err = s.SaveStep(context.Background(), StepContext{ + SessionID: "agent-revert-session", + MetadataDir: metaDir, + ModifiedFiles: []string{"test.txt"}, + NewFiles: []string{}, + AgentType: agent.AgentTypeClaudeCode, + }) + require.NoError(t, err) + + // Simulate REVERT_HEAD existing (git revert in progress) + gitDir, err := GetGitDir(context.Background()) + require.NoError(t, err) + revertHeadPath := filepath.Join(gitDir, "REVERT_HEAD") + require.NoError(t, os.WriteFile(revertHeadPath, []byte("fake-revert-head"), 0o644)) + defer os.Remove(revertHeadPath) + + // PrepareCommitMsg should add a trailer (active session = agent doing the revert) + commitMsgFile := filepath.Join(t.TempDir(), "COMMIT_EDITMSG") + require.NoError(t, os.WriteFile(commitMsgFile, []byte("Revert \"add feature\"\n"), 0o644)) + + err = s.PrepareCommitMsg(context.Background(), commitMsgFile, "") + require.NoError(t, err) + + content, err := os.ReadFile(commitMsgFile) + require.NoError(t, err) + + _, found := trailers.ParseCheckpoint(string(content)) + assert.True(t, found, "agent-initiated revert should get a checkpoint trailer") +} + +// TestShadowStrategy_PrepareCommitMsg_UserRevertSkipped verifies that when a user +// runs git revert manually (no ACTIVE session), the commit does NOT get a trailer. +func TestShadowStrategy_PrepareCommitMsg_UserRevertSkipped(t *testing.T) { + dir := setupGitRepo(t) + t.Chdir(dir) + t.Setenv("ENTIRE_TEST_TTY", "1") + + s := &ManualCommitStrategy{} + + // Create an IDLE session (agent finished, user is now doing manual work) + err := s.InitializeSession(context.Background(), "idle-session-revert", agent.AgentTypeClaudeCode, "", "done", "") + require.NoError(t, err) + + state, err := s.loadSessionState(context.Background(), "idle-session-revert") + require.NoError(t, err) + require.NoError(t, TransitionAndLog(context.Background(), state, session.EventTurnEnd, session.TransitionContext{}, session.NoOpActionHandler{})) + require.NoError(t, s.saveSessionState(context.Background(), state)) + + // Simulate REVERT_HEAD existing + gitDir, err := GetGitDir(context.Background()) + require.NoError(t, err) + revertHeadPath := filepath.Join(gitDir, "REVERT_HEAD") + require.NoError(t, os.WriteFile(revertHeadPath, []byte("fake-revert-head"), 0o644)) + defer os.Remove(revertHeadPath) + + // PrepareCommitMsg should skip (no ACTIVE session = user doing the revert) + commitMsgFile := filepath.Join(t.TempDir(), "COMMIT_EDITMSG") + originalMsg := "Revert \"add feature\"\n" + require.NoError(t, os.WriteFile(commitMsgFile, []byte(originalMsg), 0o644)) + + err = s.PrepareCommitMsg(context.Background(), commitMsgFile, "") + require.NoError(t, err) + + content, err := os.ReadFile(commitMsgFile) + require.NoError(t, err) + + _, found := trailers.ParseCheckpoint(string(content)) + assert.False(t, found, "user-initiated revert (no active session) should not get a trailer") +} + func TestAddCheckpointTrailer_NoComment(t *testing.T) { // Test that addCheckpointTrailer adds trailer without any comment lines message := "Test commit message\n" //nolint:goconst // already present in codebase From 9164d8e25c1bacdb7af783663c07c11692be7b9b Mon Sep 17 00:00:00 2001 From: Peyton Montei Date: Thu, 2 Apr 2026 15:31:14 -0700 Subject: [PATCH 2/3] feat: store tree hash in checkpoint metadata Add tree_hash field to committed checkpoint metadata. Records the git tree hash of the commit being condensed, enabling fallback checkpoint lookup by tree hash when the Entire-Checkpoint trailer is stripped by git history rewrites (rebase, filter-branch, amend). Part of fix for #834. Co-Authored-By: Claude Opus 4.6 (1M context) Entire-Checkpoint: 77773a25069e --- cmd/entire/cli/checkpoint/checkpoint.go | 10 ++++++ cmd/entire/cli/checkpoint/checkpoint_test.go | 35 +++++++++++++++++++ cmd/entire/cli/checkpoint/committed.go | 1 + .../strategy/manual_commit_condensation.go | 2 ++ .../cli/strategy/manual_commit_hooks.go | 2 ++ 5 files changed, 50 insertions(+) diff --git a/cmd/entire/cli/checkpoint/checkpoint.go b/cmd/entire/cli/checkpoint/checkpoint.go index 75ab1ed66..34993dc35 100644 --- a/cmd/entire/cli/checkpoint/checkpoint.go +++ b/cmd/entire/cli/checkpoint/checkpoint.go @@ -262,6 +262,11 @@ type WriteCommittedOptions struct { // Model is the LLM model used during the session (e.g., "claude-sonnet-4-20250514") Model string + // TreeHash is the git tree hash of the commit this checkpoint is linked to. + // Used as a fallback to re-link checkpoints when the Entire-Checkpoint trailer + // is stripped by git history rewrites (rebase, filter-branch, amend). + TreeHash string + // TurnID correlates checkpoints from the same agent turn. TurnID string @@ -383,6 +388,11 @@ type CommittedMetadata struct { // Model is the LLM model used during the session (e.g., "claude-sonnet-4-20250514") Model string `json:"model,omitempty"` + // TreeHash is the git tree hash of the commit this checkpoint is linked to. + // Enables fallback re-linking when the Entire-Checkpoint trailer is stripped + // by git history rewrites (rebase, filter-branch, amend). + TreeHash string `json:"tree_hash,omitempty"` + // TurnID correlates checkpoints from the same agent turn. // When a turn's work spans multiple commits, each gets its own checkpoint // but they share the same TurnID for future aggregation/deduplication. diff --git a/cmd/entire/cli/checkpoint/checkpoint_test.go b/cmd/entire/cli/checkpoint/checkpoint_test.go index 06c19e9f8..51111e902 100644 --- a/cmd/entire/cli/checkpoint/checkpoint_test.go +++ b/cmd/entire/cli/checkpoint/checkpoint_test.go @@ -1335,6 +1335,41 @@ func TestListCommitted_MultiSessionInfo(t *testing.T) { } } +// TestWriteCommitted_IncludesTreeHash verifies that tree_hash is stored in +// checkpoint metadata and can be read back. +func TestWriteCommitted_IncludesTreeHash(t *testing.T) { + t.Parallel() + repo, _ := setupBranchTestRepo(t) + store := NewGitStore(repo) + checkpointID := id.MustCheckpointID("aabb11223344") + treeHash := "abc123def456abc123def456abc123def456abc1" + + err := store.WriteCommitted(context.Background(), WriteCommittedOptions{ + CheckpointID: checkpointID, + SessionID: "tree-hash-session", + Strategy: "manual-commit", + Agent: agent.AgentTypeClaudeCode, + TreeHash: treeHash, + Transcript: []byte(`{"type":"human","message":{"content":"test"}}`), + FilesTouched: []string{"file.go"}, + CheckpointsCount: 1, + AuthorName: "Test Author", + AuthorEmail: "test@example.com", + }) + if err != nil { + t.Fatalf("WriteCommitted() error = %v", err) + } + + // Read back session metadata (session index 0) + sessionContent, err := store.ReadSessionContent(context.Background(), checkpointID, 0) + if err != nil { + t.Fatalf("ReadSessionContent() error = %v", err) + } + if sessionContent.Metadata.TreeHash != treeHash { + t.Errorf("TreeHash = %q, want %q", sessionContent.Metadata.TreeHash, treeHash) + } +} + // TestWriteCommitted_SessionWithNoPrompts verifies that a session can be // written without prompts and still be read correctly. func TestWriteCommitted_SessionWithNoPrompts(t *testing.T) { diff --git a/cmd/entire/cli/checkpoint/committed.go b/cmd/entire/cli/checkpoint/committed.go index 09af00f3e..25bae5aeb 100644 --- a/cmd/entire/cli/checkpoint/committed.go +++ b/cmd/entire/cli/checkpoint/committed.go @@ -374,6 +374,7 @@ func (s *GitStore) writeSessionToSubdirectory(ctx context.Context, opts WriteCom FilesTouched: opts.FilesTouched, Agent: opts.Agent, Model: opts.Model, + TreeHash: opts.TreeHash, TurnID: opts.TurnID, IsTask: opts.IsTask, ToolUseID: opts.ToolUseID, diff --git a/cmd/entire/cli/strategy/manual_commit_condensation.go b/cmd/entire/cli/strategy/manual_commit_condensation.go index 3b01adb7d..70265a3e8 100644 --- a/cmd/entire/cli/strategy/manual_commit_condensation.go +++ b/cmd/entire/cli/strategy/manual_commit_condensation.go @@ -96,6 +96,7 @@ type condenseOpts struct { repoDir string // Repository worktree path for git CLI commands parentCommitHash string // HEAD's first parent hash for per-commit non-agent file detection headCommitHash string // HEAD commit hash (passed through for attribution) + treeHash string // Tree hash of the commit being condensed (for fallback linkage after history rewrites) } // CondenseSession condenses a session's shadow branch to permanent storage. @@ -230,6 +231,7 @@ func (s *ManualCommitStrategy) CondenseSession(ctx context.Context, repo *git.Re AuthorEmail: authorEmail, Agent: state.AgentType, Model: state.ModelName, + TreeHash: o.treeHash, TurnID: state.TurnID, TranscriptIdentifierAtStart: state.TranscriptIdentifierAtStart, CheckpointTranscriptStart: state.CheckpointTranscriptStart, diff --git a/cmd/entire/cli/strategy/manual_commit_hooks.go b/cmd/entire/cli/strategy/manual_commit_hooks.go index 60042e246..2190599c1 100644 --- a/cmd/entire/cli/strategy/manual_commit_hooks.go +++ b/cmd/entire/cli/strategy/manual_commit_hooks.go @@ -663,6 +663,7 @@ func (h *postCommitActionHandler) HandleCondense(state *session.State) error { repoDir: h.repoDir, parentCommitHash: h.parentCommitHash(), headCommitHash: h.newHead, + treeHash: h.commit.TreeHash.String(), }) } else { h.s.updateBaseCommitIfChanged(h.ctx, state, h.newHead) @@ -691,6 +692,7 @@ func (h *postCommitActionHandler) HandleCondenseIfFilesTouched(state *session.St repoDir: h.repoDir, parentCommitHash: h.parentCommitHash(), headCommitHash: h.newHead, + treeHash: h.commit.TreeHash.String(), }) } else { h.s.updateBaseCommitIfChanged(h.ctx, state, h.newHead) From 7b9d87d2e1a210e07577f002bd0dfdf920f8e6a8 Mon Sep 17 00:00:00 2001 From: Peyton Montei Date: Thu, 2 Apr 2026 18:57:58 -0700 Subject: [PATCH 3/3] fix: add debug logging + remove unrelated files - Add debug logging to hasActiveSessionInWorktree error paths - Remove unrelated files (greetings.md, agent configs) from PR Co-Authored-By: Claude Opus 4.6 (1M context) --- .cursor/hooks.json | 40 ----- .entire/settings.json | 7 +- .factory/settings.json | 90 ----------- .gemini/settings.json | 143 +++++------------- .github/hooks/entire.json | 61 -------- .../cli/strategy/manual_commit_session.go | 7 + greetings.md | 5 - 7 files changed, 48 insertions(+), 305 deletions(-) delete mode 100644 .cursor/hooks.json delete mode 100644 .factory/settings.json delete mode 100644 .github/hooks/entire.json delete mode 100644 greetings.md diff --git a/.cursor/hooks.json b/.cursor/hooks.json deleted file mode 100644 index c709e3c65..000000000 --- a/.cursor/hooks.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "hooks": { - "beforeSubmitPrompt": [ - { - "command": "entire hooks cursor before-submit-prompt" - } - ], - "preCompact": [ - { - "command": "entire hooks cursor pre-compact" - } - ], - "sessionEnd": [ - { - "command": "entire hooks cursor session-end" - } - ], - "sessionStart": [ - { - "command": "entire hooks cursor session-start" - } - ], - "stop": [ - { - "command": "entire hooks cursor stop" - } - ], - "subagentStart": [ - { - "command": "entire hooks cursor subagent-start" - } - ], - "subagentStop": [ - { - "command": "entire hooks cursor subagent-stop" - } - ] - }, - "version": 1 -} diff --git a/.entire/settings.json b/.entire/settings.json index 480cd4592..75d97108d 100644 --- a/.entire/settings.json +++ b/.entire/settings.json @@ -1,14 +1,11 @@ { "enabled": true, "local_dev": true, + "strategy": "manual-commit", "strategy_options": { "checkpoint_remote": { "provider": "github", "repo": "entireio/cli-checkpoints" } - }, - "telemetry": true, - "commit_linking": "always", - "external_agents": true, - "strategy": "manual-commit" + } } diff --git a/.factory/settings.json b/.factory/settings.json deleted file mode 100644 index e0beec4a5..000000000 --- a/.factory/settings.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "hooks": { - "PostToolUse": [ - { - "matcher": "Task", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid post-tool-use" - } - ] - } - ], - "PreCompact": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid pre-compact" - } - ] - } - ], - "PreToolUse": [ - { - "matcher": "Task", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid pre-tool-use" - } - ] - } - ], - "SessionEnd": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid session-end" - } - ] - } - ], - "SessionStart": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid session-start" - }, - { - "type": "command", - "command": "entire hooks factoryai-droid user-prompt-submit" - } - ] - } - ], - "Stop": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid stop" - } - ] - } - ], - "UserPromptSubmit": [ - { - "matcher": "", - "hooks": [ - { - "type": "command", - "command": "entire hooks factoryai-droid user-prompt-submit" - } - ] - } - ] - }, - "permissions": { - "deny": [ - "Read(./.entire/metadata/**)" - ] - } -} diff --git a/.gemini/settings.json b/.gemini/settings.json index 5cfd81696..66778da27 100644 --- a/.gemini/settings.json +++ b/.gemini/settings.json @@ -1,55 +1,37 @@ { "context": { - "fileName": [ - "AGENTS.md" - ] + "fileName": ["AGENTS.md"] }, "hooks": { - "AfterAgent": [ + "SessionStart": [ { "hooks": [ { - "name": "entire-after-agent", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini after-agent" - }, - { - "name": "entire-after-agent", + "name": "entire-session-start", "type": "command", - "command": "entire hooks gemini after-agent" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini session-start" } ] } ], - "AfterModel": [ + "SessionEnd": [ { + "matcher": "exit", "hooks": [ { - "name": "entire-after-model", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini after-model" - }, - { - "name": "entire-after-model", + "name": "entire-session-end-exit", "type": "command", - "command": "entire hooks gemini after-model" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini session-end" } ] - } - ], - "AfterTool": [ + }, { - "matcher": "*", + "matcher": "logout", "hooks": [ { - "name": "entire-after-tool", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini after-tool" - }, - { - "name": "entire-after-tool", + "name": "entire-session-end-logout", "type": "command", - "command": "entire hooks gemini after-tool" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini session-end" } ] } @@ -61,11 +43,17 @@ "name": "entire-before-agent", "type": "command", "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini before-agent" - }, + } + ] + } + ], + "AfterAgent": [ + { + "hooks": [ { - "name": "entire-before-agent", + "name": "entire-after-agent", "type": "command", - "command": "entire hooks gemini before-agent" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini after-agent" } ] } @@ -77,28 +65,17 @@ "name": "entire-before-model", "type": "command", "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini before-model" - }, - { - "name": "entire-before-model", - "type": "command", - "command": "entire hooks gemini before-model" } ] } ], - "BeforeTool": [ + "AfterModel": [ { - "matcher": "*", "hooks": [ { - "name": "entire-before-tool", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini before-tool" - }, - { - "name": "entire-before-tool", + "name": "entire-after-model", "type": "command", - "command": "entire hooks gemini before-tool" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini after-model" } ] } @@ -110,100 +87,58 @@ "name": "entire-before-tool-selection", "type": "command", "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini before-tool-selection" - }, - { - "name": "entire-before-tool-selection", - "type": "command", - "command": "entire hooks gemini before-tool-selection" } ] } ], - "Notification": [ + "BeforeTool": [ { + "matcher": "*", "hooks": [ { - "name": "entire-notification", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini notification" - }, - { - "name": "entire-notification", + "name": "entire-before-tool", "type": "command", - "command": "entire hooks gemini notification" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini before-tool" } ] } ], - "PreCompress": [ + "AfterTool": [ { + "matcher": "*", "hooks": [ { - "name": "entire-pre-compress", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini pre-compress" - }, - { - "name": "entire-pre-compress", + "name": "entire-after-tool", "type": "command", - "command": "entire hooks gemini pre-compress" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini after-tool" } ] } ], - "SessionEnd": [ - { - "matcher": "exit", - "hooks": [ - { - "name": "entire-session-end-exit", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini session-end" - }, - { - "name": "entire-session-end-exit", - "type": "command", - "command": "entire hooks gemini session-end" - } - ] - }, + "PreCompress": [ { - "matcher": "logout", "hooks": [ { - "name": "entire-session-end-logout", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini session-end" - }, - { - "name": "entire-session-end-logout", + "name": "entire-pre-compress", "type": "command", - "command": "entire hooks gemini session-end" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini pre-compress" } ] } ], - "SessionStart": [ + "Notification": [ { "hooks": [ { - "name": "entire-session-start", - "type": "command", - "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini session-start" - }, - { - "name": "entire-session-start", + "name": "entire-notification", "type": "command", - "command": "entire hooks gemini session-start" + "command": "go run \"$(git rev-parse --show-toplevel)\"/cmd/entire/main.go hooks gemini notification" } ] } ] }, - "hooksConfig": { - "enabled": true - }, "tools": { "enableHooks": true } -} \ No newline at end of file +} diff --git a/.github/hooks/entire.json b/.github/hooks/entire.json deleted file mode 100644 index f21b0abc5..000000000 --- a/.github/hooks/entire.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "hooks": { - "agentStop": [ - { - "type": "command", - "bash": "entire hooks copilot-cli agent-stop", - "comment": "Entire CLI" - } - ], - "errorOccurred": [ - { - "type": "command", - "bash": "entire hooks copilot-cli error-occurred", - "comment": "Entire CLI" - } - ], - "postToolUse": [ - { - "type": "command", - "bash": "entire hooks copilot-cli post-tool-use", - "comment": "Entire CLI" - } - ], - "preToolUse": [ - { - "type": "command", - "bash": "entire hooks copilot-cli pre-tool-use", - "comment": "Entire CLI" - } - ], - "sessionEnd": [ - { - "type": "command", - "bash": "entire hooks copilot-cli session-end", - "comment": "Entire CLI" - } - ], - "sessionStart": [ - { - "type": "command", - "bash": "entire hooks copilot-cli session-start", - "comment": "Entire CLI" - } - ], - "subagentStop": [ - { - "type": "command", - "bash": "entire hooks copilot-cli subagent-stop", - "comment": "Entire CLI" - } - ], - "userPromptSubmitted": [ - { - "type": "command", - "bash": "entire hooks copilot-cli user-prompt-submitted", - "comment": "Entire CLI" - } - ] - }, - "version": 1 -} diff --git a/cmd/entire/cli/strategy/manual_commit_session.go b/cmd/entire/cli/strategy/manual_commit_session.go index bb7bc9f7b..cecc4ffee 100644 --- a/cmd/entire/cli/strategy/manual_commit_session.go +++ b/cmd/entire/cli/strategy/manual_commit_session.go @@ -3,11 +3,13 @@ package strategy import ( "context" "fmt" + "log/slog" "time" "github.com/entireio/cli/cmd/entire/cli/agent/types" "github.com/entireio/cli/cmd/entire/cli/checkpoint" "github.com/entireio/cli/cmd/entire/cli/checkpoint/id" + "github.com/entireio/cli/cmd/entire/cli/logging" "github.com/entireio/cli/cmd/entire/cli/paths" "github.com/entireio/cli/cmd/entire/cli/session" "github.com/entireio/cli/cmd/entire/cli/versioninfo" @@ -153,12 +155,17 @@ func (s *ManualCommitStrategy) findSessionsForWorktree(ctx context.Context, work // cherry-pick) from user-initiated ones. Agent-initiated operations should be // checkpointed; user-initiated ones should be skipped. func (s *ManualCommitStrategy) hasActiveSessionInWorktree(ctx context.Context) bool { + logCtx := logging.WithComponent(ctx, "checkpoint") worktreePath, err := paths.WorktreeRoot(ctx) if err != nil { + logging.Debug(logCtx, "hasActiveSessionInWorktree: failed to get worktree root", + slog.String("error", err.Error())) return false } sessions, err := s.findSessionsForWorktree(ctx, worktreePath) if err != nil { + logging.Debug(logCtx, "hasActiveSessionInWorktree: failed to find sessions", + slog.String("error", err.Error())) return false } for _, state := range sessions { diff --git a/greetings.md b/greetings.md deleted file mode 100644 index 85a46bc8a..000000000 --- a/greetings.md +++ /dev/null @@ -1,5 +0,0 @@ -# Greetings - -| Language | Greeting | Pronunciation | -|----------|----------|---------------| -| Japanese | こんにちは | Konnichiwa |