ouroboros/devtools/e2e_live
Ouroboros 4f3cda85d5 fix(e2e_live): absorb wait proves no cycle is pending; non-absorbing lanes do not promote
Adversarial review of the corrected --self-mod seeding (2026-09-06) traced
the post-task path end to end and found that IsolatedServer.wait_for_absorb
ended the wait as no_promotion on ONE idle /api/state sample once the grace
had passed: no request file, pending_count 0, running_count 0. Those are
exactly the readings of the absorb path itself. A cycle that committed keeps
its campaign transaction as waiting_for_restart while the supervisor
restarts synchronously (RUNNING already popped, the counter unchanged), and
the re-exec'd server answers /api/state with zero counts before its
supervisor is up; absorbed_cycles_done moves only when the worker boot
verifies the restart. The pre-seeded benchmark campaign used to mask this
(its t=0 cycle kept running_count above zero and the kept request file
blocked the exit); with the owner-id-only seeding every SM1 lane would have
failed a healthy absorb as no_promotion.

wait_for_absorb now needs PROOF that no cycle is pending, held on six
consecutive polls after the grace: the queue idle AND supervisor_ready AND
no post_task_evolution_request.json AND no campaign active_transaction. The
reason is typed from the durable campaign state (campaign_summary /
absorb_idle_reason): no_promotion (no campaign although the post-task
decision ran), no_decision, cycle_no_op, cycle_not_absorbed,
campaign_<status>, cycle_not_enqueued; the summary travels in the wait dict
the stand records. Benchmark callers (evolve_smoke, the CLB adapter) keep
their early exit on a genuinely idle campaign.

Two more findings from the same review: scenarios that commit nothing
(SW1, SK1) now pin OUROBOROS_POST_TASK_EVOLUTION=false in their lane
settings — a one-shot cycle promoted from their own roots could commit and
re-exec the server in the middle of the lifecycle under test; and the SK1
gate also requires the review call's own executable_review (a pending
duplicate job never passes) while _skill_entry reads the listing through
the non-raising helper so a failed listing is a failed check with facts, not
an infra_error. Tests: a new module pins the wait on a fake clock
(waiting_for_restart and a booting server do not end it, one idle sample
does not, a pending request blocks it, the absorb confirms, every idle
reason), the SK1 module pins the product gate rule and the per-scenario
promotion pin, the runner module's settings pin flips for SW1/SK1.

Co-authored-by: Ouroboros <311266734+ouroboros-agent@users.noreply.github.com>
2026-09-06 01:04:49 +00:00
..
__init__.py Live E2E stand: devtools/e2e_live runs K staggered isolated servers over the SM1/SW1/SK1 scenario table (F4-A) 2026-09-04 23:37:49 +00:00
run_live_lanes.py fix(e2e_live): --self-mod seeds the owner id only, never a campaign 2026-09-05 23:25:35 +00:00
scenarios.py fix(e2e_live): absorb wait proves no cycle is pending; non-absorbing lanes do not promote 2026-09-06 01:04:49 +00:00
stub_lane.py Live E2E stand: devtools/e2e_live runs K staggered isolated servers over the SM1/SW1/SK1 scenario table (F4-A) 2026-09-04 23:37:49 +00:00
ui_probe.py Live E2E stand: the orphan cmdline pin is procfs-gated; the lazy-open note names SW1 2026-09-05 14:57:14 +00:00