@@ -20,9 +20,28 @@ def fake_launch_tool(**kwargs: object) -> None:
2020 return fake_launch_tool
2121
2222
23+ def _hermetic_home (monkeypatch : pytest .MonkeyPatch , tmp_path ) -> None :
24+ """Redirect every home-adjacent path the wrap flow can write to.
25+
26+ The wrap flow registers Serena/headroom MCP entries into the dsh home and
27+ records installs in the Headroom workspace ledger. Without redirects these
28+ tests would mutate the developer's real `~/.dsh` / `~/.headroom` when
29+ the harness is installed on the machine running the suite.
30+ """
31+ monkeypatch .setenv ("DSH_HOME" , str (tmp_path / "dsh" ))
32+ monkeypatch .setenv ("HEADROOM_WORKSPACE_DIR" , str (tmp_path / "headroom" ))
33+ monkeypatch .setenv ("HOME" , str (tmp_path / "home" ))
34+ # The repo root carries a `.serena/project.yml`, so a successful Serena
35+ # registration would synchronously run `serena project index` (a real
36+ # subprocess, up to _SERENA_INDEX_TIMEOUT). Registration is what these
37+ # tests assert; the pre-index is orthogonal and must not run here.
38+ monkeypatch .setattr ("headroom.cli.wrap._index_serena_project" , lambda ** _kwargs : None )
39+
40+
2341def test_wrap_dsh_launches_web_with_proxy_env (
24- runner : CliRunner , monkeypatch : pytest .MonkeyPatch
42+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
2543) -> None :
44+ _hermetic_home (monkeypatch , tmp_path )
2645 captured : dict [str , object ] = {}
2746 monkeypatch .setattr ("headroom.cli.wrap._launch_tool" , _capture (captured ))
2847 monkeypatch .setattr (
@@ -40,7 +59,10 @@ def test_wrap_dsh_launches_web_with_proxy_env(
4059 assert captured ["agent_type" ] == "dsh"
4160
4261
43- def test_wrap_dsh_headless_profile (runner : CliRunner , monkeypatch : pytest .MonkeyPatch ) -> None :
62+ def test_wrap_dsh_headless_profile (
63+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
64+ ) -> None :
65+ _hermetic_home (monkeypatch , tmp_path )
4466 captured : dict [str , object ] = {}
4567 monkeypatch .setattr ("headroom.cli.wrap._launch_tool" , _capture (captured ))
4668 monkeypatch .setattr (
@@ -54,8 +76,9 @@ def test_wrap_dsh_headless_profile(runner: CliRunner, monkeypatch: pytest.Monkey
5476
5577
5678def test_wrap_dsh_forwards_deepseek_api_url (
57- runner : CliRunner , monkeypatch : pytest .MonkeyPatch
79+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
5880) -> None :
81+ _hermetic_home (monkeypatch , tmp_path )
5982 captured : dict [str , object ] = {}
6083 monkeypatch .setattr ("headroom.cli.wrap._launch_tool" , _capture (captured ))
6184 monkeypatch .setattr (
@@ -69,8 +92,9 @@ def test_wrap_dsh_forwards_deepseek_api_url(
6992
7093
7194def test_wrap_dsh_captures_ambient_deepseek_base_url (
72- runner : CliRunner , monkeypatch : pytest .MonkeyPatch
95+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
7396) -> None :
97+ _hermetic_home (monkeypatch , tmp_path )
7498 captured : dict [str , object ] = {}
7599 monkeypatch .setattr ("headroom.cli.wrap._launch_tool" , _capture (captured ))
76100 monkeypatch .setattr ("headroom.providers.dsh.runtime.shutil.which" , lambda _name : "/usr/bin/dsh" )
@@ -80,15 +104,21 @@ def test_wrap_dsh_captures_ambient_deepseek_base_url(
80104 assert captured ["deepseek_api_url" ] == "https://gateway.internal"
81105
82106
83- def test_wrap_dsh_missing_binary_fails (runner : CliRunner , monkeypatch : pytest .MonkeyPatch ) -> None :
107+ def test_wrap_dsh_missing_binary_fails (
108+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
109+ ) -> None :
110+ _hermetic_home (monkeypatch , tmp_path )
84111 monkeypatch .setattr ("headroom.providers.dsh.runtime.shutil.which" , lambda _name : None )
85112
86113 result = runner .invoke (main , ["wrap" , "dsh" ])
87114 assert result .exit_code == 1
88115 assert "not found in PATH" in result .output
89116
90117
91- def test_unwrap_dsh_stops_proxy (runner : CliRunner , monkeypatch : pytest .MonkeyPatch ) -> None :
118+ def test_unwrap_dsh_stops_proxy (
119+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
120+ ) -> None :
121+ _hermetic_home (monkeypatch , tmp_path )
92122 monkeypatch .setattr (
93123 "headroom.cli.wrap._stop_local_proxy_for_unwrap" ,
94124 lambda _port : "stopped" ,
@@ -100,3 +130,39 @@ def test_unwrap_dsh_stops_proxy(runner: CliRunner, monkeypatch: pytest.MonkeyPat
100130
101131 result = runner .invoke (main , ["unwrap" , "dsh" ])
102132 assert result .exit_code == 0 , result .output
133+
134+
135+ def test_wrap_dsh_establishes_managed_entry_before_launch_without_home (
136+ runner : CliRunner , monkeypatch : pytest .MonkeyPatch , tmp_path
137+ ) -> None :
138+ """Fresh install: no DSH home exists — the managed entry must land before
139+ dsh launches (review #4985851059: detect() alone would skip registration).
140+ """
141+ _hermetic_home (monkeypatch , tmp_path )
142+ dsh_home = tmp_path / "dsh"
143+ assert not dsh_home .exists ()
144+
145+ captured : dict [str , object ] = {}
146+ launch_saw_entry : list [bool ] = []
147+
148+ def fake_launch_tool (** kwargs : object ) -> None :
149+ # Prove the managed entry already exists at launch time.
150+ launch_saw_entry .append ((dsh_home / "cordis.patch.yml" ).exists ())
151+ captured .update (kwargs )
152+
153+ monkeypatch .setattr ("headroom.cli.wrap._launch_tool" , fake_launch_tool )
154+ monkeypatch .setattr (
155+ "headroom.providers.dsh.runtime.shutil.which" ,
156+ lambda _name : "/usr/bin/dsh" ,
157+ )
158+
159+ result = runner .invoke (main , ["wrap" , "dsh" , "--port" , "9000" ])
160+ assert result .exit_code == 0 , result .output
161+
162+ patch = dsh_home / "cordis.patch.yml"
163+ assert patch .exists (), "managed entry must exist before dsh launches"
164+ text = patch .read_text (encoding = "utf-8" )
165+ assert "@deepseek-ai/dsh-mcp-client" in text
166+ assert "serverName: serena" in text
167+ assert captured ["agent_type" ] == "dsh"
168+ assert launch_saw_entry == [True ]
0 commit comments