Commit Graph

2915 Commits (4c507ea13c98978aea6d42b20fa86e4930892d69)

Author SHA1 Message Date
Gud Boi 4c507ea13c Add a dedicated-registrar example + discovery guide
Add a runnable `examples/dedicated_registrar.py` + a "A dedicated
registrar" subsection in `guide/discovery.rst` demoing the
registrar decoupled from any app tree's root: boot a bare
`tractor.run_daemon([], registry_addrs=[...])` as its own process
(a root actor that does nothing but hold the registry), point the
app tree at the same `registry_addrs`, and discover a service
*through* that external registrar.

This is the buildable-today form of the #472
"Registrar-as-subsystem (not the root actor)" bullet. Two
constraints are called out inline as follow-ups:
`enable_transports` is single-proto per runtime (no multi-backend
registrar yet), and a registrar can only be a root (no `actor_cls`
hook on `start_actor()` to spawn one as a subactor).

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-08-28 14:40:01 -04:00
Gud Boi a279cb39a9 Expand caps-based-msging docs w/ #365, #376 + tests
The "Toward capability-based msging" section only pointed at the
`#196`/`#36` epics. Fold in the concrete recent state,

- `#365` as the most recent step: driving the whole `pld_spec` off
  plain type-annotations (e.g. annotating a context's
  `open_stream()` with `msgspec.Struct` subtypes) rather than
  explicit `pld_spec=` kwargs.
- clarify that the decorator-level `@tractor.context(pld_spec=...)`
  is already the higher-level path (vs the lower-level
  `tractor.msg._ops.limit_plds()` escape hatch), pointing at
  `tests/msg/test_pldrx_limiting.py` + `test_ext_types_msgspec.py`
  which exercise both.
- `#376` (from @guilledk, `auto_codecs` branch) as the drafted
  public factory API for the `enc_hook`/`dec_hook` pair (today only
  reachable via `tractor.msg._ops`).

Addresses the caps-based-msging bullet in #472.

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-08-28 14:40:01 -04:00
Bd f40efdd8da
Merge pull request #490 from goodboy/wkt/fix_broadcast_lag_count
Harden broadcast fan-out ownership and failures
2026-08-28 14:31:52 -04:00
Gud Boi 6429e6a515 Reject concurrent `BroadcastReceiver.receive()` calls
Two tasks could receive through one `BroadcastReceiver` and race its
single `_wait_scope`. A later call could replace the scope, leaving
the first blocked through `.aclose()`.

Track the active `trio.lowlevel.Task` per receiver and reject an
overlapping call with `trio.BusyResourceError`. Include the owner's
task name and repr in the error, then clear ownership in `finally`.

Define each receiver as one logical subscription cursor. Concurrent
consumers must use separate `.subscribe()` receivers so each retains
an independent cursor and lag policy. Strict mode reads every retained
value or raises `Lagged`; `raise_on_lag=False` explicitly permits
drops.

Cover the regression with a checkpoint loop synchronized on
`recv_ready`; explain the interleaving inline, assert the error names
the active consumer, then release the source and prove the original
receive remains usable.

Prompt-IO: ai/prompt-io/opencode/20260828T014247Z_d06ee34b_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 22:11:55 -04:00
Gud Boi d06ee34b83 Clean broadcast cancellation diagnostics
Bound `BroadcastState.cancelled` entries to receiver progress,
terminal state and resource lifetime instead of retaining completed
`Task`s indefinitely.

Deats,
- make EOC durable so awakened peers never re-enter a closed source.
- close root broadcasters during explicit `MsgStream` and
  `LinkedTaskChannel` teardown without re-entrant EOC closure or
  breaking `MsgStream.aclose()` overrides.
- reject non-positive fan-out retention capacity before constructing
  an unusable zero-length queue.
- cover child/root cancellation cleanup, terminal peer wakeups,
  wrapper teardown, subclass compatibility and zero-buffer rejection.

Prompt-IO: ai/prompt-io/opencode/20260813T181901Z_a2e0df4b_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 21:18:00 -04:00
Gud Boi ff4391669b Expose stream subscriber lag policy
`MsgStream.subscribe()` and `LinkedTaskChannel.subscribe()` omitted
`BroadcastReceiver.raise_on_lag`, forcing downstream consumers to
mutate a private receiver attribute when overruns were acceptable.

Add `raise_on_lag` to both public wrappers. The first subscription
sets the irreversible root broadcaster's policy, while every child
selects its own strict or warn/drop/resume behavior independently.

Document both fan-out APIs. Cover policy forwarding plus real IPC
and infected-asyncio paths.

Prompt-IO: ai/prompt-io/opencode/20260812T213117Z_51185487_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 21:18:00 -04:00
Gud Boi a5259a8ee4 Isolate `BroadcastReceiver.aclose()` wakeups
Closing any subscriber set the shared `recv_ready` event, even when
another receiver owned the source read. Waiting peers then looped
until an idle source produced another value.

