Re-cuts v0.48.2 with a CI-only fix. The
setup_cursor acceptance specs that v0.48.2
introduced asserted mcp.json contains an absolute
path ending in /morph-mcp. They passed locally
(where morph-mcp is on PATH for any
active Morph user) but failed on the GitHub Actions runner
because cargo test --workspace does not
build the actual morph-mcp binary at
target/debug/morph-mcp — only its unit-test
binary in target/debug/deps/. With no
morph-mcp on PATH and no sibling of
morph, the resolver correctly fell back to the
bare name and the spec assertion flunked. v0.48.3 carries the
same user-visible behaviour as v0.48.2 and ships through the
release pipeline cleanly.
Fixed
morph-cli/build.rs plants a
stub morph-mcp file in OUT_DIR and
injects MORPH_MCP_PATH=<OUT_DIR>/morph-mcp
into every generated spec-test invocation. The resolver’s
first resolution branch (env var, validated via
is_file()) is now exercised deterministically
across local and CI runs without depending on workspace
build order or the runner’s PATH. The
production fallback chain (env → sibling →
PATH → bare) is unchanged; only the
test-harness path is pinned.
Tests
- Same six
setup_cursor cases as v0.48.2; now
green on a runner with no installed
morph-mcp and no
target/debug/morph-mcp. Verified locally with
PATH=/tmp/fake-bins:/usr/bin:/bin — 1220
tests passing across the workspace.
Fix: morph setup cursor now writes an
absolute path to morph-mcp. Cursor on
macOS is a GUI-launched app and does not inherit the
user’s shell PATH, so the previous bare
command: “morph-mcp” entry in
.cursor/mcp.json silently failed to spawn for
Homebrew users on /opt/homebrew/bin. The agent
saw the morph-record.mdc rule but had no
morph_record_session tool to call. This release
closes that gap for Cursor, Claude Code, and OpenCode.
Fixed
morph-cli/src/setup.rs: new
resolve_mcp_command() helper writes an absolute
path to morph-mcp into
.cursor/mcp.json,
.claude/settings.json, and
opencode.json. Resolution order:
MORPH_MCP_PATH env var (escape hatch) →
morph-mcp sibling of the running
morph binary via current_exe()
(the common case for Homebrew, cargo install,
AUR, etc.) → manual PATH walk →
bare-name fallback. The bare-name fallback emits a stderr
warning so the user can fix it manually.
SetupReport /
OpenCodeSetupReport /
ClaudeCodeSetupReport now carry the resolved
mcp_command string, and the
morph setup … CLI summary prints it as
morph-mcp: <resolved path> so a fresh
setup immediately shows what got written into the IDE
config.
Tests
- New spec
morph-cli/tests/specs/setup_cursor.yaml
covers setup cursor’s contract end-to-end
(6 cases: file emission, absolute-path command, CLI summary,
idempotency, existing-config preservation, missing
.morph/ error). Two new unit tests pin the
MORPH_MCP_PATH env-override contract and the
resolver’s fallback behaviour against bogus overrides.
Existing setup_claude_code spec relaxes its
'"morph-mcp"' assertion to
'morph-mcp"'.
- 493 morph-cli tests passing
(41 + 8 + 432 + 10 + 2). No other crate’s behaviour
changed.
Senior-engineer cleanup pass. Small reliability
and readability fixes plus a documentation/website sweep so
every surface that mentions the v0.43–v0.48 vocabulary
unification matches reality. No on-disk format changes; the
public CLI/MCP surface is unchanged beyond one new exported
helper.
Added
morph_core::hex_prefix(s, max)
— new public helper that truncates a hex hash string
to its first max chars (or fewer if shorter),
bounds-safe. Centralises the “8 chars for morph
hashes, 12 chars for git SHAs” convention so every CLI
call site uses the same path.
short_hash_str is now a thin alias.
Changed
- Every
<morph_dir>/config.json mutation
in morph-core/src/repo.rs now goes through a
single write_config_pretty helper that
propagates serialization errors as
MorphError::Serialization. Replaces four
serde_json::to_string_pretty(...).unwrap()
calls.
- Replaced 11 ad-hoc
&hash.to_string()[..N] /
&sha[..sha.len().min(N)] slicings with
hex_prefix(s, N) across
morph-cli/src/main.rs,
morph-cli/src/inspect.rs, and
morph-core/src/forget.rs. No behaviour change.
- Clarified the unreachable
.expect(...) messages in
merge_aoe_config_toml and
version_json so a future reader can see the
structural invariant.
Documentation
docs/v0-spec.md §13 now
past-tenses the removed eval aliases
(add-case / suite-show /
suite-from-specs) instead of saying they
continue to work through v0.47.
docs/TESTING.md refreshed:
1212 Rust tests, 426 spec tests, 659 morph-core unit
tests; CLI evidence category list updated from the removed
run/trace/tap/traces
spellings to session + inspect;
new callout that the MCP wire names stay stable across
the rename.
docs/THEORY.md §15
gained a naming-note callout disambiguating the paper-level
operations morph run / morph eval
from the (renamed) CLI surface.
.cursor/rules/eval-driven-development.mdc
now lists morph eval suite-from-specs
alongside add-case and suite-show
in the “removed in v0.48” callout.
CONTRIBUTING.md: removed
tap from the morph-cli example command list;
current commands are inspect /
session / eval.
site/index.html header +
hero badge bumped from v0.42.2 to
v0.48.1.
- Both tutorials
(
site/tutorials/getting-started.html,
site/tutorials/adding-to-git-project.html)
now show morph 0.48.x (built …) in
their install-verification copy.
Tests
- All 1212 / 1212 workspace tests passing
(39 + 8 + 426 + 10 + 2 + 659 + 31 + 37). Cucumber 34 / 37
(3 skipped, 0 failed) — no change.
cargo build,
cargo clippy --all-targets --all-features -- -D
warnings, and
cargo fmt -- --check are clean.
Older versions
See CHANGELOG.md
in the repo for the rolling, longer-form history, or
git log --grep '(0\.\|v0\.' for the full record back to
0.3.0.