ouroboros/tests/test_consciousness_authority.py
Ouroboros 16281a517d Post-task synthesis and routing read one host-recorded run origin
The first user message of every run was recorded as source="initial_user"
regardless of who issued the run, then printed to the reflection and summary
prompts as "## Task goal" and "Owner decisions" under two interrogation
templates, one asserting "non-trivial (high round count or high cost)" for any
run the workspace trigger admitted. A Presence turn that rightly stayed silent
on a colleague's message to a third person was reviewed as an unfulfilled owner
assignment and persisted the lesson "do not finish silently"; wake templates,
follow-ups, schedules, host templates and children's work orders travel the same
path. _routing_issuer shared the class: a Presence event (provider event id as
client_message_id) and the auto-resume template counted as owner turns.

dialogue_provenance.run_origin mints the one authority fact from typed fields:
owner_ingress is True iff owner routing stamped the run (origin_message_ref or
origin_suppressed, inherited by a promoted root by value); every other key is
the raw marker the producer recorded. The corpus label follows the stamp
(initial_user / initial_text; owner rows keep their bytes and hash), the routing
issuer is the direct turn the door stamped, the stamp is reserved on /api/tasks
and schedule templates, capture_task_inputs freezes run_origin first, the
acceptance packet carries it host_attested, the reflection has one open frame
with the origin before the initial text, the Pattern Register and the context
renderer show the origin, and the transcript fallback runs only without a
collector under labels that claim no owner authority.

Chapter budgets for 01, 06 and development/03 are re-based with the sizes the
official line already carries after the long-work continuity merge.
2026-09-24 23:42:24 +03:00

