From b5c4cd486f58a28e5d95ff00742984256e4ce4ac Mon Sep 17 00:00:00 2001 From: "m2 (AI Agent)" Date: Thu, 2 Jul 2026 04:15:33 +0200 Subject: [PATCH] wedge: local adapter resolves dest symlinks before home containment check Found by the T036 gate install on m2bd-m2o: $HOME is a bind of /agent_home/home/developer; Path.home().resolve() followed the mount while the expanded dest did not, false-positiving the safety guard. The failed install correctly auto-refunded (the FR-005 compensation path proved itself live). Co-Authored-By: Claude Fable 5 --- cli/src/m2_market/apply/local.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cli/src/m2_market/apply/local.py b/cli/src/m2_market/apply/local.py index 6bebd11..c0f366d 100644 --- a/cli/src/m2_market/apply/local.py +++ b/cli/src/m2_market/apply/local.py @@ -151,6 +151,11 @@ class LocalApplyAdapter: if not dest.is_absolute(): dest = home / dest dest = Path(os.path.normpath(str(dest))) + # Resolve symlinked/bind-mounted ancestors so the containment check + # compares real paths: on m2o desktops $HOME (/home/developer) is a + # mount of /agent_home/home/developer, and Path.home().resolve() + # already followed it — an unresolved dest would false-positive here. + dest = dest.resolve() if dest != home and home not in dest.parents: raise ValueError(