Give each receiver private source-read and peer-wait cancellation
scopes. Closing a waiting peer interrupts only that peer. Closing
the source owner discards post-close source outcomes and then wakes
peers for a clean ownership handoff.

Keep outer task cancellation as `trio.Cancelled`; only explicit
receiver close maps either private scope's cancellation to
`ClosedResourceError`. Assert that scope cancellation implies the
receiver is closed and document the source-owner key check.

Prompt-IO: ai/prompt-io/opencode/20260812T150027Z_c2a6ccef_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 21:18:00 -04:00
Gud Boi d6da0e7a22 Wake broadcast peers on shared receive failures
Only `EndOfChannel` and direct cancellation woke tasks waiting
behind the subscriber which owned the underlying receive. Any other
failure cleared `BroadcastState.recv_ready` while peers remained
blocked on its unreachable event.

Publish ordinary receive exceptions as terminal broadcast state.
The owner keeps the original failure while peers drain retained
values and then raise `BroadcastReceiveError` from that cause. Also
wake peers on process-control exits without retaining them as state.

Document the public owner/peer contract and cover current, late and
control-flow subscribers with deterministic bounded regressions.

Prompt-IO: ai/prompt-io/opencode/20260812T030608Z_1095e7f7_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 21:18:00 -04:00
Gud Boi 5afd834732 Fix `BroadcastState.statistics()` queue counts
`BroadcastState.subs` stores each receiver's next unread deque
index, but `.statistics()` exposed that index as a queue length. A
caught-up receiver looked correct by accident while every queued
count was one short.

Convert cursors to retained, receivable counts and clamp lagged
receivers to the current queue length. Also avoid deprecated
`trio.Event` truthiness when reporting waiter counts.

Cover caught-up, queued, lagged and real-event states using actual
broadcast sends and receives.

Prompt-IO: ai/prompt-io/opencode/20260812T012324Z_06c4af17_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 21:18:00 -04:00
Gud Boi 206b0354c5 Fix `BroadcastReceiver` lag counts
`BroadcastReceiver.receive_nowait()` treated `seq` as a deque index
but subtracted `BroadcastState.maxlen` without counting the first
invalid index. A one-slot queue thus claimed it dropped zero values
after its subscriber missed one.

Include that first displaced value in the count. Preserve the
existing Tokio-style reset to the oldest retained item.

Also, cover exact loss reporting and recovery for one- and
three-slot retention windows.

Prompt-IO: ai/prompt-io/opencode/20260811T233833Z_7cbd64ee_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 21:18:00 -04:00
Bd 11dc534a5d
Merge pull request #510 from goodboy/wkt/ai_skillz_run_tests_landing
`ai.skillz` multi-harness deploy (and a proper `/run-tests` landing)
2026-08-27 20:25:14 -04:00
Gud Boi 24e55e918e Document canonical `/run-tests` deployment
Link Tractor's project reference to the immutable canonical skill
and its repository, then show the exact hybrid deployment command.

Also clarify the Prompt-IO record's commit boundaries and PR #510
review direction.

Review: PR #510 (copilot-pull-request-reviewer)
https://github.com/goodboy/tractor/pull/510#pullrequestreview-5046306236

Prompt-IO: ai/prompt-io/opencode/20260822T022526Z_5562fd9a_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-27 19:47:31 -04:00
Gud Boi c9cfce441a Harden `run-tests` signal and reaper guidance
Prevent unsafe harness guidance from sending SIGUSR1 before
`stackscope` installs its handler or using shared-memory scans on
unsupported platforms.

Deats,
- verify `stackscope` in the pytest env before signaling.
- target pytest by default and require a separately verified handler
  before signaling subactors.
- keep `tractor-reap --shm*` guidance to Linux and FreeBSD.
- pin staged Prompt-IO provenance to `eb3c99c9` and record the
  PR #510 review direction.

Prompt-IO: ai/prompt-io/opencode/20260822T022526Z_5562fd9a_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-27 18:52:16 -04:00
Gud Boi 7b89995089 Ignore deployed `ai.skillz/` state
Record generated ignore blocks for deployed skills, commands, and
runtime artifacts so direct symlink deployments remain status-clean.

(this commit msg was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 18:34:49 -04:00
Gud Boi eb3c99c9fd Correct `run-tests` harness guidance
The migration reference overstated cleanup safety and omitted
current environment, platform, debugger and timeout behavior.

- document runtime env overrides and the actual CI matrix
- distinguish interactive debugger capture from hang diagnosis
- describe Trio-aware and SIGALRM timeout guards separately
- expose reaper platform limits and dry-run descendant expansion
- restore exact change-to-test mappings and randomized-port wording
- drop unrelated Taken and broad command ignores from the migration

Prompt-IO: ai/prompt-io/opencode/20260822T022526Z_5562fd9a_prompt_io.md

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-27 18:34:48 -04:00
Gud Boi 11ae5171d1 Use canonical `/run-tests` skill
Move Tractor's project-specific test knowledge into the local harness
reference and let `ai.skillz` own shared execution and safety policy.

Deats,
- document current Python envs, pytest opts, backends, and transports.
- replace broad registry and process cleanup rules with scoped checks.
- record capture, diagnostics, reaper, and expected-outcome caveats.
- ignore canonical Claude and OpenCode links plus Taken runtime state.

(this patch was generated in some part by `opencode` using
`gpt-5.6-sol` (`openai`))
2026-08-27 18:34:48 -04:00
Bd 90c4954cb9
Merge pull request #508 from goodboy/wkt/macos_ci_reruns
Retry macOS tests with `pytest-rerunfailures`
2026-08-27 16:45:35 -04:00
Gud Boi 0664731372 Retry macOS tests with `pytest-rerunfailures`
Give only the macOS matrix leg two retries so actor/PTY timing
flakes do not strand otherwise-green runs. Linux and Windows remain
strict first-attempt jobs, while persistent macOS failures stay red
after the final visible rerun.

Deats,
- add the pytest-dev-maintained plugin to testing deps
- keep a one-second delay between macOS attempts
- validate the workflow, lock and both observed flaky test areas

Prompt-IO: ai/prompt-io/opencode/20260821T052052Z_3690e43a_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-27 13:43:06 -04:00
Bd e90f2f224a
Merge pull request #484 from goodboy/drop_ria_nursery
Drop `run_in_actor()` + the ria reap-cluster
2026-08-26 22:48:32 -04:00
Gud Boi 1ad6281348 Clarify recursive one-shot spawning test
Handle the child RPC leaf as an early return, then leave the root-only
runtime and recursive one-shot flow unindented. Rename the helper for
that behavior and document why RPC namespace lookup requires it to
remain import-addressable at module scope.

Review: PR #484 (goodboy)
https://github.com/goodboy/tractor/pull/484#discussion_r3859956375

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-26 18:27:11 -04:00
Gud Boi b3e8ed18d1 Link asyncio cancellation regression provenance
Point `test_tractor_cancels_aio()`'s anti-hang guard at the original
fix commit and the detailed ria-removal analysis plan.

Review: PR #484 (goodboy)
https://github.com/goodboy/tractor/pull/484#discussion_r3859956368

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-26 17:00:54 -04:00
Gud Boi d5e66dffaa Restore high-fanout startup cancellation stress
Release 25 concurrent `to_actor.run()` callers through one local
barrier so their implicit child starts race the first remote error.
Exercise one, five and 25 deterministically placed errorers without
overloading actor-nursery internals.

Validate bounded cancel-on-first teardown, only boxed assertion
relays and empty actor-nursery child/reap maps across Trio and
multiprocessing backends. Clarify this successor's distinction from
`test_nested_multierrors()`, diagram flat-pool error propagation and
align the nearby expected-error comment with its handler.

Review: PR #484 (goodboy)
https://github.com/goodboy/tractor/pull/484#discussion_r3858891778

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-26 17:00:44 -04:00
Gud Boi cf56f33be6 Correct cancellation and asyncio test prose
Fix five spelling errors in comments and failure text touched by the
one-shot migration: one `propagate`, one `Daemon` and three `directly`
corrections.

Review: PR #484 (GitHub Copilot)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025348921

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 23:35:43 -04:00
Gud Boi 8739c5fadb Document legacy one-shot API removals
Add the PR #484 towncrier fragment for removing
`ActorNursery.run_in_actor()`, `Portal.wait_for_result()` and
`Portal.result()`.

Point callers to `to_actor.run()`, `Portal.run()` or
`Portal.open_context()` according to task ownership and dialog shape.

Review: PR #484 (OpenCode)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025383596

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 23:03:20 -04:00
Gud Boi dfdaf2b1c1 Validate `test_multierror()` relay shapes
Inspect the exception emitted by the concurrent error fan-out instead
of accepting any `RemoteActorError` or `BaseExceptionGroup`.

Require each non-cancellation leaf to box `AssertionError`, allow one
or two relays for cancel-on-first timing and require both child relays
when no cancellation leaf accompanies the group.

Review: PR #484 (OpenCode)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025383596

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 23:00:13 -04:00
Gud Boi 37eeb7bab6 Exercise active RPC tasks in SIGINT test
Open one linked sleeping context in each daemon and wait for every
`StartAck` before `test_cancel_via_SIGINT_other_task()` reports
startup.

This restores the legacy test's active remote-task cancellation
target instead of proving SIGINT teardown only against idle actor
runtimes.

Review: PR #484 (OpenCode)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025383596

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 22:53:18 -04:00
Gud Boi 1d59f1963c Propagate unexpected `@pub` subscriber errors
Give each background subscriber runner its own teardown event and
suppress only `ContextCancelled` relayed by the root actor after that
portal's explicit cancellation begins.

Let generic remote errors, foreign cancellation and cancellation
before teardown escape the local task nursery so the test cannot pass
after a subscriber fails unexpectedly.

Review: PR #484 (GitHub Copilot and OpenCode)
https://github.com/goodboy/tractor/pull/484#discussion_r3858426546

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 20:38:57 -04:00
Gud Boi dd3e7482bf Wait for active pub/sub cancellation targets
Replace `test_dynamic_pub_sub()`'s fixed startup sleep with an RPC
activity probe in the publisher actor. Track the publisher task and
wait until every launched consumer has installed its first
subscription before raising the user cancellation exception.

This keeps slow spawn backends from passing the regression by
cancelling actors which never reached the streaming workload.

Review: PR #484 (OpenCode)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025383596

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 20:23:53 -04:00
Gud Boi 266073cb69 Reap the `@pub` example daemon on stream exit
Wrap the documented publisher stream in `try/finally` and explicitly
cancel its `start_actor()` daemon. Closing `open_stream_from()` owns
only the remote stream task, so actor-nursery exit otherwise waits on
the still-running actor indefinitely.

Review: PR #484 (OpenCode)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025383596

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 20:03:18 -04:00
Gud Boi 4134726ec4 Pass `pub_service` directly to stream RPC
Keep the `@pub` docstring example's remote target namespace
addressable by passing the module-level function directly to
`Portal.open_stream_from()`.

Forward the topic and task-name inputs as RPC kwargs instead of
wrapping the target in a `functools.partial` object that resolves to
the wrong namespace path.

Review: PR #484 (OpenCode)
https://github.com/goodboy/tractor/pull/484#pullrequestreview-5025383596

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 19:59:17 -04:00
Gud Boi 09e78ad087 Bind named `to_actor.run()` inputs with partials
PR #481 made target inputs positional and reserved keywords for
actor placement/runtime controls. PR #484 still forwarded target
kwargs, so tests and examples failed local signature binding after
the rebase.

Deats,
- bind named target inputs with `functools.partial()`
- keep placement, naming and runtime controls as direct keywords
- reject invalid target calls locally before actor startup
- require linked one-shots to raise one direct `RemoteActorError`
- doc linked context execution and per-child process reaping

Prompt-IO: ai/prompt-io/opencode/20260819T184640Z_481ba003_prompt_io.md

(this patch was generated in some part by `opencode` using `gpt-5.6-sol` (`openai`))
2026-08-25 19:20:43 -04:00
Gud Boi dd91195377 Doc the #477 migration outcome + one-shot-acm sketch
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..ad42871e`.

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-08-25 19:19:28 -04:00
Gud Boi e7f5968850 Name every `ActorNursery` binding `an` in tests/examples
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
2026-08-25 19:19:28 -04:00
Gud Boi 551090d129 Fix mutual-rendezvous premature-reap race (#477)
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
2026-08-25 19:19:23 -04:00
Gud Boi bb0a9b3c93 Remove `run_in_actor()` + the ria reap cluster
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
2026-08-25 19:16:32 -04:00
Gud Boi 5d70959a2b Fix stale `@pub` docstring example in `experimental`
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
2026-08-25 19:16:32 -04:00
Gud Boi e8f636ddbb Port docs off `run_in_actor` + `Portal.wait_for_result`
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
2026-08-25 19:16:21 -04:00
Gud Boi 4eca8d7a10 Port `test_dynamic_pub_sub` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi 3fcc4ee713 Port SIGINT + sync-sleep cancel tests off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi de3dc2ded0 Port `test_nested_multierrors` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi f81f7d40c3 Fix unbound `timeout` under non-trio/MTF backends
`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
2026-08-25 17:57:12 -04:00
Gud Boi f4f3034555 Port `test_some_cancels_all` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi 5420b13482 Doc ria-reap hang fix + paused reaper re-scope
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`))
2026-08-25 17:57:12 -04:00
Gud Boi e824e6b768 Port `test_cancellation` multierror cluster off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi 0835963fa2 Port `test_registrar` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi 4e4191701c Port `test_pubsub` off `run_in_actor`
`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
2026-08-25 17:57:12 -04:00
Gud Boi 19d0e9cb78 Port `test_spawning` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi 8df118dde8 Port `test_rpc` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi e328b4d729 Port `test_runtime` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00
Gud Boi 3a6bff0b6e Port `test_infected_asyncio` off `run_in_actor`
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
2026-08-25 17:57:12 -04:00