Skip to content

fix(setup): avoid baking versioned Homebrew Cellar path into MCP configs#499

Merged
Alan-TheGentleman merged 2 commits into
mainfrom
fix/engram-cellar-symlink-resolve
Jun 14, 2026
Merged

fix(setup): avoid baking versioned Homebrew Cellar path into MCP configs#499
Alan-TheGentleman merged 2 commits into
mainfrom
fix/engram-cellar-symlink-resolve

Conversation

@Alan-TheGentleman

@Alan-TheGentleman Alan-TheGentleman commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Closes #498

Type

Bug fix (type:bug)

Summary

  • resolveEngramCommand() no longer bakes a versioned Homebrew/Linuxbrew Cellar path (e.g. .../Cellar/engram/1.16.1/bin/engram) into MCP client configs.
  • When the resolved executable points into a versioned Cellar directory, it maps to the stable <brew-prefix>/bin/engram symlink (which brew keeps current), falling back to bare engram when that symlink is missing.
  • Non-Cellar absolute paths are preserved unchanged.

Why

After brew upgrade engram the old Cellar version directory is removed, so OpenCode/Codex fail to spawn the engram MCP server with ENOENT: posix_spawn. On Linux os.Executable() reads /proc/self/exe, which is already fully resolved to the Cellar path, so dropping EvalSymlinks alone does not help — the Cellar path must be explicitly detected and mapped back to the stable symlink.

Changes

File Change
internal/setup/setup.go Add stableHomebrewEngramCommand; map versioned Cellar paths to the stable brew bin symlink; corrected doc comment
internal/setup/setup_test.go Add TestResolveEngramCommandHomebrewCellar (linuxbrew, macOS arm/intel, missing-symlink fallback, non-Cellar preserved)

Test Plan

  • go build ./...
  • go test ./internal/setup/ — all pass, including existing TestResolveEngramCommand
  • New table test covers each Cellar prefix and the fallback paths

Context

Originally reported against gentle-ai (Gentleman-Programming/gentle-ai#863), but gentle-ai already migrates Cellar paths in opencode.json and never writes opencode.jsonc. The real source of the versioned path is engram setup, fixed here.

Checklist

  • Linked an approved issue
  • Exactly one type:* label
  • Conventional commit format
  • No Co-Authored-By trailers

Summary by CodeRabbit

Bug Fixes

  • Fixed MCP configuration paths to remain stable across Homebrew/Linuxbrew upgrades by preferring the stable .../bin/engram symlink when the resolved executable previously pointed to a versioned Cellar location.
  • Improved fallback behavior to ensure a sensible command is still used if the stable symlink is not present.

resolveEngramCommand() used os.Executable() + filepath.EvalSymlinks(), which
resolves the engram symlink down to a versioned Homebrew/Linuxbrew Cellar path
(e.g. .../Cellar/engram/1.16.1/bin/engram). That path is removed on the next
'brew upgrade', so OpenCode/Codex fail to spawn the engram MCP server with
ENOENT. On Linux os.Executable() reads /proc/self/exe which is already fully
resolved, so dropping EvalSymlinks alone does not help.

When the resolved executable points into a versioned Cellar directory, map it
to the stable <brew-prefix>/bin/engram symlink that brew keeps current, falling
back to bare "engram" when that symlink is missing. Non-Cellar absolute paths
are preserved unchanged.

Relates to Gentleman-Programming/gentle-ai#863
Copilot AI review requested due to automatic review settings June 14, 2026 10:18
@Alan-TheGentleman Alan-TheGentleman added the type:bug Bug fix label Jun 14, 2026
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9f251ee9-9cd4-4040-b4cf-c670d4ee282a

📥 Commits

Reviewing files that changed from the base of the PR and between 34bf538 and 2a7d3fa.

📒 Files selected for processing (1)
  • internal/setup/setup_test.go

📝 Walkthrough

Walkthrough

resolveEngramCommand() in internal/setup/setup.go gains a new helper stableHomebrewEngramCommand() that detects versioned Homebrew Cellar paths, derives the stable <brew-prefix>/bin/engram symlink, and returns it when it exists or falls back to bare "engram". A table-driven test validates all three resolution cases using mocked filesystem seams.

Changes

Stable Homebrew symlink resolution in setup

Layer / File(s) Summary
Homebrew Cellar detection and stable symlink resolution
internal/setup/setup.go
Expands resolveEngramCommand() docs to describe the new behavior. Adds stableHomebrewEngramCommand() that detects versioned /Cellar/engram/ paths, derives <brew-prefix>/bin/engram, returns it when the symlink exists, or falls back to bare "engram". resolveEngramCommand() calls this helper after EvalSymlinks and returns its result or the resolved path.
Table-driven Homebrew path tests
internal/setup/setup_test.go
Adds TestResolveEngramCommandHomebrewCellar covering Homebrew and Linuxbrew Cellar-to-stable-symlink mapping, non-Cellar path preservation, and missing-symlink fallback using mocked osExecutable and statFn.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • #498 (bug(setup): engram bakes versioned Homebrew Cellar path into MCP configs): This PR directly fixes the reported bug by detecting Cellar paths in resolveEngramCommand() and substituting the stable <brew-prefix>/bin/engram symlink so MCP configs survive brew upgrade.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: preventing versioned Homebrew Cellar paths from being written into MCP configurations.
Linked Issues check ✅ Passed The PR fully addresses issue #498 by implementing the stableHomebrewEngramCommand function to detect and map versioned Cellar paths to stable symlinks with fallback logic.
Out of Scope Changes check ✅ Passed All changes are directly related to resolving issue #498: the new helper function detects Cellar paths, the test comprehensively validates the fix across platforms.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/engram-cellar-symlink-resolve

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes engram setup generating MCP client configs that embed a versioned Homebrew/Linuxbrew Cellar path to the engram binary (which becomes stale after brew upgrade). It detects versioned .../Cellar/engram/<version>/bin/engram executables and maps them back to the stable <brew-prefix>/bin/engram symlink (or falls back when missing), so MCP registrations keep working across upgrades.

Changes:

  • Updated resolveEngramCommand() to translate versioned Homebrew/Linuxbrew Cellar paths to the stable <brew-prefix>/bin/engram symlink.
  • Added stableHomebrewEngramCommand() helper to encapsulate Cellar detection/mapping logic.
  • Added a table-driven test covering linuxbrew/macOS (arm/intel) Cellar mappings, missing-symlink fallback, and non-Cellar preservation.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
internal/setup/setup.go Maps resolved versioned Homebrew/Linuxbrew Cellar paths back to the stable brew bin/engram symlink when generating MCP commands.
internal/setup/setup_test.go Adds coverage to prevent regressions where versioned Cellar paths are baked into generated MCP configurations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/setup/setup_test.go Outdated
Comment on lines +1409 to +1411
if got := resolveEngramCommand(); got != tc.want {
t.Fatalf("resolveEngramCommand() = %q, want %q", got, tc.want)
}
resolveEngramCommand returns OS-native separators via filepath.FromSlash, so
compare with filepath.ToSlash to keep the table test green on Windows runners.
Addresses PR review feedback.
@Alan-TheGentleman Alan-TheGentleman merged commit 75cdfcb into main Jun 14, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(setup): engram bakes versioned Homebrew Cellar path into MCP configs (ENOENT after brew upgrade)

2 participants