972 lines
53 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Authority levels of a consciousness wake-up and how they follow its work (P3).
Observe / Act / Full (owner decision В10', default Act) are carried as
``metadata.consciousness_autonomy`` and derived at task build into the
contract's ``disabled_tools`` and the per-task ``runtime_mode_cap`` (В21=A);
for a consciousness-origin task the disabled list binds at DISPATCH ONLY so the
wake's tool schemas and prompt prefix are byte-identical to an owner turn's
(В31=B, the I3 comparison below). The origin (label, ledger category, level)
is inherited by everything the wake starts; a wake speaks as a task through
``steer_task`` (ISSUER, PLAN 5.2a); ``/evolve off`` is sticky against the agent
tool (В12); a Full-level campaign stays inside the consciousness tree.
"""
from __future__ import annotations
import json
import pathlib
import types
import pytest
from ouroboros import consciousness_authority as ca
from ouroboros.tools.registry import ToolContext, ToolRegistry
WAKE_META = {
"initiator": "consciousness", "usage_category": "consciousness",
"wake_reason": "heartbeat", "consciousness_autonomy": "act", "model_role": "consciousness",
}
def _wake_task(level="act", **extra):
task = {"id": "wake-1", "type": "task", "text": "wake", "_is_direct_chat": True, "chat_id": 1,
"metadata": {**WAKE_META, "consciousness_autonomy": level, **extra}}
return ca.apply_consciousness_authority(task)
def _registry(tmp_path, metadata=None, *, task_id="turn-1"):
repo = tmp_path / "repo"
repo.mkdir(exist_ok=True)
(repo / "README.md").write_text("ok\n", encoding="utf-8")
drive = tmp_path / "drive"
drive.mkdir(exist_ok=True)
reg = ToolRegistry(repo_dir=repo, drive_root=drive)
reg.set_context(ToolContext(
repo_dir=repo, drive_root=drive, task_id=task_id, is_direct_chat=True,
task_metadata=dict(metadata or {}),
))
return reg
# --- the level tables -------------------------------------------------------------
def test_levels_and_their_two_consequences():
assert ca.LEVELS == ("observe", "act", "full")
assert ca.disabled_tools_for("full") == []
assert ca.disabled_tools_for("act") == list(ca.ACT_DISABLED)
observe = ca.disabled_tools_for("observe")
assert set(ca.ACT_DISABLED) <= set(observe)
assert {"promote_chat_to_task", "run_command",
"browser_action", "initiate_presence", "submit_skill_to_hub"} <= set(observe)
# The names with a real read-only path are kept and narrowed on ARGUMENTS.
assert ca.OBSERVE_ARGUMENT_NARROWED.isdisjoint(observe)
assert {"schedule_subagent", "delegate_start", "cancel_task"} <= ca.OBSERVE_ARGUMENT_NARROWED
# The nanny of a running campaign is never withheld, at any level.
assert "steer_task" not in observe and "steer_task" not in ca.disabled_tools_for("act")
# Observe is an EXCEPTION list: reading and talking stay available by default.
for name in ("read_file", "web_search", "browse_page", "send_user_message", "escalate",
"knowledge_write", "update_scratchpad", "switch_model", "enable_tools"):
assert name not in observe
assert ca.runtime_mode_cap_for("act") == "light" == ca.runtime_mode_cap_for("observe")
assert ca.runtime_mode_cap_for("full") == ""
def test_unknown_level_falls_back_to_the_owner_setting(monkeypatch):
monkeypatch.setenv("OUROBOROS_CONSCIOUSNESS_AUTONOMY", "observe")
assert ca.normalize_level("bogus") == "observe"
assert ca.normalize_level("") == "observe"
assert ca.normalize_level("FULL") == "full"
def test_observe_table_covers_every_registry_entry_marked_mutates_worktree(tmp_path):
"""The registry marker is the second source of the same fact; the table cannot drift."""
reg = _registry(tmp_path)
marked = {e.name for e in reg._entries.values() if e.mutates_worktree and not e.alias_for}
assert marked, "the catalog carries mutates_worktree entries"
# The argument-narrowed names have a read-only Observe path; what they may be
# ASKED to do is checked at dispatch instead of hiding the whole tool.
missing = marked - set(ca.OBSERVE_DISABLED) - ca.OBSERVE_ARGUMENT_NARROWED
assert not missing, f"mutates_worktree entries missing from OBSERVE_WORLD_MUTATION_TOOLS: {sorted(missing)}"
unknown = set(ca.OBSERVE_DISABLED) - {e.name for e in reg._entries.values()}
# Skill/project tools are registered lazily (skills, journal); the built-in names must exist.
assert unknown <= {"toggle_skill", "skill_owner_action", "journal_write", "workpad_write",
"configure_presence", "initiate_presence", "delegate_start"}, sorted(unknown)
# --- derivation at task build ---------------------------------------------------
def test_apply_consciousness_authority_derives_both_consequences_once():
task = _wake_task("act")
assert task["metadata"]["disabled_tools"] == list(ca.ACT_DISABLED)
assert task["metadata"]["runtime_mode_cap"] == "light"
full = _wake_task("full")
assert full["metadata"]["disabled_tools"] == [] and full["metadata"]["runtime_mode_cap"] == ""
# An explicit producer list stands; an owner turn is untouched.
explicit = _wake_task("act", disabled_tools=["web_search"])
assert explicit["metadata"]["disabled_tools"] == ["web_search"]
owner = ca.apply_consciousness_authority({"id": "o", "metadata": {"client_message_id": "cm"}})
assert "disabled_tools" not in owner["metadata"] and "runtime_mode_cap" not in owner["metadata"]
def test_contract_carries_the_derived_list_and_origin_helpers():
from ouroboros.contracts.task_contract import attach_task_contract
task = attach_task_contract(_wake_task("observe"))
assert task["task_contract"]["disabled_tools"] == ca.disabled_tools_for("observe")
assert "toggle_evolution" in ca.task_disabled_tools(task)
origin = ca.consciousness_origin_metadata(task["metadata"])
assert origin == {"initiator": "consciousness", "usage_category": "consciousness_task",
"consciousness_autonomy": "observe"}
assert ca.consciousness_origin_metadata({"client_message_id": "cm"}) == {}
assert ca.is_consciousness_origin(origin) and not ca.is_consciousness_origin(None)
@pytest.mark.parametrize(("install", "cap", "expected"), [
("cyber_pro", "light", "light"), ("pro", "light", "light"), ("advanced", "light", "light"),
("light", "light", "light"), ("light", "advanced", "light"), ("cyber_pro", "", "cyber_pro"),
("pro", "bogus", "pro"),
])
def test_effective_runtime_mode_is_the_stricter_of_install_and_cap(install, cap, expected):
assert ca.effective_runtime_mode(install, {"runtime_mode_cap": cap}) == expected
assert ca.effective_runtime_mode(install, None) == install
# --- dispatch-only enforcement (В31=B) -------------------------------------------
def test_consciousness_contract_keeps_the_full_schema_set_and_refuses_at_dispatch(tmp_path, monkeypatch):
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", "advanced")
main = _registry(tmp_path, {"client_message_id": "cm-1"})
wake = _registry(tmp_path, _wake_task("act")["metadata"])
# Same schemas, same advertised names, same initial envelope, same omission manifest.
assert wake.schemas() == main.schemas()
assert wake.available_tools() == main.available_tools()
assert wake.initial_tool_names() == main.initial_tool_names()
assert wake.capability_omissions() == main.capability_omissions()
assert not any(item.get("reason") == "disabled_by_contract" for item in wake.capability_omissions())
assert "toggle_evolution" in wake.available_tools()
assert wake.get_schema_by_name("toggle_evolution") is not None
assert wake.policy_hidden_reason("toggle_evolution") is None
# The dispatcher is the mechanism: the withheld name is refused with the typed block.
result = wake.execute("toggle_evolution", {"enabled": True, "objective": "x"})
assert "RESOURCE_CONSTRAINT_BLOCKED" in result and "toggle_evolution" in result
for name, args in (("request_restart", {}), ("set_tool_timeout", {"seconds": 30}),
("toggle_consciousness", {"action": "stop"})):
assert "RESOURCE_CONSTRAINT_BLOCKED" in wake.execute(name, args), name
def test_an_ordinary_contract_still_hides_its_disabled_tools(tmp_path):
"""The dispatch-only case is the consciousness special case, not a general change."""
reg = _registry(tmp_path, {"disabled_tools": ["toggle_evolution"]})
assert "toggle_evolution" not in reg.available_tools()
assert all(s["function"]["name"] != "toggle_evolution" for s in reg.schemas())
assert reg.get_schema_by_name("toggle_evolution") is None
assert reg.policy_hidden_reason("toggle_evolution") == "disabled by this task's contract (disabled_tools)"
assert any(item.get("reason") == "disabled_by_contract" for item in reg.capability_omissions())
def test_i3_serialized_request_prefix_matches_an_owner_turn(tmp_path, monkeypatch):
"""The provider request's cached prefix — the tool schema array and the two
cached system blocks up to the dynamic boundary (context_fit) — is byte-identical
for an owner turn and for a wake at Act and at Observe built from one snapshot."""
from ouroboros.context import build_llm_messages
from tests.test_cache_optimization import _make_env_and_memory
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", "advanced")
env, memory = _make_env_and_memory(tmp_path)
owner = {"id": "t-owner", "type": "task", "text": "hi", "_is_direct_chat": True, "chat_id": 1,
"metadata": {"client_message_id": "cm-1"}}
owner_msgs, _ = build_llm_messages(env=env, memory=memory, task=owner)
owner_prefix = [json.dumps(owner_msgs[0]["content"][i], sort_keys=True) for i in (0, 1)]
owner_reg = _registry(tmp_path, owner["metadata"], task_id="t-owner")
owner_tools = json.dumps(owner_reg.schemas(), sort_keys=True)
for level in ("act", "observe"):
task = _wake_task(level)
task.update(id="t-owner", text="hi") # the same turn: the wake differs only in its metadata
msgs, _ = build_llm_messages(env=env, memory=memory, task=task)
prefix = [json.dumps(msgs[0]["content"][i], sort_keys=True) for i in (0, 1)]
assert prefix == owner_prefix, level
assert "cache_control" not in msgs[0]["content"][2]
reg = _registry(tmp_path, task["metadata"], task_id="t-owner")
assert json.dumps(reg.schemas(), sort_keys=True) == owner_tools, level
assert reg.capability_omissions() == owner_reg.capability_omissions(), level
# --- the per-task mode cap (В21=A): level x install mode --------------------------
_BLOCKED_CALLS = (
("write_file", {"path": "README.md", "content": "changed\n"}),
("commit_reviewed", {"commit_message": "test"}),
("run_command", {"cmd": "touch x.py"}),
("start_service", {"cmd": ["sleep", "5"], "name": "svc"}),
)
@pytest.mark.parametrize("mode", ["light", "advanced", "pro", "cyber_pro"])
@pytest.mark.parametrize("level", ["act", "observe"])
@pytest.mark.parametrize(("tool_name", "args"), _BLOCKED_CALLS)
def test_act_and_observe_cannot_touch_the_repo_in_any_install_mode(tmp_path, monkeypatch, mode, level, tool_name, args):
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", mode)
reg = _registry(tmp_path, _wake_task(level)["metadata"])
result = reg.execute(tool_name, dict(args))
expected = "RESOURCE_CONSTRAINT_BLOCKED" if level == "observe" and tool_name != "commit_reviewed" else "LIGHT_MODE_BLOCKED"
assert expected in result, (mode, level, tool_name, result[:300])
assert not (tmp_path / "repo" / "x.py").exists()
assert (tmp_path / "repo" / "README.md").read_text(encoding="utf-8") == "ok\n"
@pytest.mark.parametrize("mode", ["advanced", "pro", "cyber_pro"])
def test_full_follows_the_install_mode(tmp_path, monkeypatch, mode):
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", mode)
reg = _registry(tmp_path, _wake_task("full")["metadata"])
assert "LIGHT_MODE_BLOCKED" not in reg.execute("write_file", {"path": "scratch.txt", "content": "changed\n"})
assert (tmp_path / "repo" / "scratch.txt").read_text(encoding="utf-8") == "changed\n"
assert "LIGHT_MODE_BLOCKED" not in reg.execute("run_command", {"cmd": "touch x.py"})
def test_full_in_a_light_install_is_still_light(tmp_path, monkeypatch):
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", "light")
reg = _registry(tmp_path, _wake_task("full")["metadata"])
assert "LIGHT_MODE_BLOCKED" in reg.execute("write_file", {"path": "README.md", "content": "x"})
@pytest.mark.parametrize(("level", "expected"), [("act", "LIGHT_MODE_BLOCKED"),
("observe", "RESOURCE_CONSTRAINT_BLOCKED")])
def test_a_repo_path_reached_through_user_files_is_still_light_blocked(tmp_path, monkeypatch, level, expected):
"""The P3 residual: a cyber_pro install resolves ``user_files`` to a base that
CONTAINS the repo, so the ROOT NAME alone cannot decide the light gate — the
resolved target must. A light-capped wake writing a repository path under
that root is refused; Observe never reaches the gate (the tool is withheld)."""
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", "cyber_pro")
monkeypatch.setenv("OUROBOROS_USER_FILES_ROOT", str(tmp_path))
reg = _registry(tmp_path, _wake_task(level)["metadata"])
target = tmp_path / "repo" / "x.py"
result = reg.execute("write_file", {"root": "user_files", "path": "repo/x.py", "content": "print(1)\n"})
assert expected in result, (level, result[:300])
assert not target.exists()
if level == "act":
# The same root still writes a genuine user file outside the repo.
assert "OK: wrote" in reg.execute(
"write_file", {"root": "user_files", "path": "notes.txt", "content": "kept\n"})
def test_full_may_still_write_a_repo_path_through_user_files(tmp_path, monkeypatch):
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", "cyber_pro")
monkeypatch.setenv("OUROBOROS_USER_FILES_ROOT", str(tmp_path))
reg = _registry(tmp_path, _wake_task("full")["metadata"])
assert "LIGHT_MODE_BLOCKED" not in reg.execute(
"write_file", {"root": "user_files", "path": "repo/x.py", "content": "print(1)\n"})
assert (tmp_path / "repo" / "x.py").read_text(encoding="utf-8") == "print(1)\n"
def test_act_keeps_the_light_positive_paths(tmp_path, monkeypatch):
monkeypatch.setenv("OUROBOROS_RUNTIME_MODE", "pro")
reg = _registry(tmp_path, _wake_task("act")["metadata"])
for root in ("task_drive", "artifact_store"):
result = reg.execute("write_file", {"root": root, "path": "notes.txt", "content": "kept\n"})
assert "BLOCKED" not in result, (root, result[:300])
assert "BLOCKED" not in reg.execute("read_file", {"path": "README.md"})
# --- the wake through the real lane --------------------------------------------
def test_the_lane_attaches_the_level_to_the_wake_contract(monkeypatch, tmp_path):
import queue
import threading
from ouroboros import agent as agent_module
from supervisor import workers
from tests.test_consciousness_wake_lane import _lane, _wait_for
_lane(monkeypatch, tmp_path, event_q=queue.Queue())
seen: list = []
done = threading.Event()
class Actor:
def handle_task(self, task):
seen.append(task)
done.set()
return []
monkeypatch.setattr(agent_module, "make_agent", lambda **kw: Actor())
receipt = workers.handle_wake_direct(1, "wake", {**WAKE_META, "consciousness_autonomy": "act"})
assert receipt["admitted"] is True
assert done.wait(10) and _wait_for(lambda: bool(seen))
task = seen[0]
assert task["task_contract"]["disabled_tools"] == list(ca.ACT_DISABLED)
assert task["metadata"]["runtime_mode_cap"] == "light"
# --- ISSUER: a wake speaks as a task -------------------------------------------
def test_routing_issuer_keeps_wake_relays_task_authored_and_explicit_owner_ingress(tmp_path):
from ouroboros.tools.control_routing import ISSUER_OWNER_TURN, ISSUER_TASK, _routing_issuer
wake = types.SimpleNamespace(task_id="wake-1", is_direct_chat=True, last_owner_delivery=None,
task_metadata=dict(_wake_task("act")["metadata"]))
assert _routing_issuer(wake) == {"kind": ISSUER_TASK, "task_id": "wake-1", "root_task_id": "wake-1"}
# An owner turn is the direct turn the owner door stamped; a bare direct context is not one.
owner = types.SimpleNamespace(task_id="turn-1", is_direct_chat=True, last_owner_delivery=None,
task_metadata={"origin_message_ref": {"chat_id": 1, "client_message_id": "cm-1"}})
assert _routing_issuer(owner) == {"kind": ISSUER_OWNER_TURN}
bare = types.SimpleNamespace(task_id="turn-2", is_direct_chat=True, last_owner_delivery=None, task_metadata={})
assert _routing_issuer(bare) == {"kind": ISSUER_TASK, "task_id": "turn-2", "root_task_id": "turn-2"}
# Draining real owner dialogue provides receipt identity, never authorship.
relaying = types.SimpleNamespace(task_id="c-root", is_direct_chat=False,
last_owner_delivery={"client_message_id": "cm-9", "text": "go"},
task_metadata={"initiator": "consciousness"})
assert _routing_issuer(relaying) == {"kind": ISSUER_TASK, "task_id": "c-root", "root_task_id": "c-root"}
# A client id is not the door's stamp: a wake (or a Presence event, whose client id is the
# provider's event id) keeps speaking as a task.
client_id_only = types.SimpleNamespace(task_id="c-root", is_direct_chat=True, last_owner_delivery=None,
task_metadata={"initiator": "consciousness", "client_message_id": "cm-2"})
assert _routing_issuer(client_id_only) == {"kind": ISSUER_TASK, "task_id": "c-root", "root_task_id": "c-root"}
def test_steer_from_a_wake_is_written_as_an_independent_task_message(tmp_path, monkeypatch):
from ouroboros.tools import control_routing
sent: list = []
monkeypatch.setattr(control_routing, "_send_task_message",
lambda ctx, issuer, target, msg, chat_id: sent.append((issuer, target, msg)) or "WRITTEN")
ctx = types.SimpleNamespace(
pending_events=[], event_queue=None, current_chat_id=1, drive_root=tmp_path,
task_id="wake-1", is_direct_chat=True, last_owner_delivery=None,
task_metadata=dict(_wake_task("act")["metadata"]),
)
assert control_routing._steer_task(ctx, task_id="r-1", message="please also check X") == "WRITTEN"
assert sent == [({"kind": "task", "task_id": "wake-1", "root_task_id": "wake-1"}, "r-1", "please also check X")]
assert ctx.pending_events == []
# --- origin inheritance: promote / followup / subagent -------------------------
@pytest.fixture
def _promote_root(tmp_path, monkeypatch):
"""The real promote admission path (tool -> supervisor handler -> worker_promotion)."""
import ouroboros.config as cfg
import supervisor.message_bus as mb
import supervisor.queue as queue_mod
from supervisor import workers
monkeypatch.setattr(cfg, "DATA_DIR", tmp_path)
monkeypatch.setattr(workers, "DRIVE_ROOT", tmp_path)
monkeypatch.setattr(queue_mod, "DRIVE_ROOT", str(tmp_path))
monkeypatch.setattr(queue_mod, "ACCEPTANCE_FENCES", {})
monkeypatch.setattr(mb, "get_bridge", lambda: types.SimpleNamespace(broadcast=lambda payload: None))
monkeypatch.setattr(workers, "_announce_created_project", lambda *a, **kw: None)
# Origin admission is under test, not the asynchronous Git/toolchain scan.
monkeypatch.setattr("ouroboros.workspace_admission.bounded_workspace_preflight",
lambda root: {"schema_version": 1, "workspace_root": str(root)})
(tmp_path / "logs").mkdir(parents=True, exist_ok=True)
return tmp_path
def test_promote_from_a_wake_mints_a_consciousness_root_through_the_real_admission(_promote_root):
from ouroboros.tools.control_routing import _promote_chat_to_task
from ouroboros.utils import append_jsonl
from supervisor.events_project_routing import _handle_promote_chat_to_task
tmp_path = _promote_root
enqueued: list = []
captured: dict = {}
supervisor = types.SimpleNamespace(
DRIVE_ROOT=tmp_path, RUNNING={}, PENDING=[], WORKERS={0: types.SimpleNamespace()},
bridge=types.SimpleNamespace(send_routing_ack=lambda *a, **k: None, broadcast=lambda *a, **k: None),
enqueue_task=lambda task: enqueued.append(task) or dict(task),
persist_queue_snapshot=lambda **_k: True, load_state=lambda: {"owner_chat_id": 1},
append_jsonl=append_jsonl,
)
ctx = types.SimpleNamespace(
pending_events=[], current_chat_id=1, drive_root=tmp_path, budget_drive_root=str(tmp_path),
task_id="wake-1", is_direct_chat=True, last_owner_delivery=None, project_id="",
task_metadata=dict(_wake_task("act")["metadata"]), task_contract={},
event_queue=types.SimpleNamespace(
put_nowait=lambda event: (captured.update(event), _handle_promote_chat_to_task(event, supervisor))),
)
out = _promote_chat_to_task(ctx, "audit the logs", workspace="none", predecessor_task_id="")
assert out.startswith("OK: task"), out
# The event carries the origin by value and nothing the wake asked for is stripped.
assert captured["initiator"] == "consciousness" and captured["consciousness_autonomy"] == "act"
assert captured["usage_category"] == "consciousness_task" and captured["workspace"] == "none"
assert "presence" not in captured
[root] = enqueued
assert root["actor_id"] == "consciousness" and root["delegation_role"] == "root"
assert root["metadata"]["initiator"] == "consciousness"
assert root["metadata"]["usage_category"] == "consciousness_task"
assert root["task_contract"]["disabled_tools"] == list(ca.ACT_DISABLED)
assert root["metadata"]["runtime_mode_cap"] == "light" and "_presence_origin" not in root
def test_route_to_project_from_a_wake_mints_a_consciousness_root_too(_promote_root):
"""P3d (live stand): the wake's route DID create a root in project redline-exodus, but
with empty metadata — no origin, no ledger category, no level, no withheld tools — because
only ``promote_chat_to_task`` stamped the origin onto its event. A route mints a root
through the SAME admission door, so it carries the same origin by value."""
from ouroboros.projects_registry import create_project
from ouroboros.tools.control_routing import _route_to_project
from ouroboros.utils import append_jsonl
from supervisor.events_project_routing import _handle_promote_chat_to_task
tmp_path = _promote_root
create_project(tmp_path, "racer", name="Racer")
enqueued: list = []
captured: dict = {}
supervisor = types.SimpleNamespace(
DRIVE_ROOT=tmp_path, RUNNING={}, PENDING=[], WORKERS={0: types.SimpleNamespace()},
bridge=types.SimpleNamespace(send_routing_ack=lambda *a, **k: None, broadcast=lambda *a, **k: None),
enqueue_task=lambda task: enqueued.append(task) or dict(task),
persist_queue_snapshot=lambda **_k: True, load_state=lambda: {"owner_chat_id": 1},
append_jsonl=append_jsonl,
)
ctx = types.SimpleNamespace(
pending_events=[], current_chat_id=1, drive_root=tmp_path, budget_drive_root=str(tmp_path),
task_id="wake-1", is_direct_chat=True, last_owner_delivery=None, project_id="",
task_metadata=dict(_wake_task("act")["metadata"]), task_contract={},
event_queue=types.SimpleNamespace(
put_nowait=lambda event: (captured.update(event), _handle_promote_chat_to_task(event, supervisor))),
)
out = _route_to_project(ctx, "racer", "audit the logs", predecessor_task_id="")
assert "Routed to project" in out, out
assert captured["initiator"] == "consciousness"
assert captured["usage_category"] == "consciousness_task"
assert captured["consciousness_autonomy"] == "act"
[root] = enqueued
assert root["actor_id"] == "consciousness" and root["project_id"] == "racer"
assert root["metadata"]["initiator"] == "consciousness"
assert root["metadata"]["usage_category"] == "consciousness_task"
assert root["metadata"]["runtime_mode_cap"] == "light"
assert root["task_contract"]["disabled_tools"] == list(ca.ACT_DISABLED)
def test_route_to_project_from_an_owner_turn_stays_unstamped(_promote_root):
"""The origin is inherited, never minted: an owner's own route keeps the plain root."""
from ouroboros.projects_registry import create_project
from ouroboros.tools.control_routing import _route_to_project
tmp_path = _promote_root
create_project(tmp_path, "racer", name="Racer")
ctx = types.SimpleNamespace(
pending_events=[], event_queue=None, current_chat_id=1, drive_root=tmp_path,
task_id="owner-turn", is_direct_chat=True, project_id="", task_contract={},
task_metadata={"client_message_id": "cm-1"},
)
_route_to_project(ctx, "racer", "audit the logs", predecessor_task_id="")
[evt] = ctx.pending_events
assert "initiator" not in evt and "usage_category" not in evt
def test_promoted_root_is_stamped_and_its_contract_derives_the_level(tmp_path, monkeypatch):
import supervisor.workers as workers
monkeypatch.setattr(workers, "DRIVE_ROOT", tmp_path)
enqueued: list = []
def enqueue(task):
enqueued.append(task)
return dict(task)
ctx = types.SimpleNamespace(enqueue_task=enqueue, persist_queue_snapshot=lambda **_k: True,
load_state=lambda: {"owner_chat_id": 1})
evt = {"type": "promote_chat_to_task", "task_id": "c0000001", "objective": "audit the logs",
"chat_id": 1, "workspace": "none", "initiator": "consciousness",
"usage_category": "consciousness_task", "consciousness_autonomy": "act"}
assert workers.promote_chat_to_task(evt, ctx)["status"] == "scheduled"
task = enqueued[0]
assert task["actor_id"] == "consciousness" and task["delegation_role"] == "root"
assert task["metadata"]["initiator"] == "consciousness"
assert task["metadata"]["usage_category"] == "consciousness_task"
assert task["metadata"]["consciousness_autonomy"] == "act"
assert task["task_contract"]["disabled_tools"] == list(ca.ACT_DISABLED)
assert task["metadata"]["runtime_mode_cap"] == "light"
assert task["source"] == "promote_chat_to_task" and "_presence_origin" not in task
def test_followup_template_inherits_the_origin_and_admission_derives_the_level(tmp_path, monkeypatch):
from supervisor import queue
from tests.test_schedule_followup import _ctx, _followup
ctx = _ctx(tmp_path)
ctx.task_metadata.update(_wake_task("act")["metadata"])
assert _followup(ctx).startswith("FOLLOWUP_SCHEDULED")
record = queue.list_scheduled_tasks(tmp_path / "data")["tasks"][0]
meta = record["task"]["metadata"]
assert meta["initiator"] == "consciousness" and meta["usage_category"] == "consciousness_task"
assert meta["consciousness_autonomy"] == "act" and "task_contract" not in record["task"]
monkeypatch.setattr(queue, "load_state", lambda: {"owner_chat_id": 1})
task = queue._task_from_schedule(record)
assert task["delegation_role"] == "root" and task["metadata"]["initiator"] == "consciousness"
assert task["task_contract"]["disabled_tools"] == list(ca.ACT_DISABLED)
assert task["metadata"]["runtime_mode_cap"] == "light"
def test_owner_followup_template_carries_no_origin(tmp_path):
from supervisor import queue
from tests.test_schedule_followup import _ctx, _followup
assert _followup(_ctx(tmp_path)).startswith("FOLLOWUP_SCHEDULED")
meta = queue.list_scheduled_tasks(tmp_path / "data")["tasks"][0]["task"]["metadata"]
assert "initiator" not in meta and "consciousness_autonomy" not in meta
def test_subagent_payload_lands_the_origin_on_the_child_metadata():
from supervisor.task_dispatch import build_scheduled_task_payload
fields = {"tid": "kid1", "chat_id": 1, "text": "x", "desc": "x", "role": "researcher",
"root_task_id": "wake-1", "delegation_role": "subagent", "actor_id": "subagent:researcher",
"origin_metadata": ca.consciousness_origin_metadata(_wake_task("act")["metadata"])}
task = build_scheduled_task_payload(fields)
assert task["metadata"]["initiator"] == "consciousness"
assert task["metadata"]["usage_category"] == "consciousness_task"
assert task["metadata"]["consciousness_autonomy"] == "act"
plain = build_scheduled_task_payload({**fields, "origin_metadata": {}})
assert "initiator" not in plain["metadata"]
def test_schedule_subagent_event_names_the_origin():
"""The tool stamps ``origin_metadata`` on the schedule event beside the envelope."""
source = pathlib.Path("ouroboros/tools/control_scheduling.py").read_text(encoding="utf-8")
assert '"origin_metadata": consciousness_origin_metadata(metadata),' in source
handler = pathlib.Path("supervisor/events_schedule_task.py").read_text(encoding="utf-8")
assert '"origin_metadata": evt.get("origin_metadata"),' in handler
# --- evolution: eligibility, sticky owner stop, campaign provenance ------------
def test_post_task_promotion_is_refused_when_toggle_evolution_is_withheld():
from ouroboros.post_task_evolution import _eligible
assert _eligible({"type": "task"}) is True
assert _eligible({"type": "task", "task_contract": {"disabled_tools": ["toggle_evolution"]}}) is False
assert _eligible({"type": "task", "metadata": {"disabled_tools": ["toggle_evolution"]}}) is False
from ouroboros.contracts.task_contract import attach_task_contract
assert _eligible(attach_task_contract(_wake_task("act"))) is False
assert _eligible(attach_task_contract(_wake_task("full"))) is True
def test_globalized_promotion_view_keeps_the_contract(tmp_path, monkeypatch):
from ouroboros import agent_task_pipeline as pipeline
from ouroboros.contracts.task_contract import attach_task_contract
seen: list = []
monkeypatch.setattr(pipeline, "_update_improvement_backlog", lambda env, entry: None)
monkeypatch.setattr("ouroboros.post_task_evolution.maybe_promote",
lambda env, task, entry, llm: seen.append(task))
task = attach_task_contract({**_wake_task("act"), "project_id": "lab"})
pipeline._run_global_backlog_promotion_only(
types.SimpleNamespace(drive_root=tmp_path), task,
{"backlog_candidates": [{"summary": "tidy the logs"}]}, None,
)
assert seen and seen[0]["task_contract"]["disabled_tools"] == list(ca.ACT_DISABLED)
def test_request_file_and_pending_apply_carry_the_origin(tmp_path, monkeypatch):
from ouroboros import post_task_evolution as pte
task = _wake_task("full")
pte._write_request(tmp_path, {"objective": "improve X", "requires_plan_review": False}, task)
req = json.loads((tmp_path / pte._REQUEST_REL).read_text(encoding="utf-8"))
assert req["initiator"] == "consciousness" and req["consciousness_autonomy"] == "full"
assert req["usage_category"] == "consciousness_task"
calls: list = []
monkeypatch.setattr("ouroboros.config.get_post_task_evolution_enabled", lambda: True)
monkeypatch.setattr("supervisor.evolution_lifecycle.evolution_block_reason", lambda: "")
monkeypatch.setattr("supervisor.evolution_lifecycle.start_evolution_campaign",
lambda objective, source="", **kw: calls.append((objective, source, kw)) or {"id": "c1"})
monkeypatch.setattr("supervisor.state.load_state", lambda: {"owner_chat_id": 7})
def _update_state(mutator):
live: dict = {}
mutator(live)
return live
monkeypatch.setattr("supervisor.state.update_state", _update_state)
monkeypatch.setattr("ouroboros.config.get_post_task_evolution_budget_usd", lambda: 0.0)
assert pte.apply_pending_request(tmp_path) is True
assert calls == [("improve X", "post_task", {"origin": {
"initiator": "consciousness", "usage_category": "consciousness_task", "consciousness_autonomy": "full"}})]
def _toggle_ctx(state, sent):
return types.SimpleNamespace(load_state=state.load_state,
send_with_budget=lambda cid, text, **kw: sent.append(text))
def test_agent_tool_enable_is_refused_while_the_owner_stop_stands(tmp_path, monkeypatch):
"""В12: /evolve off is sticky against toggle_evolution — the typed refusal, no campaign."""
import supervisor.state as state
from supervisor import events as events_mod
from supervisor import evolution_lifecycle as el
state.init(tmp_path)
state.update_state(lambda live: live.update(owner_chat_id=7, evolution_owner_stopped=True))
started: list = []
monkeypatch.setattr(el, "evolution_block_reason", lambda: "")
monkeypatch.setattr(el, "start_evolution_campaign",
lambda objective, source="", **kw: started.append(source) or {"status": "active"})
sent: list = []
events_mod._handle_toggle_evolution({"enabled": True, "objective": "x"}, _toggle_ctx(state, sent))
assert started == []
assert bool(state.load_state().get("evolution_owner_stopped")) is True
assert not state.load_state().get("evolution_mode_enabled")
assert sent and "stayed OFF" in sent[0] and "sticky" in sent[0]
def test_agent_tool_enable_without_an_owner_stop_starts_a_campaign_with_the_origin(tmp_path, monkeypatch):
import supervisor.state as state
from supervisor import events as events_mod
from supervisor import evolution_lifecycle as el
state.init(tmp_path)
state.update_state(lambda live: live.update(owner_chat_id=7, evolution_owner_stopped=False))
started: list = []
monkeypatch.setattr(el, "evolution_block_reason", lambda: "")
monkeypatch.setattr(el, "start_evolution_campaign",
lambda objective, source="", **kw: started.append((source, kw)) or {"status": "active"})
sent: list = []
evt = {"enabled": True, "objective": "x", "initiator": "consciousness",
"usage_category": "consciousness_task", "consciousness_autonomy": "full"}
events_mod._handle_toggle_evolution(evt, _toggle_ctx(state, sent))
assert started == [("agent_tool", {"origin": {
"initiator": "consciousness", "usage_category": "consciousness_task", "consciousness_autonomy": "full"}})]
live = state.load_state()
assert live["evolution_mode_enabled"] is True and live["evolution_owner_stopped"] is False
def test_a_stop_the_agent_placed_itself_stays_undoable_by_the_agent(tmp_path, monkeypatch):
"""В12 binds the OWNER's stop; the agent's own toggle_evolution(False) is not an owner
stop — it still blocks the post-task re-arm (the flag), but the agent may re-enable."""
import supervisor.state as state
from supervisor import events as events_mod
from supervisor import evolution_lifecycle as el
state.init(tmp_path)
# What the agent's own toggle_evolution(False) leaves behind (the disable path itself needs
# the live supervisor; its state write is pinned in test_evolution_stop_and_cost).
state.update_state(lambda live: live.update(owner_chat_id=7, evolution_owner_stopped=True,
evolution_stop_source="agent_tool"))
started: list = []
monkeypatch.setattr(el, "evolution_block_reason", lambda: "")
monkeypatch.setattr(el, "start_evolution_campaign",
lambda objective, source="", **kw: started.append(source) or {"status": "active"})
sent: list = []
events_mod._handle_toggle_evolution({"enabled": True, "objective": "again"}, _toggle_ctx(state, sent))
live = state.load_state()
assert started == ["agent_tool"] and live["evolution_owner_stopped"] is False
assert "evolution_stop_source" not in live and not [t for t in sent if "sticky" in t]
# The owner's stop (/evolve off, panic, an owner-sourced toggle: no agent_tool source) stays sticky.
state.update_state(lambda live: live.update(evolution_owner_stopped=True, evolution_stop_source="owner_chat"))
events_mod._handle_toggle_evolution({"enabled": True, "objective": "x"}, _toggle_ctx(state, sent))
assert started == ["agent_tool"] and sent and "sticky" in sent[-1]
state.update_state(lambda live: (live.update(evolution_owner_stopped=True), live.pop("evolution_stop_source", None)))
events_mod._handle_toggle_evolution({"enabled": True, "objective": "y"}, _toggle_ctx(state, sent))
assert started == ["agent_tool"] and len([t for t in sent if "sticky" in t]) == 2
def test_observe_does_without_the_work_starting_review_verb():
"""`request_deep_self_review` enqueues a ROOT: Observe starts nothing (В10')."""
assert "request_deep_self_review" in ca.OBSERVE_DISABLED and "request_deep_self_review" not in ca.ACT_DISABLED
# The GitHub write verbs change the world beyond the repository (PLAN §5.4: Observe keeps the reads only).
for verb in ("create_github_issue", "comment_on_issue", "comment_on_pr", "close_github_issue"):
assert verb in ca.OBSERVE_DISABLED and verb not in ca.ACT_DISABLED, verb
for verb in ("list_github_prs", "get_github_pr", "list_github_issues", "get_github_issue"):
assert verb not in ca.OBSERVE_DISABLED, verb
# The two built-in execution verbs (astra scope round 5): a skill's script, a push + CI run.
for verb in ("skill_exec", "run_ci_tests"):
assert verb in ca.OBSERVE_DISABLED and verb not in ca.ACT_DISABLED, verb
def test_deep_review_request_carries_the_origin_to_the_one_door(tmp_path, monkeypatch):
"""The tool's event names the caller's origin, the handler hands it to the queue, and the
queued root carries it — so the admission door and the ledger see the tree (В11/В18)."""
from ouroboros.tools.control_runtime import _request_deep_self_review
from supervisor import queue, state
from supervisor.events_runtime_controls import _handle_deep_self_review_request
monkeypatch.setattr("ouroboros.deep_self_review.deep_review_route", lambda: ("", "reviewer-x"))
ctx = types.SimpleNamespace(pending_events=[], task_metadata=dict(_wake_task("act")["metadata"]))
assert _request_deep_self_review(ctx, "look again").startswith("Deep self-review requested")
evt = ctx.pending_events[0]
assert evt["type"] == "deep_self_review_request" and evt["initiator"] == "consciousness"
owner = types.SimpleNamespace(pending_events=[], task_metadata={"client_message_id": "cm"})
_request_deep_self_review(owner, "look")
assert "initiator" not in owner.pending_events[0]
state.init(tmp_path)
queue.init(tmp_path)
pending: list = []
queue.init_queue_refs(pending, {}, {"value": 0})
state.update_state(lambda live: live.update(owner_chat_id=1))
monkeypatch.setattr(state, "TOTAL_BUDGET_LIMIT", 0.0)
monkeypatch.setattr(queue, "send_with_budget", lambda *a, **k: None)
monkeypatch.setattr(queue, "persist_queue_snapshot", lambda reason="": None)
monkeypatch.setattr("supervisor.workers._worker_pool_execution_state",
lambda: {"available": True, "disabled_reason": ""})
monkeypatch.setattr("ouroboros.consciousness_allowance.allowance_window",
lambda root, now=None: {"status": "available", "limit_usd": 20.0, "accounted_usd": 0.0,
"remaining_usd": 20.0, "unknown_unmetered": 0, "resets_at": ""})
handed: list = []
sup = types.SimpleNamespace(queue_deep_self_review_task=lambda **kw: handed.append(kw))
_handle_deep_self_review_request(evt, sup)
assert handed[0]["origin"] == {"initiator": "consciousness", "usage_category": "consciousness_task",
"consciousness_autonomy": "act"}
assert queue.queue_deep_self_review_task("look again", model="reviewer-x", origin=handed[0]["origin"])
assert pending[0]["type"] == "deep_self_review" and pending[0]["metadata"]["initiator"] == "consciousness"
assert pending[0]["metadata"]["usage_category"] == "consciousness_task"
# The owner's own request stays unmarked.
assert queue.queue_deep_self_review_task("mine", model="reviewer-x", force=True)
assert "metadata" not in pending[1] or "initiator" not in pending[1]["metadata"]
def test_the_allowance_is_read_before_the_queue_lock(tmp_path, monkeypatch):
"""The ledger read takes the cross-process ledger lock; it must not run under the queue lock,
or a contended ledger stalls every queue reader."""
from supervisor import queue, state
state.init(tmp_path)
queue.init(tmp_path)
pending: list = []
queue.init_queue_refs(pending, {}, {"value": 0})
monkeypatch.setattr(state, "TOTAL_BUDGET_LIMIT", 0.0)
monkeypatch.setattr(queue, "persist_queue_snapshot", lambda reason="": None)
seen: list = []
def _window(root, now=None):
seen.append(queue._queue_lock._is_owned())
return {"status": "available", "limit_usd": 20.0, "accounted_usd": 0.0, "remaining_usd": 20.0,
"unknown_unmetered": 0, "resets_at": ""}
monkeypatch.setattr("ouroboros.consciousness_allowance.allowance_window", _window)
task = {"id": "root-1", "type": "task", "chat_id": 1, "text": "x", "metadata": dict(_wake_task("act")["metadata"])}
assert not queue.enqueue_task(task).get("_admission_blocked")
assert seen == [False]
def test_toggle_tool_stamps_the_turn_origin_on_its_event(monkeypatch):
from ouroboros.tools.control_runtime import _toggle_evolution
monkeypatch.setattr("supervisor.evolution_lifecycle.evolution_block_reason", lambda: "")
ctx = types.SimpleNamespace(pending_events=[], task_metadata=dict(_wake_task("full")["metadata"]))
assert _toggle_evolution(ctx, True, "improve X").startswith("OK")
evt = ctx.pending_events[0]
assert evt["type"] == "toggle_evolution" and evt["initiator"] == "consciousness"
assert evt["consciousness_autonomy"] == "full"
owner = types.SimpleNamespace(pending_events=[], task_metadata={"client_message_id": "cm"})
_toggle_evolution(owner, True, "improve X")
assert "initiator" not in owner.pending_events[0]
def test_campaign_keeps_the_origin_and_its_cycle_tasks_inherit_it(tmp_path, monkeypatch):
from supervisor import evolution_lifecycle, queue, state
state.init(tmp_path)
queue.init(tmp_path)
pending: list = []
queue.init_queue_refs(pending, {}, {"value": 0})
monkeypatch.setattr(state, "TOTAL_BUDGET_LIMIT", 0.0)
origin = {"initiator": "consciousness", "usage_category": "consciousness_task", "consciousness_autonomy": "full"}
campaign = evolution_lifecycle.start_evolution_campaign("Improve", source="agent_tool", origin=origin)
assert campaign["initiator"] == "consciousness" and campaign["consciousness_autonomy"] == "full"
# An agent-sourced resume keeps the recorded origin; the owner's explicit resume of a PAUSED
# campaign ADOPTS it (see test_the_owners_start_adopts_a_paused_consciousness_campaign).
campaign["status"] = "paused"
assert evolution_lifecycle._write_evolution_campaign(campaign) is True
resumed = evolution_lifecycle.start_evolution_campaign("", source="agent_tool")
assert resumed["initiator"] == "consciousness"
state.update_state(lambda live: live.update(owner_chat_id=1, evolution_mode_enabled=True,
evolution_owner_stopped=False))
monkeypatch.setattr(evolution_lifecycle, "evolution_block_reason", lambda: "")
monkeypatch.setattr(queue, "send_with_budget", lambda *a, **k: None)
monkeypatch.setattr(queue, "persist_queue_snapshot", lambda reason="": None)
monkeypatch.setattr("ouroboros.consciousness_allowance.allowance_window",
lambda root, now=None: {"status": "available", "limit_usd": 20.0, "accounted_usd": 0.0,
"remaining_usd": 20.0, "unknown_unmetered": 0, "resets_at": ""})
queue.enqueue_evolution_task_if_needed()
assert len(pending) == 1
task = pending[0]
assert task["type"] == "evolution" and task["metadata"]["initiator"] == "consciousness"
assert task["metadata"]["usage_category"] == "consciousness_task"
assert task["task_contract"]["disabled_tools"] == [] and task["metadata"]["runtime_mode_cap"] == ""
assert state.load_state()["evolution_cycle"] == 1
# The ONE door refuses the next cycle (the tree's allowance is spent): the campaign is
# paused ONCE with an owner line — no cycle bump, no transaction minted on every pass.
pending.clear()
sent: list = []
monkeypatch.setattr(queue, "send_with_budget", lambda cid, text, **kw: sent.append(text))
monkeypatch.setattr("ouroboros.consciousness_allowance.allowance_window",
lambda root, now=None: {"status": "exhausted", "limit_usd": 20.0, "accounted_usd": 21.0,
"remaining_usd": 0.0, "unknown_unmetered": 0, "resets_at": "2027-01-01T00:00:00+00:00"})
queue.enqueue_evolution_task_if_needed()
queue.enqueue_evolution_task_if_needed()
assert pending == [] and state.load_state()["evolution_cycle"] == 1
paused = evolution_lifecycle._read_evolution_campaign()
assert paused["status"] == "paused" and paused["pause_reason"] == "admission_refused:consciousness_allowance_exhausted"
assert len(sent) == 1 and "Evolution paused" in sent[0] and "consciousness_allowance_exhausted" in sent[0]
assert not state.load_state().get("evolution_mode_enabled")
def test_a_transient_refusal_never_pauses_the_campaign(tmp_path, monkeypatch):
"""Only a consciousness refusal (allowance, concurrency) pauses; anything else clears itself
and the next pass retries — without recording a cycle (opus round 3)."""
from supervisor import evolution_lifecycle, queue, state
state.init(tmp_path)
queue.init(tmp_path)
pending: list = []
queue.init_queue_refs(pending, {}, {"value": 0})
monkeypatch.setattr(state, "TOTAL_BUDGET_LIMIT", 0.0)
evolution_lifecycle.start_evolution_campaign("Improve", source="owner_chat")
state.update_state(lambda live: live.update(owner_chat_id=1, evolution_mode_enabled=True,
evolution_owner_stopped=False))
monkeypatch.setattr(evolution_lifecycle, "evolution_block_reason", lambda: "")
sent: list = []
monkeypatch.setattr(queue, "send_with_budget", lambda cid, text, **kw: sent.append(text))
monkeypatch.setattr(queue, "persist_queue_snapshot", lambda reason="": None)
monkeypatch.setattr(queue, "enqueue_task", lambda task, **kw: {**task, "_admission_blocked": "duplicate_task_id"})
queue.enqueue_evolution_task_if_needed()
assert pending == [] and sent == []
assert evolution_lifecycle._read_evolution_campaign()["status"] == "active"
live = state.load_state()
assert live.get("evolution_mode_enabled") is True and not live.get("evolution_cycle")
def test_the_owners_start_adopts_a_paused_consciousness_campaign(tmp_path):
"""BIBLE P0: the owner's explicit /evolve start on a campaign the consciousness allowance paused
makes it the owner's work — otherwise the door refuses and re-pauses it until the window frees."""
from supervisor import evolution_lifecycle, queue, state
state.init(tmp_path)
queue.init(tmp_path)
origin = {"initiator": "consciousness", "usage_category": "consciousness_task", "consciousness_autonomy": "full"}
campaign = evolution_lifecycle.start_evolution_campaign("Improve", source="agent_tool", origin=origin)
campaign["status"], campaign["pause_reason"] = "paused", "admission_refused:consciousness_allowance_exhausted"
assert evolution_lifecycle._write_evolution_campaign(campaign) is True
adopted = evolution_lifecycle.start_evolution_campaign("", source="owner_chat")
assert adopted["status"] == "active" and adopted["adopted_by_owner_at"] and "pause_reason" not in adopted
assert not any(key in adopted for key in origin)
assert ca.consciousness_origin_metadata(adopted) == {}
# The function's own default source is the owner too (grok round 4).
campaign = evolution_lifecycle.start_evolution_campaign("Again", source="agent_tool", origin=origin)
campaign["status"] = "paused"
assert evolution_lifecycle._write_evolution_campaign(campaign) is True
assert "initiator" not in evolution_lifecycle.start_evolution_campaign("")
def test_owner_campaign_carries_no_origin(tmp_path):
from supervisor import evolution_lifecycle, queue, state
state.init(tmp_path)
queue.init(tmp_path)
campaign = evolution_lifecycle.start_evolution_campaign("Improve", source="owner_chat")
assert "initiator" not in campaign
assert ca.consciousness_origin_metadata(campaign) == {}
# --- what a wake may address: the host routing manifest (P3c) -------------------
def _wake_routing_ctx(tmp_path, **metadata):
"""A wake's tool context: the P3 envelope plus whatever Main-lane routing facts the
alarm clock merged into it (``main_lane_routing_metadata``)."""
return types.SimpleNamespace(
pending_events=[], event_queue=None, current_chat_id=1, drive_root=tmp_path,
budget_drive_root=str(tmp_path), task_id="wake-1", is_direct_chat=True,
last_owner_delivery=None, project_id="", task_contract={},
task_metadata={**_wake_task("act")["metadata"], **metadata},
)
def _addressable_result(tmp_path, task_id="racer-old"):
"""One settled root on disk, exactly as the Main manifest would preview it."""
from ouroboros.server_routing_context import _task_result_ground_truth
row = {"task_id": task_id, "status": "completed", "project_id": "racer",
"title": "Racer prototype", "objective": "Build the racer prototype",
"task_contract": {"objective": "Build the racer prototype", "context": "exact old context"}}
results = tmp_path / "task_results"
results.mkdir(parents=True, exist_ok=True)
(results / f"{task_id}.json").write_text(json.dumps({"_schema_version": 1, **row}), encoding="utf-8")
return _task_result_ground_truth(row)
def test_a_wake_continues_a_result_its_routing_manifest_makes_addressable(tmp_path):
"""The first live wake chose a predecessor and got AUTHORITY_SOURCE_UNAVAILABLE twice,
so the work it had decided on never started: its metadata carried no routing manifest
(P3c). With the Main lane's own facts the named id is addressable, on both verbs."""
from ouroboros.projects_registry import create_project
from ouroboros.tools.control_routing import _promote_chat_to_task, _route_to_project
create_project(tmp_path, "racer", name="Racer")
preview = _addressable_result(tmp_path)
facts = {"main_routing_manifest": {"final_results": [preview]}}
routed = _wake_routing_ctx(tmp_path, **facts)
out = _route_to_project(routed, "racer", "Continue the racer", predecessor_task_id="racer-old")
assert out.startswith("⚠️ ROUTE_UNCONFIRMED"), out
[route_evt] = routed.pending_events
assert route_evt["predecessor_task_id"] == "racer-old"
assert route_evt["predecessor_authority_source"] == preview["authority_source"]
promoted = _wake_routing_ctx(tmp_path, **facts)
_promote_chat_to_task(promoted, "Finish the racer", workspace="none", predecessor_task_id="racer-old")
[promote_evt] = promoted.pending_events
assert promote_evt["predecessor_task_id"] == "racer-old"
assert promote_evt["predecessor_authority_source"] == preview["authority_source"]
# The manifest never dilutes the wake's own origin.
assert promote_evt["initiator"] == "consciousness"
def test_a_wake_starts_fresh_work_with_no_predecessor_and_needs_no_manifest(tmp_path):
from ouroboros.projects_registry import create_project
from ouroboros.tools.control_routing import _promote_chat_to_task, _route_to_project
create_project(tmp_path, "racer", name="Racer")
routed = _wake_routing_ctx(tmp_path)
assert _route_to_project(routed, "racer", "Start a separate experiment",
predecessor_task_id="").startswith("⚠️ ROUTE_UNCONFIRMED")
assert "predecessor_authority_source" not in routed.pending_events[0]
promoted = _wake_routing_ctx(tmp_path)
_promote_chat_to_task(promoted, "audit the logs", workspace="none", predecessor_task_id="")
assert "predecessor_task_id" not in promoted.pending_events[0]
def test_a_wake_without_the_manifest_continues_a_settled_root_and_still_refuses_a_live_one(tmp_path):
"""The door judges the root, not the facts a wake was handed: with no manifest at all
a wake continues a settled root on both verbs (the pointer is rebuilt from the durable
result and equals the one the manifest would have shown), while a live root keeps its
typed refusal toward steer_task and emits nothing."""
from ouroboros.projects_registry import create_project
from ouroboros.tools.control_routing import _promote_chat_to_task, _route_to_project
create_project(tmp_path, "racer", name="Racer")
preview = _addressable_result(tmp_path)
routed = _wake_routing_ctx(tmp_path)
out = _route_to_project(routed, "racer", "Continue the racer", predecessor_task_id="racer-old")
assert out.startswith("⚠️ ROUTE_UNCONFIRMED"), out
[route_evt] = routed.pending_events
assert route_evt["predecessor_authority_source"] == preview["authority_source"]
promoted = _wake_routing_ctx(tmp_path)
_promote_chat_to_task(promoted, "Finish the racer", workspace="none", predecessor_task_id="racer-old")
[promote_evt] = promoted.pending_events
assert promote_evt["predecessor_task_id"] == "racer-old"
assert promote_evt["initiator"] == "consciousness"
(tmp_path / "task_results" / "racer-live.json").write_text(json.dumps({
"_schema_version": 1, "task_id": "racer-live", "status": "running", "project_id": "racer",
}), encoding="utf-8")
refused = _wake_routing_ctx(tmp_path)
out = _route_to_project(refused, "racer", "Continue the racer", predecessor_task_id="racer-live")
assert out.startswith("⚠️ AUTHORITY_SOURCE_UNAVAILABLE (route_to_project)") and "steer_task" in out
assert refused.pending_events == []