mirror of
https://github.com/usestrix/strix.git
synced 2026-08-25 04:12:37 +02:00
feat(safety): add contextual action review with guarded and observe modes
Introduce a pre-execution safety layer that reviews effectful agent actions against compiled, frozen evidence before they run. `--safety-mode guarded` allows non-destructive interaction after review; `--safety-mode observe` permits passive target interaction only. `off` stays the default, so existing runs are unchanged. Deterministic rules decide what they can on their own: destructive commands, code-loading environment overrides, blocked browser actions, and mutating requests in observe mode are refused without a model call, and a small set of read-only commands is allowed outright. Everything else compiles an evidence packet — command, scope, script source and its local import closure, prior tool-call evidence, and browser snapshot context — for a bounded reviewer that may make one isolated inspection call. Incomplete evidence fails closed. In safety modes, user-owned local directories are copied into the run directory so the originals are never mounted writable, while `.git`, `.agents`, and `.codex` inside the copy stay read-only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,10 @@ _LLM_ENV_KEYS = [
|
||||
# RuntimeSettings
|
||||
"STRIX_IMAGE",
|
||||
"STRIX_RUNTIME_BACKEND",
|
||||
# SafetySettings
|
||||
"STRIX_SAFETY_MODE",
|
||||
"STRIX_SAFETY_MODEL",
|
||||
"STRIX_SAFETY_TIMEOUT",
|
||||
# TelemetrySettings
|
||||
"STRIX_TELEMETRY",
|
||||
]
|
||||
@@ -177,6 +181,29 @@ def test_apply_override_and_load_settings_round_trip(tmp_path: Path) -> None:
|
||||
assert loader.load_settings() is settings
|
||||
|
||||
|
||||
def test_safety_settings_load_from_config(tmp_path: Path) -> None:
|
||||
path = tmp_path / "cli-config.json"
|
||||
path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"env": {
|
||||
"STRIX_SAFETY_MODE": "guarded",
|
||||
"STRIX_SAFETY_MODEL": "openai/safety-model",
|
||||
"STRIX_SAFETY_TIMEOUT": "12",
|
||||
}
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
loader.apply_config_override(path)
|
||||
settings = loader.load_settings().safety
|
||||
|
||||
assert settings.mode == "guarded"
|
||||
assert settings.model == "openai/safety-model"
|
||||
assert settings.timeout == 12
|
||||
|
||||
|
||||
def test_apply_config_override_invalidates_cache(tmp_path: Path) -> None:
|
||||
first = tmp_path / "first.json"
|
||||
first.write_text(json.dumps({"env": {"STRIX_LLM": "first-model"}}), encoding="utf-8")
|
||||
|
||||
Reference in New Issue
Block a user