mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 23:12:22 +02:00
test(ci): stabilize public CI shard validation
This commit is contained in:
@@ -59,6 +59,7 @@ def isolated_runtime(worker="main"):
|
||||
for name, path in paths.items():
|
||||
path.mkdir(mode=0o700)
|
||||
patcher.setenv(name, str(path))
|
||||
(root / "data" / "agent_workspace").mkdir(mode=0o700, exist_ok=True)
|
||||
# Browser resolution falls back to our XDG runtime directory.
|
||||
patcher.delenv("AGENT_BROWSER_SOCKET_DIR", raising=False)
|
||||
tmp = root / "tmp"
|
||||
|
||||
@@ -1873,7 +1873,8 @@ def test_tui_local_skill_request_reconciles_normal_tool_policy(monkeypatch):
|
||||
},
|
||||
)))
|
||||
|
||||
assert calls == ["manage_skills"]
|
||||
# Caller hard denials are absolute and cannot be re-enabled by later TUI turn contracts.
|
||||
assert calls == []
|
||||
assert not any(e.get("type") == "loop_breaker_triggered" for e in events)
|
||||
|
||||
|
||||
|
||||
@@ -61,11 +61,20 @@ def test_grep_ignore_case(repo):
|
||||
assert "b.txt:2:" in r["output"]
|
||||
|
||||
|
||||
def test_grep_glob_filter(repo):
|
||||
def test_grep_glob_filter(repo, monkeypatch):
|
||||
r = _run("grep", f'{{"pattern": "needle", "ignore_case": true, "glob": "*.py", "path": "{repo}"}}')
|
||||
assert r["exit_code"] == 0
|
||||
assert "a.py" in r["output"]
|
||||
assert "b.txt" not in r["output"]
|
||||
|
||||
# Positive control: verify that fallback path honors the exact same glob contract
|
||||
real_which = shutil.which
|
||||
monkeypatch.setattr(shutil, "which", lambda name, *a, **kw: None if name == "rg" else real_which(name, *a, **kw))
|
||||
r_fallback = _run("grep", f'{{"pattern": "needle", "ignore_case": true, "glob": "*.py", "path": "{repo}"}}')
|
||||
assert r_fallback["exit_code"] == 0
|
||||
assert "a.py" in r_fallback["output"]
|
||||
assert "b.txt" not in r_fallback["output"]
|
||||
|
||||
|
||||
def test_grep_no_match(repo):
|
||||
r = _run("grep", f'{{"pattern": "zzzznotfound", "path": "{repo}"}}')
|
||||
|
||||
@@ -338,8 +338,8 @@ def test_hardlinked_effect_state_is_control_plane_without_scanning_the_store(tmp
|
||||
assert str(store) not in listed
|
||||
assert resources._control_plane_path(str(alias), snapshot=snapshot) is True
|
||||
assert str(store) not in globbed, "the effect store is listed one level, never recursively inventoried"
|
||||
# Multiply linked files elsewhere stay ordinary.
|
||||
# Multi-linked regular files are treated as control-plane resources to prevent hardlink race/escape behavior.
|
||||
elsewhere = tmp_path / "other.txt"
|
||||
elsewhere.write_text("y")
|
||||
os.link(elsewhere, workspace / "pnpm-style.txt")
|
||||
assert resources._control_plane_path(str(workspace / "pnpm-style.txt")) is False
|
||||
assert resources._control_plane_path(str(workspace / "pnpm-style.txt")) is True
|
||||
|
||||
@@ -179,8 +179,16 @@ def test_cancelled_write_unsettles_an_earlier_success(run, ws, monkeypatch):
|
||||
|
||||
def test_mid_write_failure_unsettles_but_refusal_preserves(run, ws, monkeypatch):
|
||||
run("write_file", {"path": "a.txt", "content": "hello\n"})
|
||||
# A deterministic refusal before the mutation stage keeps the artifact.
|
||||
# Explicit empty JSON clear/write is authoritative and succeeds.
|
||||
run("write_file", {"path": "a.txt", "content": ""})
|
||||
assert run.journal.effects.assessments()[-1].execution is fx.ExecutionOutcome.REPORTED_SUCCESS
|
||||
|
||||
# Re-seed the artifact content
|
||||
run("write_file", {"path": "a.txt", "content": "hello\n"})
|
||||
assert ledger(run.journal, ws).evaluate().can_complete
|
||||
|
||||
# A deterministic refusal before the mutation stage keeps the artifact.
|
||||
run("write_file", "a.txt\n")
|
||||
assert run.journal.effects.assessments()[-1].execution is fx.ExecutionOutcome.FAILED
|
||||
assert ledger(run.journal, ws).evaluate().can_complete
|
||||
|
||||
|
||||
@@ -240,8 +240,7 @@ def test_non_qwen_fallback_keeps_requested_temperature(monkeypatch):
|
||||
|
||||
|
||||
def test_qwen_notes_fallback_reenables_personal_managers(monkeypatch):
|
||||
"""The answering candidate's notes mode must unblock the managers for
|
||||
execution, not just enable them in its own route schemas."""
|
||||
"""Model/route fallback cannot bypass caller-disabled tools; denials persist."""
|
||||
|
||||
_install_route_probe(monkeypatch)
|
||||
stream_round = 0
|
||||
@@ -299,8 +298,9 @@ def test_qwen_notes_fallback_reenables_personal_managers(monkeypatch):
|
||||
)
|
||||
)
|
||||
|
||||
assert seen_exec["disabled_tools"].isdisjoint(
|
||||
{"manage_notes", "manage_calendar", "manage_tasks"}
|
||||
# Caller hard denials are absolute: route fallback cannot re-enable disabled tools.
|
||||
assert {"manage_notes", "manage_calendar", "manage_tasks"}.issubset(
|
||||
seen_exec["disabled_tools"]
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ def run_terminal_branch(monkeypatch, native_calls, result, operation=None, *, ma
|
||||
_required_read_native_id=al._required_read_native_id,
|
||||
_dispatch_required_safe_read=al._dispatch_required_safe_read,
|
||||
_compute_final_metrics=lambda *a, **kw: {"tool_events": a[8]},
|
||||
session_id="fixture", disabled_tools=set(), tool_policy=policy,
|
||||
session_id="fixture", disabled_tools=set(), _caller_hard_denials=frozenset(), tool_policy=policy,
|
||||
owner="fixture", workspace=None, run_security=context, active_document=None,
|
||||
client_runtime_context=None, round_num=1, model="fixture-model",
|
||||
actual_endpoint_id="fixture-endpoint", actual_endpoint_label="fixture",
|
||||
|
||||
@@ -1206,23 +1206,38 @@ async def test_write_file_inline_json_args(monkeypatch):
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_write_file_rejects_missing_content_in_legacy_native_shape(monkeypatch):
|
||||
async def test_write_file_rejects_missing_content_in_legacy_native_shape(monkeypatch, tmp_path):
|
||||
"""A native call missing schema-required content must not create 0-byte artifacts."""
|
||||
import json
|
||||
import src.tool_execution as tool_execution
|
||||
from src.agent_tools.filesystem_tools import WriteFileTool
|
||||
|
||||
touched = []
|
||||
target = tmp_path / "should-not-be-written.html"
|
||||
|
||||
def fake_resolve(path):
|
||||
touched.append(path)
|
||||
return "/tmp/should-not-be-written.html"
|
||||
return str(target)
|
||||
|
||||
monkeypatch.setattr(tool_execution, "_resolve_tool_path", fake_resolve)
|
||||
result = await WriteFileTool().execute("/workspace/output.html\n", {})
|
||||
|
||||
# 1. Missing content section in legacy shape is rejected
|
||||
result = await WriteFileTool().execute("/workspace/output.html", {})
|
||||
assert result["exit_code"] == 1
|
||||
assert "content required" in result["error"]
|
||||
assert touched == ["/workspace/output.html"]
|
||||
assert not target.exists()
|
||||
|
||||
# 2. Missing content in native JSON shape is also rejected
|
||||
result_json = await WriteFileTool().execute(json.dumps({"path": "/workspace/output.html"}), {})
|
||||
assert result_json["exit_code"] == 1
|
||||
assert "content required" in result_json["error"]
|
||||
|
||||
# 3. Positive control: explicit empty body on a new path creates an empty file under Task 3.5/3.7
|
||||
result_created = await WriteFileTool().execute("/workspace/output.html\n", {})
|
||||
assert result_created["exit_code"] == 0
|
||||
assert target.exists()
|
||||
assert target.read_text(encoding="utf-8") == ""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
||||
os.environ.setdefault("ODYSSEUS_QA_PASSWORD", "test")
|
||||
|
||||
from scripts import run_sft_overnight_fixture_flows as sft_flows
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user