From c70811cc4024e9f157e0a91cb1938a230204a35c Mon Sep 17 00:00:00 2001 From: hinotoi-agent Date: Tue, 12 May 2026 10:05:00 +0800 Subject: [PATCH 1/2] fix(commands): keep diff local-only by default --- src/openharness/commands/registry.py | 10 +++- tests/test_commands/test_registry.py | 17 +++++++ tests/test_ohmo/test_gateway.py | 70 ++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/openharness/commands/registry.py b/src/openharness/commands/registry.py index 3f64456..df8c364 100644 --- a/src/openharness/commands/registry.py +++ b/src/openharness/commands/registry.py @@ -2343,7 +2343,15 @@ def create_default_command_registry( registry.register(SlashCommand("vim", "Show or update Vim mode", _vim_handler)) registry.register(SlashCommand("voice", "Show or update voice mode", _voice_handler)) registry.register(SlashCommand("doctor", "Show environment diagnostics", _doctor_handler)) - registry.register(SlashCommand("diff", "Show git diff output", _diff_handler)) + registry.register( + SlashCommand( + "diff", + "Show git diff output", + _diff_handler, + remote_invocable=False, + remote_admin_opt_in=True, + ) + ) registry.register(SlashCommand("branch", "Show git branch information", _branch_handler)) registry.register(SlashCommand("commit", "Show status or create a git commit", _commit_handler)) registry.register(SlashCommand("issue", "Show or update project issue context", _issue_handler)) diff --git a/tests/test_commands/test_registry.py b/tests/test_commands/test_registry.py index da2e080..2b5dc48 100644 --- a/tests/test_commands/test_registry.py +++ b/tests/test_commands/test_registry.py @@ -161,6 +161,23 @@ async def test_bridge_command_supports_explicit_remote_admin_opt_in(tmp_path: Pa assert getattr(command, "remote_admin_opt_in", False) is True +@pytest.mark.asyncio +async def test_diff_command_is_marked_local_only(tmp_path: Path, monkeypatch): + monkeypatch.setenv("OPENHARNESS_CONFIG_DIR", str(tmp_path / "config")) + registry = create_default_command_registry() + command, _ = registry.lookup("/diff full") + assert command is not None + assert command.remote_invocable is False + + +@pytest.mark.asyncio +async def test_diff_command_supports_explicit_remote_admin_opt_in(tmp_path: Path, monkeypatch): + monkeypatch.setenv("OPENHARNESS_CONFIG_DIR", str(tmp_path / "config")) + registry = create_default_command_registry() + command, _ = registry.lookup("/diff full") + assert command is not None + assert getattr(command, "remote_admin_opt_in", False) is True + @pytest.mark.asyncio async def test_sensitive_control_plane_commands_are_local_only(tmp_path: Path, monkeypatch): diff --git a/tests/test_ohmo/test_gateway.py b/tests/test_ohmo/test_gateway.py index 898faa5..63188eb 100644 --- a/tests/test_ohmo/test_gateway.py +++ b/tests/test_ohmo/test_gateway.py @@ -1,6 +1,7 @@ import asyncio import contextlib import logging +import subprocess from types import SimpleNamespace from datetime import datetime import json @@ -237,6 +238,75 @@ async def test_runtime_pool_restores_messages_for_private_legacy_session_key(tmp assert bundle.session_id == "sess123" +@pytest.mark.asyncio +async def test_runtime_pool_blocks_registered_diff_full_without_leaking_workspace_changes( + tmp_path, monkeypatch +): + workspace = tmp_path / ".ohmo-home" + repo = tmp_path / "repo" + repo.mkdir() + initialize_workspace(workspace) + subprocess.run(["git", "init", "-q"], cwd=repo, check=True) + subprocess.run(["git", "config", "user.email", "test@example.com"], cwd=repo, check=True) + subprocess.run(["git", "config", "user.name", "OpenHarness Test"], cwd=repo, check=True) + changed_file = repo / "app.env" + changed_file.write_text("OPENHARNESS_VALUE=old\n", encoding="utf-8") + subprocess.run(["git", "add", "app.env"], cwd=repo, check=True) + subprocess.run(["git", "commit", "-q", "-m", "init"], cwd=repo, check=True) + changed_file.write_text("OPENHARNESS_VALUE=LEAKMARK_REMOTE_DIFF_VALUE\n", encoding="utf-8") + + registry = create_default_command_registry() + command, _ = registry.lookup("/diff full") + assert command is not None + assert command.name == "diff" + assert command.remote_invocable is False + + class FakeEngine: + messages = [] + total_usage = UsageSnapshot() + tool_metadata = {} + + def set_system_prompt(self, prompt): + return None + + async def fake_build_runtime(**kwargs): + return SimpleNamespace( + engine=FakeEngine(), + cwd=str(repo), + session_id="sess123", + current_settings=lambda: SimpleNamespace(model="gpt-5.4"), + commands=registry, + tool_registry=None, + app_state=None, + session_backend=None, + extra_skill_dirs=(), + extra_plugin_roots=(), + hook_summary=lambda: "", + mcp_summary=lambda: "", + plugin_summary=lambda: "", + ) + + async def fake_start_runtime(bundle): + return None + + monkeypatch.setattr("ohmo.gateway.runtime.build_runtime", fake_build_runtime) + monkeypatch.setattr("ohmo.gateway.runtime.start_runtime", fake_start_runtime) + + pool = OhmoSessionRuntimePool(cwd=repo, workspace=workspace, provider_profile="codex") + message = InboundMessage( + channel="slack", + sender_id="U_ALLOWED", + chat_id="C_SHARED", + content="/diff full", + ) + + updates = [update async for update in pool.stream_message(message, "slack:C_SHARED:U_ALLOWED")] + + assert updates[-1].kind == "final" + assert updates[-1].text == "/diff is only available in the local OpenHarness UI." + assert "LEAKMARK_REMOTE_DIFF_VALUE" not in updates[-1].text + + @pytest.mark.asyncio async def test_runtime_pool_uses_managed_group_cwd_binding(tmp_path, monkeypatch): workspace = tmp_path / ".ohmo-home" From efb4b71eb36ed306cf44beb8ef8e8281c3a6ed48 Mon Sep 17 00:00:00 2001 From: hinotoi-agent Date: Tue, 12 May 2026 10:21:54 +0800 Subject: [PATCH 2/2] chore: retrigger CI for diff command fix