diff --git a/workspace/executor_helpers.py b/workspace/executor_helpers.py index 95e73857..dc40301e 100644 --- a/workspace/executor_helpers.py +++ b/workspace/executor_helpers.py @@ -299,11 +299,11 @@ Instead: (1) try delegating to a different peer, (2) handle the task yourself, o _A2A_INSTRUCTIONS_CLI = """## Inter-Agent Communication You can delegate tasks to other workspaces using the a2a command: - python3 /app/a2a_cli.py peers # List available peers - python3 /app/a2a_cli.py delegate # Sync: wait for response - python3 /app/a2a_cli.py delegate --async # Async: return task_id - python3 /app/a2a_cli.py status # Check async task - python3 /app/a2a_cli.py info # Your workspace info + python3 -m molecule_runtime.a2a_cli peers # List available peers + python3 -m molecule_runtime.a2a_cli delegate # Sync: wait for response + python3 -m molecule_runtime.a2a_cli delegate --async # Async: return task_id + python3 -m molecule_runtime.a2a_cli status # Check async task + python3 -m molecule_runtime.a2a_cli info # Your workspace info For quick questions, use sync delegate. For long tasks, use --async + status. Only delegate to peers listed by the peers command (access control enforced).""" diff --git a/workspace/molecule_ai_status.py b/workspace/molecule_ai_status.py index 6787c38e..fa22ba9c 100644 --- a/workspace/molecule_ai_status.py +++ b/workspace/molecule_ai_status.py @@ -4,14 +4,10 @@ Usage (from any script, cron job, or shell inside the container): # Set current task (shows on canvas card) - python3 /app/molecule_ai_status.py "Running weekly SEO audit..." + python3 -m molecule_runtime.molecule_ai_status "Running weekly SEO audit..." # Clear task (removes banner from canvas) - python3 /app/molecule_ai_status.py "" - - # Or use the shell alias: - molecule-monorepo-status "Analyzing competitor data..." - molecule-monorepo-status "" + python3 -m molecule_runtime.molecule_ai_status "" The status appears as an amber banner on the workspace card in the canvas, visible to the project owner in real-time. @@ -63,13 +59,13 @@ def set_status(task: str): timeout=5.0, ) except Exception as e: - print(f"molecule-monorepo-status: failed to update: {e}", file=sys.stderr) + print(f"molecule_ai_status: failed to update: {e}", file=sys.stderr) if __name__ == "__main__": # pragma: no cover if len(sys.argv) < 2: - print("Usage: molecule-monorepo-status 'task description'") - print(" molecule-monorepo-status '' # clear") + print("Usage: python3 -m molecule_runtime.molecule_ai_status 'task description'") + print(" python3 -m molecule_runtime.molecule_ai_status '' # clear") sys.exit(1) set_status(sys.argv[1]) diff --git a/workspace/tests/test_executor_helpers.py b/workspace/tests/test_executor_helpers.py index 688f6044..75869be2 100644 --- a/workspace/tests/test_executor_helpers.py +++ b/workspace/tests/test_executor_helpers.py @@ -445,10 +445,28 @@ def test_get_a2a_instructions_mcp_default(): def test_get_a2a_instructions_cli_variant(): out = get_a2a_instructions(mcp=False) - assert "a2a_cli.py" in out + assert "a2a_cli" in out assert "MCP tools" not in out +def test_a2a_cli_instructions_use_module_invocation_not_legacy_app_path(): + # The CLI variant of the a2a instructions ships in the agent system + # prompt for non-MCP runtimes (Ollama, custom). The model copies the + # invocation form verbatim into shell calls, so any path drift here + # silently breaks delegation. The legacy /app/a2a_cli.py path was + # correct under the pre-#87 monolithic-template Docker layout but + # stops resolving once the runtime ships as a wheel — pin the + # canonical `python3 -m molecule_runtime.a2a_cli` form so future + # refactors can't silently regress it. + out = get_a2a_instructions(mcp=False) + assert "/app/a2a_cli.py" not in out, ( + "Legacy /app/a2a_cli.py path leaked back into the CLI-variant " + "system prompt — agents on Ollama/custom runtimes would copy " + "this verbatim and every delegation would fail." + ) + assert "python3 -m molecule_runtime.a2a_cli" in out + + def test_a2a_mcp_instructions_reference_existing_tools(): """The MCP instructions text must only reference tools that are actually registered in a2a_mcp_server.py. If someone renames a server tool, the