mirror of
https://github.com/razzant/ouroboros.git
synced 2026-10-03 04:07:04 +00:00
fix(e2e_live): --self-mod seeds the owner id only, never a campaign
The rc.15 paid run2 (2026-09-05, SM1_a1/a2) showed the stand's --self-mod
lanes pre-seeding the benchmark helper's ACTIVE campaign ("benchmark
evidence" objective, evolution_mode_enabled) instead of relying on the
post-task promotion path the flag is meant to exercise:
- generic cycles ran from t=0 next to the scenario task (three no_op
cycles, $16 on one lane), each counted as a consecutive failure;
- the promotion the scenario task wrote (post_task_evolution_request.json)
was refused by apply_pending_request because evolution was already
enabled, and the kept request file also blocked wait_for_absorb's
no_promotion exit — every SM1 lane waited the full task timeout with
absorbed_cycles_done at 0 although its reviewed commit had landed.
seed_owner_state(data_root, evolution_enabled=False) under every profile:
--self-mod stays a settings fact (OUROBOROS_POST_TASK_EVOLUTION + cadence
every_n:1) and the scenario task's own promotion enables the one-shot
campaign whose cycle lands, restarts and absorbs. The reservation rule
keeps +1 root (the one post-task cycle); its wording, the RunBudget
docstring and the DEVELOPMENT.md stand section say so, and a runner test
pins the seeded state (owner_chat_id only, no evolution_campaign.json,
no evolution_mode_enabled) with and without --self-mod.
Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
This commit is contained in:
parent
f450953d5c
commit
c6f002c122
3 changed files with 28 additions and 23 deletions
|
|
@ -93,7 +93,7 @@ PROCFS_AVAILABLE = os.path.isdir("/proc") # the orphan scan reads /proc enviro
|
|||
LANE_BUDGET_FLOOR_USD = 0.01
|
||||
RESERVATION_RULE = (f"max({LANE_BUDGET_FLOOR_USD:g}, per_task_usd x (root_tasks + 1 if --self-mod else root_tasks)) — the "
|
||||
"runtime fences each root task tree at OUROBOROS_PER_TASK_COST_USD and --self-mod adds one root for the "
|
||||
"evolution cycle (rc.14: up to two cycles per lane, one at t=0 and one post-task, under the same lane fence). "
|
||||
"one post-task evolution cycle (the lane seeds no campaign: the promotion enables a one-shot one). "
|
||||
"The lane's TOTAL_BUDGET is that reservation — the true fence — so settled spend + in-flight ceilings <= cap")
|
||||
|
||||
|
||||
|
|
@ -257,8 +257,7 @@ class RunBudget:
|
|||
Reservation rule, per attempt: ``per_task_usd x (root_tasks + int(self_mod))`` — the runtime fences each ROOT
|
||||
task tree at ``OUROBOROS_PER_TASK_COST_USD`` and children spend under their root's ceiling, so SW1 (one root,
|
||||
two scouts) reserves for one root, SK1 (author + dispatch) for two, and ``--self-mod`` adds one root for the
|
||||
evolution cycle: rc.14 showed up to TWO cycles per lane, one at t=0 next to the scenario task and one
|
||||
post-task, all under the lane fence — the lane's TOTAL_BUDGET is the true fence. Admission asks, PER attempt:
|
||||
one post-task evolution cycle, all under the lane fence — the true fence. Admission asks, PER attempt:
|
||||
``spent + reservation > cap`` — it can NEVER fit, refused and recorded ``not_run`` (a later, smaller attempt is
|
||||
asked on its own; nothing halts the run); otherwise it reserves only when no earlier-dispatched attempt is
|
||||
still asking (FIFO by ``dispatch_index``, see ``admit``) and ``spent + reserved(in flight) + reservation <=
|
||||
|
|
@ -705,7 +704,8 @@ def run_lane(job: tuple[str, int], args: argparse.Namespace, out: pathlib.Path,
|
|||
row["budget"] = {"reservation_usd": budget.reservation(scenario.root_tasks),
|
||||
"lane_total_budget_usd": cfg["TOTAL_BUDGET"], "per_task_usd": float(args.per_task_usd)}
|
||||
sha = write_settings(settings_path, cfg)
|
||||
seed_owner_state(data_root, evolution_enabled=args.self_mod)
|
||||
# Owner id only, never a campaign: the task's post-task promotion enables the one-shot one (rc.15 run2 pin).
|
||||
seed_owner_state(data_root, evolution_enabled=False)
|
||||
from supervisor import state as sstate
|
||||
(data_root / sstate.ISOLATED_BENCHMARK_SENTINEL).write_text("isolated e2e_live data root\n", encoding="utf-8")
|
||||
oracle = harness.ArtifactOracle(data_root)
|
||||
|
|
|
|||
|
|
@ -1296,8 +1296,8 @@ refuses below `--min-credit-usd`. `--total-budget` (default 100) is the RUN-WIDE
|
|||
cap: a ledger sums the lanes' durable `llm_usage` costs, reserves
|
||||
`max(0.01, --per-task-usd × (root tasks + 1 with --self-mod))` per attempt (SM1 and SW1 one root — scouts spend
|
||||
under their root's `OUROBOROS_PER_TASK_COST_USD` fence — SK1 two; with `--self-mod` the
|
||||
evolution cycle is one more root: the rc.14 paid run showed up to TWO cycles per lane, one
|
||||
starting at t=0 next to the scenario task and one post-task, all under the lane fence — SM1_a1
|
||||
one post-task evolution cycle is one more root (the rc.14 paid run showed a second, generic
|
||||
cycle at t=0 from the benchmark campaign the lane pre-seeded then), all under the lane fence — SM1_a1
|
||||
task $3.84 + cycles $12.40 + $2.84 of $20; the lane's TOTAL_BUDGET is the true fence and the
|
||||
+1 root is its reservation), admits an
|
||||
attempt only while `spent + reserved(in flight) + reservation ≤ cap` — an attempt that
|
||||
|
|
@ -1366,7 +1366,12 @@ server and resolves `-n auto` to the host CPU count, so the stand sets
|
|||
`preflight_runner._preflight_env` still scrubs it from the candidate suite) and
|
||||
records the applied value as `extra.preflight_test_workers` in the manifest and
|
||||
`preflight_test_workers` in every lane row. `--self-mod` enables post-task evolution with the real
|
||||
re-exec restart and REQUIRES a confirmed absorb per lane whose scenario
|
||||
re-exec restart — a settings fact (`OUROBOROS_POST_TASK_EVOLUTION` + cadence `every_n:1`) while the
|
||||
lane seeds `owner_chat_id` ONLY, never a campaign: the scenario task's post-task promotion
|
||||
(`apply_pending_request`) enables the one-shot campaign whose cycle lands, restarts and absorbs.
|
||||
A pre-seeded active campaign (the benchmark helper's form, rc.15 paid run2) runs generic cycles from
|
||||
t=0, gets the promotion refused (evolution already enabled) and its kept request file blocks the
|
||||
`no_promotion` exit of the absorb wait. `--self-mod` REQUIRES a confirmed absorb per lane whose scenario
|
||||
`expects_absorb` (SM1, the one that lands a commit): a pre-task snapshot
|
||||
(clone HEAD, served sha, uptime, absorbed-cycle counter) and, afterwards, the
|
||||
counter advanced, the served sha moved, the uptime reset and the server ready;
|
||||
|
|
|
|||
|
|
@ -388,9 +388,8 @@ def test_admission_is_fifo_by_dispatch_index_and_a_refused_head_frees_the_line(t
|
|||
|
||||
|
||||
def test_reservation_counts_roots_plus_the_evolution_root_and_is_the_lane_total_budget(tmp_path, monkeypatch):
|
||||
"""EQUALITY pins of the rc.14/rc.15 finding: the reservation is per-task x root tasks, +1 with --self-mod (rc.14
|
||||
showed up to TWO evolution cycles per lane, one at t=0 next to the scenario task and one post-task, all under the
|
||||
lane fence: SM1_a1 task $3.84 + cycles $12.40 + $2.84 of $20 — the lane's TOTAL_BUDGET is the true fence); the 2x
|
||||
"""EQUALITY pins of the rc.14/rc.15 finding: the reservation is per-task x root tasks, +1 with --self-mod (the one
|
||||
post-task cycle; rc.14: SM1_a1 task $3.84 + cycles $12.40 + $2.84 of $20 — the lane's TOTAL_BUDGET is the fence); the 2x
|
||||
factor and its product import are gone and no bench budget profile is projected. Per-task $20 and one root reserve
|
||||
$20 ($40 with --self-mod, $60 for SK1 + evolution) and that exact number reaches the lane's settings file as
|
||||
TOTAL_BUDGET through ``run_lane`` (never the run-wide cap)."""
|
||||
|
|
@ -398,7 +397,7 @@ def test_reservation_counts_roots_plus_the_evolution_root_and_is_the_lane_total_
|
|||
rule = run_live_lanes.RESERVATION_RULE
|
||||
assert not hasattr(run_live_lanes, "HARD_STOP_INVERSE") and rule == run_live_lanes.RunBudget(1, 1).snapshot()["reservation_rule"]
|
||||
assert rule.startswith("max(0.01, per_task_usd x (root_tasks + 1 if --self-mod else root_tasks))")
|
||||
assert "up to two cycles per lane" in rule and "the true fence" in rule and "cost_hard_stop" not in rule
|
||||
assert "one post-task evolution cycle" in rule and "the true fence" in rule and "cost_hard_stop" not in rule
|
||||
budget = run_live_lanes.RunBudget(100.0, 20.0, reader=lambda root: (0.0, 0))
|
||||
assert budget.reservation(1) == 20.0 and budget.reservation(2) == 40.0 and not budget.self_mod
|
||||
evolving = run_live_lanes.RunBudget(100.0, 20.0, reader=lambda root: (0.0, 0), self_mod=True)
|
||||
|
|
@ -408,10 +407,7 @@ def test_reservation_counts_roots_plus_the_evolution_root_and_is_the_lane_total_
|
|||
ok, facts = budget.admit(job, 1, out / "lanes" / "SM1_a1" / "data", dispatch_index=0)
|
||||
assert ok and facts["reservation_usd"] == 20.0 and budget.ceiling(job) == 20.0
|
||||
|
||||
class _NoServer: # the real path up to the written settings, then stop
|
||||
def __init__(self, *_a, **_k) -> None:
|
||||
self.base_url = "http://127.0.0.1:0"
|
||||
|
||||
class _NoServer(_NoopServer): # the real path up to the written settings, then stop
|
||||
def start(self, **_k) -> None:
|
||||
raise RuntimeError("no server in this pin: the settings file on disk is the evidence")
|
||||
|
||||
|
|
@ -877,8 +873,8 @@ def test_lane_with_a_dead_browser_target_is_checks_failed_not_infra_error(tmp_pa
|
|||
def test_absorb_wait_and_check_follow_the_scenarios_expects_absorb(tmp_path, monkeypatch):
|
||||
"""The rc.15 paid stand (2026-09-05, SK1_a1): every ``--self-mod`` lane waited ``--task-timeout`` for an absorb
|
||||
only SM1's commit could trigger, then failed ``self_mod_absorb_confirmed`` by construction. Now SM1 waits and
|
||||
carries the check; SW1/SK1 stop right after the scenario with ``{"expected": False}``, no check, and post-task
|
||||
evolution still ON in their settings (the campaign may run during the scenario; the stand does not wait)."""
|
||||
carries the check; SW1/SK1 stop right after the scenario with ``{"expected": False}``, no check, post-task
|
||||
evolution ON in their settings; every lane seeds ``owner_chat_id`` ONLY, never a campaign (run2's t=0 cycles)."""
|
||||
waits: list = []
|
||||
monkeypatch.setattr(run_live_lanes, "resolve_ui_client", lambda base_url: (None, "ui_unavailable:test"))
|
||||
monkeypatch.setattr(run_live_lanes, "self_mod_snapshot", lambda server, clone, data_root: {"pre": True})
|
||||
|
|
@ -887,12 +883,16 @@ def test_absorb_wait_and_check_follow_the_scenarios_expects_absorb(tmp_path, mon
|
|||
sm1 = _attempt_row(tmp_path, monkeypatch, "SM1", flags="--self-mod")
|
||||
assert waits == [{"pre": True}] and sm1["status"] == "fail" and sm1["checks"]["self_mod_absorb_confirmed"] is False
|
||||
assert sm1["self_mod_absorb"] == {"expected": True, "confirmed": False, "reason": "no_promotion", "healthy": True}
|
||||
for sid in ("SW1", "SK1"):
|
||||
row = _attempt_row(tmp_path, monkeypatch, sid, flags="--self-mod")
|
||||
assert row["status"] == "pass" and "self_mod_absorb_confirmed" not in row["checks"], row["checks"]
|
||||
assert row["self_mod_absorb"] == {"expected": False} and row["self_mod"] is True and waits == [{"pre": True}]
|
||||
applied = json.loads((tmp_path / sid / "out" / "lanes" / f"{sid}_a1" / "data" / "settings.json").read_text())
|
||||
assert applied["OUROBOROS_POST_TASK_EVOLUTION"] == "true"
|
||||
for sid in ("SM1", "SW1", "SK1"):
|
||||
if sid != "SM1":
|
||||
row = _attempt_row(tmp_path, monkeypatch, sid, flags="--self-mod")
|
||||
assert row["status"] == "pass" and "self_mod_absorb_confirmed" not in row["checks"], row["checks"]
|
||||
assert row["self_mod_absorb"] == {"expected": False} and row["self_mod"] is True and waits == [{"pre": True}]
|
||||
lane = tmp_path / sid / "out" / "lanes" / f"{sid}_a1" / "data"
|
||||
state = json.loads((lane / "state" / "state.json").read_text(encoding="utf-8"))
|
||||
assert json.loads((lane / "settings.json").read_text())["OUROBOROS_POST_TASK_EVOLUTION"] == "true"
|
||||
assert state["owner_chat_id"] == 1 and "evolution_mode_enabled" not in state, state
|
||||
assert not (lane / "state" / "evolution_campaign.json").exists(), sid
|
||||
|
||||
|
||||
def test_wait_task_namespaces_checks_per_task_and_check_refuses_overwrites():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue