@@ -105,15 +105,16 @@ def test_preflight_catches_missing_bearer_token(self):
105105 assert "OPENSPACE_MCP_BEARER_TOKEN" in token_issues [0 ].message
106106
107107 def test_preflight_suggestion_is_actionable (self ):
108- """Suggestions must include a command the user can run ."""
108+ """Suggestions must include a platform-appropriate set command ."""
109109 from openspace .deploy .preflight import preflight_check
110110
111111 with patch .dict (os .environ , {}, clear = True ):
112112 issues = preflight_check (transport = "streamable-http" , check_port = False )
113113 token_issues = [i for i in issues if i .check == "bearer-token" ]
114114 assert token_issues
115115 suggestion = token_issues [0 ].suggestion
116- assert "export" in suggestion or "set" in suggestion .lower ()
116+ # Must contain a real shell command, not just descriptive text
117+ assert "$env:" in suggestion or "export " in suggestion
117118
118119 def test_preflight_no_token_check_for_stdio (self ):
119120 from openspace .deploy .preflight import check_bearer_token
@@ -201,6 +202,60 @@ def test_preflight_report_all_clear(self):
201202 report = format_preflight_report ([])
202203 assert "All checks passed" in report
203204
205+ def test_preflight_bearer_suggestion_platform_aware (self ):
206+ """Suggestion must use platform-appropriate shell syntax."""
207+ from openspace .deploy .preflight import check_bearer_token
208+
209+ with patch .dict (os .environ , {}, clear = True ):
210+ result = check_bearer_token ("streamable-http" )
211+ assert result is not None
212+ if os .name == "nt" :
213+ assert "$env:" in result .suggestion
214+ else :
215+ assert "export " in result .suggestion
216+
217+ def test_preflight_skill_store_suggestion_platform_aware (self , tmp_path ):
218+ """Skill store fix suggestion must use platform-appropriate commands."""
219+ from openspace .deploy .preflight import check_skill_store
220+
221+ fake_path = tmp_path / "skills"
222+ fake_path .write_text ("not a directory" )
223+ result = check_skill_store (str (fake_path ))
224+ assert result is not None
225+ if os .name == "nt" :
226+ assert "Remove-Item" in result .suggestion
227+ else :
228+ assert "rm " in result .suggestion
229+
230+
231+ # ======================================================================
232+ # Preflight visibility (P0 fix)
233+ # ======================================================================
234+ class TestPreflightVisibility :
235+ """Preflight output must reach the user, not just the log file."""
236+
237+ def test_preflight_writes_to_console_not_just_logger (self ):
238+ """run_mcp_server must write preflight to sys.__stderr__, not just logger."""
239+ import inspect
240+ from openspace .mcp .server import run_mcp_server
241+
242+ source = inspect .getsource (run_mcp_server )
243+ assert "__stderr__" in source , (
244+ "Preflight output must use sys.__stderr__ to reach console"
245+ )
246+
247+ def test_critical_errors_write_to_console (self ):
248+ """Bearer token errors must also reach console."""
249+ import inspect
250+ from openspace .mcp .server import run_mcp_server
251+
252+ source = inspect .getsource (run_mcp_server )
253+ # Count __stderr__ occurrences — should be used for both preflight AND auth errors
254+ count = source .count ("__stderr__" )
255+ assert count >= 2 , (
256+ f"Expected __stderr__ used for preflight AND auth errors, found { count } uses"
257+ )
258+
204259
205260# ======================================================================
206261# Error message UX
0 commit comments