Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: Duplicated commit-creation logic with independent signing
- Replaced the duplicated createCommit body in strategy/common.go with a single-line delegation to checkpoint.CreateCommit, eliminating the duplicated signing call and ensuring future changes stay consistent.
- ✅ Fixed: SSH agent connection opened but never closed
- Wrapped connectSSHAgent with sync.Once so the SSH agent socket connection is opened at most once per process and reused on subsequent calls, preventing file descriptor accumulation.
Or push these changes by commenting:
@cursor push f25329b356
Preview (f25329b356)
diff --git a/cmd/entire/cli/strategy/common.go b/cmd/entire/cli/strategy/common.go
--- a/cmd/entire/cli/strategy/common.go
+++ b/cmd/entire/cli/strategy/common.go
@@ -1439,40 +1439,9 @@
//
// See push_common.go and session_test.go for usage examples.
-// createCommit creates a commit object
+// createCommit creates a commit object by delegating to checkpoint.CreateCommit.
func createCommit(ctx context.Context, repo *git.Repository, treeHash, parentHash plumbing.Hash, message, authorName, authorEmail string) (plumbing.Hash, error) { //nolint:unparam // already present in codebase
- now := time.Now()
- sig := object.Signature{
- Name: authorName,
- Email: authorEmail,
- When: now,
- }
-
- commit := &object.Commit{
- TreeHash: treeHash,
- Author: sig,
- Committer: sig,
- Message: message,
- }
-
- // Add parent if not a new branch
- if parentHash != plumbing.ZeroHash {
- commit.ParentHashes = []plumbing.Hash{parentHash}
- }
-
- checkpoint.SignCommitBestEffort(ctx, commit)
-
- obj := repo.Storer.NewEncodedObject()
- if err := commit.Encode(obj); err != nil {
- return plumbing.ZeroHash, fmt.Errorf("failed to encode commit: %w", err)
- }
-
- hash, err := repo.Storer.SetEncodedObject(obj)
- if err != nil {
- return plumbing.ZeroHash, fmt.Errorf("failed to store commit: %w", err)
- }
-
- return hash, nil
+ return checkpoint.CreateCommit(ctx, repo, treeHash, parentHash, message, authorName, authorEmail)
}
// getSessionDescriptionFromTree reads the first line of prompt.txt from a git tree.
diff --git a/cmd/entire/main.go b/cmd/entire/main.go
--- a/cmd/entire/main.go
+++ b/cmd/entire/main.go
@@ -9,6 +9,7 @@
"os/signal"
"runtime"
"strings"
+ "sync"
"syscall"
"github.com/entireio/cli/cmd/entire/cli"
@@ -92,20 +93,30 @@
})
}
+var (
+ sshAgentOnce sync.Once
+ sshAgentClient agent.Agent
+)
+
// connectSSHAgent connects to the SSH agent via SSH_AUTH_SOCK.
+// The connection is established at most once per process and reused.
// Returns nil if the agent is unavailable.
func connectSSHAgent() agent.Agent {
- sock := os.Getenv("SSH_AUTH_SOCK")
- if sock == "" {
- return nil
- }
+ sshAgentOnce.Do(func() {
+ sock := os.Getenv("SSH_AUTH_SOCK")
+ if sock == "" {
+ return
+ }
- conn, err := net.Dial("unix", sock)
- if err != nil {
- return nil
- }
+ conn, err := net.Dial("unix", sock)
+ if err != nil {
+ return
+ }
- return agent.NewClient(conn)
+ sshAgentClient = agent.NewClient(conn)
+ })
+
+ return sshAgentClient
}
var scopeName = map[config.Scope]string{This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 9deb0f1. Configure here.
There was a problem hiding this comment.
Pull request overview
This PR adds best-effort signing for Entire’s checkpoint-related commits (shadow/metadata/trails refs, merge/cherry-pick commits, v2 checkpoint refs), using the user’s Git signing configuration when available, with an opt-out setting in .entire/settings*.json.
Changes:
- Introduces
checkpoint.SignCommitBestEffortand wires it into all checkpoint/strategy commit-creation paths. - Adds
sign_checkpoint_commitssetting (default on) and documents checkpoint signing behavior/requirements. - Updates go-git v6 + adds go-git objectsigner plugin dependencies to support signing.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| go.mod | Updates go-git v6 pseudo-version and adds objectsigner/crypto dependencies needed for signing. |
| go.sum | Updates dependency checksums corresponding to new go-git + signing dependencies. |
| docs/architecture/checkpoint-signing.md | New architecture doc describing requirements, formats, and best-effort semantics. |
| cmd/entire/main.go | Registers an ObjectSigner plugin (intended to enable signing based on Git config). |
| cmd/entire/cli/trail/store.go | Threads context.Context into commit creation for trails branch updates. |
| cmd/entire/cli/strategy/push_v2.go | Passes context into merge-commit creation so signing can run. |
| cmd/entire/cli/strategy/push_common.go | Adds signing hook to merge commit creation and updates signature to accept context. |
| cmd/entire/cli/strategy/push_v2_test.go | Updates tests for new CreateCommit(ctx, ...) signature. |
| cmd/entire/cli/strategy/metadata_reconcile.go | Signs cherry-pick commits best-effort and threads context through. |
| cmd/entire/cli/strategy/metadata_reconcile_test.go | Updates tests for new CreateCommit(ctx, ...) signature. |
| cmd/entire/cli/strategy/common.go | Updates local helper commit creation to accept context and apply signing. |
| cmd/entire/cli/strategy/manual_commit_test.go | Updates helper commit creation calls to include context. |
| cmd/entire/cli/strategy/clean_test.go | Updates helper commit creation calls to include context. |
| cmd/entire/cli/settings/settings.go | Adds sign_checkpoint_commits setting + helpers for default-on behavior. |
| cmd/entire/cli/settings/settings_test.go | Extends settings validation test to accept/read sign_checkpoint_commits. |
| cmd/entire/cli/migrate.go | Threads context into v2 task metadata splice commits to support signing. |
| cmd/entire/cli/migrate_test.go | Updates migration tests for new context-threaded commit helpers. |
| cmd/entire/cli/integration_test/explain_test.go | Updates integration test helper commit creation signature. |
| cmd/entire/cli/doctor_test.go | Updates doctor tests for new CreateCommit(ctx, ...) signature. |
| cmd/entire/cli/checkpoint/v2_store.go | Threads context into v2 ref update commit creation. |
| cmd/entire/cli/checkpoint/v2_store_test.go | Updates v2 store tests for the updated updateRef(ctx, ...) signature. |
| cmd/entire/cli/checkpoint/v2_read_test.go | Updates v2 read test to call updateRef(ctx, ...). |
| cmd/entire/cli/checkpoint/v2_generation.go | Threads context into v2 generation rotation commit creation. |
| cmd/entire/cli/checkpoint/v2_generation_test.go | Updates generation tests for new CreateCommit(ctx, ...) signature. |
| cmd/entire/cli/checkpoint/v2_committed.go | Threads context into committed v2 ref updates to support signing. |
| cmd/entire/cli/checkpoint/temporary.go | Threads context into temporary checkpoint commit creation. |
| cmd/entire/cli/checkpoint/committed_reader_resolve_test.go | Updates resolve test helper commit creation signature. |
| cmd/entire/cli/checkpoint/committed.go | Adds SignCommitBestEffort, updates CreateCommit signature to accept context, and applies signing. |
| signer, err := auto.FromConfig(cfg) | ||
| if err != nil { | ||
| fmt.Fprintf(os.Stderr, "warning: failed to create object signer: %v\n", err) | ||
| return nil |
There was a problem hiding this comment.
These warnings are printed directly to os.Stderr, but the PR description says signing failures should be logged to .entire/logs/ (and the repo generally uses cli/logging for operational messages). Consider switching these to logging.Warn (passing a context) so they go to the standard log sink, and avoid user-facing stderr noise during normal runs.
There was a problem hiding this comment.
This was intentional to avoid having to wire in the logging this early in the execution process. We can revisit this if others believe is the right thing to do.
There was a problem hiding this comment.
Wouldn't it be a better place to put this logic here? ->
Line 44 in a92fb24
PersistentPreRun where we can init the logger and this and .. maybe adding it into the context ? wdyt ?
deb8840 to
e0c4617
Compare
0c16a2e to
c6af756
Compare
Register an ObjectSigner plugin in main.go that loads system and global git config to obtain gpg.format and user.signingKey. In CreateCommit, sign the commit when a signer is available via signCommitBestEffort. Signed-off-by: Paulo Gomes <paulo@entire.io> Assisted-by: Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Paulo Gomes <paulo@entire.io>
Export SignCommitBestEffort and add signing to createCommit, createMergeCommitCommon, and createCherryPickCommit so that all internally created commits are signed when a signer is registered. Signed-off-by: Paulo Gomes <paulo@entire.io> Assisted-by: Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 10e057177578
Only create an ObjectSigner when commit.gpgSign is true, so users without signing enabled see no warnings. Connect to the SSH agent via SSH_AUTH_SOCK when available, enabling key::, .pub, and agent-based SSH signing. Signed-off-by: Paulo Gomes <paulo@entire.io> Assisted-by: Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: 87d00b47af3f
…ommits setting SignCommitBestEffort now logs errors via the logging package instead of returning them, so users with hardware security keys or other signers requiring physical presence won't have checkpoint commits blocked. Add sign_checkpoint_commits setting (default: true) to let users opt out of signing checkpoint commits entirely via .entire/settings.json. Thread context.Context through CreateCommit, createCommit, updateRef, createMergeCommitCommon, createCherryPickCommit, and related helpers so that signing warnings flow to .entire/logs/ like all other operational messages. Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Paulo Gomes <paulo@entire.io> Entire-Checkpoint: 855bb9174e57
Signed-off-by: Paulo Gomes <paulo@entire.io>
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Paulo Gomes <paulo@entire.io> Entire-Checkpoint: e4d4d2037f61
Entire-Checkpoint: a70d97c363c8 Entire-Checkpoint: 983194b9963d
c6af756 to
3fdf9a4
Compare


Entire will now sign checkpoint commits (shadow branch, metadata branch) using the same key configured for regular git commits. Signing is best-effort: if the signer is unavailable or fails, the commit is created unsigned and a warning is logged to
.entire/logs/.Users may opt-out from checkpoint commit signing. This does not affect signing of regular user commits.
Add to
.entire/settings.json(shared with the team) or.entire/settings.local.json(personal, gitignored):{ "sign_checkpoint_commits": false }Fixes #311.
Note
Medium Risk
Touches commit creation paths for checkpoints, trails, merges, and migration by adding optional signing and new go-git plugin dependencies; failures are best-effort but could change commit object bytes and introduce environment-specific behavior (gpg/ssh-agent).
Overview
Enables best-effort signing for git commits created by Entire (checkpoint v1/v2 commits, shadow branch commits, trail commits, merge/cherry-pick commits, and migration task-metadata splices) by routing commit creation through
CreateCommit(ctx, ...)and applyingSignCommitBestEffortbefore storing the commit.Registers a go-git
ObjectSignerplugin at startup that reads global/system git config (commit.gpgsign,user.signingkey,gpg.format) and can usessh-agentwhen available; adds a new settingsign_checkpoint_commits(default enabled) to allow opting out, plus documentation and dependency updates to support the signer plugins.Reviewed by Cursor Bugbot for commit 9deb0f1. Configure here.