mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-03 04:07:04 +00:00
Let a refused or lost promote stop reading as pending, and pin what the mutation pass found loose
The pre-push panel's third reviewer ran 56 mutations and drove the real
supervisor handler. One defect and several unpinned branches:
- A refusal that writes no result of its own (rejected attachments, and the
duplicate-id exit) left this promote's emitted stub on disk, so the
reconciliation read answered 'admission pending, do not promote the same
work a second time' for ever and the owner's work never started. Both exits
now replace the stub of their OWN routing token; with no stub on disk they
still write nothing. This corrects the claim in 8d57aabe3 that every refused
promote already overwrote the stub.
- The pending sentence states only what the row proves (emitted, no receipt,
the time now) and hands the decision back: an event can be lost with a
restarted supervisor, so a standing ban was a lie waiting to happen.
- The admission gates use a strict form, is_own_admission_stub: no token is
no claim, so a tokenless admission meets any stub as a row that owns the id,
and _promote_duplicate_reason requires its token. This closes the disclosed
tokenless residual structurally.
- An emitted stub is neither the project's last result nor a steerable
predecessor: the lookup skips it like a child, and the door says what it is.
- prompts/SYSTEM.md, the same one sentence: a read-only subagent reads
deliverables, every subagent its parent's and root's task files (the earlier
'never a sibling's' is false on a single-drive geometry).
- The light-mode refusal says 'runtime control data', since it lists the task
drive under the writable roots in the same text.
New pins, each re-run against the reviewer's surviving mutation and now red
without its line: the stub's token and status conditions, the token passed
by the promote handler, the retry window of the compaction floor, the
read-only gate of the lineage redirect, the project filter and omission count
of a room's live roots, the secret-name filter of a Deliverables listing, and
the host-issued authority source of a listed row.
This commit is contained in:
parent
a017123653
commit
3837e384fd
15 changed files with 283 additions and 23 deletions
|
|
@ -17,6 +17,13 @@ from typing import Any, Dict
|
|||
PROMOTE_CONFIRM_POLL_SEC = 0.05
|
||||
|
||||
|
||||
def is_own_admission_stub(result: Any, routing_token: str) -> bool:
|
||||
"""The admission gates' form: a stub is read around ONLY by the token that wrote
|
||||
it. No token is no claim, so a tokenless admission meets any stub as a row that
|
||||
owns the id (``is_emitted_admission_stub`` without a token is for readers)."""
|
||||
token = str(routing_token or "").strip()
|
||||
return bool(token) and is_emitted_admission_stub(result, token)
|
||||
|
||||
def _confirm_wait_sec(timeout_sec: float | None) -> float:
|
||||
"""The one bound of both confirmation waits (``runtime_limits``), read at the
|
||||
wait itself so this routing leaf keeps no import-time edge into the limits."""
|
||||
|
|
|
|||
|
|
@ -270,6 +270,14 @@ def _project_routing_manifest(ctx: Any, project_id: str) -> Dict[str, Any]:
|
|||
}
|
||||
|
||||
|
||||
def _not_a_root_result(row: Dict[str, Any]) -> bool:
|
||||
"""A row that is never "the project's last result": a child's result, or a
|
||||
promote's emitted stub (an admission still pending, no result at all)."""
|
||||
from ouroboros.routing_wait import is_emitted_admission_stub
|
||||
|
||||
return _is_child_result(row) or is_emitted_admission_stub(row)
|
||||
|
||||
|
||||
def _latest_project_task_result(ctx: Any, project_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Newest ROOT task result bound to ``project_id`` (a child's is never the room's
|
||||
continuation: the promote door refuses it, ``_is_child_result``) WITHOUT replaying the whole
|
||||
|
|
@ -309,7 +317,7 @@ def _latest_project_task_result(ctx: Any, project_id: str) -> Optional[Dict[str,
|
|||
if pointer:
|
||||
pointed = load_task_result(ctx.DRIVE_ROOT, pointer)
|
||||
if isinstance(pointed, dict) and str(pointed.get("project_id") or "") == project_id:
|
||||
if not _is_child_result(pointed):
|
||||
if not _not_a_root_result(pointed):
|
||||
return pointed
|
||||
pointer = "" # a child-stamped pointer is provably wrong, not in flight: heal it
|
||||
log.debug(
|
||||
|
|
@ -348,7 +356,7 @@ def _latest_project_task_result(ctx: Any, project_id: str) -> Optional[Dict[str,
|
|||
if candidate is None:
|
||||
uncertain = True
|
||||
continue
|
||||
if str(candidate.get("project_id") or "") != project_id or _is_child_result(candidate):
|
||||
if str(candidate.get("project_id") or "") != project_id or _not_a_root_result(candidate):
|
||||
continue
|
||||
row = candidate
|
||||
# The match's whole equal-mtime group is read to its end — across the
|
||||
|
|
@ -360,7 +368,7 @@ def _latest_project_task_result(ctx: Any, project_id: str) -> Optional[Dict[str,
|
|||
other = read_json_dict(tied)
|
||||
if other is None:
|
||||
uncertain = True
|
||||
elif (str(other.get("project_id") or "") == project_id and not _is_child_result(other)
|
||||
elif (str(other.get("project_id") or "") == project_id and not _not_a_root_result(other)
|
||||
and _order(other) > _order(row)):
|
||||
row = other
|
||||
break
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ def _predecessor_door_refusal(
|
|||
project to compare against, and an absent project is not a match: there the
|
||||
host's own list still decides.
|
||||
"""
|
||||
from ouroboros.routing_wait import is_emitted_admission_stub
|
||||
from ouroboros.server_routing_context import _is_child_result
|
||||
from ouroboros.task_status import SETTLED_STATUSES
|
||||
|
||||
|
|
@ -131,6 +132,9 @@ def _predecessor_door_refusal(
|
|||
"belongs to - a child's work is reachable through its root"
|
||||
)
|
||||
status = str(result.get("status") or "")
|
||||
if is_emitted_admission_stub(result):
|
||||
return ("the selected predecessor is a promote whose admission is still pending, not a "
|
||||
"result; read get_task_result on it, and name a finished root instead")
|
||||
if status not in SETTLED_STATUSES:
|
||||
return (
|
||||
f"the selected predecessor is still live (status {status or 'unknown'}); "
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from ouroboros.task_status import (
|
|||
wait_for_effective_tasks,
|
||||
)
|
||||
from ouroboros.tools.registry import ToolContext
|
||||
from ouroboros.utils import truncate_review_artifact
|
||||
from ouroboros.utils import truncate_review_artifact, utc_now_iso
|
||||
from ouroboros.tools.tool_result import ToolResult, _publish_tool_result
|
||||
|
||||
|
||||
|
|
@ -208,10 +208,11 @@ def _get_task_result(
|
|||
return _publish_tool_result(ctx, ToolResult(
|
||||
status="unavailable", code="LEGACY_UNAVAILABLE",
|
||||
text=(
|
||||
f"Task {task_id}: admission pending since {since} - the promote was emitted and "
|
||||
"the supervisor has not confirmed or refused it yet. This id is durably reserved: "
|
||||
f"call get_task_result({task_id}) again to read the outcome, and do not promote "
|
||||
"the same work a second time."
|
||||
f"Task {task_id}: admission pending since {since} (now {utc_now_iso()}) - the promote "
|
||||
"was emitted and this row carries no supervisor receipt yet, neither scheduled nor "
|
||||
f"refused. Read get_task_result({task_id}) again before promoting the same work: the "
|
||||
"supervisor answers within seconds of draining its queue. If the row is still "
|
||||
"pending minutes later, the event did not land and a new promote is the way forward."
|
||||
),
|
||||
))
|
||||
if bool(include_authority) or bool(include_work_order_source) or bool(include_completion_source):
|
||||
|
|
|
|||
|
|
@ -677,7 +677,7 @@ def _direct_shell_write_block(self, raw_cmd: Any, work_dir: pathlib.Path, runtim
|
|||
writable = ", ".join(dict.fromkeys(
|
||||
f"{root}={pathlib.Path(base).resolve(strict=False)}" for root, base, _source, _skill in roots
|
||||
if not (light_internal and pathlib.Path(base).resolve(strict=False) == system_repo))) or "(none)"
|
||||
reason = ("runtime_mode=light keeps the Ouroboros repository and runtime data read-only"
|
||||
reason = ("runtime_mode=light keeps the Ouroboros repository and runtime control data read-only"
|
||||
if light_internal else "explicit write target is outside every root this task may write")
|
||||
return ToolResult(
|
||||
status="blocked", code="LIGHT_MODE_BLOCKED" if light_internal else "WORKSPACE_BLOCKED",
|
||||
|
|
|
|||
|
|
@ -164,8 +164,8 @@ canonical deliverables, `skill_payload` for reviewed skill payloads, and
|
|||
`user_files` for user-visible files under the owner's home (a bare filename
|
||||
lands in the visible Deliverables folder, not the home root).
|
||||
`subagent_projects` and `deliverables` are read-only (never written or a
|
||||
shell cwd); a subagent reads its lineage's task files, never a sibling's, and
|
||||
a read-only one also reads `deliverables`.
|
||||
shell cwd); a read-only subagent reads `deliverables`, every subagent its
|
||||
parent's and root's task files.
|
||||
|
||||
My cognitive memory has first-class tools — `update_identity`,
|
||||
`update_scratchpad`, `knowledge_write` — and I never reach for
|
||||
|
|
|
|||
|
|
@ -256,6 +256,20 @@ def _rollback_promoted_pending(
|
|||
return removed
|
||||
|
||||
|
||||
def _own_emitted_stub(ctx: Any, task_id: str, routing_token: str) -> bool:
|
||||
"""Whether the row on disk is THIS promote's emitted pre-receipt (#1160). A
|
||||
refusal that writes no result of its own must still replace it, or the
|
||||
reconciliation read answers "admission pending" for ever."""
|
||||
try:
|
||||
from ouroboros.routing_wait import is_own_admission_stub
|
||||
from ouroboros.task_results import load_task_result
|
||||
|
||||
return is_own_admission_stub(load_task_result(ctx.DRIVE_ROOT, task_id), routing_token)
|
||||
except Exception:
|
||||
log.warning("promote: emitted-stub lookup failed for %s", task_id, exc_info=True)
|
||||
return False
|
||||
|
||||
|
||||
def _persist_promote_rejection(
|
||||
ctx: Any,
|
||||
evt: Dict[str, Any],
|
||||
|
|
@ -407,7 +421,7 @@ def _promote_chat_to_task_outcome(evt: Dict[str, Any], ctx: Any) -> Dict[str, An
|
|||
"task_id": task_id,
|
||||
"reservation_owned": False,
|
||||
}
|
||||
if blocked["reason"] != "duplicate_task_id":
|
||||
if blocked["reason"] != "duplicate_task_id" or _own_emitted_stub(ctx, task_id, routing_token):
|
||||
_persist_promote_rejection(ctx, evt, blocked)
|
||||
_emit_routing_receipt(
|
||||
ctx,
|
||||
|
|
@ -564,7 +578,8 @@ def _promote_chat_to_task_outcome(evt: Dict[str, Any], ctx: Any) -> Dict[str, An
|
|||
reason="promote_chat_to_task_rejected",
|
||||
)
|
||||
supervisor_queue.release_task_admission(task_id, routing_token)
|
||||
if str(outcome.get("reason") or "") != "attachment_admission_rejected":
|
||||
if (str(outcome.get("reason") or "") != "attachment_admission_rejected"
|
||||
or _own_emitted_stub(ctx, task_id, routing_token)):
|
||||
_persist_promote_rejection(ctx, evt, outcome)
|
||||
_emit_routing_receipt(
|
||||
ctx,
|
||||
|
|
|
|||
|
|
@ -209,12 +209,12 @@ def enqueue_task(
|
|||
t["_admission_blocked"] = "duplicate_task_id"
|
||||
return t
|
||||
try:
|
||||
from ouroboros.routing_wait import is_emitted_admission_stub
|
||||
from ouroboros.routing_wait import is_own_admission_stub
|
||||
from ouroboros.task_results import load_task_result
|
||||
stored = load_task_result(DRIVE_ROOT, task_id, strict=True)
|
||||
# The emitted promote stub (#1160) belongs to THIS admission token:
|
||||
# its own enqueue reads around it, any other row still owns the id.
|
||||
if stored and not is_emitted_admission_stub(stored, admission_token):
|
||||
if stored and not is_own_admission_stub(stored, admission_token):
|
||||
if ADMISSION_RESERVATIONS.get(task_id) == admission_token:
|
||||
ADMISSION_RESERVATIONS.pop(task_id, None)
|
||||
t["_admission_blocked"] = "duplicate_task_id"
|
||||
|
|
|
|||
|
|
@ -624,9 +624,9 @@ def reserve_task_admission(
|
|||
) or {}
|
||||
except Exception:
|
||||
return {"status": "blocked", "reason": "task_id_lookup_failed"}
|
||||
from ouroboros.routing_wait import is_emitted_admission_stub
|
||||
from ouroboros.routing_wait import is_own_admission_stub
|
||||
|
||||
if existing and not is_emitted_admission_stub(existing, token):
|
||||
if existing and not is_own_admission_stub(existing, token):
|
||||
# The emitted stub of THIS admission is its own pre-receipt (#1160), not
|
||||
# another task owning the id: the request it belongs to still reserves.
|
||||
admission = existing.get("promotion_admission")
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ def _canonical_promoted_repair_constraint(value: Any) -> tuple[Optional[dict], s
|
|||
}, ""
|
||||
|
||||
|
||||
def _promote_duplicate_reason(task_id: str, ctx: Any, *, admission_token: str = "") -> str:
|
||||
def _promote_duplicate_reason(task_id: str, ctx: Any, *, admission_token: str) -> str:
|
||||
"""Fail closed if a promoted id is already live, durable, or uncheckable.
|
||||
|
||||
A row that is only THIS admission's emitted stub (#1160) is its own
|
||||
|
|
@ -161,13 +161,13 @@ def _promote_duplicate_reason(task_id: str, ctx: Any, *, admission_token: str =
|
|||
for row in list(pending or [])
|
||||
) or task_id in (running or {})
|
||||
try:
|
||||
from ouroboros.routing_wait import is_emitted_admission_stub
|
||||
from ouroboros.routing_wait import is_own_admission_stub
|
||||
from ouroboros.task_results import load_task_result
|
||||
|
||||
stored = load_task_result(
|
||||
getattr(ctx, "DRIVE_ROOT", _pool().DRIVE_ROOT), task_id, strict=True,
|
||||
)
|
||||
stored_duplicate = bool(stored) and not is_emitted_admission_stub(
|
||||
stored_duplicate = bool(stored) and not is_own_admission_stub(
|
||||
stored, admission_token,
|
||||
)
|
||||
except Exception:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ import types
|
|||
|
||||
import pytest
|
||||
|
||||
from tests.test_swarm_host_admission import host as _swarm_host
|
||||
|
||||
swarm_host = _swarm_host # the real supervisor handler needs a real host
|
||||
|
||||
|
||||
class _DeadQueue:
|
||||
"""A supervisor that accepted the event and has not answered yet."""
|
||||
|
|
@ -192,6 +196,44 @@ def test_the_emitted_stub_never_owns_its_own_admissions_id(tmp_path, monkeypatch
|
|||
) == "duplicate_task_id"
|
||||
|
||||
|
||||
def test_a_stub_is_read_around_only_by_the_token_that_wrote_it(tmp_path, monkeypatch, _short_confirmation_window):
|
||||
"""The other direction of the three gates: a promote's stub belongs to its own
|
||||
routing token. Any OTHER admission meets it as a row that owns the id, and a
|
||||
`requested` row that carries no emitted admission is never a stub at all."""
|
||||
import supervisor.queue as supervisor_queue
|
||||
import supervisor.workers as workers
|
||||
from ouroboros.routing_wait import is_emitted_admission_stub, is_own_admission_stub
|
||||
from ouroboros.task_results import load_task_result
|
||||
from ouroboros.tools.control_routing import _promote_chat_to_task
|
||||
|
||||
ctx = _promote_ctx(tmp_path, _DeadQueue())
|
||||
_promote_chat_to_task(ctx, "Build the racer", workspace="none", predecessor_task_id="")
|
||||
task_id = ctx.event_queue.events[0]["task_id"]
|
||||
monkeypatch.setattr(supervisor_queue, "DRIVE_ROOT", tmp_path)
|
||||
monkeypatch.setattr(supervisor_queue, "PENDING", [])
|
||||
monkeypatch.setattr(supervisor_queue, "RUNNING", {})
|
||||
monkeypatch.setattr(supervisor_queue, "ADMISSION_RESERVATIONS", {})
|
||||
host = types.SimpleNamespace(DRIVE_ROOT=tmp_path, PENDING=[], RUNNING={})
|
||||
|
||||
assert supervisor_queue.reserve_task_admission(
|
||||
task_id, "other-token", drive_root=tmp_path) == {"status": "blocked", "reason": "duplicate_task_id"}
|
||||
assert workers._promote_duplicate_reason(task_id, host, admission_token="other-token") == "duplicate_task_id"
|
||||
queued = supervisor_queue.enqueue_task({
|
||||
"id": task_id, "type": "task", "_require_unique_task_id": True, "_admission_token": "other-token"})
|
||||
assert queued.get("_admission_blocked") == "duplicate_task_id"
|
||||
|
||||
stub = load_task_result(tmp_path, task_id)
|
||||
assert is_emitted_admission_stub(stub) and not is_emitted_admission_stub(stub, "other-token")
|
||||
# The gates' form: no token is no claim, so a tokenless admission never reads around it.
|
||||
assert is_own_admission_stub(stub, stub["promotion_admission"]["routing_token"])
|
||||
assert not is_own_admission_stub(stub, "") and not is_own_admission_stub(stub, "other-token")
|
||||
assert supervisor_queue.enqueue_task({
|
||||
"id": task_id, "type": "task", "_require_unique_task_id": True,
|
||||
}).get("_admission_blocked") == "duplicate_task_id"
|
||||
assert not is_emitted_admission_stub({**stub, "status": "completed"})
|
||||
assert not is_emitted_admission_stub({**stub, "promotion_admission": {"status": "scheduled"}})
|
||||
|
||||
|
||||
def test_one_runtime_limit_bounds_both_promote_confirmation_waits():
|
||||
"""The two confirmation windows were byte-identical literals in two modules."""
|
||||
from ouroboros import routing_wait, runtime_limits
|
||||
|
|
@ -203,3 +245,80 @@ def test_one_runtime_limit_bounds_both_promote_confirmation_waits():
|
|||
assert routing_wait._confirm_wait_sec(None) == runtime_limits.get_promote_confirm_wait_sec()
|
||||
assert routing_wait._confirm_wait_sec(0.05) == 0.05 and routing_wait._confirm_wait_sec(-1) == 0.0
|
||||
assert control_events._PROMOTE_CONFIRM_TIMEOUT_SEC == runtime_limits.get_promote_confirm_wait_sec()
|
||||
|
||||
|
||||
def _emit_into(root, monkeypatch):
|
||||
"""A promote emitted at a supervisor that has not answered: the stub is on disk."""
|
||||
from ouroboros.tools import control_events
|
||||
from ouroboros.tools.control_routing import _promote_chat_to_task
|
||||
|
||||
monkeypatch.setattr(control_events, "_PROMOTE_CONFIRM_TIMEOUT_SEC", 0.05)
|
||||
monkeypatch.setattr(control_events, "_PROMOTE_CONFIRM_POLL_SEC", 0.005)
|
||||
ctx = _promote_ctx(root, _DeadQueue())
|
||||
out = _promote_chat_to_task(ctx, "Build the racer", workspace="none", predecessor_task_id="")
|
||||
assert out.startswith("⚠️ PROMOTE_UNCONFIRMED"), out
|
||||
return ctx, ctx.event_queue.events[0]
|
||||
|
||||
|
||||
def _attachments_rejected(task_id):
|
||||
return {"status": "needs_manual_target", "reason": "attachment_admission_rejected",
|
||||
"detail": "- a.png: rejected (reason=staging_unavailable, ordinal=0)",
|
||||
"task_id": task_id, "attachment_manifest": []}
|
||||
|
||||
|
||||
def test_a_refusal_that_writes_no_result_of_its_own_still_replaces_the_stub(swarm_host, monkeypatch):
|
||||
"""The attachment refusal persists no task result by design. Over an emitted
|
||||
stub that silence left "admission pending" on disk for ever, so the model was
|
||||
told not to promote again and the owner's work never started."""
|
||||
import supervisor.workers as workers
|
||||
from ouroboros.task_results import load_task_result
|
||||
from ouroboros.tools.control_task_results import _get_task_result
|
||||
from supervisor.events_project_routing import _handle_promote_chat_to_task
|
||||
|
||||
ctx, event = _emit_into(swarm_host.root, monkeypatch)
|
||||
task_id = event["task_id"]
|
||||
assert load_task_result(swarm_host.root, task_id)["promotion_admission"]["status"] == "emitted"
|
||||
monkeypatch.setattr(workers, "promote_chat_to_task", lambda evt, c: _attachments_rejected(task_id))
|
||||
|
||||
_handle_promote_chat_to_task(event, swarm_host.ctx)
|
||||
|
||||
stored = load_task_result(swarm_host.root, task_id)
|
||||
assert stored["status"] == "failed"
|
||||
assert stored["promotion_admission"]["status"] == "rejected"
|
||||
assert stored["promotion_admission"]["reason"] == "attachment_admission_rejected"
|
||||
read = _get_task_result(ctx, task_id)
|
||||
assert "admission pending" not in read and "attachment_admission_rejected" in read
|
||||
|
||||
|
||||
def test_the_attachment_refusal_without_a_stub_still_writes_no_result(swarm_host, monkeypatch):
|
||||
"""The quiet direction: that refusal's own contract is untouched. With no
|
||||
emitted stub on disk (a host-issued promote) it persists nothing, as before."""
|
||||
import supervisor.workers as workers
|
||||
from ouroboros.task_results import load_task_result
|
||||
from supervisor.events_project_routing import _handle_promote_chat_to_task
|
||||
|
||||
event = {"type": "promote_chat_to_task", "task_id": "hostpromote000001", "routing_token": "tok-host",
|
||||
"objective": "Build the racer", "chat_id": 1, "workspace": "none"}
|
||||
monkeypatch.setattr(workers, "promote_chat_to_task",
|
||||
lambda evt, c: _attachments_rejected("hostpromote000001"))
|
||||
|
||||
_handle_promote_chat_to_task(event, swarm_host.ctx)
|
||||
|
||||
assert not load_task_result(swarm_host.root, "hostpromote000001")
|
||||
|
||||
|
||||
def test_the_pending_sentence_never_forbids_a_new_promote_for_ever(tmp_path, _short_confirmation_window):
|
||||
"""The row proves one thing: emitted, no receipt yet. An event can be lost (a
|
||||
supervisor restart drops its in-memory queue), so the sentence hands the
|
||||
decision back with the facts instead of a standing ban."""
|
||||
from ouroboros.tools.control_routing import _promote_chat_to_task
|
||||
from ouroboros.tools.control_task_results import _get_task_result
|
||||
|
||||
ctx = _promote_ctx(tmp_path, _DeadQueue())
|
||||
_promote_chat_to_task(ctx, "Continue the racer", workspace="none", predecessor_task_id="")
|
||||
task_id = ctx.event_queue.events[0]["task_id"]
|
||||
|
||||
read = _get_task_result(ctx, task_id)
|
||||
assert "admission pending since" in read and f"get_task_result({task_id})" in read
|
||||
assert "do not promote the same work a second time" not in read
|
||||
assert "did not land" in read and "new promote" in read
|
||||
|
|
|
|||
|
|
@ -786,7 +786,7 @@ def test_exact_id_ingress_fails_closed_on_unreadable_result(monkeypatch, tmp_pat
|
|||
duplicate_reason = workers._promote_duplicate_reason(
|
||||
"malformed-id", types.SimpleNamespace(
|
||||
DRIVE_ROOT=tmp_path, PENDING=[], RUNNING={},
|
||||
),
|
||||
), admission_token="",
|
||||
)
|
||||
|
||||
assert reservation == {"status": "blocked", "reason": "task_id_lookup_failed"}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,33 @@ def test_a_root_the_room_manifest_lists_is_still_addressable(tmp_path):
|
|||
assert evt["predecessor_authority_source"]["tool"] == "get_task_result"
|
||||
|
||||
|
||||
def test_a_listed_row_is_accepted_only_with_the_pointer_the_host_issued_for_it(tmp_path):
|
||||
"""A row the host showed carries its own host-issued authority source, and only
|
||||
that one is accepted: rebuilding a source for a shown row would make a tampered
|
||||
manifest row indistinguishable from a host-built one."""
|
||||
import copy
|
||||
|
||||
import server
|
||||
from ouroboros.projects_registry import create_project
|
||||
from ouroboros.task_results import write_task_result
|
||||
|
||||
project = create_project(tmp_path, "racer", name="Racer")
|
||||
write_task_result(tmp_path, "racer-root", "completed", project_id="racer",
|
||||
objective="the root", ts="2026-08-10T00:00:01Z")
|
||||
metadata = server._decision_turn_metadata(
|
||||
_host_ctx(tmp_path), int(project["chat_id"]), "room-2", {"project_id": "racer"},
|
||||
)
|
||||
tampered = copy.deepcopy(metadata)
|
||||
tampered["project_last_task_result"]["authority_source"] = {"kind": "invented"}
|
||||
for row in tampered["project_routing_manifest"]["final_results"]:
|
||||
row["authority_source"] = {"kind": "invented"}
|
||||
|
||||
evt: dict = {}
|
||||
assert "no readable authority source" in _door(_room_ctx(tmp_path, tampered), "racer-root", evt)
|
||||
assert evt == {}
|
||||
assert _door(_room_ctx(tmp_path, metadata), "racer-root") == "" # the host's own row passes
|
||||
|
||||
|
||||
def test_a_room_root_older_than_the_list_is_addressable_all_the_same(tmp_path, monkeypatch):
|
||||
"""The 16-row cap is a HINT window, never the door: the night's root was a
|
||||
finished root of this very project, and only the cap hid it."""
|
||||
|
|
@ -308,6 +335,34 @@ def test_a_pointer_a_child_stamped_before_the_rule_heals_onto_the_root(tmp_path)
|
|||
assert get_project(tmp_path, "racer")["last_task_result_id"] == "racer-root"
|
||||
|
||||
|
||||
def test_a_pending_promote_is_neither_the_last_result_nor_a_predecessor(tmp_path):
|
||||
"""An emitted stub carries the project's id and is the newest file, but it is an
|
||||
admission still pending, not a result: the lookup answers with the root and never
|
||||
stamps the stub, and the door says what it is instead of "steer this live root"."""
|
||||
import os
|
||||
|
||||
import server
|
||||
from ouroboros.projects_registry import create_project, get_project
|
||||
from ouroboros.task_results import task_results_dir, write_task_result
|
||||
|
||||
create_project(tmp_path, "racer", name="Racer")
|
||||
write_task_result(tmp_path, "racer-root", "completed", project_id="racer", result="root answer")
|
||||
write_task_result(tmp_path, "racer-promote", "requested", project_id="racer", promotion_admission={
|
||||
"status": "emitted", "routing_token": "tok-1", "emitted_at": "2026-09-21T10:00:00Z"})
|
||||
results = task_results_dir(tmp_path, create=False)
|
||||
os.utime(results / "racer-root.json", (1_000, 1_000))
|
||||
os.utime(results / "racer-promote.json", (2_000, 2_000))
|
||||
|
||||
assert server._latest_project_task_result(_host_ctx(tmp_path), "racer")["task_id"] == "racer-root"
|
||||
assert get_project(tmp_path, "racer")["last_task_result_id"] == "racer-root"
|
||||
|
||||
refusal = _door(_room_ctx(tmp_path, {}), "racer-promote")
|
||||
assert "admission is still pending" in refusal and "steer_task" not in refusal
|
||||
# The quiet direction: a root that really is live keeps its own sentence.
|
||||
write_task_result(tmp_path, "racer-live", "running", project_id="racer")
|
||||
assert "steer_task" in _door(_room_ctx(tmp_path, {}), "racer-live")
|
||||
|
||||
|
||||
def test_the_room_manifest_carries_cancel_facts_and_an_honest_omission_count(tmp_path):
|
||||
import server
|
||||
from ouroboros.cancel_intents import request_cancel
|
||||
|
|
@ -327,7 +382,11 @@ def test_the_room_manifest_carries_cancel_facts_and_an_honest_omission_count(tmp
|
|||
ts="2026-08-10T00:00:02Z")
|
||||
running = {"racer-live": {"task": {"id": "racer-live", "project_id": "racer",
|
||||
"title": "Live", "objective": "in flight"},
|
||||
"started_at": "2026-08-10T00:00:03Z"}}
|
||||
"started_at": "2026-08-10T00:00:03Z"},
|
||||
# Another project's live root is none of this room's business.
|
||||
"other-live": {"task": {"id": "other-live", "project_id": "other",
|
||||
"title": "Elsewhere", "objective": "not this room"},
|
||||
"started_at": "2026-08-10T00:00:04Z"}}
|
||||
request_cancel(tmp_path, "racer-live", source="owner", reason="stop it")
|
||||
|
||||
manifest = server._decision_turn_metadata(
|
||||
|
|
@ -343,6 +402,15 @@ def test_the_room_manifest_carries_cancel_facts_and_an_honest_omission_count(tmp
|
|||
assert live["task_id"] == "racer-live" and live["cancel_state"] == "pending"
|
||||
assert manifest["omissions"]["children"] == 1
|
||||
assert manifest["omissions"]["final_results"] == 0
|
||||
assert manifest["omissions"]["active_roots"] == 0
|
||||
|
||||
# The live list is bounded too, and says how many of this room's roots it left out.
|
||||
crowd = {f"racer-live-{index:02d}": {"task": {"id": f"racer-live-{index:02d}", "project_id": "racer"},
|
||||
"started_at": "2026-08-10T00:00:05Z"} for index in range(43)}
|
||||
crowded = server._decision_turn_metadata(
|
||||
_host_ctx(tmp_path, running=crowd), int(project["chat_id"]), "room-8", {"project_id": "racer"},
|
||||
)["project_routing_manifest"]
|
||||
assert len(crowded["active_roots"]) == 40 and crowded["omissions"]["active_roots"] == 3
|
||||
|
||||
|
||||
def test_the_manifest_row_cap_is_one_runtime_limit(tmp_path, monkeypatch):
|
||||
|
|
|
|||
|
|
@ -184,6 +184,26 @@ def test_lineage_is_read_only_even_for_a_top_level_parent_drive(geometry):
|
|||
assert target.read_text(encoding="utf-8") == before
|
||||
|
||||
|
||||
def test_the_lineage_redirect_is_a_read_redirect_whatever_the_matrix_says(geometry):
|
||||
"""The write above is refused by the matrix first, so it never reaches the
|
||||
resolver. This one does: the redirect onto a lineage root exists for READ
|
||||
operations alone, so a profile whose matrix allows the write (an acting child
|
||||
in cyber_pro) still cannot be resolved into its parent's drive."""
|
||||
from ouroboros.tool_access import _resolve_target_in_selected_base
|
||||
|
||||
_registry, ctx = child_registry(geometry, acting=True)
|
||||
target = geometry.parent_drive / "triage-draft.json"
|
||||
own_base = geometry.headless / "task_drives" / CHILD
|
||||
|
||||
assert _resolve_target_in_selected_base(
|
||||
ctx, root="task_drive", base_path=own_base, path=str(target), operation="read",
|
||||
) == target.resolve()
|
||||
for operation in ("write", "edit"):
|
||||
with pytest.raises(ValueError):
|
||||
_resolve_target_in_selected_base(
|
||||
ctx, root="task_drive", base_path=own_base, path=str(target), operation=operation)
|
||||
|
||||
|
||||
# --- owner 7A: an absolute path without a root runs under the root holding it --
|
||||
|
||||
def test_child_reads_its_parents_task_drive_by_absolute_path_and_no_root(geometry):
|
||||
|
|
@ -345,6 +365,18 @@ def test_child_lists_the_parents_drive_with_secret_names_hidden(geometry):
|
|||
assert any("hidden from this subagent" in item for item in items), items
|
||||
|
||||
|
||||
def test_child_lists_deliverables_with_secret_names_hidden(geometry):
|
||||
"""Deliverables is a new listing root for the child, so it gets the same
|
||||
secret-name filter as every other root it lists; an ordinary file stays."""
|
||||
(geometry.deliverables / ".env").write_text("SECRET_TOKEN=sk-secret\n", encoding="utf-8")
|
||||
registry, _ctx = child_registry(geometry)
|
||||
|
||||
items = json.loads(registry.execute("list_files", {"root": "deliverables", "path": str(geometry.deliverables)}))
|
||||
|
||||
assert "answer.txt" in items and ".env" not in items, items
|
||||
assert any("hidden from this subagent" in item for item in items), items
|
||||
|
||||
|
||||
# --- the pure lineage function ------------------------------------------------
|
||||
|
||||
def test_lineage_task_ids_are_own_parent_and_root_and_nothing_else(geometry):
|
||||
|
|
|
|||
|
|
@ -383,10 +383,16 @@ def test_a_peer_process_does_not_refold_what_another_just_folded(data_root, monk
|
|||
assert _folds(data_root) == 1
|
||||
assert _skip_events(data_root) == [] # declined before the pass, not aborted inside it
|
||||
|
||||
# The floor is what that pass READ plus the retry window, not the bare size: a
|
||||
# ledger that regrew just past the old size is still inside the window (at the
|
||||
# measured 0.02 % gain that is a few KB, the very cascade this guard removes).
|
||||
_grow_past(data_root, monkeypatch, before.st_size + 1, "peer-growth")
|
||||
assert _trigger(data_root) is False
|
||||
assert len(entered) == 1
|
||||
|
||||
# Quiet on real growth: once the file passes what that pass READ plus the
|
||||
# retry window, the peer folds on its own.
|
||||
monkeypatch.setattr("ouroboros.config.USAGE_LEDGER_COMPACT_RETRY_GROWTH_BYTES", 1)
|
||||
_grow_past(data_root, monkeypatch, before.st_size + 1, "peer-growth")
|
||||
assert _trigger(data_root) is True
|
||||
assert len(entered) == 2
|
||||
assert int(_ledger_rows(data_root)[0]["compaction_epoch"]) == 2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue