New API idea: .to_actor.open_taskman() - #486
Draft
goodboy wants to merge 32 commits into
Draft
Conversation
to_actor.open_taskman()to_actor.open_taskman()
to_actor.open_taskman().to_actor.open_taskman()
3 tasks
First cut at the `to_thread`/`to_process`-style "run it over there" wrapper layer from issue #477: a single-remote-task invocation API decoupled from the `ActorNursery` spawn machinery, composed purely from the lower level daemon-actor + portal primitives, - `to_actor.run(fn, **fn_kwargs)` spawns a subactor via `ActorNursery.start_actor()`, schedules `fn` as its lone task with `Portal.run()` and ALWAYS reaps it via a `finally`-scoped `Portal.cancel_actor()` (whose bounded cancel-req wait is internally shielded so the reap also runs under caller-scope cancellation). - remote errors raise directly in the caller's task as boxed `RemoteActorError`s, moving error collection/propagation up into whatever local `trio` scope encloses the call. - "placement" opts: `portal=` reuses a running actor (no spawn/reap), `an=` spawns from a caller-managed actor-nursery, neither opens a private call-scoped `open_nursery()` (implicitly booting the runtime, tunable via pass-through `runtime_kwargs`). - fail-fast validation BEFORE any spawn: non-streaming async fn only (same constraint as `Portal.run()`), `portal=`/`an=` mutual exclusion and no `runtime_kwargs` alongside a placement opt. Also, - x-ref the successor API from `.run_in_actor()`'s deprecation TODO + docstring; emitting a formal `DeprecationWarning` waits on migrating in-repo usage. - log prompt-io provenance per NLNet policy incl. the driver prompt file. Prompt-IO: ai/prompt-io/claude/20260702T154255Z_65bf9df5_prompt_io.md (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Cover every placement variant + failure mode of the new `to_actor.run()`, - private-nursery one-shot + implicit runtime boot via pass-through `runtime_kwargs`, - remote-error relay to the caller's task (bare and inside a caller-managed `an`) as boxed `RemoteActorError`s, - caller-nursery spawn + portal-reuse w/o implicit reap, - the concurrent "worker-pool-ish" pattern: a local `trio` task nursery scheduling one-shots against a shared `an`, - the 4 pre-spawn validation rejections (sync fn, async-gen fn, `portal`+`an` combo, `runtime_kwargs`+placement combo). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Demo both flavors of the new API in a runnable script (auto-collected by `test_docs_examples.py`), - the fully-implicit one-shot which boots (and tears down) the actor-runtime around a single `to_actor.run()` call, - the concurrent "worker-pool-ish" prime-check pattern: a local `trio` task nursery scheduling one-shots against a shared caller-managed `an`, mirroring (in miniature) the neighboring `concurrent_actors_primes.py` example per issue #477. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Split from the step-A code commit to keep the runtime diff free of `ai/` meta noise, - `ai/conc-anal/ria_nursery_removal_plan.md`: agent-verified machinery map + 3-step (A/B/C) design + probe history (reap-relocation deadlock -> sequencing fix -> bound tighten) + risk register for the `._ria_nursery` excision. - `ai/prompt-io/claude/20260702T165806Z_a34aaf98_*`: NLNet provenance (log + unedited raw) for the step-A work. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Step A of the `._ria_nursery` removal (issue #477 follow-up, see `ai/conc-anal/ria_nursery_removal_plan.md`): `.run_in_actor()` children now spawn via the default daemon nursery and their result-reaping moves up into the `ActorNursery` machinery, - new `_supervise._reap_ria_portals()`: one `_spawn.cancel_on_completion()` task per ria child, run AFTER `._join_procs` is set — replacing the per-child reaper task the backends formerly spawned (keyed off `._cancel_after_result_on_exit` membership) which required routing such children into `._ria_nursery`. - happy path: reap awaited right after `._join_procs.set()`, preserving "collect ria results before daemon join" sequencing. - error path: snapshot ria `(portal, subactor)` pairs (backend `finally`s pop `._children` as procs reap), `await an.cancel()`, THEN a 0.5s-bounded reap over the snapshot; anything collectable is already queued in the local ctx and a parked reaper self-cleans (`trio.Cancelled` results are never stashed). NB: a concurrent reap+cancel variant deadlocked `test_multierror` and a 3s bound blew `test_cancel_while_childs_child_in_sync_sleep`'s deadline — deats in the plan doc's probe history. - `spawn/_trio.py` + `spawn/_mp.py`: drop the membership branch, per-child reaper nursery + now-unused `cancel_on_completion` imports; the join phase is a bare `soft_kill()`. `._ria_nursery` is now vestigial (zero spawn users): step B deletes it + `start_actor()`'s `nursery=` escape hatch and merges the supervisor's two error handlers. Prompt-IO: ai/prompt-io/claude/20260702T165806Z_a34aaf98_prompt_io.md (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Split from the step-B code commit to keep the runtime diff free of `ai/` meta noise, - `ai/conc-anal/ria_nursery_removal_plan.md`: add a "Step-B outcome" section — the empty-nursery collapse, why it's behavior-preserving, the deliberate handler-merge deferral, and the targeted-gate result. - `ai/prompt-io/claude/20260702T172233Z_5cd190c5_*`: NLNet provenance (log + unedited raw) for the step-B work. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Step B of the `._ria_nursery` removal (issue #477; see `ai/conc-anal/ria_nursery_removal_plan.md`). With step A having rerouted `.run_in_actor()` children onto the daemon nursery, the 2ndary "run-in-actor" nursery spawns nothing and its stored ref is never read — pure dead weight, - collapse the inner `async with trio.open_nursery() as ria_nursery` layer in `_open_and_supervise_one_cancels_all_nursery`; `da_nursery` is now the single nursery for ALL subactors. - `ActorNursery.__init__` loses the `ria_nursery` param + the `self._ria_nursery` attr; `start_actor()` loses its `nursery=` escape-hatch (spawns via `self._da_nursery` directly). - `._cancel_after_result_on_exit` stays — still the ria-child discriminator for `_reap_ria_portals()`. Behavior-preserving: a zero-task `trio.open_nursery()` only adds a checkpoint. The two error handlers are KEPT (now nested under the single nursery); merging them changes error/cancel propagation and is deferred to its own PR (TODO left at the outer `except`). Prompt-IO: ai/prompt-io/claude/20260702T172233Z_5cd190c5_prompt_io.md (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Split from the step-B2 code commit to keep the runtime diff free of `ai/` meta noise, - `ai/conc-anal/ria_nursery_removal_plan.md`: add a "Step-B2 outcome" section — the dead-outer-`raise` trace, why the merge is behavior-preserving, and the gate results. - `ai/prompt-io/claude/20260702T222544Z_9201a2ed_*`: NLNet provenance (log + unedited raw) for the step-B2 work. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Step B2 of the `._ria_nursery` removal (issue #477; see `ai/conc-anal/ria_nursery_removal_plan.md`). With the 2ndary nursery gone (step B), the two nested error handlers in `_open_and_supervise_one_cancels_all_nursery` collapse to one, - the outer `except (Exception, BaseExceptionGroup, trio.Cancelled)` existed to catch errors bubbling from the old `._ria_nursery.__aexit__` reaper-group; that nursery no longer exists. - trace shows the outer handler's `raise` was already DEAD: the inner handler records `errors[uid]` as its first action, so `errors` is always non-empty by the time anything could reach the outer handler, and the `finally`'s raise-from-`errors` always superseded the outer `raise`. - so fold both into a single `except BaseException as _scope_err` guarding the lone daemon nursery; the `finally` (unchanged) still raises the collected `errors` as a single exc or `BaseExceptionGroup`. - drop the now-unused `outer_err`/`inner_err` locals. Behaviour-preserving (net ~30 lines lighter); the big diff is the one-level de-indent of the handler body. The two remaining `maybe_wait_for_debugger()` guards collapse to the single pre-teardown wait. Prompt-IO: ai/prompt-io/claude/20260702T222544Z_9201a2ed_prompt_io.md (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Wrap `test_tractor_cancels_aio`'s `main()` in a `trio.fail_after(9 * cpu_perf_headroom())` so a wedged remote runtime can't hang the test forever. This is the blessed anti-hang guard here bc `pytest-timeout`'s global cap is intentionally off (it breaks `trio` under the fork backends, per the `pyproject` NOTE). The cap is generous + CPU-headroom-scaled bc it's an anti-hang guard, not a perf assertion. Motivated by the `._ria_nursery`-removal regression where a wedged ria-reaper once hung this exact test indefinitely. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
First test-file of the #477 `.run_in_actor()` removal (blocking `to_actor.run()` is the successor; the legacy non-blocking one-shot is dropped, not replaced). All 9 call-sites migrated, - blocking result/error/streaming-result tests -> `to_actor.run(fn, an=an, ...)`; the "streaming" ones stream aio<->trio INSIDE the subactor so the caller only awaits the final result. - forever-task + cancel tests (`test_tractor_cancels_aio`, `test_trio_cancels_aio`) -> `start_actor()` + `Portal.open_context()` + cancel — can't block on a never-returning task. Adds a small `sleep_forever_aio_ctx` `@context` shim. - greens the red `test_tractor_cancels_aio` anti-hang guard from the prior commit: under the correctly-scoped API the wait is bounded by the caller's cancel scope, so the hang is structurally gone — not patched. Suite: 34 passed, 2 xfailed (trio backend). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Sole call-site: an inlined `run_in_actor(...).result()` -> blocking `tractor.to_actor.run(fn, an=an, ...)` (#477 removal). Behaviour identical — the one-shot's result/error is awaited in the caller's task rather than reaped at nursery teardown; the enclosing `move_on_after` still cancels the sub in the `error_in_child=False` case. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Sole call-site: `run_in_actor(sleep_back_actor, ...)` -> blocking `tractor.to_actor.run(..., an=n, ...)` (#477 removal). The RPC-callback subactor is awaited in-caller instead of reaped at nursery teardown; `name=`/`enable_modules=` map to `to_actor.run()`'s same-named params, the rest to `**fn_kwargs`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Migrate all 4 sites to blocking `tractor.to_actor.run()` (#477 removal), - rename the two API-named tests to `test_to_actor_run_*` (`same_func_in_child`, `can_skip_parent_main_inheritance`) — they exercise the same spawn / `inherit_parent_main` path via the successor API. - the recursive `spawn()` helper drops its white-box `an._children` / portal-`_peers` asserts (which probed `run_in_actor`'s portal + nursery-tracking internals); `to_actor.run()` returns the result and reaps internally, so keep the user-facing `result == 10` check. - `test_most_beautiful_word` drops the 2nd `wait_for_result()` (the legacy result-cache re-fetch) — `to_actor.run()` delivers the value once, no cache. Suite: 9 passed. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
`test_multi_actor_subs_arbiter_pub` used `run_in_actor()` to spawn two forever-ish subscriber actors and hold their portals for a later `cancel_actor()` (its `.result()` was commented out exactly because `subs()` never cleanly returns). That deferred-spawn + cancel shape isn't a blocking `to_actor.run()`, so convert to the successor primitives (#477 removal), - `start_actor()` per subscriber — keeps the portal for the existing `cancel_actor()` teardown, - run `subs()` on each via a background `Portal.run()` task in a local `trio` nursery so both subscribe concurrently with the test's `wait_for_actor` / topic checks, - each bg runner swallows the `RemoteActorError`/`ContextCancelled` that `cancel_actor()` relays; a trailing `tn.cancel_scope.cancel()` drops any lingering runner. Suite: 8 passed. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Two sites migrated (#477 removal), - `test_trynamic_trio`: donny + gretchen each wait on the *other* to register, so they must run CONCURRENTLY — was two non-blocking `run_in_actor()`s awaited after; now two `to_actor.run()` one-shots scheduled into a local `trio` task-nursery. - the unregister-on-cancel cluster test: its non-streaming branch spawned `run_in_actor(trio.sleep_forever)` purely to keep each subactor alive + registered — a `start_actor()` daemon does that without a "main" task, so the spawn loop collapses to the same `start_actor()` the streaming branch already used. Suite: 16 passed. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
First group of the `test_cancellation.py` `run_in_actor` removal (#477), - `test_remote_error` -> blocking `to_actor.run()` (single erroring one-shot; a bad-arg `TypeError` still relays as a `RemoteActorError`). - `test_multierror` -> concurrent fan-out via `gather_contexts([p.open_context(assert_err_ctx) ...])` over `start_actor()` portals. NB `gather_contexts` is cancel-on-first so the 2nd errorer is usually cancelled before relaying its own exc and the pair collapses to a single `RemoteActorError` (vs the legacy reap-all-at-teardown `BEG`-of-N) — the assertion now accepts either shape. - delete `test_multierror_fast_nursery` — a 25-actor stress test of `run_in_actor`'s teardown-reap; no analogous surface under the `to_actor` fan-out. - add an `assert_err_ctx` `@context` shim for the `open_context` fan-out. Remaining `test_cancellation` groups (some_cancels_all, nested, SIGINT, sync-blocking) still on `run_in_actor` — ported next. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Append two sections to the ria-removal plan capturing the 2026-07-02 hang episode + the resulting design pivot. Regression writeup: the full-suite hang on `test_tractor_cancels_aio` root-caused to the step-A reaper hoist (`5cd190c5`), not the B2 handler merge. The happy-path `_reap_ria_portals()` parks unbounded on `wait_for_result()` after a user `portal.cancel_actor()`; the old spawn-backend reaper raced `soft_kill()`'s scope-cancel, the hoist dropped it. Records the `proc.poll()` death-watch fix + why poll (not the event `wait_func`) bc `soft_kill` already awaits `proc.sentinel` (a 2nd `wait_readable` -> `BusyResourceError`). Pause writeup: user's insight that the hoist landed in the wrong scope — result-waiting belongs in the `to_actor` one-shot scope (`_invoke_in_subactor()`), beside `an` + a local task-nursery + cancel-scope, where bounding the wait is trivial + the hang dissolves. So the poll fix is likely SUPERSEDED (flagged do-not-land); the anti-hang guard commit (`d1fb4a1a`) stays red-first per the failing-test convention. (this patch was generated in some part by `claude-code` using `claude-opus-4-8` (`anthropic`))
Second `test_cancellation.py` group of the `run_in_actor` removal (#477), - one-shot subactors now run as concurrent `to_actor.run(fn, an=an)` tasks in a local `trio` task-nursery, so their errors raise WHILE the actor-nursery block is open (vs the legacy teardown-reap) and the first error cancels sibling one-shots. - wrap the task-nursery in `collapse_eg()` so the deterministic single-error cases still surface a bare `RemoteActorError`. - loosen the group-shape assertion: the relay-vs-cancel race populates anywhere from 1 to `num_actors` `RemoteActorError`s (the exact-`num_actors` BEG was `run_in_actor`'s reap-all-at-teardown); group members are always `RemoteActorError` now since sibling `trio.Cancelled`s are absorbed by the task-nursery. - move the daemon-portal call loop inside the task-nursery body so the sleep-forever one-shot case is cancelled by the daemon error raise. - rename the `*run_in_actor*` param ids to `*one_shot*`. Gate: 6 passed on both `trio` + `mp_spawn` backends. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
`test_nested_multierrors`'s backend/depth budget `match` only carries arms for the `trio` + `main_thread_forkserver` spawn backends, so running under any other (e.g. `mp_spawn`) leaves `timeout` unbound and crashes with an `UnboundLocalError` at the headroom-scaling below. Add default per-depth arms riding the MTF budgets (same per-spawn round-trip cost class). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Third `test_cancellation.py` group of the `run_in_actor` removal (#477), - `spawn_and_error` fans out each level's erroring one-shots as concurrent `to_actor.run(fn, an=an)` tasks in a local `trio` task-nursery (recursing per spawner subactor), as does the test-body's top-level spawner loop. - the deterministic exact-breadth nested-BEG shape dies with the legacy teardown-reap: each level now groups whatever subset of sub-tree errors relay before the first one's cancel wins, and a single-member group gets unwrapped by the runtime's own `collapse_eg()` at every actor boundary — so a fully-raced tree relays a bare `RemoteActorError` chain. - loosen the shape walk accordingly: accept a lone `RemoteActorError` or a 1..breadth group whose members box `ExceptionGroup` (multi-relay), `AssertionError` (collapsed leaf chain), `RemoteActorError` (re-boxed collapsed chain) or `BaseExceptionGroup` (runtime reap-deadline `Cancelled` upgrade); fold the windows-only tolerances into the same walk. - raced sibling `trio.Cancelled`s are now ABSORBED by the task-nursery instead of landing in the group, so the MTF shape-mismatch xfail should consistently xpass — note added to drop the marker once CI confirms. - add an `else: pytest.fail()` so a silently-clean tree can no longer pass. Gate: both depths green on `trio` (10 consecutive runs) + `mp_spawn`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Final `test_cancellation.py` group of the `run_in_actor` removal (#477) — cancel-mechanics tests, so clean conversions, - `test_cancel_via_SIGINT_other_task`: the 3 keep-alive `run_in_actor(sleep_forever)` one-shots become plain `start_actor()` daemons (an idle daemon needs no "main" task, and no longer shares a single dup'd `namesucka` name). - `spawn_sub_with_sync_blocking_task`: the middle layer's spawn becomes a blocking `to_actor.run(spin_for, an=an)` which parks awaiting the sync-sleeping grandchild's result until cancelled from above. - `test_cancel_while_childs_child_in_sync_sleep`: the fire-and-forget middle-actor spawn becomes a bg `to_actor.run()` task in a local task-nursery; the root's `assert 0` cancels it, driving the same graceful-cancel-then-zombie-reap cascade on the sync-blocked grandchild. The `man_cancel_outer` xfail param is unchanged. Zero live `run_in_actor()` call-sites remain in this suite. Gate: full `test_cancellation.py` module green on both `trio` (18p/1xf) + `mp_spawn` (18p/1xf). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The known-flaky dynamic pubsub test's 3 fire-and-forget spawn sites (#477 removal), - the forever-streaming `publisher` + N `consumer` one-shots now bg-schedule as `to_actor.run(fn, an=n)` tasks in a local `trio` task-nursery (`publisher`'s rendezvous name still derives from `fn.__name__`). - the simulated user-cancel raise (`KeyboardInterrupt` / `TooSlowError` params) cancels the task-nursery, each one-shot reaping its subactor via `to_actor.run()`'s shielded `Portal.cancel_actor()`; `_run_and_match()`'s existing `BaseExceptionGroup.split()` walk covers the (possibly nested) relay shapes unchanged. - spawns now issue concurrently rather than sequentially — comment on the fork-backend budget updated to match. Gate: both params x4 runs green on `trio` + x1 on `mp_spawn`; full module green. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
4 example scripts of the #477 removal sweep, each exercised by `test_docs_examples.py`, - `actor_spawning_and_causality.py`: the simplest possible `to_actor.run()` demo — private call-scoped nursery, block on and print the one-shot's result. - `remote_error_propagation.py`: blocking `to_actor.run(an=n)` raises the boxed `AssertionError` in the caller's task, cancelling the sibling daemons. - `parallelism/single_func.py`: bg-burn a core in the parent via a local task-nursery while the one-shot burns (and returns from) a subactor. - `a_trynamic_first_scene.py`: donny + gretchen wait on each *other* so their one-shots run concurrently in a local task-nursery against a shared `an` (mirrors the migrated `test_trynamic_trio`). Gate: all 4 green via the example-runner suite. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The 8 `examples/debugging/` scripts driven by the pexpect'd `test_debugger.py` REPL-flows (#477 removal), - blocking one-shots (`subactor_error`, `subactor_breakpoint`, `shielded_pause`): straight `to_actor.run(fn, an=an)` — the boxed error/`BdbQuit` raises in the root's task. - `multi_subactors`: introduces the "collect all errors" pattern — each one-shot catches + stashes its `RemoteActorError` (vs raising) so no child's crash cancels its siblings before they've had their own REPL sessions, then a `BaseExceptionGroup` of the lot raises at the end; preserves the legacy teardown-reap REPL flow exactly (28/28 debugger suite unchanged). - `multi_nested_subactors_error_up_through_nurseries` + `root_cancelled_but_child_is_in_tty_lock`: recursive `spawn_until` levels each block on their one-shot child; the parallel spawner-trees run as bg task-nursery one-shots where the first tree's error cancels the other. - `multi_subactor_root_errors` + `root_timeout_while_child_crashed`: `start_actor()` + bg `Portal.run()` tasks so the root's own error/timeout races the already-crashed children, same as before. - `sync_bp`: TODO-comment x-ref update only. `test_debugger.py`: the nested-nurseries test's final-output patterns update to the new relay shape — the LAST-released leaf REPL's error chain wins each level's relay-vs-cancel race and relays as a `collapse_eg()`-annotated collapsed chain, while the sibling tree is cancelled + absorbed. (The legacy teardown-reap grouped BOTH the `name_error` and bp-quit chains — explaining the previously-mysterious "extra" `src_uid`/`relay_uid` patterns noted in the old TODO.) Gate: `tests/devx/test_debugger.py` = 28 passed, 6 skipped — identical to the pre-migration baseline. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The 8-page docs sweep of the #477 removal, ahead of the API's excision, - `start/quickstart.rst`: the first-actor-tree walkthrough now narrates the (migrated) `to_actor.run()` example — no portal in hand until the daemon section introduces `start_actor()`. - `guide/spawning.rst`: the one-shot section becomes `to_actor.run()` (blocking call, placement opts, "built on the primitives" note); lifetime/teardown rules update — one-shots never make it to nursery exit since each is reaped inside its own call. - `guide/rpc.rst`: the `wait_for_result()` section (an API that dies with the reap cluster, incl. the `NoResult` sentinel) becomes a `to_actor.run()` one-shot section. - `api/core.rst`: drop `run_in_actor`/`wait_for_result` from the autodoc member lists, drop the `Portal.result()` deprecation note, add a "One-shot task actors" `tractor.to_actor.run` autodoc section. - `guide/{asyncio,context,cancellation,parallelism}.rst`: mention swaps to the successor API. Gate: `make -C docs html` builds clean; `to_actor.run` autodoc renders in `api/core.html`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The `_pubsub.pub` decorator's usage example predates several API generations: ancient positional-arg-order `run_in_actor()` (a missing `await` too) plus the deprecated `portal.result()` — and `run_in_actor()` never allowed streaming funcs anyway. Show the canonical `start_actor()` + `Portal.open_stream_from()` consumption instead (#477 removal sweep). (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The final excision of #477: with zero in-repo callers left (all tests/examples/docs migrated to `to_actor.run()` et al) the entire legacy one-shot machinery drops out, - `runtime/_supervise.py`: `ActorNursery.run_in_actor()`, the `._cancel_after_result_on_exit` portal-set and the `_reap_ria_portals()` teardown-reaper (both its happy-path block-exit call AND the error-path snapshot + 0.5s-bounded collection) are deleted — one-shot result-waiting now lives entirely in the caller's task via `to_actor.run()`, whose enclosing cancel-scope bounds the wait by construction (the correct-scoping fix for the unbounded-reap hang class; the `d1fb4a1a` guard test now passes structurally). - `runtime/_portal.py`: `Portal._submit_for_result()`, `._expect_result_ctx`, `._final_result_msg/_pld`, `.wait_for_result()` + the deprecated `.result()` alias are gone — a `Portal` no longer has any "main result" notion. NB `Context.wait_for_result()` is a different (very alive) API and is untouched. - `spawn/_spawn.py`: `exhaust_portal()` + `cancel_on_completion()` (the reaper tasks) deleted; backend comment sweeps in `_trio.py`/`_mp.py`. - `_exceptions.py`: the `NoResult` sentinel dies with its lone reader. - `tests/test_ringbuf.py`: drop a daemon-portal `.result()` call that was already a warn + `NoResult` no-op (the ctx-acm exit does the real result-wait); unshadow the 2nd `sctx` as `rctx`. - comment/docstring x-ref sweeps: `msg/types.py`, `_context.py`, `to_actor/`, `tests/test_to_actor.py`. Gate: `test_to_actor test_spawning test_cancellation test_infected_asyncio test_local test_rpc` = 81 passed, 3 xfailed on `trio`; +`test_ringbuf` = 70 passed, 3 skipped, 3 xfailed on `mp_spawn`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
The `test_trynamic_trio` + `a_trynamic_first_scene.py` migration to paired `to_actor.run()` one-shots carries a race the legacy `run_in_actor()` shape never had: donny + gretchen each `wait_for_actor()` (then DIAL) the *other*, but a one-shot is reaped the instant its own hello returns — so the slower peer can resolve the winner's registry entry and connect to an already-dead sockaddr -> `ConnectionRefusedError` boxed as a `RemoteActorError` (or a reg-wait `TooSlowError`), flaking ~1-in-3 standalone runs. Mutual-rendezvous peers must OUTLIVE both dialogs, so pin the lifetimes explicitly: `start_actor()` both as daemons, run both hellos concurrently via bg `Portal.run()` tasks, then reap with `an.cancel()` only after the task-nursery joins. (The legacy teardown-reap provided this pinning implicitly — one of the few places its semantics were ever actually relied upon.) Gate: `-k trynamic` standalone x8 green (was flaking); full `test_registrar` module + the example-runner green. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Convention sweep (user req): all `tractor.open_nursery()` bindings in test + example code use `an: ActorNursery` (`n`, `nursery` + several tractor-nurseries confusingly named `tn` are renamed); `trio.open_nursery()` bindings stay `tn` (incl. `concurrent_actors_primes.py`'s inner trio nursery, renamed `n` -> `tn` to match). Purely mechanical, function-scoped renames — prose "nursery"/ "an" in docstrings/comments untouched; func-arg kwargs like `portal.run(func, n=value)` untouched. Gate: renamed test modules green on `trio`; full debugger suite (28p/6s) + example-runner (21p) green. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Fold the endeavour's resolution into the plan doc + log the session per prompt-io policy, - `ria_nursery_removal_plan.md`: RESOLVED section — migrate everything, remove the API; the migration-pattern table (blocking / fire-and-forget / fan-out / collect-don't-cancel / mutual-rendezvous), the semantic deltas (cancel-on-first + `collapse_eg()` chain collapse vs the old teardown-reap BEG), the excision inventory and the structural dissolution of the reap-hang class. - adds the `to_actor.open_one_shot()` follow-up sketch: an `@acm` + private task-nursery over the existing blocking `run()` — done-`trio.Event` as a result memo (NOT a cancel-relay), no `Portal` in the iface, errors always propagate at scope exit; zero `_supervise` coupling. - prompt-io entry `20260706T172818Z_ad42871e` (+ raw diff-ref companion) covering commits `d01a2123..ad42871`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code
Two new provenance/planning docs kicking off issue #485 — the `to_actor.open_taskman()` deferred/non-blocking successor to the `run_in_actor()` removed by #477/#484. `ai/conc-anal/to_actor_taskman_design.md` (self-contained hand-off): the core principle (every non-blocking remote-task invocation needs an explicitly-owned scope, so NO `Portal.run_soon()` — the scope-owning `tm` IS the API), the three prior-art sources to mine (`hilevel_serman` `ServiceMngr`, PR #363 `trionics` taskman, `piker` `Services`), the `hilevel_serman` rebase + convergence map (incl. the known `portal.wait_for_result()` breakage at `_service.py:292`), the parked-holder core + `run_soon()` API, the `one_cancels_all`/`collect` strategies + `wait`/`cancel` exit policies, resolved design items, and the PR A/B/C sequencing. `ai/prompt-io/prompts/issue_485.md`: the kickoff brief for PR A — required reading, prior art, + house rules. Prompt-IO: ai/prompt-io/prompts/issue_485.md (this patch was generated in some part by `claude-code` using `claude-opus-4-8` (`anthropic`))
goodboy
force-pushed
the
to_actor.open_taskman
branch
from
August 13, 2026 00:07
62b02e9 to
bcf7946
Compare
goodboy
force-pushed
the
drop_ria_nursery
branch
2 times, most recently
from
August 18, 2026 02:07
6e2ce2b to
38d6688
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Just pushing of the draft design doc vibed with
fable.