---
model: claude-opus-4-7[1m]
service: claude
timestamp: 2026-04-17T03:58:05Z
git_ref: 61a73ba
diff_cmd: git diff 61a73ba~1..61a73ba
---

Code generated in this turn was committed verbatim as
`61a73bae` ("Mv `trio_proc`/`mp_proc` to per-backend
submods"). Per diff-ref mode, per-file code is captured
via the pointers below, each followed by a prose
summary of what the AI generated. Non-code output
(sanity-check results, design rationale) is included
verbatim.

## Per-file generated content

### `tractor/spawn/_trio.py` (new, 292 lines)

> `git diff 61a73ba~1..61a73ba -- tractor/spawn/_trio.py`

Pure lift-and-shift of `trio_proc()` out of
`tractor/spawn/_spawn.py` (previously lines 448–670).
Added AGPL header + module docstring describing the
backend; imports include local `from ._spawn import
cancel_on_completion, hard_kill, soft_kill` which
creates the bottom-of-module late-import pattern in
the core file to avoid a cycle. All call sites,
log-format strings, and body logic are byte-identical
to the originals — no semantic change.

### `tractor/spawn/_mp.py` (new, 235 lines)

> `git diff 61a73ba~1..61a73ba -- tractor/spawn/_mp.py`

Pure lift-and-shift of `mp_proc()` out of
`tractor/spawn/_spawn.py` (previously lines 672–842).
Same AGPL header convention. Key difference from
`_trio.py`: uses `from . import _spawn` (module
import, not from-import) for `_ctx` and
`_spawn_method` references — these are mutated at
runtime by `try_set_start_method()`, so late binding
via `_spawn._ctx` / `_spawn._spawn_method` is required
for correctness. Also imports `cancel_on_completion`,
`soft_kill`, `proc_waiter` from `._spawn`.

### `tractor/spawn/_spawn.py` (modified, 847 → 448 LOC)

> `git diff 61a73ba~1..61a73ba -- tractor/spawn/_spawn.py`

- removed `trio_proc()` body (moved to `_trio.py`)
- removed `mp_proc()` body (moved to `_mp.py`)
- pruned imports now unused in core: `sys`,
  `is_root_process`, `current_actor`,
  `is_main_process`, `_mp_main`, `ActorFailure`,
  `pretty_struct`, `_pformat`
- added bottom-of-file late imports
  `from ._trio import trio_proc` and
  `from ._mp import mp_proc` with a one-line
  comment explaining why (circular dep)
- `_methods` dict unchanged structurally; still binds
  `'trio' → trio_proc`, `'mp_spawn' → mp_proc`,
  `'mp_forkserver' → mp_proc`

### `tractor/spawn/__init__.py` (modified)

> `git diff 61a73ba~1..61a73ba -- tractor/spawn/__init__.py`

Docstring rewrite only — no code. New text describes
the per-backend `Layout` with `- ._spawn` (core),
`- ._trio` (default), `- ._mp` (two mp variants), and
reiterates the "no eager import" NOTE.

### `tractor/_testing/pytest.py` (modified)

> `git diff 61a73ba~1..61a73ba -- tractor/_testing/pytest.py`

Two-line logical change (plus a comment):
- `from typing import` grows `get_args`
- `pytest_generate_tests()` replaces the hardcoded
  `('mp_spawn','mp_forkserver','trio')` tuple with
  `get_args(SpawnMethodKey)` via lazy import
  `from tractor.spawn._spawn import SpawnMethodKey`
  inside the function body (matching the project's
  existing lazy-import convention for the spawn
  module)

## Non-code output (verbatim)

### Design rationale for the file split

From my Phase A plan turn (already captured in
`20260417T034918Z_9703210_prompt_io.md`):
- `_spawn.py` stays as the "core" rather than renamed
  to `_core.py` so external imports
  (`_testing/pytest.py:228` imports
  `try_set_start_method` from `tractor.spawn._spawn`)
  keep working without churn.
- Per-backend extraction chosen over alternatives
  (e.g. splitting generic helpers further) because
  the immediate motivation is hosting a 3rd
  `_subint.py` sibling cleanly in Phase B.

### Sanity-check output (verbatim terminal excerpts)

Post-extraction import probe:
```
extraction OK
_methods: {'trio': 'tractor.spawn._trio.trio_proc',
           'mp_spawn': 'tractor.spawn._mp.mp_proc',
           'mp_forkserver': 'tractor.spawn._mp.mp_proc'}
```

Spawn-relevant test subset (`tests/test_local.py
test_rpc.py test_spawning.py test_multi_program.py
test_discovery.py`):
```
37 passed, 1 skipped, 14 warnings in 55.37s
```

Full suite:
```
350 passed, 14 skipped, 7 xfailed, 1 xpassed,
151 warnings in 437.73s (0:07:17)
```

No regressions vs. `main`. One transient `-x`
early-stop `ERROR` on
`test_close_channel_explicit_remote_registrar[trio-True]`
was flaky (passed solo, passed without `-x`), not
caused by this refactor.

### Commit message

Also AI-drafted (via `/commit-msg`) — the 40-line
message on commit `61a73bae` itself. Not reproduced
here; see `git log -1 61a73bae`.
