fix: inherit environment in daemon subprocess calls (#876)

The daemon's exec.Command calls were not explicitly setting cmd.Env,
causing subprocesses to fail when the daemon process doesn't have
the expected PATH environment variable. This manifests as:

  Warning: failed to fetch deacon inbox: exec: "gt": executable file not found in $PATH

When the daemon is started by mechanisms with minimal environments
(launchd, systemd, or shells without full PATH), executables like
gt, bd, git, and sqlite3 couldn't be found.

The fix adds cmd.Env = os.Environ() to all 15 subprocess calls across
three files, ensuring they inherit the daemon's full environment.

Affected commands:
- gt mail inbox/delete/send (lifecycle requests, notifications)
- bd sync/show/list/activity (beads operations)
- git fetch/pull (workspace pre-sync)
- sqlite3 (convoy completion queries)

Fixes #875

Co-authored-by: Jackson Cantrell <cantrelljax@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jackson Cantrell
2026-01-22 16:41:51 -08:00
committed by John Ogle
parent e1101b94eb
commit 14b72f6edf
3 changed files with 16 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
@@ -87,6 +88,7 @@ func (w *ConvoyWatcher) run() {
func (w *ConvoyWatcher) watchActivity() error {
cmd := exec.CommandContext(w.ctx, "bd", "activity", "--follow", "--town", "--json")
cmd.Dir = w.townRoot
cmd.Env = os.Environ() // Inherit PATH to find bd executable
stdout, err := cmd.StdoutPipe()
if err != nil {
@@ -168,6 +170,7 @@ func (w *ConvoyWatcher) getTrackingConvoys(issueID string) []string {
`, safeIssueID, safeIssueID)
queryCmd := exec.Command("sqlite3", "-json", dbPath, query)
queryCmd.Env = os.Environ() // Inherit PATH to find sqlite3 executable
var stdout bytes.Buffer
queryCmd.Stdout = &stdout
@@ -200,6 +203,7 @@ func (w *ConvoyWatcher) checkConvoyCompletion(convoyID string) {
strings.ReplaceAll(convoyID, "'", "''"))
queryCmd := exec.Command("sqlite3", "-json", dbPath, convoyQuery)
queryCmd.Env = os.Environ() // Inherit PATH to find sqlite3 executable
var stdout bytes.Buffer
queryCmd.Stdout = &stdout
@@ -224,6 +228,7 @@ func (w *ConvoyWatcher) checkConvoyCompletion(convoyID string) {
checkCmd := exec.Command("gt", "convoy", "check", convoyID)
checkCmd.Dir = w.townRoot
checkCmd.Env = os.Environ() // Inherit PATH to find gt executable
var checkStdout, checkStderr bytes.Buffer
checkCmd.Stdout = &checkStdout
checkCmd.Stderr = &checkStderr