Compare commits

...

1 Commits

Author SHA1 Message Date
freemo 3c8ed0aaea docs: add shell safety API docs and update README highlights
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 26s
CI / quality (pull_request) Successful in 35s
CI / helm (pull_request) Successful in 26s
CI / security (pull_request) Successful in 54s
CI / build (pull_request) Successful in 37s
CI / typecheck (pull_request) Successful in 58s
CI / unit_tests (pull_request) Successful in 9m57s
CI / coverage (pull_request) Successful in 10m59s
CI / e2e_tests (pull_request) Successful in 16m40s
CI / integration_tests (pull_request) Successful in 22m18s
CI / docker (pull_request) Successful in 1m52s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Successful in 56m5s
Document the new ShellSafetyService subsystem (DangerousPattern,
ShellDangerLevel, DangerousPatternDetector, SafetyCheckResult) in
docs/api/tui.md with the full built-in pattern table and usage examples.

Update README.md Highlights to surface inline PermissionQuestionWidget,
shell danger detection, and plan workflow isolation (legacy/v3 mixing
guard) introduced in the unreleased milestone.
2026-04-05 02:28:45 +00:00
2 changed files with 162 additions and 0 deletions
+9
View File
@@ -22,6 +22,12 @@ embracing modern Python tooling.
application services (session, plan, registry, event)
- **Permissions screen** — TUI overlay for reviewing tool permission requests with
unified, side-by-side, and context diff views; session-scoped allow/reject decisions
- **Inline permission questions** — `PermissionQuestionWidget` renders single-file
permission requests directly in the conversation stream; single-key shortcuts
(`a`/`A`/`r`/`R`) resolve without opening the full overlay
- **Shell danger detection** — TUI shell mode (`!` prefix) scans commands against a
configurable pattern registry before execution; warning overlay surfaces dangerous
patterns (CRITICAL/HIGH/MEDIUM/LOW) and lets the user abort or proceed
- **Actor thought blocks** — expandable reasoning trace widgets rendered inline in the
conversation stream with muted styling
- **UKO runtime** — Universal Knowledge Ontology query interface, inference engine, and
@@ -30,6 +36,9 @@ embracing modern Python tooling.
PostgreSQL, MySQL, and DuckDB resources
- **Estimation lifecycle** — `actor.default.estimation` config key wires an estimation
actor into the Strategize-to-Estimate lifecycle hook
- **Plan workflow isolation** — `agents plan` commands detect and reject attempts to
mix legacy plan commands with v3 plan workflows in the same session, surfacing a
clear error with migration guidance
- Fast Typer/Click-based interface with parity for help/version behavior
- Behavior-driven coverage via Behave and Robot Framework
- Nox automation for linting, typing, testing, docs, builds, and benchmarks
+153
View File
@@ -269,6 +269,159 @@ from cleveragents.tui.screens import PermissionsScreen
---
## Shell Safety
The TUI shell mode (`!` prefix) passes commands through a configurable
danger-detection layer before execution. A warning overlay is surfaced to
the user when a dangerous pattern is matched; the user can choose to proceed
or abort.
**Module:** `cleveragents.tui.shell_safety`
### `ShellDangerLevel`
```python
from cleveragents.tui.shell_safety import ShellDangerLevel
class ShellDangerLevel(IntEnum):
LOW = 1 # minor risk, generally recoverable
MEDIUM = 2 # moderate risk — data loss or security exposure possible
HIGH = 3 # significant, hard-to-reverse damage likely
CRITICAL = 4 # system destruction or fork bomb
```
Levels are ordered so numeric comparisons work naturally:
`level >= ShellDangerLevel.HIGH`.
---
### `DangerousPattern`
```python
from cleveragents.tui.shell_safety import DangerousPattern
pattern = DangerousPattern(
name="rm_rf_root",
pattern=r"rm\s+(-\w*r\w*f|-\w*f\w*r)\s+/\s*$",
level=ShellDangerLevel.CRITICAL,
description="rm -rf / recursively deletes the entire filesystem root.",
)
```
A frozen dataclass describing a single dangerous shell pattern.
| Field | Type | Description |
|-------|------|-------------|
| `name` | `str` | Unique identifier for the pattern |
| `pattern` | `str` | Regular expression matched against the command |
| `level` | `ShellDangerLevel` | Severity classification |
| `description` | `str` | Human-readable explanation shown in the warning overlay |
---
### Built-in Patterns (`DEFAULT_PATTERNS`)
The default pattern registry covers the following categories:
| Name | Level | Description |
|------|-------|-------------|
| `rm_rf_root` | CRITICAL | `rm -rf /` — destroys filesystem root |
| `rm_rf_wildcard` | CRITICAL | `rm -rf /*` or similar wildcard paths |
| `fork_bomb` | CRITICAL | `:(){ :|:& };:` — exhausts process table |
| `dd_if_device` | HIGH | `dd if=` — can overwrite disk devices |
| `mkfs` | HIGH | Formats a filesystem, erasing all data |
| `shred_device` | HIGH | `shred` on a device or with `--remove` |
| `chmod_777` | MEDIUM | World-writable permissions |
| `sudo_rm` | MEDIUM | `sudo rm` — elevated-privilege deletion |
| `wget_pipe_sh` | MEDIUM | Remote code execution via `wget \| sh` |
| `curl_pipe_sh` | MEDIUM | Remote code execution via `curl \| sh` |
| `wget_pipe_bash` | MEDIUM | Remote code execution via `wget \| bash` |
| `curl_pipe_bash` | MEDIUM | Remote code execution via `curl \| bash` |
| `git_push_force` | LOW | `git push --force` — overwrites remote history |
| `chmod_recursive_permissive` | LOW | Recursive chmod with permissive modes |
---
### `ShellSafetyService`
```python
from cleveragents.tui.shell_safety import ShellSafetyService
service = ShellSafetyService()
result = service.check_command("rm -rf /")
if not result.allowed:
print(result.warning.message)
```
Application service that wraps `DangerousPatternDetector` with a higher-level
API.
```python
ShellSafetyService(
*,
detector: DangerousPatternDetector | None = None,
block_level: ShellDangerLevel = ShellDangerLevel.MEDIUM,
warn_callback: Callable[[DangerousCommandWarning], bool] | None = None,
extra_patterns: list[DangerousPattern] | None = None,
)
```
| Parameter | Description |
|-----------|-------------|
| `detector` | Custom detector; defaults to `DangerousPatternDetector()` with `DEFAULT_PATTERNS` |
| `block_level` | Minimum level that triggers automatic blocking when no `warn_callback` is provided (default: `MEDIUM`) |
| `warn_callback` | Optional `(warning) -> bool`; return `True` to allow, `False` to block |
| `extra_patterns` | Additional patterns registered on top of the defaults |
**Methods:**
| Method | Returns | Description |
|--------|---------|-------------|
| `check_command(command)` | `SafetyCheckResult` | Full safety check with warning and allow/block decision |
| `is_safe(command)` | `bool` | Convenience wrapper — `True` if command is allowed |
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `detector` | `DangerousPatternDetector` | The underlying detector instance |
| `block_level` | `ShellDangerLevel` | The configured automatic-block threshold |
---
### `SafetyCheckResult`
```python
result = service.check_command("sudo rm -rf /var/log")
result.command # "sudo rm -rf /var/log"
result.allowed # False (MEDIUM >= block_level MEDIUM)
result.warning # DangerousCommandWarning(...)
```
| Attribute | Type | Description |
|-----------|------|-------------|
| `command` | `str` | The command that was checked |
| `warning` | `DangerousCommandWarning \| None` | Warning if a pattern matched, else `None` |
| `allowed` | `bool` | `True` if the command is permitted to proceed |
---
### `DangerousPatternDetector`
```python
from cleveragents.tui.shell_safety import DangerousPatternDetector
detector = DangerousPatternDetector()
detector.add_pattern(my_pattern)
warning = detector.check_first("rm -rf /")
```
Low-level detector that scans a command string against all registered patterns
and returns the first (highest-severity) match as a `DangerousCommandWarning`,
or `None` if no pattern matches.
---
## TUI State Persistence
The TUI persists minimal state to `~/.config/cleveragents/tui-state.yaml`: