Files
cleveragents-core/robot/tui_shell_safety.robot
HAL9000 b56c824909 fix(tui): repair shell-safety test scaffolding
Three independent test-scaffold defects blocked the unit_tests and
integration_tests gates on PR #6361's shell-safety wiring:

- features/steps/_tui_helpers.py: the mocked-shell helper patched
  cleveragents.tui.input.shell_exec.run_shell_command, but modes.py
  binds the symbol into its own namespace via `from ... import`. The
  patch was inert, and only the CLEVERAGENTS_ALLOW_DANGEROUS_SHELL=1
  gate kept the real `rm -rf /tmp` from running in the behave runner.
  Patch the use site (modes.run_shell_command) instead.

- src/cleveragents/tui/widgets/prompt.py: _FallbackPromptInput (used
  whenever Textual is mocked or unavailable) had no add_class /
  remove_class / has_class, so the new "prompt should be marked as
  dangerous" assertions raised AttributeError and the three new
  scenarios errored. The production path (_TextualPromptInput) already
  inherits these from textual.containers.Horizontal; the fallback now
  mirrors that contract via a small self._classes set.

- robot/tui_shell_safety.robot: Catenate's space-based argument
  separator collapses multi-space indentation, so the Python function
  bodies (warn_callback, deny) landed at column 0 and the helper
  scripts died with IndentationError before either assertion ran.
  Preserve the 4-space indent with ${SPACE * 4} markers.

ISSUES CLOSED: #6361
2026-06-17 00:21:34 -04:00

63 lines
3.3 KiB
Plaintext

*** Settings ***
Documentation Integration coverage for TUI shell safety wiring and safeguards.
Resource ${CURDIR}/common.resource
Suite Setup Setup Test Environment With Database Isolation
Suite Teardown Cleanup Test Environment
*** Variables ***
${TIMEOUT} 45s
*** Test Cases ***
Shell Safety Service Blocks Denied Command
[Documentation] ShellSafetyService verdict should block commands even when heuristics allow them.
[Tags] tui shell_safety regression
${script}= Catenate SEPARATOR=\n
... import os
... from cleveragents.tui.input.modes import InputModeRouter
... from cleveragents.tui.shell_safety import ShellSafetyService
... from cleveragents.tui.shell_safety.warning import DangerousCommandWarning
...
... warnings: list[DangerousCommandWarning] = []
...
... def warn_callback(warning: DangerousCommandWarning) -> bool:
... ${SPACE * 4}warnings.append(warning)
... ${SPACE * 4}return False
...
... router = InputModeRouter(lambda cmd: "handled", shell_safety=ShellSafetyService(warn_callback=warn_callback))
... os.environ.pop("CLEVERAGENTS_ALLOW_DANGEROUS_SHELL", None)
... result = router.process("!chmod -R 777 /tmp/test-shell-safety")
... assert result.shell_warning is not None, "Shell safety warning should be surfaced"
... assert warnings and warnings[0].command == "chmod -R 777 /tmp/test-shell-safety"
... assert result.shell_result is not None, "Shell result should be populated"
... assert result.shell_result.exit_code == 1, f"Expected blocked exit code, got {result.shell_result.exit_code}"
... assert "blocked" in result.shell_result.stderr.lower(), result.shell_result.stderr
... print("blocked-ok")
${result}= Run Process ${PYTHON} -c ${script}
... timeout=${TIMEOUT} on_timeout=kill
... env:PYTHONPATH=${CURDIR}/../src
Should Be Equal As Integers ${result.rc} 0 Shell safety blocking script failed: ${result.stderr}
Should Contain ${result.stdout} blocked-ok
Shell Confirm Callback Gates All Commands
[Documentation] run_shell_command must respect confirm callback regardless of built-in heuristics.
[Tags] tui shell_safety regression
${script}= Catenate SEPARATOR=\n
... from cleveragents.tui.input.shell_exec import run_shell_command
...
... counter = {"count": 0}
...
... def deny(command: str) -> bool:
... ${SPACE * 4}counter["count"] += 1
... ${SPACE * 4}return False
...
... result = run_shell_command("chmod -R 777 /tmp/test-shell-safety", confirm_dangerous=deny)
... assert counter["count"] == 1, f"Expected confirm to be invoked once, got {counter['count']}"
... assert result.exit_code == 1, f"Expected blocked exit code, got {result.exit_code}"
... assert "blocked" in result.stderr.lower(), result.stderr
... print("confirm-gate-ok")
${result}= Run Process ${PYTHON} -c ${script}
... timeout=${TIMEOUT} on_timeout=kill
... env:PYTHONPATH=${CURDIR}/../src
Should Be Equal As Integers ${result.rc} 0 Shell confirm gate script failed: ${result.stderr}
Should Contain ${result.stdout} confirm-gate-ok