mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-02 19:58:46 +00:00
88 lines
5.1 KiB
Python
88 lines
5.1 KiB
Python
"""An ordinary parent names concrete task targets; descendants only narrow them."""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import queue
|
|
|
|
import pytest
|
|
|
|
from ouroboros.contracts.task_contract import build_task_contract, normalize_allowed_origins, normalize_browser_origin
|
|
from ouroboros.contracts.task_constraint import TaskConstraint
|
|
from ouroboros.tools.control import _schedule_task
|
|
from ouroboros.tools.control_subagent_spec import _validated_schedule_fields
|
|
from ouroboros.tools.registry import ToolContext
|
|
from supervisor.task_dispatch import build_scheduled_task_payload
|
|
from tests._shared import configure_test_subagent
|
|
|
|
|
|
@pytest.mark.parametrize("source,expected", [
|
|
("HTTP://Example.test./", "http://example.test:80"),
|
|
("https://bücher.test", "https://xn--bcher-kva.test:443"),
|
|
("http://[::1]:5173", "http://[::1]:5173"),
|
|
("http://192.168.1.3:5173", "http://192.168.1.3:5173"),
|
|
("http://*.test", ""), ("http://user:pass@host", ""),
|
|
("file:///tmp", ""), ("http://host:0", ""), ("http://host:99999", ""),
|
|
("http://host/path", ""), ("http://host?secret=value", ""),
|
|
])
|
|
def test_only_concrete_origins_normalize(source, expected):
|
|
assert normalize_browser_origin(source, origin_only=True) == expected
|
|
|
|
|
|
def test_origin_contract_normalization_keeps_other_resource_policy():
|
|
policy = {"allowed_origins": ["http://dev.test", "http://dev.test:80/", "*"], "unrelated": {"x": 1}}
|
|
result = build_task_contract({"resource_policy": policy})
|
|
assert result["resource_policy"] == {"allowed_origins": ["http://dev.test:80"], "unrelated": {"x": 1}}
|
|
assert policy["allowed_origins"][-1] == "*"
|
|
assert normalize_allowed_origins("http://dev.test") == []
|
|
|
|
|
|
def test_main_schedule_persists_target_and_child_can_only_inherit_or_narrow(tmp_path, monkeypatch):
|
|
subagent = configure_test_subagent(monkeypatch)
|
|
monkeypatch.setenv("OUROBOROS_MAX_SUBAGENT_DEPTH", "4")
|
|
canonical = tmp_path / "data"
|
|
ctx = ToolContext(repo_dir=tmp_path / "repo", drive_root=canonical, is_direct_chat=True)
|
|
ctx.task_id, ctx.task_depth, ctx.current_chat_id = "main", 0, 1
|
|
ctx.event_queue = queue.Queue()
|
|
ctx.task_metadata = {"root_task_id": "main"}
|
|
origins = ["http://192.168.1.20:5173", "http://dev.test:5173"]
|
|
answer = _schedule_task(ctx, subagent_id=subagent, objective="Verify the assigned UI",
|
|
expected_output="Screenshot and findings", allowed_origins=origins)
|
|
assert "error" not in answer.lower(), answer
|
|
event = ctx.event_queue.get_nowait()
|
|
saved = json.loads((canonical / "task_results" / f"{event['task_id']}.json").read_text())
|
|
contract = event["task_contract"]
|
|
assert saved["task_contract"]["resource_policy"]["allowed_origins"] == origins
|
|
assert contract["source"] == "parent_delegation"
|
|
task = build_scheduled_task_payload({**event, "tid": event["task_id"], "parent_id": "main"})
|
|
child = ToolContext(repo_dir=ctx.repo_dir, drive_root=canonical, task_constraint=TaskConstraint(mode="local_readonly_subagent"))
|
|
child.task_metadata, child.task_contract = task["metadata"], task["task_contract"]
|
|
request = {"objective": "Inspect", "expected_output": "Findings"}
|
|
inherited, error = _validated_schedule_fields(request, ctx=child)
|
|
assert not error and inherited["resource_policy"]["allowed_origins"] == origins
|
|
for selected in ([], origins[:1]):
|
|
narrowed, error = _validated_schedule_fields({**request, "allowed_origins": selected}, ctx=child)
|
|
assert not error and narrowed["resource_policy"]["allowed_origins"] == selected
|
|
_, error = _validated_schedule_fields({**request, "allowed_origins": ["http://192.168.1.21:5173"]}, ctx=child)
|
|
assert "BROWSER_ORIGIN_NOT_GRANTED" in error
|
|
assert child.task_contract["resource_policy"]["allowed_origins"] == origins
|
|
child.task_id, child.task_depth, child.current_chat_id = event["task_id"], 1, 1
|
|
child.event_queue = queue.Queue()
|
|
answer = _schedule_task(child, subagent_id=subagent, **request, allowed_origins=origins[:1])
|
|
assert "error" not in answer.lower(), answer
|
|
grandchild = child.event_queue.get_nowait()
|
|
saved = json.loads((canonical / "task_results" / f"{grandchild['task_id']}.json").read_text())
|
|
assert saved["task_contract"]["resource_policy"]["allowed_origins"] == origins[:1]
|
|
assert grandchild["task_contract"]["resource_policy"]["allowed_origins"] == origins[:1]
|
|
assert child.task_contract["resource_policy"]["allowed_origins"] == origins
|
|
|
|
|
|
def test_external_presence_cannot_mint_origin_from_an_event(tmp_path):
|
|
from ouroboros.presence_authority import PresenceCapabilityCeiling, presence_ceiling_payload
|
|
|
|
ceiling = PresenceCapabilityCeiling("helper", "a" * 64, "b" * 64, "c" * 64,
|
|
"d" * 64, "main", 10, (), (), "0" * 64)
|
|
ctx = ToolContext(repo_dir=tmp_path, drive_root=tmp_path, is_direct_chat=True)
|
|
ctx.task_contract = {"capability_ceiling": presence_ceiling_payload(ceiling)}
|
|
_, error = _validated_schedule_fields({"objective": "Open a page", "expected_output": "Screenshot",
|
|
"allowed_origins": ["http://10.1.2.3:5173"]}, ctx=ctx)
|
|
assert "BROWSER_ORIGIN_NOT_GRANTED" in error
|