ouroboros/tests/test_loop_compaction_policy.py
Ouroboros 62f87cc94c Merge upstream ouroboros db6d7cf8 into the v7 line: absorb PR #609 net-resilience and PR #614 update letter
Second absorption of the frozen upstream line (23ab428f..db6d7cf8: 89
commits, 47 files) on top of the rc.10 hotfix tip, by the F2 rules (S1
upstream body in the owning leaf, S2 hand-merge, S3 only with proof;
retired 7.0 surfaces never return):

- PR #609 net-resilience: interactive transport-wait episodes bounded by
  the task idle timeout with the typed task_incident/toast_once pair, a
  bounded paid repeat after a typed post-dispatch transport death with a
  round-keyed record that fences every other send, the shutdown-aware
  supervisor crash counter and bounded lifespan join, Darwin keepalive
  tuning. loop_transport/transport_custody/net_transport/loop_llm_call
  land verbatim (same shapes on both sides); the loop.py deltas are
  relocated into the v7 leaves (loop_round_limits, loop_model_call,
  loop_delivery, loop_forced_finalization, loop_nudges, loop_messages,
  loop_budget) with bodies AST-equal to upstream modulo the call-time
  handles; _emit_overflow_retry_skipped stays a public helper (the v7
  facade contract) and upstream's nested _skipped delegates to it.
- PR #614 update letter: ouroboros/update_letter.py and its web module
  land verbatim; the new OUROBOROS_UPDATE_LETTER_TIMEOUT_SEC key and
  get_update_letter_timeout_sec live in their v7 owners
  (settings_defaults.py, runtime_limits.py, re-exported by config.py);
  _supervisor_stop lives in server_process.py beside the restart events;
  docs/PERSISTENCE.md gains the state/update_letter.json row and the
  inventory pin moves to 286.
- Tests: the relocated run_llm_loop tests take the emit_progress
  incident keyword (every one-argument progress fake in tests/ swept, a
  gap upstream itself left in test_tree_cost_ceiling); the official-update
  runtime-section test lands in tests/test_context.py; _MOVED_OWNERS
  registers the relocated getter.
- Docs: ARCHITECTURE/DEVELOPMENT hunks land on the upstream text; the two
  legacy timeout rows upstream's context still carries stay retired (7.0).
- Size ratchet regenerated; the band rationale for tests/test_update_letter.py
  is carried verbatim from upstream.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-04 22:53:15 +00:00

90 lines
2.9 KiB
Python

"""Deletion-first loop policy: manual control plus one measured Main pass."""
from __future__ import annotations
from types import SimpleNamespace
def _ctx(tmp_path, *, pending=None):
from ouroboros import loop
inner = SimpleNamespace(_pending_compaction=pending)
return loop._CompactionRoundContext(
tools=SimpleNamespace(_ctx=inner),
drive_root=tmp_path,
drive_logs=tmp_path / "logs",
task_id="task",
round_idx=77,
event_queue=None,
emit_progress=lambda _text, *, incident=None: None,
)
def test_no_manual_request_is_byte_identical_at_every_round(tmp_path, monkeypatch):
from ouroboros import loop
called = False
def forbidden(*_a, **_kw):
nonlocal called
called = True
raise AssertionError("fixed/routine compaction must not run")
monkeypatch.setattr(loop, "compact_tool_history_llm", forbidden)
messages = [{"role": "user", "content": "x" * 1_500_000}]
result, usage = loop._run_round_compaction(
messages,
_ctx(tmp_path),
)
assert result is messages
assert usage is None
assert called is False
def test_manual_request_uses_the_shared_typed_materializer(tmp_path, monkeypatch):
from ouroboros import loop
from ouroboros.context_budget import ContextReclaimReceipt
seen = {}
rebuilt = [{"role": "assistant", "content": "summary"}]
receipt = ContextReclaimReceipt(
status="applied",
before_transcript_sha256="a" * 64,
after_transcript_sha256="b" * 64,
selection_fingerprint="c" * 64,
selected_unit_ids=("unit",),
reclaimed_tokens=10,
goal_reached=False,
checkpoint_ref={"path": "checkpoint"},
capsule_refs=(),
)
def fake(messages, **kwargs):
seen.update(kwargs)
return rebuilt, receipt, {"prompt_tokens": 3, "completion_tokens": 2}
monkeypatch.setattr(loop, "compact_tool_history_llm", fake)
context = _ctx(tmp_path, pending=4)
result, usage = loop._run_round_compaction([{"role": "user", "content": "go"}], context)
assert result is rebuilt
assert usage == {"prompt_tokens": 3, "completion_tokens": 2}
assert seen["keep_recent"] == 4
assert seen["negative_memo"] is context.tools._ctx._context_reclaim_negative_memo
assert context.tools._ctx._pending_compaction is None
def test_old_main_trigger_authorities_are_deleted():
from pathlib import Path
source = Path("ouroboros/loop.py").read_text(encoding="utf-8")
budget = Path("ouroboros/context_budget.py").read_text(encoding="utf-8")
for symbol in (
"EMERGENCY_COMPACTION_CHARS",
"LOW_EMERGENCY_COMPACTION_CHARS",
"COMPACTION_HYSTERESIS_REGION_GROWTH",
"COMPACTION_HYSTERESIS_ROUNDS",
"_compaction_floor_chars",
"_emergency_keep_recent",
):
assert symbol not in source
assert symbol not in budget
assert "round_idx > 6" not in source