Skip to content

factory r3: fix server-rest test drift and the factory_changed timer leak - #142

Merged
LittleChimera merged 4 commits into
stagingfrom
fix/server-rest-r3
Oct 28, 2026
Merged

LittleChimera merged 4 commits into
stagingfrom
fix/server-rest-r3

Conversation

@LittleChimera

@LittleChimera LittleChimera commented Oct 27, 2026 •

Copy link
Copy Markdown

Related issue

N/A (Test / CI)

Summary

The Pytest (server-rest) lane is red on staging and on every round-3 PR. The two original failures were test drift, not product regressions: factory label writes, factory session creation and GitHub credentials in sandboxes all still work. Once those were fixed, a flake and a memory leak surfaced in the same lane. The leak was killing the runner.

Factory flows I checked against the code:

  • Spawn (sys_factory_spawn) sends POST /v1/sessions with factory labels. The factory r3: Tier-0 hardening (push-ref allowlist, merge lockout, human origin, bundle fence, label audit) #135 guard (_reject_runner_factory_labels) only covers the generic PATCH /v1/sessions/{id}, so spawn is unaffected. The new test covers this case.
  • sys_factory_set and mutual supervision go through PATCH /v1/factory/sessions/{id}. That route is not guarded, and its tests pass.
  • Supervisor/reconcile label writes happen on the server through the stores. No runner-side code writes omnigent.factory.* labels through the generic PATCH.

Out of scope, found in review (both predate this PR):

  • SSH keys for VS Code Remote / SSHPiper. The credential broker did not replace SSH keys. Before Sync5: merge upstream/main into staging #83 the Kubernetes launcher wrote ~/.ssh/authorized_keys. Nothing in omnigent writes it on staging now, but the deployed SSHPiper config still reads the sandbox's client_authorized_keys. VS Code Remote through SSHPiper has probably been broken since Sync5. ssh_authorized_keys_setup_commands and resolve_sandbox_identity should stay until someone decides whether SSHPiper is still supported.
  • Runner-origin session create with server-only factory labels. A runner bearer can POST /v1/sessions with server-only labels (e.g. omnigent.factory.engine_mode, def_version, role=root) and get 201. The R3-04 checks only guard the PATCH routes. sys_factory_spawn never sends these labels, so a follow-up can refuse them on runner-origin creates without breaking spawn.

Test Plan

  • Reproduced the label-test failure locally with a scratch pytest plugin that moves the clock back 700 s during collection: 6 failed / 1 passed on staging, all pass with this change.
  • Leak: a scratch plugin counted live objects after a 19-test factory slice. Before the fix it found 11 event loops, 11 engines and 1177 alembic Script objects retained, all rooted in live._pending. After the fix it found 0 / 0 / 0. test_a_loop_closed_inside_the_debounce_leaves_no_pending_timer fails without the fix and passes with it.
  • Whole server-rest lane locally, -n 4 as in CI, rebased on staging 760d0ab: 6077 passed, peak worker RSS 4.3 GB (8 GB before). The only failures are local-env gaps (databricks / asgiref not installed).
  • tests/server/factory, the labels, github-injection and tests/runner/test_factory_spawn.py modules on the final rebase: 1447 passed.
  • Credential broker and sandboxes: tests/server/routes/test_host_credentials.py tests/test_git_credential_github.py tests/onboarding/sandboxes: 669 passed.
  • pre-commit clean on the changed files (pyrefly reports only pre-existing errors in other files).

Demo

N/A

Type of change

  • Bug fix
  • Feature
  • UI / frontend change
  • Refactor / chore
  • Docs
  • Test / CI
  • Breaking change

Test coverage

  • Unit tests added / updated
  • Integration tests added / updated
  • E2E tests added / updated
  • Manual verification completed
  • Existing tests cover this change
  • Not applicable

Coverage notes

github_sandbox_env and git_identity_env are unused since #83. ssh_authorized_keys_setup_commands and resolve_sandbox_identity are also unwired, but they are tied to the open SSHPiper question above, so this PR leaves them in place.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the size/M Pull request size: M label Oct 27, 2026
@LittleChimera LittleChimera changed the title factory r3: fix server-rest regressions after round-3 hardening factory r3: fix server-rest test drift after round-3 hardening Oct 27, 2026
@LittleChimera
LittleChimera force-pushed the fix/server-rest-r3 branch 3 times, most recently from 9c478c1 to 9b2da69 Compare October 28, 2026 02:18
LittleChimera and others added 4 commits October 28, 2026 04:00
test_sessions_factory_labels minted its runner and person bearers at
collection time with a 600 s TTL. Under xdist the server-rest lane runs the
module ~15 min after collection, so every parametrized case got 401 instead
of the 403 it asserts. Mint the headers inside the test. Add a case that a
runner bearer still creates a session carrying factory labels
(sys_factory_spawn's POST /v1/sessions).

test_github_injection still passed github_token / github_login /
ssh_authorized_keys to start_host, which Sync5 (#83) removed in favour of
the server-side credential broker that the host configures at startup.
Assert the launch carries no GitHub credentials instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…test

The runner-create case now sends the heartbeat label that _spawn_member
always sends. The start_host test no longer asserts on authorized_keys or
frames SSH keys as handled by the credential broker: the broker covers
GitHub tokens only, and SSH key setup is currently unwired.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lead and ic refusals were logged on the same FakeClock millisecond, and
find_events breaks ts ties by event id, which is minted in a worker thread.
Under xdist load the two came back in either order. Advance the clock one
second before the ic post so the events sort by ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
announce_factory_changed parks a debounce task per (loop, factory) in a
module-level dict and only removed it after the 0.5 s sleep. A loop that
closes inside that window (every async test that emits a factory event)
cancels the task and leaves the entry behind, and the entry pins the task,
its loop, the app state, the stores and their engines with the compiled
migration statements. In the server-rest lane that is ~5 MB per factory
test; the workers reached ~8 GB and the runner was killed at 91-97% on
every run since the round-3 merges. A done callback now drops the entry
however the timer ends: the lane peaks at ~4.3 GB locally, and a
19-test factory slice runs in 40 s instead of 300 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LittleChimera LittleChimera changed the title factory r3: fix server-rest test drift after round-3 hardening factory r3: fix server-rest test drift and the factory_changed timer leak Oct 28, 2026
@LittleChimera
LittleChimera merged commit aab4d5e into staging Oct 28, 2026
54 of 63 checks passed
@LittleChimera
LittleChimera deleted the fix/server-rest-r3 branch October 28, 2026 03:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Pull request size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant